void log_content_submit(log_content_ctx_t *ctx, logbuf_t *lb, int direction) { logbuf_t *head; time_t epoch; struct tm *utc; char *header; if (!ctx->open) { log_err_printf("log_content_submit called on closed ctx\n"); return; } if (!(header = direction ? ctx->header_out : ctx->header_in)) goto out; /* prepend size tag and newline */ head = logbuf_new_printf(lb->fd, lb, " (%zu):\n", logbuf_size(lb)); if (!head) { log_err_printf("Failed to allocate memory\n"); logbuf_free(lb); return; } lb = head; /* prepend header */ head = logbuf_new_copy(header, strlen(header), lb->fd, lb); if (!head) { log_err_printf("Failed to allocate memory\n"); logbuf_free(lb); return; } lb = head; /* prepend timestamp */ head = logbuf_new_alloc(32, lb->fd, lb); if (!head) { log_err_printf("Failed to allocate memory\n"); logbuf_free(lb); return; } lb = head; time(&epoch); utc = gmtime(&epoch); lb->sz = strftime((char*)lb->buf, lb->sz, "%Y-%m-%d %H:%M:%S UTC ", utc); out: lb->fd = ctx->fd; logger_submit(content_log, lb); }
static logbuf_t * log_content_file_prepcb(void *fh, unsigned long prepflags, logbuf_t *lb) { log_content_ctx_t *ctx = fh; int is_request = !!(prepflags & PREPFLAG_REQUEST); logbuf_t *head; time_t epoch; struct tm *utc; char *header; if (!(header = is_request ? ctx->u.file.header_req : ctx->u.file.header_resp)) goto out; /* prepend size tag and newline */ head = logbuf_new_printf(lb->fh, lb, " (%zu):\n", logbuf_size(lb)); if (!head) { log_err_printf("Failed to allocate memory\n"); logbuf_free(lb); return NULL; } lb = head; /* prepend header */ head = logbuf_new_copy(header, strlen(header), lb->fh, lb); if (!head) { log_err_printf("Failed to allocate memory\n"); logbuf_free(lb); return NULL; } lb = head; /* prepend timestamp */ head = logbuf_new_alloc(32, lb->fh, lb); if (!head) { log_err_printf("Failed to allocate memory\n"); logbuf_free(lb); return NULL; } lb = head; time(&epoch); utc = gmtime(&epoch); lb->sz = strftime((char*)lb->buf, lb->sz, "%Y-%m-%d %H:%M:%S UTC ", utc); out: return lb; }
/* * Free dynbuf including internal and chained buffers. */ void logbuf_free(logbuf_t *lb) { if (lb->buf) { free(lb->buf); } if (lb->next) { logbuf_free(lb->next); } free(lb); }
/* * Generic print to a logger. These functions should be called by the * actual worker thread(s) doing network I/O. * * _printf(), _print() and _write() copy the input buffers. * _ncprint() and _ncwrite() will free() the input buffers. * * The file descriptor argument is a virtual or real system file descriptor * used for multiplexing write requests to several files over the same * logger. This argument is passed to the write handler as-is and is not * interpreted or used by the logger itself in any way. * * All of the functions return 0 on succes, -1 on failure. */ int logger_printf(logger_t *logger, int fd, const char *fmt, ...) { va_list ap; logbuf_t *lb; lb = logbuf_new(NULL, 0, fd, NULL); if (!lb) return -1; va_start(ap, fmt); lb->sz = vasprintf((char**)&lb->buf, fmt, ap); va_end(ap); if (lb->sz == -1) { logbuf_free(lb); return -1; } return logger_submit(logger, lb); }
/* * Write content of logbuf using writefunc and free all buffers. * Returns -1 on errors and sets errno according to write(). * Returns total of bytes written by 1 .. n write() calls on success. */ ssize_t logbuf_write_free(logbuf_t *lb, writefunc_t writefunc) { ssize_t rv1, rv2; rv1 = writefunc(lb->fd, lb->buf, lb->sz); free(lb->buf); if (lb->next) { if (rv1 == -1) { logbuf_free(lb->next); } else { lb->next->fd = lb->fd; rv2 = logbuf_write_free(lb->next, writefunc); } } free(lb); if (rv1 == -1 || rv2 == -1) return -1; else return rv1 + rv2; }