Annotation of embedaddon/rsync/params.c, revision 1.1.1.2

1.1       misho       1: /* This modules is based on the params.c module from Samba, written by Karl Auer
                      2:    and much modifed by Christopher Hertel. */
                      3: 
                      4: /*
                      5:  * This program is free software; you can redistribute it and/or modify
                      6:  * it under the terms of the GNU General Public License as published by
                      7:  * the Free Software Foundation; either version 3 of the License, or
                      8:  * (at your option) any later version.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful,
                     11:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     12:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     13:  * GNU General Public License for more details.
                     14:  *
                     15:  * You should have received a copy of the GNU General Public License along
                     16:  * with this program; if not, visit the http://fsf.org website.
                     17:  */
                     18: 
                     19: /* -------------------------------------------------------------------------- **
                     20:  *
                     21:  * Module name: params
                     22:  *
                     23:  * -------------------------------------------------------------------------- **
                     24:  *
                     25:  *  This module performs lexical analysis and initial parsing of a
                     26:  *  Windows-like parameter file.  It recognizes and handles four token
                     27:  *  types:  section-name, parameter-name, parameter-value, and
                     28:  *  end-of-file.  Comments and line continuation are handled
                     29:  *  internally.
                     30:  *
                     31:  *  The entry point to the module is function pm_process().  This
                     32:  *  function opens the source file, calls the Parse() function to parse
                     33:  *  the input, and then closes the file when either the EOF is reached
                     34:  *  or a fatal error is encountered.
                     35:  *
                     36:  *  A sample parameter file might look like this:
                     37:  *
                     38:  *  [section one]
                     39:  *  parameter one = value string
                     40:  *  parameter two = another value
                     41:  *  [section two]
                     42:  *  new parameter = some value or t'other
                     43:  *
                     44:  *  The parameter file is divided into sections by section headers:
                     45:  *  section names enclosed in square brackets (eg. [section one]).
                     46:  *  Each section contains parameter lines, each of which consist of a
                     47:  *  parameter name and value delimited by an equal sign.  Roughly, the
                     48:  *  syntax is:
                     49:  *
                     50:  *    <file>            :==  { <section> } EOF
                     51:  *
                     52:  *    <section>         :==  <section header> { <parameter line> }
                     53:  *
                     54:  *    <section header>  :==  '[' NAME ']'
                     55:  *
                     56:  *    <parameter line>  :==  NAME '=' VALUE '\n'
                     57:  *
                     58:  *  Blank lines and comment lines are ignored.  Comment lines are lines
                     59:  *  beginning with either a semicolon (';') or a pound sign ('#').
                     60:  *
                     61:  *  All whitespace in section names and parameter names is compressed
                     62:  *  to single spaces.  Leading and trailing whitespace is stipped from
                     63:  *  both names and values.
                     64:  *
                     65:  *  Only the first equals sign in a parameter line is significant.
                     66:  *  Parameter values may contain equals signs, square brackets and
                     67:  *  semicolons.  Internal whitespace is retained in parameter values,
                     68:  *  with the exception of the '\r' character, which is stripped for
                     69:  *  historic reasons.  Parameter names may not start with a left square
                     70:  *  bracket, an equal sign, a pound sign, or a semicolon, because these
                     71:  *  are used to identify other tokens.
                     72:  *
                     73:  * -------------------------------------------------------------------------- **
                     74:  */
                     75: 
                     76: #include "rsync.h"
                     77: #include "ifuncs.h"
1.1.1.2 ! misho      78: #include "itypes.h"
1.1       misho      79: 
                     80: /* -------------------------------------------------------------------------- **
                     81:  * Constants...
                     82:  */
                     83: 
                     84: #define BUFR_INC 1024
                     85: 
                     86: 
                     87: /* -------------------------------------------------------------------------- **
                     88:  * Variables...
                     89:  *
                     90:  *  bufr        - pointer to a global buffer.  This is probably a kludge,
                     91:  *                but it was the nicest kludge I could think of (for now).
                     92:  *  bSize       - The size of the global buffer <bufr>.
                     93:  */
                     94: 
                     95: static char *bufr  = NULL;
                     96: static int   bSize = 0;
1.1.1.2 ! misho      97: static BOOL  (*the_sfunc)(char *);
        !            98: static BOOL  (*the_pfunc)(char *, char *);
1.1       misho      99: 
                    100: /* -------------------------------------------------------------------------- **
                    101:  * Functions...
                    102:  */
                    103: 
                    104: static int EatWhitespace( FILE *InFile )
                    105:   /* ------------------------------------------------------------------------ **
                    106:    * Scan past whitespace (see ctype(3C)) and return the first non-whitespace
                    107:    * character, or newline, or EOF.
                    108:    *
                    109:    *  Input:  InFile  - Input source.
                    110:    *
                    111:    *  Output: The next non-whitespace character in the input stream.
                    112:    *
                    113:    *  Notes:  Because the config files use a line-oriented grammar, we
                    114:    *          explicitly exclude the newline character from the list of
                    115:    *          whitespace characters.
                    116:    *        - Note that both EOF (-1) and the nul character ('\0') are
                    117:    *          considered end-of-file markers.
                    118:    *
                    119:    * ------------------------------------------------------------------------ **
                    120:    */
                    121:   {
                    122:   int c;
                    123: 
                    124:   for( c = getc( InFile ); isspace( c ) && ('\n' != c); c = getc( InFile ) )
                    125:     ;
                    126:   return( c );
                    127:   } /* EatWhitespace */
                    128: 
                    129: static int EatComment( FILE *InFile )
                    130:   /* ------------------------------------------------------------------------ **
                    131:    * Scan to the end of a comment.
                    132:    *
                    133:    *  Input:  InFile  - Input source.
                    134:    *
                    135:    *  Output: The character that marks the end of the comment.  Normally,
                    136:    *          this will be a newline, but it *might* be an EOF.
                    137:    *
                    138:    *  Notes:  Because the config files use a line-oriented grammar, we
                    139:    *          explicitly exclude the newline character from the list of
                    140:    *          whitespace characters.
                    141:    *        - Note that both EOF (-1) and the nul character ('\0') are
                    142:    *          considered end-of-file markers.
                    143:    *
                    144:    * ------------------------------------------------------------------------ **
                    145:    */
                    146:   {
                    147:   int c;
                    148: 
                    149:   for( c = getc( InFile ); ('\n'!=c) && (EOF!=c) && (c>0); c = getc( InFile ) )
                    150:     ;
                    151:   return( c );
                    152:   } /* EatComment */
                    153: 
                    154: static int Continuation( char *line, int pos )
                    155:   /* ------------------------------------------------------------------------ **
                    156:    * Scan backards within a string to discover if the last non-whitespace
                    157:    * character is a line-continuation character ('\\').
                    158:    *
                    159:    *  Input:  line  - A pointer to a buffer containing the string to be
                    160:    *                  scanned.
                    161:    *          pos   - This is taken to be the offset of the end of the
                    162:    *                  string.  This position is *not* scanned.
                    163:    *
                    164:    *  Output: The offset of the '\\' character if it was found, or -1 to
                    165:    *          indicate that it was not.
                    166:    *
                    167:    * ------------------------------------------------------------------------ **
                    168:    */
                    169:   {
                    170:   pos--;
                    171:   while( pos >= 0 && isSpace(line + pos) )
                    172:      pos--;
                    173: 
                    174:   return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 );
                    175:   } /* Continuation */
                    176: 
                    177: 
                    178: static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
                    179:   /* ------------------------------------------------------------------------ **
                    180:    * Scan a section name, and pass the name to function sfunc().
                    181:    *
                    182:    *  Input:  InFile  - Input source.
                    183:    *          sfunc   - Pointer to the function to be called if the section
                    184:    *                    name is successfully read.
                    185:    *
                    186:    *  Output: True if the section name was read and True was returned from
                    187:    *          <sfunc>.  False if <sfunc> failed or if a lexical error was
                    188:    *          encountered.
                    189:    *
                    190:    * ------------------------------------------------------------------------ **
                    191:    */
                    192:   {
                    193:   int   c;
                    194:   int   i;
                    195:   int   end;
                    196:   char *func  = "params.c:Section() -";
                    197: 
                    198:   i = 0;      /* <i> is the offset of the next free byte in bufr[] and  */
                    199:   end = 0;    /* <end> is the current "end of string" offset.  In most  */
                    200:               /* cases these will be the same, but if the last          */
                    201:               /* character written to bufr[] is a space, then <end>     */
                    202:               /* will be one less than <i>.                             */
                    203: 
                    204:   c = EatWhitespace( InFile );    /* We've already got the '['.  Scan */
                    205:                                   /* past initial white space.        */
                    206: 
                    207:   while( (EOF != c) && (c > 0) )
                    208:     {
                    209: 
                    210:     /* Check that the buffer is big enough for the next character. */
                    211:     if( i > (bSize - 2) )
                    212:       {
                    213:       bSize += BUFR_INC;
                    214:       bufr   = realloc_array( bufr, char, bSize );
                    215:       if( NULL == bufr )
                    216:         {
                    217:         rprintf(FLOG, "%s Memory re-allocation failure.", func);
                    218:         return( False );
                    219:         }
                    220:       }
                    221: 
                    222:     /* Handle a single character. */
                    223:     switch( c )
                    224:       {
                    225:       case ']':                       /* Found the closing bracket.         */
                    226:         bufr[end] = '\0';
                    227:         if( 0 == end )                  /* Don't allow an empty name.       */
                    228:           {
1.1.1.2 ! misho     229:           rprintf(FLOG, "%s Empty section name in config file.\n", func );
1.1       misho     230:           return( False );
                    231:           }
                    232:         if( !sfunc( bufr ) )            /* Got a valid name.  Deal with it. */
                    233:           return( False );
                    234:         (void)EatComment( InFile );     /* Finish off the line.             */
                    235:         return( True );
                    236: 
                    237:       case '\n':                      /* Got newline before closing ']'.    */
                    238:         i = Continuation( bufr, i );    /* Check for line continuation.     */
                    239:         if( i < 0 )
                    240:           {
                    241:           bufr[end] = '\0';
1.1.1.2 ! misho     242:           rprintf(FLOG, "%s Badly formed line in config file: %s\n",
1.1       misho     243:                    func, bufr );
                    244:           return( False );
                    245:           }
                    246:         end = ( (i > 0) && (' ' == bufr[i - 1]) ) ? (i - 1) : (i);
                    247:         c = getc( InFile );             /* Continue with next line.         */
                    248:         break;
                    249: 
                    250:       default:                        /* All else are a valid name chars.   */
                    251:         if( isspace( c ) )              /* One space per whitespace region. */
                    252:           {
                    253:           bufr[end] = ' ';
                    254:           i = end + 1;
                    255:           c = EatWhitespace( InFile );
                    256:           }
                    257:         else                            /* All others copy verbatim.        */
                    258:           {
                    259:           bufr[i++] = c;
                    260:           end = i;
                    261:           c = getc( InFile );
                    262:           }
                    263:       }
                    264:     }
                    265: 
                    266:   /* We arrive here if we've met the EOF before the closing bracket. */
1.1.1.2 ! misho     267:   rprintf(FLOG, "%s Unexpected EOF in the config file: %s\n", func, bufr );
1.1       misho     268:   return( False );
                    269:   } /* Section */
                    270: 
                    271: static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
                    272:   /* ------------------------------------------------------------------------ **
                    273:    * Scan a parameter name and value, and pass these two fields to pfunc().
                    274:    *
                    275:    *  Input:  InFile  - The input source.
                    276:    *          pfunc   - A pointer to the function that will be called to
                    277:    *                    process the parameter, once it has been scanned.
                    278:    *          c       - The first character of the parameter name, which
                    279:    *                    would have been read by Parse().  Unlike a comment
                    280:    *                    line or a section header, there is no lead-in
                    281:    *                    character that can be discarded.
                    282:    *
                    283:    *  Output: True if the parameter name and value were scanned and processed
                    284:    *          successfully, else False.
                    285:    *
                    286:    *  Notes:  This function is in two parts.  The first loop scans the
                    287:    *          parameter name.  Internal whitespace is compressed, and an
                    288:    *          equal sign (=) terminates the token.  Leading and trailing
                    289:    *          whitespace is discarded.  The second loop scans the parameter
                    290:    *          value.  When both have been successfully identified, they are
                    291:    *          passed to pfunc() for processing.
                    292:    *
                    293:    * ------------------------------------------------------------------------ **
                    294:    */
                    295:   {
                    296:   int   i       = 0;    /* Position within bufr. */
                    297:   int   end     = 0;    /* bufr[end] is current end-of-string. */
                    298:   int   vstart  = 0;    /* Starting position of the parameter value. */
                    299:   char *func    = "params.c:Parameter() -";
                    300: 
                    301:   /* Read the parameter name. */
                    302:   while( 0 == vstart )  /* Loop until we've found the start of the value. */
                    303:     {
                    304: 
                    305:     if( i > (bSize - 2) )       /* Ensure there's space for next char.    */
                    306:       {
                    307:       bSize += BUFR_INC;
                    308:       bufr   = realloc_array( bufr, char, bSize );
                    309:       if( NULL == bufr )
                    310:         {
                    311:         rprintf(FLOG, "%s Memory re-allocation failure.", func) ;
                    312:         return( False );
                    313:         }
                    314:       }
                    315: 
                    316:     switch( c )
                    317:       {
                    318:       case '=':                 /* Equal sign marks end of param name. */
                    319:         if( 0 == end )              /* Don't allow an empty name.      */
                    320:           {
1.1.1.2 ! misho     321:           rprintf(FLOG, "%s Invalid parameter name in config file.\n", func );
1.1       misho     322:           return( False );
                    323:           }
                    324:         bufr[end++] = '\0';         /* Mark end of string & advance.   */
1.1.1.2 ! misho     325:         i = vstart = end;           /* New string starts here.         */
        !           326:         c = EatWhitespace(InFile);
1.1       misho     327:         break;
                    328: 
                    329:       case '\n':                /* Find continuation char, else error. */
                    330:         i = Continuation( bufr, i );
                    331:         if( i < 0 )
                    332:           {
                    333:           bufr[end] = '\0';
1.1.1.2 ! misho     334:           rprintf(FLOG, "%s Ignoring badly formed line in config file: %s\n",
1.1       misho     335:                    func, bufr );
                    336:           return( True );
                    337:           }
                    338:         end = ( (i > 0) && (' ' == bufr[i - 1]) ) ? (i - 1) : (i);
                    339:         c = getc( InFile );       /* Read past eoln.                   */
                    340:         break;
                    341: 
                    342:       case '\0':                /* Shouldn't have EOF within param name. */
                    343:       case EOF:
                    344:         bufr[i] = '\0';
                    345:         rprintf(FLOG, "%s Unexpected end-of-file at: %s\n", func, bufr );
                    346:         return( True );
                    347: 
1.1.1.2 ! misho     348:       case ' ':
        !           349:       case '\t':
        !           350:         /* A directive divides at the first space or tab. */
        !           351:         if (*bufr == '&') {
        !           352:           bufr[end++] = '\0';
        !           353:           i = vstart = end;
        !           354:           c = EatWhitespace(InFile);
        !           355:           if (c == '=')
        !           356:             c = EatWhitespace(InFile);
        !           357:           break;
        !           358:         }
        !           359:         /* FALL THROUGH */
        !           360: 
1.1       misho     361:       default:
                    362:         if( isspace( c ) )     /* One ' ' per whitespace region.       */
                    363:           {
                    364:           bufr[end] = ' ';
                    365:           i = end + 1;
                    366:           c = EatWhitespace( InFile );
                    367:           }
                    368:         else                   /* All others verbatim.                 */
                    369:           {
                    370:           bufr[i++] = c;
                    371:           end = i;
                    372:           c = getc( InFile );
                    373:           }
                    374:       }
                    375:     }
                    376: 
                    377:   /* Now parse the value. */
                    378:   while( (EOF !=c) && (c > 0) )
                    379:     {
                    380: 
                    381:     if( i > (bSize - 2) )       /* Make sure there's enough room. */
                    382:       {
                    383:       bSize += BUFR_INC;
                    384:       bufr   = realloc_array( bufr, char, bSize );
                    385:       if( NULL == bufr )
                    386:         {
                    387:         rprintf(FLOG, "%s Memory re-allocation failure.", func) ;
                    388:         return( False );
                    389:         }
                    390:       }
                    391: 
                    392:     switch( c )
                    393:       {
                    394:       case '\r':              /* Explicitly remove '\r' because the older */
                    395:         c = getc( InFile );   /* version called fgets_slash() which also  */
                    396:         break;                /* removes them.                            */
                    397: 
                    398:       case '\n':              /* Marks end of value unless there's a '\'. */
                    399:         i = Continuation( bufr, i );
                    400:         if( i < 0 )
                    401:           c = 0;
                    402:         else
                    403:           {
                    404:           for( end = i; end >= 0 && isSpace(bufr + end); end-- )
                    405:             ;
                    406:           c = getc( InFile );
                    407:           }
                    408:         break;
                    409: 
                    410:       default:               /* All others verbatim.  Note that spaces do */
                    411:         bufr[i++] = c;       /* not advance <end>.  This allows trimming  */
                    412:         if( !isspace( c ) )  /* of whitespace at the end of the line.     */
                    413:           end = i;
                    414:         c = getc( InFile );
                    415:         break;
                    416:       }
                    417:     }
                    418:   bufr[end] = '\0';          /* End of value. */
                    419: 
                    420:   return( pfunc( bufr, &bufr[vstart] ) );   /* Pass name & value to pfunc().  */
                    421:   } /* Parameter */
                    422: 
1.1.1.2 ! misho     423: static int name_cmp(const void *n1, const void *n2)
        !           424: {
        !           425:     return strcmp(*(char * const *)n1, *(char * const *)n2);
        !           426: }
        !           427: 
        !           428: static int include_config(char *include, int manage_globals)
        !           429: {
        !           430:     STRUCT_STAT sb;
        !           431:     char *match = manage_globals ? "*.conf" : "*.inc";
        !           432:     int ret;
        !           433: 
        !           434:     if (do_stat(include, &sb) < 0) {
        !           435:        rsyserr(FLOG, errno, "unable to stat config file \"%s\"", include);
        !           436:        return 0;
        !           437:     }
        !           438: 
        !           439:     if (S_ISREG(sb.st_mode)) {
        !           440:        if (manage_globals && the_sfunc)
        !           441:            the_sfunc("]push");
        !           442:        ret = pm_process(include, the_sfunc, the_pfunc);
        !           443:        if (manage_globals && the_sfunc)
        !           444:            the_sfunc("]pop");
        !           445:     } else if (S_ISDIR(sb.st_mode)) {
        !           446:        char buf[MAXPATHLEN], **bpp;
        !           447:        item_list conf_list;
        !           448:        struct dirent *di;
        !           449:        size_t j;
        !           450:        DIR *d;
        !           451: 
        !           452:        if (!(d = opendir(include))) {
        !           453:            rsyserr(FLOG, errno, "unable to open config dir \"%s\"", include);
        !           454:            return 0;
        !           455:        }
        !           456: 
        !           457:        memset(&conf_list, 0, sizeof conf_list);
        !           458: 
        !           459:        while ((di = readdir(d)) != NULL) {
        !           460:            char *dname = d_name(di);
        !           461:            if (!wildmatch(match, dname))
        !           462:                continue;
        !           463:            bpp = EXPAND_ITEM_LIST(&conf_list, char *, 32);
        !           464:            pathjoin(buf, sizeof buf, include, dname);
        !           465:            *bpp = strdup(buf);
        !           466:        }
        !           467:        closedir(d);
        !           468: 
        !           469:        if (!(bpp = conf_list.items))
        !           470:            return 1;
        !           471: 
        !           472:        if (conf_list.count > 1)
        !           473:            qsort(bpp, conf_list.count, sizeof (char *), name_cmp);
        !           474: 
        !           475:        for (j = 0, ret = 1; j < conf_list.count; j++) {
        !           476:            if (manage_globals && the_sfunc)
        !           477:                the_sfunc(j == 0 ? "]push" : "]reset");
        !           478:            if ((ret = pm_process(bpp[j], the_sfunc, the_pfunc)) != 1)
        !           479:                break;
        !           480:        }
        !           481: 
        !           482:        if (manage_globals && the_sfunc)
        !           483:            the_sfunc("]pop");
        !           484: 
        !           485:        for (j = 0; j < conf_list.count; j++)
        !           486:            free(bpp[j]);
        !           487:        free(bpp);
        !           488:     } else
        !           489:        ret = 0;
        !           490: 
        !           491:     return ret;
        !           492: }
        !           493: 
        !           494: static int parse_directives(char *name, char *val)
        !           495: {
        !           496:     if (strcasecmp(name, "&include") == 0)
        !           497:         return include_config(val, 1);
        !           498:     if (strcasecmp(name, "&merge") == 0)
        !           499:         return include_config(val, 0);
        !           500:     rprintf(FLOG, "Unknown directive: %s.\n", name);
        !           501:     return 0;
        !           502: }
        !           503: 
        !           504: static int Parse( FILE *InFile,
1.1       misho     505:                    BOOL (*sfunc)(char *),
                    506:                    BOOL (*pfunc)(char *, char *) )
                    507:   /* ------------------------------------------------------------------------ **
                    508:    * Scan & parse the input.
                    509:    *
                    510:    *  Input:  InFile  - Input source.
                    511:    *          sfunc   - Function to be called when a section name is scanned.
                    512:    *                    See Section().
                    513:    *          pfunc   - Function to be called when a parameter is scanned.
                    514:    *                    See Parameter().
                    515:    *
1.1.1.2 ! misho     516:    *  Output: 1 if the file was successfully scanned, 2 if the file was
        !           517:    *  scanned until a section header with no section function, else 0.
1.1       misho     518:    *
                    519:    *  Notes:  The input can be viewed in terms of 'lines'.  There are four
                    520:    *          types of lines:
                    521:    *            Blank      - May contain whitespace, otherwise empty.
                    522:    *            Comment    - First non-whitespace character is a ';' or '#'.
                    523:    *                         The remainder of the line is ignored.
                    524:    *            Section    - First non-whitespace character is a '['.
                    525:    *            Parameter  - The default case.
1.1.1.2 ! misho     526:    *
1.1       misho     527:    * ------------------------------------------------------------------------ **
                    528:    */
                    529:   {
                    530:   int    c;
                    531: 
                    532:   c = EatWhitespace( InFile );
                    533:   while( (EOF != c) && (c > 0) )
                    534:     {
                    535:     switch( c )
                    536:       {
                    537:       case '\n':                        /* Blank line. */
                    538:         c = EatWhitespace( InFile );
                    539:         break;
                    540: 
                    541:       case ';':                         /* Comment line. */
                    542:       case '#':
                    543:         c = EatComment( InFile );
                    544:         break;
                    545: 
                    546:       case '[':                         /* Section Header. */
1.1.1.2 ! misho     547:         if (!sfunc)
        !           548:           return 2;
        !           549:         if( !Section( InFile, sfunc ) )
        !           550:           return 0;
        !           551:         c = EatWhitespace( InFile );
        !           552:         break;
1.1       misho     553: 
                    554:       case '\\':                        /* Bogus backslash. */
                    555:         c = EatWhitespace( InFile );
                    556:         break;
                    557: 
1.1.1.2 ! misho     558:       case '&':                         /* Handle directives */
        !           559:         the_sfunc = sfunc;
        !           560:         the_pfunc = pfunc;
        !           561:         c = Parameter( InFile, parse_directives, c );
        !           562:         if (c != 1)
        !           563:           return c;
        !           564:         c = EatWhitespace( InFile );
        !           565:         break;
        !           566: 
1.1       misho     567:       default:                          /* Parameter line. */
                    568:         if( !Parameter( InFile, pfunc, c ) )
1.1.1.2 ! misho     569:           return 0;
1.1       misho     570:         c = EatWhitespace( InFile );
                    571:         break;
                    572:       }
                    573:     }
1.1.1.2 ! misho     574:   return 1;
1.1       misho     575:   } /* Parse */
                    576: 
                    577: static FILE *OpenConfFile( char *FileName )
                    578:   /* ------------------------------------------------------------------------ **
1.1.1.2 ! misho     579:    * Open a config file.
1.1       misho     580:    *
                    581:    *  Input:  FileName  - The pathname of the config file to be opened.
                    582:    *
                    583:    *  Output: A pointer of type (FILE *) to the opened file, or NULL if the
                    584:    *          file could not be opened.
                    585:    *
                    586:    * ------------------------------------------------------------------------ **
                    587:    */
                    588:   {
                    589:   FILE *OpenedFile;
                    590:   char *func = "params.c:OpenConfFile() -";
                    591: 
                    592:   if( NULL == FileName || 0 == *FileName )
                    593:     {
1.1.1.2 ! misho     594:     rprintf(FLOG, "%s No config filename specified.\n", func);
1.1       misho     595:     return( NULL );
                    596:     }
                    597: 
                    598:   OpenedFile = fopen( FileName, "r" );
                    599:   if( NULL == OpenedFile )
                    600:     {
1.1.1.2 ! misho     601:     rsyserr(FLOG, errno, "unable to open config file \"%s\"",
1.1       misho     602:            FileName);
                    603:     }
                    604: 
                    605:   return( OpenedFile );
                    606:   } /* OpenConfFile */
                    607: 
1.1.1.2 ! misho     608: int pm_process( char *FileName,
1.1       misho     609:                  BOOL (*sfunc)(char *),
                    610:                  BOOL (*pfunc)(char *, char *) )
                    611:   /* ------------------------------------------------------------------------ **
                    612:    * Process the named parameter file.
                    613:    *
                    614:    *  Input:  FileName  - The pathname of the parameter file to be opened.
                    615:    *          sfunc     - A pointer to a function that will be called when
                    616:    *                      a section name is discovered.
                    617:    *          pfunc     - A pointer to a function that will be called when
                    618:    *                      a parameter name and value are discovered.
                    619:    *
1.1.1.2 ! misho     620:    *  Output: 1 if the file was successfully parsed, 2 if parsing ended at a
        !           621:    *  section header w/o a section function, else 0.
1.1       misho     622:    *
                    623:    * ------------------------------------------------------------------------ **
                    624:    */
                    625:   {
                    626:   int   result;
                    627:   FILE *InFile;
                    628:   char *func = "params.c:pm_process() -";
                    629: 
                    630:   InFile = OpenConfFile( FileName );          /* Open the config file. */
                    631:   if( NULL == InFile )
                    632:     return( False );
                    633: 
                    634:   if( NULL != bufr )                          /* If we already have a buffer */
                    635:     result = Parse( InFile, sfunc, pfunc );   /* (recursive call), then just */
                    636:                                               /* use it.                     */
                    637: 
                    638:   else                                        /* If we don't have a buffer   */
                    639:     {                                         /* allocate one, then parse,   */
                    640:     bSize = BUFR_INC;                         /* then free.                  */
                    641:     bufr = new_array( char, bSize );
                    642:     if( NULL == bufr )
                    643:       {
                    644:       rprintf(FLOG, "%s memory allocation failure.\n", func);
                    645:       fclose(InFile);
                    646:       return( False );
                    647:       }
                    648:     result = Parse( InFile, sfunc, pfunc );
                    649:     free( bufr );
                    650:     bufr  = NULL;
                    651:     bSize = 0;
                    652:     }
                    653: 
                    654:   fclose(InFile);
                    655: 
                    656:   if( !result )                               /* Generic failure. */
                    657:     {
                    658:     rprintf(FLOG, "%s Failed.  Error returned from params.c:parse().\n", func);
1.1.1.2 ! misho     659:     return 0;
1.1       misho     660:     }
                    661: 
1.1.1.2 ! misho     662:   return result;
1.1       misho     663:   } /* pm_process */
                    664: 
                    665: /* -------------------------------------------------------------------------- */
                    666: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>