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