1#!/bin/sh 2# $NetBSD: postfix-script,v 1.4 2023/12/23 20:30:42 christos Exp $ 3# 4 5#++ 6# NAME 7# postfix-script 1 8# SUMMARY 9# execute Postfix administrative commands 10# SYNOPSIS 11# \fBpostfix-script\fR \fIcommand\fR 12# DESCRIPTION 13# The \fBpostfix-script\fR script executes Postfix administrative 14# commands in an environment that is set up by the \fBpostfix\fR(1) 15# command. 16# SEE ALSO 17# master(8) Postfix master program 18# postfix(1) Postfix administrative interface 19# LICENSE 20# .ad 21# .fi 22# The Secure Mailer license must be distributed with this software. 23# AUTHOR(S) 24# Wietse Venema 25# IBM T.J. Watson Research 26# P.O. Box 704 27# Yorktown Heights, NY 10598, USA 28# 29# Wietse Venema 30# Google, Inc. 31# 111 8th Avenue 32# New York, NY 10011, USA 33#-- 34 35# Avoid POSIX death due to SIGHUP when some parent process exits. 36 37trap '' 1 38 39case $daemon_directory in 40"") echo This script must be run by the postfix command. 1>&2 41 echo Do not run directly. 1>&2 42 exit 1 43esac 44 45LOGGER="$command_directory/postlog -t $MAIL_LOGTAG/postfix-script" 46INFO="$LOGGER -p info" 47WARN="$LOGGER -p warn" 48ERROR="$LOGGER -p error" 49FATAL="$LOGGER -p fatal" 50PANIC="$LOGGER -p panic" 51 52umask 022 53SHELL=/bin/sh 54 55# 56# Can't do much without these in place. 57# 58cd $command_directory || { 59 $FATAL no Postfix command directory $command_directory! 60 exit 1 61} 62cd $daemon_directory || { 63 $FATAL no Postfix daemon directory $daemon_directory! 64 exit 1 65} 66test -f master || { 67 $FATAL no Postfix master program $daemon_directory/master! 68 exit 1 69} 70cd $config_directory || { 71 $FATAL no Postfix configuration directory $config_directory! 72 exit 1 73} 74case $shlib_directory in 75no) ;; 76 *) cd $shlib_directory || { 77 $FATAL no Postfix shared-library directory $shlib_directory! 78 exit 1 79 } 80esac 81cd $meta_directory || { 82 $FATAL no Postfix meta directory $meta_directory! 83 exit 1 84} 85cd $queue_directory || { 86 $FATAL no Postfix queue directory $queue_directory! 87 exit 1 88} 89def_config_directory=`$command_directory/postconf -dh config_directory` || { 90 $FATAL cannot execute $command_directory/postconf! 91 exit 1 92} 93 94# If this is a secondary instance, don't touch shared files. 95 96instances=`test ! -f $def_config_directory/main.cf || 97 $command_directory/postconf -c $def_config_directory \ 98 -h multi_instance_directories | sed 's/,/ /'` || { 99 $FATAL cannot execute $command_directory/postconf! 100 exit 1 101} 102 103check_shared_files=1 104for name in $instances 105do 106 case "$name" in 107 "$def_config_directory") ;; 108 "$config_directory") check_shared_files=; break;; 109 esac 110done 111 112# 113# Parse JCL 114# 115case $1 in 116 117start_msg) 118 119 echo "Start postfix" 120 ;; 121 122stop_msg) 123 124 echo "Stop postfix" 125 ;; 126 127start|start-fg) 128 129 $daemon_directory/master -t 2>/dev/null || { 130 $FATAL the Postfix mail system is already running 131 exit 1 132 } 133 if [ -f $queue_directory/quick-start ] 134 then 135 rm -f $queue_directory/quick-start 136 else 137 $daemon_directory/postfix-script check-fatal || { 138 $FATAL Postfix integrity check failed! 139 exit 1 140 } 141 # Foreground this so it can be stopped. All inodes are cached. 142 $daemon_directory/postfix-script check-warn 143 fi 144 $INFO starting the Postfix mail system || exit 1 145 case $1 in 146 start) 147 # NOTE: wait in foreground process to get the initialization status. 148 $daemon_directory/master -w || { 149 $FATAL "mail system startup failed" 150 exit 1 151 } 152 ;; 153 start-fg) 154 # Foreground start-up is incompatible with multi-instance mode. 155 # Use "exec $daemon_directory/master" only if PID == 1. 156 # Otherwise, doing so would break process group management, 157 # and "postfix stop" would kill too many processes. 158 case $instances in 159 "") case $$ in 160 1) exec $daemon_directory/master -i 161 $FATAL "cannot start-fg the master daemon" 162 exit 1;; 163 *) $daemon_directory/master -s;; 164 esac 165 ;; 166 *) $FATAL "start-fg does not support multi_instance_directories" 167 exit 1 168 ;; 169 esac 170 ;; 171 esac 172 ;; 173 174drain) 175 176 $daemon_directory/master -t 2>/dev/null && { 177 $FATAL the Postfix mail system is not running 178 exit 1 179 } 180 $INFO stopping the Postfix mail system 181 kill -9 `sed 1q pid/master.pid` 182 ;; 183 184quick-stop) 185 186 $daemon_directory/postfix-script stop 187 touch $queue_directory/quick-start 188 ;; 189 190stop) 191 192 $daemon_directory/master -t 2>/dev/null && { 193 $FATAL the Postfix mail system is not running 194 exit 1 195 } 196 $INFO stopping the Postfix mail system 197 kill `sed 1q pid/master.pid` 198 for i in 5 4 3 2 1 199 do 200 $daemon_directory/master -t && exit 0 201 $INFO waiting for the Postfix mail system to terminate 202 sleep 1 203 done 204 $WARN stopping the Postfix mail system with force 205 pid=`awk '{ print $1; exit 0 } END { exit 1 }' pid/master.pid` && 206 kill -9 -$pid 207 ;; 208 209abort) 210 211 $daemon_directory/master -t 2>/dev/null && { 212 $FATAL the Postfix mail system is not running 213 exit 1 214 } 215 $INFO aborting the Postfix mail system 216 kill `sed 1q pid/master.pid` 217 ;; 218 219reload) 220 221 $daemon_directory/master -t 2>/dev/null && { 222 $FATAL the Postfix mail system is not running 223 exit 1 224 } 225 $INFO refreshing the Postfix mail system 226 $command_directory/postsuper active || exit 1 227 kill -HUP `sed 1q pid/master.pid` 228 $command_directory/postsuper & 229 ;; 230 231flush) 232 233 cd $queue_directory || { 234 $FATAL no Postfix queue directory $queue_directory! 235 exit 1 236 } 237 $command_directory/postqueue -f 238 ;; 239 240check) 241 242 $daemon_directory/postfix-script check-fatal || exit 1 243 $daemon_directory/postfix-script check-warn 244 exit 0 245 ;; 246 247status) 248 249 $daemon_directory/master -t 2>/dev/null && { 250 $INFO the Postfix mail system is not running 251 exit 1 252 } 253 $INFO the Postfix mail system is running: PID: `sed 1q pid/master.pid` 254 exit 0 255 ;; 256 257 258check-fatal) 259 # This command is NOT part of the public interface. 260 261 $SHELL $daemon_directory/post-install create-missing || { 262 $FATAL unable to create missing queue directories 263 exit 1 264 } 265 266 # Look for incomplete installations. 267 268 test -f $config_directory/master.cf || { 269 $FATAL no $config_directory/master.cf file found 270 exit 1 271 } 272 273 maillog_file=`$command_directory/postconf -h maillog_file` || { 274 $FATAL cannot execute $command_directory/postconf! 275 exit 1 276 } 277 test -n "$maillog_file" && { 278 $command_directory/postconf -M postlog/unix-dgram 2>/dev/null \ 279 | grep . >/dev/null || { 280 $FATAL "missing 'postlog' service in master.cf - run 'postfix upgrade-configuration'" 281 exit 1 282 } 283 } 284 285 # See if all queue files are in the right place. This is slow. 286 # We must scan all queues for mis-named queue files before the 287 # mail system can run. 288 289 $command_directory/postsuper || exit 1 290 exit 0 291 ;; 292 293check-warn) 294 # This command is NOT part of the public interface. 295 296 # Check Postfix root-owned directory owner/permissions. 297 298 find $queue_directory/. $queue_directory/pid \ 299 -prune ! -user root \ 300 -exec $WARN not owned by root: {} \; 301 302 find $queue_directory/. $queue_directory/pid \ 303 -prune \( -perm -020 -o -perm -002 \) \ 304 -exec $WARN group or other writable: {} \; 305 306 # Check Postfix root-owned directory tree owner/permissions. 307 308 todo="$config_directory/." 309 test -n "$check_shared_files" && { 310 todo="$daemon_directory/. $meta_directory/. $todo" 311 test "$shlib_directory" = "no" || 312 todo="$shlib_directory/. $todo" 313 } 314 todo=`echo "$todo" | tr ' ' '\12' | sort -u` 315 316 find $todo ! -user root \ 317 -exec $WARN not owned by root: {} \; 318 319 find $todo \( -perm -020 -o -perm -002 \) \ 320 -exec $WARN group or other writable: {} \; 321 322 # Check Postfix mail_owner-owned directory tree owner/permissions. 323 324 find $data_directory/. ! -user $mail_owner \ 325 -exec $WARN not owned by $mail_owner: {} \; 326 327 find $data_directory/. \( -perm -020 -o -perm -002 \) \ 328 -exec $WARN group or other writable: {} \; 329 330 # Check Postfix mail_owner-owned directory tree owner. 331 332 find `ls -d $queue_directory/* | \ 333 grep -E '/(saved|incoming|active|defer|deferred|bounce|hold|trace|corrupt|public|private|flush)$'` \ 334 ! \( -type p -o -type s \) ! -user $mail_owner \ 335 -exec $WARN not owned by $mail_owner: {} \; 336 337 # WARNING: this should not descend into the maildrop directory. 338 # maildrop is the least trusted Postfix directory. 339 340 find $queue_directory/maildrop -prune ! -user $mail_owner \ 341 -exec $WARN not owned by $mail_owner: $queue_directory/maildrop \; 342 343 # Check Postfix setgid_group-owned directory and file group/permissions. 344 345 todo="$queue_directory/public $queue_directory/maildrop" 346 test -n "$check_shared_files" && 347 todo="$command_directory/postqueue $command_directory/postdrop $todo" 348 349 find $todo \ 350 -prune ! -group $setgid_group \ 351 -exec $WARN not owned by group $setgid_group: {} \; 352 353 test -n "$check_shared_files" && 354 find $command_directory/postqueue $command_directory/postdrop \ 355 -prune ! -perm -02111 \ 356 -exec $WARN not set-gid or not owner+group+world executable: {} \; 357 358 # Check non-Postfix root-owned directory tree owner/content. 359 360 for dir in bin etc lib sbin usr 361 do 362 test -d $dir && { 363 find $dir ! -user root \ 364 -exec $WARN not owned by root: $queue_directory/{} \; 365 366 find $dir -type f -print | while read path 367 do 368 test -f /$path && { 369 cmp -s $path /$path || 370 $WARN $queue_directory/$path and /$path differ 371 } 372 done 373 } 374 done 375 376 find corrupt -type f -exec $WARN damaged message: {} \; 377 378 # Check for non-Postfix MTA remnants. 379 380 test -n "$check_shared_files" -a -f /usr/sbin/sendmail -a \ 381 -f /usr/lib/sendmail && { 382 cmp -s /usr/sbin/sendmail /usr/lib/sendmail || { 383 $WARN /usr/lib/sendmail and /usr/sbin/sendmail differ 384 $WARN Replace one by a symbolic link to the other 385 } 386 } 387 exit 0 388 ;; 389 390set-permissions|upgrade-configuration) 391 $daemon_directory/post-install create-missing "$@" 392 ;; 393 394post-install) 395 # Currently not part of the public interface. 396 shift 397 $daemon_directory/post-install "$@" 398 ;; 399 400tls) 401 shift 402 $daemon_directory/postfix-tls-script "$@" 403 ;; 404 405/*) 406 # Currently not part of the public interface. 407 "$@" 408 ;; 409 410logrotate) 411 case $# in 412 1) ;; 413 *) $FATAL "usage postfix $1 (no arguments)"; exit 1;; 414 esac 415 for name in maillog_file maillog_file_compressor \ 416 maillog_file_rotate_suffix 417 do 418 value="`$command_directory/postconf -h $name`" 419 case "$value" in 420 "") $FATAL "empty '$name' parameter value - logfile rotation failed" 421 exit 1;; 422 esac 423 eval $name='"$value"'; 424 done 425 426 case "$maillog_file" in 427 /dev/*) $FATAL "not rotating '$maillog_file'"; exit 1;; 428 esac 429 430 errors=`( 431 suffix="\`date +$maillog_file_rotate_suffix\`" || exit 1 432 mv "$maillog_file" "$maillog_file.$suffix" || exit 1 433 $daemon_directory/master -t 2>/dev/null || 434 kill -HUP \`sed 1q pid/master.pid\` || exit 1 435 sleep 1 436 "$maillog_file_compressor" "$maillog_file.$suffix" || exit 1 437 ) 2>&1` || { 438 $FATAL "logfile '$maillog_file' rotation failed: $errors" 439 exit 1 440 } 441 ;; 442 443*) 444 $FATAL "unknown command: '$1'. Usage: postfix start (or stop, reload, abort, flush, check, status, set-permissions, upgrade-configuration, logrotate)" 445 exit 1 446 ;; 447 448esac 449