113 #include <sys/stat.h>
145 #define FREE_AND_WIPE(free, arg) do { if (arg) free(arg); arg = 0; } while (0)
147 #define STR(x) vstring_str(x)
161 #if defined(HAS_FUTIMES_AT)
162 #define CAN_STAMP_BY_STREAM
166 static int stamp_stream(
VSTREAM *fp, time_t when)
168 struct timeval tv[2];
171 tv[0].tv_sec = tv[1].tv_sec = when;
172 tv[0].tv_usec = tv[1].tv_usec = 0;
175 return (futimesat(
vstream_fileno(fp), (
char *) 0, (
struct timeval *) 0));
179 #elif defined(HAS_FUTIMES)
180 #define CAN_STAMP_BY_STREAM
184 static int stamp_stream(
VSTREAM *fp, time_t when)
186 struct timeval tv[2];
189 tv[0].tv_sec = tv[1].tv_sec = when;
190 tv[0].tv_usec = tv[1].tv_usec = 0;
201 static int stamp_path(
const char *path, time_t when)
206 tbuf.actime = tbuf.modtime = when;
207 return (utime(path, &tbuf));
209 return (utime(path, (
struct utimbuf *) 0));
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;
265 check_incoming_fs_clock =
272 want_stamp = time((time_t *) 0) + info->delay;
291 #ifdef CAN_STAMP_BY_STREAM
292 || stamp_stream(info->
stream, want_stamp)
300 || (check_incoming_fs_clock
316 expect_stamp = want_stamp ? want_stamp : time((time_t *) 0);
317 if (st.st_mtime > expect_stamp) {
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;
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;
349 if (path_to_reset != 0) {
351 if (stamp_path(path_to_reset, expect_stamp) < 0 && errno != ENOENT)
352 msg_fatal(
"%s: update file time stamps: %m", info->
id);
400 return (info->
finish(info, why));
406 const char *service,
int mode)
417 info->stream = stream;
418 info->finish = mail_stream_finish_file;
450 info->
finish = mail_stream_finish_ipc;
498 msg_warn(
"command \"%s\" exited with status %d", command, status);
503 info->
finish = mail_stream_finish_ipc;
517 const char *myname =
"mail_stream_ctl";
526 if (info->
finish != mail_stream_finish_file)
527 msg_panic(
"%s: attempt to update non-file stream %s",
539 if ((new_queue = va_arg(ap,
char *)) == 0)
549 if ((string_value = va_arg(ap,
char *)) != 0)
555 if ((string_value = va_arg(ap,
char *)) != 0)
563 info->
mode = va_arg(ap,
int);
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);
577 msg_panic(
"%s: bad op code %d", myname, op);
595 if (new_queue != 0 && strcmp(info->
queue, new_queue) != 0) {
596 char *saved_queue = info->
queue;
611 msg_fatal(
"%s: move to %s queue failed: %m", info->
id,
int mail_stream_finish(MAIL_STREAM *info, VSTRING *why)
VSTREAM * mail_connect_wait(const char *class, const char *name)
void mail_stream_ctl(MAIL_STREAM *info, int op,...)
MAIL_STREAM * mail_stream_file(const char *queue, const char *class, const char *service, int mode)
char * mystrdup(const char *str)
MAIL_STREAM_FINISH_FN finish
MAIL_STREAM_CLOSE_FN close
void mail_stream_cleanup(MAIL_STREAM *info)
ARGV * argv_free(ARGV *argvp)
#define CLEANUP_STAT_SIZE
NORETURN msg_panic(const char *fmt,...)
#define ATTR_FLAG_MISSING
int mail_queue_mkdirs(const char *path)
#define MAIL_STREAM_CTL_END
#define MAIL_STREAM_CTL_CLASS
#define RECV_ATTR_INT(name, val)
int mail_trigger(const char *, const char *, const char *, ssize_t)
MAIL_STREAM * mail_stream_command(const char *command)
#define CA_VSTREAM_POPEN_EXPORT(v)
const char * mail_queue_path(VSTRING *buf, const char *queue_name, const char *queue_id)
int vstream_pclose(VSTREAM *)
#define VAR_EXPORT_ENVIRON
#define MAIL_STREAM_CTL_MODE
ARGV * mail_parm_split(const char *name, const char *value)
int vstream_fclose(VSTREAM *stream)
#define MAIL_QUEUE_INCOMING
VSTREAM * mail_queue_enter(const char *queue_name, mode_t mode, struct timeval *tp)
void msg_warn(const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
#define CA_VSTREAM_POPEN_END
NORETURN msg_fatal(const char *fmt,...)
MAIL_STREAM * mail_stream_service(const char *class, const char *name)
#define MAIL_STREAM_CTL_SERVICE
int vstream_fflush(VSTREAM *stream)
#define MAIL_STREAM_CTL_QUEUE
#define MAIL_QUEUE_DEFERRED
#define CA_VSTREAM_POPEN_COMMAND(v)
#define TRIGGER_REQ_WAKEUP
VSTRING * vstring_free(VSTRING *vp)
#define FREE_AND_WIPE(free, arg)
#define vstream_fileno(vp)
#define CA_VSTREAM_CTL_END
char * var_export_environ
#define CA_VSTREAM_CTL_PATH(v)
#define CLEANUP_STAT_WRITE
#define MAIL_ATTR_QUEUEID
void vstream_control(VSTREAM *stream, int name,...)
VSTREAM VSTREAM const char VSTREAM * vstream_popen(int,...)
#define RECV_ATTR_STR(name, val)
void * mymalloc(ssize_t len)
int WARN_UNUSED_RESULT sane_rename(const char *, const char *)
void msg_info(const char *fmt,...)