159 #include <sys/socket.h>
169 #ifdef STRCASECMP_IN_STRINGS_H
218 static int use_count;
220 static void (*single_server_service) (
VSTREAM *,
char *,
char **);
221 static char *single_server_name;
222 static char **single_server_argv;
223 static void (*single_server_accept) (
int,
void *);
224 static void (*single_server_onexit) (
char *,
char **);
225 static void (*single_server_pre_accept) (
char *,
char **);
226 static VSTREAM *single_server_lock;
227 static int single_server_in_flow_delay;
228 static unsigned single_server_generation;
232 static NORETURN single_server_exit(
void)
234 if (single_server_onexit)
235 single_server_onexit(single_server_name, single_server_argv);
241 static void single_server_abort(
int unused_event,
void *unused_context)
244 msg_info(
"master disconnect -- exiting");
245 single_server_exit();
250 static void single_server_timeout(
int unused_event,
void *unused_context)
253 msg_info(
"idle timeout -- exiting");
254 single_server_exit();
259 static void single_server_wakeup(
int fd,
HTABLE *attr)
276 tmp =
concatenate(single_server_name,
" socket", (
char *) 0);
287 single_server_service(stream, single_server_name, single_server_argv);
294 if (use_count < INT_MAX)
304 static void single_server_accept_local(
int unused_event,
void *context)
319 if (single_server_pre_accept)
320 single_server_pre_accept(single_server_name, single_server_argv);
322 if (single_server_lock != 0
333 single_server_wakeup(fd, (
HTABLE *) 0);
336 #ifdef MASTER_XPORT_NAME_PASS
340 static void single_server_accept_pass(
int unused_event,
void *context)
356 if (single_server_pre_accept)
357 single_server_pre_accept(single_server_name, single_server_argv);
359 if (single_server_lock != 0
370 single_server_wakeup(fd, attr);
377 static void single_server_accept_inet(
int unused_event,
void *context)
392 if (single_server_pre_accept)
393 single_server_pre_accept(single_server_name, single_server_argv);
395 if (single_server_lock != 0
406 single_server_wakeup(fd, (
HTABLE *) 0);
413 const char *myname =
"single_server_main";
419 char *service_name =
basename(argv[0]);
422 int socket_count = 1;
440 int msg_vstream_needed = 0;
441 int redo_syslog_init = 0;
442 const char *dsn_filter_title;
443 const char **dsn_filter_maps;
456 signal(SIGPIPE, SIG_IGN);
462 signal(SIGXFSZ, SIG_IGN);
501 while ((c =
GETOPT(argc, argv,
"cdDi:lm:n:o:s:St:uvVz")) > 0) {
522 service_name = optarg;
527 msg_fatal(
"invalid \"-o %s\" option value: %s", optarg, err);
530 redo_syslog_init = 1;
534 if ((socket_count = atoi(optarg)) <= 0)
535 msg_fatal(
"invalid socket_count: %s", optarg);
550 if (++msg_vstream_needed == 1)
567 if (redo_syslog_init)
579 if (daemon_mode && stream == 0 && isatty(STDIN_FILENO)) {
581 msg_fatal(
"do not run this command by hand");
587 va_start(ap, service);
588 while ((key = va_arg(ap,
int)) != 0) {
630 single_server_in_flow_delay = 1;
633 if (stream == 0 && !alone)
634 msg_fatal(
"service %s requires a process limit of 1",
638 if (stream == 0 && !zerolimit)
639 msg_fatal(
"service %s requires a process limit of 0",
644 msg_fatal(
"service %s requires privileged operation",
648 dsn_filter_title = va_arg(ap,
const char *);
649 dsn_filter_maps = va_arg(ap,
const char **);
653 msg_panic(
"%s: unknown argument type: %d", myname, key);
668 msg_fatal(
"no transport type specified");
670 single_server_accept = single_server_accept_inet;
672 single_server_accept = single_server_accept_local;
673 #ifdef MASTER_XPORT_NAME_PASS
675 single_server_accept = single_server_accept_pass;
678 msg_fatal(
"unsupported transport type: %s", transport);
686 msg_fatal(
"bad generation: %s", generation);
689 msg_info(
"process generation: %s (%o)",
690 generation, single_server_generation);
705 if (stream == 0 && !alone) {
707 ".", service_name, (
void *) 0);
709 if ((single_server_lock =
safe_open(lock_path, O_CREAT | O_RDWR, 0600,
710 (
struct stat *) 0, -1, -1, why)) == 0)
720 single_server_service = service;
721 single_server_name = service_name;
722 single_server_argv = argv + optind;
730 pre_init(single_server_name, single_server_argv);
743 post_init(single_server_name, single_server_argv);
755 service(stream, single_server_name, single_server_argv);
757 single_server_exit();
782 if (single_server_lock != 0) {
789 delay = loop ? loop(single_server_name, single_server_argv) : -1;
792 single_server_exit();
void event_enable_read(int fd, EVENT_NOTIFY_RDWR_FN callback, void *context)
void msg_error(const char *fmt,...)
void htable_free(HTABLE *table, void(*free_fn)(void *))
#define MAIL_SERVER_UNLIMITED
const char * mail_task(const char *argv0)
#define MAIL_SERVER_STR_TABLE
char * mystrdup(const char *str)
int master_notify(int pid, unsigned generation, int status)
void set_mail_conf_str(const char *, const char *)
#define CAST_ANY_PTR_TO_INT(cptr)
NORETURN msg_panic(const char *fmt,...)
void chroot_uid(const char *root_dir, const char *user_name)
#define MAIL_SERVER_INT_TABLE
#define MASTER_FLOW_WRITE
#define MYFLOCK_OP_EXCLUSIVE
#define OCTAL_TO_UNSIGNED(res, str)
#define MAIL_SERVER_TIME_TABLE
void get_mail_conf_nint_table(const CONFIG_NINT_TABLE *)
void(* MAIL_SERVER_EXIT_FN)(char *, char **)
#define CA_VSTREAM_CTL_DOUBLE
#define CA_VSTREAM_CTL_CONTEXT(v)
void get_mail_conf_nbool_table(const CONFIG_NBOOL_TABLE *)
#define MASTER_XPORT_NAME_PASS
#define EVENT_NULL_CONTEXT
int alldig(const char *string)
#define MASTER_STAT_AVAIL
const char * split_nameval(char *buf, char **name, char **value)
void watchdog_start(WATCHDOG *wp)
void(* WATCHDOG_FN)(WATCHDOG *, char *)
void mail_conf_suck(void)
#define MAIL_SERVER_BOOL_TABLE
#define MAIL_SERVER_PRIVILEGED
#define MAIL_SERVER_POST_INIT
#define MAIL_SERVER_BOUNCE_INIT
#define CA_VSTREAM_CTL_WRITE_FD(v)
void get_mail_conf_time_table(const CONFIG_TIME_TABLE *)
#define MAIL_SERVER_PRE_ACCEPT
#define MASTER_STAT_TAKEN
void(* MAIL_SERVER_INIT_FN)(char *, char **)
void get_mail_conf_raw_table(const CONFIG_RAW_TABLE *)
#define CAST_INT_TO_VOID_PTR(ival)
int vstream_fclose(VSTREAM *stream)
ssize_t mail_flow_get(ssize_t len)
void event_loop(int delay)
WATCHDOG * watchdog_create(unsigned timeout, WATCHDOG_FN action, char *context)
#define MAIL_SERVER_IN_FLOW_DELAY
void resolve_local_init(void)
VSTRING * vstring_alloc(ssize_t len)
int myflock(int fd, int lock_style, int operation)
void mail_dict_init(void)
void doze(unsigned delay)
#define MASTER_XPORT_NAME_INET
void get_mail_conf_str_table(const CONFIG_STR_TABLE *)
void timed_ipc_setup(VSTREAM *stream)
NORETURN msg_fatal(const char *fmt,...)
void get_mail_conf_bool_table(const CONFIG_BOOL_TABLE *)
#define MASTER_XPORT_NAME_UNIX
#define MAIL_VERSION_CHECK
#define MAIL_SERVER_LONG_TABLE
int vstream_fflush(VSTREAM *stream)
void watchdog_stop(WATCHDOG *wp)
void(* SINGLE_SERVER_FN)(VSTREAM *, char *, char **)
char * concatenate(const char *arg0,...)
#define GETOPT(argc, argv, str)
void bounce_client_init(const char *title, const char *maps)
void msg_syslog_init(const char *name, int logopt, int facility)
void(* MAIL_SERVER_ACCEPT_FN)(char *, char **)
#define MAIL_SERVER_NINT_TABLE
int strcasecmp(const char *s1, const char *s2)
int non_blocking(int, int)
VSTREAM * safe_open(const char *path, int flags, mode_t mode, struct stat *st, uid_t user, gid_t group, VSTRING *why)
VSTRING * vstring_free(VSTRING *vp)
time_t event_request_timer(EVENT_NOTIFY_TIME_FN callback, void *context, int delay)
#define MAIL_SERVER_PRE_INIT
void get_mail_conf_int_table(const CONFIG_INT_TABLE *)
#define vstream_fileno(vp)
void msg_vstream_init(const char *name, VSTREAM *vp)
#define CA_VSTREAM_CTL_END
#define CA_VSTREAM_CTL_PATH(v)
int(* MAIL_SERVER_LOOP_FN)(char *, char **)
void get_mail_conf_long_table(const CONFIG_LONG_TABLE *)
void vstream_control(VSTREAM *stream, int name,...)
void mail_conf_update(const char *key, const char *value)
#define MAIL_SERVER_NBOOL_TABLE
int event_cancel_timer(EVENT_NOTIFY_TIME_FN callback, void *context)
int close_on_exec(int fd, int on)
#define MAIL_SERVER_RAW_TABLE
int pass_accept_attr(int, HTABLE **)
#define MAIL_SERVER_SOLITARY
VSTREAM * vstream_fdopen(int fd, int flags)
NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
void msg_info(const char *fmt,...)