1#!/bin/sh
2
3#++
4# NAME
5#	postfix-script 1
6# SUMMARY
7#	execute Postfix administrative commands
8# SYNOPSIS
9#	\fBpostfix-script\fR \fIcommand\fR
10# DESCRIPTION
11#	The \fBpostfix-script\fR script executes Postfix administrative
12#	commands in an environment that is set up by the \fBpostfix\fR(1)
13#	command.
14# SEE ALSO
15#	master(8) Postfix master program
16#	postfix(1) Postfix administrative interface
17# LICENSE
18# .ad
19# .fi
20#	The Secure Mailer license must be distributed with this software.
21# AUTHOR(S)
22#	Wietse Venema
23#	IBM T.J. Watson Research
24#	P.O. Box 704
25#	Yorktown Heights, NY 10598, USA
26#--
27
28# Avoid POSIX death due to SIGHUP when some parent process exits.
29
30trap '' 1
31
32case $daemon_directory in
33"") echo This script must be run by the postfix command. 1>&2
34    echo Do not run directly. 1>&2
35    exit 1
36esac
37
38LOGGER="$command_directory/postlog -t $MAIL_LOGTAG/postfix-script"
39INFO="$LOGGER -p info"
40WARN="$LOGGER -p warn"
41ERROR="$LOGGER -p error"
42FATAL="$LOGGER -p fatal"
43PANIC="$LOGGER -p panic"
44
45umask 022
46SHELL=/bin/sh
47
48#
49# Can't do much without these in place.
50#
51cd $command_directory || {
52	$FATAL no Postfix command directory $command_directory!
53	exit 1
54}
55cd $daemon_directory || {
56	$FATAL no Postfix daemon directory $daemon_directory!
57	exit 1
58}
59test -f master || {
60	$FATAL no Postfix master program $daemon_directory/master!
61	exit 1
62}
63cd $config_directory || {
64	$FATAL no Postfix configuration directory $config_directory!
65	exit 1
66}
67cd $queue_directory || {
68	$FATAL no Postfix queue directory $queue_directory!
69	exit 1
70}
71def_config_directory=`$command_directory/postconf -dh config_directory` || {
72	$FATAL cannot execute $command_directory/postconf!
73	exit 1
74}
75
76# If this is a secondary instance, don't touch shared files.
77
78instances=`test ! -f $def_config_directory/main.cf ||
79    $command_directory/postconf -c $def_config_directory \
80    -h multi_instance_directories | sed 's/,/ /'` || {
81	$FATAL cannot execute $command_directory/postconf!
82	exit 1
83}
84
85check_shared_files=1
86for name in $instances
87do
88    case "$name" in
89    "$def_config_directory") ;;
90    "$config_directory") check_shared_files=; break;;
91    esac
92done
93
94#
95# Parse JCL
96#
97case $1 in
98
99start_msg)
100
101	echo "Start postfix"
102	;;
103
104stop_msg)
105
106	echo "Stop postfix"
107	;;
108
109start)
110
111	$daemon_directory/master -t 2>/dev/null || {
112		$FATAL the Postfix mail system is already running
113		exit 1
114	}
115	if [ -f $queue_directory/quick-start ]
116	then
117		rm -f $queue_directory/quick-start
118	else
119		$daemon_directory/postfix-script check-fatal || {
120			$FATAL Postfix integrity check failed!
121			exit 1
122		}
123		# Foreground this so it can be stopped. All inodes are cached.
124		$daemon_directory/postfix-script check-warn
125	fi
126	$INFO starting the Postfix mail system
127	# NOTE: wait in foreground process to get the initialization status.
128	$daemon_directory/master -w || {
129	    $FATAL "mail system startup failed"
130	    exit 1
131	}
132	;;
133
134drain)
135
136	$daemon_directory/master -t 2>/dev/null && {
137		$FATAL the Postfix mail system is not running
138		exit 1
139	}
140	$INFO stopping the Postfix mail system
141	kill -9 `sed 1q pid/master.pid`
142	;;
143
144quick-stop)
145
146	$daemon_directory/postfix-script stop
147	touch $queue_directory/quick-start
148	;;
149
150stop)
151
152	$daemon_directory/master -t 2>/dev/null && {
153		$FATAL the Postfix mail system is not running
154		exit 1
155	}
156	$INFO stopping the Postfix mail system
157	kill `sed 1q pid/master.pid`
158	for i in 5 4 3 2 1
159	do
160	    $daemon_directory/master -t && exit 0
161	    $INFO waiting for the Postfix mail system to terminate
162	    sleep 1
163	done
164	$WARN stopping the Postfix mail system with force
165	pid=`awk '{ print $1; exit 0 } END { exit 1 }' pid/master.pid` && 
166		kill -9 -$pid
167	;;
168
169abort)
170
171	$daemon_directory/master -t 2>/dev/null && {
172		$FATAL the Postfix mail system is not running
173		exit 1
174	}
175	$INFO aborting the Postfix mail system
176	kill `sed 1q pid/master.pid`
177	;;
178
179reload)
180
181	$daemon_directory/master -t 2>/dev/null && {
182		$FATAL the Postfix mail system is not running
183		exit 1
184	}
185	$INFO refreshing the Postfix mail system
186	$command_directory/postsuper active || exit 1
187	kill -HUP `sed 1q pid/master.pid`
188	$command_directory/postsuper &
189	;;
190
191flush)
192
193	cd $queue_directory || {
194		$FATAL no Postfix queue directory $queue_directory!
195		exit 1
196	}
197	$command_directory/postqueue -f
198	;;
199
200check)
201
202	$daemon_directory/postfix-script check-fatal || exit 1
203	$daemon_directory/postfix-script check-warn
204	exit 0
205	;;
206
207status)
208
209	$daemon_directory/master -t 2>/dev/null && {
210		$INFO the Postfix mail system is not running
211		exit 1
212	}
213	$INFO the Postfix mail system is running: PID: `sed 1q pid/master.pid`
214	exit 0
215	;;
216
217
218check-fatal)
219	# This command is NOT part of the public interface.
220
221	$SHELL $daemon_directory/post-install create-missing || {
222		$FATAL unable to create missing queue directories
223		exit 1
224	}
225
226	# Look for incomplete installations.
227
228	test -f $config_directory/master.cf || {
229		$FATAL no $config_directory/master.cf file found
230		exit 1
231	}
232
233	# See if all queue files are in the right place. This is slow.
234	# We must scan all queues for mis-named queue files before the
235	# mail system can run.
236
237	$command_directory/postsuper || exit 1
238	exit 0
239	;;
240
241check-warn)
242	# This command is NOT part of the public interface.
243
244	todo="$config_directory $queue_directory $queue_directory/pid"
245	test -n "$check_shared_files" && todo="$daemon_directory $todo"
246
247	for dir in $todo
248	do
249		ls -lLd $dir | (grep " root " >/dev/null ||
250		    $WARN not owned by root: $dir)
251	done
252
253	# Some people break Postfix's security model.
254	ls -lLd $queue_directory | egrep '^.....(w|...w)' >/dev/null && \
255		$WARN group or other writable: $queue_directory
256
257	todo="$config_directory/*"
258	test -n "$check_shared_files" && todo="$daemon_directory/* $todo"
259
260	find $todo ! -user root \
261		-exec $WARN not owned by root: {} \;
262
263	todo="$config_directory/."
264	test -n "$check_shared_files" && todo="$daemon_directory/. $todo"
265
266	find $todo \
267		\( -perm -020 -o -perm -002 \) -type f \
268		-exec $WARN group or other writable: {} \;
269
270	find $data_directory/. ! -user $mail_owner \
271	    -exec $WARN not owned by $mail_owner: {} \;
272
273	ls -lLd $data_directory | egrep '^.....(w|...w)' >/dev/null && \
274		$WARN group or other writable: $data_directory
275
276	find `ls -d $queue_directory/* | \
277	    egrep '/(saved|incoming|active|defer|deferred|bounce|hold|trace|corrupt|public|private|flush)$'` \
278	    ! \( -type p -o -type s \) ! -user $mail_owner \
279		-exec $WARN not owned by $mail_owner: {} \;
280
281	todo="$queue_directory/public $queue_directory/maildrop"
282	test -n "$check_shared_files" && 
283	   todo="$command_directory/postqueue $command_directory/postdrop $todo"
284
285	find $todo \
286	    -prune ! -group $setgid_group \
287	    -exec $WARN not owned by group $setgid_group: {} \;
288
289	test -n "$check_shared_files" &&
290	find $command_directory/postqueue $command_directory/postdrop \
291	    -prune ! -perm -02111 \
292	    -exec $WARN not set-gid or not owner+group+world executable: {} \;
293
294	for name in `ls -d $queue_directory/* | \
295	    egrep '/(bin|etc|lib|usr)$'` ; \
296	do \
297	    find $name ! -user root \
298		-exec $WARN not owned by root: {} \; ; \
299	done
300
301	# WARNING: this should not descend into the maildrop directory.
302	# maildrop is the least trusted Postfix directory.
303
304	find $queue_directory/maildrop/. -prune ! -user $mail_owner \
305	    -exec $WARN not owned by $mail_owner: $queue_directory/maildrop \;
306
307	for dir in bin etc lib sbin usr
308	do
309		test -d $dir && find $dir -type f -print | while read path
310		do
311			test -f /$path && {
312			    cmp -s $path /$path || 
313				$WARN $queue_directory/$path and /$path differ
314			}
315		done
316	done
317
318	find corrupt -type f -exec $WARN damaged message: {} \;
319
320	# XXX also: look for weird stuff, weird permissions, etc.
321
322	test -n "$check_shared_files" -a -f /usr/sbin/sendmail -a \
323		-f /usr/lib/sendmail && {
324	    cmp -s /usr/sbin/sendmail /usr/lib/sendmail || {
325		$WARN /usr/lib/sendmail and /usr/sbin/sendmail differ
326		$WARN Replace one by a symbolic link to the other
327	    }
328	}
329	exit 0
330	;;
331
332set-permissions|upgrade-configuration)
333	$daemon_directory/post-install create-missing "$@"
334	;;
335
336post-install)
337	# Currently not part of the public interface.
338	shift
339	$daemon_directory/post-install "$@"
340	;;
341
342/*)
343	# Currently not part of the public interface.
344	"$@"
345	;;
346
347*)
348	$ERROR "unknown command: '$1'"
349	$FATAL "usage: postfix start (or stop, reload, abort, flush, check, status, set-permissions, upgrade-configuration)"
350	exit 1
351	;;
352
353esac
354