Home | History | Annotate | Line # | Download | only in conf
postmulti-script revision 1.2
      1  1.1      tron #! /bin/sh
      2  1.1      tron #	$NetBSD: postmulti-script,v 1.2 2017/02/14 01:16:43 christos Exp $
      3  1.1      tron #
      4  1.1      tron 
      5  1.1      tron umask 022
      6  1.1      tron 
      7  1.1      tron # postmulti(1) contract:
      8  1.1      tron #
      9  1.1      tron # Arguments:
     10  1.1      tron #  postmulti-script -e <edit_command>
     11  1.1      tron #
     12  1.1      tron # Environment:
     13  1.1      tron #
     14  1.1      tron # All actions:
     15  1.1      tron #
     16  1.1      tron #  MAIL_CONFIG			- config_directory of primary instance
     17  1.1      tron #  command_directory		- From primary instance
     18  1.1      tron #  daemon_directory		- From primary instance
     19  1.2  christos #  meta_directory		- From primary instance
     20  1.2  christos #  shlib_directory		- From primary instance
     21  1.1      tron #  config_directroy		- config_directory of target instance
     22  1.1      tron #  queue_directory		- queue_directory of target instance
     23  1.1      tron #  data_directory		- data_directory of target instance
     24  1.1      tron #
     25  1.1      tron # Create, destroy, import and deport:
     26  1.1      tron #
     27  1.1      tron #  multi_instance_directories	- New value for primary instance
     28  1.1      tron #
     29  1.1      tron # Create, import and assign (unset == nochange, "-" == clear):
     30  1.1      tron #
     31  1.1      tron #  multi_instance_group		- New value for target instance
     32  1.1      tron #  multi_instance_name		- New value for target instance
     33  1.1      tron 
     34  1.1      tron : ${MAIL_CONFIG:?"do not invoke this command directly"}
     35  1.1      tron : ${command_directory:?"do not invoke this command directly"}
     36  1.1      tron : ${daemon_directory:?"do not invoke this command directly"}
     37  1.2  christos : ${meta_directory:?"do not invoke this command directly"}
     38  1.2  christos : ${shlib_directory:?"do not invoke this command directly"}
     39  1.1      tron 
     40  1.1      tron USAGE="$0 -e create|destroy|import|deport|enable|disable|assign|init"
     41  1.1      tron usage() { echo "$0: Error: Usage: $USAGE" >&2; exit 1; }
     42  1.1      tron 
     43  1.1      tron TAG="$MAIL_LOGTAG/postmulti-script"
     44  1.1      tron fatal() { postlog -p fatal -t "$TAG" "$1"; exit 1; }
     45  1.1      tron 
     46  1.1      tron # args: add|del $dir
     47  1.1      tron #
     48  1.1      tron update_cfdirs() {
     49  1.1      tron     op=$1
     50  1.1      tron     dir=$2
     51  1.1      tron 
     52  1.1      tron     alt=`postconf -h alternate_config_directories` || return 1
     53  1.1      tron 
     54  1.1      tron     shift $#	# Needed on SunOS where bare "set --" is NOP!
     55  1.1      tron     IFS="$IFS,"; set -- $alt; IFS="$BACKUP_IFS"
     56  1.1      tron     keep=
     57  1.1      tron     found=
     58  1.1      tron     # Portability: SunOS "sh" needs 'in "$@"' for one-line for-loop.
     59  1.1      tron     for d in "$@"; do [ "$d" = "$dir" ] && found=1 || keep="$keep $d"; done
     60  1.1      tron 
     61  1.1      tron     set -- "multi_instance_directories = $multi_instance_directories"
     62  1.1      tron 
     63  1.1      tron     case $op in
     64  1.1      tron     add) test -n "$found" ||
     65  1.1      tron 	 set -- "$@" "alternate_config_directories =$keep $dir";;
     66  1.1      tron     del) test -n "$found" &&
     67  1.1      tron 	 set -- "$@" "alternate_config_directories =$keep";;
     68  1.1      tron       *) return 1;;		# XXX: Internal error
     69  1.1      tron     esac
     70  1.1      tron     postconf -e "$@" || return 1
     71  1.1      tron }
     72  1.1      tron 
     73  1.1      tron assign_names() {
     74  1.1      tron     # Set the instance name and group
     75  1.1      tron     #
     76  1.1      tron     test -n "$multi_instance_name" && {
     77  1.1      tron 	test "$multi_instance_name" = "-" && multi_instance_name=
     78  1.1      tron 	set -- "$@" "multi_instance_name = $multi_instance_name"
     79  1.1      tron     }
     80  1.1      tron     test -n "$multi_instance_group" && {
     81  1.1      tron 	test "$multi_instance_group" = "-" && multi_instance_group=
     82  1.1      tron 	set -- "$@" "multi_instance_group = $multi_instance_group"
     83  1.1      tron     }
     84  1.1      tron     test $# -eq 0 || postconf -c "$config_directory" -e "$@" || return 1
     85  1.1      tron }
     86  1.1      tron 
     87  1.1      tron # Process command-line options and parameter settings. Work around
     88  1.1      tron # brain damaged shells. "IFS=value command" should not make the
     89  1.1      tron # IFS=value setting permanent. But some broken standard allows it.
     90  1.1      tron 
     91  1.1      tron BACKUP_IFS="$IFS"
     92  1.1      tron action=
     93  1.1      tron 
     94  1.1      tron while getopts ":e:" opt
     95  1.1      tron do
     96  1.1      tron     case $opt in
     97  1.1      tron     e) action="$OPTARG";;
     98  1.1      tron     *) usage;;
     99  1.1      tron     esac
    100  1.1      tron done
    101  1.1      tron shift `expr $OPTIND - 1`
    102  1.1      tron 
    103  1.1      tron # Check for valid action and required instance name
    104  1.1      tron case "$action" in
    105  1.1      tron  create|import|destroy|deport|enable|disable|assign|init) ;;
    106  1.1      tron 						       *) usage;;
    107  1.1      tron esac
    108  1.1      tron test $# -eq 0 || usage
    109  1.1      tron 
    110  1.1      tron case $action in
    111  1.1      tron init)
    112  1.1      tron     postconf -e \
    113  1.1      tron     	'multi_instance_wrapper = ${command_directory}/postmulti -p --' \
    114  1.1      tron     	'multi_instance_enable = yes'
    115  1.1      tron     exit $? ;;
    116  1.1      tron esac
    117  1.1      tron 
    118  1.2  christos # Backport note: "-x" requires 2.10 or later, and is not essential here.
    119  1.2  christos #
    120  1.2  christos wrapper=`postconf -hx multi_instance_wrapper` || exit 1
    121  1.2  christos enable=`postconf -hx multi_instance_enable` || exit 1
    122  1.2  christos 
    123  1.2  christos test -n "$wrapper" ||
    124  1.2  christos     fatal "multi_instance_wrapper is empty, run 'postmulti -e init' first."
    125  1.2  christos 
    126  1.2  christos test "$enable" = "yes" ||
    127  1.2  christos     fatal "multi_instance_enable!=yes, run 'postmulti -e init' first."
    128  1.2  christos 
    129  1.1      tron : ${config_directory:?"Invalid empty target instance config_directory"}
    130  1.1      tron 
    131  1.1      tron case $action in
    132  1.1      tron create|import)
    133  1.1      tron 
    134  1.1      tron     # Atomically install stock main.cf/master.cf files. We install the
    135  1.1      tron     # master.cf file last. Once it is present the instance is complete.
    136  1.1      tron     #
    137  1.1      tron     test -f $config_directory/main.cf -a \
    138  1.1      tron 	 -f $config_directory/master.cf || {
    139  1.1      tron 
    140  1.1      tron 	test "$action" = "create" || {
    141  1.1      tron 	    test -f $config_directory/main.cf ||
    142  1.1      tron 		fatal "'$config_directory' lacks a main.cf file"
    143  1.1      tron 	    test -f $config_directory/master.cf ||
    144  1.1      tron 		fatal "'$config_directory' lacks a master.cf file"
    145  1.1      tron 	}
    146  1.1      tron 
    147  1.2  christos 	test -f $meta_directory/main.cf.proto ||
    148  1.2  christos 	    fatal "Missing main.cf prototype: $meta_directory/main.cf.proto"
    149  1.2  christos 	test -f $meta_directory/master.cf.proto ||
    150  1.2  christos 	    fatal "Missing master.cf prototype: $meta_directory/master.cf.proto"
    151  1.2  christos 
    152  1.1      tron 	# Create instance-specific directories
    153  1.1      tron 	#
    154  1.1      tron 	test -d $config_directory ||
    155  1.1      tron 	    { (umask 022; mkdir -p $config_directory) || exit 1; }
    156  1.1      tron 	test -d $queue_directory ||
    157  1.1      tron 	    { (umask 022; mkdir -p $queue_directory) || exit 1; }
    158  1.1      tron 	test -d $data_directory ||
    159  1.1      tron 	    { (umask 077; mkdir -p $data_directory) || exit 1; }
    160  1.1      tron 
    161  1.1      tron 	tmpdir=$config_directory/.tmp
    162  1.1      tron 	(umask 077; mkdir -p $tmpdir) || exit 1
    163  1.2  christos 	cp -p $meta_directory/main.cf.proto $tmpdir/main.cf || exit 1
    164  1.1      tron 
    165  1.1      tron 	# Shared install parameters are cloned from user-specified values in
    166  1.1      tron 	# the default instance, but only if explicitly set there. Otherwise,
    167  1.1      tron 	# they are commented out in the new main.cf file.
    168  1.1      tron 	#
    169  1.1      tron 	SHARED_PARAMETERS="
    170  1.1      tron 	    command_directory
    171  1.1      tron 	    daemon_directory
    172  1.2  christos 	    meta_directory
    173  1.1      tron 	    mail_owner
    174  1.1      tron 	    setgid_group
    175  1.1      tron 	    sendmail_path
    176  1.1      tron 	    mailq_path
    177  1.1      tron 	    newaliases_path
    178  1.1      tron 	    html_directory
    179  1.1      tron 	    manpage_directory
    180  1.1      tron 	    sample_directory
    181  1.1      tron 	    readme_directory
    182  1.2  christos 	    shlib_directory
    183  1.1      tron 	"
    184  1.1      tron 
    185  1.1      tron 	shift $#	# Needed on SunOS where bare "set --" is NOP!
    186  1.1      tron 	comment_out=
    187  1.1      tron 	for p in $SHARED_PARAMETERS; do
    188  1.1      tron 	    val=`postconf -nh $p` || exit 1
    189  1.1      tron 	    test -n "$val" && { set -- "$@" "$p = $val"; continue; }
    190  1.1      tron 	    comment_out="$comment_out $p"
    191  1.1      tron 	done
    192  1.1      tron 
    193  1.1      tron 	# First comment-out any parameters that take default values
    194  1.1      tron 	test -n "$comment_out" && {
    195  1.1      tron 	    postconf -c $tmpdir -# $comment_out || exit 1
    196  1.1      tron 	}
    197  1.1      tron 
    198  1.1      tron 	# Now add instance-specific and non-default values.
    199  1.1      tron 	# By default, disable inet services and local submission
    200  1.1      tron 	# in new instances
    201  1.1      tron 	#
    202  1.1      tron 	postconf -c $tmpdir -e \
    203  1.1      tron 	    "queue_directory = $queue_directory" \
    204  1.1      tron 	    "data_directory = $data_directory" \
    205  1.1      tron 	    "authorized_submit_users =" \
    206  1.1      tron 	    "master_service_disable = inet" \
    207  1.1      tron 	    "$@" || exit 1
    208  1.1      tron 
    209  1.1      tron 
    210  1.2  christos 	cp -p $meta_directory/master.cf.proto $tmpdir/master.cf || exit 1
    211  1.1      tron 	mv $tmpdir/main.cf $config_directory/main.cf || exit 1
    212  1.1      tron 	mv $tmpdir/master.cf $config_directory/master.cf || exit 1
    213  1.1      tron 	rmdir $tmpdir 2>/dev/null
    214  1.1      tron     }
    215  1.1      tron 
    216  1.1      tron     # Set instance name and group
    217  1.1      tron     #
    218  1.1      tron     assign_names || exit 1
    219  1.1      tron 
    220  1.1      tron     # Update multi_instance_directories
    221  1.1      tron     # and drop from alternate_config_directories
    222  1.1      tron     #
    223  1.1      tron     # XXX: Must happen before set-permissions below, otherwise instance
    224  1.1      tron     # is treated as a non-slave instance by post-install via postfix(1).
    225  1.1      tron     #
    226  1.1      tron     update_cfdirs del $config_directory || exit 1
    227  1.1      tron 
    228  1.1      tron     # Update permissions of private files. Verifies existence of
    229  1.1      tron     # queue_directory and data_directory, ...
    230  1.1      tron     #
    231  1.1      tron     # XXX: Must happen after instance list updates above, otherwise instance
    232  1.1      tron     # is treated as a non-slave instance by post-install via postfix(1).
    233  1.1      tron     #
    234  1.1      tron     postfix -c $config_directory set-permissions || exit 1
    235  1.1      tron     ;;
    236  1.1      tron 
    237  1.1      tron deport)
    238  1.1      tron     # Deporting an already deleted instance?
    239  1.1      tron     #
    240  1.1      tron     [ -f "$config_directory/main.cf" ] || {
    241  1.1      tron 	update_cfdirs del $config_directory
    242  1.1      tron 	exit $?
    243  1.1      tron     }
    244  1.1      tron 
    245  1.1      tron     postfix -c "$config_directory" status >/dev/null 2>&1 &&
    246  1.1      tron     	fatal "Instance '$config_directory' is not stopped"
    247  1.1      tron 
    248  1.1      tron     # Update multi_instance_directories
    249  1.1      tron     # and add to alternate_config_directories
    250  1.1      tron     #
    251  1.1      tron     update_cfdirs add $config_directory || exit 1
    252  1.1      tron     ;;
    253  1.1      tron 
    254  1.1      tron destroy)
    255  1.2  christos 
    256  1.2  christos     # "postmulti -e destroy" will remove an entire instance only when
    257  1.2  christos     # invoked immediately after "postmulti -e create" (i.e. before
    258  1.2  christos     # other files are added to the instance). We delete only known
    259  1.2  christos     # safe names without "/".
    260  1.2  christos     #
    261  1.2  christos     QUEUE_SUBDIRS="active bounce corrupt defer deferred flush hold \
    262  1.2  christos     incoming maildrop pid private public saved trace"
    263  1.2  christos     #DEBUG=echo
    264  1.2  christos     WARN="postlog -p warn -t $TAG"
    265  1.2  christos 
    266  1.1      tron     # Locate the target instance
    267  1.1      tron     #
    268  1.1      tron     [ -f "$config_directory/main.cf" ] ||
    269  1.1      tron 	fatal "$config_directory/main.cf file not found"
    270  1.1      tron 
    271  1.1      tron     postfix -c "$config_directory" status >/dev/null 2>&1 &&
    272  1.1      tron     	fatal "Instance '$config_directory' is not stopped"
    273  1.1      tron 
    274  1.1      tron     # Update multi_instance directories
    275  1.1      tron     # and also (just in case) drop from alternate_config_directories
    276  1.1      tron     #
    277  1.2  christos     $DEBUG update_cfdirs del "$config_directory" || exit 1
    278  1.1      tron 
    279  1.2  christos     # XXX: Internal "postfix /some/cmd" interface.
    280  1.2  christos     #
    281  1.2  christos     postfix -c "$config_directory" /bin/sh -c "
    282  1.2  christos     for q in $QUEUE_SUBDIRS
    283  1.2  christos     do
    284  1.2  christos 	$DEBUG rmdir -- \$q || 
    285  1.2  christos 	    $WARN \`pwd\`/\$q: please verify contents and remove by hand
    286  1.2  christos     done
    287  1.2  christos     "
    288  1.1      tron 
    289  1.2  christos     postfix -c "$config_directory" /bin/sh -c "
    290  1.2  christos     for dir in \$data_directory \$queue_directory
    291  1.2  christos     do
    292  1.2  christos 	$DEBUG rmdir -- \$dir || 
    293  1.2  christos 	    $WARN \$dir: please verify contents and remove by hand
    294  1.2  christos     done
    295  1.2  christos     "
    296  1.1      tron 
    297  1.1      tron     # In the configuration directory remove just the main.cf and master.cf
    298  1.1      tron     # files.
    299  1.2  christos     $DEBUG rm -f -- "$config_directory/master.cf" "$config_directory/main.cf" 2>/dev/null
    300  1.2  christos     $DEBUG rmdir -- "$config_directory" || 
    301  1.2  christos 	$WARN $config_directory: please verify contents and remove by hand
    302  1.1      tron     ;;
    303  1.2  christos 
    304  1.1      tron enable)
    305  1.1      tron     postconf -c "$config_directory" -e \
    306  1.1      tron     	"multi_instance_enable = yes" || exit 1;;
    307  1.1      tron disable)
    308  1.1      tron     postconf -c "$config_directory" -e \
    309  1.1      tron     	"multi_instance_enable = no" || exit 1;;
    310  1.1      tron assign)
    311  1.1      tron     assign_names || exit 1;;
    312  1.1      tron esac
    313  1.1      tron 
    314  1.1      tron exit 0
    315