/*++ /* NAME /* postlogd 8 /* SUMMARY /* Postfix internal log server /* SYNOPSIS /* \fBpostlogd\fR [generic Postfix daemon options] /* DESCRIPTION /* This program logs events on behalf of Postfix programs /* when the maillog configuration parameter specifies a non-empty /* value. /* BUGS /* Non-daemon Postfix programs don't know that they should log /* to the internal logging service before they have processed /* command-line options and main.cf parameters. These programs /* still log earlier events to the syslog service. /* /* If Postfix is down, the non-daemon programs \fBpostfix\fR(1), /* \fBpostsuper\fR(1), \fBpostmulti\fR(1), and \fBpostlog\fR(1), /* will log directly to \fB$maillog_file\fR. These programs /* expect to run with root privileges, for example during /* Postfix start-up, reload, or shutdown. /* /* Other non-daemon Postfix programs will never write directly to /* \fB$maillog_file\fR (also, logging to stdout would interfere /* with the operation of some of these programs). These programs /* can log to \fBpostlogd\fR(8) if they are run by the super-user, /* or if their executable file has set-gid permission. Do not /* set this permission on programs other than \fBpostdrop\fR(1), /* \fBpostqueue\fR(1) and (Postfix >= 3.7) \fBpostlog\fR(1). /* CONFIGURATION PARAMETERS /* .ad /* .fi /* Changes to \fBmain.cf\fR are picked up automatically, as /* \fBpostlogd\fR(8) processes run for only a limited amount /* of time. Use the command "\fBpostfix reload\fR" to speed /* up a change. /* /* The text below provides only a parameter summary. See /* \fBpostconf\fR(5) for more details including examples. /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" /* The default location of the Postfix main.cf and master.cf /* configuration files. /* .IP "\fBmaillog_file (empty)\fR" /* The name of an optional logfile that is written by the Postfix /* \fBpostlogd\fR(8) service. /* .IP "\fBprocess_id (read-only)\fR" /* The process ID of a Postfix command or daemon process. /* .IP "\fBprocess_name (read-only)\fR" /* The process name of a Postfix command or daemon process. /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" /* A prefix that is prepended to the process name in syslog /* records, so that, for example, "smtpd" becomes "prefix/smtpd". /* .IP "\fBservice_name (read-only)\fR" /* The master.cf service name of a Postfix daemon process. /* .IP "\fBpostlogd_watchdog_timeout (10s)\fR" /* How much time a \fBpostlogd\fR(8) process may take to process a request /* before it is terminated by a built-in watchdog timer. /* SEE ALSO /* postconf(5), configuration parameters /* syslogd(8), system logging /* README_FILES /* .ad /* .fi /* Use "\fBpostconf readme_directory\fR" or /* "\fBpostconf html_directory\fR" to locate this information. /* .na /* .nf /* MAILLOG_README, Postfix logging to file or stdout /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* HISTORY /* .ad /* .fi /* This service was introduced with Postfix version 3.4. /* AUTHOR(S) /* Wietse Venema /* Google, Inc. /* 111 8th Avenue /* New York, NY 10011, USA /*--*/ /* * System library. */ #include /* * Utility library. */ #include #include #include #include #include /* * Global library. */ #include #include #include #include /* * Server skeleton. */ #include /* * Tunable parameters. */ int var_postlogd_watchdog; /* * Silly little macros. */ #define STR(x) vstring_str(x) #define LEN(x) VSTRING_LEN(x) /* * Logfile stream. */ static VSTREAM *postlogd_stream = 0; /* postlogd_fallback - log messages from postlogd(8) itself */ static void postlogd_fallback(const char *buf) { (void) logwriter_write(postlogd_stream, buf, strlen(buf)); } /* postlogd_service - perform service for client */ static void postlogd_service(char *buf, ssize_t len, char *unused_service, char **unused_argv) { if (postlogd_stream) { (void) logwriter_write(postlogd_stream, buf, len); } /* * After a configuration change that removes the maillog_file pathname, * this service may still receive messages (after "postfix reload" or * after process refresh) from programs that use the old maillog_file * setting. Redirect those messages to the current logging mechanism. */ else { char *bp = buf; char *progname_pid; /* * Avoid surprises: strip off the date, time, host, and program[pid]: * prefix that were prepended by msg_logger(3). Then, hope that the * current logging driver suppresses its own PID, when it sees that * there is a PID embedded in the 'program name'. */ (void) mystrtok(&bp, CHARS_SPACE); /* month */ (void) mystrtok(&bp, CHARS_SPACE); /* day */ (void) mystrtok(&bp, CHARS_SPACE); /* time */ (void) mystrtok(&bp, CHARS_SPACE); /* host */ progname_pid = mystrtok(&bp, ":" CHARS_SPACE); /* name[pid] sans ':' */ bp += strspn(bp, CHARS_SPACE); if (progname_pid) maillog_client_init(progname_pid, MAILLOG_CLIENT_FLAG_NONE); msg_info("%.*s", (int) (len - (bp - buf)), bp); /* * Restore the program name, in case postlogd(8) needs to log * something about itself. We have to call maillog_client_init() in * any case, because neither msg_syslog_init() nor openlog() make a * copy of the name argument. We can't leave that pointing into the * middle of the above message buffer. */ maillog_client_init(mail_task((char *) 0), MAILLOG_CLIENT_FLAG_NONE); } } /* pre_jail_init - pre-jail handling */ static void pre_jail_init(char *unused_service_name, char **argv) { /* * During process initialization, the postlogd daemon will log events to * the postlog socket, so that they can be logged to file later. Once the * postlogd daemon is handling requests, it will stop logging to the * postlog socket and will instead write to the logfile, to avoid * infinite recursion. */ /* * Sanity check. This service takes no command-line arguments. */ if (argv[0]) msg_fatal("unexpected command-line argument: %s", argv[0]); /* * After a configuration change that removes the maillog_file pathname, * this service may still receive messages from processes that still use * the old configuration. Those messages will have to be redirected to * the current logging subsystem. */ if (*var_maillog_file != 0) { /* * Instantiate the logwriter or bust. */ postlogd_stream = logwriter_open_or_die(var_maillog_file); /* * Inform the msg_logger client to stop using the postlog socket, and * to call our logwriter. */ msg_logger_control(CA_MSG_LOGGER_CTL_FALLBACK_ONLY, CA_MSG_LOGGER_CTL_FALLBACK_FN(postlogd_fallback), CA_MSG_LOGGER_CTL_END); } } /* post_jail_init - post-jail initialization */ static void post_jail_init(char *unused_name, char **unused_argv) { /* * Prevent automatic process suicide after a limited number of client * requests. It is OK to terminate after a limited amount of idle time. */ var_use_limit = 0; } MAIL_VERSION_STAMP_DECLARE; /* main - pass control to the multi-threaded skeleton */ int main(int argc, char **argv) { static const CONFIG_TIME_TABLE time_table[] = { VAR_POSTLOGD_WATCHDOG, DEF_POSTLOGD_WATCHDOG, &var_postlogd_watchdog, 10, 0, 0, }; /* * Fingerprint executables and core dumps. */ MAIL_VERSION_STAMP_ALLOCATE; /* * This is a datagram service, not a stream service, so that postlogd can * restart immediately after "postfix reload" without requiring clients * to resend messages. Those messages remain queued in the kernel until a * new postlogd process retrieves them. It would be unreasonable to * require that clients retransmit logs, especially in the case of a * fatal or panic error. */ dgram_server_main(argc, argv, postlogd_service, CA_MAIL_SERVER_TIME_TABLE(time_table), CA_MAIL_SERVER_PRE_INIT(pre_jail_init), CA_MAIL_SERVER_POST_INIT(post_jail_init), CA_MAIL_SERVER_SOLITARY, CA_MAIL_SERVER_WATCHDOG(&var_postlogd_watchdog), 0); }