1 /* $NetBSD: postlog.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* postlog 1 6 /* SUMMARY 7 /* Postfix-compatible logging utility 8 /* SYNOPSIS 9 /* .fi 10 /* .ad 11 /* \fBpostlog\fR [\fB-iv\fR] [\fB-c \fIconfig_dir\fR] 12 /* [\fB-p \fIpriority\fR] [\fB-t \fItag\fR] [\fItext...\fR] 13 /* DESCRIPTION 14 /* The \fBpostlog\fR(1) command implements a Postfix-compatible logging 15 /* interface for use in, for example, shell scripts. 16 /* 17 /* By default, \fBpostlog\fR(1) logs the \fItext\fR given on the command 18 /* line as one record. If no \fItext\fR is specified on the command 19 /* line, \fBpostlog\fR(1) reads from standard input and logs each input 20 /* line as one record. 21 /* 22 /* Logging is sent to \fBsyslogd\fR(8); when the standard error stream 23 /* is connected to a terminal, logging is sent there as well. 24 /* 25 /* The following options are implemented: 26 /* .IP "\fB-c \fIconfig_dir\fR" 27 /* Read the \fBmain.cf\fR configuration file in the named directory 28 /* instead of the default configuration directory. 29 /* .IP \fB-i\fR 30 /* Include the process ID in the logging tag. 31 /* .IP "\fB-p \fIpriority\fR (default: \fBinfo\fR)" 32 /* Specifies the logging severity: \fBinfo\fR, \fBwarn\fR, 33 /* \fBerror\fR, \fBfatal\fR, or \fBpanic\fR. With Postfix 3.1 34 /* and later, the program will pause for 1 second after reporting 35 /* a \fBfatal\fR or \fBpanic\fR condition, just like other 36 /* Postfix programs. 37 /* .IP "\fB-t \fItag\fR" 38 /* Specifies the logging tag, that is, the identifying name that 39 /* appears at the beginning of each logging record. A default tag 40 /* is used when none is specified. 41 /* .IP \fB-v\fR 42 /* Enable verbose logging for debugging purposes. Multiple \fB-v\fR 43 /* options make the software increasingly verbose. 44 /* ENVIRONMENT 45 /* .ad 46 /* .fi 47 /* .IP MAIL_CONFIG 48 /* Directory with the \fBmain.cf\fR file. 49 /* CONFIGURATION PARAMETERS 50 /* .ad 51 /* .fi 52 /* The following \fBmain.cf\fR parameters are especially relevant to 53 /* this program. 54 /* 55 /* The text below provides only a parameter summary. See 56 /* \fBpostconf\fR(5) for more details including examples. 57 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" 58 /* The default location of the Postfix main.cf and master.cf 59 /* configuration files. 60 /* .IP "\fBsyslog_facility (mail)\fR" 61 /* The syslog facility of Postfix logging. 62 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" 63 /* The mail system name that is prepended to the process name in syslog 64 /* records, so that "smtpd" becomes, for example, "postfix/smtpd". 65 /* SEE ALSO 66 /* postconf(5), configuration parameters 67 /* syslogd(8), syslog daemon 68 /* LICENSE 69 /* .ad 70 /* .fi 71 /* The Secure Mailer license must be distributed with this software. 72 /* AUTHOR(S) 73 /* Wietse Venema 74 /* IBM T.J. Watson Research 75 /* P.O. Box 704 76 /* Yorktown Heights, NY 10598, USA 77 /* 78 /* Wietse Venema 79 /* Google, Inc. 80 /* 111 8th Avenue 81 /* New York, NY 10011, USA 82 /*--*/ 83 84 /* System library. */ 85 86 #include <sys_defs.h> 87 #include <sys/stat.h> 88 #include <string.h> 89 #include <syslog.h> 90 #include <fcntl.h> 91 #include <stdlib.h> 92 #include <unistd.h> 93 94 #ifdef STRCASECMP_IN_STRINGS_H 95 #include <strings.h> 96 #endif 97 98 /* Utility library. */ 99 100 #include <msg.h> 101 #include <vstring.h> 102 #include <vstream.h> 103 #include <vstring_vstream.h> 104 #include <msg_output.h> 105 #include <msg_vstream.h> 106 #include <msg_syslog.h> 107 #include <warn_stat.h> 108 109 /* Global library. */ 110 111 #include <mail_params.h> /* XXX right place for LOG_FACILITY? */ 112 #include <mail_version.h> 113 #include <mail_conf.h> 114 #include <mail_task.h> 115 116 /* Application-specific. */ 117 118 /* 119 * Support for the severity level mapping. 120 */ 121 struct level_table { 122 char *name; 123 int level; 124 }; 125 126 static struct level_table level_table[] = { 127 "info", MSG_INFO, 128 "warn", MSG_WARN, 129 "warning", MSG_WARN, 130 "error", MSG_ERROR, 131 "err", MSG_ERROR, 132 "fatal", MSG_FATAL, 133 "crit", MSG_FATAL, 134 "panic", MSG_PANIC, 135 0, 136 }; 137 138 /* level_map - lookup facility or severity value */ 139 140 static int level_map(char *name) 141 { 142 struct level_table *t; 143 144 for (t = level_table; t->name; t++) 145 if (strcasecmp(t->name, name) == 0) 146 return (t->level); 147 msg_fatal("bad severity: \"%s\"", name); 148 } 149 150 /* log_argv - log the command line */ 151 152 static void log_argv(int level, char **argv) 153 { 154 VSTRING *buf = vstring_alloc(100); 155 156 while (*argv) { 157 vstring_strcat(buf, *argv++); 158 if (*argv) 159 vstring_strcat(buf, " "); 160 } 161 msg_text(level, vstring_str(buf)); 162 vstring_free(buf); 163 } 164 165 /* log_stream - log lines from a stream */ 166 167 static void log_stream(int level, VSTREAM *fp) 168 { 169 VSTRING *buf = vstring_alloc(100); 170 171 while (vstring_get_nonl(buf, fp) != VSTREAM_EOF) 172 msg_text(level, vstring_str(buf)); 173 vstring_free(buf); 174 } 175 176 MAIL_VERSION_STAMP_DECLARE; 177 178 /* main - logger */ 179 180 int main(int argc, char **argv) 181 { 182 struct stat st; 183 int fd; 184 int ch; 185 const char *tag; 186 int log_flags = 0; 187 int level = MSG_INFO; 188 189 /* 190 * Fingerprint executables and core dumps. 191 */ 192 MAIL_VERSION_STAMP_ALLOCATE; 193 194 /* 195 * Be consistent with file permissions. 196 */ 197 umask(022); 198 199 /* 200 * To minimize confusion, make sure that the standard file descriptors 201 * are open before opening anything else. XXX Work around for 44BSD where 202 * fstat can return EBADF on an open file descriptor. 203 */ 204 for (fd = 0; fd < 3; fd++) 205 if (fstat(fd, &st) == -1 206 && (close(fd), open("/dev/null", O_RDWR, 0)) != fd) 207 msg_fatal("open /dev/null: %m"); 208 209 /* 210 * Set up diagnostics. 211 */ 212 tag = mail_task(argv[0]); 213 if (isatty(STDERR_FILENO)) 214 msg_vstream_init(tag, VSTREAM_ERR); 215 msg_syslog_init(tag, LOG_PID, LOG_FACILITY); 216 217 /* 218 * Check the Postfix library version as soon as we enable logging. 219 */ 220 MAIL_VERSION_CHECK; 221 222 /* 223 * Parse switches. 224 */ 225 tag = 0; 226 while ((ch = GETOPT(argc, argv, "c:ip:t:v")) > 0) { 227 switch (ch) { 228 default: 229 msg_fatal("usage: %s [-c config_dir] [-i] [-p priority] [-t tag] [-v] [text]", argv[0]); 230 break; 231 case 'c': 232 if (setenv(CONF_ENV_PATH, optarg, 1) < 0) 233 msg_fatal("out of memory"); 234 break; 235 case 'i': 236 log_flags |= LOG_PID; 237 break; 238 case 'p': 239 level = level_map(optarg); 240 break; 241 case 't': 242 tag = optarg; 243 break; 244 case 'v': 245 msg_verbose++; 246 break; 247 } 248 } 249 250 /* 251 * Process the main.cf file. This may change the syslog_name setting and 252 * may require that mail_task() be re-evaluated. 253 */ 254 mail_conf_read(); 255 if (tag == 0) 256 tag = mail_task(argv[0]); 257 258 /* 259 * Re-initialize the logging, this time with the tag specified in main.cf 260 * or on the command line. 261 */ 262 if (isatty(STDERR_FILENO)) 263 msg_vstream_init(tag, VSTREAM_ERR); 264 msg_syslog_init(tag, LOG_PID, LOG_FACILITY); 265 266 /* 267 * Log the command line or log lines from standard input. 268 */ 269 if (argc > optind) { 270 log_argv(level, argv + optind); 271 } else { 272 log_stream(level, VSTREAM_IN); 273 } 274 275 /* 276 * Consistency with msg(3) functions. 277 */ 278 if (level >= MSG_FATAL) 279 sleep(1); 280 exit(0); 281 } 282