1 /* $OpenBSD: utils.c,v 1.3 2016/05/25 05:39:50 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 trances 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 a 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 a (small) abount of memory, and abort if it fails 144 */ 145 void * 146 xmalloc(size_t size) 147 { 148 void *p; 149 150 p = malloc(size); 151 if (p == NULL) { 152 log_puts("failed to allocate "); 153 log_putx(size); 154 log_puts(" bytes\n"); 155 panic(); 156 } 157 return p; 158 } 159 160 /* 161 * free memory allocated with xmalloc() 162 */ 163 void 164 xfree(void *p) 165 { 166 #ifdef DEBUG 167 if (p == NULL) { 168 log_puts("xfree with NULL arg\n"); 169 panic(); 170 } 171 #endif 172 free(p); 173 } 174 175 /* 176 * xmalloc-style strdup(3) 177 */ 178 char * 179 xstrdup(char *s) 180 { 181 size_t size; 182 void *p; 183 184 size = strlen(s) + 1; 185 p = xmalloc(size); 186 memcpy(p, s, size); 187 return p; 188 } 189