xref: /openbsd/usr.bin/sndiod/utils.c (revision 264ca280)
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