1 /*
2 * Copyright (c) 2004, Stefan Walter
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above
10 * copyright notice, this list of conditions and the
11 * following disclaimer.
12 * * Redistributions in binary form must reproduce the
13 * above copyright notice, this list of conditions and
14 * the following disclaimer in the documentation and/or
15 * other materials provided with the distribution.
16 * * The names of contributors to this software may not be
17 * used to endorse or promote products derived from this
18 * software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 * DAMAGE.
32 *
33 *
34 * CONTRIBUTORS
35 * Stef Walter <stef@memberwebs.com>
36 *
37 */
38
39 #include <sys/types.h>
40
41 #include <ctype.h>
42 #include <syslog.h>
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <err.h>
46 #include <strings.h>
47
48 #include "usuals.h"
49 #include "compat.h"
50
51 #ifndef HAVE_STRCLN
52
53 void
strcln(char * data,char ch)54 strcln(char* data, char ch)
55 {
56 char* p;
57 for(p = data; *data; data++, p++)
58 {
59 while(*data == ch)
60 data++;
61 *p = *data;
62 }
63
64 /* Renull terminate */
65 *p = 0;
66 }
67
68 #endif /* HAVE_STRCLN */
69
70 #ifndef HAVE_STRBTRIM
71
72 char*
strbtrim(const char * data)73 strbtrim(const char* data)
74 {
75 while(*data && isspace(*data))
76 ++data;
77 return (char*)data;
78 }
79
80 #endif /* HAVE_STRBTRIM */
81
82 #ifndef HAVE_STRETRIM
83
84 void
stretrim(char * data)85 stretrim(char* data)
86 {
87 char* t = data + strlen(data);
88 while(t > data && isspace(*(t - 1)))
89 {
90 t--;
91 *t = 0;
92 }
93 }
94
95 #endif /* HAVE_STRETRIM */
96
97 #ifndef HAVE_STRTRIM
98
99 char*
strtrim(char * data)100 strtrim(char* data)
101 {
102 data = (char*)strbtrim(data);
103 stretrim(data);
104 return data;
105 }
106
107 #endif /* HAVE_STRTRIM */
108
109 #ifndef HAVE_STRTOB
110
111 int
strtob(const char * str)112 strtob(const char* str)
113 {
114 if(strcasecmp(str, "0") == 0 ||
115 strcasecmp(str, "no") == 0 ||
116 strcasecmp(str, "false") == 0 ||
117 strcasecmp(str, "f") == 0 ||
118 strcasecmp(str, "off") == 0)
119 return 0;
120
121 if(strcasecmp(str, "1") == 0 ||
122 strcasecmp(str, "yes") == 0 ||
123 strcasecmp(str, "true") == 0 ||
124 strcasecmp(str, "t") == 0 ||
125 strcasecmp(str, "on") == 0)
126 return 1;
127
128 return -1;
129 }
130
131 #endif /* HAVE_STRTOB */
132
133
134 #ifndef HAVE_STRLCPY
135
136 size_t
strlcpy(char * dst,const char * src,size_t len)137 strlcpy(char *dst, const char *src, size_t len)
138 {
139 size_t ret = strlen(src);
140 size_t copied;
141
142 while (ret > 0 && len > 1) {
143 *dst++ = *src++;
144 --len;
145 --ret;
146 ++copied;
147 }
148 if (len > 0)
149 *dst = '\0';
150 return copied;
151 }
152
153 #endif /* HAVE_STRLCPY */
154
155 #ifndef HAVE_STRLCAT
156
157 size_t
strlcat(char * dst,const char * src,size_t siz)158 strlcat(char* dst, const char* src, size_t siz)
159 {
160 char* d = dst;
161 const char* s = src;
162 size_t n = siz;
163 size_t dlen;
164
165 while(n-- != 0 && *d != '\0')
166 d++;
167 dlen = d - dst;
168 n = siz - dlen;
169 if(n == 0)
170 return dlen + strlen(s);
171 while(*s != '\0')
172 {
173 if(n != 1)
174 {
175 *d++ = *s;
176 n--;
177 }
178
179 s++;
180 }
181 *d = '\0';
182 return dlen + (s - src); /* count does not include NUL */
183 }
184
185 #endif /* HAVE_STRLCAT */
186
187 #ifndef HAVE_ATEXITV
188
189 typedef void (*voidfunc)(void*);
190 typedef struct _exit_stack
191 {
192 voidfunc func;
193 void* data;
194
195 /* We have a list of these beauties */
196 struct _exit_stack* next;
197 }
198 exit_stack;
199
200 /* Our exit stack */
201 static exit_stack* atexits = NULL;
202 static int atexit_registered = 0;
203
204 static void
atexit_do_stack(void)205 atexit_do_stack(void)
206 {
207 exit_stack* next;
208 for(; atexits; atexits = next)
209 {
210 next = atexits->next;
211 (atexits->func)(atexits->data);
212 free(atexits);
213 }
214 }
215
216 void
atexitv(voidfunc func,void * data)217 atexitv(voidfunc func, void* data)
218 {
219 exit_stack* ae;
220
221 ASSERT(func);
222
223 ae = (exit_stack*)calloc(1, sizeof(exit_stack));
224 if(ae)
225 {
226 ae->func = func;
227 ae->data = data;
228 ae->next = atexits;
229 atexits = ae;
230
231 if(!atexit_registered)
232 atexit(atexit_do_stack);
233 }
234 }
235
236 #endif /* HAVE_ATEXITV */
237
238 #ifndef HAVE_XREALLOC
239
240 void*
xrealloc(void * p,size_t size)241 xrealloc(void *p, size_t size)
242 {
243 register void* value = realloc(p, size);
244 if(value == NULL && size)
245 errx(1, "out of memory");
246 return value;
247 }
248
249 #endif /* HAVE_XREALLOC */
250
251 #ifndef HAVE_XCALLOC
252
253 void*
xcalloc(size_t size)254 xcalloc(size_t size)
255 {
256 register void* value = calloc(1, size);
257 if(value == NULL)
258 errx(1, "out of memory");
259 return value;
260 }
261
262 #endif /* HAVE_XCALLOC */
263
264
265 #ifndef HAVE_STRLWR
266
strlwr(char * data)267 void strlwr(char* data)
268 {
269 while(*data)
270 {
271 *data = tolower(*data);
272 data++;
273 }
274 }
275
276 #endif /* HAVE_STRLWR */
277
278
279 #ifndef HAVE_STRUPR
280
strupr(char * data)281 void strupr(char* data)
282 {
283 while(*data)
284 {
285 *data = toupper(*data);
286 data++;
287 }
288 }
289
290 #endif /* HAVE_STRUPR */
291
292 #ifndef HAVE_STRNCASECMP
293
294 int
strncasecmp(const char * s1,const char * s2,size_t n)295 strncasecmp(const char *s1, const char *s2, size_t n)
296 {
297 if (n != 0) {
298 const unsigned char
299 *us1 = (const unsigned char *)s1,
300 *us2 = (const unsigned char *)s2;
301
302 do {
303 if (tolower(*us1) != tolower(*us2++))
304 return (tolower(*us1) - tolower(*--us2));
305 if (*us1++ == '\0')
306 break;
307 } while (--n != 0);
308 }
309 return (0);
310 }
311
312 #endif /* HAVE_STRNCASECMP */
313
314 #ifndef HAVE_STRCASESTR
315
316 char *
strcasestr(const char * s,const char * find)317 strcasestr(const char *s, const char *find)
318 {
319 char c, sc;
320 size_t len;
321
322 if ((c = *find++) != 0) {
323 c = tolower((unsigned char)c);
324 len = strlen(find);
325 do {
326 do {
327 if ((sc = *s++) == 0)
328 return (NULL);
329 } while ((char)tolower((unsigned char)sc) != c);
330 } while (strncasecmp(s, find, len) != 0);
331 s--;
332 }
333 return ((char *)s);
334 }
335
336 #endif /* HAVE_STRCASESTR */
337
338 #ifndef HAVE_DAEMON
339
340 #include <sys/types.h>
341 #include <unistd.h>
342 #include <stdlib.h>
343 #include <signal.h>
344 #include <fcntl.h>
345
daemon(int nochdir,int noclose)346 int daemon(int nochdir, int noclose)
347 {
348 struct sigaction osa, sa;
349 int oerrno, fd, osa_ok;
350 pid_t newgrp;
351
352 /* A SIGHUP may be thrown when the parent exits below. */
353 sigemptyset(&sa.sa_mask);
354 sa.sa_handler = SIG_IGN;
355 sa.sa_flags = 0;
356 osa_ok = sigaction(SIGHUP, &sa, &osa);
357
358 switch(fork())
359 {
360 case -1:
361 return -1;
362 case 0:
363 break;
364 default:
365 _exit(0);
366 }
367
368 newgrp = setsid();
369 oerrno = errno;
370 if(osa_ok != -1)
371 sigaction(SIGHUP, &osa, NULL);
372 if(newgrp == -1)
373 {
374 errno = oerrno;
375 return -1;
376 }
377 if(!nochdir)
378 chdir("/");
379 if(!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1)
380 {
381 dup2(fd, STDIN_FILENO);
382 dup2(fd, STDOUT_FILENO);
383 dup2(fd, STDERR_FILENO);
384 if(fd > 2)
385 close(fd);
386 }
387 return 0;
388
389 }
390
391 #endif /* HAVE_DAEMON */
392
393