Sync usage with man page.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / postlock / postlock.c
blobba46d22e45011175cdd0140b29d8b7827338c7e5
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* postlock 1
6 /* SUMMARY
7 /* lock mail folder and execute command
8 /* SYNOPSIS
9 /* .fi
10 /* \fBpostlock\fR [\fB-c \fIconfig_dir\fB] [\fB-l \fIlock_style\fB]
11 /* [\fB-v\fR] \fIfile command...\fR
12 /* DESCRIPTION
13 /* The \fBpostlock\fR(1) command locks \fIfile\fR for exclusive
14 /* access, and executes \fIcommand\fR. The locking method is
15 /* compatible with the Postfix UNIX-style local delivery agent.
17 /* Options:
18 /* .IP "\fB-c \fIconfig_dir\fR"
19 /* Read the \fBmain.cf\fR configuration file in the named directory
20 /* instead of the default configuration directory.
21 /* .IP "\fB-l \fIlock_style\fR"
22 /* Override the locking method specified via the
23 /* \fBmailbox_delivery_lock\fR configuration parameter (see below).
24 /* .IP \fB-v\fR
25 /* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
26 /* options make the software increasingly verbose.
27 /* .PP
28 /* Arguments:
29 /* .IP \fIfile\fR
30 /* A mailbox file. The user should have read/write permission.
31 /* .IP \fIcommand...\fR
32 /* The command to execute while \fIfile\fR is locked for exclusive
33 /* access. The command is executed directly, i.e. without
34 /* interpretation by a shell command interpreter.
35 /* DIAGNOSTICS
36 /* The result status is 75 (EX_TEMPFAIL) when \fBpostlock\fR(1)
37 /* could not perform the requested operation. Otherwise, the
38 /* exit status is the exit status from the command.
39 /* BUGS
40 /* With remote file systems, the ability to acquire a lock does not
41 /* necessarily eliminate access conflicts. Avoid file access by
42 /* processes running on different machines.
43 /* ENVIRONMENT
44 /* .ad
45 /* .fi
46 /* .IP \fBMAIL_CONFIG\fR
47 /* Directory with Postfix configuration files.
48 /* .IP \fBMAIL_VERBOSE\fR
49 /* Enable verbose logging for debugging purposes.
50 /* CONFIGURATION PARAMETERS
51 /* .ad
52 /* .fi
53 /* The following \fBmain.cf\fR parameters are especially relevant to
54 /* this program.
55 /* The text below provides only a parameter summary. See
56 /* \fBpostconf\fR(5) for more details including examples.
57 /* LOCKING CONTROLS
58 /* .ad
59 /* .fi
60 /* .IP "\fBdeliver_lock_attempts (20)\fR"
61 /* The maximal number of attempts to acquire an exclusive lock on a
62 /* mailbox file or \fBbounce\fR(8) logfile.
63 /* .IP "\fBdeliver_lock_delay (1s)\fR"
64 /* The time between attempts to acquire an exclusive lock on a mailbox
65 /* file or \fBbounce\fR(8) logfile.
66 /* .IP "\fBstale_lock_time (500s)\fR"
67 /* The time after which a stale exclusive mailbox lockfile is removed.
68 /* .IP "\fBmailbox_delivery_lock (see 'postconf -d' output)\fR"
69 /* How to lock a UNIX-style \fBlocal\fR(8) mailbox before attempting delivery.
70 /* RESOURCE AND RATE CONTROLS
71 /* .ad
72 /* .fi
73 /* .IP "\fBfork_attempts (5)\fR"
74 /* The maximal number of attempts to fork() a child process.
75 /* .IP "\fBfork_delay (1s)\fR"
76 /* The delay between attempts to fork() a child process.
77 /* MISCELLANEOUS CONTROLS
78 /* .ad
79 /* .fi
80 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
81 /* The default location of the Postfix main.cf and master.cf
82 /* configuration files.
83 /* SEE ALSO
84 /* postconf(5), configuration parameters
85 /* LICENSE
86 /* .ad
87 /* .fi
88 /* The Secure Mailer license must be distributed with this software.
89 /* AUTHOR(S)
90 /* Wietse Venema
91 /* IBM T.J. Watson Research
92 /* P.O. Box 704
93 /* Yorktown Heights, NY 10598, USA
94 /*--*/
96 /* System library. */
98 #include <sys_defs.h>
99 #include <sys/stat.h>
100 #include <sys/wait.h>
101 #include <stdlib.h>
102 #include <unistd.h>
103 #include <fcntl.h>
104 #include <errno.h>
106 /* Utility library. */
108 #include <msg.h>
109 #include <vstring.h>
110 #include <vstream.h>
111 #include <msg_vstream.h>
112 #include <iostuff.h>
114 /* Global library. */
116 #include <mail_params.h>
117 #include <mail_version.h>
118 #include <dot_lockfile.h>
119 #include <deliver_flock.h>
120 #include <mail_conf.h>
121 #include <sys_exits.h>
122 #include <mbox_conf.h>
123 #include <mbox_open.h>
124 #include <dsn_util.h>
126 /* Application-specific. */
128 /* usage - explain */
130 static NORETURN usage(char *myname)
132 msg_fatal("usage: %s [-c config_dir] [-l lock_style] [-v] folder command...", myname);
135 /* fatal_exit - all failures are deemed recoverable */
137 static void fatal_exit(void)
139 exit(EX_TEMPFAIL);
142 MAIL_VERSION_STAMP_DECLARE;
144 /* main - go for it */
146 int main(int argc, char **argv)
148 DSN_BUF *why;
149 char *folder;
150 char **command;
151 int ch;
152 int fd;
153 struct stat st;
154 int count;
155 WAIT_STATUS_T status;
156 pid_t pid;
157 int lock_mask;
158 char *lock_style = 0;
159 MBOX *mp;
162 * Fingerprint executables and core dumps.
164 MAIL_VERSION_STAMP_ALLOCATE;
167 * Be consistent with file permissions.
169 umask(022);
172 * To minimize confusion, make sure that the standard file descriptors
173 * are open before opening anything else. XXX Work around for 44BSD where
174 * fstat can return EBADF on an open file descriptor.
176 for (fd = 0; fd < 3; fd++)
177 if (fstat(fd, &st) == -1
178 && (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
179 msg_fatal("open /dev/null: %m");
182 * Process environment options as early as we can. We are not set-uid,
183 * and we are supposed to be running in a controlled environment.
185 if (getenv(CONF_ENV_VERB))
186 msg_verbose = 1;
189 * Set up logging and error handling. Intercept fatal exits so we can
190 * return a distinguished exit status.
192 msg_vstream_init(argv[0], VSTREAM_ERR);
193 msg_cleanup(fatal_exit);
196 * Parse JCL.
198 while ((ch = GETOPT(argc, argv, "c:l:v")) > 0) {
199 switch (ch) {
200 default:
201 usage(argv[0]);
202 break;
203 case 'c':
204 if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
205 msg_fatal("out of memory");
206 break;
207 case 'l':
208 lock_style = optarg;
209 break;
210 case 'v':
211 msg_verbose++;
212 break;
215 if (optind + 2 > argc)
216 usage(argv[0]);
217 folder = argv[optind];
218 command = argv + optind + 1;
221 * Read the config file. The command line lock style can override the
222 * configured lock style.
224 mail_conf_read();
225 lock_mask = mbox_lock_mask(lock_style ? lock_style :
226 get_mail_conf_str(VAR_MAILBOX_LOCK, DEF_MAILBOX_LOCK, 1, 0));
229 * Lock the folder for exclusive access. Lose the lock upon exit. The
230 * command is not supposed to disappear into the background.
232 why = dsb_create();
233 if ((mp = mbox_open(folder, O_APPEND | O_WRONLY | O_CREAT,
234 S_IRUSR | S_IWUSR, (struct stat *) 0,
235 -1, -1, lock_mask, "5.2.0", why)) == 0)
236 msg_fatal("open file %s: %s", folder, vstring_str(why->reason));
237 dsb_free(why);
240 * Run the command. Remove the lock after completion.
242 for (count = 1; (pid = fork()) == -1; count++) {
243 msg_warn("fork %s: %m", command[0]);
244 if (count >= var_fork_tries) {
245 mbox_release(mp);
246 exit(EX_TEMPFAIL);
248 sleep(var_fork_delay);
250 switch (pid) {
251 case 0:
252 (void) msg_cleanup((MSG_CLEANUP_FN) 0);
253 execvp(command[0], command);
254 msg_fatal("execvp %s: %m", command[0]);
255 default:
256 if (waitpid(pid, &status, 0) < 0)
257 msg_fatal("waitpid: %m");
258 vstream_fclose(mp->fp);
259 mbox_release(mp);
260 exit(WIFEXITED(status) ? WEXITSTATUS(status) : 1);