File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / params.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 14 07:51:14 2013 UTC (10 years, 8 months ago) by misho
Branches: rsync, MAIN
CVS tags: v3_1_2p5, RSYNC3_1_0, HEAD
v 3.1.0

    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"
   78: #include "itypes.h"
   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;
   97: static BOOL  (*the_sfunc)(char *);
   98: static BOOL  (*the_pfunc)(char *, char *);
   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:           {
  229:           rprintf(FLOG, "%s Empty section name in config file.\n", func );
  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';
  242:           rprintf(FLOG, "%s Badly formed line in config file: %s\n",
  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. */
  267:   rprintf(FLOG, "%s Unexpected EOF in the config file: %s\n", func, bufr );
  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:           {
  321:           rprintf(FLOG, "%s Invalid parameter name in config file.\n", func );
  322:           return( False );
  323:           }
  324:         bufr[end++] = '\0';         /* Mark end of string & advance.   */
  325:         i = vstart = end;           /* New string starts here.         */
  326:         c = EatWhitespace(InFile);
  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';
  334:           rprintf(FLOG, "%s Ignoring badly formed line in config file: %s\n",
  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: 
  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: 
  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: 
  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,
  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:    *
  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.
  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.
  526:    *
  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. */
  547:         if (!sfunc)
  548:           return 2;
  549:         if( !Section( InFile, sfunc ) )
  550:           return 0;
  551:         c = EatWhitespace( InFile );
  552:         break;
  553: 
  554:       case '\\':                        /* Bogus backslash. */
  555:         c = EatWhitespace( InFile );
  556:         break;
  557: 
  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: 
  567:       default:                          /* Parameter line. */
  568:         if( !Parameter( InFile, pfunc, c ) )
  569:           return 0;
  570:         c = EatWhitespace( InFile );
  571:         break;
  572:       }
  573:     }
  574:   return 1;
  575:   } /* Parse */
  576: 
  577: static FILE *OpenConfFile( char *FileName )
  578:   /* ------------------------------------------------------------------------ **
  579:    * Open a config file.
  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:     {
  594:     rprintf(FLOG, "%s No config filename specified.\n", func);
  595:     return( NULL );
  596:     }
  597: 
  598:   OpenedFile = fopen( FileName, "r" );
  599:   if( NULL == OpenedFile )
  600:     {
  601:     rsyserr(FLOG, errno, "unable to open config file \"%s\"",
  602: 	    FileName);
  603:     }
  604: 
  605:   return( OpenedFile );
  606:   } /* OpenConfFile */
  607: 
  608: int pm_process( char *FileName,
  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:    *
  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.
  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);
  659:     return 0;
  660:     }
  661: 
  662:   return result;
  663:   } /* pm_process */
  664: 
  665: /* -------------------------------------------------------------------------- */
  666: 

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