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