1 /* $OpenBSD: utils.c,v 1.8 2021/11/01 14:43:25 ratchov Exp $ */ 2 /* 3 * Copyright (c) 2003-2012 Alexandre Ratchov <alex@caoua.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 /* 18 * log_xxx() routines are used to quickly store traces into a trace buffer. 19 * This allows traces to be collected during time sensitive operations without 20 * disturbing them. The buffer can be flushed on standard error later, when 21 * slow syscalls are no longer disruptive, e.g. at the end of the poll() loop. 22 */ 23 #include <signal.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <unistd.h> 27 #include <fcntl.h> 28 #include "utils.h" 29 30 /* 31 * log buffer size 32 */ 33 #define LOG_BUFSZ 8192 34 35 /* 36 * store a character in the log 37 */ 38 #define LOG_PUTC(c) do { \ 39 if (log_used < LOG_BUFSZ) \ 40 log_buf[log_used++] = (c); \ 41 } while (0) 42 43 char log_buf[LOG_BUFSZ]; /* buffer where traces are stored */ 44 unsigned int log_used = 0; /* bytes used in the buffer */ 45 unsigned int log_sync = 1; /* if true, flush after each '\n' */ 46 47 /* 48 * write the log buffer on stderr 49 */ 50 void 51 log_flush(void) 52 { 53 if (log_used == 0) 54 return; 55 write(STDERR_FILENO, log_buf, log_used); 56 log_used = 0; 57 } 58 59 /* 60 * store a string in the log 61 */ 62 void 63 log_puts(char *msg) 64 { 65 char *p = msg; 66 int c; 67 68 while ((c = *p++) != '\0') { 69 LOG_PUTC(c); 70 if (log_sync && c == '\n') 71 log_flush(); 72 } 73 } 74 75 /* 76 * store a hex in the log 77 */ 78 void 79 log_putx(unsigned long num) 80 { 81 char dig[sizeof(num) * 2], *p = dig, c; 82 unsigned int ndig; 83 84 if (num != 0) { 85 for (ndig = 0; num != 0; ndig++) { 86 *p++ = num & 0xf; 87 num >>= 4; 88 } 89 for (; ndig != 0; ndig--) { 90 c = *(--p); 91 c += (c < 10) ? '0' : 'a' - 10; 92 LOG_PUTC(c); 93 } 94 } else 95 LOG_PUTC('0'); 96 } 97 98 /* 99 * store an unsigned decimal in the log 100 */ 101 void 102 log_putu(unsigned long num) 103 { 104 char dig[sizeof(num) * 3], *p = dig; 105 unsigned int ndig; 106 107 if (num != 0) { 108 for (ndig = 0; num != 0; ndig++) { 109 *p++ = num % 10; 110 num /= 10; 111 } 112 for (; ndig != 0; ndig--) 113 LOG_PUTC(*(--p) + '0'); 114 } else 115 LOG_PUTC('0'); 116 } 117 118 /* 119 * store a signed decimal in the log 120 */ 121 void 122 log_puti(long num) 123 { 124 if (num < 0) { 125 LOG_PUTC('-'); 126 num = -num; 127 } 128 log_putu(num); 129 } 130 131 /* 132 * abort program execution after a fatal error 133 */ 134 void 135 panic(void) 136 { 137 log_flush(); 138 (void)kill(getpid(), SIGABRT); 139 _exit(1); 140 } 141 142 /* 143 * allocate 'size' bytes of memory (with size > 0). This functions never 144 * fails (and never returns NULL), if there isn't enough memory then 145 * abort the program. 146 */ 147 void * 148 xmalloc(size_t size) 149 { 150 void *p; 151 152 p = malloc(size); 153 if (p == NULL) { 154 log_puts("failed to allocate "); 155 log_putx(size); 156 log_puts(" bytes\n"); 157 panic(); 158 } 159 return p; 160 } 161 162 /* 163 * free memory allocated with xmalloc() 164 */ 165 void 166 xfree(void *p) 167 { 168 #ifdef DEBUG 169 if (p == NULL) { 170 log_puts("xfree with NULL arg\n"); 171 panic(); 172 } 173 #endif 174 free(p); 175 } 176 177 /* 178 * xmalloc-style strdup(3) 179 */ 180 char * 181 xstrdup(char *s) 182 { 183 size_t size; 184 void *p; 185 186 size = strlen(s) + 1; 187 p = xmalloc(size); 188 memcpy(p, s, size); 189 return p; 190 } 191