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 v4-17-test 1498b464 Lines: 255 481 53.0 %
Date: 2024-06-13 04:01:37 Functions: 24 42 57.1 %

          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    57267055 : 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    57267055 :     if(ptr->f != NULL)
      58    57267055 :         return fgets(str, len, ptr->f);
      59             :     else {
      60             :         /* this is almost strsep_copy */
      61             :         const char *p;
      62             :         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    36705666 : heim_config_get_entry(heim_config_section **parent, const char *name, int type)
      91             : {
      92             :     heim_config_section **q;
      93             : 
      94   108012158 :     for (q = parent; *q != NULL; q = &(*q)->next)
      95    85491419 :         if (type == heim_config_list &&
      96    28367902 :             (unsigned)type == (*q)->type &&
      97    14183951 :             strcmp(name, (*q)->name) == 0)
      98         976 :             return *q;
      99    36704690 :     *q = calloc(1, sizeof(**q));
     100    36704690 :     if (*q == NULL)
     101           0 :         return NULL;
     102    36704690 :     (*q)->name = strdup(name);
     103    36704690 :     (*q)->type = type;
     104    36704690 :     if ((*q)->name == NULL) {
     105           0 :         free(*q);
     106           0 :         *q = NULL;
     107           0 :         return NULL;
     108             :     }
     109    36704690 :     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     3739920 : parse_section(char *p, heim_config_section **s, heim_config_section **parent,
     129             :               const char **err_message)
     130             : {
     131             :     char *p1;
     132             :     heim_config_section *tmp;
     133             : 
     134     3739920 :     p1 = strchr (p + 1, ']');
     135     3739920 :     if (p1 == NULL) {
     136           0 :         *err_message = "missing ]";
     137           0 :         return HEIM_ERR_CONFIG_BADFORMAT;
     138             :     }
     139     3739920 :     *p1 = '\0';
     140     3739920 :     tmp = heim_config_get_entry(parent, p + 1, heim_config_list);
     141     3739920 :     if(tmp == NULL) {
     142           0 :         *err_message = "out of memory";
     143           0 :         return HEIM_ERR_CONFIG_BADFORMAT;
     144             :     }
     145     3739920 :     *s = tmp;
     146     3739920 :     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     4301768 : parse_list(struct fileptr *f, unsigned *lineno, heim_config_binding **parent,
     157             :            const char **err_message)
     158             : {
     159             :     char buf[2048];
     160             :     heim_error_code ret;
     161     4301768 :     heim_config_binding *b = NULL;
     162     4301768 :     unsigned beg_lineno = *lineno;
     163             : 
     164    25806712 :     while(config_fgets(buf, sizeof(buf), f) != NULL) {
     165             :         char *p;
     166             : 
     167    21504944 :         ++*lineno;
     168    21504944 :         buf[strcspn(buf, "\r\n")] = '\0';
     169    21504944 :         p = buf;
     170    81729180 :         while(isspace((unsigned char)*p))
     171    38719292 :             ++p;
     172    21504944 :         if (*p == '#' || *p == ';' || *p == '\0')
     173           0 :             continue;
     174    43009888 :         while(isspace((unsigned char)*p))
     175           0 :             ++p;
     176    21504944 :         if (*p == '}')
     177     4301768 :             return 0;
     178    17203176 :         if (*p == '\0')
     179           0 :             continue;
     180    17203176 :         ret = parse_binding (f, lineno, p, &b, parent, err_message);
     181    17203176 :         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    32965746 : 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             :     heim_config_binding *tmp;
     199             :     char *p1, *p2;
     200    32965746 :     heim_error_code ret = 0;
     201             : 
     202    32965746 :     p1 = p;
     203   562436762 :     while (*p && *p != '=' && !isspace((unsigned char)*p))
     204   496505270 :         ++p;
     205    32965746 :     if (*p == '\0') {
     206           0 :         *err_message = "missing =";
     207           0 :         return HEIM_ERR_CONFIG_BADFORMAT;
     208             :     }
     209    32965746 :     p2 = p;
     210    98897238 :     while (isspace((unsigned char)*p))
     211    32965746 :         ++p;
     212    32965746 :     if (*p != '=') {
     213           0 :         *err_message = "missing =";
     214           0 :         return HEIM_ERR_CONFIG_BADFORMAT;
     215             :     }
     216    32965746 :     ++p;
     217    98897238 :     while(isspace((unsigned char)*p))
     218    32965746 :         ++p;
     219    32965746 :     *p2 = '\0';
     220    32965746 :     if (*p == '{') {
     221     4301768 :         tmp = heim_config_get_entry(parent, p1, heim_config_list);
     222     4301768 :         if (tmp == NULL) {
     223           0 :             *err_message = "out of memory";
     224           0 :             return HEIM_ERR_CONFIG_BADFORMAT;
     225             :         }
     226     4301768 :         ret = parse_list (f, lineno, &tmp->u.list, err_message);
     227             :     } else {
     228    28663978 :         tmp = heim_config_get_entry(parent, p1, heim_config_string);
     229    28663978 :         if (tmp == NULL) {
     230           0 :             *err_message = "out of memory";
     231           0 :             return HEIM_ERR_CONFIG_BADFORMAT;
     232             :         }
     233    28663978 :         p1 = p;
     234    28663978 :         p = p1 + strlen(p1);
     235    57327956 :         while(p > p1 && isspace((unsigned char)*(p-1)))
     236           0 :             --p;
     237    28663978 :         *p = '\0';
     238    28663978 :         tmp->u.string = strdup(p1);
     239             :     }
     240    32965746 :     *b = tmp;
     241    32965746 :     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(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      941541 : heim_config_parse_debug(struct fileptr *f,
     386             :                         heim_config_section **res,
     387             :                         unsigned *lineno,
     388             :                         const char **err_message)
     389             : {
     390      941541 :     heim_config_section *s = NULL;
     391      941541 :     heim_config_binding *b = NULL;
     392             :     char buf[2048];
     393             :     heim_error_code ret;
     394             : 
     395      941541 :     *lineno = 0;
     396      941541 :     *err_message = "";
     397             : 
     398    36703652 :     while (config_fgets(buf, sizeof(buf), f) != NULL) {
     399             :         char *p;
     400             : 
     401    34820570 :         ++*lineno;
     402    34820570 :         buf[strcspn(buf, "\r\n")] = '\0';
     403    34820570 :         p = buf;
     404    88362668 :         while(isspace((unsigned char)*p))
     405    18721528 :             ++p;
     406    34820570 :         if (*p == '#' || *p == ';')
     407     2823699 :             continue;
     408    31996871 :         if (*p == '[') {
     409     3739920 :             ret = parse_section(p, &s, res, err_message);
     410     3739920 :             if (ret)
     411           0 :                 return ret;
     412     3739920 :             b = NULL;
     413    28256951 :         } else if (*p == '}') {
     414           0 :             *err_message = "unmatched }";
     415           0 :             return 2048;
     416    28256951 :         } else if (strncmp(p, "include", sizeof("include") - 1) == 0 &&
     417           0 :             isspace(p[sizeof("include") - 1])) {
     418           0 :             p += sizeof("include");
     419           0 :             while (isspace(*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    28256951 :         } else if (strncmp(p, "includedir", sizeof("includedir") - 1) == 0 &&
     431           0 :             isspace(p[sizeof("includedir") - 1])) {
     432           0 :             p += sizeof("includedir");
     433           0 :             while (isspace(*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    28256951 :         } else if(*p != '\0') {
     445    15762570 :             if (s == NULL) {
     446           0 :                 *err_message = "binding before section";
     447           0 :                 return 2048;
     448             :             }
     449    15762570 :             ret = parse_binding(f, lineno, p, &b, &s->u.list, err_message);
     450    15762570 :             if (ret)
     451           0 :                 return ret;
     452             :         }
     453             :     }
     454      941541 :     return 0;
     455             : }
     456             : 
     457             : static int
     458     2076982 : is_plist_file(const char *fname)
     459             : {
     460     2076982 :     size_t len = strlen(fname);
     461     2076982 :     char suffix[] = ".plist";
     462     2076982 :     if (len < sizeof(suffix))
     463           0 :         return 0;
     464     2076982 :     if (strcasecmp(&fname[len - (sizeof(suffix) - 1)], suffix) != 0)
     465     2076982 :         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             :     struct dirent *entry;
     492             :     heim_error_code ret;
     493             :     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             :         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(*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             : /**
     539             :  * Parse a configuration file and add the result into res. This
     540             :  * interface can be used to parse several configuration files into one
     541             :  * resulting heim_config_section by calling it repeatably.
     542             :  *
     543             :  * @param context a Kerberos 5 context.
     544             :  * @param fname a file name to a Kerberos configuration file
     545             :  * @param res the returned result, must be free with heim_free_config_files().
     546             :  * @return Return an error code or 0, see heim_get_error_message().
     547             :  *
     548             :  * @ingroup heim_support
     549             :  */
     550             : 
     551             : HEIMDAL_THREAD_LOCAL int config_include_depth = 0;
     552             : 
     553             : heim_error_code
     554     2076982 : heim_config_parse_file_multi(heim_context context,
     555             :                              const char *fname,
     556             :                              heim_config_section **res)
     557             : {
     558             :     const char *str;
     559     2076982 :     char *newfname = NULL;
     560     2076982 :     unsigned lineno = 0;
     561     2076982 :     heim_error_code ret = 0;
     562             :     struct fileptr f;
     563             :     struct stat st;
     564             : 
     565     2076982 :     if (config_include_depth > 5) {
     566           0 :         heim_warnx(context, "Maximum config file include depth reached; "
     567             :                    "not including %s", fname);
     568           0 :         return 0;
     569             :     }
     570     2076982 :     config_include_depth++;
     571             : 
     572             :     /**
     573             :      * If the fname starts with "~/" parse configuration file in the
     574             :      * current users home directory. The behavior can be disabled and
     575             :      * enabled by calling heim_set_home_dir_access().
     576             :      */
     577     2076982 :     if (ISTILDE(fname[0]) && ISPATHSEP(fname[1])) {
     578      555900 :         if (!heim_context_get_homedir_access(context)) {
     579           0 :             heim_set_error_message(context, EPERM,
     580             :                                    "Access to home directory not allowed");
     581           0 :             ret = EPERM;
     582           0 :             goto out;
     583             :         }
     584     1111800 :         if (asprintf(&newfname, "%%{USERCONFIG}%s", &fname[1]) < 0 ||
     585      555900 :             newfname == NULL) {
     586           0 :             ret = heim_enomem(context);
     587           0 :             goto out;
     588             :         }
     589      555900 :         fname = newfname;
     590             :     }
     591             : 
     592     2076982 :     if (is_plist_file(fname)) {
     593             : #if defined(HAVE_FRAMEWORK_COREFOUNDATION)
     594             :         ret = parse_plist_config(context, fname, res);
     595             :         if (ret) {
     596             :             heim_set_error_message(context, ret,
     597             :                                    "Failed to parse plist %s", fname);
     598             :             goto out;
     599             :         }
     600             : #else
     601           0 :         heim_set_error_message(context, ENOENT,
     602             :                                "no support for plist configuration files");
     603           0 :         ret = ENOENT;
     604           0 :         goto out;
     605             : #endif
     606             :     } else {
     607     2076982 :         char *exp_fname = NULL;
     608             : 
     609             :         /*
     610             :          * Note that heim_config_parse_dir_multi() doesn't want tokens
     611             :          * expanded here, but it happens to limit the names of files to
     612             :          * include such that there can be no tokens to expand.  Don't
     613             :          * add token expansion for tokens using _, say.
     614             :          */
     615     2076982 :         ret = heim_expand_path_tokens(context, fname, 1, &exp_fname, NULL);
     616     2076982 :         if (ret)
     617     1135441 :             goto out;
     618     2076982 :         free(newfname);
     619     2076982 :         fname = newfname = exp_fname;
     620             : 
     621     2076982 :         f.context = context;
     622     2076982 :         f.f = fopen(fname, "r");
     623     2076982 :         f.s = NULL;
     624     2076982 :         if (f.f == NULL || fstat(fileno(f.f), &st) == -1) {
     625     1135441 :             if (f.f != NULL)
     626           0 :                 (void) fclose(f.f);
     627     1135441 :             ret = errno;
     628     1135441 :             heim_set_error_message(context, ret, "open or stat %s: %s",
     629             :                                    fname, strerror(ret));
     630     1135441 :             goto out;
     631             :         }
     632             : 
     633      941541 :         if (!S_ISREG(st.st_mode)) {
     634           0 :             (void) fclose(f.f);
     635           0 :             heim_set_error_message(context, EISDIR, "not a regular file %s: %s",
     636             :                                    fname, strerror(EISDIR));
     637           0 :             ret = EISDIR;
     638           0 :             goto out;
     639             :         }
     640             : 
     641      941541 :         ret = heim_config_parse_debug(&f, res, &lineno, &str);
     642      941541 :         fclose(f.f);
     643      941541 :         if (ret) {
     644           0 :             if (ret != HEIM_ERR_CONFIG_BADFORMAT)
     645           0 :                 ret = HEIM_ERR_CONFIG_BADFORMAT;
     646           0 :             heim_set_error_message(context, ret, "%s:%u: %s",
     647             :                                    fname, lineno, str);
     648           0 :             goto out;
     649             :         }
     650             :     }
     651             : 
     652     2076982 :   out:
     653     2076982 :     config_include_depth--;
     654     2076982 :     if (ret == HEIM_ERR_CONFIG_BADFORMAT || (ret && config_include_depth > 0)) {
     655           0 :         heim_warn(context, ret, "Ignoring");
     656           0 :         if (config_include_depth > 0)
     657           0 :             ret = 0;
     658             :     }
     659     2076982 :     free(newfname);
     660     2076982 :     return ret;
     661             : }
     662             : 
     663             : heim_error_code
     664           0 : heim_config_parse_file(heim_context context,
     665             :                        const char *fname,
     666             :                        heim_config_section **res)
     667             : {
     668           0 :     *res = NULL;
     669           0 :     return heim_config_parse_file_multi(context, fname, res);
     670             : }
     671             : 
     672             : static void
     673     9852648 : free_binding(heim_context context, heim_config_binding *b)
     674             : {
     675             :     heim_config_binding *next_b;
     676             : 
     677    55487526 :     while (b) {
     678    35782230 :         free (b->name);
     679    35782230 :         assert(b->type == heim_config_string || b->type == heim_config_list);
     680    35782230 :         if (b->type == heim_config_string)
     681    27940032 :             free (b->u.string);
     682             :         else
     683     7842198 :             free_binding (context, b->u.list);
     684    35782230 :         next_b = b->next;
     685    35782230 :         free (b);
     686    35782230 :         b = next_b;
     687             :     }
     688     9852648 : }
     689             : 
     690             : /**
     691             :  * Free configuration file section, the result of
     692             :  * heim_config_parse_file() and heim_config_parse_file_multi().
     693             :  *
     694             :  * @param context A Kerberos 5 context
     695             :  * @param s the configuration section to free
     696             :  *
     697             :  * @return returns 0 on successes, otherwise an error code, see
     698             :  *          heim_get_error_message()
     699             :  *
     700             :  * @ingroup heim_support
     701             :  */
     702             : 
     703             : heim_error_code
     704     2010450 : heim_config_file_free(heim_context context, heim_config_section *s)
     705             : {
     706     2010450 :     free_binding (context, s);
     707     2010450 :     return 0;
     708             : }
     709             : 
     710             : #ifndef HEIMDAL_SMALLER
     711             : 
     712             : heim_error_code
     713           0 : heim_config_copy(heim_context context,
     714             :                  heim_config_section *c,
     715             :                  heim_config_section **head)
     716             : {
     717           0 :     heim_config_binding *d, *previous = NULL;
     718             : 
     719           0 :     *head = NULL;
     720             : 
     721           0 :     while (c) {
     722           0 :         d = calloc(1, sizeof(*d));
     723             : 
     724           0 :         if (*head == NULL)
     725           0 :             *head = d;
     726             : 
     727           0 :         d->name = strdup(c->name);
     728           0 :         d->type = c->type;
     729           0 :         assert(d->type == heim_config_string || d->type == heim_config_list);
     730           0 :         if (d->type == heim_config_string)
     731           0 :             d->u.string = strdup(c->u.string);
     732             :         else
     733           0 :             heim_config_copy (context, c->u.list, &d->u.list);
     734           0 :         if (previous)
     735           0 :             previous->next = d;
     736             : 
     737           0 :         previous = d;
     738           0 :         c = c->next;
     739             :     }
     740           0 :     return 0;
     741             : }
     742             : 
     743             : #endif /* HEIMDAL_SMALLER */
     744             : 
     745             : const void *
     746           0 : heim_config_get_next(heim_context context,
     747             :                      const heim_config_section *c,
     748             :                      const heim_config_binding **pointer,
     749             :                      int type,
     750             :                      ...)
     751             : {
     752             :     const char *ret;
     753             :     va_list args;
     754             : 
     755           0 :     va_start(args, type);
     756           0 :     ret = heim_config_vget_next(context, c, pointer, type, args);
     757           0 :     va_end(args);
     758           0 :     return ret;
     759             : }
     760             : 
     761             : static const void *
     762    61030429 : vget_next(heim_context context,
     763             :           const heim_config_binding *b,
     764             :           const heim_config_binding **pointer,
     765             :           int type,
     766             :           const char *name,
     767             :           va_list args)
     768             : {
     769    61030429 :     const char *p = va_arg(args, const char *);
     770             : 
     771   361411469 :     while (b != NULL) {
     772   271458105 :         if (strcmp(b->name, name) == 0) {
     773    32128338 :             if (b->type == (unsigned)type && p == NULL) {
     774     2126298 :                 *pointer = b;
     775     2126298 :                 return b->u.generic;
     776    30002040 :             } else if (b->type == heim_config_list && p != NULL) {
     777    29981196 :                 return vget_next(context, b->u.list, pointer, type, p, args);
     778             :             }
     779             :         }
     780   239350611 :         b = b->next;
     781             :     }
     782    28922935 :     return NULL;
     783             : }
     784             : 
     785             : const void *
     786    32412393 : heim_config_vget_next(heim_context context,
     787             :                       const heim_config_section *c,
     788             :                       const heim_config_binding **pointer,
     789             :                       int type,
     790             :                       va_list args)
     791             : {
     792             :     const heim_config_binding *b;
     793             :     const char *p;
     794             : 
     795    32412393 :     if (c == NULL)
     796     1169033 :         return NULL;
     797             : 
     798    31243360 :     if (*pointer == NULL) {
     799             :         /* first time here, walk down the tree looking for the right
     800             :            section */
     801    31049233 :         p = va_arg(args, const char *);
     802    31049233 :         if (p == NULL)
     803           0 :             return NULL;
     804    31049233 :         return vget_next(context, c, pointer, type, p, args);
     805             :     }
     806             : 
     807             :     /* we were called again, so just look for more entries with the
     808             :        same name and type */
     809      749777 :     for (b = (*pointer)->next; b != NULL; b = b->next) {
     810      555853 :         if(strcmp(b->name, (*pointer)->name) == 0 && b->type == (unsigned)type) {
     811         203 :             *pointer = b;
     812         203 :             return b->u.generic;
     813             :         }
     814             :     }
     815      193924 :     return NULL;
     816             : }
     817             : 
     818             : const void *
     819           0 : heim_config_get(heim_context context,
     820             :                 const heim_config_section *c,
     821             :                 int type,
     822             :                 ...)
     823             : {
     824             :     const void *ret;
     825             :     va_list args;
     826             : 
     827           0 :     va_start(args, type);
     828           0 :     ret = heim_config_vget(context, c, type, args);
     829           0 :     va_end(args);
     830           0 :     return ret;
     831             : }
     832             : 
     833             : 
     834             : const void *
     835    24361649 : heim_config_vget(heim_context context,
     836             :                  const heim_config_section *c,
     837             :                  int type,
     838             :                  va_list args)
     839             : {
     840    24361649 :     const heim_config_binding *foo = NULL;
     841             : 
     842    24361649 :     return heim_config_vget_next(context, c, &foo, type, args);
     843             : }
     844             : 
     845             : /**
     846             :  * Get a list of configuration binding list for more processing
     847             :  *
     848             :  * @param context A Kerberos 5 context.
     849             :  * @param c a configuration section, or NULL to use the section from context
     850             :  * @param ... a list of names, terminated with NULL.
     851             :  *
     852             :  * @return NULL if configuration list is not found, a list otherwise
     853             :  *
     854             :  * @ingroup heim_support
     855             :  */
     856             : 
     857             : const heim_config_binding *
     858           0 : heim_config_get_list(heim_context context,
     859             :                      const heim_config_section *c,
     860             :                      ...)
     861             : {
     862             :     const heim_config_binding *ret;
     863             :     va_list args;
     864             : 
     865           0 :     va_start(args, c);
     866           0 :     ret = heim_config_vget_list(context, c, args);
     867           0 :     va_end(args);
     868           0 :     return ret;
     869             : }
     870             : 
     871             : /**
     872             :  * Get a list of configuration binding list for more processing
     873             :  *
     874             :  * @param context A Kerberos 5 context.
     875             :  * @param c a configuration section, or NULL to use the section from context
     876             :  * @param args a va_list of arguments
     877             :  *
     878             :  * @return NULL if configuration list is not found, a list otherwise
     879             :  *
     880             :  * @ingroup heim_support
     881             :  */
     882             : 
     883             : const heim_config_binding *
     884           0 : heim_config_vget_list(heim_context context,
     885             :                       const heim_config_section *c,
     886             :                       va_list args)
     887             : {
     888           0 :     return heim_config_vget(context, c, heim_config_list, args);
     889             : }
     890             : 
     891             : /**
     892             :  * Returns a "const char *" to a string in the configuration database.
     893             :  * The string may not be valid after a reload of the configuration
     894             :  * database so a caller should make a local copy if it needs to keep
     895             :  * the string.
     896             :  *
     897             :  * @param context A Kerberos 5 context.
     898             :  * @param c a configuration section, or NULL to use the section from context
     899             :  * @param ... a list of names, terminated with NULL.
     900             :  *
     901             :  * @return NULL if configuration string not found, a string otherwise
     902             :  *
     903             :  * @ingroup heim_support
     904             :  */
     905             : 
     906             : const char *
     907      555816 : heim_config_get_string(heim_context context,
     908             :                        const heim_config_section *c,
     909             :                        ...)
     910             : {
     911             :     const char *ret;
     912             :     va_list args;
     913             : 
     914      555816 :     va_start(args, c);
     915      555816 :     ret = heim_config_vget_string(context, c, args);
     916      555816 :     va_end(args);
     917      555816 :     return ret;
     918             : }
     919             : 
     920             : /**
     921             :  * Like heim_config_get_string(), but uses a va_list instead of ...
     922             :  *
     923             :  * @param context A Kerberos 5 context.
     924             :  * @param c a configuration section, or NULL to use the section from context
     925             :  * @param args a va_list of arguments
     926             :  *
     927             :  * @return NULL if configuration string not found, a string otherwise
     928             :  *
     929             :  * @ingroup heim_support
     930             :  */
     931             : 
     932             : const char *
     933    24361649 : heim_config_vget_string(heim_context context,
     934             :                         const heim_config_section *c,
     935             :                         va_list args)
     936             : {
     937    24361649 :     return heim_config_vget(context, c, heim_config_string, args);
     938             : }
     939             : 
     940             : /**
     941             :  * Like heim_config_vget_string(), but instead of returning NULL,
     942             :  * instead return a default value.
     943             :  *
     944             :  * @param context A Kerberos 5 context.
     945             :  * @param c a configuration section, or NULL to use the section from context
     946             :  * @param def_value the default value to return if no configuration
     947             :  *        found in the database.
     948             :  * @param args a va_list of arguments
     949             :  *
     950             :  * @return a configuration string
     951             :  *
     952             :  * @ingroup heim_support
     953             :  */
     954             : 
     955             : const char *
     956     4759700 : heim_config_vget_string_default(heim_context context,
     957             :                                 const heim_config_section *c,
     958             :                                 const char *def_value,
     959             :                                 va_list args)
     960             : {
     961             :     const char *ret;
     962             : 
     963     4759700 :     ret = heim_config_vget_string(context, c, args);
     964     4759700 :     if (ret == NULL)
     965     4752552 :         ret = def_value;
     966     4759700 :     return ret;
     967             : }
     968             : 
     969             : /**
     970             :  * Like heim_config_get_string(), but instead of returning NULL,
     971             :  * instead return a default value.
     972             :  *
     973             :  * @param context A Kerberos 5 context.
     974             :  * @param c a configuration section, or NULL to use the section from context
     975             :  * @param def_value the default value to return if no configuration
     976             :  *        found in the database.
     977             :  * @param ... a list of names, terminated with NULL.
     978             :  *
     979             :  * @return a configuration string
     980             :  *
     981             :  * @ingroup heim_support
     982             :  */
     983             : 
     984             : const char *
     985           0 : heim_config_get_string_default(heim_context context,
     986             :                                const heim_config_section *c,
     987             :                                const char *def_value,
     988             :                                ...)
     989             : {
     990             :     const char *ret;
     991             :     va_list args;
     992             : 
     993           0 :     va_start(args, def_value);
     994           0 :     ret = heim_config_vget_string_default (context, c, def_value, args);
     995           0 :     va_end(args);
     996           0 :     return ret;
     997             : }
     998             : 
     999             : static char *
    1000      649394 : next_component_string(char * begin, const char * delims, char **state)
    1001             : {
    1002             :     char * end;
    1003             : 
    1004      649394 :     if (begin == NULL)
    1005      455267 :         begin = *state;
    1006             : 
    1007      649394 :     if (*begin == '\0')
    1008      194127 :         return NULL;
    1009             : 
    1010      455267 :     end = begin;
    1011      910534 :     while (*end == '"') {
    1012           0 :         char * t = strchr(end + 1, '"');
    1013             : 
    1014           0 :         if (t)
    1015           0 :             end = ++t;
    1016             :         else
    1017           0 :             end += strlen(end);
    1018             :     }
    1019             : 
    1020      455267 :     if (*end != '\0') {
    1021             :         size_t pos;
    1022             : 
    1023      455267 :         pos = strcspn(end, delims);
    1024      455267 :         end = end + pos;
    1025             :     }
    1026             : 
    1027      455267 :     if (*end != '\0') {
    1028      261140 :         *end = '\0';
    1029      261140 :         *state = end + 1;
    1030      261140 :         if (*begin == '"' && *(end - 1) == '"' && begin + 1 < end) {
    1031           0 :             begin++; *(end - 1) = '\0';
    1032             :         }
    1033      261140 :         return begin;
    1034             :     }
    1035             : 
    1036      194127 :     *state = end;
    1037      194127 :     if (*begin == '"' && *(end - 1) == '"' && begin + 1 < end) {
    1038           0 :         begin++; *(end - 1) = '\0';
    1039             :     }
    1040      194127 :     return begin;
    1041             : }
    1042             : 
    1043             : /**
    1044             :  * Get a list of configuration strings, free the result with
    1045             :  * heim_config_free_strings().
    1046             :  *
    1047             :  * @param context A Kerberos 5 context.
    1048             :  * @param c a configuration section, or NULL to use the section from context
    1049             :  * @param args a va_list of arguments
    1050             :  *
    1051             :  * @return TRUE or FALSE
    1052             :  *
    1053             :  * @ingroup heim_support
    1054             :  */
    1055             : 
    1056             : char **
    1057     7856617 : heim_config_vget_strings(heim_context context,
    1058             :                          const heim_config_section *c,
    1059             :                          va_list args)
    1060             : {
    1061     7856617 :     char **strings = NULL;
    1062     7856617 :     size_t nstr = 0;
    1063     7856617 :     const heim_config_binding *b = NULL;
    1064             :     const char *p;
    1065             : 
    1066    15907361 :     while((p = heim_config_vget_next(context, c, &b,
    1067             :                                      heim_config_string, args))) {
    1068      194127 :         char *tmp = strdup(p);
    1069      194127 :         char *pos = NULL;
    1070             :         char *s;
    1071      194127 :         if(tmp == NULL)
    1072           0 :             goto cleanup;
    1073      194127 :         s = next_component_string(tmp, " \t", &pos);
    1074      843521 :         while(s){
    1075      455267 :             char **tmp2 = realloc(strings, (nstr + 1) * sizeof(*strings));
    1076      455267 :             if(tmp2 == NULL) {
    1077           0 :                 free(tmp);
    1078           0 :                 goto cleanup;
    1079             :             }
    1080      455267 :             strings = tmp2;
    1081      455267 :             strings[nstr] = strdup(s);
    1082      455267 :             nstr++;
    1083      455267 :             if(strings[nstr-1] == NULL) {
    1084           0 :                 free(tmp);
    1085           0 :                 goto cleanup;
    1086             :             }
    1087      455267 :             s = next_component_string(NULL, " \t", &pos);
    1088             :         }
    1089      194127 :         free(tmp);
    1090             :     }
    1091     7856617 :     if(nstr){
    1092      193924 :         char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings));
    1093      193924 :         if(tmp == NULL)
    1094           0 :             goto cleanup;
    1095      193924 :         strings = tmp;
    1096      193924 :         strings[nstr] = NULL;
    1097             :     }
    1098     7856617 :     return strings;
    1099           0 : cleanup:
    1100           0 :     while(nstr--)
    1101           0 :         free(strings[nstr]);
    1102           0 :     free(strings);
    1103           0 :     return NULL;
    1104             : 
    1105             : }
    1106             : 
    1107             : /**
    1108             :  * Get a list of configuration strings, free the result with
    1109             :  * heim_config_free_strings().
    1110             :  *
    1111             :  * @param context A Kerberos 5 context.
    1112             :  * @param c a configuration section, or NULL to use the section from context
    1113             :  * @param ... a list of names, terminated with NULL.
    1114             :  *
    1115             :  * @return TRUE or FALSE
    1116             :  *
    1117             :  * @ingroup heim_support
    1118             :  */
    1119             : 
    1120             : char **
    1121           0 : heim_config_get_strings(heim_context context,
    1122             :                         const heim_config_section *c,
    1123             :                         ...)
    1124             : {
    1125             :     va_list ap;
    1126             :     char **ret;
    1127           0 :     va_start(ap, c);
    1128           0 :     ret = heim_config_vget_strings(context, c, ap);
    1129           0 :     va_end(ap);
    1130           0 :     return ret;
    1131             : }
    1132             : 
    1133             : /**
    1134             :  * Free the resulting strings from heim_config-get_strings() and
    1135             :  * heim_config_vget_strings().
    1136             :  *
    1137             :  * @param strings strings to free
    1138             :  *
    1139             :  * @ingroup heim_support
    1140             :  */
    1141             : 
    1142             : void
    1143     2066458 : heim_config_free_strings(char **strings)
    1144             : {
    1145     2066458 :     char **s = strings;
    1146             : 
    1147     4573944 :     while (s && *s) {
    1148      441028 :         free(*s);
    1149      441028 :         s++;
    1150             :     }
    1151     2066458 :     free(strings);
    1152     2066458 : }
    1153             : 
    1154             : /**
    1155             :  * Like heim_config_get_bool_default() but with a va_list list of
    1156             :  * configuration selection.
    1157             :  *
    1158             :  * Configuration value to a boolean value, where yes/true and any
    1159             :  * non-zero number means TRUE and other value is FALSE.
    1160             :  *
    1161             :  * @param context A Kerberos 5 context.
    1162             :  * @param c a configuration section, or NULL to use the section from context
    1163             :  * @param def_value the default value to return if no configuration
    1164             :  *        found in the database.
    1165             :  * @param args a va_list of arguments
    1166             :  *
    1167             :  * @return TRUE or FALSE
    1168             :  *
    1169             :  * @ingroup heim_support
    1170             :  */
    1171             : 
    1172             : int
    1173     9982040 : heim_config_vget_bool_default(heim_context context,
    1174             :                               const heim_config_section *c,
    1175             :                               int def_value,
    1176             :                               va_list args)
    1177             : {
    1178             :     const char *str;
    1179     9982040 :     str = heim_config_vget_string(context, c, args);
    1180     9982040 :     if (str == NULL)
    1181     8056956 :         return def_value;
    1182     4805600 :     return !!(strcasecmp(str, "yes") == 0 ||
    1183     1910938 :               strcasecmp(str, "true") == 0 ||
    1184      969578 :               atoi(str));
    1185             : }
    1186             : 
    1187             : /**
    1188             :  * heim_config_get_bool() will convert the configuration
    1189             :  * option value to a boolean value, where yes/true and any non-zero
    1190             :  * number means TRUE and other value is FALSE.
    1191             :  *
    1192             :  * @param context A Kerberos 5 context.
    1193             :  * @param c a configuration section, or NULL to use the section from context
    1194             :  * @param args a va_list of arguments
    1195             :  *
    1196             :  * @return TRUE or FALSE
    1197             :  *
    1198             :  * @ingroup heim_support
    1199             :  */
    1200             : 
    1201             : int
    1202           0 : heim_config_vget_bool(heim_context context,
    1203             :                       const heim_config_section *c,
    1204             :                       va_list args)
    1205             : {
    1206           0 :     return heim_config_vget_bool_default(context, c, 0, args);
    1207             : }
    1208             : 
    1209             : /**
    1210             :  * heim_config_get_bool_default() will convert the configuration
    1211             :  * option value to a boolean value, where yes/true and any non-zero
    1212             :  * number means TRUE and other value is FALSE.
    1213             :  *
    1214             :  * @param context A Kerberos 5 context.
    1215             :  * @param c a configuration section, or NULL to use the section from context
    1216             :  * @param def_value the default value to return if no configuration
    1217             :  *        found in the database.
    1218             :  * @param ... a list of names, terminated with NULL.
    1219             :  *
    1220             :  * @return TRUE or FALSE
    1221             :  *
    1222             :  * @ingroup heim_support
    1223             :  */
    1224             : 
    1225             : int
    1226           0 : heim_config_get_bool_default(heim_context context,
    1227             :                              const heim_config_section *c,
    1228             :                              int def_value,
    1229             :                              ...)
    1230             : {
    1231             :     va_list ap;
    1232             :     int ret;
    1233             : 
    1234           0 :     va_start(ap, def_value);
    1235           0 :     ret = heim_config_vget_bool_default(context, c, def_value, ap);
    1236           0 :     va_end(ap);
    1237           0 :     return ret;
    1238             : }
    1239             : 
    1240             : /**
    1241             :  * Like heim_config_get_bool() but with a va_list list of
    1242             :  * configuration selection.
    1243             :  *
    1244             :  * Configuration value to a boolean value, where yes/true and any
    1245             :  * non-zero number means TRUE and other value is FALSE.
    1246             :  *
    1247             :  * @param context A Kerberos 5 context.
    1248             :  * @param c a configuration section, or NULL to use the section from context
    1249             :  * @param ... a list of names, terminated with NULL.
    1250             :  *
    1251             :  * @return TRUE or FALSE
    1252             :  *
    1253             :  * @ingroup heim_support
    1254             :  */
    1255             : 
    1256             : int
    1257           0 : heim_config_get_bool(heim_context context,
    1258             :                      const heim_config_section *c,
    1259             :                      ...)
    1260             : {
    1261             :     va_list ap;
    1262             :     int ret;
    1263           0 :     va_start(ap, c);
    1264           0 :     ret = heim_config_vget_bool (context, c, ap);
    1265           0 :     va_end(ap);
    1266           0 :     return ret;
    1267             : }
    1268             : 
    1269             : /**
    1270             :  * Get the time from the configuration file using a relative time.
    1271             :  *
    1272             :  * Like heim_config_get_time_default() but with a va_list list of
    1273             :  * configuration selection.
    1274             :  *
    1275             :  * @param context A Kerberos 5 context.
    1276             :  * @param c a configuration section, or NULL to use the section from context
    1277             :  * @param def_value the default value to return if no configuration
    1278             :  *        found in the database.
    1279             :  * @param args a va_list of arguments
    1280             :  *
    1281             :  * @return parsed the time (or def_value on parse error)
    1282             :  *
    1283             :  * @ingroup heim_support
    1284             :  */
    1285             : 
    1286             : time_t
    1287     3401849 : heim_config_vget_time_default(heim_context context,
    1288             :                               const heim_config_section *c,
    1289             :                               int def_value,
    1290             :                               va_list args)
    1291             : {
    1292             :     const char *str;
    1293     3401849 :     time_t t = -1;
    1294             : 
    1295     3401849 :     if ((str = heim_config_vget_string(context, c, args)))
    1296           0 :         t = parse_time(str, "s");
    1297     3401849 :     return t != -1 ? t : def_value;
    1298             : }
    1299             : 
    1300             : /**
    1301             :  * Get the time from the configuration file using a relative time, for example: 1h30s
    1302             :  *
    1303             :  * @param context A Kerberos 5 context.
    1304             :  * @param c a configuration section, or NULL to use the section from context
    1305             :  * @param args a va_list of arguments
    1306             :  *
    1307             :  * @return parsed the time or -1 on error
    1308             :  *
    1309             :  * @ingroup heim_support
    1310             :  */
    1311             : 
    1312             : time_t
    1313       16202 : heim_config_vget_time(heim_context context,
    1314             :                       const heim_config_section *c,
    1315             :                       va_list args)
    1316             : {
    1317       16202 :     return heim_config_vget_time_default(context, c, -1, args);
    1318             : }
    1319             : 
    1320             : /**
    1321             :  * Get the time from the configuration file using a relative time, for example: 1h30s
    1322             :  *
    1323             :  * @param context A Kerberos 5 context.
    1324             :  * @param c a configuration section, or NULL to use the section from context
    1325             :  * @param def_value the default value to return if no configuration
    1326             :  *        found in the database.
    1327             :  * @param ... a list of names, terminated with NULL.
    1328             :  *
    1329             :  * @return parsed the time (or def_value on parse error)
    1330             :  *
    1331             :  * @ingroup heim_support
    1332             :  */
    1333             : 
    1334             : time_t
    1335      555816 : heim_config_get_time_default(heim_context context,
    1336             :                              const heim_config_section *c,
    1337             :                              int def_value,
    1338             :                              ...)
    1339             : {
    1340             :     va_list ap;
    1341             :     time_t ret;
    1342             : 
    1343      555816 :     va_start(ap, def_value);
    1344      555816 :     ret = heim_config_vget_time_default(context, c, def_value, ap);
    1345      555816 :     va_end(ap);
    1346      555816 :     return ret;
    1347             : }
    1348             : 
    1349             : /**
    1350             :  * Get the time from the configuration file using a relative time, for example: 1h30s
    1351             :  *
    1352             :  * @param context A Kerberos 5 context.
    1353             :  * @param c a configuration section, or NULL to use the section from context
    1354             :  * @param ... a list of names, terminated with NULL.
    1355             :  *
    1356             :  * @return parsed the time or -1 on error
    1357             :  *
    1358             :  * @ingroup heim_support
    1359             :  */
    1360             : 
    1361             : time_t
    1362           0 : heim_config_get_time(heim_context context,
    1363             :                      const heim_config_section *c,
    1364             :                      ...)
    1365             : {
    1366             :     va_list ap;
    1367             :     int ret;
    1368           0 :     va_start(ap, c);
    1369           0 :     ret = heim_config_vget_time(context, c, ap);
    1370           0 :     va_end(ap);
    1371           0 :     return ret;
    1372             : }
    1373             : 
    1374             : 
    1375             : int
    1376     3772946 : heim_config_vget_int_default(heim_context context,
    1377             :                              const heim_config_section *c,
    1378             :                              int def_value,
    1379             :                              va_list args)
    1380             : {
    1381             :     const char *str;
    1382     3772946 :     str = heim_config_vget_string (context, c, args);
    1383     3772946 :     if(str == NULL)
    1384     3772946 :         return def_value;
    1385             :     else {
    1386             :         char *endptr;
    1387             :         long l;
    1388           0 :         l = strtol(str, &endptr, 0);
    1389           0 :         if (endptr == str)
    1390           0 :             return def_value;
    1391             :         else
    1392           0 :             return l;
    1393             :     }
    1394             : }
    1395             : 
    1396             : int
    1397           0 : heim_config_vget_int(heim_context context,
    1398             :                      const heim_config_section *c,
    1399             :                      va_list args)
    1400             : {
    1401           0 :     return heim_config_vget_int_default(context, c, -1, args);
    1402             : }
    1403             : 
    1404             : int
    1405           0 : heim_config_get_int_default(heim_context context,
    1406             :                             const heim_config_section *c,
    1407             :                             int def_value,
    1408             :                             ...)
    1409             : {
    1410             :     va_list ap;
    1411             :     int ret;
    1412             : 
    1413           0 :     va_start(ap, def_value);
    1414           0 :     ret = heim_config_vget_int_default(context, c, def_value, ap);
    1415           0 :     va_end(ap);
    1416           0 :     return ret;
    1417             : }
    1418             : 
    1419             : int
    1420           0 : heim_config_get_int(heim_context context,
    1421             :                     const heim_config_section *c,
    1422             :                     ...)
    1423             : {
    1424             :     va_list ap;
    1425             :     int ret;
    1426           0 :     va_start(ap, c);
    1427           0 :     ret = heim_config_vget_int (context, c, ap);
    1428           0 :     va_end(ap);
    1429           0 :     return ret;
    1430             : }
    1431             : 
    1432             : #ifndef HEIMDAL_SMALLER
    1433             : heim_error_code
    1434           0 : heim_config_parse_string_multi(heim_context context,
    1435             :                                const char *string,
    1436             :                                heim_config_section **res)
    1437             : {
    1438             :     const char *str;
    1439           0 :     unsigned lineno = 0;
    1440             :     heim_error_code ret;
    1441             :     struct fileptr f;
    1442             : 
    1443           0 :     f.context = context;
    1444           0 :     f.f = NULL;
    1445           0 :     f.s = string;
    1446             : 
    1447           0 :     ret = heim_config_parse_debug(&f, res, &lineno, &str);
    1448           0 :     if (ret) {
    1449           0 :         if (ret != HEIM_ERR_CONFIG_BADFORMAT) {
    1450           0 :             ret = HEIM_ERR_CONFIG_BADFORMAT;
    1451           0 :             heim_set_error_message(context, ret, "%s:%u: %s",
    1452             :                                    "<constant>", lineno, str);
    1453             :         }
    1454           0 :         return ret;
    1455             :     }
    1456           0 :     return 0;
    1457             : }
    1458             : #endif

Generated by: LCOV version 1.13