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