1 /*
2  * $Id: com-misc.c,v 1.9.2.1 2003/05/07 11:15:05 mt Exp $
3  *
4  * Common miscellaneous functions
5  *
6  * Author(s): Jens-Gero Boehm <jens-gero.boehm@suse.de>
7  *            Pieter Hollants <pieter.hollants@suse.de>
8  *            Marius Tomaschewski <mt@suse.de>
9  *            Volker Wiegand <volker.wiegand@suse.de>
10  *
11  * This file is part of the SuSE Proxy Suite
12  *            See also  http://proxy-suite.suse.de/
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version
17  * 2 of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the
26  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27  * Boston, MA 02111-1307, USA.
28  *
29  * A history log can be found at the end of this file.
30  */
31 
32 #ifndef lint
33 static char rcsid[] = "$Id: com-misc.c,v 1.9.2.1 2003/05/07 11:15:05 mt Exp $";
34 #endif
35 
36 #include <config.h>
37 
38 #if defined(STDC_HEADERS)
39 #  include <stdio.h>
40 #  include <string.h>
41 #  include <stdlib.h>
42 #  include <stdarg.h>
43 #  include <errno.h>
44 #endif
45 
46 #include <sys/types.h>
47 #if defined(HAVE_UNISTD_H)
48 #  include <unistd.h>
49 #endif
50 
51 #if TIME_WITH_SYS_TIME
52 #  include <sys/time.h>
53 #  include <time.h>
54 #else
55 #  if HAVE_SYS_TIME_H
56 #    include <sys/time.h>
57 #  else
58 #    include <time.h>
59 #  endif
60 #endif
61 
62 #if defined(HAVE_FCNTL_H)
63 #  include <fcntl.h>
64 #elif defined(HAVE_SYS_FCNTL_H)
65 #  include <sys/fcntl.h>
66 #endif
67 
68 #include "com-config.h"
69 #include "com-debug.h"
70 #include "com-misc.h"
71 #include "com-syslog.h"
72 
73 
74 /* ------------------------------------------------------------ */
75 
76 static void misc_cleanup(void);
77 
78 
79 /* ------------------------------------------------------------ */
80 
81 static int initflag = 0;	/* Have we been initialized?	*/
82 
83 static char p_name[512] = "[unknown name]";
84 static char p_vers[512] = "[unknown version]";
85 static char p_date[512] = "[unknown date]";
86 
87 static char **use_ptr = NULL;	/* Usage information array	*/
88 static char *pid_name = NULL;	/* Name of ProcID file		*/
89 
90 
91 /* ------------------------------------------------------------ **
92 **
93 **	Function......:	misc_cleanup
94 **
95 **	Parameters....:	(none)
96 **
97 **	Return........:	(none)
98 **
99 **	Purpose.......: Clean up at program exit.
100 **
101 ** ------------------------------------------------------------ */
102 
misc_cleanup(void)103 static void misc_cleanup(void)
104 {
105 	if (pid_name != NULL) {
106 		void *tmp = (void *) pid_name;
107 		unlink(pid_name);
108 		pid_name = NULL;
109 		misc_free(FL, tmp);
110 	}
111 }
112 
113 
114 /* ------------------------------------------------------------ **
115 **
116 **	Function......:	misc_forget
117 **
118 **	Parameters....:	(none)
119 **
120 **	Return........:	(none)
121 **
122 **	Purpose.......: Forget cleanup's (for forked children).
123 **
124 ** ------------------------------------------------------------ */
125 
misc_forget(void)126 void misc_forget(void)
127 {
128 	if (pid_name != NULL) {
129 		void *tmp = (void *) pid_name;
130 		pid_name = NULL;
131 		misc_free(FL, tmp);
132 	}
133 }
134 
135 
136 /* ------------------------------------------------------------ **
137 **
138 **	Function......:	misc_setprog / misc_getprog
139 **
140 **	Parameters....:	prog_str	Program name
141 **			usage_arr	Usage info string array
142 **
143 **	Return........:	Program basename
144 **
145 **	Purpose.......: Makes the prog-name known to logging,
146 **			provides a short name without path.
147 **
148 ** ------------------------------------------------------------ */
149 
misc_setprog(char * prog_str,char * usage_arr[])150 char *misc_setprog(char *prog_str, char *usage_arr[])
151 {
152 	char *p;
153 
154 	if (prog_str == NULL)
155 		p = "[unknown name]";
156 	else if ((p = strrchr(prog_str, '/')) != NULL)
157 		p++;
158 	else
159 		p = prog_str;
160 	misc_strncpy(p_name, p, sizeof(p_name));
161 
162 	if (usage_arr != NULL)
163 		use_ptr = usage_arr;
164 
165 	return p_name;
166 }
167 
168 
misc_getprog(void)169 char *misc_getprog(void)
170 {
171 	return p_name;
172 }
173 
174 
175 /* ------------------------------------------------------------ **
176 **
177 **	Function......:	misc_setvers / misc_getvers
178 **			misc_setdate / misc_getdate
179 **			misc_getvsdt
180 **
181 **	Parameters....:	version		Program version
182 **
183 **	Return........:	Program version
184 **
185 **	Purpose.......: Sets and retrieves the program version
186 **			and program compilation date and time.
187 **			And a "standard version + date" thing.
188 **
189 ** ------------------------------------------------------------ */
190 
misc_setvers(char * vers_str)191 void misc_setvers(char *vers_str)
192 {
193 	if (vers_str == NULL)
194 		vers_str = "[unknown version]";
195 	misc_strncpy(p_vers, vers_str, sizeof(p_vers));
196 }
197 
198 
misc_getvers(void)199 char *misc_getvers(void)
200 {
201 	return p_vers;
202 }
203 
204 
misc_setdate(char * date_str)205 void misc_setdate(char *date_str)
206 {
207 	if (date_str == NULL)
208 		date_str = "[unknown date]";
209 	misc_strncpy(p_date, date_str, sizeof(p_date));
210 }
211 
212 
misc_getdate(void)213 char *misc_getdate(void)
214 {
215 	return p_date;
216 }
217 
218 
misc_getvsdt(void)219 char *misc_getvsdt(void)
220 {
221 	static char str[MAX_PATH_SIZE * 2];
222 
223 #if defined(HAVE_SNPRINTF)
224 	snprintf(str, sizeof(str), "Version %s - %s", p_vers, p_date);
225 #else
226 	sprintf(str, "Version %s - %s", p_vers, p_date);
227 #endif
228 	return str;
229 }
230 
231 
232 /* ------------------------------------------------------------ **
233 **
234 **	Function......:	misc_alloc
235 **
236 **	Parameters....:	file		Filename of requestor
237 **			line		Line number of requestor
238 **			len		Number of bytes requested
239 **
240 **	Return........:	Pointer to memory
241 **
242 **	Purpose.......: Allocate memory with malloc. The program
243 **			dies if no memory is available.
244 **			The memory is automatically zero'ed.
245 **
246 ** ------------------------------------------------------------ */
247 
misc_alloc(char * file,int line,size_t len)248 void *misc_alloc(char *file, int line, size_t len)
249 {
250 	void *ptr;
251 
252 	if (file == NULL)		/* Sanity check		*/
253 		file = "[unknown file]";
254 
255 	if (len == 0)			/* Another check ...	*/
256 		misc_die(file, line, "misc_alloc: ?len?");
257 
258 	if ((ptr = malloc(len)) == NULL)
259 		misc_die(file, line, "out of memory");
260 
261 #if defined(COMPILE_DEBUG)
262 	debug(4, "alloc %u (%.*s:%d): %p",
263 		(unsigned) len, MAX_PATH_SIZE, file, line, ptr);
264 #endif
265 
266 	memset(ptr, 0, len);
267 	return ptr;
268 }
269 
270 
271 /* ------------------------------------------------------------ **
272 **
273 **	Function......:	misc_strdup
274 **
275 **	Parameters....:	file		Filename of requestor
276 **			line		Line number of requestor
277 **			str		Pointer to original string
278 **
279 **	Return........:	Pointer to allocated string
280 **
281 **	Purpose.......: Allocate memory for a copy of the given
282 **			string with misc_alloc and copy the
283 **			string in place.
284 **
285 ** ------------------------------------------------------------ */
286 
misc_strdup(char * file,int line,char * str)287 char *misc_strdup(char *file, int line, char *str)
288 {
289 	char *ptr;
290 	int   len;
291 
292 	/* Basic sanity check	*/
293 	if (str == NULL)
294 		misc_die(file, line, "misc_strdup: ?str?");
295 
296 	len = strlen(str);
297 	ptr = (char *) misc_alloc(file, line, len + 1);
298 	strncpy(ptr, str, len);
299 
300 	return ptr;
301 }
302 
303 
304 /* ------------------------------------------------------------ **
305 **
306 **	Function......:	misc_free
307 **
308 **	Parameters....:	file		Filename of requestor
309 **			line		Line number of requestor
310 **			ptr		Memory area to be freed
311 **
312 **	Return........:	(none)
313 **
314 **	Purpose.......: Free memory allocated with misc_alloc.
315 **
316 ** ------------------------------------------------------------ */
317 
misc_free(char * file,int line,void * ptr)318 void misc_free(char *file, int line, void *ptr)
319 {
320 	if (file == NULL)		/* Sanity check		*/
321 		file = "[unknown file]";
322 
323 #if defined(COMPILE_DEBUG)
324 	debug(4, "free %p (%.*s:%d)", ptr, MAX_PATH_SIZE, file, line);
325 #else
326 	line = line;		/* Calm down picky compilers...	*/
327 #endif
328 
329 	if (ptr != NULL)
330 		free(ptr);
331 }
332 
333 
334 /* ------------------------------------------------------------ **
335 **
336 **	Function......:	misc_usage
337 **
338 **	Parameters....:	fmt		Printf-string with usage
339 **
340 **	Return........:	(none)
341 **
342 **	Purpose.......: Print a usage info and terminate.
343 **
344 ** ------------------------------------------------------------ */
345 
misc_usage(char * fmt,...)346 void misc_usage(char *fmt, ...)
347 {
348 	va_list aptr;
349 	int i;
350 
351 	if (use_ptr != NULL) {
352 		for (i = 0; use_ptr[i] != NULL; i++)
353 			fprintf(stderr, "%s\n", use_ptr[i]);
354 	}
355 
356 	if (fmt != NULL && *fmt != '\0') {
357 		fprintf(stderr, "%s Error: ", p_name);
358 		va_start(aptr, fmt);
359 		vfprintf(stderr, fmt, aptr);
360 		va_end(aptr);
361 		fprintf(stderr, "\n\n");
362 	}
363 
364 	exit(EXIT_FAILURE);
365 }
366 
367 
368 /* ------------------------------------------------------------ **
369 **
370 **	Function......:	misc_die
371 **
372 **	Parameters....:	fmt		Printf-string with message
373 **
374 **	Return........:	(none)
375 **
376 **	Purpose.......: Print an error message and terminate.
377 **
378 ** ------------------------------------------------------------ */
379 
misc_die(char * file,int line,char * fmt,...)380 void misc_die(char *file, int line, char *fmt, ...)
381 {
382 	int tmperr = errno;		/* Save errno for later	*/
383 	char str[MAX_PATH_SIZE * 4];
384 	va_list aptr;
385 	size_t len;
386 
387 	if (file == NULL)		/* Sanity check		*/
388 		file = "[unknown file]";
389 
390 	memset(str, 0, sizeof(str));
391 #if defined(HAVE_SNPRINTF)
392 	snprintf(str, sizeof(str), "%s (%.*s:%d): ",
393 	         p_name, MAX_PATH_SIZE, file, line);
394 #else
395 	sprintf(str, "%s (%.*s:%d): ",
396 			p_name, MAX_PATH_SIZE, file, line);
397 #endif
398 	len = strlen(str);
399 
400 	if (fmt != NULL && *fmt != '\0') {
401 		va_start(aptr, fmt);
402 #if defined(HAVE_VSNPRINTF)
403 		vsnprintf(str + len, sizeof(str)-len, fmt, aptr);
404 #else
405 		vsprintf(str + len, fmt, aptr);
406 #endif
407 		va_end(aptr);
408 		len = strlen(str);
409 	}
410 	if (tmperr) {
411 #if defined(HAVE_SNPRINTF)
412 		snprintf(str + len, sizeof(str)-len,
413 		         " (errno=%d [%.256s])",
414 		         tmperr, strerror(tmperr));
415 #else
416 		sprintf(str + len, " (errno=%d [%.256s])",
417 		        tmperr, strerror(tmperr));
418 #endif
419 	}
420 
421 	fprintf(stderr, "%s\n", str);
422 	syslog_write(T_FTL, "%s", str);
423 
424 	errno = tmperr;			/* Restore errno	*/
425 	exit(EXIT_FAILURE);
426 }
427 
428 
429 /* ------------------------------------------------------------ **
430 **
431 **	Function......:	misc_pidfile
432 **
433 **	Parameters....:	name		Desired PID-file name
434 **
435 **	Return........:	(none)
436 **
437 **	Purpose.......: Create a file with the Process-ID.
438 **
439 ** ------------------------------------------------------------ */
440 
misc_pidfile(char * name)441 void misc_pidfile(char *name)
442 {
443 	FILE *fp;
444 	int fd;
445 
446 	if (initflag == 0) {
447 		atexit(misc_cleanup);
448 		initflag = 1;
449 	}
450 
451 	/*
452 	** Do some housekeeping (maybe it's just a close)
453 	*/
454 	if (misc_strequ(name, pid_name))
455 		return;
456 	if (pid_name != NULL) {
457 		void *tmp = (void *) pid_name;
458 		unlink(pid_name);
459 		pid_name = NULL;
460 		misc_free(FL, tmp);
461 	}
462 
463 	/*
464 	** Do we have a real filename now?
465 	*/
466 	if (name != NULL) {
467 		if (unlink(name) < 0 && errno != ENOENT) {
468 			syslog_error("can't remove pidfile '%.*s'",
469 			             MAX_PATH_SIZE, name);
470 			exit(EXIT_FAILURE);
471 		}
472 		if ((fd = open(name, O_RDWR | O_CREAT | O_EXCL, 0644)) < 0)
473 		{
474 			syslog_error("can't open pidfile '%.*s'",
475 			             MAX_PATH_SIZE, name);
476 			exit(EXIT_FAILURE);
477 		}
478 		if ((fp = fdopen(fd, "w")) == NULL) {
479 			syslog_error("can't open pidfile '%.*s'",
480 			             MAX_PATH_SIZE, name);
481 			exit(EXIT_FAILURE);
482 		}
483 		fprintf(fp, "%d\n", (int) getpid());
484 		fclose(fp);
485 		pid_name = misc_strdup(FL, name);
486 	}
487 
488 #if defined(COMPILE_DEBUG)
489 	debug(2, "pid-file: '%s'", NIL(pid_name));
490 #endif
491 }
492 
493 
494 /* ------------------------------------------------------------ **
495 **
496 **	Function......:	misc_strtrim
497 **
498 **	Parameters....:	s		String to be trimmed
499 **
500 **	Return........:	String without leading or trailing space
501 **
502 **	Purpose.......: Trims white space at the beginning and end
503 **			of a given string (this is done in-place).
504 **
505 ** ------------------------------------------------------------ */
506 
misc_strtrim(char * s)507 char *misc_strtrim(char *s)
508 {
509 	char *p;
510 
511 	if (s == NULL)
512 		return NULL;
513 	while (*s == ' ' || *s == '\t')
514 		s++;
515 
516 	p = s + strlen(s);
517 	while (p > s && (p[-1] == ' '  || p[-1] == '\t' ||
518 	                 p[-1] == '\n' || p[-1] == '\r'))
519 		*--p = '\0';
520 
521 	return s;
522 }
523 
524 
525 /* ------------------------------------------------------------ **
526 **
527 **	Function......:	misc_strequ / misc_strcaseequ
528 **
529 **	Parameters....:	s1		First string to compare
530 **			s2		Second string to compare
531 **
532 **	Return........:	1=strings are equal, 0=strings differ
533 **
534 **	Purpose.......: Check if two strings are equal. The
535 **			strings could well be NULL pointers.
536 **			And strcasecmp ignores upper/lower case.
537 **
538 ** ------------------------------------------------------------ */
539 
misc_strequ(const char * s1,const char * s2)540 int misc_strequ(const char *s1, const char *s2)
541 {
542 	if (s1 == NULL && s2 == NULL)
543 		return 1;
544 	if (s1 == NULL && s2 != NULL)
545 		return 0;
546 	if (s1 != NULL && s2 == NULL)
547 		return 0;
548 	return (strcmp(s1, s2) == 0);
549 }
550 
551 
misc_strcaseequ(const char * s1,const char * s2)552 int misc_strcaseequ(const char *s1, const char *s2)
553 {
554 	if (s1 == NULL && s2 == NULL)
555 		return 1;
556 	if (s1 == NULL && s2 != NULL)
557 		return 0;
558 	if (s1 != NULL && s2 == NULL)
559 		return 0;
560 	return (strcasecmp(s1, s2) == 0);
561 }
562 
563 
564 /* ------------------------------------------------------------ **
565 **
566 **	Function......:	misc_strnequ / misc_strncaseequ
567 **
568 **	Parameters....:	s1		First string to compare
569 **			s2		Second string to compare
570 **			n		number of characters in
571 **					in s1 to compare
572 **
573 **	Return........:	1=strings are equal, 0=strings differ
574 **
575 **	Purpose.......: Check if two strings are equal. The
576 **			strings could well be NULL pointers.
577 **			strncasecmp ignores upper/lower case.
578 **
579 ** ------------------------------------------------------------ */
580 
misc_strnequ(const char * s1,const char * s2,size_t n)581 int misc_strnequ(const char *s1, const char *s2, size_t n)
582 {
583 	if (s1 == NULL && s2 == NULL)
584 		return 1;
585 	if (s1 == NULL && s2 != NULL)
586 		return 0;
587 	if (s1 != NULL && s2 == NULL)
588 		return 0;
589 	return (strncmp(s1, s2, n) == 0);
590 }
591 
misc_strncaseequ(const char * s1,const char * s2,size_t n)592 int misc_strncaseequ(const char *s1, const char *s2, size_t n)
593 {
594 	if (s1 == NULL && s2 == NULL)
595 		return 1;
596 	if (s1 == NULL && s2 != NULL)
597 		return 0;
598 	if (s1 != NULL && s2 == NULL)
599 		return 0;
600 	return (strncasecmp(s1, s2, n) == 0);
601 }
602 
603 
604 /* ------------------------------------------------------------ **
605 **
606 **	Function......:	misc_strncpy
607 **
608 **	Parameters....:	s1		Destination pointer
609 **			s2		Source pointer
610 **			len		Size of Destination buffer
611 **
612 **	Return........:	Destination pointer
613 **
614 **	Purpose.......: Copies at most (len - 1) bytes from source
615 **			to destination and fills the residual space
616 **			of the destination buffer with null bytes.
617 **
618 ** ------------------------------------------------------------ */
619 
misc_strncpy(char * s1,const char * s2,size_t len)620 char *misc_strncpy(char *s1, const char *s2, size_t len)
621 {
622 	size_t cnt;
623 
624 	/*
625 	** Prepare the destination buffer
626 	*/
627 	if (s1 == NULL)
628 		return NULL;
629 	memset(s1, 0, len);
630 
631 	/*
632 	** Check the source and get its size
633 	*/
634 	if (s2 == NULL || (cnt = strlen(s2)) == 0)
635 		return s1;
636 
637 	/*
638 	** Copy at most (len - 1) bytes
639 	*/
640 	if (cnt >= len)
641 		cnt = len - 1;
642 	memcpy(s1, s2, cnt);
643 
644 	/*
645 	** Done -- return destination pointer
646 	*/
647 	return s1;
648 }
649 
650 
651 /* ------------------------------------------------------------ **
652 **
653 **	Function......:	misc_chroot
654 **
655 **	Parameters....:	dir	chroot directory
656 **
657 **	Return........:	0 on success, -1 if dir argument
658 **	               was emtpy; exits program on error
659 **
660 **	Purpose.......:	change root into specified directory
661 **
662 ** ------------------------------------------------------------ */
663 
misc_chroot(char * dir)664 int misc_chroot (char *dir)
665 {
666 	if(dir && *dir) {
667 		chdir("/");
668 		if (chroot(dir)) {
669 			syslog_error("can't chroot to '%.1024s'", dir);
670 			exit(EXIT_FAILURE);
671 		}
672 		chdir("/");
673 		return 0;
674 	}
675 	return -1;
676 }
677 
678 
679 /* ------------------------------------------------------------ **
680 **
681 **	Function......:	misc_uidgid
682 **
683 **	Parameters....:	uid		UID (-1 -> use config_uid)
684 **			gid		GID (-1 -> use config_gid)
685 **
686 **	Return........:	(none), exits program on error
687 **
688 **	Purpose.......: Set the UID and GID for the current process.
689 **			If the parameters are -1, use the config
690 **			file's "User" and "Group" variables.
691 **
692 ** ------------------------------------------------------------ */
693 
misc_uidgid(uid_t uid,gid_t gid)694 void misc_uidgid(uid_t uid, gid_t gid)
695 {
696 #if defined(COMPILE_DEBUG)
697 	debug(2, "uid-gid desired: uid=%d gid=%d",
698 					(int) uid, (int) gid);
699 #endif
700 
701 	if (gid == CONFIG_GID) {
702 		if(config_str(NULL, "Group", NULL)) {
703 			/*
704 			** if config defines a group, use it
705 			** or complain (not found in system)
706 			*/
707 			gid = config_gid(NULL, "Group", CONFIG_GID);
708 		} else {
709 			gid = getgid();
710 		}
711 	}
712 	if (gid == CONFIG_GID) {
713 		syslog_error("can't determine Group-ID to use");
714 		exit(EXIT_FAILURE);
715 	}
716 	if (setgid(gid) < 0) {
717 		syslog_error("can't set Group-ID to %d", (int) gid);
718 		exit(EXIT_FAILURE);
719 	}
720 	if (getegid() != gid) {
721 		syslog_error("can't set Group-ID to %d", (int) gid);
722 		exit(EXIT_FAILURE);
723 	}
724 
725 	if (uid == CONFIG_UID) {
726 		if(config_str(NULL, "User", NULL)) {
727 			/*
728 			** if config defines a user, use it
729 			** or complain (not found in system)
730 			*/
731 			uid = config_uid(NULL, "User", CONFIG_UID);
732 		} else {
733 			uid = getuid();
734 		}
735 	}
736 	if (uid == CONFIG_UID) {
737 		syslog_error("can't determine User-ID to use");
738 		exit(EXIT_FAILURE);
739 	}
740 	if (setuid(uid) < 0) {
741 		syslog_error("can't set User-ID to %d", (int) uid);
742 		exit(EXIT_FAILURE);
743 	}
744 	if (geteuid() != uid) {
745 		syslog_error("can't set User-ID to %d", (int) uid);
746 		exit(EXIT_FAILURE);
747 	}
748 
749 #if defined(COMPILE_DEBUG)
750 	debug(2, "uid-gid adopted: uid=%d gid=%d",
751 				(int) getuid(), (int) getgid());
752 #endif
753 }
754 
755 
756 /* ------------------------------------------------------------ **
757 **
758 **	Function......:	misc_rand
759 **
760 **	Parameters....:	lower range mark
761 **			upper range mark
762 **
763 **	Return........:	random number between lower and upper mark
764 **
765 **	Purpose.......: generates a random number in specified range.
766 **
767 ** ------------------------------------------------------------ */
768 
misc_rand(int lrng,int urng)769 int misc_rand (int lrng, int urng)
770 {
771 	struct timeval t;
772 
773 	if (lrng == urng) return lrng;
774 	if (lrng > urng) {
775 		/* swap values */
776 		lrng ^= urng;
777 		urng ^= lrng;
778 		lrng ^= urng;
779 	}
780 
781 	gettimeofday (&t, NULL);
782 	srand (t.tv_usec);
783 
784 	return (lrng + (rand () % (urng - lrng + 1)));
785 }
786 
787 /* ------------------------------------------------------------
788  * $Log: com-misc.c,v $
789  * Revision 1.9.2.1  2003/05/07 11:15:05  mt
790  * misc_strdup: changed to allow empty strings
791  * misc_rand: removed sequence in lrng/urng swapping
792  *
793  * Revision 1.9  2002/05/02 12:59:00  mt
794  * merged with v1.8.2.2
795  *
796  * Revision 1.8.2.1  2002/01/28 01:53:07  mt
797  * implemented misc_strnequ misc_strncaseequ wrappers
798  *
799  * Revision 1.8  2002/01/14 18:18:50  mt
800  * implemented misc_chroot wrapper function
801  * added checks in misc_uidgid if User/Group are set in config
802  * added snprintf usage if supported, replaced all strcpy with strncpy
803  *
804  * Revision 1.7  2001/11/06 23:04:43  mt
805  * applied / merged with transparent proxy patches v8
806  * see ftp-proxy/NEWS for more detailed release news
807  *
808  * Revision 1.6  1999/09/30 09:49:45  wiegand
809  * updated string trim function to trim also newlines
810  *
811  * Revision 1.5  1999/09/26 13:25:05  wiegand
812  * protection of debug/pid/log files against attacks
813  *
814  * Revision 1.4  1999/09/21 05:42:28  wiegand
815  * syslog / abort review
816  *
817  * Revision 1.3  1999/09/17 06:32:28  wiegand
818  * buffer length and overflow protection review
819  *
820  * Revision 1.2  1999/09/16 14:26:33  wiegand
821  * minor code review and cleanup
822  *
823  * Revision 1.1  1999/09/15 14:05:38  wiegand
824  * initial checkin
825  *
826  * ------------------------------------------------------------ */
827 
828