LCOV - code coverage report
Current view: top level - third_party/popt - poptconfig.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 0 284 0.0 %
Date: 2024-04-21 15:09:00 Functions: 0 11 0.0 %

          Line data    Source code
       1             : /** \ingroup popt
       2             :  * \file popt/poptconfig.c
       3             :  */
       4             : 
       5             : /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
       6             :    file accompanying popt source distributions, available from 
       7             :    ftp://ftp.rpm.org/pub/rpm/dist. */
       8             : 
       9             : #include "system.h"
      10             : #include "poptint.h"
      11             : #include <sys/stat.h>
      12             : 
      13             : #if defined(HAVE_FNMATCH_H)
      14             : #include <fnmatch.h>
      15             : 
      16             : #if defined(__LCLINT__)
      17             : /*@-declundef -exportheader -incondefs -protoparammatch -redecl -type @*/
      18             : extern int fnmatch (const char *__pattern, const char *__name, int __flags)
      19             :         /*@*/;
      20             : /*@=declundef =exportheader =incondefs =protoparammatch =redecl =type @*/
      21             : #endif  /* __LCLINT__ */
      22             : #endif
      23             : 
      24             : #if defined(HAVE_GLOB_H)
      25             : #include <glob.h>
      26             : 
      27             : #if defined(__LCLINT__)
      28             : /*@-declundef -exportheader -incondefs -protoparammatch -redecl -type @*/
      29             : extern int glob (const char *__pattern, int __flags,
      30             :                 /*@null@*/ int (*__errfunc) (const char *, int),
      31             :                 /*@out@*/ glob_t *__pglob)
      32             :         /*@globals errno, fileSystem @*/
      33             :         /*@modifies *__pglob, errno, fileSystem @*/;
      34             : 
      35             : /* XXX only annotation is a white lie */
      36             : extern void globfree (/*@only@*/ glob_t *__pglob)
      37             :         /*@modifies *__pglob @*/;
      38             : 
      39             : /* XXX _GNU_SOURCE ifdef and/or retrofit is needed for portability. */
      40             : extern int glob_pattern_p (const char *__pattern, int __quote)
      41             :         /*@*/;
      42             : /*@=declundef =exportheader =incondefs =protoparammatch =redecl =type @*/
      43             : #endif  /* __LCLINT__ */
      44             : 
      45             : #if !defined(__GLIBC__)
      46             : /* Return nonzero if PATTERN contains any metacharacters.
      47             :    Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
      48             : static int
      49             : glob_pattern_p (const char * pattern, int quote)
      50             :         /*@*/
      51             : {
      52             :     const char * p;
      53             :     int open = 0;
      54             : 
      55             :     for (p = pattern; *p != '\0'; ++p)
      56             :     switch (*p) {
      57             :     case '?':
      58             :     case '*':
      59             :         return 1;
      60             :         /*@notreached@*/ /*@switchbreak@*/ break;
      61             :     case '\\':
      62             :         if (quote && p[1] != '\0')
      63             :           ++p;
      64             :         /*@switchbreak@*/ break;
      65             :     case '[':
      66             :         open = 1;
      67             :         /*@switchbreak@*/ break;
      68             :     case ']':
      69             :         if (open)
      70             :           return 1;
      71             :         /*@switchbreak@*/ break;
      72             :     }
      73             :     return 0;
      74             : }
      75             : #endif  /* !defined(__GLIBC__) */
      76             : 
      77             : /*@unchecked@*/
      78             : static int poptGlobFlags = 0;
      79             : 
      80           0 : static int poptGlob_error(/*@unused@*/ UNUSED(const char * epath),
      81             :                 /*@unused@*/ UNUSED(int eerrno))
      82             :         /*@*/
      83             : {
      84           0 :     return 1;
      85             : }
      86             : #endif  /* HAVE_GLOB_H */
      87             : 
      88             : /**
      89             :  * Return path(s) from a glob pattern.
      90             :  * @param con           context
      91             :  * @param pattern       glob pattern
      92             :  * @retval *acp         no. of paths
      93             :  * @retval *avp         array of paths
      94             :  * @return              0 on success
      95             :  */
      96           0 : static int poptGlob(/*@unused@*/ UNUSED(poptContext con), const char * pattern,
      97             :                 /*@out@*/ int * acp, /*@out@*/ const char *** avp)
      98             :         /*@modifies *acp, *avp @*/
      99             : {
     100           0 :     const char * pat = pattern;
     101           0 :     int rc = 0;         /* assume success */
     102             : 
     103             :     /* XXX skip the attention marker. */
     104           0 :     if (pat[0] == '@' && pat[1] != '(')
     105           0 :         pat++;
     106             : 
     107             : #if defined(HAVE_GLOB_H)
     108           0 :     if (glob_pattern_p(pat, 0)) {
     109           0 :         glob_t _g, *pglob = &_g;
     110             : 
     111           0 :         if (!glob(pat, poptGlobFlags, poptGlob_error, pglob)) {
     112           0 :             if (acp) {
     113           0 :                 *acp = (int) pglob->gl_pathc;
     114           0 :                 pglob->gl_pathc = 0;
     115             :             }
     116           0 :             if (avp) {
     117             : /*@-onlytrans@*/
     118           0 :                 *avp = (const char **) pglob->gl_pathv;
     119             : /*@=onlytrans@*/
     120           0 :                 pglob->gl_pathv = NULL;
     121             :             }
     122             : /*@-nullstate@*/
     123           0 :             globfree(pglob);
     124             : /*@=nullstate@*/
     125             :         } else
     126           0 :             rc = POPT_ERROR_ERRNO;
     127             :     } else
     128             : #endif  /* HAVE_GLOB_H */
     129             :     {
     130           0 :         if (acp)
     131           0 :             *acp = 1;
     132           0 :         if (avp && (*avp = calloc((size_t)(1 + 1), sizeof (**avp))) != NULL)
     133           0 :             (*avp)[0] = xstrdup(pat);
     134             :     }
     135             : 
     136           0 :     return rc;
     137             : }
     138             : 
     139             : /*@access poptContext @*/
     140             : 
     141           0 : int poptSaneFile(const char * fn)
     142             : {
     143             :     struct stat sb;
     144           0 :     uid_t uid = getuid();
     145             : 
     146           0 :     if (stat(fn, &sb) == -1)
     147           0 :         return 1;
     148           0 :     if ((uid_t)sb.st_uid != uid)
     149           0 :         return 0;
     150           0 :     if (!S_ISREG(sb.st_mode))
     151           0 :         return 0;
     152             : /*@-bitwisesigned@*/
     153           0 :     if (sb.st_mode & (S_IWGRP|S_IWOTH))
     154           0 :         return 0;
     155             : /*@=bitwisesigned@*/
     156           0 :     return 1;
     157             : }
     158             : 
     159           0 : int poptReadFile(const char * fn, char ** bp, size_t * nbp, int flags)
     160             : {
     161             :     int fdno;
     162           0 :     char * b = NULL;
     163           0 :     off_t nb = 0;
     164             :     char * s, * t, * se;
     165           0 :     int rc = POPT_ERROR_ERRNO;  /* assume failure */
     166             : 
     167           0 :     fdno = open(fn, O_RDONLY);
     168           0 :     if (fdno < 0)
     169           0 :         goto exit;
     170             : 
     171           0 :     if ((nb = lseek(fdno, 0, SEEK_END)) == (off_t)-1
     172           0 :      || lseek(fdno, 0, SEEK_SET) == (off_t)-1
     173           0 :      || (b = calloc(sizeof(*b), (size_t)nb + 1)) == NULL
     174           0 :      || read(fdno, (char *)b, (size_t)nb) != (ssize_t)nb)
     175             :     {
     176           0 :         int oerrno = errno;
     177           0 :         (void) close(fdno);
     178           0 :         errno = oerrno;
     179           0 :         goto exit;
     180             :     }
     181           0 :     if (close(fdno) == -1)
     182           0 :         goto exit;
     183           0 :     if (b == NULL) {
     184           0 :         rc = POPT_ERROR_MALLOC;
     185           0 :         goto exit;
     186             :     }
     187           0 :     rc = 0;
     188             : 
     189             :    /* Trim out escaped newlines. */
     190             : /*@-bitwisesigned@*/
     191           0 :     if (flags & POPT_READFILE_TRIMNEWLINES)
     192             : /*@=bitwisesigned@*/
     193             :     {
     194           0 :         for (t = b, s = b, se = b + nb; *s && s < se; s++) {
     195           0 :             switch (*s) {
     196           0 :             case '\\':
     197           0 :                 if (s[1] == '\n') {
     198           0 :                     s++;
     199           0 :                     continue;
     200             :                 }
     201             :                 /*@fallthrough@*/
     202             :             default:
     203           0 :                 *t++ = *s;
     204           0 :                 /*@switchbreak@*/ break;
     205             :             }
     206             :         }
     207           0 :         *t++ = '\0';
     208           0 :         nb = (off_t)(t - b);
     209             :     }
     210             : 
     211           0 : exit:
     212           0 :     if (rc != 0) {
     213             : /*@-usedef@*/
     214           0 :         if (b)
     215           0 :             free(b);
     216             : /*@=usedef@*/
     217           0 :         b = NULL;
     218           0 :         nb = 0;
     219             :     }
     220           0 :     if (bp)
     221           0 :         *bp = b;
     222             : /*@-usereleased@*/
     223           0 :     else if (b)
     224           0 :         free(b);
     225             : /*@=usereleased@*/
     226           0 :     if (nbp)
     227           0 :         *nbp = (size_t)nb;
     228             : /*@-compdef -nullstate @*/      /* XXX cannot annotate char ** correctly */
     229           0 :     return rc;
     230             : /*@=compdef =nullstate @*/
     231             : }
     232             : 
     233             : /**
     234             :  * Check for application match.
     235             :  * @param con           context
     236             :  * @param s             config application name
     237             :  * return               0 if config application matches
     238             :  */
     239           0 : static int configAppMatch(poptContext con, const char * s)
     240             :         /*@*/
     241             : {
     242           0 :     int rc = 1;
     243             : 
     244           0 :     if (con->appName == NULL)        /* XXX can't happen. */
     245           0 :         return rc;
     246             : 
     247             : #if defined(HAVE_GLOB_H) && defined(HAVE_FNMATCH_H)
     248           0 :     if (glob_pattern_p(s, 1)) {
     249             : /*@-bitwisesigned@*/
     250             :         static int flags = FNM_PATHNAME | FNM_PERIOD;
     251             : #ifdef FNM_EXTMATCH
     252           0 :         flags |= FNM_EXTMATCH;
     253             : #endif
     254             : /*@=bitwisesigned@*/
     255           0 :         rc = fnmatch(s, con->appName, flags);
     256             :     } else
     257             : #endif
     258           0 :         rc = strcmp(s, con->appName);
     259           0 :     return rc;
     260             : }
     261             : 
     262             : /*@-compmempass@*/      /* FIX: item->option.longName kept, not dependent. */
     263           0 : static int poptConfigLine(poptContext con, char * line)
     264             :         /*@globals fileSystem, internalState @*/
     265             :         /*@modifies con, fileSystem, internalState @*/
     266             : {
     267           0 :     char *b = NULL;
     268           0 :     size_t nb = 0;
     269           0 :     char * se = line;
     270             :     const char * appName;
     271             :     const char * entryType;
     272             :     const char * opt;
     273             :     struct poptItem_s item_buf;
     274           0 :     poptItem item = &item_buf;
     275             :     int i, j;
     276           0 :     int rc = POPT_ERROR_BADCONFIG;
     277             : 
     278           0 :     if (con->appName == NULL)
     279           0 :         goto exit;
     280             :     
     281           0 :     memset(item, 0, sizeof(*item));
     282             : 
     283           0 :     appName = se;
     284           0 :     while (*se != '\0' && !_isspaceptr(se)) se++;
     285           0 :     if (*se == '\0')
     286           0 :         goto exit;
     287             :     else
     288           0 :         *se++ = '\0';
     289             : 
     290           0 :     if (configAppMatch(con, appName)) goto exit;
     291             : 
     292           0 :     while (*se != '\0' && _isspaceptr(se)) se++;
     293           0 :     entryType = se;
     294           0 :     while (*se != '\0' && !_isspaceptr(se)) se++;
     295           0 :     if (*se != '\0') *se++ = '\0';
     296             : 
     297           0 :     while (*se != '\0' && _isspaceptr(se)) se++;
     298           0 :     if (*se == '\0') goto exit;
     299           0 :     opt = se;
     300           0 :     while (*se != '\0' && !_isspaceptr(se)) se++;
     301           0 :     if (opt[0] == '-' && *se == '\0') goto exit;
     302           0 :     if (*se != '\0') *se++ = '\0';
     303             : 
     304           0 :     while (*se != '\0' && _isspaceptr(se)) se++;
     305           0 :     if (opt[0] == '-' && *se == '\0') goto exit;
     306             : 
     307             : /*@-temptrans@*/ /* FIX: line alias is saved */
     308           0 :     if (opt[0] == '-' && opt[1] == '-')
     309           0 :         item->option.longName = opt + 2;
     310           0 :     else if (opt[0] == '-' && opt[2] == '\0')
     311           0 :         item->option.shortName = opt[1];
     312             :     else {
     313           0 :         const char * fn = opt;
     314             : 
     315             :         /* XXX handle globs and directories in fn? */
     316           0 :         if ((rc = poptReadFile(fn, &b, &nb, POPT_READFILE_TRIMNEWLINES)) != 0)
     317           0 :             goto exit;
     318           0 :         if (b == NULL || nb == 0)
     319           0 :             goto exit;
     320             : 
     321             :         /* Append remaining text to the interpolated file option text. */
     322           0 :         if (*se != '\0') {
     323           0 :             size_t nse = strlen(se) + 1;
     324           0 :             if ((b = realloc(b, (nb + nse))) == NULL)   /* XXX can't happen */
     325           0 :                 goto exit;
     326           0 :             (void) stpcpy( stpcpy(&b[nb-1], " "), se);
     327           0 :             nb += nse;
     328             :         }
     329           0 :         se = b;
     330             : 
     331             :         /* Use the basename of the path as the long option name. */
     332           0 :         {   const char * longName = strrchr(fn, '/');
     333           0 :             if (longName != NULL)
     334           0 :                 longName++;
     335             :             else
     336           0 :                 longName = fn;
     337           0 :             if (longName == NULL)       /* XXX can't happen. */
     338           0 :                 goto exit;
     339             :             /* Single character basenames are treated as short options. */
     340           0 :             if (longName[1] != '\0')
     341           0 :                 item->option.longName = longName;
     342             :             else
     343           0 :                 item->option.shortName = longName[0];
     344             :         }
     345             :     }
     346             : /*@=temptrans@*/
     347             : 
     348           0 :     if (poptParseArgvString(se, &item->argc, &item->argv)) goto exit;
     349             : 
     350             : /*@-modobserver@*/
     351           0 :     item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
     352           0 :     for (i = 0, j = 0; i < item->argc; i++, j++) {
     353             :         const char * f;
     354           0 :         if (!strncmp(item->argv[i], "--POPTdesc=", sizeof("--POPTdesc=")-1)) {
     355           0 :             f = item->argv[i] + sizeof("--POPTdesc=");
     356           0 :             if (f[0] == '$' && f[1] == '"') f++;
     357           0 :             item->option.descrip = f;
     358           0 :             item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
     359           0 :             j--;
     360             :         } else
     361           0 :         if (!strncmp(item->argv[i], "--POPTargs=", sizeof("--POPTargs=")-1)) {
     362           0 :             f = item->argv[i] + sizeof("--POPTargs=");
     363           0 :             if (f[0] == '$' && f[1] == '"') f++;
     364           0 :             item->option.argDescrip = f;
     365           0 :             item->option.argInfo &= ~POPT_ARGFLAG_DOC_HIDDEN;
     366           0 :             item->option.argInfo |= POPT_ARG_STRING;
     367           0 :             j--;
     368             :         } else
     369           0 :         if (j != i)
     370           0 :             item->argv[j] = item->argv[i];
     371             :     }
     372           0 :     if (j != i) {
     373           0 :         item->argv[j] = NULL;
     374           0 :         item->argc = j;
     375             :     }
     376             : /*@=modobserver@*/
     377             : 
     378             : /*@-nullstate@*/ /* FIX: item->argv[] may be NULL */
     379           0 :     if (!strcmp(entryType, "alias"))
     380           0 :         rc = poptAddItem(con, item, 0);
     381           0 :     else if (!strcmp(entryType, "exec"))
     382           0 :         rc = poptAddItem(con, item, 1);
     383             : /*@=nullstate@*/
     384           0 : exit:
     385           0 :     rc = 0;     /* XXX for now, always return success */
     386           0 :     if (b)
     387           0 :         free(b);
     388           0 :     return rc;
     389             : }
     390             : /*@=compmempass@*/
     391             : 
     392           0 : int poptReadConfigFile(poptContext con, const char * fn)
     393             : {
     394           0 :     char * b = NULL, *be;
     395           0 :     size_t nb = 0;
     396             :     const char *se;
     397             :     char *t, *te;
     398             :     int rc;
     399             :     int xx;
     400             : 
     401           0 :     if ((rc = poptReadFile(fn, &b, &nb, POPT_READFILE_TRIMNEWLINES)) != 0)
     402           0 :         return (errno == ENOENT ? 0 : rc);
     403           0 :     if (b == NULL || nb == 0)
     404           0 :         return POPT_ERROR_BADCONFIG;
     405             : 
     406           0 :     if ((t = malloc(nb + 1)) == NULL)
     407           0 :         goto exit;
     408           0 :     te = t;
     409             : 
     410           0 :     be = (b + nb);
     411           0 :     for (se = b; se < be; se++) {
     412           0 :         switch (*se) {
     413           0 :           case '\n':
     414           0 :             *te = '\0';
     415           0 :             te = t;
     416           0 :             while (*te && _isspaceptr(te)) te++;
     417           0 :             if (*te && *te != '#')
     418           0 :                 xx = poptConfigLine(con, te);
     419           0 :             /*@switchbreak@*/ break;
     420             : /*@-usedef@*/   /* XXX *se may be uninitialized */
     421           0 :           case '\\':
     422           0 :             *te = *se++;
     423             :             /* \ at the end of a line does not insert a \n */
     424           0 :             if (se < be && *se != '\n') {
     425           0 :                 te++;
     426           0 :                 *te++ = *se;
     427             :             }
     428           0 :             /*@switchbreak@*/ break;
     429           0 :           default:
     430           0 :             *te++ = *se;
     431           0 :             /*@switchbreak@*/ break;
     432             : /*@=usedef@*/
     433             :         }
     434             :     }
     435             : 
     436           0 :     free(t);
     437           0 :     rc = 0;
     438             : 
     439           0 : exit:
     440           0 :     if (b)
     441           0 :         free(b);
     442           0 :     return rc;
     443             : }
     444             : 
     445           0 : int poptReadConfigFiles(poptContext con, const char * paths)
     446             : {
     447           0 :     char * buf = (paths ? xstrdup(paths) : NULL);
     448             :     const char * p;
     449             :     char * pe;
     450           0 :     int rc = 0;         /* assume success */
     451             : 
     452           0 :     for (p = buf; p != NULL && *p != '\0'; p = pe) {
     453           0 :         const char ** av = NULL;
     454           0 :         int ac = 0;
     455             :         int i;
     456             :         int xx;
     457             : 
     458             :         /* locate start of next path element */
     459           0 :         pe = strchr(p, ':');
     460           0 :         if (pe != NULL && *pe == ':')
     461           0 :             *pe++ = '\0';
     462             :         else
     463           0 :             pe = (char *) (p + strlen(p));
     464             : 
     465           0 :         xx = poptGlob(con, p, &ac, &av);
     466             : 
     467             :         /* work-off each resulting file from the path element */
     468           0 :         for (i = 0; i < ac; i++) {
     469           0 :             const char * fn = av[i];
     470           0 :             if (av[i] == NULL)  /* XXX can't happen */
     471           0 :                 /*@innercontinue@*/ continue;
     472             :             /* XXX should '@' attention be pushed into poptReadConfigFile? */
     473           0 :             if (p[0] == '@' && p[1] != '(') {
     474           0 :                 if (fn[0] == '@' && fn[1] != '(')
     475           0 :                     fn++;
     476           0 :                 xx = poptSaneFile(fn);
     477           0 :                 if (!xx && rc == 0)
     478           0 :                     rc = POPT_ERROR_BADCONFIG;
     479           0 :                 /*@innercontinue@*/ continue;
     480             :             }
     481           0 :             xx = poptReadConfigFile(con, fn);
     482           0 :             if (xx && rc == 0)
     483           0 :                 rc = xx;
     484           0 :             free((void *)av[i]);
     485           0 :             av[i] = NULL;
     486             :         }
     487           0 :         free(av);
     488           0 :         av = NULL;
     489             :     }
     490             : 
     491             : /*@-usedef@*/
     492           0 :     if (buf)
     493           0 :         free(buf);
     494             : /*@=usedef@*/
     495             : 
     496           0 :     return rc;
     497             : }
     498             : 
     499           0 : int poptReadDefaultConfig(poptContext con, /*@unused@*/ UNUSED(int useEnv))
     500             : {
     501             :     static const char _popt_sysconfdir[] = POPT_SYSCONFDIR "/popt";
     502             :     static const char _popt_etc[] = "/etc/popt";
     503             :     char * home;
     504             :     struct stat sb;
     505           0 :     int rc = 0;         /* assume success */
     506             : 
     507           0 :     if (con->appName == NULL) goto exit;
     508             : 
     509           0 :     if (strcmp(_popt_sysconfdir, _popt_etc)) {
     510           0 :         rc = poptReadConfigFile(con, _popt_sysconfdir);
     511           0 :         if (rc) goto exit;
     512             :     }
     513             : 
     514           0 :     rc = poptReadConfigFile(con, _popt_etc);
     515           0 :     if (rc) goto exit;
     516             : 
     517             : #if defined(HAVE_GLOB_H)
     518           0 :     if (!stat("/etc/popt.d", &sb) && S_ISDIR(sb.st_mode)) {
     519           0 :         const char ** av = NULL;
     520           0 :         int ac = 0;
     521             :         int i;
     522             : 
     523           0 :         if ((rc = poptGlob(con, "/etc/popt.d/*", &ac, &av)) == 0) {
     524           0 :             for (i = 0; rc == 0 && i < ac; i++) {
     525           0 :                 const char * fn = av[i];
     526           0 :                 if (fn == NULL || strstr(fn, ".rpmnew") || strstr(fn, ".rpmsave"))
     527           0 :                     continue;
     528           0 :                 if (!stat(fn, &sb)) {
     529           0 :                     if (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode))
     530           0 :                         continue;
     531             :                 }
     532           0 :                 rc = poptReadConfigFile(con, fn);
     533           0 :                 free((void *)av[i]);
     534           0 :                 av[i] = NULL;
     535             :             }
     536           0 :             free(av);
     537           0 :             av = NULL;
     538             :         }
     539             :     }
     540           0 :     if (rc) goto exit;
     541             : #endif
     542             : 
     543           0 :     if ((home = getenv("HOME"))) {
     544           0 :         char * fn = malloc(strlen(home) + 20);
     545           0 :         if (fn != NULL) {
     546           0 :             (void) stpcpy(stpcpy(fn, home), "/.popt");
     547           0 :             rc = poptReadConfigFile(con, fn);
     548           0 :             free(fn);
     549             :         } else
     550           0 :             rc = POPT_ERROR_ERRNO;
     551           0 :         if (rc) goto exit;
     552             :     }
     553             : 
     554           0 : exit:
     555           0 :     return rc;
     556             : }
     557             : 
     558             : poptContext
     559           0 : poptFini(poptContext con)
     560             : {
     561           0 :     return poptFreeContext(con);
     562             : }
     563             : 
     564             : poptContext
     565           0 : poptInit(int argc, const char ** argv,
     566             :                 const struct poptOption * options, const char * configPaths)
     567             : {
     568           0 :     poptContext con = NULL;
     569             :     const char * argv0;
     570             : 
     571           0 :     if (argv == NULL || argv[0] == NULL || options == NULL)
     572           0 :         return con;
     573             : 
     574           0 :     if ((argv0 = strrchr(argv[0], '/')) != NULL) argv0++;
     575           0 :     else argv0 = argv[0];
     576             : 
     577           0 :     con = poptGetContext(argv0, argc, (const char **)argv, options, 0);
     578           0 :     if (con != NULL&& poptReadConfigFiles(con, configPaths))
     579           0 :         con = poptFini(con);
     580             : 
     581           0 :     return con;
     582             : }

Generated by: LCOV version 1.14