Introduction
Introduction Statistics Contact Development Disclaimer Help
util.c - quark - quark web server
git clone git://git.suckless.org/quark
Log
Files
Refs
LICENSE
---
util.c (4808B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <errno.h>
3 #include <limits.h>
4 #include <stdarg.h>
5 #include <stdint.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sys/types.h>
10 #include <time.h>
11
12 #ifdef __OpenBSD__
13 #include <unistd.h>
14 #endif /* __OpenBSD__ */
15
16 #include "util.h"
17
18 char *argv0;
19
20 static void
21 verr(const char *fmt, va_list ap)
22 {
23 if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) {
24 fprintf(stderr, "%s: ", argv0);
25 }
26
27 vfprintf(stderr, fmt, ap);
28
29 if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
30 fputc(' ', stderr);
31 perror(NULL);
32 } else {
33 fputc('\n', stderr);
34 }
35 }
36
37 void
38 warn(const char *fmt, ...)
39 {
40 va_list ap;
41
42 va_start(ap, fmt);
43 verr(fmt, ap);
44 va_end(ap);
45 }
46
47 void
48 die(const char *fmt, ...)
49 {
50 va_list ap;
51
52 va_start(ap, fmt);
53 verr(fmt, ap);
54 va_end(ap);
55
56 exit(1);
57 }
58
59 void
60 epledge(const char *promises, const char *execpromises)
61 {
62 (void)promises;
63 (void)execpromises;
64
65 #ifdef __OpenBSD__
66 if (pledge(promises, execpromises) == -1) {
67 die("pledge:");
68 }
69 #endif /* __OpenBSD__ */
70 }
71
72 void
73 eunveil(const char *path, const char *permissions)
74 {
75 (void)path;
76 (void)permissions;
77
78 #ifdef __OpenBSD__
79 if (unveil(path, permissions) == -1) {
80 die("unveil:");
81 }
82 #endif /* __OpenBSD__ */
83 }
84
85 int
86 timestamp(char *buf, size_t len, time_t t)
87 {
88 struct tm tm;
89
90 if (gmtime_r(&t, &tm) == NULL ||
91 strftime(buf, len, "%a, %d %b %Y %T GMT", &tm) == 0) {
92 return 1;
93 }
94
95 return 0;
96 }
97
98 int
99 esnprintf(char *str, size_t size, const char *fmt, ...)
100 {
101 va_list ap;
102 int ret;
103
104 va_start(ap, fmt);
105 ret = vsnprintf(str, size, fmt, ap);
106 va_end(ap);
107
108 return (ret < 0 || (size_t)ret >= size);
109 }
110
111 int
112 prepend(char *str, size_t size, const char *prefix)
113 {
114 size_t len = strlen(str), prefixlen = strlen(prefix);
115
116 if (len + prefixlen + 1 > size) {
117 return 1;
118 }
119
120 memmove(str + prefixlen, str, len + 1);
121 memcpy(str, prefix, prefixlen);
122
123 return 0;
124 }
125
126 int
127 spacetok(const char *s, char **t, size_t tlen)
128 {
129 const char *tok;
130 size_t i, j, toki, spaces;
131
132 /* fill token-array with NULL-pointers */
133 for (i = 0; i < tlen; i++) {
134 t[i] = NULL;
135 }
136 toki = 0;
137
138 /* don't allow NULL string or leading spaces */
139 if (!s || *s == ' ') {
140 return 1;
141 }
142 start:
143 /* skip spaces */
144 for (; *s == ' '; s++)
145 ;
146
147 /* don't allow trailing spaces */
148 if (*s == '\0') {
149 goto err;
150 }
151
152 /* consume token */
153 for (tok = s, spaces = 0; ; s++) {
154 if (*s == '\\' && *(s + 1) == ' ') {
155 spaces++;
156 s++;
157 continue;
158 } else if (*s == ' ') {
159 /* end of token */
160 goto token;
161 } else if (*s == '\0') {
162 /* end of string */
163 goto token;
164 }
165 }
166 token:
167 if (toki >= tlen) {
168 goto err;
169 }
170 if (!(t[toki] = malloc(s - tok - spaces + 1))) {
171 die("malloc:");
172 }
173 for (i = 0, j = 0; j < s - tok - spaces + 1; i++, j++) {
174 if (tok[i] == '\\' && tok[i + 1] == ' ') {
175 i++;
176 }
177 t[toki][j] = tok[i];
178 }
179 t[toki][s - tok - spaces] = '\0';
180 toki++;
181
182 if (*s == ' ') {
183 s++;
184 goto start;
185 }
186
187 return 0;
188 err:
189 for (i = 0; i < tlen; i++) {
190 free(t[i]);
191 t[i] = NULL;
192 }
193
194 return 1;
195 }
196
197
198
199 #define INVALID 1
200 #define TOOSMALL 2
201 #define TOOLARGE 3
202
203 long long
204 strtonum(const char *numstr, long long minval, long long maxval,
205 const char **errstrp)
206 {
207 long long ll = 0;
208 int error = 0;
209 char *ep;
210 struct errval {
211 const char *errstr;
212 int err;
213 } ev[4] = {
214 { NULL, 0 },
215 { "invalid", EINVAL },
216 { "too small", ERANGE },
217 { "too large", ERANGE },
218 };
219
220 ev[0].err = errno;
221 errno = 0;
222 if (minval > maxval) {
223 error = INVALID;
224 } else {
225 ll = strtoll(numstr, &ep, 10);
226 if (numstr == ep || *ep != '\0')
227 error = INVALID;
228 else if ((ll == LLONG_MIN && errno == ERANGE) || ll < mi…
229 error = TOOSMALL;
230 else if ((ll == LLONG_MAX && errno == ERANGE) || ll > ma…
231 error = TOOLARGE;
232 }
233 if (errstrp != NULL)
234 *errstrp = ev[error].errstr;
235 errno = ev[error].err;
236 if (error)
237 ll = 0;
238
239 return ll;
240 }
241
242 /*
243 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
244 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
245 */
246 #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
247
248 void *
249 reallocarray(void *optr, size_t nmemb, size_t size)
250 {
251 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
252 nmemb > 0 && SIZE_MAX / nmemb < size) {
253 errno = ENOMEM;
254 return NULL;
255 }
256 return realloc(optr, size * nmemb);
257 }
258
259 int
260 buffer_appendf(struct buffer *buf, const char *suffixfmt, ...)
261 {
262 va_list ap;
263 int ret;
264
265 va_start(ap, suffixfmt);
266 ret = vsnprintf(buf->data + buf->len,
267 sizeof(buf->data) - buf->len, suffixfmt, ap);
268 va_end(ap);
269
270 if (ret < 0 || (size_t)ret >= (sizeof(buf->data) - buf->len)) {
271 /* truncation occured, discard and error out */
272 memset(buf->data + buf->len, 0,
273 sizeof(buf->data) - buf->len);
274 return 1;
275 }
276
277 /* increase buffer length by number of bytes written */
278 buf->len += ret;
279
280 return 0;
281 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.