xref: /netbsd-src/external/ibm-public/postfix/dist/conf/postfix-script (revision c48c605c14fd8622b523d1d6a3f0c0bad133ea89)
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