Postfix3.3.1
postcat.c
[詳解]
1 /*++
2 /* NAME
3 /* postcat 1
4 /* SUMMARY
5 /* show Postfix queue file contents
6 /* SYNOPSIS
7 /* \fBpostcat\fR [\fB-bdehnoqv\fR] [\fB-c \fIconfig_dir\fR] [\fIfiles\fR...]
8 /* DESCRIPTION
9 /* The \fBpostcat\fR(1) command prints the contents of the
10 /* named \fIfiles\fR in human-readable form. The files are
11 /* expected to be in Postfix queue file format. If no \fIfiles\fR
12 /* are specified on the command line, the program reads from
13 /* standard input.
14 /*
15 /* By default, \fBpostcat\fR(1) shows the envelope and message
16 /* content, as if the options \fB-beh\fR were specified. To
17 /* view message content only, specify \fB-bh\fR (Postfix 2.7
18 /* and later).
19 /*
20 /* Options:
21 /* .IP \fB-b\fR
22 /* Show body content. The \fB-b\fR option starts producing
23 /* output at the first non-header line, and stops when the end
24 /* of the message is reached.
25 /* .sp
26 /* This feature is available in Postfix 2.7 and later.
27 /* .IP "\fB-c \fIconfig_dir\fR"
28 /* The \fBmain.cf\fR configuration file is in the named directory
29 /* instead of the default configuration directory.
30 /* .IP \fB-d\fR
31 /* Print the decimal type of each record.
32 /* .IP \fB-e\fR
33 /* Show message envelope content.
34 /* .sp
35 /* This feature is available in Postfix 2.7 and later.
36 /* .IP \fB-h\fR
37 /* Show message header content. The \fB-h\fR option produces
38 /* output from the beginning of the message up to, but not
39 /* including, the first non-header line.
40 /* .sp
41 /* This feature is available in Postfix 2.7 and later.
42 /* .IP \fB-o\fR
43 /* Print the queue file offset of each record.
44 /* .IP \fB-q\fR
45 /* Search the Postfix queue for the named \fIfiles\fR instead
46 /* of taking the names literally.
47 /*
48 /* This feature is available in Postfix 2.0 and later.
49 /* .IP \fB-v\fR
50 /* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
51 /* options make the software increasingly verbose.
52 /* DIAGNOSTICS
53 /* Problems are reported to the standard error stream.
54 /* ENVIRONMENT
55 /* .ad
56 /* .fi
57 /* .IP \fBMAIL_CONFIG\fR
58 /* Directory with Postfix configuration files.
59 /* CONFIGURATION PARAMETERS
60 /* .ad
61 /* .fi
62 /* The following \fBmain.cf\fR parameters are especially relevant to
63 /* this program.
64 /*
65 /* The text below provides only a parameter summary. See
66 /* \fBpostconf\fR(5) for more details including examples.
67 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
68 /* The default location of the Postfix main.cf and master.cf
69 /* configuration files.
70 /* .IP "\fBimport_environment (see 'postconf -d' output)\fR"
71 /* The list of environment parameters that a privileged Postfix
72 /* process will import from a non-Postfix parent process, or name=value
73 /* environment overrides.
74 /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
75 /* The location of the Postfix top-level queue directory.
76 /* FILES
77 /* /var/spool/postfix, Postfix queue directory
78 /* SEE ALSO
79 /* postconf(5), Postfix configuration
80 /* LICENSE
81 /* .ad
82 /* .fi
83 /* The Secure Mailer license must be distributed with this software.
84 /* AUTHOR(S)
85 /* Wietse Venema
86 /* IBM T.J. Watson Research
87 /* P.O. Box 704
88 /* Yorktown Heights, NY 10598, USA
89 /*
90 /* Wietse Venema
91 /* Google, Inc.
92 /* 111 8th Avenue
93 /* New York, NY 10011, USA
94 /*--*/
95 
96 /* System library. */
97 
98 #include <sys_defs.h>
99 #include <sys/stat.h>
100 #include <sys/time.h>
101 #include <stdlib.h>
102 #include <unistd.h>
103 #include <time.h>
104 #include <fcntl.h>
105 #include <string.h>
106 #include <stdio.h> /* sscanf() */
107 
108 /* Utility library. */
109 
110 #include <msg.h>
111 #include <vstream.h>
112 #include <vstring.h>
113 #include <msg_vstream.h>
114 #include <vstring_vstream.h>
115 #include <stringops.h>
116 #include <warn_stat.h>
117 #include <clean_env.h>
118 
119 /* Global library. */
120 
121 #include <record.h>
122 #include <rec_type.h>
123 #include <mail_queue.h>
124 #include <mail_conf.h>
125 #include <mail_params.h>
126 #include <mail_version.h>
127 #include <mail_proto.h>
128 #include <is_header.h>
129 #include <lex_822.h>
130 #include <mail_parm_split.h>
131 
132 /* Application-specific. */
133 
134 #define PC_FLAG_SEARCH_QUEUE (1<<0) /* search queue */
135 #define PC_FLAG_PRINT_OFFSET (1<<1) /* print record offsets */
136 #define PC_FLAG_PRINT_ENV (1<<2) /* print envelope records */
137 #define PC_FLAG_PRINT_HEADER (1<<3) /* print header records */
138 #define PC_FLAG_PRINT_BODY (1<<4) /* print body records */
139 #define PC_FLAG_PRINT_RTYPE_DEC (1<<5) /* print decimal record type */
140 #define PC_FLAG_PRINT_RTYPE_SYM (1<<6) /* print symbolic record type */
141 
142 #define PC_MASK_PRINT_TEXT (PC_FLAG_PRINT_HEADER | PC_FLAG_PRINT_BODY)
143 #define PC_MASK_PRINT_ALL (PC_FLAG_PRINT_ENV | PC_MASK_PRINT_TEXT)
144 
145  /*
146  * State machine.
147  */
148 #define PC_STATE_ENV 0 /* initial or extracted envelope */
149 #define PC_STATE_HEADER 1 /* primary header */
150 #define PC_STATE_BODY 2 /* other */
151 
152 #define STR vstring_str
153 #define LEN VSTRING_LEN
154 
155 /* postcat - visualize Postfix queue file contents */
156 
157 static void postcat(VSTREAM *fp, VSTRING *buffer, int flags)
158 {
159  int prev_type = 0;
160  int rec_type;
161  struct timeval tv;
162  time_t time;
163  int ch;
164  off_t offset;
165  const char *error_text;
166  char *attr_name;
167  char *attr_value;
168  int rec_flags = (msg_verbose ? REC_FLAG_NONE : REC_FLAG_DEFAULT);
169  int state; /* state machine, input type */
170  int do_print; /* state machine, output control */
171  long data_offset; /* state machine, read optimization */
172  long data_size; /* state machine, read optimization */
173 
174 #define TEXT_RECORD(rec_type) \
175  (rec_type == REC_TYPE_CONT || rec_type == REC_TYPE_NORM)
176 
177  /*
178  * See if this is a plausible file.
179  */
180  if ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF) {
181  if (!strchr(REC_TYPE_ENVELOPE, ch)) {
182  msg_warn("%s: input is not a valid queue file", VSTREAM_PATH(fp));
183  return;
184  }
185  vstream_ungetc(fp, ch);
186  }
187 
188  /*
189  * Other preliminaries.
190  */
191  if (flags & PC_FLAG_PRINT_ENV)
192  vstream_printf("*** ENVELOPE RECORDS %s ***\n",
193  VSTREAM_PATH(fp));
194  state = PC_STATE_ENV;
195  do_print = (flags & PC_FLAG_PRINT_ENV);
196  data_offset = data_size = -1;
197 
198  /*
199  * Now look at the rest.
200  */
201  for (;;) {
202  if (flags & PC_FLAG_PRINT_OFFSET)
203  offset = vstream_ftell(fp);
204  rec_type = rec_get_raw(fp, buffer, 0, rec_flags);
205  if (rec_type == REC_TYPE_ERROR)
206  msg_fatal("record read error");
207  if (rec_type == REC_TYPE_EOF)
208  break;
209 
210  /*
211  * First inspect records that have side effects on the (envelope,
212  * header, body) state machine or on the record reading order.
213  *
214  * XXX Comments marked "Optimization:" identify subtle code that will
215  * likely need to be revised when the queue file organization is
216  * changed.
217  */
218 #define PRINT_MARKER(flags, fp, offset, type, text) do { \
219  if ((flags) & PC_FLAG_PRINT_OFFSET) \
220  vstream_printf("%9lu ", (unsigned long) (offset)); \
221  if (flags & PC_FLAG_PRINT_RTYPE_DEC) \
222  vstream_printf("%3d ", (type)); \
223  vstream_printf("*** %s %s ***\n", (text), VSTREAM_PATH(fp)); \
224  vstream_fflush(VSTREAM_OUT); \
225 } while (0)
226 
227 #define PRINT_RECORD(flags, offset, type, value) do { \
228  if ((flags) & PC_FLAG_PRINT_OFFSET) \
229  vstream_printf("%9lu ", (unsigned long) (offset)); \
230  if (flags & PC_FLAG_PRINT_RTYPE_DEC) \
231  vstream_printf("%3d ", (type)); \
232  vstream_printf("%s: %s\n", rec_type_name(rec_type), (value)); \
233  vstream_fflush(VSTREAM_OUT); \
234 } while (0)
235 
236  if (TEXT_RECORD(rec_type)) {
237  /* This is wrong when the message starts with whitespace. */
238  if (state == PC_STATE_HEADER && (flags & (PC_MASK_PRINT_TEXT))
239  && prev_type != REC_TYPE_CONT && TEXT_RECORD(rec_type)
240  && !(is_header(STR(buffer)) || IS_SPACE_TAB(STR(buffer)[0]))) {
241  /* Update the state machine. */
242  state = PC_STATE_BODY;
243  do_print = (flags & PC_FLAG_PRINT_BODY);
244  /* Optimization: terminate if nothing left to print. */
245  if (do_print == 0 && (flags & PC_FLAG_PRINT_ENV) == 0)
246  break;
247  /* Optimization: skip to extracted segment marker. */
248  if (do_print == 0 && (flags & PC_FLAG_PRINT_ENV)
249  && data_offset >= 0 && data_size >= 0
250  && vstream_fseek(fp, data_offset + data_size, SEEK_SET) < 0)
251  msg_fatal("seek error: %m");
252  }
253  /* Optional output happens further down below. */
254  } else if (rec_type == REC_TYPE_MESG) {
255  /* Sanity check. */
256  if (state != PC_STATE_ENV)
257  msg_warn("%s: out-of-order message content marker",
258  VSTREAM_PATH(fp));
259  /* Optional output. */
260  if (flags & PC_FLAG_PRINT_ENV)
261  PRINT_MARKER(flags, fp, offset, rec_type, "MESSAGE CONTENTS");
262  /* Optimization: skip to extracted segment marker. */
263  if ((flags & PC_MASK_PRINT_TEXT) == 0
264  && data_offset >= 0 && data_size >= 0
265  && vstream_fseek(fp, data_offset + data_size, SEEK_SET) < 0)
266  msg_fatal("seek error: %m");
267  /* Update the state machine, even when skipping. */
268  state = PC_STATE_HEADER;
269  do_print = (flags & PC_FLAG_PRINT_HEADER);
270  continue;
271  } else if (rec_type == REC_TYPE_XTRA) {
272  /* Sanity check. */
273  if (state != PC_STATE_HEADER && state != PC_STATE_BODY)
274  msg_warn("%s: out-of-order extracted segment marker",
275  VSTREAM_PATH(fp));
276  /* Optional output (terminate preceding header/body line). */
277  if (do_print && prev_type == REC_TYPE_CONT)
278  VSTREAM_PUTCHAR('\n');
279  if (flags & PC_FLAG_PRINT_ENV)
280  PRINT_MARKER(flags, fp, offset, rec_type, "HEADER EXTRACTED");
281  /* Update the state machine. */
282  state = PC_STATE_ENV;
283  do_print = (flags & PC_FLAG_PRINT_ENV);
284  /* Optimization: terminate if nothing left to print. */
285  if (do_print == 0)
286  break;
287  continue;
288  } else if (rec_type == REC_TYPE_END) {
289  /* Sanity check. */
290  if (state != PC_STATE_ENV)
291  msg_warn("%s: out-of-order message end marker",
292  VSTREAM_PATH(fp));
293  /* Optional output. */
294  if (flags & PC_FLAG_PRINT_ENV)
295  PRINT_MARKER(flags, fp, offset, rec_type, "MESSAGE FILE END");
296  /* Terminate the state machine. */
297  break;
298  } else if (rec_type == REC_TYPE_PTR) {
299  /* Optional output. */
300  /* This record type is exposed only with '-v'. */
301  if (do_print)
302  PRINT_RECORD(flags, offset, rec_type, STR(buffer));
303  /* Skip to the pointer's target record. */
304  if (rec_goto(fp, STR(buffer)) == REC_TYPE_ERROR)
305  msg_fatal("bad pointer record, or input is not seekable");
306  continue;
307  } else if (rec_type == REC_TYPE_SIZE) {
308  /* Optional output (here before we update the state machine). */
309  if (do_print)
310  PRINT_RECORD(flags, offset, rec_type, STR(buffer));
311  /* Read the message size/offset for the state machine optimizer. */
312  if (data_size >= 0 || data_offset >= 0) {
313  msg_warn("file contains multiple size records");
314  } else {
315  if (sscanf(STR(buffer), "%ld %ld", &data_size, &data_offset) != 2
316  || data_offset <= 0 || data_size <= 0)
317  msg_fatal("invalid size record: %.100s", STR(buffer));
318  /* Optimization: skip to the message header. */
319  if ((flags & PC_FLAG_PRINT_ENV) == 0) {
320  if (vstream_fseek(fp, data_offset, SEEK_SET) < 0)
321  msg_fatal("seek error: %m");
322  /* Update the state machine. */
323  state = PC_STATE_HEADER;
324  do_print = (flags & PC_FLAG_PRINT_HEADER);
325  }
326  }
327  continue;
328  }
329 
330  /*
331  * Don't inspect side-effect-free records that aren't printed.
332  */
333  if (do_print == 0)
334  continue;
335  if (flags & PC_FLAG_PRINT_OFFSET)
336  vstream_printf("%9lu ", (unsigned long) offset);
337  if (flags & PC_FLAG_PRINT_RTYPE_DEC)
338  vstream_printf("%3d ", rec_type);
339  switch (rec_type) {
340  case REC_TYPE_TIME:
341  REC_TYPE_TIME_SCAN(STR(buffer), tv);
342  time = tv.tv_sec;
343  vstream_printf("%s: %s", rec_type_name(rec_type),
344  asctime(localtime(&time)));
345  break;
346  case REC_TYPE_WARN:
347  REC_TYPE_WARN_SCAN(STR(buffer), time);
348  vstream_printf("%s: %s", rec_type_name(rec_type),
349  asctime(localtime(&time)));
350  break;
351  case REC_TYPE_CONT: /* REC_TYPE_FILT collision */
352  if (state == PC_STATE_ENV)
353  vstream_printf("%s: ", rec_type_name(rec_type));
354  else if (msg_verbose)
355  vstream_printf("unterminated_text: ");
356  vstream_fwrite(VSTREAM_OUT, STR(buffer), LEN(buffer));
357  if (state == PC_STATE_ENV || msg_verbose
358  || (flags & PC_FLAG_PRINT_OFFSET) != 0) {
359  rec_type = 0;
360  VSTREAM_PUTCHAR('\n');
361  }
362  break;
363  case REC_TYPE_NORM:
364  if (msg_verbose)
365  vstream_printf("%s: ", rec_type_name(rec_type));
366  vstream_fwrite(VSTREAM_OUT, STR(buffer), LEN(buffer));
367  VSTREAM_PUTCHAR('\n');
368  break;
369  case REC_TYPE_DTXT:
370  /* This record type is exposed only with '-v'. */
371  vstream_printf("%s: ", rec_type_name(rec_type));
372  vstream_fwrite(VSTREAM_OUT, STR(buffer), LEN(buffer));
373  VSTREAM_PUTCHAR('\n');
374  break;
375  case REC_TYPE_ATTR:
376  error_text = split_nameval(STR(buffer), &attr_name, &attr_value);
377  if (error_text != 0) {
378  msg_warn("%s: malformed attribute: %s: %.100s",
379  VSTREAM_PATH(fp), error_text, STR(buffer));
380  break;
381  }
382  if (strcmp(attr_name, MAIL_ATTR_CREATE_TIME) == 0) {
383  time = atol(attr_value);
385  asctime(localtime(&time)));
386  } else {
387  vstream_printf("%s: %s=%s\n", rec_type_name(rec_type),
388  attr_name, attr_value);
389  }
390  break;
391  default:
392  vstream_printf("%s: %s\n", rec_type_name(rec_type), STR(buffer));
393  break;
394  }
395  prev_type = rec_type;
396 
397  /*
398  * In case the next record is broken.
399  */
401  }
402 }
403 
404 /* usage - explain and terminate */
405 
406 static NORETURN usage(char *myname)
407 {
408  msg_fatal("usage: %s [-b (body text)] [-c config_dir] [-d (decimal record type)] [-e (envelope records)] [-h (header text)] [-q (access queue)] [-v] [file(s)...]",
409  myname);
410 }
411 
413 
414 int main(int argc, char **argv)
415 {
416  VSTRING *buffer;
417  VSTREAM *fp;
418  int ch;
419  int fd;
420  struct stat st;
421  int flags = 0;
422  static char *queue_names[] = {
429  0,
430  };
431  char **cpp;
432  int tries;
433  ARGV *import_env;
434 
435  /*
436  * Fingerprint executables and core dumps.
437  */
439 
440  /*
441  * To minimize confusion, make sure that the standard file descriptors
442  * are open before opening anything else. XXX Work around for 44BSD where
443  * fstat can return EBADF on an open file descriptor.
444  */
445  for (fd = 0; fd < 3; fd++)
446  if (fstat(fd, &st) == -1
447  && (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
448  msg_fatal("open /dev/null: %m");
449 
450  /*
451  * Set up logging.
452  */
453  msg_vstream_init(argv[0], VSTREAM_ERR);
454 
455  /*
456  * Parse JCL.
457  */
458  while ((ch = GETOPT(argc, argv, "bc:dehoqv")) > 0) {
459  switch (ch) {
460  case 'b':
461  flags |= PC_FLAG_PRINT_BODY;
462  break;
463  case 'c':
464  if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
465  msg_fatal("out of memory");
466  break;
467  case 'd':
468  flags |= PC_FLAG_PRINT_RTYPE_DEC;
469  break;
470  case 'e':
471  flags |= PC_FLAG_PRINT_ENV;
472  break;
473  case 'h':
474  flags |= PC_FLAG_PRINT_HEADER;
475  break;
476  case 'o':
477  flags |= PC_FLAG_PRINT_OFFSET;
478  break;
479  case 'q':
480  flags |= PC_FLAG_SEARCH_QUEUE;
481  break;
482  case 'v':
483  msg_verbose++;
484  break;
485  default:
486  usage(argv[0]);
487  }
488  }
489  if ((flags & PC_MASK_PRINT_ALL) == 0)
490  flags |= PC_MASK_PRINT_ALL;
491 
492  /*
493  * Further initialization...
494  */
495  mail_conf_read();
497  update_env(import_env->argv);
498  argv_free(import_env);
499 
500  /*
501  * Initialize.
502  */
503  buffer = vstring_alloc(10);
504 
505  /*
506  * If no file names are given, copy stdin.
507  */
508  if (argc == optind) {
510  CA_VSTREAM_CTL_PATH("stdin"),
512  postcat(VSTREAM_IN, buffer, flags);
513  }
514 
515  /*
516  * Copy the named queue files in the specified order.
517  */
518  else if (flags & PC_FLAG_SEARCH_QUEUE) {
519  if (chdir(var_queue_dir))
520  msg_fatal("chdir %s: %m", var_queue_dir);
521  while (optind < argc) {
522  if (!mail_queue_id_ok(argv[optind]))
523  msg_fatal("bad mail queue ID: %s", argv[optind]);
524  for (fp = 0, tries = 0; fp == 0 && tries < 2; tries++)
525  for (cpp = queue_names; fp == 0 && *cpp != 0; cpp++)
526  fp = mail_queue_open(*cpp, argv[optind], O_RDONLY, 0);
527  if (fp == 0)
528  msg_fatal("open queue file %s: %m", argv[optind]);
529  postcat(fp, buffer, flags);
530  if (vstream_fclose(fp))
531  msg_warn("close %s: %m", argv[optind]);
532  optind++;
533  }
534  }
535 
536  /*
537  * Copy the named files in the specified order.
538  */
539  else {
540  while (optind < argc) {
541  if ((fp = vstream_fopen(argv[optind], O_RDONLY, 0)) == 0)
542  msg_fatal("open %s: %m", argv[optind]);
543  postcat(fp, buffer, flags);
544  if (vstream_fclose(fp))
545  msg_warn("close %s: %m", argv[optind]);
546  optind++;
547  }
548  }
549 
550  /*
551  * Clean up.
552  */
553  vstring_free(buffer);
554  exit(0);
555 }
int msg_verbose
Definition: msg.c:177
#define IS_SPACE_TAB(ch)
Definition: lex_822.h:17
#define VSTREAM_EOF
Definition: vstream.h:110
#define MAIL_ATTR_CREATE_TIME
Definition: mail_proto.h:144
char * var_import_environ
Definition: mail_params.c:296
#define PC_MASK_PRINT_ALL
Definition: postcat.c:143
int mail_queue_id_ok(const char *queue_id)
Definition: mail_queue.c:296
ARGV * argv_free(ARGV *argvp)
Definition: argv.c:136
#define NORETURN
Definition: sys_defs.h:1583
Definition: argv.h:17
#define VAR_IMPORT_ENVIRON
Definition: mail_params.h:2506
int main(int argc, char **argv)
Definition: postcat.c:414
#define MAIL_QUEUE_SAVED
Definition: mail_queue.h:38
#define MAIL_QUEUE_ACTIVE
Definition: mail_queue.h:31
off_t vstream_ftell(VSTREAM *stream)
Definition: vstream.c:1157
#define VSTREAM_OUT
Definition: vstream.h:67
#define stat(p, s)
Definition: warn_stat.h:18
#define VSTREAM_GETC(vp)
Definition: vstream.h:108
int rec_goto(VSTREAM *stream, const char *buf)
Definition: record.c:326
#define PC_STATE_ENV
Definition: postcat.c:148
#define REC_TYPE_SIZE
Definition: rec_type.h:37
#define PC_FLAG_PRINT_ENV
Definition: postcat.c:136
#define REC_FLAG_NONE
Definition: record.h:45
#define PC_STATE_HEADER
Definition: postcat.c:149
char ** argv
Definition: argv.h:20
const char * rec_type_name(int type)
Definition: rec_type.c:79
#define VSTREAM_PATH(vp)
Definition: vstream.h:126
#define VSTREAM_PUTCHAR(ch)
Definition: vstream.h:112
#define VSTREAM_IN
Definition: vstream.h:66
#define REC_TYPE_END
Definition: rec_type.h:77
#define MAIL_QUEUE_HOLD
Definition: mail_queue.h:29
#define PC_FLAG_PRINT_RTYPE_DEC
Definition: postcat.c:139
const char * split_nameval(char *buf, char **name, char **value)
Definition: split_nameval.c:61
#define REC_TYPE_EOF
Definition: rec_type.h:23
void mail_conf_read(void)
Definition: mail_conf.c:178
VSTREAM * vstream_fopen(const char *path, int flags, mode_t mode)
Definition: vstream.c:1241
#define is_header(str)
Definition: is_header.h:17
int rec_get_raw(VSTREAM *stream, VSTRING *buf, ssize_t maxsize, int flags)
Definition: record.c:236
#define PC_FLAG_PRINT_HEADER
Definition: postcat.c:137
#define PC_MASK_PRINT_TEXT
Definition: postcat.c:142
#define CONF_ENV_PATH
Definition: mail_conf.h:22
#define PC_FLAG_PRINT_OFFSET
Definition: postcat.c:135
ARGV * mail_parm_split(const char *name, const char *value)
#define STR
Definition: postcat.c:152
#define REC_TYPE_CONT
Definition: rec_type.h:58
MAIL_VERSION_STAMP_DECLARE
Definition: postcat.c:412
#define vstream_ungetc(vp, ch)
Definition: vstream.h:109
int vstream_fclose(VSTREAM *stream)
Definition: vstream.c:1268
VSTREAM * mail_queue_open(const char *queue_name, const char *queue_id, int flags, mode_t mode)
Definition: mail_queue.c:424
VSTREAM * vstream_printf(const char *fmt,...)
Definition: vstream.c:1335
#define REC_TYPE_MESG
Definition: rec_type.h:56
#define REC_TYPE_PTR
Definition: rec_type.h:67
#define MAIL_QUEUE_INCOMING
Definition: mail_queue.h:30
void msg_warn(const char *fmt,...)
Definition: msg.c:215
#define PC_STATE_BODY
Definition: postcat.c:150
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define PRINT_MARKER(flags, fp, offset, type, text)
#define MAIL_VERSION_STAMP_ALLOCATE
Definition: mail_version.h:67
#define REC_TYPE_WARN
Definition: rec_type.h:48
#define PC_FLAG_SEARCH_QUEUE
Definition: postcat.c:134
#define TEXT_RECORD(rec_type)
#define MAIL_QUEUE_MAILDROP
Definition: mail_queue.h:28
#define REC_TYPE_WARN_SCAN(cp, tv)
Definition: rec_type.h:142
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
off_t vstream_fseek(VSTREAM *stream, off_t offset, int whence)
Definition: vstream.c:1093
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
void update_env(char **preserve_list)
Definition: clean_env.c:102
#define MAIL_QUEUE_DEFERRED
Definition: mail_queue.h:32
#define PC_FLAG_PRINT_BODY
Definition: postcat.c:138
#define GETOPT(argc, argv, str)
Definition: sys_defs.h:1313
#define vstream_fwrite(v, b, n)
Definition: vstream.h:105
#define REC_TYPE_XTRA
Definition: rec_type.h:62
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
char * var_queue_dir
Definition: mail_params.c:246
#define REC_TYPE_ATTR
Definition: rec_type.h:49
void msg_vstream_init(const char *name, VSTREAM *vp)
Definition: msg_vstream.c:77
#define REC_TYPE_ERROR
Definition: rec_type.h:24
#define CA_VSTREAM_CTL_END
Definition: vstream.h:155
#define REC_TYPE_NORM
Definition: rec_type.h:59
#define REC_TYPE_TIME
Definition: rec_type.h:38
#define CA_VSTREAM_CTL_PATH(v)
Definition: vstream.h:158
#define REC_FLAG_DEFAULT
Definition: record.h:50
void vstream_control(VSTREAM *stream, int name,...)
Definition: vstream.c:1372
#define REC_TYPE_TIME_SCAN(cp, tv)
Definition: rec_type.h:150
#define LEN
Definition: postcat.c:153
#define REC_TYPE_DTXT
Definition: rec_type.h:60
#define VSTREAM_ERR
Definition: vstream.h:68
#define fstat(f, s)
Definition: warn_stat.h:20
#define PRINT_RECORD(flags, offset, type, value)
#define REC_TYPE_ENVELOPE
Definition: rec_type.h:106