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