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