/* $OpenBSD: utils.c,v 1.9 2024/12/20 07:35:56 ratchov Exp $ */ /* * Copyright (c) 2003-2012 Alexandre Ratchov * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * logx() quickly stores traces into a trace buffer. * This allows traces to be collected during time sensitive operations without * disturbing them. The buffer can be flushed on standard error later, when * slow syscalls are no longer disruptive, e.g. at the end of the poll() loop. */ #include #include #include #include #include #include #include #include #include #include "utils.h" /* * log buffer size */ #define LOG_BUFSZ 8192 char log_buf[LOG_BUFSZ]; /* buffer where traces are stored */ size_t log_used = 0; /* bytes used in the buffer */ unsigned int log_sync = 1; /* if true, flush after each '\n' */ /* * write the log buffer on stderr */ void log_flush(void) { if (log_used == 0) return; write(STDERR_FILENO, log_buf, log_used); log_used = 0; } /* * log a single line to stderr */ void log_do(const char *fmt, ...) { va_list ap; int n, save_errno = errno; va_start(ap, fmt); n = vsnprintf(log_buf + log_used, sizeof(log_buf) - log_used, fmt, ap); va_end(ap); if (n != -1) { log_used += n; if (log_used >= sizeof(log_buf)) log_used = sizeof(log_buf) - 1; log_buf[log_used++] = '\n'; if (log_sync) log_flush(); } errno = save_errno; } /* * abort program execution after a fatal error */ void panic(void) { log_flush(); (void)kill(getpid(), SIGABRT); _exit(1); } /* * allocate 'size' bytes of memory (with size > 0). This functions never * fails (and never returns NULL), if there isn't enough memory then * abort the program. */ void * xmalloc(size_t size) { void *p; p = malloc(size); if (p == NULL) { logx(0, "failed to allocate %zu bytes", size); panic(); } return p; } /* * free memory allocated with xmalloc() */ void xfree(void *p) { #ifdef DEBUG if (p == NULL) { logx(0, "xfree with NULL arg"); panic(); } #endif free(p); } /* * xmalloc-style strdup(3) */ char * xstrdup(char *s) { size_t size; void *p; size = strlen(s) + 1; p = xmalloc(size); memcpy(p, s, size); return p; }