Annotation of pgp/src/config.c, revision 1.1.1.6

1.1.1.6 ! root        1: /*     config.c  - config file parser by Peter Gutmann
        !             2:        Parses config file for PGP
        !             3: 
        !             4:        (c) Copyright 1990-1994 by Philip Zimmermann.  All rights reserved.
        !             5:        The author assumes no liability for damages resulting from the use
        !             6:        of this software, even if the damage results from defects in this
        !             7:        software.  No warranty is expressed or implied.
        !             8: 
        !             9:        Note that while most PGP source modules bear Philip Zimmermann's
        !            10:        copyright notice, many of them have been revised or entirely written
        !            11:        by contributors who frequently failed to put their names in their
        !            12:        code.  Code that has been incorporated into PGP from other authors
        !            13:        was either originally published in the public domain or is used with
        !            14:        permission from the various authors.
        !            15: 
        !            16:        PGP is available for free to the public under certain restrictions.
        !            17:        See the PGP User's Guide (included in the release package) for
        !            18:        important information about licensing, patent restrictions on
        !            19:        certain algorithms, trademarks, copyrights, and export controls.
        !            20: 
        !            21:        Modified 24 Jun 92 - HAJK
        !            22:        Misc fixes for VAX C restrictions.
        !            23: 
        !            24: */
        !            25: 
        !            26: #include <ctype.h>
        !            27: #include <string.h>
        !            28: #include <stdio.h>
        !            29: #include <stdlib.h>
        !            30: #include "usuals.h"
        !            31: #include "fileio.h"
        !            32: #include "pgp.h"
        !            33: #include "config.h"
        !            34: #include "charset.h"
        !            35: 
        !            36: static int lookup( char *key, int keyLength, char *keyWords[], int range );
        !            37: static int extractToken( char *buffer, int *endIndex, int *length );
        !            38: static int getaString( char *buffer, int *endIndex );
        !            39: static int getAssignment( char *buffer, int *endIndex, INPUT_TYPE settingType );
        !            40: static void processAssignment( int intrinsicIndex );
        !            41: 
        !            42: /* The external config variables we can set here are referenced in pgp.h */
        !            43: 
        !            44: /* Return values */
        !            45: 
        !            46: #define ERROR  -1
        !            47: #define OK             0
        !            48: 
        !            49: /* The types of error we check for */
        !            50: 
        !            51: enum { NO_ERROR, ILLEGAL_CHAR_ERROR, LINELENGTH_ERROR };
        !            52: 
        !            53: #define CPM_EOF                        0x1A    /* ^Z = CPM EOF char */
        !            54: 
        !            55: #define MAX_ERRORS             3               /* Max.no.errors before we give up */
        !            56: 
        !            57: #define LINEBUF_SIZE   100             /* Size of input buffer */
        !            58: 
        !            59: static int line;                               /* The line on which an error occurred */
        !            60: static int errCount;                   /* Total error count */
        !            61: static boolean hasError;               /* Whether this line has an error in it */
        !            62: 
        !            63: /* The settings parsed out by getAssignment() */
        !            64: 
        !            65: static char str[ LINEBUF_SIZE ];
        !            66: static int value;
        !            67: static boolean flag;
        !            68: static char *errtag;   /* prefix for printing error messages */
        !            69: static char optstr[100];       /* option being processed */
        !            70: 
        !            71: /* A .CFG file roughly follows the format used in the world-famous HPACK
        !            72:    archiver and is as follows:
        !            73: 
        !            74:        - Leading spaces/tabs (whitespace) are ignored.
        !            75: 
        !            76:        - Lines with a '#' as the first non-whitespace character are treated as
        !            77:          comment lines.
        !            78: 
        !            79:        - All other lines are treated as config options for the program.
        !            80: 
        !            81:        - Lines may be terminated by either linefeeds, carriage returns, or
        !            82:          carriage return/linefeed pairs (the latter being the DOS default
        !            83:          method of storing text files).
        !            84: 
        !            85:        - Config options have the form:
        !            86: 
        !            87:          <option> '=' <setting>
        !            88: 
        !            89:          where <setting> may be 'on', 'off', a numeric value, or a string
        !            90:          value.
        !            91: 
        !            92:        - If strings have spaces or the '#' character inside them they must be
        !            93:          surrounded by quote marks '"' */
        !            94: 
        !            95: /* Intrinsic variables */
        !            96: 
        !            97: #define NO_INTRINSICS          (sizeof(intrinsics) / sizeof(intrinsics[0]))
        !            98: 
        !            99: enum
        !           100: {      ARMOR, COMPRESS, SHOWPASS, KEEPBINARY, LANGUAGE,
        !           101:        MYNAME, TEXTMODE, TMP, TZFIX, VERBOSE, BAKRING,
        !           102:        ARMORLINES, COMPLETES_NEEDED, MARGINALS_NEEDED, PAGER,
        !           103:        CERT_DEPTH, CHARSET, CLEAR, SELF_ENCRYPT,
        !           104:        INTERACTIVE, PKCS_COMPAT, PUBRING, SECRING, RANDSEED,
        !           105:        COMMENT,
        !           106:        /* options below this line can only be used as command line
        !           107:         * "long" options */
        !           108: #define CONFIG_INTRINSICS      BATCHMODE
        !           109:        BATCHMODE, FORCE, LEGAL_KLUDGE, NOMANUAL
        !           110: };
        !           111: 
        !           112: static char *intrinsics[] =
        !           113: {      "ARMOR", "COMPRESS", "SHOWPASS", "KEEPBINARY", "LANGUAGE",
        !           114:        "MYNAME", "TEXTMODE", "TMP", "TZFIX", "VERBOSE", "BAKRING",
        !           115:        "ARMORLINES", "COMPLETES_NEEDED", "MARGINALS_NEEDED", "PAGER",
        !           116:        "CERT_DEPTH", "CHARSET", "CLEARSIG", "ENCRYPTTOSELF", 
        !           117:        "INTERACTIVE", "PKCS_COMPAT", "PUBRING", "SECRING", "RANDSEED",
        !           118:        "COMMENT",
        !           119:        /* command line only */
        !           120:        "BATCHMODE", "FORCE", "LEGAL_KLUDGE", "NOMANUAL"
        !           121: };
        !           122: 
        !           123: static INPUT_TYPE intrinsicType[] =
        !           124: {      BOOL, BOOL, BOOL, BOOL, STRING,
        !           125:        STRING, BOOL, STRING, NUMERIC, NUMERIC, STRING,
        !           126:        NUMERIC, NUMERIC, NUMERIC, STRING,
        !           127:        NUMERIC, STRING, BOOL, BOOL,
        !           128:        BOOL, NUMERIC, STRING, STRING, STRING,
        !           129:        STRING,
        !           130:        /* command line only */
        !           131:        BOOL, BOOL, BOOL, BOOL
        !           132: };
        !           133: 
        !           134: /* Possible settings for variables */
        !           135: 
        !           136: #define NO_SETTINGS                    2
        !           137: 
        !           138: static char *settings[] = { "OFF", "ON" };
        !           139: 
        !           140: 
        !           141: /* Search a list of keywords for a match */
        !           142: 
        !           143: static int lookup( char *key, int keyLength, char *keyWords[], int range )
        !           144: {
        !           145:        int indx, pos = 0, matches = 0;
        !           146: 
        !           147:        strncpy(optstr, key, keyLength);
        !           148:        optstr[keyLength] = '\0';
        !           149:        /* Make the search case insensitive */
        !           150:        for( indx = 0; indx < keyLength; indx++ )
        !           151:                key[ indx ] = to_upper( key[ indx ] );
        !           152: 
        !           153:        for( indx = 0; indx < range; indx++ )
        !           154:                if( !strncmp( key, keyWords[ indx ], keyLength ) ) {
        !           155:                        if (strlen(keyWords[indx]) == keyLength)
        !           156:                                return indx;    /* exact match */
        !           157:                        pos = indx;
        !           158:                        ++matches;
        !           159:                }
        !           160:        
        !           161:        switch (matches) {
        !           162:          case 0:
        !           163:                fprintf(stderr, "%s: unknown keyword: \"%s\"\n", errtag, optstr);
        !           164:                break;
        !           165:          case 1:
        !           166:                return pos;
        !           167:          default:
        !           168:                fprintf(stderr, "%s: \"%s\" is ambiguous\n", errtag, optstr);
        !           169:        }
        !           170:        return ERROR;
        !           171: }
        !           172: 
        !           173: /* Extract a token from a buffer */
        !           174: static int extractToken( char *buffer, int *endIndex, int *length )
        !           175: {
        !           176:        int indx = 0, tokenStart;
        !           177:        char ch;
        !           178: 
        !           179:        /* Skip whitespace */
        !           180:        for( ch = buffer[ indx ]; ch && ( ch == ' ' || ch == '\t' ); ch = buffer[ indx ] )
        !           181:                indx++;
        !           182:        tokenStart = indx;
        !           183: 
        !           184:        /* Find end of setting */
        !           185:        while( indx < LINEBUF_SIZE && ( ch = buffer[ indx ] ) != '\0' && ch != ' ' && ch != '\t' )
        !           186:                indx++;
        !           187:        *endIndex += indx;
        !           188:        *length = indx - tokenStart;
        !           189: 
        !           190:        /* Return start position of token in buffer */
        !           191:        return tokenStart;
        !           192: }
        !           193: 
        !           194: 
        !           195: /* Get a string constant */
        !           196: static int getaString( char *buffer, int *endIndex )
        !           197:        {
        !           198:        boolean noQuote = FALSE;
        !           199:        int stringIndex = 0, bufIndex = 1;
        !           200:        char ch = *buffer;
        !           201: 
        !           202:        /* Skip whitespace */
        !           203:        while( ch && ( ch == ' ' || ch == '\t' ) )
        !           204:                ch = buffer[ bufIndex++ ];
        !           205: 
        !           206:        /* Check for non-string */
        !           207:        if( ch != '\"' ) {
        !           208:                *endIndex += bufIndex;
        !           209: 
        !           210:                /* Check for special case of null string */
        !           211:                if( !ch ) {
        !           212:                        *str = '\0';
        !           213:                        return OK;
        !           214:                }
        !           215: 
        !           216:                /* Use nasty non-rigorous string format */
        !           217:                noQuote = TRUE;
        !           218:        }
        !           219: 
        !           220:        /* Get first char of string */
        !           221:        if( !noQuote )
        !           222:                ch = buffer[ bufIndex++ ];
        !           223: 
        !           224:        /* Get string into string */
        !           225:        while( ch && ch != '\"' ) {
        !           226:                /* Exit on '#' if using non-rigorous format */
        !           227:                if( noQuote && ch == '#' )
        !           228:                        break;
        !           229: 
        !           230:                str[ stringIndex++ ] = ch;
        !           231:                ch = buffer[ bufIndex++ ];
        !           232:        }
        !           233: 
        !           234:        /* If using the non-rigorous format, stomp trailing spaces */
        !           235:        if( noQuote )
        !           236:                while( stringIndex > 0 && str[ stringIndex - 1 ] == ' ' )
        !           237:                        stringIndex--;
        !           238: 
        !           239:        str[ stringIndex++ ] = '\0';
        !           240:        *endIndex += bufIndex;
        !           241: 
        !           242:        /* Check for missing string terminator */
        !           243:        if( ch != '\"' && !noQuote ) {
        !           244:                if (line)
        !           245:                        fprintf(stderr, "%s: unterminated string in line %d\n", errtag, line );
        !           246:                else
        !           247:                        fprintf(stderr, "unterminated string: '\"%s'\n", str );
        !           248:                hasError = TRUE;
        !           249:                errCount++;
        !           250:                return ERROR;
        !           251:        }
        !           252: 
        !           253:        return OK;
        !           254: }
        !           255: 
        !           256: /* Get an assignment to an intrinsic */
        !           257: static int getAssignment( char *buffer, int *endIndex, INPUT_TYPE settingType )
        !           258: {
        !           259:        int settingIndex = 0, length;
        !           260: 
        !           261:        buffer += extractToken( buffer, endIndex, &length );
        !           262: 
        !           263:        /* Check for an assignment operator */
        !           264:        if ( *buffer != '=' ) {
        !           265:                if (line)
        !           266:                        fprintf(stderr, "%s: expected '=' in line %d\n", errtag, line );
        !           267:                else
        !           268:                        fprintf(stderr, "%s: expected '=' after \"%s\"\n", errtag, optstr);
        !           269:                hasError = TRUE;
        !           270:                errCount++;
        !           271:                return ERROR;
        !           272:        }
        !           273:        buffer++;               /* Skip '=' */
        !           274: 
        !           275:        buffer += extractToken( buffer, endIndex, &length );
        !           276: 
        !           277:        switch( settingType ) {
        !           278:          case BOOL:
        !           279:                /* Check for known intrinsic - really more general than just
        !           280:                   checking for TRUE or FALSE */
        !           281:                if( ( settingIndex = lookup( buffer, length, settings, NO_SETTINGS ) ) == ERROR )
        !           282:                {
        !           283:                        hasError = TRUE;
        !           284:                        errCount++;
        !           285:                        return ERROR;
        !           286:                }
        !           287: 
        !           288:                flag = ( settingIndex == 0 ) ? FALSE : TRUE;
        !           289:                break;
        !           290: 
        !           291:          case STRING:
        !           292:                /* Get a string */
        !           293:                getaString( buffer, &length );
        !           294:                break;
        !           295: 
        !           296:          case NUMERIC:
        !           297:                /* Get numeric input.  Error checking is a pain since atoi()
        !           298:                        has no real equivalent of NAN */
        !           299:                value = atoi( buffer );
        !           300:                break;
        !           301:        }
        !           302: 
        !           303:        return settingIndex;
        !           304: }
        !           305: 
        !           306: /* Process an assignment */
        !           307: 
        !           308: static void processAssignment( int intrinsicIndex )
        !           309: {
        !           310:        if( !hasError )
        !           311:                switch( intrinsicIndex ) {
        !           312:                  case ARMOR:
        !           313:                        emit_radix_64 = flag;
        !           314:                        break;
        !           315: 
        !           316:                  case COMPRESS:
        !           317:                        compress_enabled = flag;
        !           318:                        break;
        !           319: 
        !           320:                  case SHOWPASS:
        !           321:                        showpass = flag;
        !           322:                        break;
        !           323: 
        !           324:                  case KEEPBINARY:
        !           325:                        keepctx = flag;
        !           326:                        break;
        !           327: 
        !           328:                  case LANGUAGE:
        !           329:                        strncpy(language, str, 15);
        !           330:                        break;
        !           331: 
        !           332:                  case BAKRING:
        !           333:                        strcpy(floppyring, str);
        !           334:                        break;
        !           335: 
        !           336:                  case MYNAME:
        !           337:                        strcpy(my_name, str);
        !           338:                        break;
        !           339: 
        !           340:                  case TEXTMODE:
        !           341:                        if( flag )
        !           342:                                literal_mode = MODE_TEXT;
        !           343:                        else
        !           344:                                literal_mode = MODE_BINARY;
        !           345:                        break;
        !           346: 
        !           347:                  case TMP:
        !           348:                        /* directory pathname to store temp files */
        !           349:                        settmpdir(str);
        !           350:                        break;
        !           351: 
        !           352:                  case TZFIX:
        !           353:                        /* How many hours to add to time() to get GMT. */
        !           354:                        /* Compute seconds from hours to shift to GMT: */
        !           355:                        timeshift = 3600L * (long) value;
        !           356:                        break;
        !           357: 
        !           358:                  case VERBOSE:
        !           359:                        if (value < 1) {
        !           360:                                quietmode = TRUE; verbose = FALSE;
        !           361:                        } else if (value == 1) {
        !           362:                                quietmode = FALSE; verbose = FALSE;
        !           363:                        } else {        /* value > 1 */
        !           364:                                quietmode = FALSE; verbose = TRUE;
        !           365:                        }
        !           366:                        break;
        !           367: 
        !           368:                  case ARMORLINES:
        !           369:                        pem_lines = value;
        !           370:                        break;
        !           371: 
        !           372:                  case MARGINALS_NEEDED:
        !           373:                        marg_min = value;
        !           374:                        if (marg_min < 1)
        !           375:                                marg_min = 1;
        !           376:                        break;
        !           377: 
        !           378:                  case COMPLETES_NEEDED:
        !           379:                        compl_min = value;
        !           380:                        if (compl_min < 1)
        !           381:                                compl_min = 1;
        !           382:                        if (compl_min > 4)
        !           383:                                compl_min = 4;
        !           384:                        break;
        !           385: 
        !           386:                  case CERT_DEPTH:
        !           387:                        max_cert_depth = value;
        !           388:                        if (max_cert_depth < 0)
        !           389:                                max_cert_depth = 0;
        !           390:                        if (max_cert_depth > 8)
        !           391:                                max_cert_depth = 8;
        !           392:                        break;
        !           393: 
        !           394:                  case PAGER:
        !           395:                        strcpy(pager, str);
        !           396:                        break;
        !           397: 
        !           398:                  case CHARSET:
        !           399:                        strcpy(charset, str);
        !           400:                        break;
        !           401: 
        !           402:                  case CLEAR:
        !           403:                        clear_signatures = flag;
        !           404:                        break;
        !           405:                        
        !           406:                  case SELF_ENCRYPT:
        !           407:                        encrypt_to_self = flag;
        !           408:                        break;
        !           409:                        
        !           410:                  case INTERACTIVE:
        !           411:                        interactive_add = flag;
        !           412:                        break;
        !           413:                        
        !           414:                  case BATCHMODE: batchmode = flag; break;
        !           415:                  case FORCE: force_flag = flag; break;
        !           416:                  case PKCS_COMPAT: pkcs_compat = value; break;
        !           417: 
        !           418:                /* Undocumented flag to test contractually-mandated time bomb */
        !           419:                  case LEGAL_KLUDGE:
        !           420:                        legal_kludge = value;
        !           421:                        break;
        !           422: 
        !           423:                  case NOMANUAL: nomanual = value; break;
        !           424: 
        !           425:                  case PUBRING:
        !           426:                        strcpy(globalPubringName, str);
        !           427:                        break;
        !           428: 
        !           429:                  case SECRING:
        !           430:                        strcpy(globalSecringName, str);
        !           431:                        break;
        !           432: 
        !           433:                  case RANDSEED:
        !           434:                        strcpy(globalRandseedName, str);
        !           435:                        break;
        !           436: 
        !           437:                  case COMMENT:
        !           438:                        strcpy(globalCommentString, str);
        !           439:                        break;
        !           440:                }
        !           441: }
        !           442: 
        !           443: /* Process an option on a line by itself.  This expects options which are
        !           444:    taken from the command-line, and is less finicky about errors than the
        !           445:    config-file version */
        !           446: 
        !           447: int processConfigLine( char *option )
        !           448: {
        !           449:        int indx, intrinsicIndex;
        !           450:        char ch;
        !           451: 
        !           452:        /* Give it a pseudo-linenumber of 0 */
        !           453:        line = 0;
        !           454: 
        !           455:        errtag = "pgp";
        !           456:        errCount = 0;
        !           457:        for( indx = 0;
        !           458:                 indx < LINEBUF_SIZE && ( ch = option[ indx ] ) != '\0' &&
        !           459:                                ch != ' ' && ch != '\t' && ch != '=';
        !           460:                 indx++ );
        !           461:        if( ( intrinsicIndex = lookup( ( char * ) option, indx, intrinsics, NO_INTRINSICS ) ) == ERROR )
        !           462:                return -1;
        !           463:        if (option[indx] == '\0' && intrinsicType[intrinsicIndex] == BOOL)
        !           464:        {
        !           465:                /* boolean option, no '=' means TRUE */
        !           466:                flag = TRUE;
        !           467:                processAssignment(intrinsicIndex);
        !           468:        } else /* Get the value to set to, either as a string, a
        !           469:                    numeric value, or a boolean flag */
        !           470:                if (getAssignment( ( char * ) option + indx, &indx, intrinsicType[ intrinsicIndex ] ) != ERROR)
        !           471:                        processAssignment( intrinsicIndex );
        !           472:        return errCount ? -1 : 0;
        !           473: }
        !           474: 
        !           475: /* Process a config file */
        !           476: int processConfigFile( char *configFileName )
        !           477: {
        !           478:        FILE *configFilePtr;
        !           479:        int ch = 0, theCh;
        !           480:        int errType, errPos = 0, lineBufCount, intrinsicIndex;
        !           481:        int indx;
        !           482:        char inBuffer[ LINEBUF_SIZE ];
        !           483: 
        !           484:        line = 1;
        !           485:        errCount = 0;
        !           486:        errtag = "config.txt";
        !           487: 
        !           488:        if( ( configFilePtr = fopen( configFileName, FOPRTXT ) ) == NULL ) {
        !           489:                fprintf(stderr, "Cannot open configuration file %s\n", configFileName );
        !           490:                return OK;      /* treat like empty config file */
        !           491:        }
        !           492: 
        !           493:        /* Process each line in the configFile */
        !           494:        while( ch != EOF ) {
        !           495:                /* Skip whitespace */
        !           496:                while( ( ( ch = getc( configFilePtr ) ) == ' ' || ch == '\t' ) && ch != EOF )
        !           497:                ;
        !           498: 
        !           499:                /* Get a line into the inBuffer */
        !           500:                hasError = FALSE;
        !           501:                lineBufCount = 0;
        !           502:                errType = NO_ERROR;
        !           503:                while( ch != '\r' && ch != '\n' && ch != CPM_EOF && ch != EOF )
        !           504:                {
        !           505:                        /* Check for an illegal char in the data */
        !           506:                        if( ( ch < ' ' || ch > '~' ) && ch != '\r' && ch != '\n' &&
        !           507:                                ch != ' ' && ch != '\t' && ch != CPM_EOF && ch != EOF )
        !           508:                        {
        !           509:                                if( errType == NO_ERROR )
        !           510:                                        /* Save position of first illegal char */
        !           511:                                        errPos = lineBufCount;
        !           512:                                errType = ILLEGAL_CHAR_ERROR;
        !           513:                        }
        !           514: 
        !           515:                        /* Make sure the path is of the correct length.  Note that the
        !           516:                           code is ordered so that a LINELENGTH_ERROR takes precedence over
        !           517:                           an ILLEGAL_CHAR_ERROR */
        !           518:                        if( lineBufCount > LINEBUF_SIZE )
        !           519:                                errType = LINELENGTH_ERROR;
        !           520:                        else
        !           521:                                inBuffer[ lineBufCount++ ] = ch;
        !           522: 
        !           523:                        if( ( ch = getc( configFilePtr ) ) == '#' )
        !           524:                        {
        !           525:                                /* Skip comment section and trailing whitespace */
        !           526:                                while( ch != '\r' && ch != '\n' && ch != CPM_EOF && ch != EOF )
        !           527:                                        ch = getc( configFilePtr );
        !           528:                                break;
        !           529:                        }
        !           530:                }
        !           531: 
        !           532:                /* Skip trailing whitespace and add der terminador */
        !           533:                while(lineBufCount && (( theCh = inBuffer[ lineBufCount - 1 ] ) == ' ' || theCh == '\t' ))
        !           534:                        lineBufCount--;
        !           535: 
        !           536:                inBuffer[ lineBufCount ] = '\0';
        !           537: 
        !           538:                /* Process the line unless its a blank or comment line */
        !           539:                if( lineBufCount && *inBuffer != '#' )
        !           540:                {
        !           541:                        switch( errType )
        !           542:                        {
        !           543:                          case LINELENGTH_ERROR:
        !           544:                                fprintf(stderr, "%s: line '%.30s...' too long\n", errtag, inBuffer );
        !           545:                                errCount++;
        !           546:                                break;
        !           547: 
        !           548:                          case ILLEGAL_CHAR_ERROR:
        !           549:                                fprintf(stderr, "> %s\n  ", inBuffer );
        !           550:                                fprintf(stderr, "%*s^\n", errPos, ""); 
        !           551:                                fprintf(stderr, "%s: bad character in command on line %d\n", errtag, line );
        !           552:                                errCount++;
        !           553:                                break;
        !           554: 
        !           555:                          default:
        !           556:                                for( indx = 0;
        !           557:                                         indx < LINEBUF_SIZE && ( ch = inBuffer[ indx ] ) != '\0'
        !           558:                                                        && ch != ' ' && ch != '\t' && ch != '=';
        !           559:                                         indx++ )
        !           560:                                                ;
        !           561:                                if( ( intrinsicIndex = lookup( inBuffer, indx, intrinsics, CONFIG_INTRINSICS ) ) == ERROR )
        !           562:                                {
        !           563:                                        errCount++;
        !           564:                                } else {
        !           565:                                        /* Get the value to set to, either as a string, a
        !           566:                                           numeric value, or a boolean flag */
        !           567:                                        getAssignment( inBuffer + indx, &indx, intrinsicType[ intrinsicIndex ] );
        !           568:                                        processAssignment( intrinsicIndex );
        !           569:                                }
        !           570:                        }
        !           571:                }
        !           572: 
        !           573:                /* Handle special-case of ^Z if configFile came off an MSDOS system */
        !           574:                if( ch == CPM_EOF )
        !           575:                        ch = EOF;
        !           576: 
        !           577:                /* Exit if there are too many errors */
        !           578:                if( errCount >= MAX_ERRORS )
        !           579:                        break;
        !           580: 
        !           581:                line++;
        !           582:        }
        !           583: 
        !           584:        fclose( configFilePtr );
        !           585: 
        !           586:        /* Exit if there were errors */
        !           587:        if( errCount ) {
        !           588:                fprintf(stderr, "%s: %s%d error(s) detected\n\n", configFileName, ( errCount >= MAX_ERRORS ) ?
        !           589:                                "Maximum level of " : "", errCount );
        !           590:                return ERROR;
        !           591:        }
        !           592: 
        !           593:        return OK;
        !           594: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.