Postfix3.3.1
mail_stream.c
[詳解]
1 /*++
2 /* NAME
3 /* mail_stream 3
4 /* SUMMARY
5 /* mail stream management
6 /* SYNOPSIS
7 /* #include <mail_stream.h>
8 /*
9 /* typedef struct {
10 /* .in +4
11 /* VSTREAM *stream; /* read/write stream */
12 /* char *id; /* queue ID */
13 /* struct timeval ctime; /* create time */
14 /* private members...
15 /* .in -4
16 /* } MAIL_STREAM;
17 /*
18 /* MAIL_STREAM *mail_stream_file(queue, class, service, mode)
19 /* const char *queue;
20 /* const char *class;
21 /* const char *service;
22 /* int mode;
23 /*
24 /* MAIL_STREAM *mail_stream_service(class, service)
25 /* const char *class;
26 /* const char *service;
27 /*
28 /* MAIL_STREAM *mail_stream_command(command)
29 /* const char *command;
30 /*
31 /* void mail_stream_cleanup(info)
32 /* MAIL_STREAM *info;
33 /*
34 /* int mail_stream_finish(info, why)
35 /* MAIL_STREAM *info;
36 /* VSTRING *why;
37 /*
38 /* void mail_stream_ctl(info, op, ...)
39 /* MAIL_STREAM *info;
40 /* int op;
41 /* DESCRIPTION
42 /* This module provides a generic interface to Postfix queue file
43 /* format messages to file, to Postfix server, or to external command.
44 /* The routines that open a stream return a handle with an initialized
45 /* stream and queue id member. The handle is either given to a cleanup
46 /* routine, to dispose of a failed request, or to a finish routine, to
47 /* complete the request.
48 /*
49 /* mail_stream_file() opens a mail stream to a newly-created file and
50 /* arranges for trigger delivery at finish time. This call never fails.
51 /* But it may take forever. The mode argument specifies additional
52 /* file permissions that will be OR-ed in when the file is finished.
53 /* While embryonic files have mode 0600, finished files have mode 0700.
54 /*
55 /* mail_stream_command() opens a mail stream to external command,
56 /* and receives queue ID information from the command. The result
57 /* is a null pointer when the initial handshake fails. The command
58 /* is given to the shell only when necessary. At finish time, the
59 /* command is expected to send a completion status.
60 /*
61 /* mail_stream_service() opens a mail stream to Postfix service,
62 /* and receives queue ID information from the command. The result
63 /* is a null pointer when the initial handshake fails. At finish
64 /* time, the daemon is expected to send a completion status.
65 /*
66 /* mail_stream_cleanup() cancels the operation that was started with
67 /* any of the mail_stream_xxx() routines, and destroys the argument.
68 /* It is up to the caller to remove incomplete file objects.
69 /*
70 /* mail_stream_finish() completes the operation that was started with
71 /* any of the mail_stream_xxx() routines, and destroys the argument.
72 /* The result is any of the status codes defined in <cleanup_user.h>.
73 /* It is up to the caller to remove incomplete file objects.
74 /* The why argument can be a null pointer.
75 /*
76 /* mail_stream_ctl() selectively overrides information that
77 /* was specified with mail_stream_file(); none of the attributes
78 /* are applicable for other mail stream types. The arguments
79 /* are a list macros with arguments, terminated with
80 /* CA_MAIL_STREAM_CTL_END which has none. The following lists
81 /* the macros and the types of the corresponding arguments.
82 /* .IP "CA_MAIL_STREAM_CTL_QUEUE(const char *)"
83 /* The argument specifies an alternate destination queue. The
84 /* queue file is moved to the specified queue before the call
85 /* returns. Failure to rename the queue file results in a fatal
86 /* error.
87 /* .IP "CA_MAIL_STREAM_CTL_CLASS(const char *)"
88 /* The argument specifies an alternate trigger class.
89 /* .IP "CA_MAIL_STREAM_CTL_SERVICE(const char *)"
90 /* The argument specifies an alternate trigger service.
91 /* .IP "CA_MAIL_STREAM_CTL_MODE(int)"
92 /* The argument specifies alternate permissions that override
93 /* the permissions specified with mail_stream_file().
94 /* .IP "CA_MAIL_STREAM_CTL_DELAY(int)"
95 /* Attempt to postpone initial delivery by advancing the queue
96 /* file modification time stamp by this amount. This has
97 /* effect only within the deferred mail queue.
98 /* This feature may have no effect with remote file systems.
99 /* LICENSE
100 /* .ad
101 /* .fi
102 /* The Secure Mailer license must be distributed with this software.
103 /* AUTHOR(S)
104 /* Wietse Venema
105 /* IBM T.J. Watson Research
106 /* P.O. Box 704
107 /* Yorktown Heights, NY 10598, USA
108 /*--*/
109 
110 /* System library. */
111 
112 #include <sys_defs.h>
113 #include <sys/stat.h>
114 #include <unistd.h>
115 #include <errno.h>
116 #include <utime.h>
117 #include <string.h>
118 #include <stdarg.h>
119 
120 /* Utility library. */
121 
122 #include <msg.h>
123 #include <mymalloc.h>
124 #include <vstring.h>
125 #include <vstream.h>
126 #include <stringops.h>
127 #include <argv.h>
128 #include <sane_fsops.h>
129 #include <warn_stat.h>
130 
131 /* Global library. */
132 
133 #include <cleanup_user.h>
134 #include <mail_proto.h>
135 #include <mail_queue.h>
136 #include <opened.h>
137 #include <mail_params.h>
138 #include <mail_stream.h>
139 #include <mail_parm_split.h>
140 
141 /* Application-specific. */
142 
143 static VSTRING *id_buf;
144 
145 #define FREE_AND_WIPE(free, arg) do { if (arg) free(arg); arg = 0; } while (0)
146 
147 #define STR(x) vstring_str(x)
148 
149 /* mail_stream_cleanup - clean up after success or failure */
150 
152 {
153  FREE_AND_WIPE(info->close, info->stream);
154  FREE_AND_WIPE(myfree, info->queue);
155  FREE_AND_WIPE(myfree, info->id);
156  FREE_AND_WIPE(myfree, info->class);
157  FREE_AND_WIPE(myfree, info->service);
158  myfree((void *) info);
159 }
160 
161 #if defined(HAS_FUTIMES_AT)
162 #define CAN_STAMP_BY_STREAM
163 
164 /* stamp_stream - update open file [am]time stamp */
165 
166 static int stamp_stream(VSTREAM *fp, time_t when)
167 {
168  struct timeval tv[2];
169 
170  if (when != 0) {
171  tv[0].tv_sec = tv[1].tv_sec = when;
172  tv[0].tv_usec = tv[1].tv_usec = 0;
173  return (futimesat(vstream_fileno(fp), (char *) 0, tv));
174  } else {
175  return (futimesat(vstream_fileno(fp), (char *) 0, (struct timeval *) 0));
176  }
177 }
178 
179 #elif defined(HAS_FUTIMES)
180 #define CAN_STAMP_BY_STREAM
181 
182 /* stamp_stream - update open file [am]time stamp */
183 
184 static int stamp_stream(VSTREAM *fp, time_t when)
185 {
186  struct timeval tv[2];
187 
188  if (when != 0) {
189  tv[0].tv_sec = tv[1].tv_sec = when;
190  tv[0].tv_usec = tv[1].tv_usec = 0;
191  return (futimes(vstream_fileno(fp), tv));
192  } else {
193  return (futimes(vstream_fileno(fp), (struct timeval *) 0));
194  }
195 }
196 
197 #endif
198 
199 /* stamp_path - update file [am]time stamp by pathname */
200 
201 static int stamp_path(const char *path, time_t when)
202 {
203  struct utimbuf tbuf;
204 
205  if (when != 0) {
206  tbuf.actime = tbuf.modtime = when;
207  return (utime(path, &tbuf));
208  } else {
209  return (utime(path, (struct utimbuf *) 0));
210  }
211 }
212 
213 /* mail_stream_finish_file - finish file mail stream */
214 
215 static int mail_stream_finish_file(MAIL_STREAM *info, VSTRING *unused_why)
216 {
217  int status = CLEANUP_STAT_OK;
218  static char wakeup[] = {TRIGGER_REQ_WAKEUP};
219  struct stat st;
220  char *path_to_reset = 0;
221  static int incoming_fs_clock_ok = 0;
222  static int incoming_clock_warned = 0;
223  int check_incoming_fs_clock;
224  int err;
225  time_t want_stamp;
226  time_t expect_stamp;
227 
228  /*
229  * Make sure the message makes it to file. Set the execute bit when no
230  * write error was detected. Some people believe that this code has a
231  * problem if the system crashes before fsync() returns; fchmod() could
232  * take effect before all the data blocks are written. Wietse claims that
233  * this is not a problem. Postfix rejects incomplete queue files, even
234  * when the +x attribute is set. Every Postfix queue file record has a
235  * type code and a length field. Files with missing records are rejected,
236  * as are files with unknown record type codes. Every Postfix queue file
237  * must end with an explicit END record. Postfix queue files without END
238  * record are discarded.
239  *
240  * Attempt to detect file system clocks that are ahead of local time, but
241  * don't check the file system clock all the time. The effect of file
242  * system clock drift can be difficult to understand (Postfix ignores new
243  * mail until the local clock catches up with the file mtime stamp).
244  *
245  * This clock drift detection code may not work with file systems that work
246  * on a local copy of the file and that update the server only after the
247  * file is closed.
248  *
249  * Optionally set a cooldown time.
250  *
251  * XXX: We assume that utime() does control the file modification time even
252  * when followed by an fchmod(), fsync(), close() sequence. This may fail
253  * with remote file systems when fsync() actually updates the file. Even
254  * then, we still delay the average message by 1/2 of the
255  * queue_run_delay.
256  *
257  * XXX: Victor does not like running utime() after the close(), since this
258  * creates a race even with local filesystems. But Wietse is not
259  * confident that utime() before fsync() and close() will work reliably
260  * with remote file systems.
261  *
262  * XXX Don't run the clock skew tests with Postfix sendmail submissions.
263  * Don't whine against unsuspecting users or applications.
264  */
265  check_incoming_fs_clock =
266  (!incoming_fs_clock_ok && !strcmp(info->queue, MAIL_QUEUE_INCOMING));
267 
268 #ifdef DELAY_ACTION
269  if (strcmp(info->queue, MAIL_QUEUE_DEFERRED) != 0)
270  info->delay = 0;
271  if (info->delay > 0)
272  want_stamp = time((time_t *) 0) + info->delay;
273  else
274 #endif
275  want_stamp = 0;
276 
277  /*
278  * If we can cheaply set the file time stamp (no pathname lookup) do it
279  * anyway, so that we can avoid whining later about file server/client
280  * clock skew.
281  *
282  * Otherwise, if we must set the file time stamp for delayed delivery, use
283  * whatever means we have to get the job done, no matter if it is
284  * expensive.
285  *
286  * XXX Unfortunately, Linux futimes() is not usable because it uses /proc.
287  * This may not be available because of chroot, or because of access
288  * restrictions after a process changes privileges.
289  */
290  if (vstream_fflush(info->stream)
291 #ifdef CAN_STAMP_BY_STREAM
292  || stamp_stream(info->stream, want_stamp)
293 #else
294  || (want_stamp && stamp_path(VSTREAM_PATH(info->stream), want_stamp))
295 #endif
296  || fchmod(vstream_fileno(info->stream), 0700 | info->mode)
297 #ifdef HAS_FSYNC
298  || fsync(vstream_fileno(info->stream))
299 #endif
300  || (check_incoming_fs_clock
301  && fstat(vstream_fileno(info->stream), &st) < 0)
302  )
303  status = (errno == EFBIG ? CLEANUP_STAT_SIZE : CLEANUP_STAT_WRITE);
304 #ifdef TEST
305  st.st_mtime += 10;
306 #endif
307 
308  /*
309  * Work around file system clock skew. If the file system clock is ahead
310  * of the local clock, Postfix won't deliver mail immediately, which is
311  * bad for performance. If the file system clock falls behind the local
312  * clock, it just looks silly in mail headers.
313  */
314  if (status == CLEANUP_STAT_OK && check_incoming_fs_clock) {
315  /* Do NOT use time() result from before fsync(). */
316  expect_stamp = want_stamp ? want_stamp : time((time_t *) 0);
317  if (st.st_mtime > expect_stamp) {
318  path_to_reset = mystrdup(VSTREAM_PATH(info->stream));
319  if (incoming_clock_warned == 0) {
320  msg_warn("file system clock is %d seconds ahead of local clock",
321  (int) (st.st_mtime - expect_stamp));
322  msg_warn("resetting file time stamps - this hurts performance");
323  incoming_clock_warned = 1;
324  }
325  } else {
326  if (st.st_mtime < expect_stamp - 100)
327  msg_warn("file system clock is %d seconds behind local clock",
328  (int) (expect_stamp - st.st_mtime));
329  incoming_fs_clock_ok = 1;
330  }
331  }
332 
333  /*
334  * Close the queue file and mark it as closed. Be prepared for
335  * vstream_fclose() to fail even after vstream_fflush() and fsync()
336  * reported no error. Reason: after a file is closed, some networked file
337  * systems copy the file out to another machine. Running the queue on a
338  * remote file system is not recommended, if only for performance
339  * reasons.
340  */
341  err = info->close(info->stream);
342  info->stream = 0;
343  if (status == CLEANUP_STAT_OK && err != 0)
344  status = (errno == EFBIG ? CLEANUP_STAT_SIZE : CLEANUP_STAT_WRITE);
345 
346  /*
347  * Work around file system clocks that are ahead of local time.
348  */
349  if (path_to_reset != 0) {
350  if (status == CLEANUP_STAT_OK) {
351  if (stamp_path(path_to_reset, expect_stamp) < 0 && errno != ENOENT)
352  msg_fatal("%s: update file time stamps: %m", info->id);
353  }
354  myfree(path_to_reset);
355  }
356 
357  /*
358  * When all is well, notify the next service that a new message has been
359  * queued.
360  */
361  if (status == CLEANUP_STAT_OK && info->class && info->service)
362  mail_trigger(info->class, info->service, wakeup, sizeof(wakeup));
363 
364  /*
365  * Cleanup.
366  */
367  mail_stream_cleanup(info);
368  return (status);
369 }
370 
371 /* mail_stream_finish_ipc - finish IPC mail stream */
372 
373 static int mail_stream_finish_ipc(MAIL_STREAM *info, VSTRING *why)
374 {
375  int status = CLEANUP_STAT_WRITE;
376 
377  /*
378  * Receive the peer's completion status.
379  */
380  if ((why && attr_scan(info->stream, ATTR_FLAG_STRICT,
383  ATTR_TYPE_END) != 2)
384  || (!why && attr_scan(info->stream, ATTR_FLAG_MISSING,
386  ATTR_TYPE_END) != 1))
387  status = CLEANUP_STAT_WRITE;
388 
389  /*
390  * Cleanup.
391  */
392  mail_stream_cleanup(info);
393  return (status);
394 }
395 
396 /* mail_stream_finish - finish action */
397 
399 {
400  return (info->finish(info, why));
401 }
402 
403 /* mail_stream_file - destination is file */
404 
405 MAIL_STREAM *mail_stream_file(const char *queue, const char *class,
406  const char *service, int mode)
407 {
408  struct timeval tv;
409  MAIL_STREAM *info;
410  VSTREAM *stream;
411 
412  stream = mail_queue_enter(queue, 0600 | mode, &tv);
413  if (msg_verbose)
414  msg_info("open %s", VSTREAM_PATH(stream));
415 
416  info = (MAIL_STREAM *) mymalloc(sizeof(*info));
417  info->stream = stream;
418  info->finish = mail_stream_finish_file;
419  info->close = vstream_fclose;
420  info->queue = mystrdup(queue);
421  info->id = mystrdup(basename(VSTREAM_PATH(stream)));
422  info->class = mystrdup(class);
423  info->service = mystrdup(service);
424  info->mode = mode;
425 #ifdef DELAY_ACTION
426  info->delay = 0;
427 #endif
428  info->ctime = tv;
429  return (info);
430 }
431 
432 /* mail_stream_service - destination is service */
433 
434 MAIL_STREAM *mail_stream_service(const char *class, const char *name)
435 {
436  VSTREAM *stream;
437  MAIL_STREAM *info;
438 
439  if (id_buf == 0)
440  id_buf = vstring_alloc(10);
441 
442  stream = mail_connect_wait(class, name);
443  if (attr_scan(stream, ATTR_FLAG_MISSING,
444  RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id_buf), 0) != 1) {
445  vstream_fclose(stream);
446  return (0);
447  } else {
448  info = (MAIL_STREAM *) mymalloc(sizeof(*info));
449  info->stream = stream;
450  info->finish = mail_stream_finish_ipc;
451  info->close = vstream_fclose;
452  info->queue = 0;
453  info->id = mystrdup(vstring_str(id_buf));
454  info->class = 0;
455  info->service = 0;
456  return (info);
457  }
458 }
459 
460 /* mail_stream_command - destination is command */
461 
462 MAIL_STREAM *mail_stream_command(const char *command)
463 {
464  VSTREAM *stream;
465  MAIL_STREAM *info;
466  ARGV *export_env;
467  int status;
468 
469  if (id_buf == 0)
470  id_buf = vstring_alloc(10);
471 
472  /*
473  * Treat fork() failure as a transient problem. Treat bad handshake as a
474  * permanent error.
475  *
476  * XXX Are we invoking a Postfix process or a non-Postfix process? In the
477  * former case we can share the full environment; in the latter case only
478  * a restricted environment should be propagated. Even though we are
479  * talking a Postfix-internal protocol there is no way we can tell what
480  * is being executed except by duplicating a lot of existing code.
481  */
483  while ((stream = vstream_popen(O_RDWR,
484  CA_VSTREAM_POPEN_COMMAND(command),
485  CA_VSTREAM_POPEN_EXPORT(export_env->argv),
486  CA_VSTREAM_POPEN_END)) == 0) {
487  msg_warn("fork: %m");
488  sleep(10);
489  }
490  argv_free(export_env);
491  vstream_control(stream,
492  CA_VSTREAM_CTL_PATH(command),
494 
495  if (attr_scan(stream, ATTR_FLAG_MISSING,
496  RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id_buf), 0) != 1) {
497  if ((status = vstream_pclose(stream)) != 0)
498  msg_warn("command \"%s\" exited with status %d", command, status);
499  return (0);
500  } else {
501  info = (MAIL_STREAM *) mymalloc(sizeof(*info));
502  info->stream = stream;
503  info->finish = mail_stream_finish_ipc;
504  info->close = vstream_pclose;
505  info->queue = 0;
506  info->id = mystrdup(vstring_str(id_buf));
507  info->class = 0;
508  info->service = 0;
509  return (info);
510  }
511 }
512 
513 /* mail_stream_ctl - update file-based mail stream properties */
514 
515 void mail_stream_ctl(MAIL_STREAM *info, int op,...)
516 {
517  const char *myname = "mail_stream_ctl";
518  va_list ap;
519  char *new_queue = 0;
520  char *string_value;
521 
522  /*
523  * Sanity check. None of the attributes below are applicable unless the
524  * target is a file-based stream.
525  */
526  if (info->finish != mail_stream_finish_file)
527  msg_panic("%s: attempt to update non-file stream %s",
528  myname, info->id);
529 
530  for (va_start(ap, op); op != MAIL_STREAM_CTL_END; op = va_arg(ap, int)) {
531 
532  switch (op) {
533 
534  /*
535  * Change the queue directory. We do this at the end of this
536  * call.
537  */
539  if ((new_queue = va_arg(ap, char *)) == 0)
540  msg_panic("%s: NULL queue",
541  myname);
542  break;
543 
544  /*
545  * Change the service that needs to be notified.
546  */
548  FREE_AND_WIPE(myfree, info->class);
549  if ((string_value = va_arg(ap, char *)) != 0)
550  info->class = mystrdup(string_value);
551  break;
552 
554  FREE_AND_WIPE(myfree, info->service);
555  if ((string_value = va_arg(ap, char *)) != 0)
556  info->service = mystrdup(string_value);
557  break;
558 
559  /*
560  * Change the (finished) file access mode.
561  */
563  info->mode = va_arg(ap, int);
564  break;
565 
566  /*
567  * Advance the (finished) file modification time.
568  */
569 #ifdef DELAY_ACTION
570  case MAIL_STREAM_CTL_DELAY:
571  if ((info->delay = va_arg(ap, int)) < 0)
572  msg_panic("%s: bad delay time %d", myname, info->delay);
573  break;
574 #endif
575 
576  default:
577  msg_panic("%s: bad op code %d", myname, op);
578  }
579  }
580  va_end(ap);
581 
582  /*
583  * Rename the queue file after allocating memory for new information, so
584  * that the caller can still remove an embryonic file when memory
585  * allocation fails (there is no risk of deleting the wrong file).
586  *
587  * Wietse opposed the idea to update run-time error handler information
588  * here, because this module wasn't designed to defend against internal
589  * concurrency issues with error handlers that attempt to follow dangling
590  * pointers.
591  *
592  * This code duplicates mail_queue_rename(), except that we need the new
593  * path to update the stream pathname.
594  */
595  if (new_queue != 0 && strcmp(info->queue, new_queue) != 0) {
596  char *saved_queue = info->queue;
597  char *saved_path = mystrdup(VSTREAM_PATH(info->stream));
598  VSTRING *new_path = vstring_alloc(100);
599 
600  (void) mail_queue_path(new_path, new_queue, info->id);
601  info->queue = mystrdup(new_queue);
602  vstream_control(info->stream, CA_VSTREAM_CTL_PATH(STR(new_path)),
604 
605  if (sane_rename(saved_path, STR(new_path)) == 0
606  || (mail_queue_mkdirs(STR(new_path)) == 0
607  && sane_rename(saved_path, STR(new_path)) == 0)) {
608  if (msg_verbose)
609  msg_info("%s: placed in %s queue", info->id, info->queue);
610  } else {
611  msg_fatal("%s: move to %s queue failed: %m", info->id,
612  info->queue);
613  }
614 
615  myfree(saved_path);
616  myfree(saved_queue);
617  vstring_free(new_path);
618  }
619 }
int mail_stream_finish(MAIL_STREAM *info, VSTRING *why)
Definition: mail_stream.c:398
int msg_verbose
Definition: msg.c:177
void myfree(void *ptr)
Definition: mymalloc.c:207
VSTREAM * mail_connect_wait(const char *class, const char *name)
Definition: mail_connect.c:108
void mail_stream_ctl(MAIL_STREAM *info, int op,...)
Definition: mail_stream.c:515
char * id
Definition: mail_stream.h:37
MAIL_STREAM * mail_stream_file(const char *queue, const char *class, const char *service, int mode)
Definition: mail_stream.c:405
char * mystrdup(const char *str)
Definition: mymalloc.c:225
MAIL_STREAM_FINISH_FN finish
Definition: mail_stream.h:38
MAIL_STREAM_CLOSE_FN close
Definition: mail_stream.h:39
void mail_stream_cleanup(MAIL_STREAM *info)
Definition: mail_stream.c:151
ARGV * argv_free(ARGV *argvp)
Definition: argv.c:136
#define CLEANUP_STAT_SIZE
Definition: cleanup_user.h:59
Definition: argv.h:17
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define vstring_str(vp)
Definition: vstring.h:71
#define ATTR_FLAG_MISSING
Definition: attr.h:99
int mail_queue_mkdirs(const char *path)
Definition: mail_queue.c:228
#define stat(p, s)
Definition: warn_stat.h:18
#define MAIL_STREAM_CTL_END
Definition: mail_stream.h:50
#define MAIL_STREAM_CTL_CLASS
Definition: mail_stream.h:52
char ** argv
Definition: argv.h:20
#define RECV_ATTR_INT(name, val)
Definition: attr.h:71
#define ATTR_TYPE_END
Definition: attr.h:39
#define CLEANUP_STAT_OK
Definition: cleanup_user.h:56
#define VSTREAM_PATH(vp)
Definition: vstream.h:126
char * service
Definition: mail_stream.h:41
int mail_trigger(const char *, const char *, const char *, ssize_t)
Definition: mail_trigger.c:72
MAIL_STREAM * mail_stream_command(const char *command)
Definition: mail_stream.c:462
char * queue
Definition: mail_stream.h:36
#define CA_VSTREAM_POPEN_EXPORT(v)
Definition: vstream.h:210
const char * mail_queue_path(VSTRING *buf, const char *queue_name, const char *queue_id)
Definition: mail_queue.c:204
#define STR(x)
Definition: mail_stream.c:147
int vstream_pclose(VSTREAM *)
#define VAR_EXPORT_ENVIRON
Definition: mail_params.h:2510
#define MAIL_STREAM_CTL_MODE
Definition: mail_stream.h:54
ARGV * mail_parm_split(const char *name, const char *value)
int vstream_fclose(VSTREAM *stream)
Definition: vstream.c:1268
#define MAIL_ATTR_WHY
Definition: mail_proto.h:135
#define MAIL_QUEUE_INCOMING
Definition: mail_queue.h:30
VSTREAM * mail_queue_enter(const char *queue_name, mode_t mode, struct timeval *tp)
Definition: mail_queue.c:319
void msg_warn(const char *fmt,...)
Definition: msg.c:215
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define CA_VSTREAM_POPEN_END
Definition: vstream.h:202
#define MAIL_ATTR_STATUS
Definition: mail_proto.h:126
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
MAIL_STREAM * mail_stream_service(const char *class, const char *name)
Definition: mail_stream.c:434
VSTREAM * stream
Definition: mail_stream.h:35
#define MAIL_STREAM_CTL_SERVICE
Definition: mail_stream.h:53
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
#define MAIL_STREAM_CTL_QUEUE
Definition: mail_stream.h:51
#define MAIL_QUEUE_DEFERRED
Definition: mail_queue.h:32
#define CA_VSTREAM_POPEN_COMMAND(v)
Definition: vstream.h:203
#define TRIGGER_REQ_WAKEUP
Definition: mail_proto.h:101
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
#define FREE_AND_WIPE(free, arg)
Definition: mail_stream.c:145
#define vstream_fileno(vp)
Definition: vstream.h:115
#define CA_VSTREAM_CTL_END
Definition: vstream.h:155
char * var_export_environ
Definition: mail_params.c:297
#define CA_VSTREAM_CTL_PATH(v)
Definition: vstream.h:158
#define CLEANUP_STAT_WRITE
Definition: cleanup_user.h:58
#define MAIL_ATTR_QUEUEID
Definition: mail_proto.h:130
void vstream_control(VSTREAM *stream, int name,...)
Definition: vstream.c:1372
VSTREAM VSTREAM const char VSTREAM * vstream_popen(int,...)
#define attr_scan
Definition: attr.h:111
#define basename
Definition: stringops.h:36
char * class
Definition: mail_stream.h:40
#define fstat(f, s)
Definition: warn_stat.h:20
#define RECV_ATTR_STR(name, val)
Definition: attr.h:72
void * mymalloc(ssize_t len)
Definition: mymalloc.c:150
#define ATTR_FLAG_STRICT
Definition: attr.h:103
int WARN_UNUSED_RESULT sane_rename(const char *, const char *)
Definition: sane_rename.c:41
void msg_info(const char *fmt,...)
Definition: msg.c:199