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

1.1.1.6   root        1: /*     config.c  - config file parser by Peter Gutmann
                      2:        Parses config file for PGP
1.1.1.8 ! root        3: 
1.1.1.6   root        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.
1.1.1.8 ! root        8: 
1.1.1.6   root        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.
1.1.1.8 ! root       15: 
1.1.1.6   root       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.
1.1.1.8 ! root       20: 
1.1.1.6   root       21:        Modified 24 Jun 92 - HAJK
1.1.1.8 ! root       22:        Misc fixes for VAX C restrictions
        !            23: 
        !            24:        Updated by Peter Gutmann to only warn about unrecognized options,
        !            25:        so future additions to the config file will give old versions a
        !            26:        chance to still run.  A number of code cleanups, too.  */
1.1.1.6   root       27: 
                     28: #include <ctype.h>
                     29: #include <string.h>
                     30: #include <stdio.h>
                     31: #include <stdlib.h>
1.1.1.8 ! root       32: #include <limits.h>
1.1.1.6   root       33: #include "usuals.h"
                     34: #include "fileio.h"
                     35: #include "pgp.h"
                     36: #include "config.h"
                     37: #include "charset.h"
                     38: 
1.1.1.8 ! root       39: /* Various maximum/minimum allowable settings for config options */
        !            40: 
        !            41: #define MIN_MARGINALS  1
        !            42: #define MIN_COMPLETE   1
        !            43: #define MAX_COMPLETE   4
        !            44: #define MIN_CERT_DEPTH 0
        !            45: #define MAX_CERT_DEPTH 8
        !            46: 
        !            47: /* Prototypes for local functions */
        !            48: 
1.1.1.6   root       49: static int lookup( char *key, int keyLength, char *keyWords[], int range );
                     50: static int extractToken( char *buffer, int *endIndex, int *length );
                     51: static int getaString( char *buffer, int *endIndex );
1.1.1.8 ! root       52: static int getAssignment( char *buffer, int *endIndex, INPUT_TYPE settingType );
1.1.1.6   root       53: static void processAssignment( int intrinsicIndex );
                     54: 
                     55: /* The external config variables we can set here are referenced in pgp.h */
                     56: 
                     57: /* Return values */
                     58: 
                     59: #define ERROR  -1
                     60: #define OK             0
                     61: 
                     62: /* The types of error we check for */
                     63: 
                     64: enum { NO_ERROR, ILLEGAL_CHAR_ERROR, LINELENGTH_ERROR };
                     65: 
1.1.1.8 ! root       66: #define CPM_EOF                0x1A    /* ^Z = CPM EOF char */
1.1.1.6   root       67: 
1.1.1.8 ! root       68: #define MAX_ERRORS     3       /* Max.no.errors before we give up */
1.1.1.6   root       69: 
1.1.1.8 ! root       70: #define LINEBUF_SIZE   100     /* Size of input buffer */
1.1.1.6   root       71: 
1.1.1.7   root       72: static int line;               /* The line on which an error occurred */
1.1.1.8 ! root       73: static int errCount;           /* Total error count */
1.1.1.7   root       74: static boolean hasError;       /* Whether this line has an error in it */
1.1.1.6   root       75: 
                     76: /* The settings parsed out by getAssignment() */
                     77: 
                     78: static char str[ LINEBUF_SIZE ];
                     79: static int value;
1.1.1.8 ! root       80: static char *errtag;           /* Prefix for printing error messages */
        !            81: static char optstr[ 100 ];     /* Option being processed */
1.1.1.6   root       82: 
                     83: /* A .CFG file roughly follows the format used in the world-famous HPACK
                     84:    archiver and is as follows:
                     85: 
                     86:        - Leading spaces/tabs (whitespace) are ignored.
                     87: 
1.1.1.7   root       88:        - Lines with a '#' as the first non-whitespace character are treated
                     89:          as comment lines.
1.1.1.6   root       90: 
                     91:        - All other lines are treated as config options for the program.
                     92: 
                     93:        - Lines may be terminated by either linefeeds, carriage returns, or
                     94:          carriage return/linefeed pairs (the latter being the DOS default
                     95:          method of storing text files).
                     96: 
                     97:        - Config options have the form:
                     98: 
                     99:          <option> '=' <setting>
                    100: 
                    101:          where <setting> may be 'on', 'off', a numeric value, or a string
                    102:          value.
                    103: 
                    104:        - If strings have spaces or the '#' character inside them they must be
                    105:          surrounded by quote marks '"' */
                    106: 
                    107: /* Intrinsic variables */
                    108: 
                    109: #define NO_INTRINSICS          (sizeof(intrinsics) / sizeof(intrinsics[0]))
1.1.1.8 ! root      110: #define CONFIG_INTRINSICS      BATCHMODE
1.1.1.6   root      111: 
1.1.1.8 ! root      112: enum {
        !           113:        ARMOR, COMPRESS, SHOWPASS, KEEPBINARY, LANGUAGE,
1.1.1.6   root      114:        MYNAME, TEXTMODE, TMP, TZFIX, VERBOSE, BAKRING,
                    115:        ARMORLINES, COMPLETES_NEEDED, MARGINALS_NEEDED, PAGER,
                    116:        CERT_DEPTH, CHARSET, CLEAR, SELF_ENCRYPT,
1.1.1.8 ! root      117:        INTERACTIVE, PUBRING, SECRING, RANDSEED,
1.1.1.6   root      118:        COMMENT,
                    119:        /* options below this line can only be used as command line
                    120:         * "long" options */
1.1.1.8 ! root      121:        BATCHMODE, FORCE, NOMANUAL, MAKERANDOM
        !           122:        };
1.1.1.6   root      123: 
1.1.1.8 ! root      124: static char *intrinsics[] = {
        !           125:        "ARMOR", "COMPRESS", "SHOWPASS", "KEEPBINARY", "LANGUAGE",
1.1.1.6   root      126:        "MYNAME", "TEXTMODE", "TMP", "TZFIX", "VERBOSE", "BAKRING",
                    127:        "ARMORLINES", "COMPLETES_NEEDED", "MARGINALS_NEEDED", "PAGER",
                    128:        "CERT_DEPTH", "CHARSET", "CLEARSIG", "ENCRYPTTOSELF", 
1.1.1.8 ! root      129:        "INTERACTIVE", "PUBRING", "SECRING", "RANDSEED",
1.1.1.6   root      130:        "COMMENT",
                    131:        /* command line only */
1.1.1.8 ! root      132:        "BATCHMODE", "FORCE", "NOMANUAL", "MAKERANDOM"
        !           133:        };
1.1.1.6   root      134: 
1.1.1.8 ! root      135: static INPUT_TYPE intrinsicType[] = {
        !           136:        BOOL, BOOL, BOOL, BOOL, STRING,
1.1.1.6   root      137:        STRING, BOOL, STRING, NUMERIC, NUMERIC, STRING,
                    138:        NUMERIC, NUMERIC, NUMERIC, STRING,
                    139:        NUMERIC, STRING, BOOL, BOOL,
1.1.1.8 ! root      140:        BOOL, STRING, STRING, STRING,
1.1.1.6   root      141:        STRING,
                    142:        /* command line only */
1.1.1.8 ! root      143:        BOOL, BOOL, BOOL, NUMERIC
        !           144:        };
1.1.1.6   root      145: 
                    146: /* Possible settings for variables */
                    147: 
                    148: #define NO_SETTINGS                    2
                    149: 
                    150: static char *settings[] = { "OFF", "ON" };
                    151: 
                    152: /* Search a list of keywords for a match */
1.1.1.8 ! root      153: 
1.1.1.6   root      154: static int lookup( char *key, int keyLength, char *keyWords[], int range )
                    155: {
1.1.1.8 ! root      156:        int index, position = 0, noMatches = 0;
        !           157: 
        !           158:        strncpy( optstr, key, keyLength );
        !           159:        optstr[ keyLength ] = '\0';
1.1.1.6   root      160: 
                    161:        /* Make the search case insensitive */
1.1.1.8 ! root      162:        for( index = 0; index < keyLength; index++ )
        !           163:                key[ index ] = to_upper( key[ index ] );
1.1.1.6   root      164: 
1.1.1.8 ! root      165:        for( index = 0; index < range; index++ )
        !           166:                if( !strncmp( key, keyWords[ index ], keyLength ) )
        !           167:                        {
        !           168:                        if( strlen( keyWords[ index ] ) == keyLength )
        !           169:                                return index;   /* exact match */
        !           170:                        position = index;
        !           171:                        noMatches++;
        !           172:                        }
        !           173: 
        !           174:        switch( noMatches )
        !           175:                {
        !           176:                case 0:
        !           177:                        fprintf( stderr, "%s: unknown keyword: \"%s\"\n",
        !           178:                                         errtag, optstr );
        !           179:                        break;
        !           180:                case 1:
        !           181:                        return( position );     /* Match succeeded */
        !           182:                default:
        !           183:                        fprintf( stderr, "%s: \"%s\" is ambiguous\n",
        !           184:                                         errtag, optstr );
1.1.1.6   root      185:                }
                    186:        return ERROR;
                    187: }
                    188: 
                    189: /* Extract a token from a buffer */
1.1.1.8 ! root      190: 
1.1.1.6   root      191: static int extractToken( char *buffer, int *endIndex, int *length )
                    192: {
1.1.1.8 ! root      193:        int index = 0, tokenStart;
1.1.1.6   root      194:        char ch;
                    195: 
                    196:        /* Skip whitespace */
1.1.1.8 ! root      197:        for( ch = buffer[ index ]; ch && ( ch == ' ' || ch == '\t' );
        !           198:                 ch = buffer[ index ] )
        !           199:                index++;
        !           200:        tokenStart = index;
1.1.1.6   root      201: 
                    202:        /* Find end of setting */
1.1.1.8 ! root      203:        while( index < LINEBUF_SIZE && ( ch = buffer[ index ] ) != '\0'
        !           204:                   && ch != ' ' && ch != '\t' )
        !           205:                index++;
        !           206:        *endIndex += index;
        !           207:        *length = index - tokenStart;
1.1.1.6   root      208: 
                    209:        /* Return start position of token in buffer */
                    210:        return tokenStart;
                    211: }
                    212: 
                    213: /* Get a string constant */
1.1.1.8 ! root      214: 
1.1.1.6   root      215: static int getaString( char *buffer, int *endIndex )
                    216:        {
                    217:        boolean noQuote = FALSE;
1.1.1.8 ! root      218:        int stringIndex = 0, bufferIndex = 1;
1.1.1.6   root      219:        char ch = *buffer;
                    220: 
                    221:        /* Skip whitespace */
                    222:        while( ch && ( ch == ' ' || ch == '\t' ) )
1.1.1.8 ! root      223:                ch = buffer[ bufferIndex++ ];
1.1.1.6   root      224: 
                    225:        /* Check for non-string */
1.1.1.8 ! root      226:        if( ch != '\"' )
        !           227:                {
        !           228:                *endIndex += bufferIndex;
1.1.1.6   root      229: 
                    230:                /* Check for special case of null string */
1.1.1.8 ! root      231:                if( !ch )
        !           232:                        {
1.1.1.6   root      233:                        *str = '\0';
                    234:                        return OK;
1.1.1.8 ! root      235:                        }
1.1.1.6   root      236: 
                    237:                /* Use nasty non-rigorous string format */
                    238:                noQuote = TRUE;
1.1.1.8 ! root      239:                }
1.1.1.6   root      240: 
                    241:        /* Get first char of string */
                    242:        if( !noQuote )
1.1.1.8 ! root      243:                ch = buffer[ bufferIndex++ ];
1.1.1.6   root      244: 
                    245:        /* Get string into string */
1.1.1.8 ! root      246:        while( ch && ch != '\"' )
        !           247:                {
1.1.1.6   root      248:                /* Exit on '#' if using non-rigorous format */
                    249:                if( noQuote && ch == '#' )
                    250:                        break;
                    251: 
                    252:                str[ stringIndex++ ] = ch;
1.1.1.8 ! root      253:                ch = buffer[ bufferIndex++ ];
        !           254:                }
1.1.1.6   root      255: 
                    256:        /* If using the non-rigorous format, stomp trailing spaces */
                    257:        if( noQuote )
                    258:                while( stringIndex > 0 && str[ stringIndex - 1 ] == ' ' )
                    259:                        stringIndex--;
                    260: 
                    261:        str[ stringIndex++ ] = '\0';
1.1.1.8 ! root      262:        *endIndex += bufferIndex;
1.1.1.6   root      263: 
                    264:        /* Check for missing string terminator */
1.1.1.8 ! root      265:        if( ch != '\"' && !noQuote )
        !           266:                {
        !           267:                if( line )
        !           268:                        fprintf( stderr, "%s: unterminated string in line %d\n",
        !           269:                                         errtag, line );
1.1.1.6   root      270:                else
1.1.1.8 ! root      271:                        fprintf( stderr, "unterminated string: '\"%s'\n", str );
1.1.1.6   root      272:                hasError = TRUE;
                    273:                errCount++;
                    274:                return ERROR;
1.1.1.8 ! root      275:                }
1.1.1.6   root      276: 
                    277:        return OK;
                    278: }
                    279: 
                    280: /* Get an assignment to an intrinsic */
1.1.1.8 ! root      281: 
1.1.1.6   root      282: static int getAssignment( char *buffer, int *endIndex, INPUT_TYPE settingType )
                    283: {
                    284:        int settingIndex = 0, length;
1.1.1.8 ! root      285:        long longval;
        !           286:        char *p;
1.1.1.6   root      287: 
                    288:        buffer += extractToken( buffer, endIndex, &length );
                    289: 
                    290:        /* Check for an assignment operator */
1.1.1.8 ! root      291:        if( *buffer != '=' )
        !           292:                {
        !           293:                if( line )
        !           294:                        fprintf( stderr, "%s: expected '=' in line %d\n",
        !           295:                                         errtag, line );
1.1.1.6   root      296:                else
1.1.1.8 ! root      297:                        fprintf( stderr, "%s: expected '=' after \"%s\"\n",
        !           298:                                         errtag, optstr);
1.1.1.6   root      299:                hasError = TRUE;
                    300:                errCount++;
                    301:                return ERROR;
1.1.1.8 ! root      302:                }
        !           303:        buffer++;       /* Skip '=' */
1.1.1.6   root      304: 
                    305:        buffer += extractToken( buffer, endIndex, &length );
                    306: 
1.1.1.8 ! root      307:        switch( settingType )
1.1.1.6   root      308:                {
1.1.1.8 ! root      309:                case BOOL:
        !           310:                        /* Check for known intrinsic - really more general
        !           311:                           than just checking for TRUE or FALSE */
        !           312:                        settingIndex = lookup( buffer, length, settings,
        !           313:                                               NO_SETTINGS );
        !           314:                        if( settingIndex == ERROR )
        !           315:                                {
        !           316:                                hasError = TRUE;
        !           317:                                errCount++;
        !           318:                                return ERROR;
        !           319:                                }
        !           320: 
        !           321:                        value = ( settingIndex == 0 ) ? FALSE : TRUE;
        !           322:                        break;
        !           323: 
        !           324:                case STRING:
        !           325:                        /* Get a string */
        !           326:                        getaString( buffer, &length );
        !           327:                        break;
        !           328: 
        !           329:                case NUMERIC:
        !           330:                        longval = strtol(buffer, &p, 0);
        !           331:                        if (p == buffer+length &&
        !           332:                            longval <= INT_MAX && longval >= INT_MIN) {
        !           333:                                value = (int)longval;
        !           334:                                break;
        !           335:                        }
        !           336:                        if( line )
        !           337:                                fprintf( stderr,
        !           338:                                  "%s: numeric argument expected in line %d\n",
        !           339:                                                 errtag, line );
        !           340:                        else
        !           341:                                fprintf( stderr,
        !           342:                                   "%s: numeric argument required for \"%s\"\n",
        !           343:                                                 errtag, optstr);
1.1.1.6   root      344:                        hasError = TRUE;
                    345:                        errCount++;
                    346:                        return ERROR;
                    347:                }
                    348: 
                    349:        return settingIndex;
                    350: }
                    351: 
                    352: /* Process an assignment */
1.1.1.8 ! root      353: 
1.1.1.6   root      354: static void processAssignment( int intrinsicIndex )
1.1.1.8 ! root      355:        {
1.1.1.6   root      356:        if( !hasError )
1.1.1.8 ! root      357:                switch( intrinsicIndex )
        !           358:                        {
        !           359:                        case ARMOR:
        !           360:                                emit_radix_64 = value;
        !           361:                                break;
1.1.1.6   root      362: 
1.1.1.8 ! root      363:                        case ARMORLINES:
        !           364:                                pem_lines = value;
        !           365:                                break;
1.1.1.6   root      366: 
1.1.1.8 ! root      367:                        case BAKRING:
        !           368:                                strcpy( floppyring, str );
        !           369:                                break;
1.1.1.6   root      370: 
1.1.1.8 ! root      371:                        case BATCHMODE:
        !           372:                                batchmode = value;
        !           373:                                break;
1.1.1.6   root      374: 
1.1.1.8 ! root      375:                        case CERT_DEPTH:
        !           376:                                max_cert_depth = value;
        !           377:                                if( max_cert_depth < MIN_CERT_DEPTH )
        !           378:                                        max_cert_depth = MIN_CERT_DEPTH;
        !           379:                                if( max_cert_depth > MAX_CERT_DEPTH )
        !           380:                                        max_cert_depth = MAX_CERT_DEPTH;
        !           381:                                break;
1.1.1.6   root      382: 
1.1.1.8 ! root      383:                        case CHARSET:
        !           384:                                strcpy( charset, str );
        !           385:                                break;
1.1.1.6   root      386: 
1.1.1.8 ! root      387:                        case CLEAR:
        !           388:                                clear_signatures = value;
        !           389:                                break;
1.1.1.6   root      390: 
1.1.1.8 ! root      391:                        case COMMENT:
        !           392:                                strcpy( globalCommentString, str );
        !           393:                                break;
1.1.1.6   root      394: 
1.1.1.8 ! root      395:                        case COMPLETES_NEEDED:
        !           396:                                compl_min = value;
        !           397:                                /* Keep within range */
        !           398:                                if( compl_min < MIN_COMPLETE )
        !           399:                                        compl_min = MIN_COMPLETE;
        !           400:                                if( compl_min > MAX_COMPLETE )
        !           401:                                        compl_min = MAX_COMPLETE;
        !           402:                                break;
1.1.1.6   root      403: 
1.1.1.8 ! root      404:                        case COMPRESS:
        !           405:                                compress_enabled = value;
        !           406:                                break;
1.1.1.6   root      407: 
1.1.1.8 ! root      408:                        case FORCE:
        !           409:                                force_flag = value;
        !           410:                                break;
1.1.1.6   root      411: 
1.1.1.8 ! root      412:                        case INTERACTIVE:
        !           413:                                interactive_add = value;
        !           414:                                break;
1.1.1.6   root      415: 
1.1.1.8 ! root      416:                        case KEEPBINARY:
        !           417:                                keepctx = value;
        !           418:                                break;
1.1.1.6   root      419: 
1.1.1.8 ! root      420:                        case LANGUAGE:
        !           421:                                strncpy( language, str, 15 );
        !           422:                                break;
1.1.1.6   root      423: 
1.1.1.8 ! root      424:                        case MAKERANDOM:
        !           425:                                makerandom = value;
        !           426:                                break;
1.1.1.6   root      427: 
1.1.1.8 ! root      428:                        case MARGINALS_NEEDED:
        !           429:                                marg_min = value;
        !           430:                                /* Keep within range */
        !           431:                                if( marg_min < MIN_MARGINALS )
        !           432:                                        marg_min = MIN_MARGINALS;
        !           433:                                break;
1.1.1.6   root      434: 
1.1.1.8 ! root      435:                        case MYNAME:
        !           436:                                strcpy( my_name, str );
        !           437:                                break;
1.1.1.6   root      438: 
1.1.1.8 ! root      439:                        case NOMANUAL:
        !           440:                                nomanual = value;
        !           441:                                break;
1.1.1.6   root      442: 
1.1.1.8 ! root      443:                        case PAGER:
        !           444:                                strcpy( pager, str );
        !           445:                                break;
1.1.1.6   root      446: 
1.1.1.8 ! root      447:                        case PUBRING:
        !           448:                                strcpy( globalPubringName, str );
        !           449:                                break;
1.1.1.6   root      450: 
1.1.1.8 ! root      451:                        case RANDSEED:
        !           452:                                strcpy( globalRandseedName, str );
        !           453:                                break;
1.1.1.6   root      454: 
1.1.1.8 ! root      455:                        case SECRING:
        !           456:                                strcpy( globalSecringName, str );
        !           457:                                break;
1.1.1.6   root      458: 
1.1.1.8 ! root      459:                        case SELF_ENCRYPT:
        !           460:                                encrypt_to_self = value;
        !           461:                                break;
        !           462: 
        !           463:                        case SHOWPASS:
        !           464:                                showpass = value;
        !           465:                                break;
        !           466: 
        !           467:                        case TEXTMODE:
        !           468:                                if( value )
        !           469:                                        literal_mode = MODE_TEXT;
        !           470:                                else
        !           471:                                        literal_mode = MODE_BINARY;
        !           472:                                break;
        !           473: 
        !           474:                        case TMP:
        !           475:                                /* directory pathname to store temp files */
        !           476:                                settmpdir( str );
        !           477:                                break;
        !           478: 
        !           479:                        case TZFIX:
        !           480:                                /* How many hours to add to time() to get GMT.
        !           481:                                   We just compute the seconds from hours to
        !           482:                                   get the GMT shift */
        !           483:                                timeshift = 3600L * ( long ) value;
        !           484:                                break;
        !           485: 
        !           486:                        case VERBOSE:
        !           487:                                if( value < 1 )
        !           488:                                        {
        !           489:                                        quietmode = TRUE;
        !           490:                                        verbose = FALSE;
        !           491:                                        }
        !           492:                                else
        !           493:                                        if( value == 1 )
        !           494:                                                {
        !           495:                                                quietmode = FALSE;
        !           496:                                                verbose = FALSE;
        !           497:                                                }
        !           498:                                        else
        !           499:                                                {
        !           500:                                                /* Value > 1 */
        !           501:                                                quietmode = FALSE;
        !           502:                                                verbose = TRUE;
        !           503:                                                }
        !           504:                                break;
        !           505: 
        !           506:                        }
1.1.1.6   root      507: }
                    508: 
                    509: /* Process an option on a line by itself.  This expects options which are
                    510:    taken from the command-line, and is less finicky about errors than the
                    511:    config-file version */
1.1.1.8 ! root      512: 
1.1.1.6   root      513: int processConfigLine( char *option )
                    514: {
1.1.1.8 ! root      515:        int index, intrinsicIndex;
1.1.1.6   root      516:        char ch;
                    517: 
                    518:        /* Give it a pseudo-linenumber of 0 */
                    519:        line = 0;
                    520: 
                    521:        errtag = "pgp";
                    522:        errCount = 0;
1.1.1.8 ! root      523:        for( index = 0;
        !           524:                 index < LINEBUF_SIZE && ( ch = option[ index ] ) != '\0' &&
1.1.1.6   root      525:                                ch != ' ' && ch != '\t' && ch != '=';
1.1.1.8 ! root      526:                 index++ );
        !           527:        if( ( intrinsicIndex = lookup( ( char * ) option, index, intrinsics,
1.1.1.7   root      528:                                      NO_INTRINSICS ) ) == ERROR )
1.1.1.6   root      529:                return -1;
1.1.1.8 ! root      530:        if( option[ index ] == '\0' && intrinsicType[ intrinsicIndex ] == BOOL)
        !           531:                {
        !           532:                /* Boolean option, no '=' means TRUE */
        !           533:                value = TRUE;
        !           534:                processAssignment( intrinsicIndex );
        !           535:                }
        !           536:        else
        !           537:                /* Get the value to set to, either as a string, a numeric
        !           538:                   value, or a boolean flag */
        !           539:                if( getAssignment( ( char * ) option + index,
        !           540:                           &index, intrinsicType[ intrinsicIndex ] ) != ERROR )
1.1.1.6   root      541:                        processAssignment( intrinsicIndex );
1.1.1.8 ! root      542: 
1.1.1.6   root      543:        return errCount ? -1 : 0;
                    544: }
                    545: 
1.1.1.8 ! root      546: /* Process a configuration file */
        !           547: 
1.1.1.6   root      548: int processConfigFile( char *configFileName )
                    549: {
                    550:        FILE *configFilePtr;
1.1.1.8 ! root      551:        int ch = 0, theChar;
1.1.1.6   root      552:        int errType, errPos = 0, lineBufCount, intrinsicIndex;
1.1.1.8 ! root      553:        int index;
1.1.1.6   root      554:        char inBuffer[ LINEBUF_SIZE ];
                    555: 
                    556:        line = 1;
                    557:        errCount = 0;
1.1.1.8 ! root      558:        errtag = file_tail( configFileName );
1.1.1.6   root      559: 
1.1.1.8 ! root      560:        if( ( configFilePtr = fopen( configFileName, FOPRTXT ) ) == NULL )
        !           561:                {
        !           562:                fprintf( stderr, "Cannot open configuration file %s\n",
        !           563:                                 configFileName );
        !           564:                return OK;      /* Treat it as if it were an empty file */
        !           565:                }
1.1.1.6   root      566: 
                    567:        /* Process each line in the configFile */
1.1.1.8 ! root      568:        while( ch != EOF )
        !           569:                {
1.1.1.6   root      570:                /* Skip whitespace */
1.1.1.7   root      571:                while( ( ( ch = getc( configFilePtr ) ) == ' ' || ch == '\t' )
                    572:                      && ch != EOF )
1.1.1.8 ! root      573:                        ;
1.1.1.6   root      574: 
                    575:                /* Get a line into the inBuffer */
                    576:                hasError = FALSE;
                    577:                lineBufCount = 0;
                    578:                errType = NO_ERROR;
                    579:                while( ch != '\r' && ch != '\n' && ch != CPM_EOF && ch != EOF )
1.1.1.8 ! root      580:                        {
1.1.1.6   root      581:                        /* Check for an illegal char in the data */
1.1.1.7   root      582:                        if( ( ch < ' ' || ch > '~' ) &&
1.1.1.8 ! root      583:                                  ch != '\r' && ch != '\n' &&
        !           584:                                  ch != ' ' && ch != '\t' && ch != CPM_EOF &&
        !           585:                                  ch != EOF )
        !           586:                                {
1.1.1.6   root      587:                                if( errType == NO_ERROR )
1.1.1.8 ! root      588:                                        /* Save pos of first illegal char */
1.1.1.6   root      589:                                        errPos = lineBufCount;
                    590:                                errType = ILLEGAL_CHAR_ERROR;
1.1.1.8 ! root      591:                                }
1.1.1.7   root      592: 
1.1.1.8 ! root      593:                        /* Make sure the path is of the correct length.  Note
        !           594:                           that the code is ordered so that a LINELENGTH_ERROR
        !           595:                           takes precedence over an ILLEGAL_CHAR_ERROR */
1.1.1.6   root      596:                        if( lineBufCount > LINEBUF_SIZE )
                    597:                                errType = LINELENGTH_ERROR;
                    598:                        else
                    599:                                inBuffer[ lineBufCount++ ] = ch;
                    600: 
                    601:                        if( ( ch = getc( configFilePtr ) ) == '#' )
1.1.1.8 ! root      602:                                {
1.1.1.7   root      603:                                /* Skip comment section and trailing
                    604:                                   whitespace */
1.1.1.8 ! root      605:                                while( ch != '\r' && ch != '\n' &&
        !           606:                                           ch != CPM_EOF && ch != EOF )
1.1.1.7   root      607:                                  ch = getc( configFilePtr );
1.1.1.6   root      608:                                break;
1.1.1.8 ! root      609:                                }
1.1.1.6   root      610:                        }
                    611: 
                    612:                /* Skip trailing whitespace and add der terminador */
1.1.1.8 ! root      613:                while( lineBufCount &&
        !           614:                       ( ( theChar = inBuffer[ lineBufCount - 1 ] ) == ' ' ||
        !           615:                           theChar == '\t' ) )
1.1.1.7   root      616:                  lineBufCount--;
1.1.1.6   root      617:                inBuffer[ lineBufCount ] = '\0';
                    618: 
                    619:                /* Process the line unless its a blank or comment line */
                    620:                if( lineBufCount && *inBuffer != '#' )
                    621:                        {
1.1.1.8 ! root      622:                        switch( errType )
        !           623:                                {
        !           624:                                case LINELENGTH_ERROR:
        !           625:                                        fprintf( stderr,
        !           626:                                            "%s: line '%.30s...' too long\n",
        !           627:                                                         errtag, inBuffer );
        !           628:                                        errCount++;
        !           629:                                        break;
1.1.1.6   root      630: 
1.1.1.8 ! root      631:                                case ILLEGAL_CHAR_ERROR:
        !           632:                                        fprintf( stderr, "> %s\n  ", inBuffer );
        !           633:                                        fprintf( stderr, "%*s^\n", errPos, "" );
        !           634:                                        fprintf( stderr,
        !           635:                                    "%s: bad character in command on line %d\n",
        !           636:                                                         errtag, line );
        !           637:                                        errCount++;
        !           638:                                        break;
1.1.1.6   root      639: 
1.1.1.8 ! root      640:                                default:
        !           641:                                        for( index = 0;
        !           642:                                             index < LINEBUF_SIZE &&
        !           643:                                             ( ch = inBuffer[ index ] ) != '\0'
        !           644:                                             && ch != ' ' && ch != '\t'
        !           645:                                             && ch != '=';
        !           646:                                             index++ )
        !           647:                                                /*Do nothing*/ ;
        !           648: 
        !           649:                                        /* Try and find the intrinsic.  We
        !           650:                                           don't treat unknown intrinsics as
        !           651:                                           an error to allow older versions to
        !           652:                                           be used with new config files */
        !           653:                                        intrinsicIndex = lookup(inBuffer,
        !           654:                                                index, intrinsics,
        !           655:                                                CONFIG_INTRINSICS );
1.1.1.7   root      656:                                
1.1.1.8 ! root      657:                                        if( intrinsicIndex == ERROR )
        !           658:                                                break;
        !           659: 
        !           660:                                        /* Get the value to set to, either as
        !           661:                                           a string, a numeric value, or a
        !           662:                                           boolean flag */
        !           663:                                        getAssignment( inBuffer + index, &index,
        !           664:                                             intrinsicType[ intrinsicIndex ] );
        !           665:                                        processAssignment( intrinsicIndex );
        !           666:                                        break;
1.1.1.6   root      667:                                }
                    668:                        }
                    669: 
1.1.1.8 ! root      670:                /* Handle special-case of ^Z if configFile came off an
        !           671:                   MSDOS system */
1.1.1.6   root      672:                if( ch == CPM_EOF )
                    673:                        ch = EOF;
                    674: 
                    675:                /* Exit if there are too many errors */
                    676:                if( errCount >= MAX_ERRORS )
                    677:                        break;
                    678: 
                    679:                line++;
1.1.1.8 ! root      680:                }
1.1.1.6   root      681: 
                    682:        fclose( configFilePtr );
                    683: 
                    684:        /* Exit if there were errors */
1.1.1.8 ! root      685:        if( errCount )
        !           686:                {
        !           687:                fprintf( stderr, "%s: %s%d error(s) detected\n\n",
        !           688:                                 configFileName, ( errCount >= MAX_ERRORS ) ?
        !           689:                                 "Maximum level of " : "", errCount );
1.1.1.6   root      690:                return ERROR;
1.1.1.8 ! root      691:                }
1.1.1.6   root      692: 
                    693:        return OK;
                    694: }

unix.superglobalmegacorp.com

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