LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/base - config_file.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 284 546 52.0 %
Date: 2024-05-31 13:13:24 Functions: 24 43 55.8 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  *
      12             :  * 1. Redistributions of source code must retain the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer.
      14             :  *
      15             :  * 2. Redistributions in binary form must reproduce the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer in the
      17             :  *    documentation and/or other materials provided with the distribution.
      18             :  *
      19             :  * 3. Neither the name of the Institute nor the names of its contributors
      20             :  *    may be used to endorse or promote products derived from this software
      21             :  *    without specific prior written permission.
      22             :  *
      23             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      24             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      25             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      26             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      27             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      28             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      29             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      30             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      31             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      32             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      33             :  * SUCH DAMAGE.
      34             :  */
      35             : 
      36             : #include "baselocl.h"
      37             : #include <assert.h>
      38             : #include <ctype.h>
      39             : #include <parse_time.h>
      40             : 
      41             : #if defined(HAVE_FRAMEWORK_COREFOUNDATION)
      42             : #include <CoreFoundation/CoreFoundation.h>
      43             : #endif
      44             : 
      45             : /* Gaah! I want a portable funopen */
      46             : struct fileptr {
      47             :     heim_context context;
      48             :     const char *s;
      49             :     FILE *f;
      50             : };
      51             : 
      52             : static char *
      53    75509496 : config_fgets(char *str, size_t len, struct fileptr *ptr)
      54             : {
      55             :     /* XXX this is not correct, in that they don't do the same if the
      56             :        line is longer than len */
      57    75509496 :     if(ptr->f != NULL)
      58    77369444 :         return fgets(str, len, ptr->f);
      59             :     else {
      60             :         /* this is almost strsep_copy */
      61           0 :         const char *p;
      62           0 :         ssize_t l;
      63           0 :         if(*ptr->s == '\0')
      64           0 :             return NULL;
      65           0 :         p = ptr->s + strcspn(ptr->s, "\n");
      66           0 :         if(*p == '\n')
      67           0 :             p++;
      68           0 :         l = min(len, (size_t)(p - ptr->s));
      69           0 :         if(len > 0) {
      70           0 :             memcpy(str, ptr->s, l);
      71           0 :             str[l] = '\0';
      72             :         }
      73           0 :         ptr->s = p;
      74           0 :         return str;
      75             :     }
      76             : }
      77             : 
      78             : static heim_error_code parse_section(char *p, heim_config_section **s,
      79             :                                      heim_config_section **res,
      80             :                                      const char **err_message);
      81             : static heim_error_code parse_binding(struct fileptr *f, unsigned *lineno, char *p,
      82             :                                      heim_config_binding **b,
      83             :                                      heim_config_binding **parent,
      84             :                                      const char **err_message);
      85             : static heim_error_code parse_list(struct fileptr *f, unsigned *lineno,
      86             :                                   heim_config_binding **parent,
      87             :                                   const char **err_message);
      88             : 
      89             : heim_config_section *
      90    48810885 : heim_config_get_entry(heim_config_section **parent, const char *name, int type)
      91             : {
      92     1186556 :     heim_config_section **q;
      93             : 
      94   144369790 :     for (q = parent; *q != NULL; q = &(*q)->next)
      95    95560481 :         if (type == heim_config_list &&
      96    18389312 :             (unsigned)type == (*q)->type &&
      97    18389312 :             strcmp(name, (*q)->name) == 0)
      98        1576 :             return *q;
      99    48809309 :     *q = calloc(1, sizeof(**q));
     100    48809309 :     if (*q == NULL)
     101           0 :         return NULL;
     102    48809309 :     (*q)->name = strdup(name);
     103    48809309 :     (*q)->type = type;
     104    48809309 :     if ((*q)->name == NULL) {
     105           0 :         free(*q);
     106           0 :         *q = NULL;
     107           0 :         return NULL;
     108             :     }
     109    47622753 :     return *q;
     110             : }
     111             : 
     112             : /*
     113             :  * Parse a section:
     114             :  *
     115             :  * [section]
     116             :  *      foo = bar
     117             :  *      b = {
     118             :  *              a
     119             :  *          }
     120             :  * ...
     121             :  *
     122             :  * starting at the line in `p', storing the resulting structure in
     123             :  * `s' and hooking it into `parent'.
     124             :  * Store the error message in `err_message'.
     125             :  */
     126             : 
     127             : static heim_error_code
     128     4864032 : parse_section(char *p, heim_config_section **s, heim_config_section **parent,
     129             :               const char **err_message)
     130             : {
     131      128228 :     char *p1;
     132      128228 :     heim_config_section *tmp;
     133             : 
     134     4864032 :     p1 = strchr (p + 1, ']');
     135     4864032 :     if (p1 == NULL) {
     136           0 :         *err_message = "missing ]";
     137           0 :         return HEIM_ERR_CONFIG_BADFORMAT;
     138             :     }
     139     4864032 :     *p1 = '\0';
     140     4864032 :     tmp = heim_config_get_entry(parent, p + 1, heim_config_list);
     141     4864032 :     if(tmp == NULL) {
     142           0 :         *err_message = "out of memory";
     143           0 :         return HEIM_ERR_CONFIG_BADFORMAT;
     144             :     }
     145     4864032 :     *s = tmp;
     146     4864032 :     return 0;
     147             : }
     148             : 
     149             : /*
     150             :  * Parse a brace-enclosed list from `f', hooking in the structure at
     151             :  * `parent'.
     152             :  * Store the error message in `err_message'.
     153             :  */
     154             : 
     155             : static heim_error_code
     156     5582604 : parse_list(struct fileptr *f, unsigned *lineno, heim_config_binding **parent,
     157             :            const char **err_message)
     158             : {
     159      128312 :     char buf[2048];
     160      128312 :     heim_error_code ret;
     161     5582604 :     heim_config_binding *b = NULL;
     162     5582604 :     unsigned beg_lineno = *lineno;
     163             : 
     164    27902660 :     while(config_fgets(buf, sizeof(buf), f) != NULL) {
     165      641488 :         char *p;
     166             : 
     167    27902660 :         ++*lineno;
     168    27902660 :         buf[strcspn(buf, "\r\n")] = '\0';
     169    27902660 :         p = buf;
     170    78141336 :         while(isspace((unsigned char)*p))
     171    50238676 :             ++p;
     172    27902660 :         if (*p == '#' || *p == ';' || *p == '\0')
     173           0 :             continue;
     174    27902660 :         while(isspace((unsigned char)*p))
     175           0 :             ++p;
     176    27902660 :         if (*p == '}')
     177     5454292 :             return 0;
     178    22320056 :         if (*p == '\0')
     179           0 :             continue;
     180    22320056 :         ret = parse_binding (f, lineno, p, &b, parent, err_message);
     181    22320056 :         if (ret)
     182           0 :             return ret;
     183             :     }
     184           0 :     *lineno = beg_lineno;
     185           0 :     *err_message = "unclosed {";
     186           0 :     return HEIM_ERR_CONFIG_BADFORMAT;
     187             : }
     188             : 
     189             : /*
     190             :  *
     191             :  */
     192             : 
     193             : static heim_error_code
     194    43946853 : parse_binding(struct fileptr *f, unsigned *lineno, char *p,
     195             :               heim_config_binding **b, heim_config_binding **parent,
     196             :               const char **err_message)
     197             : {
     198     1058328 :     heim_config_binding *tmp;
     199     1058328 :     char *p1, *p2;
     200    43946853 :     heim_error_code ret = 0;
     201             : 
     202    43946853 :     p1 = p;
     203   703653668 :     while (*p && *p != '=' && !isspace((unsigned char)*p))
     204   659706815 :         ++p;
     205    43946853 :     if (*p == '\0') {
     206           0 :         *err_message = "missing =";
     207           0 :         return HEIM_ERR_CONFIG_BADFORMAT;
     208             :     }
     209    42888525 :     p2 = p;
     210    87893706 :     while (isspace((unsigned char)*p))
     211    43946853 :         ++p;
     212    43946853 :     if (*p != '=') {
     213           0 :         *err_message = "missing =";
     214           0 :         return HEIM_ERR_CONFIG_BADFORMAT;
     215             :     }
     216    43946853 :     ++p;
     217    87893706 :     while(isspace((unsigned char)*p))
     218    43946853 :         ++p;
     219    43946853 :     *p2 = '\0';
     220    43946853 :     if (*p == '{') {
     221     5582604 :         tmp = heim_config_get_entry(parent, p1, heim_config_list);
     222     5582604 :         if (tmp == NULL) {
     223           0 :             *err_message = "out of memory";
     224           0 :             return HEIM_ERR_CONFIG_BADFORMAT;
     225             :         }
     226     5582604 :         ret = parse_list (f, lineno, &tmp->u.list, err_message);
     227             :     } else {
     228    38364249 :         tmp = heim_config_get_entry(parent, p1, heim_config_string);
     229    38364249 :         if (tmp == NULL) {
     230           0 :             *err_message = "out of memory";
     231           0 :             return HEIM_ERR_CONFIG_BADFORMAT;
     232             :         }
     233    38364249 :         p1 = p;
     234    38364249 :         p = p1 + strlen(p1);
     235    38364249 :         while(p > p1 && isspace((unsigned char)*(p-1)))
     236           0 :             --p;
     237    38364249 :         *p = '\0';
     238    38364249 :         tmp->u.string = strdup(p1);
     239             :     }
     240    43946853 :     *b = tmp;
     241    43946853 :     return ret;
     242             : }
     243             : 
     244             : #if defined(HAVE_FRAMEWORK_COREFOUNDATION)
     245             : 
     246             : #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
     247             : #define HAVE_CFPROPERTYLISTCREATEWITHSTREAM 1
     248             : #endif
     249             : 
     250             : static char *
     251             : cfstring2cstring(CFStringRef string)
     252             : {
     253             :     CFIndex len;
     254             :     char *str;
     255             : 
     256             :     str = (char *) CFStringGetCStringPtr(string, kCFStringEncodingUTF8);
     257             :     if (str)
     258             :         return strdup(str);
     259             : 
     260             :     len = CFStringGetLength(string);
     261             :     len = 1 + CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8);
     262             :     str = malloc(len);
     263             :     if (str == NULL)
     264             :         return NULL;
     265             : 
     266             :     if (!CFStringGetCString (string, str, len, kCFStringEncodingUTF8)) {
     267             :         free (str);
     268             :         return NULL;
     269             :     }
     270             :     return str;
     271             : }
     272             : 
     273             : static void
     274             : convert_content(const void *key, const void *value, void *context)
     275             : {
     276             :     heim_config_section *tmp, **parent = context;
     277             :     char *k;
     278             : 
     279             :     if (CFGetTypeID(key) != CFStringGetTypeID())
     280             :         return;
     281             : 
     282             :     k = cfstring2cstring(key);
     283             :     if (k == NULL)
     284             :         return;
     285             : 
     286             :     if (CFGetTypeID(value) == CFStringGetTypeID()) {
     287             :         tmp = heim_config_get_entry(parent, k, heim_config_string);
     288             :         tmp->u.string = cfstring2cstring(value);
     289             :     } else if (CFGetTypeID(value) == CFDictionaryGetTypeID()) {
     290             :         tmp = heim_config_get_entry(parent, k, heim_config_list);
     291             :         CFDictionaryApplyFunction(value, convert_content, &tmp->u.list);
     292             :     } else {
     293             :         /* log */
     294             :     }
     295             :     free(k);
     296             : }
     297             : 
     298             : static heim_error_code
     299             : parse_plist_config(heim_context context, const char *path, heim_config_section **parent)
     300             : {
     301             :     CFReadStreamRef s;
     302             :     CFDictionaryRef d;
     303             :     CFURLRef url;
     304             : 
     305             :     url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8 *)path, strlen(path), 0);
     306             :     if (url == NULL) {
     307             :         heim_clear_error_message(context);
     308             :         return ENOMEM;
     309             :     }
     310             : 
     311             :     s = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
     312             :     CFRelease(url);
     313             :     if (s == NULL) {
     314             :         heim_clear_error_message(context);
     315             :         return ENOMEM;
     316             :     }
     317             : 
     318             :     if (!CFReadStreamOpen(s)) {
     319             :         CFRelease(s);
     320             :         heim_clear_error_message(context);
     321             :         return ENOENT;
     322             :     }
     323             : 
     324             : #ifdef HAVE_CFPROPERTYLISTCREATEWITHSTREAM
     325             :     d = (CFDictionaryRef)CFPropertyListCreateWithStream(NULL, s, 0, kCFPropertyListImmutable, NULL, NULL);
     326             : #else
     327             :     d = (CFDictionaryRef)CFPropertyListCreateFromStream(NULL, s, 0, kCFPropertyListImmutable, NULL, NULL);
     328             : #endif
     329             :     CFRelease(s);
     330             :     if (d == NULL) {
     331             :         heim_clear_error_message(context);
     332             :         return ENOENT;
     333             :     }
     334             : 
     335             :     CFDictionaryApplyFunction(d, convert_content, parent);
     336             :     CFRelease(d);
     337             : 
     338             :     return 0;
     339             : }
     340             : 
     341             : #endif
     342             : 
     343             : static int
     344           0 : is_absolute_path(const char *path)
     345             : {
     346             :     /*
     347             :      * An absolute path is one that refers to an explicit object
     348             :      * without ambiguity.
     349             :      */
     350             : #ifdef WIN32
     351             :     size_t len = strlen(path);
     352             : 
     353             :     /* UNC path is by definition absolute */
     354             :     if (len > 2
     355             :          && ISPATHSEP(path[0])
     356             :          && ISPATHSEP(path[1]))
     357             :         return 1;
     358             : 
     359             :     /* A drive letter path might be absolute */
     360             :     if (len > 3
     361             :          && isalpha((unsigned char)path[0])
     362             :          && path[1] == ':'
     363             :          && ISPATHSEP(path[2]))
     364             :         return 1;
     365             : 
     366             :     /*
     367             :      * if no drive letter but first char is a path
     368             :      * separator then the drive letter must be obtained
     369             :      * from the including file.
     370             :      */
     371             : #else
     372             :     /* UNIX is easy, first char '/' is absolute */
     373           0 :     if (ISPATHSEP(path[0]))
     374           0 :         return 1;
     375             : #endif
     376           0 :     return 0;
     377             : }
     378             : 
     379             : /*
     380             :  * Parse the config file `fname', generating the structures into `res'
     381             :  * returning error messages in `err_message'
     382             :  */
     383             : 
     384             : static heim_error_code
     385     1224516 : heim_config_parse_debug(struct fileptr *f,
     386             :                         heim_config_section **res,
     387             :                         unsigned *lineno,
     388             :                         const char **err_message)
     389             : {
     390     1224516 :     heim_config_section *s = NULL;
     391     1224516 :     heim_config_binding *b = NULL;
     392       32060 :     char buf[2048];
     393       32060 :     heim_error_code ret;
     394             : 
     395     1224516 :     *lineno = 0;
     396     1224516 :     *err_message = "";
     397             : 
     398    47606836 :     while (config_fgets(buf, sizeof(buf), f) != NULL) {
     399     1186400 :         char *p;
     400             : 
     401    46382320 :         ++*lineno;
     402    46382320 :         buf[strcspn(buf, "\r\n")] = '\0';
     403    46382320 :         p = buf;
     404    71851320 :         while(isspace((unsigned char)*p))
     405    25469000 :             ++p;
     406    46382320 :         if (*p == '#' || *p == ';')
     407     3668508 :             continue;
     408    42713812 :         if (*p == '[') {
     409     4864032 :             ret = parse_section(p, &s, res, err_message);
     410     4864032 :             if (ret)
     411           0 :                 return ret;
     412     4864032 :             b = NULL;
     413    37849780 :         } else if (*p == '}') {
     414           0 :             *err_message = "unmatched }";
     415           0 :             return 2048;
     416    37849780 :         } else if (strncmp(p, "include", sizeof("include") - 1) == 0 &&
     417           0 :             isspace((unsigned char)p[sizeof("include") - 1])) {
     418           0 :             p += sizeof("include");
     419           0 :             while (isspace((unsigned char)*p))
     420           0 :                 p++;
     421           0 :             if (!is_absolute_path(p)) {
     422           0 :                 heim_set_error_message(f->context, HEIM_ERR_CONFIG_BADFORMAT,
     423             :                                        "Configuration include path must be "
     424             :                                        "absolute");
     425           0 :                 return HEIM_ERR_CONFIG_BADFORMAT;
     426             :             }
     427           0 :             ret = heim_config_parse_file_multi(f->context, p, res);
     428           0 :             if (ret)
     429           0 :                 return ret;
     430    37849780 :         } else if (strncmp(p, "includedir", sizeof("includedir") - 1) == 0 &&
     431           0 :             isspace((unsigned char)p[sizeof("includedir") - 1])) {
     432           0 :             p += sizeof("includedir");
     433           0 :             while (isspace((unsigned char)*p))
     434           0 :                 p++;
     435           0 :             if (!is_absolute_path(p)) {
     436           0 :                 heim_set_error_message(f->context, HEIM_ERR_CONFIG_BADFORMAT,
     437             :                                        "Configuration includedir path must be "
     438             :                                        "absolute");
     439           0 :                 return HEIM_ERR_CONFIG_BADFORMAT;
     440             :             }
     441           0 :             ret = heim_config_parse_dir_multi(f->context, p, res);
     442           0 :             if (ret)
     443           0 :                 return ret;
     444    37849780 :         } else if(*p != '\0') {
     445    21626797 :             if (s == NULL) {
     446           0 :                 *err_message = "binding before section";
     447           0 :                 return 2048;
     448             :             }
     449    21626797 :             ret = parse_binding(f, lineno, p, &b, &s->u.list, err_message);
     450    21626797 :             if (ret)
     451           0 :                 return ret;
     452             :         }
     453             :     }
     454     1192456 :     return 0;
     455             : }
     456             : 
     457             : static int
     458     2899272 : is_plist_file(const char *fname)
     459             : {
     460     2899272 :     size_t len = strlen(fname);
     461     2899272 :     char suffix[] = ".plist";
     462     2899272 :     if (len < sizeof(suffix))
     463           0 :         return 0;
     464     2899272 :     if (strcasecmp(&fname[len - (sizeof(suffix) - 1)], suffix) != 0)
     465     2899272 :         return 0;
     466           0 :     return 1;
     467             : }
     468             : 
     469             : /**
     470             :  * Parse configuration files in the given directory and add the result
     471             :  * into res.  Only files whose names consist only of alphanumeric
     472             :  * characters, hyphen, and underscore, will be parsed, though files
     473             :  * ending in ".conf" will also be parsed.
     474             :  *
     475             :  * This interface can be used to parse several configuration directories
     476             :  * into one resulting heim_config_section by calling it repeatably.
     477             :  *
     478             :  * @param context a Kerberos 5 context.
     479             :  * @param dname a directory name to a Kerberos configuration file
     480             :  * @param res the returned result, must be free with heim_free_config_files().
     481             :  * @return Return an error code or 0, see heim_get_error_message().
     482             :  *
     483             :  * @ingroup heim_support
     484             :  */
     485             : 
     486             : heim_error_code
     487           0 : heim_config_parse_dir_multi(heim_context context,
     488             :                             const char *dname,
     489             :                             heim_config_section **res)
     490             : {
     491           0 :     struct dirent *entry;
     492           0 :     heim_error_code ret;
     493           0 :     DIR *d;
     494             : 
     495           0 :     if ((d = opendir(dname)) == NULL)
     496           0 :         return errno;
     497             : 
     498           0 :     while ((entry = readdir(d)) != NULL) {
     499           0 :         char *p = entry->d_name;
     500           0 :         char *path;
     501           0 :         int is_valid = 1;
     502             : 
     503           0 :         while (*p) {
     504             :             /*
     505             :              * Here be dragons.  The call to heim_config_parse_file_multi()
     506             :              * below expands path tokens.  Because of the limitations here
     507             :              * on file naming, we can't have path tokens in the file name,
     508             :              * so we're safe.  Anyone changing this if condition here should
     509             :              * be aware.
     510             :              */
     511           0 :             if (!isalnum((unsigned char)*p) && *p != '_' && *p != '-' &&
     512           0 :                 strcmp(p, ".conf") != 0) {
     513           0 :                 is_valid = 0;
     514           0 :                 break;
     515             :             }
     516           0 :             p++;
     517             :         }
     518           0 :         if (!is_valid)
     519           0 :             continue;
     520             : 
     521           0 :         if (asprintf(&path, "%s/%s", dname, entry->d_name) == -1 ||
     522           0 :             path == NULL) {
     523           0 :             (void) closedir(d);
     524           0 :             return heim_enomem(context);
     525             :         }
     526           0 :         ret = heim_config_parse_file_multi(context, path, res);
     527           0 :         free(path);
     528           0 :         if (ret == ENOMEM) {
     529           0 :             (void) closedir(d);
     530           0 :             return ENOMEM;
     531             :         }
     532             :         /* Ignore malformed config files so we don't lock out admins, etc... */
     533             :     }
     534           0 :     (void) closedir(d);
     535           0 :     return 0;
     536             : }
     537             : 
     538             : static int
     539           0 : is_devnull(struct stat *st)
     540             : {
     541             : #ifdef WIN32
     542             :     return 0;
     543             : #else
     544           0 :     struct stat devnullst;
     545             : 
     546           0 :     if (stat("/dev/null", &devnullst) == -1)
     547           0 :         return 0;
     548           0 :     return st->st_dev == devnullst.st_dev && st->st_ino == devnullst.st_ino;
     549             : #endif
     550             : }
     551             : 
     552             : HEIMDAL_THREAD_LOCAL int config_include_depth = 0;
     553             : 
     554             : /**
     555             :  * Parse a configuration file and add the result into res. This
     556             :  * interface can be used to parse several configuration files into one
     557             :  * resulting heim_config_section by calling it repeatably.
     558             :  *
     559             :  * @param context a Kerberos 5 context.
     560             :  * @param fname a file name to a Kerberos configuration file
     561             :  * @param res the returned result, must be free with heim_free_config_files().
     562             :  * @return Return an error code or 0, see heim_get_error_message().
     563             :  *
     564             :  * @ingroup heim_support
     565             :  */
     566             : 
     567             : heim_error_code
     568     2899272 : heim_config_parse_file_multi(heim_context context,
     569             :                              const char *fname,
     570             :                              heim_config_section **res)
     571             : {
     572       74106 :     const char *str;
     573     2899272 :     char *newfname = NULL;
     574     2899272 :     unsigned lineno = 0;
     575     2899272 :     heim_error_code ret = 0;
     576       74106 :     struct fileptr f;
     577       74106 :     struct stat st;
     578             : 
     579     2899272 :     if (config_include_depth > 5) {
     580           0 :         heim_warnx(context, "Maximum config file include depth reached; "
     581             :                    "not including %s", fname);
     582           0 :         return 0;
     583             :     }
     584     2899272 :     config_include_depth++;
     585             : 
     586             :     /**
     587             :      * If the fname starts with "~/" parse configuration file in the
     588             :      * current users home directory. The behavior can be disabled and
     589             :      * enabled by calling heim_set_home_dir_access().
     590             :      */
     591     2899272 :     if (ISTILDE(fname[0]) && ISPATHSEP(fname[1])) {
     592      759725 :         if (!heim_context_get_homedir_access(context)) {
     593           0 :             heim_set_error_message(context, EPERM,
     594             :                                    "Access to home directory not allowed");
     595           0 :             ret = EPERM;
     596           0 :             goto out;
     597             :         }
     598      759725 :         if (asprintf(&newfname, "%%{USERCONFIG}%s", &fname[1]) < 0 ||
     599      759725 :             newfname == NULL) {
     600           0 :             ret = heim_enomem(context);
     601           0 :             goto out;
     602             :         }
     603      739992 :         fname = newfname;
     604             :     }
     605             : 
     606     2899272 :     if (is_plist_file(fname)) {
     607             : #if defined(HAVE_FRAMEWORK_COREFOUNDATION)
     608             :         ret = parse_plist_config(context, fname, res);
     609             :         if (ret) {
     610             :             heim_set_error_message(context, ret,
     611             :                                    "Failed to parse plist %s", fname);
     612             :             goto out;
     613             :         }
     614             : #else
     615           0 :         heim_set_error_message(context, ENOENT,
     616             :                                "no support for plist configuration files");
     617           0 :         ret = ENOENT;
     618           0 :         goto out;
     619             : #endif
     620             :     } else {
     621     2899272 :         char *exp_fname = NULL;
     622             : 
     623             :         /*
     624             :          * Note that heim_config_parse_dir_multi() doesn't want tokens
     625             :          * expanded here, but it happens to limit the names of files to
     626             :          * include such that there can be no tokens to expand.  Don't
     627             :          * add token expansion for tokens using _, say.
     628             :          */
     629     2899272 :         ret = heim_expand_path_tokens(context, fname, 1, &exp_fname, NULL);
     630     2899272 :         if (ret)
     631     1674756 :             goto out;
     632     2899272 :         free(newfname);
     633     2899272 :         fname = newfname = exp_fname;
     634             : 
     635     2899272 :         f.context = context;
     636     2899272 :         f.f = fopen(fname, "r");
     637     2899272 :         f.s = NULL;
     638     2899272 :         if (f.f == NULL || fstat(fileno(f.f), &st) == -1) {
     639     1674756 :             if (f.f != NULL)
     640           0 :                 (void) fclose(f.f);
     641     1674756 :             ret = errno;
     642     1674756 :             heim_set_error_message(context, ret, "open or stat %s: %s",
     643             :                                    fname, strerror(ret));
     644     1674756 :             goto out;
     645             :         }
     646             : 
     647     1224516 :         if (!S_ISREG(st.st_mode) && !is_devnull(&st)) {
     648           0 :             (void) fclose(f.f);
     649           0 :             heim_set_error_message(context, EISDIR, "not a regular file %s: %s",
     650             :                                    fname, strerror(EISDIR));
     651           0 :             ret = EISDIR;
     652           0 :             goto out;
     653             :         }
     654             : 
     655     1224516 :         ret = heim_config_parse_debug(&f, res, &lineno, &str);
     656     1224516 :         fclose(f.f);
     657     1224516 :         if (ret) {
     658           0 :             if (ret != HEIM_ERR_CONFIG_BADFORMAT)
     659           0 :                 ret = HEIM_ERR_CONFIG_BADFORMAT;
     660           0 :             heim_set_error_message(context, ret, "%s:%u: %s",
     661             :                                    fname, lineno, str);
     662           0 :             goto out;
     663             :         }
     664             :     }
     665             : 
     666     2899272 :   out:
     667     2899272 :     config_include_depth--;
     668     2899272 :     if (ret == HEIM_ERR_CONFIG_BADFORMAT || (ret && config_include_depth > 0)) {
     669           0 :         heim_warn(context, ret, "Ignoring");
     670           0 :         if (config_include_depth > 0)
     671           0 :             ret = 0;
     672             :     }
     673     2899272 :     free(newfname);
     674     2899272 :     return ret;
     675             : }
     676             : 
     677             : heim_error_code
     678           0 : heim_config_parse_file(heim_context context,
     679             :                        const char *fname,
     680             :                        heim_config_section **res)
     681             : {
     682           0 :     *res = NULL;
     683           0 :     return heim_config_parse_file_multi(context, fname, res);
     684             : }
     685             : 
     686             : static void
     687    12939117 : free_binding(heim_context context, heim_config_binding *b)
     688             : {
     689      312749 :     heim_config_binding *next_b;
     690             : 
     691    60484362 :     while (b) {
     692    47545245 :         free (b->name);
     693    47545245 :         assert(b->type == heim_config_string || b->type == heim_config_list);
     694    47545245 :         if (b->type == heim_config_string)
     695    37368041 :             free (b->u.string);
     696             :         else
     697    10177204 :             free_binding (context, b->u.list);
     698    47545245 :         next_b = b->next;
     699    47545245 :         free (b);
     700    47545245 :         b = next_b;
     701             :     }
     702    12939117 : }
     703             : 
     704             : /**
     705             :  * Free configuration file section, the result of
     706             :  * heim_config_parse_file() and heim_config_parse_file_multi().
     707             :  *
     708             :  * @param context A Kerberos 5 context
     709             :  * @param s the configuration section to free
     710             :  *
     711             :  * @return returns 0 on successes, otherwise an error code, see
     712             :  *          heim_get_error_message()
     713             :  *
     714             :  * @ingroup heim_support
     715             :  */
     716             : 
     717             : heim_error_code
     718     2761913 : heim_config_file_free(heim_context context, heim_config_section *s)
     719             : {
     720     2761913 :     free_binding (context, s);
     721     2761913 :     return 0;
     722             : }
     723             : 
     724             : #ifndef HEIMDAL_SMALLER
     725             : 
     726             : heim_error_code
     727           0 : heim_config_copy(heim_context context,
     728             :                  heim_config_section *c,
     729             :                  heim_config_section **head)
     730             : {
     731           0 :     heim_config_binding *d, *previous = NULL;
     732             : 
     733           0 :     *head = NULL;
     734             : 
     735           0 :     while (c) {
     736           0 :         d = calloc(1, sizeof(*d));
     737             : 
     738           0 :         if (*head == NULL)
     739           0 :             *head = d;
     740             : 
     741           0 :         d->name = strdup(c->name);
     742           0 :         d->type = c->type;
     743           0 :         assert(d->type == heim_config_string || d->type == heim_config_list);
     744           0 :         if (d->type == heim_config_string)
     745           0 :             d->u.string = strdup(c->u.string);
     746             :         else
     747           0 :             heim_config_copy (context, c->u.list, &d->u.list);
     748           0 :         if (previous)
     749           0 :             previous->next = d;
     750             : 
     751           0 :         previous = d;
     752           0 :         c = c->next;
     753             :     }
     754           0 :     return 0;
     755             : }
     756             : 
     757             : #endif /* HEIMDAL_SMALLER */
     758             : 
     759             : const void *
     760           0 : heim_config_get_next(heim_context context,
     761             :                      const heim_config_section *c,
     762             :                      const heim_config_binding **pointer,
     763             :                      int type,
     764             :                      ...)
     765             : {
     766           0 :     const char *ret;
     767           0 :     va_list args;
     768             : 
     769           0 :     va_start(args, type);
     770           0 :     ret = heim_config_vget_next(context, c, pointer, type, args);
     771           0 :     va_end(args);
     772           0 :     return ret;
     773             : }
     774             : 
     775             : static const void *
     776    78729944 : vget_next(heim_context context,
     777             :           const heim_config_binding *b,
     778             :           const heim_config_binding **pointer,
     779             :           int type,
     780             :           const char *name,
     781             :           va_list args)
     782             : {
     783    79770885 :     const char *p = va_arg(args, const char *);
     784             : 
     785   390583540 :     while (b != NULL) {
     786   352757807 :         if (strcmp(b->name, name) == 0) {
     787    41980621 :             if (b->type == (unsigned)type && p == NULL) {
     788     2748395 :                 *pointer = b;
     789     2748395 :                 return b->u.generic;
     790    39232226 :             } else if (b->type == heim_config_list && p != NULL) {
     791    39196757 :                 return vget_next(context, b->u.list, pointer, type, p, args);
     792             :             }
     793             :         }
     794   310812655 :         b = b->next;
     795             :     }
     796    36821292 :     return NULL;
     797             : }
     798             : 
     799             : const void *
     800    45006931 : heim_config_vget_next(heim_context context,
     801             :                       const heim_config_section *c,
     802             :                       const heim_config_binding **pointer,
     803             :                       int type,
     804             :                       va_list args)
     805             : {
     806     1151152 :     const heim_config_binding *b;
     807     1151152 :     const char *p;
     808             : 
     809    45006931 :     if (c == NULL)
     810     4135396 :         return NULL;
     811             : 
     812    40801350 :     if (*pointer == NULL) {
     813             :         /* first time here, walk down the tree looking for the right
     814             :            section */
     815    40574128 :         p = va_arg(args, const char *);
     816    40574128 :         if (p == NULL)
     817           0 :             return NULL;
     818    40574128 :         return vget_next(context, c, pointer, type, p, args);
     819             :     }
     820             : 
     821             :     /* we were called again, so just look for more entries with the
     822             :        same name and type */
     823      900943 :     for (b = (*pointer)->next; b != NULL; b = b->next) {
     824      674434 :         if(strcmp(b->name, (*pointer)->name) == 0 && b->type == (unsigned)type) {
     825         713 :             *pointer = b;
     826         713 :             return b->u.generic;
     827             :         }
     828             :     }
     829      222011 :     return NULL;
     830             : }
     831             : 
     832             : const void *
     833           0 : heim_config_get(heim_context context,
     834             :                 const heim_config_section *c,
     835             :                 int type,
     836             :                 ...)
     837             : {
     838           0 :     const void *ret;
     839           0 :     va_list args;
     840             : 
     841           0 :     va_start(args, type);
     842           0 :     ret = heim_config_vget(context, c, type, args);
     843           0 :     va_end(args);
     844           0 :     return ret;
     845             : }
     846             : 
     847             : 
     848             : const void *
     849    33896882 : heim_config_vget(heim_context context,
     850             :                  const heim_config_section *c,
     851             :                  int type,
     852             :                  va_list args)
     853             : {
     854    33896882 :     const heim_config_binding *foo = NULL;
     855             : 
     856    33896882 :     return heim_config_vget_next(context, c, &foo, type, args);
     857             : }
     858             : 
     859             : /**
     860             :  * Get a list of configuration binding list for more processing
     861             :  *
     862             :  * @param context A Kerberos 5 context.
     863             :  * @param c a configuration section, or NULL to use the section from context
     864             :  * @param ... a list of names, terminated with NULL.
     865             :  *
     866             :  * @return NULL if configuration list is not found, a list otherwise
     867             :  *
     868             :  * @ingroup heim_support
     869             :  */
     870             : 
     871             : const heim_config_binding *
     872           0 : heim_config_get_list(heim_context context,
     873             :                      const heim_config_section *c,
     874             :                      ...)
     875             : {
     876           0 :     const heim_config_binding *ret;
     877           0 :     va_list args;
     878             : 
     879           0 :     va_start(args, c);
     880           0 :     ret = heim_config_vget_list(context, c, args);
     881           0 :     va_end(args);
     882           0 :     return ret;
     883             : }
     884             : 
     885             : /**
     886             :  * Get a list of configuration binding list for more processing
     887             :  *
     888             :  * @param context A Kerberos 5 context.
     889             :  * @param c a configuration section, or NULL to use the section from context
     890             :  * @param args a va_list of arguments
     891             :  *
     892             :  * @return NULL if configuration list is not found, a list otherwise
     893             :  *
     894             :  * @ingroup heim_support
     895             :  */
     896             : 
     897             : const heim_config_binding *
     898           0 : heim_config_vget_list(heim_context context,
     899             :                       const heim_config_section *c,
     900             :                       va_list args)
     901             : {
     902           0 :     return heim_config_vget(context, c, heim_config_list, args);
     903             : }
     904             : 
     905             : /**
     906             :  * Returns a "const char *" to a string in the configuration database.
     907             :  * The string may not be valid after a reload of the configuration
     908             :  * database so a caller should make a local copy if it needs to keep
     909             :  * the string.
     910             :  *
     911             :  * @param context A Kerberos 5 context.
     912             :  * @param c a configuration section, or NULL to use the section from context
     913             :  * @param ... a list of names, terminated with NULL.
     914             :  *
     915             :  * @return NULL if configuration string not found, a string otherwise
     916             :  *
     917             :  * @ingroup heim_support
     918             :  */
     919             : 
     920             : const char *
     921      759605 : heim_config_get_string(heim_context context,
     922             :                        const heim_config_section *c,
     923             :                        ...)
     924             : {
     925       19721 :     const char *ret;
     926       19721 :     va_list args;
     927             : 
     928      759605 :     va_start(args, c);
     929      759605 :     ret = heim_config_vget_string(context, c, args);
     930      759605 :     va_end(args);
     931      759605 :     return ret;
     932             : }
     933             : 
     934             : /**
     935             :  * Like heim_config_get_string(), but uses a va_list instead of ...
     936             :  *
     937             :  * @param context A Kerberos 5 context.
     938             :  * @param c a configuration section, or NULL to use the section from context
     939             :  * @param args a va_list of arguments
     940             :  *
     941             :  * @return NULL if configuration string not found, a string otherwise
     942             :  *
     943             :  * @ingroup heim_support
     944             :  */
     945             : 
     946             : const char *
     947    33896882 : heim_config_vget_string(heim_context context,
     948             :                         const heim_config_section *c,
     949             :                         va_list args)
     950             : {
     951    33896882 :     return heim_config_vget(context, c, heim_config_string, args);
     952             : }
     953             : 
     954             : /**
     955             :  * Like heim_config_vget_string(), but instead of returning NULL,
     956             :  * instead return a default value.
     957             :  *
     958             :  * @param context A Kerberos 5 context.
     959             :  * @param c a configuration section, or NULL to use the section from context
     960             :  * @param def_value the default value to return if no configuration
     961             :  *        found in the database.
     962             :  * @param args a va_list of arguments
     963             :  *
     964             :  * @return a configuration string
     965             :  *
     966             :  * @ingroup heim_support
     967             :  */
     968             : 
     969             : const char *
     970     6613310 : heim_config_vget_string_default(heim_context context,
     971             :                                 const heim_config_section *c,
     972             :                                 const char *def_value,
     973             :                                 va_list args)
     974             : {
     975      168615 :     const char *ret;
     976             : 
     977     6613310 :     ret = heim_config_vget_string(context, c, args);
     978     6613310 :     if (ret == NULL)
     979     6601194 :         ret = def_value;
     980     6613310 :     return ret;
     981             : }
     982             : 
     983             : /**
     984             :  * Like heim_config_get_string(), but instead of returning NULL,
     985             :  * instead return a default value.
     986             :  *
     987             :  * @param context A Kerberos 5 context.
     988             :  * @param c a configuration section, or NULL to use the section from context
     989             :  * @param def_value the default value to return if no configuration
     990             :  *        found in the database.
     991             :  * @param ... a list of names, terminated with NULL.
     992             :  *
     993             :  * @return a configuration string
     994             :  *
     995             :  * @ingroup heim_support
     996             :  */
     997             : 
     998             : const char *
     999           0 : heim_config_get_string_default(heim_context context,
    1000             :                                const heim_config_section *c,
    1001             :                                const char *def_value,
    1002             :                                ...)
    1003             : {
    1004           0 :     const char *ret;
    1005           0 :     va_list args;
    1006             : 
    1007           0 :     va_start(args, def_value);
    1008           0 :     ret = heim_config_vget_string_default (context, c, def_value, args);
    1009           0 :     va_end(args);
    1010           0 :     return ret;
    1011             : }
    1012             : 
    1013             : static char *
    1014      720458 : next_component_string(char * begin, const char * delims, char **state)
    1015             : {
    1016        8996 :     char * end;
    1017             : 
    1018      720458 :     if (begin == NULL)
    1019      493236 :         begin = *state;
    1020             : 
    1021      720458 :     if (*begin == '\0')
    1022      222724 :         return NULL;
    1023             : 
    1024      488738 :     end = begin;
    1025      493236 :     while (*end == '"') {
    1026           0 :         char * t = strchr(end + 1, '"');
    1027             : 
    1028           0 :         if (t)
    1029           0 :             end = ++t;
    1030             :         else
    1031           0 :             end += strlen(end);
    1032             :     }
    1033             : 
    1034      493236 :     if (*end != '\0') {
    1035        4498 :         size_t pos;
    1036             : 
    1037      493236 :         pos = strcspn(end, delims);
    1038      493236 :         end = end + pos;
    1039             :     }
    1040             : 
    1041      493236 :     if (*end != '\0') {
    1042      266014 :         *end = '\0';
    1043      266014 :         *state = end + 1;
    1044      266014 :         if (*begin == '"' && *(end - 1) == '"' && begin + 1 < end) {
    1045           0 :             begin++; *(end - 1) = '\0';
    1046             :         }
    1047      266014 :         return begin;
    1048             :     }
    1049             : 
    1050      227222 :     *state = end;
    1051      227222 :     if (*begin == '"' && *(end - 1) == '"' && begin + 1 < end) {
    1052           0 :         begin++; *(end - 1) = '\0';
    1053             :     }
    1054      222724 :     return begin;
    1055             : }
    1056             : 
    1057             : /**
    1058             :  * Get a list of configuration strings, free the result with
    1059             :  * heim_config_free_strings().
    1060             :  *
    1061             :  * @param context A Kerberos 5 context.
    1062             :  * @param c a configuration section, or NULL to use the section from context
    1063             :  * @param args a va_list of arguments
    1064             :  *
    1065             :  * @return TRUE or FALSE
    1066             :  *
    1067             :  * @ingroup heim_support
    1068             :  */
    1069             : 
    1070             : char **
    1071    10882827 : heim_config_vget_strings(heim_context context,
    1072             :                          const heim_config_section *c,
    1073             :                          va_list args)
    1074             : {
    1075    10882827 :     char **strings = NULL;
    1076    10882827 :     size_t nstr = 0;
    1077    10882827 :     const heim_config_binding *b = NULL;
    1078      278159 :     const char *p;
    1079             : 
    1080    11110049 :     while((p = heim_config_vget_next(context, c, &b,
    1081             :                                      heim_config_string, args))) {
    1082      227222 :         char *tmp = strdup(p);
    1083      227222 :         char *pos = NULL;
    1084        4498 :         char *s;
    1085      227222 :         if(tmp == NULL)
    1086           0 :             goto cleanup;
    1087      227222 :         s = next_component_string(tmp, " \t", &pos);
    1088      720458 :         while(s){
    1089      493236 :             char **tmp2 = realloc(strings, (nstr + 1) * sizeof(*strings));
    1090      493236 :             if(tmp2 == NULL) {
    1091           0 :                 free(tmp);
    1092           0 :                 goto cleanup;
    1093             :             }
    1094      493236 :             strings = tmp2;
    1095      493236 :             strings[nstr] = strdup(s);
    1096      493236 :             nstr++;
    1097      493236 :             if(strings[nstr-1] == NULL) {
    1098           0 :                 free(tmp);
    1099           0 :                 goto cleanup;
    1100             :             }
    1101      493236 :             s = next_component_string(NULL, " \t", &pos);
    1102             :         }
    1103      227222 :         free(tmp);
    1104             :     }
    1105    10882827 :     if(nstr){
    1106      226509 :         char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings));
    1107      226509 :         if(tmp == NULL)
    1108           0 :             goto cleanup;
    1109      226509 :         strings = tmp;
    1110      226509 :         strings[nstr] = NULL;
    1111             :     }
    1112    10604668 :     return strings;
    1113           0 : cleanup:
    1114           0 :     while(nstr--)
    1115           0 :         free(strings[nstr]);
    1116           0 :     free(strings);
    1117           0 :     return NULL;
    1118             : 
    1119             : }
    1120             : 
    1121             : /**
    1122             :  * Get a list of configuration strings, free the result with
    1123             :  * heim_config_free_strings().
    1124             :  *
    1125             :  * @param context A Kerberos 5 context.
    1126             :  * @param c a configuration section, or NULL to use the section from context
    1127             :  * @param ... a list of names, terminated with NULL.
    1128             :  *
    1129             :  * @return TRUE or FALSE
    1130             :  *
    1131             :  * @ingroup heim_support
    1132             :  */
    1133             : 
    1134             : char **
    1135           0 : heim_config_get_strings(heim_context context,
    1136             :                         const heim_config_section *c,
    1137             :                         ...)
    1138             : {
    1139           0 :     va_list ap;
    1140           0 :     char **ret;
    1141           0 :     va_start(ap, c);
    1142           0 :     ret = heim_config_vget_strings(context, c, ap);
    1143           0 :     va_end(ap);
    1144           0 :     return ret;
    1145             : }
    1146             : 
    1147             : /**
    1148             :  * Free the resulting strings from heim_config-get_strings() and
    1149             :  * heim_config_vget_strings().
    1150             :  *
    1151             :  * @param strings strings to free
    1152             :  *
    1153             :  * @ingroup heim_support
    1154             :  */
    1155             : 
    1156             : void
    1157     2822617 : heim_config_free_strings(char **strings)
    1158             : {
    1159     2822617 :     char **s = strings;
    1160             : 
    1161     3295585 :     while (s && *s) {
    1162      472968 :         free(*s);
    1163      472968 :         s++;
    1164             :     }
    1165     2822617 :     free(strings);
    1166     2822617 : }
    1167             : 
    1168             : /**
    1169             :  * Like heim_config_get_bool_default() but with a va_list list of
    1170             :  * configuration selection.
    1171             :  *
    1172             :  * Configuration value to a boolean value, where yes/true and any
    1173             :  * non-zero number means TRUE and other value is FALSE.
    1174             :  *
    1175             :  * @param context A Kerberos 5 context.
    1176             :  * @param c a configuration section, or NULL to use the section from context
    1177             :  * @param def_value the default value to return if no configuration
    1178             :  *        found in the database.
    1179             :  * @param args a va_list of arguments
    1180             :  *
    1181             :  * @return TRUE or FALSE
    1182             :  *
    1183             :  * @ingroup heim_support
    1184             :  */
    1185             : 
    1186             : int
    1187    13962311 : heim_config_vget_bool_default(heim_context context,
    1188             :                               const heim_config_section *c,
    1189             :                               int def_value,
    1190             :                               va_list args)
    1191             : {
    1192      362035 :     const char *str;
    1193    13962311 :     str = heim_config_vget_string(context, c, args);
    1194    13962311 :     if (str == NULL)
    1195    11157614 :         return def_value;
    1196     4929440 :     return !!(strcasecmp(str, "yes") == 0 ||
    1197     2485594 :               strcasecmp(str, "true") == 0 ||
    1198     1261386 :               atoi(str));
    1199             : }
    1200             : 
    1201             : /**
    1202             :  * heim_config_get_bool() will convert the configuration
    1203             :  * option value to a boolean value, where yes/true and any non-zero
    1204             :  * number means TRUE and other value is FALSE.
    1205             :  *
    1206             :  * @param context A Kerberos 5 context.
    1207             :  * @param c a configuration section, or NULL to use the section from context
    1208             :  * @param args a va_list of arguments
    1209             :  *
    1210             :  * @return TRUE or FALSE
    1211             :  *
    1212             :  * @ingroup heim_support
    1213             :  */
    1214             : 
    1215             : int
    1216           0 : heim_config_vget_bool(heim_context context,
    1217             :                       const heim_config_section *c,
    1218             :                       va_list args)
    1219             : {
    1220           0 :     return heim_config_vget_bool_default(context, c, 0, args);
    1221             : }
    1222             : 
    1223             : /**
    1224             :  * heim_config_get_bool_default() will convert the configuration
    1225             :  * option value to a boolean value, where yes/true and any non-zero
    1226             :  * number means TRUE and other value is FALSE.
    1227             :  *
    1228             :  * @param context A Kerberos 5 context.
    1229             :  * @param c a configuration section, or NULL to use the section from context
    1230             :  * @param def_value the default value to return if no configuration
    1231             :  *        found in the database.
    1232             :  * @param ... a list of names, terminated with NULL.
    1233             :  *
    1234             :  * @return TRUE or FALSE
    1235             :  *
    1236             :  * @ingroup heim_support
    1237             :  */
    1238             : 
    1239             : int
    1240           0 : heim_config_get_bool_default(heim_context context,
    1241             :                              const heim_config_section *c,
    1242             :                              int def_value,
    1243             :                              ...)
    1244             : {
    1245           0 :     va_list ap;
    1246           0 :     int ret;
    1247             : 
    1248           0 :     va_start(ap, def_value);
    1249           0 :     ret = heim_config_vget_bool_default(context, c, def_value, ap);
    1250           0 :     va_end(ap);
    1251           0 :     return ret;
    1252             : }
    1253             : 
    1254             : /**
    1255             :  * Like heim_config_get_bool() but with a va_list list of
    1256             :  * configuration selection.
    1257             :  *
    1258             :  * Configuration value to a boolean value, where yes/true and any
    1259             :  * non-zero number means TRUE and other value is FALSE.
    1260             :  *
    1261             :  * @param context A Kerberos 5 context.
    1262             :  * @param c a configuration section, or NULL to use the section from context
    1263             :  * @param ... a list of names, terminated with NULL.
    1264             :  *
    1265             :  * @return TRUE or FALSE
    1266             :  *
    1267             :  * @ingroup heim_support
    1268             :  */
    1269             : 
    1270             : int
    1271           0 : heim_config_get_bool(heim_context context,
    1272             :                      const heim_config_section *c,
    1273             :                      ...)
    1274             : {
    1275           0 :     va_list ap;
    1276           0 :     int ret;
    1277           0 :     va_start(ap, c);
    1278           0 :     ret = heim_config_vget_bool (context, c, ap);
    1279           0 :     va_end(ap);
    1280           0 :     return ret;
    1281             : }
    1282             : 
    1283             : /**
    1284             :  * Get the time from the configuration file using a relative time.
    1285             :  *
    1286             :  * Like heim_config_get_time_default() but with a va_list list of
    1287             :  * configuration selection.
    1288             :  *
    1289             :  * @param context A Kerberos 5 context.
    1290             :  * @param c a configuration section, or NULL to use the section from context
    1291             :  * @param def_value the default value to return if no configuration
    1292             :  *        found in the database.
    1293             :  * @param args a va_list of arguments
    1294             :  *
    1295             :  * @return parsed the time (or def_value on parse error)
    1296             :  *
    1297             :  * @ingroup heim_support
    1298             :  */
    1299             : 
    1300             : time_t
    1301     4710541 : heim_config_vget_time_default(heim_context context,
    1302             :                               const heim_config_section *c,
    1303             :                               int def_value,
    1304             :                               va_list args)
    1305             : {
    1306      119978 :     const char *str;
    1307     4710541 :     time_t t = -1;
    1308             : 
    1309     4710541 :     if ((str = heim_config_vget_string(context, c, args)))
    1310           0 :         t = parse_time(str, "s");
    1311     4710541 :     return t != -1 ? t : def_value;
    1312             : }
    1313             : 
    1314             : /**
    1315             :  * Get the time from the configuration file using a relative time, for example: 1h30s
    1316             :  *
    1317             :  * @param context A Kerberos 5 context.
    1318             :  * @param c a configuration section, or NULL to use the section from context
    1319             :  * @param args a va_list of arguments
    1320             :  *
    1321             :  * @return parsed the time or -1 on error
    1322             :  *
    1323             :  * @ingroup heim_support
    1324             :  */
    1325             : 
    1326             : time_t
    1327       26922 : heim_config_vget_time(heim_context context,
    1328             :                       const heim_config_section *c,
    1329             :                       va_list args)
    1330             : {
    1331       26922 :     return heim_config_vget_time_default(context, c, -1, args);
    1332             : }
    1333             : 
    1334             : /**
    1335             :  * Get the time from the configuration file using a relative time, for example: 1h30s
    1336             :  *
    1337             :  * @param context A Kerberos 5 context.
    1338             :  * @param c a configuration section, or NULL to use the section from context
    1339             :  * @param def_value the default value to return if no configuration
    1340             :  *        found in the database.
    1341             :  * @param ... a list of names, terminated with NULL.
    1342             :  *
    1343             :  * @return parsed the time (or def_value on parse error)
    1344             :  *
    1345             :  * @ingroup heim_support
    1346             :  */
    1347             : 
    1348             : time_t
    1349      759605 : heim_config_get_time_default(heim_context context,
    1350             :                              const heim_config_section *c,
    1351             :                              int def_value,
    1352             :                              ...)
    1353             : {
    1354       19721 :     va_list ap;
    1355       19721 :     time_t ret;
    1356             : 
    1357      759605 :     va_start(ap, def_value);
    1358      759605 :     ret = heim_config_vget_time_default(context, c, def_value, ap);
    1359      759605 :     va_end(ap);
    1360      759605 :     return ret;
    1361             : }
    1362             : 
    1363             : /**
    1364             :  * Get the time from the configuration file using a relative time, for example: 1h30s
    1365             :  *
    1366             :  * @param context A Kerberos 5 context.
    1367             :  * @param c a configuration section, or NULL to use the section from context
    1368             :  * @param ... a list of names, terminated with NULL.
    1369             :  *
    1370             :  * @return parsed the time or -1 on error
    1371             :  *
    1372             :  * @ingroup heim_support
    1373             :  */
    1374             : 
    1375             : time_t
    1376           0 : heim_config_get_time(heim_context context,
    1377             :                      const heim_config_section *c,
    1378             :                      ...)
    1379             : {
    1380           0 :     va_list ap;
    1381           0 :     int ret;
    1382           0 :     va_start(ap, c);
    1383           0 :     ret = heim_config_vget_time(context, c, ap);
    1384           0 :     va_end(ap);
    1385           0 :     return ret;
    1386             : }
    1387             : 
    1388             : 
    1389             : int
    1390     5231847 : heim_config_vget_int_default(heim_context context,
    1391             :                              const heim_config_section *c,
    1392             :                              int def_value,
    1393             :                              va_list args)
    1394             : {
    1395      132068 :     const char *str;
    1396     5231847 :     str = heim_config_vget_string (context, c, args);
    1397     5231847 :     if(str == NULL)
    1398     5099779 :         return def_value;
    1399             :     else {
    1400           0 :         char *endptr;
    1401           0 :         long l;
    1402           0 :         l = strtol(str, &endptr, 0);
    1403           0 :         if (endptr == str)
    1404           0 :             return def_value;
    1405             :         else
    1406           0 :             return l;
    1407             :     }
    1408             : }
    1409             : 
    1410             : int
    1411           0 : heim_config_vget_int(heim_context context,
    1412             :                      const heim_config_section *c,
    1413             :                      va_list args)
    1414             : {
    1415           0 :     return heim_config_vget_int_default(context, c, -1, args);
    1416             : }
    1417             : 
    1418             : int
    1419           0 : heim_config_get_int_default(heim_context context,
    1420             :                             const heim_config_section *c,
    1421             :                             int def_value,
    1422             :                             ...)
    1423             : {
    1424           0 :     va_list ap;
    1425           0 :     int ret;
    1426             : 
    1427           0 :     va_start(ap, def_value);
    1428           0 :     ret = heim_config_vget_int_default(context, c, def_value, ap);
    1429           0 :     va_end(ap);
    1430           0 :     return ret;
    1431             : }
    1432             : 
    1433             : int
    1434           0 : heim_config_get_int(heim_context context,
    1435             :                     const heim_config_section *c,
    1436             :                     ...)
    1437             : {
    1438           0 :     va_list ap;
    1439           0 :     int ret;
    1440           0 :     va_start(ap, c);
    1441           0 :     ret = heim_config_vget_int (context, c, ap);
    1442           0 :     va_end(ap);
    1443           0 :     return ret;
    1444             : }
    1445             : 
    1446             : #ifndef HEIMDAL_SMALLER
    1447             : heim_error_code
    1448           0 : heim_config_parse_string_multi(heim_context context,
    1449             :                                const char *string,
    1450             :                                heim_config_section **res)
    1451             : {
    1452           0 :     const char *str;
    1453           0 :     unsigned lineno = 0;
    1454           0 :     heim_error_code ret;
    1455           0 :     struct fileptr f;
    1456             : 
    1457           0 :     f.context = context;
    1458           0 :     f.f = NULL;
    1459           0 :     f.s = string;
    1460             : 
    1461           0 :     ret = heim_config_parse_debug(&f, res, &lineno, &str);
    1462           0 :     if (ret) {
    1463           0 :         if (ret != HEIM_ERR_CONFIG_BADFORMAT) {
    1464           0 :             ret = HEIM_ERR_CONFIG_BADFORMAT;
    1465           0 :             heim_set_error_message(context, ret, "%s:%u: %s",
    1466             :                                    "<constant>", lineno, str);
    1467             :         }
    1468           0 :         return ret;
    1469             :     }
    1470           0 :     return 0;
    1471             : }
    1472             : #endif

Generated by: LCOV version 1.14