1 /*
2  * $Id: com-config.c,v 1.7 2002/05/02 12:57:10 mt Exp $
3  *
4  * Common functions for configuration reading
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-config.c,v 1.7 2002/05/02 12:57:10 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 #if defined(HAVE_UNISTD_H)
47 #  include <unistd.h>
48 #endif
49 
50 #include <pwd.h>
51 #include <grp.h>
52 #include <sys/types.h>
53 
54 #include "com-config.h"
55 #include "com-debug.h"
56 #include "com-misc.h"
57 #include "com-socket.h"
58 #include "com-syslog.h"
59 
60 
61 /* ------------------------------------------------------------ */
62 
63 typedef struct config_t {
64 	struct config_t *next;	/* Next config option in chain	*/
65 	char *name;		/* Config option name		*/
66 	char *data;		/* Config value as string	*/
67 } CONFIG;
68 
69 typedef struct section_t {
70 	struct section_t *next;	/* Next config section in chain	*/
71 	char   *name;		/* Section name (NULL=global)	*/
72 	CONFIG *conf;		/* Chained config option list	*/
73 } SECTION;
74 
75 
76 /*
77 ** The next are used for configuration name display
78 */
79 
80 #define MAX_CONF_NAME		128	/* Max display size	*/
81 #define MIN_CONF_NAME		24	/* Display column size	*/
82 
83 
84 /* ------------------------------------------------------------ */
85 
86 static void  config_cleanup(void);
87 static char *config_line   (FILE *fp);
88 
89 
90 /* ------------------------------------------------------------ */
91 
92 static int initflag = 0;	/* Have we been initialized?	*/
93 
94 static SECTION *sechead = NULL;	/* Chain of config sections	*/
95 
96 
97 /* ------------------------------------------------------------ **
98 **
99 **	Function......:	config_cleanup
100 **
101 **	Parameters....:	(none)
102 **
103 **	Return........:	(none)
104 **
105 **	Purpose.......: Clean up the config list.
106 **
107 ** ------------------------------------------------------------ */
108 
config_cleanup(void)109 static void config_cleanup(void)
110 {
111 	SECTION *sect;
112 	CONFIG *conf;
113 
114 #if defined(COMPILE_DEBUG)
115 	debug(3, "config_cleanup");
116 #endif
117 
118 	for (sect = sechead; sect != NULL; ) {
119 		if (sect->name != NULL)
120 			misc_free(FL, sect->name);
121 		for (conf = sect->conf; conf != NULL; ) {
122 			sect->conf = conf->next;
123 			if (conf->name != NULL)
124 				misc_free(FL, conf->name);
125 			if (conf->data != NULL)
126 				misc_free(FL, conf->data);
127 			misc_free(FL, conf);
128 			conf = sect->conf;
129 		}
130 		sechead = sect->next;
131 		misc_free(FL, sect);
132 		sect = sechead;
133 	}
134 }
135 
136 
137 /* ------------------------------------------------------------ **
138 **
139 **	Function......:	config_line
140 **
141 **	Parameters....:	fp		Pointer to the FILE
142 **
143 **	Return........:	Pointer to next line from file
144 **
145 **	Purpose.......: Read the next complete line from a file.
146 **			Filter out empty or comment lines. The
147 **			comment character is defined as '#'.
148 **
149 ** ------------------------------------------------------------ */
150 
config_line(FILE * fp)151 static char *config_line(FILE *fp)
152 {
153 	static char line[MAX_PATH_SIZE * 2];
154 	char *p;
155 	size_t len;
156 
157 	if (fp == NULL)			/* Basic sanity check	*/
158 		misc_die(FL, "config_line: ?fp?");
159 
160 	for (;;) {
161 		memset(line, 0, sizeof(line));
162 
163 		for (len = 0; ; ) {
164 			/*
165 			** Read the first or next line
166 			*/
167 			if (fgets(line + len, sizeof(line) - len,
168 							fp) == NULL) {
169 				if (line[0] == '\0')
170 					return NULL;	/* End of file */
171 				break;
172 			}
173 
174 			/*
175 			** Beautifier: cut leading blanks
176 			*/
177 			p = line + len;
178 			if (*p == ' ' || *p == '\t') {
179 				while (*p == ' ' || *p == '\t')
180 					p++;
181 				memmove(line + len, p, strlen(p) + 1);
182 			}
183 
184 			/*
185 			** Cut off the newline
186 			*/
187 			if ((p = strchr(line, '\n')) != NULL)
188 				*p = '\0';
189 
190 			/*
191 			** Skip empty lines
192 			*/
193 			if ((len = strlen(line)) == 0)
194 				continue;
195 
196 			/*
197 			** Sanity check: truncate lines too long
198 			*/
199 			if (len > (sizeof(line) - 64))
200 				break;
201 
202 			/*
203 			** If the line continues, read on
204 			*/
205 			if (line[--len] != '\\')
206 				break;
207 			line[len] = '\0';
208 		}
209 
210 		/*
211 		** We have a line now, see if it contains data
212 		*/
213 		for (p = line; *p == ' ' || *p == '\t'; p++)
214 			;
215 		if (*p != '\0' && *p != '#')
216 			break;
217 	}
218 
219 #if defined(COMPILE_DEBUG)
220 	debug(3, "config_line: '%.*s'", MAX_PATH_SIZE, p);
221 #endif
222 	return p;
223 }
224 
225 
226 /* ------------------------------------------------------------ **
227 **
228 **	Function......:	config_read
229 **
230 **	Parameters....:	name		Config file name
231 **			dflg		Flag to dump contents
232 **
233 **	Return........:	(none), exits program on error
234 **
235 **	Purpose.......: Read the configuration file and keep
236 **			the values for later usage. If dflg is
237 **			set, the contents of the config file
238 **			are displayed and the program exits.
239 **
240 ** ------------------------------------------------------------ */
241 
config_read(char * file,int dflg)242 void config_read(char *file, int dflg)
243 {
244 	FILE *fp;
245 	char *name, *data;
246 	SECTION *sect, *tmps;
247 	CONFIG *conf, *tmpc;
248 
249 	if (file == NULL)		/* Basic sanity check	*/
250 		misc_die(FL, "config_read: ?file?");
251 
252 	if (initflag == 0) {
253 		atexit(config_cleanup);
254 		initflag = 1;
255 	}
256 	if (sechead != NULL)
257 		config_cleanup();
258 
259 	if ((fp = fopen(file, "r")) == NULL) {
260 		syslog_error("can't open config file '%.*s'",
261 		             MAX_PATH_SIZE, file);
262 		exit(EXIT_FAILURE);
263 	}
264 
265 	/*
266 	** Prepare the global section
267 	*/
268 	sect = (SECTION *) misc_alloc(FL, sizeof(SECTION));
269 	sect->next = NULL;
270 	sect->name = NULL;
271 	sect->conf = NULL;
272 	sechead = sect;
273 
274 	/*
275 	** Now read the file and store sections and options
276 	*/
277 	while ((name = config_line(fp)) != NULL) {
278 		/*
279 		** Check if this is a section
280 		*/
281 		if (*name == '[') {
282 			if ((data = strchr(name, ']')) != NULL)
283 				*data = '\0';
284 			name = misc_strtrim(name + 1);
285 
286 			/*
287 			** Do not accept empty sections or
288 			** sections begining with a wildcard...
289 			*/
290 			if('\0' == name[0] || '*' == name[0]) {
291 				misc_die(FL, "config_read: invalid section");
292 			}
293 
294 			/*
295 			** The global section is outstanding
296 			*/
297 			if (strcasecmp(name, "-global-") == 0) {
298 				sect = sechead;
299 				continue;
300 			}
301 
302 			/*
303 			** Check if the section is already allocated
304 			*/
305 			for (tmps = sechead->next;
306 					tmps; tmps = tmps->next) {
307 				if (strcasecmp(name, tmps->name) == 0)
308 					break;
309 			}
310 			if (tmps != NULL) {
311 				sect = tmps;	/* Make it current */
312 				continue;
313 			}
314 
315 			/*
316 			** Create a new section
317 			*/
318 			sect = (SECTION *)
319 				misc_alloc(FL, sizeof(SECTION));
320 			sect->name = misc_strdup(FL, name);
321 			sect->conf = NULL;
322 
323 			/*
324 			** Keep the sections sorted alphabetically
325 			*/
326 			for (tmps = sechead; tmps; tmps = tmps->next) {
327 				if (tmps->next == NULL)
328 					break;
329 				if (strcasecmp(name, tmps->next->name) < 0)
330 					break;
331 			}
332 			sect->next = tmps->next;
333 			tmps->next = sect;
334 			continue;
335 		}
336 
337 		/*
338 		** Not a section, must be an ordinary line
339 		*/
340 		for (data = name; *data != ' ' && *data != '\t'; data++)
341 			;
342 		if (*data == '\0') {
343 			syslog_write(T_WRN,
344 				"no config value for '%.*s'",
345 				MAX_CONF_NAME, name);
346 			continue;	/* Ignore: missing value */
347 		}
348 
349 		/*
350 		** The following is more or less a sanity check
351 		*/
352 		*data++ = '\0';
353 		if ((name = misc_strtrim(name)) == NULL)
354 			continue;
355 		if ((data = misc_strtrim(data)) == NULL)
356 			continue;
357 		if (*name == '\0' || *data == '\0')
358 			continue;
359 
360 		/*
361 		** Check if the option is already allocated
362 		*/
363 		for (conf = sect->conf; conf; conf = conf->next) {
364 			if (strcasecmp(name, conf->name) == 0)
365 				break;
366 		}
367 		if (conf != NULL) {
368 			if (conf->data)
369 				misc_free(FL, conf->data);
370 			conf->data = misc_strdup(FL, data);
371 			continue;
372 		}
373 
374 		/*
375 		** Create a new config option
376 		*/
377 		conf = (CONFIG *) misc_alloc(FL, sizeof(CONFIG));
378 		conf->name = misc_strdup(FL, name);
379 		conf->data = misc_strdup(FL, data);
380 
381 		/*
382 		** Keep the config list sorted alphabetically
383 		*/
384 		if (sect->conf == NULL ||
385 				strcasecmp(name, sect->conf->name) < 0) {
386 			conf->next = sect->conf;
387 			sect->conf = conf;
388 		} else {
389 			for (tmpc = sect->conf; tmpc; tmpc = tmpc->next) {
390 				if (tmpc->next == NULL)
391 					break;
392 				if (strcasecmp(name, tmpc->next->name) < 0)
393 					break;
394 			}
395 			conf->next = tmpc->next;
396 			tmpc->next = conf;
397 		}
398 	}
399 	fclose(fp);
400 
401 	/*
402 	** Do we just want to validate the interpretation?
403 	*/
404 	if (dflg != 0) {
405 		printf("Config-File: '%.*s'\n", MAX_PATH_SIZE, file);
406 		for (sect = sechead; sect; sect = sect->next) {
407 			printf("Config-Section ------ '%.*s'\n",
408 				MAX_CONF_NAME,
409 				sect->name ? sect->name : "(-global-)");
410 			for (conf = sect->conf; conf; conf = conf->next) {
411 				printf("Config:        %-*.*s = '%.*s'\n",
412 					MIN_CONF_NAME, MAX_CONF_NAME,
413 					conf->name,
414 					MAX_PATH_SIZE, conf->data);
415 			}
416 		}
417 		exit(EXIT_SUCCESS);
418 	}
419 
420 	/*
421 	** Inform the possible auditor
422 	*/
423 	syslog_write(T_INF, "Config-File: '%.*s'",
424 			MAX_PATH_SIZE, file);
425 	for (sect = sechead; sect; sect = sect->next) {
426 		syslog_write(T_INF, "Config-Section ------ '%.*s'",
427 				MAX_CONF_NAME,
428 				sect->name ? sect->name : "(-global-)");
429 		for (conf = sect->conf; conf; conf = conf->next) {
430 			syslog_write(T_INF,
431 				"Config: %-*.*s = '%.*s'",
432 				MIN_CONF_NAME, MAX_CONF_NAME, conf->name,
433 				MAX_PATH_SIZE, conf->data);
434 		}
435 	}
436 }
437 
config_dump(FILE * fd)438 void config_dump(FILE *fd)
439 {
440 	SECTION *sect;
441 	CONFIG *conf;
442 
443 	if(NULL == fd)
444 		return;
445 
446 	for (sect = sechead; sect; sect = sect->next) {
447 		fprintf(fd, "[%.*s]\n", MAX_CONF_NAME,
448 			sect->name ? sect->name : "-Global-");
449 
450 		for (conf = sect->conf; conf; conf = conf->next) {
451 			fprintf(fd, "%-*.*s %.*s\n",
452 				MIN_CONF_NAME, MAX_CONF_NAME,
453 				conf->name,
454 				MAX_PATH_SIZE, conf->data);
455 		}
456 		fprintf(fd, "\n");
457 	}
458 }
459 
460 /* ------------------------------------------------------------ **
461 **
462 **	Function......:	config_sect
463 **
464 **	Parameters....:	snam		Section (NULL=global)
465 **
466 **	Return........:	1=section exists, 0=no such section
467 **
468 **	Purpose.......: Check if a section exists.
469 **
470 ** ------------------------------------------------------------ */
471 
config_sect(char * snam)472 int config_sect(char *snam)
473 {
474 	SECTION *sect;
475 
476 	/*
477 	** Find the relevant section
478 	*/
479 	for (sect = sechead; sect; sect = sect->next) {
480 		if (misc_strcaseequ(snam, sect->name))
481 			return 1;
482 	}
483 	return 0;
484 }
485 
486 
487 /* ------------------------------------------------------------ **
488 **
489 **	Function......:	config_sect_find
490 **
491 **	Parameters....:	snam		Section (NULL=global)
492 **
493 **	Return........:	pointer to the found the section or NULL
494 **
495 **	Purpose.......: find a config section by name; if snam
496 **			is NULL the global section matches!
497 **
498 ** ------------------------------------------------------------ */
config_sect_find(char * snam)499 static SECTION* config_sect_find(char *snam)
500 {
501 	SECTION *sect;
502 	char    *wild;
503 
504 	/*
505 	** Find the relevant section
506 	*/
507 	for(sect = sechead; sect; sect = sect->next) {
508 		if(sect->name && (wild = strchr(sect->name, '*'))) {
509 #if defined(COMPILE_DEBUG)
510 			debug(3, "config_sect_find: wildcard-sect='%.*s*'\n",
511 				  wild - sect->name, sect->name);
512 #endif
513 			if (misc_strncaseequ(sect->name, snam,
514 			                     wild - sect->name))
515 				break;
516 		} else {
517 			if (misc_strcaseequ(sect->name, snam))
518 				break;
519 		}
520 	}
521 	return sect;
522 }
523 
524 /* ------------------------------------------------------------ **
525 **
526 **	Function......:	config_int
527 **
528 **	Parameters....:	snam		Section (NULL=global)
529 **			name		Config option name
530 **			dflt		Default value
531 **
532 **	Return........:	Integer value for config option
533 **
534 **	Purpose.......: Retrieve a numeric config value.
535 **
536 ** ------------------------------------------------------------ */
537 
config_int(char * snam,char * name,int dflt)538 int config_int(char *snam, char *name, int dflt)
539 {
540 	SECTION *sect;
541 	CONFIG *conf;
542 	char *p;
543 	int i;
544 
545 	if (name == NULL)		/* Basic sanity check	*/
546 		misc_die(FL, "config_int: ?name?");
547 
548 #if defined(COMPILE_DEBUG)
549 	debug(3, "config_int: s='%.*s' n='%.*s' d=%d",
550 				MAX_CONF_NAME, NIL(snam),
551 				MAX_CONF_NAME, name,
552 				dflt);
553 #endif
554 
555 	/*
556 	** Find the relevant section
557 	*/
558 	sect = config_sect_find(snam);
559 	if (sect == NULL)
560 		return (snam ? config_int(NULL, name, dflt) : dflt);
561 
562 	/*
563 	** Now look for the desired value
564 	*/
565 	for (conf = sect->conf, p = NULL; conf; conf = conf->next) {
566 		if (strcasecmp(conf->name, name) == 0) {
567 			p = conf->data;
568 			break;
569 		}
570 	}
571 	if (conf == NULL)
572 		return (snam ? config_int(NULL, name, dflt) : dflt);
573 
574 	/*
575 	** Evaluate the found string
576 	*/
577 	i = atoi(p);
578 
579 	/*
580 	** Return the value found
581 	*/
582 #if defined(COMPILE_DEBUG)
583 	debug(3, "config_int: result=%d", i);
584 #endif
585 	return i;
586 }
587 
588 
589 /* ------------------------------------------------------------ **
590 **
591 **	Function......:	config_bool
592 **
593 **	Parameters....:	snam		Section (NULL=global)
594 **			name		Config option name
595 **			dflt		Default value
596 **
597 **	Return........:	0/1 value for config option
598 **
599 **	Purpose.......: Retrieve a boolean config value.
600 **
601 ** ------------------------------------------------------------ */
602 
config_bool(char * snam,char * name,int dflt)603 int config_bool(char *snam, char *name, int dflt)
604 {
605 	SECTION *sect;
606 	CONFIG *conf;
607 	char *p;
608 	int i;
609 
610 	if (name == NULL)		/* Basic sanity check	*/
611 		misc_die(FL, "config_bool: ?name?");
612 	dflt = (dflt != 0);		/* Normalize value	*/
613 
614 #if defined(COMPILE_DEBUG)
615 	debug(3, "config_bool: s='%.*s' n='%.*s' d=%d",
616 				MAX_CONF_NAME, NIL(snam),
617 				MAX_CONF_NAME, name,
618 				dflt);
619 #endif
620 
621 	/*
622 	** Find the relevant section
623 	*/
624 	sect = config_sect_find(snam);
625 	if (sect == NULL)
626 		return (snam ? config_bool(NULL, name, dflt) : dflt);
627 
628 	/*
629 	** Now look for the desired value
630 	*/
631 	for (conf = sect->conf, p = NULL; conf; conf = conf->next) {
632 		if (strcasecmp(conf->name, name) == 0) {
633 			p = conf->data;
634 			break;
635 		}
636 	}
637 	if (conf == NULL)
638 		return (snam ? config_bool(NULL, name, dflt) : dflt);
639 
640 	/*
641 	** Evaluate the found string
642 	*/
643 	if (strcasecmp(p, "y") == 0)
644 		i = 1;
645 	else if (strcasecmp(p, "on") == 0)
646 		i = 1;
647 	else if (strcasecmp(p, "yes") == 0)
648 		i = 1;
649 	else if (strcasecmp(p, "true") == 0)
650 		i = 1;
651 	else if (*p >= '0' && *p <= '9')
652 		i = (atoi(p) != 0);
653 	else
654 		i = 0;
655 
656 	/*
657 	** Return the value found
658 	*/
659 #if defined(COMPILE_DEBUG)
660 	debug(3, "config_bool: result=%d", i);
661 #endif
662 	return i;
663 }
664 
665 
666 /* ------------------------------------------------------------ **
667 **
668 **	Function......:	config_str
669 **
670 **	Parameters....:	snam		Section (NULL=global)
671 **			name		Config option name
672 **			dflt		Default value
673 **
674 **	Return........:	String value for config option
675 **
676 **	Purpose.......: Retrieve a textual config value.
677 **
678 ** ------------------------------------------------------------ */
679 
config_str(char * snam,char * name,char * dflt)680 char *config_str(char *snam, char *name, char *dflt)
681 {
682 	SECTION *sect;
683 	CONFIG *conf;
684 	char *p;
685 
686 	if (name == NULL)		/* Basic sanity check	*/
687 		misc_die(FL, "config_str: ?name?");
688 
689 #if defined(COMPILE_DEBUG)
690 	debug(3, "config_str: s='%.*s' n='%.*s' d='%.*s'",
691 				MAX_CONF_NAME, NIL(snam),
692 				MAX_CONF_NAME, name,
693 				MAX_PATH_SIZE, NIL(dflt));
694 #endif
695 
696 	/*
697 	** Find the relevant section
698 	*/
699 	sect = config_sect_find(snam);
700 	if (sect == NULL)
701 		return (snam ? config_str(NULL, name, dflt) : dflt);
702 
703 	/*
704 	** Now look for the desired value
705 	*/
706 	for (conf = sect->conf, p = NULL; conf; conf = conf->next) {
707 		if (strcasecmp(conf->name, name) == 0) {
708 			p = conf->data;
709 			break;
710 		}
711 	}
712 	if (conf == NULL)
713 		return (snam ? config_str(NULL, name, dflt) : dflt);
714 
715 	/*
716 	** Return the value found
717 	*/
718 #if defined(COMPILE_DEBUG)
719 	debug(3, "config_str: result='%.*s'", MAX_PATH_SIZE, NIL(p));
720 #endif
721 	return p;
722 }
723 
724 
725 /* ------------------------------------------------------------ **
726 **
727 **	Function......:	config_addr
728 **
729 **	Parameters....:	snam		Section (NULL=global)
730 **			name		Config option name
731 **			dflt		Default value
732 **
733 **	Return........:	IP Address value for config option
734 **			(returned in host byte order)
735 **
736 **	Purpose.......: Retrieve an IP Address config value.
737 **
738 ** ------------------------------------------------------------ */
739 
config_addr(char * snam,char * name,u_int32_t dflt)740 u_int32_t config_addr(char *snam, char *name, u_int32_t dflt)
741 {
742 	SECTION *sect;
743 	CONFIG *conf;
744 	char *p;
745 	u_int32_t addr;
746 
747 	if (name == NULL)		/* Basic sanity check	*/
748 		misc_die(FL, "config_addr: ?name?");
749 
750 #if defined(COMPILE_DEBUG)
751 	debug(3, "config_addr: s='%.*s' n='%.*s' d='%s'",
752 				MAX_CONF_NAME, NIL(snam),
753 				MAX_CONF_NAME, name,
754 				socket_addr2str(dflt));
755 #endif
756 
757 	/*
758 	** Find the relevant section
759 	*/
760 	sect = config_sect_find(snam);
761 	if (sect == NULL)
762 		return (snam ? config_addr(NULL, name, dflt) : dflt);
763 
764 	/*
765 	** Now look for the desired value
766 	*/
767 	for (conf = sect->conf, p = NULL; conf; conf = conf->next) {
768 		if (strcasecmp(conf->name, name) == 0) {
769 			p = conf->data;
770 			break;
771 		}
772 	}
773 	if (conf == NULL)
774 		return (snam ? config_addr(NULL, name, dflt) : dflt);
775 
776 	/*
777 	** Evaluate the found string
778 	*/
779 	addr = socket_str2addr(p, dflt);
780 
781 	/*
782 	** Return the value found
783 	*/
784 #if defined(COMPILE_DEBUG)
785 	debug(3, "config_addr: result='%s'", socket_addr2str(addr));
786 #endif
787 	return addr;
788 }
789 
790 
791 /* ------------------------------------------------------------ **
792 **
793 **	Function......:	config_port
794 **
795 **	Parameters....:	snam		Section (NULL=global)
796 **			name		Config option name
797 **			dflt		Default value
798 **
799 **	Return........:	TCP Port value for config option
800 **			(returned in host byte order)
801 **
802 **	Purpose.......: Retrieve a TCP Port config value.
803 **
804 ** ------------------------------------------------------------ */
805 
config_port(char * snam,char * name,u_int16_t dflt)806 u_int16_t config_port(char *snam, char *name, u_int16_t dflt)
807 {
808 	SECTION *sect;
809 	CONFIG *conf;
810 	char *p;
811 	u_int16_t port;
812 
813 	if (name == NULL)		/* Basic sanity check	*/
814 		misc_die(FL, "config_port: ?name?");
815 
816 #if defined(COMPILE_DEBUG)
817 	debug(3, "config_port: s='%.*s' n='%.*s' d=%d",
818 				MAX_CONF_NAME, NIL(snam),
819 				MAX_CONF_NAME, name,
820 				(int) dflt);
821 #endif
822 
823 	/*
824 	** Find the relevant section
825 	*/
826 	sect = config_sect_find(snam);
827 	if (sect == NULL)
828 		return (snam ? config_port(NULL, name, dflt) : dflt);
829 
830 	/*
831 	** Now look for the desired value
832 	*/
833 	for (conf = sect->conf, p = NULL; conf; conf = conf->next) {
834 		if (strcasecmp(conf->name, name) == 0) {
835 			p = conf->data;
836 			break;
837 		}
838 	}
839 	if (conf == NULL)
840 		return (snam ? config_port(NULL, name, dflt) : dflt);
841 
842 	/*
843 	** Evaluate the found string
844 	*/
845 	port = socket_str2port(p, dflt);
846 
847 	/*
848 	** Return the value found
849 	*/
850 #if defined(COMPILE_DEBUG)
851 	debug(3, "config_port: result=%d", (int) port);
852 #endif
853 	return port;
854 }
855 
856 
857 /* ------------------------------------------------------------ **
858 **
859 **	Function......:	config_uid
860 **
861 **	Parameters....:	snam		Section (NULL=global)
862 **			name		Config option name
863 **			dflt		Default value
864 **
865 **	Return........:	User-ID value for config option
866 **
867 **	Purpose.......: Retrieve a User-ID config value.
868 **
869 ** ------------------------------------------------------------ */
870 
config_uid(char * snam,char * name,uid_t dflt)871 uid_t config_uid(char *snam, char *name, uid_t dflt)
872 {
873 	SECTION *sect;
874 	CONFIG *conf;
875 	char *p;
876 	struct passwd *pwd;
877 	uid_t uid;
878 
879 	if (name == NULL)		/* Basic sanity check	*/
880 		misc_die(FL, "config_uid: ?name?");
881 
882 #if defined(COMPILE_DEBUG)
883 	debug(3, "config_uid: s='%.*s' n='%.*s' d=%d",
884 				MAX_CONF_NAME, NIL(snam),
885 				MAX_CONF_NAME, name,
886 				(int) dflt);
887 #endif
888 
889 	/*
890 	** Find the relevant section
891 	*/
892 	sect = config_sect_find(snam);
893 	if (sect == NULL)
894 		return (snam ? config_uid(NULL, name, dflt) : dflt);
895 
896 	/*
897 	** Now look for the desired value
898 	*/
899 	for (conf = sect->conf, p = NULL; conf; conf = conf->next) {
900 		if (strcasecmp(conf->name, name) == 0) {
901 			p = conf->data;
902 			break;
903 		}
904 	}
905 	if (conf == NULL)
906 		return (snam ? config_uid(NULL, name, dflt) : dflt);
907 
908 	/*
909 	** Evaluate the found string
910 	*/
911 	if (*p == '-' || (*p >= '0' && *p <= '9'))
912 		uid = (uid_t) atoi(p);
913 	else {
914 		uid = dflt;
915 		setpwent();
916 		while ((pwd = getpwent()) != NULL) {
917 			if (strcasecmp(pwd->pw_name, p) == 0) {
918 				uid = pwd->pw_uid;
919 				break;
920 			}
921 		}
922 		endpwent();
923 	}
924 
925 	/*
926 	** Return the value found
927 	*/
928 #if defined(COMPILE_DEBUG)
929 	debug(3, "config_uid: result=%d", (int) uid);
930 #endif
931 	return uid;
932 }
933 
934 
935 /* ------------------------------------------------------------ **
936 **
937 **	Function......:	config_gid
938 **
939 **	Parameters....:	snam		Section (NULL=global)
940 **			name		Config option name
941 **			dflt		Default value
942 **
943 **	Return........:	Group-ID value for config option
944 **
945 **	Purpose.......: Retrieve a Group-ID config value.
946 **
947 ** ------------------------------------------------------------ */
948 
config_gid(char * snam,char * name,gid_t dflt)949 gid_t config_gid(char *snam, char *name, gid_t dflt)
950 {
951 	SECTION *sect;
952 	CONFIG *conf;
953 	char *p;
954 	struct group *grp;
955 	gid_t gid;
956 
957 	if (name == NULL)		/* Basic sanity check	*/
958 		misc_die(FL, "config_gid: ?name?");
959 
960 #if defined(COMPILE_DEBUG)
961 	debug(3, "config_gid: s='%.*s' n='%.*s' d=%d",
962 				MAX_CONF_NAME, NIL(snam),
963 				MAX_CONF_NAME, name,
964 				(int) dflt);
965 #endif
966 
967 	/*
968 	** Find the relevant section
969 	*/
970 	sect = config_sect_find(snam);
971 	if (sect == NULL)
972 		return (snam ? config_gid(NULL, name, dflt) : dflt);
973 
974 	/*
975 	** Now look for the desired value
976 	*/
977 	for (conf = sect->conf, p = NULL; conf; conf = conf->next) {
978 		if (strcasecmp(conf->name, name) == 0) {
979 			p = conf->data;
980 			break;
981 		}
982 	}
983 	if (conf == NULL)
984 		return (snam ? config_gid(NULL, name, dflt) : dflt);
985 
986 	/*
987 	** Evaluate the found string
988 	*/
989 	if (*p == '-' || (*p >= '0' && *p <= '9'))
990 		gid = (gid_t) atoi(p);
991 	else {
992 		gid = dflt;
993 		setgrent();
994 		while ((grp = getgrent()) != NULL) {
995 			if (strcasecmp(grp->gr_name, p) == 0) {
996 				gid = grp->gr_gid;
997 				break;
998 			}
999 		}
1000 		endgrent();
1001 	}
1002 
1003 	/*
1004 	** Return the value found
1005 	*/
1006 #if defined(COMPILE_DEBUG)
1007 	debug(3, "config_gid: result=%d", (int) gid);
1008 #endif
1009 	return gid;
1010 }
1011 
1012 
1013 /* ------------------------------------------------------------
1014  * $Log: com-config.c,v $
1015  * Revision 1.7  2002/05/02 12:57:10  mt
1016  * merged with v1.8.2.2
1017  *
1018  * Revision 1.6.2.2  2002/04/04 10:00:07  mt
1019  * fixed bug done while last changes
1020  *
1021  * Revision 1.6.2.1  2002/01/28 01:55:58  mt
1022  * implemented wildcard-section support
1023  *
1024  * Revision 1.6  2002/01/14 18:12:20  mt
1025  * implemented config_dump function to dump in-memory config to a FILE stream
1026  *
1027  * Revision 1.5  1999/09/23 18:34:44  wiegand
1028  * remove white space at line start (incl. continuation lines)
1029  *
1030  * Revision 1.4  1999/09/21 05:42:28  wiegand
1031  * syslog / abort review
1032  *
1033  * Revision 1.3  1999/09/17 06:32:28  wiegand
1034  * buffer length and overflow protection review
1035  *
1036  * Revision 1.2  1999/09/16 14:26:33  wiegand
1037  * minor code review and cleanup
1038  *
1039  * Revision 1.1  1999/09/15 14:05:38  wiegand
1040  * initial checkin
1041  *
1042  * ------------------------------------------------------------ */
1043 
1044