static void queue_log(const struct envelope *e, const char *prefix, const char *status) { char rcpt[SMTPD_MAXLINESIZE]; strlcpy(rcpt, "-", sizeof rcpt); if (strcmp(e->rcpt.user, e->dest.user) || strcmp(e->rcpt.domain, e->dest.domain)) snprintf(rcpt, sizeof rcpt, "%s@%s", e->rcpt.user, e->rcpt.domain); log_info("%s: %s for %016" PRIx64 ": from=<%s@%s>, to=<%s@%s>, " "rcpt=<%s>, delay=%s, stat=%s", e->type == D_MDA ? "delivery" : "relay", prefix, e->id, e->sender.user, e->sender.domain, e->dest.user, e->dest.domain, rcpt, duration_to_text(time(NULL) - e->creation), status); }
static void show_stats_output(void) { struct stat_kv kv, *kvp; struct imsg imsg; int n; time_t duration; bzero(&kv, sizeof kv); again: imsg_compose(ibuf, IMSG_STATS_GET, 0, 0, -1, &kv, sizeof kv); while (ibuf->w.queued) if (msgbuf_write(&ibuf->w) < 0) err(1, "write error"); do { if ((n = imsg_read(ibuf)) == -1) errx(1, "imsg_read error"); if (n == 0) errx(1, "pipe closed"); do { if ((n = imsg_get(ibuf, &imsg)) == -1) errx(1, "imsg_get error"); if (n == 0) break; if (imsg.hdr.type != IMSG_STATS_GET) errx(1, "invalid imsg type"); kvp = imsg.data; if (kvp->iter == NULL) { imsg_free(&imsg); return; } if (strcmp(kvp->key, "uptime") == 0) { duration = time(NULL) - kvp->val.u.counter; printf("uptime=%zd\n", (size_t)duration); printf("uptime.human=%s\n", duration_to_text(duration)); } else { switch (kvp->val.type) { case STAT_COUNTER: printf("%s=%zd\n", kvp->key, kvp->val.u.counter); break; case STAT_TIMESTAMP: printf("%s=%" PRId64 "\n", kvp->key, (int64_t)kvp->val.u.timestamp); break; case STAT_TIMEVAL: printf("%s=%zd.%zd\n", kvp->key, kvp->val.u.tv.tv_sec, kvp->val.u.tv.tv_usec); break; case STAT_TIMESPEC: printf("%s=%li.%06li\n", kvp->key, kvp->val.u.ts.tv_sec * 1000000 + kvp->val.u.ts.tv_nsec / 1000000, kvp->val.u.ts.tv_nsec % 1000000); break; } } kv = *kvp; imsg_free(&imsg); goto again; } while (n != 0); } while (n != 0); }