diff options
Diffstat (limited to 'src/postlog/postlog.c')
-rw-r--r-- | src/postlog/postlog.c | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/src/postlog/postlog.c b/src/postlog/postlog.c new file mode 100644 index 0000000..0ad22b6 --- /dev/null +++ b/src/postlog/postlog.c @@ -0,0 +1,298 @@ +/*++ +/* NAME +/* postlog 1 +/* SUMMARY +/* Postfix-compatible logging utility +/* SYNOPSIS +/* .fi +/* .ad +/* \fBpostlog\fR [\fB-iv\fR] [\fB-c \fIconfig_dir\fR] +/* [\fB-p \fIpriority\fR] [\fB-t \fItag\fR] [\fItext...\fR] +/* DESCRIPTION +/* The \fBpostlog\fR(1) command implements a Postfix-compatible logging +/* interface for use in, for example, shell scripts. +/* +/* By default, \fBpostlog\fR(1) logs the \fItext\fR given on the command +/* line as one record. If no \fItext\fR is specified on the command +/* line, \fBpostlog\fR(1) reads from standard input and logs each input +/* line as one record. +/* +/* By default, logging is sent to \fBsyslogd\fR(8) or +/* \fBpostlogd\fR(8); when the +/* standard error stream is connected to a terminal, logging +/* is sent there as well. +/* +/* The following options are implemented: +/* .IP "\fB-c \fIconfig_dir\fR" +/* Read the \fBmain.cf\fR configuration file in the named directory +/* instead of the default configuration directory. +/* .IP "\fB-i\fR (obsolete)" +/* Include the process ID in the logging tag. This flag is ignored as +/* of Postfix 3.4, where the PID is always included. +/* .IP "\fB-p \fIpriority\fR (default: \fBinfo\fR)" +/* Specifies the logging severity: \fBinfo\fR, \fBwarn\fR, +/* \fBerror\fR, \fBfatal\fR, or \fBpanic\fR. With Postfix 3.1 +/* and later, the program will pause for 1 second after reporting +/* a \fBfatal\fR or \fBpanic\fR condition, just like other +/* Postfix programs. +/* .IP "\fB-t \fItag\fR" +/* Specifies the logging tag, that is, the identifying name that +/* appears at the beginning of each logging record. A default tag +/* is used when none is specified. +/* .IP \fB-v\fR +/* Enable verbose logging for debugging purposes. Multiple \fB-v\fR +/* options make the software increasingly verbose. +/* ENVIRONMENT +/* .ad +/* .fi +/* .IP MAIL_CONFIG +/* Directory with the \fBmain.cf\fR file. +/* CONFIGURATION PARAMETERS +/* .ad +/* .fi +/* The following \fBmain.cf\fR parameters are especially relevant to +/* this program. +/* +/* 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 "\fBimport_environment (see 'postconf -d' output)\fR" +/* The list of environment parameters that a privileged Postfix +/* process will import from a non-Postfix parent process, or name=value +/* environment overrides. +/* .IP "\fBsyslog_facility (mail)\fR" +/* The syslog facility of Postfix logging. +/* .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". +/* .PP +/* Available in Postfix 3.4 and later: +/* .IP "\fBmaillog_file (empty)\fR" +/* The name of an optional logfile that is written by the Postfix +/* \fBpostlogd\fR(8) service. +/* .IP "\fBpostlog_service_name (postlog)\fR" +/* The name of the \fBpostlogd\fR(8) service entry in master.cf. +/* SEE ALSO +/* postconf(5), configuration parameters +/* postlogd(8), Postfix logging +/* syslogd(8), system logging +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + +/* System library. */ + +#include <sys_defs.h> +#include <sys/stat.h> +#include <string.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> + +#ifdef STRCASECMP_IN_STRINGS_H +#include <strings.h> +#endif + +/* Utility library. */ + +#include <msg.h> +#include <vstring.h> +#include <vstream.h> +#include <vstring_vstream.h> +#include <msg_output.h> +#include <msg_vstream.h> +#include <warn_stat.h> +#include <clean_env.h> + +/* Global library. */ + +#include <mail_params.h> /* XXX right place for LOG_FACILITY? */ +#include <mail_version.h> +#include <mail_conf.h> +#include <mail_task.h> +#include <mail_parm_split.h> +#include <maillog_client.h> + +/* Application-specific. */ + + /* + * Support for the severity level mapping. + */ +struct level_table { + char *name; + int level; +}; + +static struct level_table level_table[] = { + "info", MSG_INFO, + "warn", MSG_WARN, + "warning", MSG_WARN, + "error", MSG_ERROR, + "err", MSG_ERROR, + "fatal", MSG_FATAL, + "crit", MSG_FATAL, + "panic", MSG_PANIC, + 0, +}; + +/* level_map - lookup facility or severity value */ + +static int level_map(char *name) +{ + struct level_table *t; + + for (t = level_table; t->name; t++) + if (strcasecmp(t->name, name) == 0) + return (t->level); + msg_fatal("bad severity: \"%s\"", name); +} + +/* log_argv - log the command line */ + +static void log_argv(int level, char **argv) +{ + VSTRING *buf = vstring_alloc(100); + + while (*argv) { + vstring_strcat(buf, *argv++); + if (*argv) + vstring_strcat(buf, " "); + } + msg_printf(level, "%s", vstring_str(buf)); + vstring_free(buf); +} + +/* log_stream - log lines from a stream */ + +static void log_stream(int level, VSTREAM *fp) +{ + VSTRING *buf = vstring_alloc(100); + + while (vstring_get_nonl(buf, fp) != VSTREAM_EOF) + msg_printf(level, "%s", vstring_str(buf)); + vstring_free(buf); +} + +MAIL_VERSION_STAMP_DECLARE; + +/* main - logger */ + +int main(int argc, char **argv) +{ + struct stat st; + int fd; + int ch; + const char *tag; + int level = MSG_INFO; + ARGV *import_env; + + /* + * Fingerprint executables and core dumps. + */ + MAIL_VERSION_STAMP_ALLOCATE; + + /* + * Be consistent with file permissions. + */ + umask(022); + + /* + * To minimize confusion, make sure that the standard file descriptors + * are open before opening anything else. XXX Work around for 44BSD where + * fstat can return EBADF on an open file descriptor. + */ + for (fd = 0; fd < 3; fd++) + if (fstat(fd, &st) == -1 + && (close(fd), open("/dev/null", O_RDWR, 0)) != fd) + msg_fatal("open /dev/null: %m"); + + /* + * Set up diagnostics. + */ + tag = mail_task(argv[0]); + if (isatty(STDERR_FILENO)) + msg_vstream_init(tag, VSTREAM_ERR); + maillog_client_init(tag, MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); + + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + + /* + * Parse switches. + */ + tag = 0; + while ((ch = GETOPT(argc, argv, "c:ip:t:v")) > 0) { + switch (ch) { + default: + msg_fatal("usage: %s [-c config_dir] [-i] [-p priority] [-t tag] [-v] [text]", argv[0]); + break; + case 'c': + if (setenv(CONF_ENV_PATH, optarg, 1) < 0) + msg_fatal("out of memory"); + break; + case 'i': + break; + case 'p': + level = level_map(optarg); + break; + case 't': + tag = optarg; + break; + case 'v': + msg_verbose++; + break; + } + } + + /* + * Process the main.cf file. This may change the syslog_name setting and + * may require that mail_task() be re-evaluated. + */ + mail_conf_read(); + /* Enforce consistent operation of different Postfix parts. */ + import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ); + update_env(import_env->argv); + argv_free(import_env); + if (tag == 0) + tag = mail_task(argv[0]); + + /* + * Re-initialize the logging, this time with the tag specified in main.cf + * or on the command line. + */ + if (isatty(STDERR_FILENO)) + msg_vstream_init(tag, VSTREAM_ERR); + maillog_client_init(tag, MAILLOG_CLIENT_FLAG_LOGWRITER_FALLBACK); + + /* + * Log the command line or log lines from standard input. + */ + if (argc > optind) { + log_argv(level, argv + optind); + } else { + log_stream(level, VSTREAM_IN); + } + + /* + * Consistency with msg(3) functions. + */ + if (level >= MSG_FATAL) + sleep(1); + exit(0); +} |