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

1.1       root        1: /*     config.c  - config file parser by Peter Gutmann
                      2:        Parses config file for PGP
                      3: 
                      4:        Modified 24 Jun 92 - HAJK
                      5:        Misc fixes for VAX C restrictions.
                      6: 
                      7: */
                      8: 
                      9: #include <ctype.h>
                     10: #include <string.h>
                     11: #include <stdio.h>
                     12: #include <stdlib.h>
                     13: #include "usuals.h"
                     14: #include "pgp.h"
                     15: /* The external config variables we can set here are referenced in pgp.h */
                     16: 
                     17: /* Return values */
                     18: 
                     19: #define ERROR  -1
                     20: #define OK             0
                     21: 
                     22: /* The types of error we check for */
                     23: 
                     24: enum { NO_ERROR, ILLEGAL_CHAR_ERROR, LINELENGTH_ERROR };
                     25: 
                     26: #define CPM_EOF                        0x1A    /* ^Z = CPM EOF char */
                     27: 
                     28: #define MAX_ERRORS             3               /* Max.no.errors before we give up */
                     29: 
                     30: #define LINEBUF_SIZE   100             /* Size of input buffer */
                     31: 
                     32: int line;                                              /* The line on which an error occurred */
                     33: int errCount;                                  /* Total error count */
                     34: boolean hasError;                              /* Whether this line has an error in it */
                     35: 
                     36: /* The settings parsed out by getAssignment() */
                     37: 
                     38: char str[ LINEBUF_SIZE ];
                     39: int value;
                     40: boolean flag;
                     41: 
                     42: /* A .CFG file roughly follows the format used in the world-famous HPACK
                     43:    archiver and is as follows:
                     44: 
                     45:        - Leading spaces/tabs (whitespace) are ignored.
                     46: 
                     47:        - Lines with a '#' as the first non-whitespace character are treated as
                     48:          comment lines.
                     49: 
                     50:        - All other lines are treated as config options for the program.
                     51: 
                     52:        - Lines may be terminated by either linefeeds, carriage returns, or
                     53:          carriage return/linefeed pairs (the latter being the DOS default method
                     54:          of storing text files).
                     55: 
                     56:        - Config options have the form:
                     57: 
                     58:          <option> '=' <setting>
                     59: 
                     60:          where <setting> may be 'on', 'off', a numeric value, or a string
                     61:          value.
                     62: 
                     63:        - If strings have spaces or the '#' character inside them they must be
                     64:          surrounded by quote marks '"' */
                     65: 
                     66: /* The types of input we can expect */
                     67: 
                     68: typedef enum { BOOL, NUMERIC, STRING } INPUT_TYPE;
                     69: 
                     70: /* Intrinsic variables */
                     71: 
                     72: #define NO_INTRINSICS          17
                     73: 
                     74: enum
                     75: {      ARMOR, COMPRESS, SHOWPASS, KEEPBINARY, LANGUAGE,
                     76:        MYNAME, TEXTMODE, TMP, TZFIX, VERBOSE, BAKRING,
                     77:        ARMORLINES, COMPLETES_NEEDED, MARGINALS_NEEDED, PAGER,
                     78:        CERT_DEPTH, CHARSET
                     79: };
                     80: 
                     81: char *intrinsics[] =
                     82: {      "ARMOR", "COMPRESS", "SHOWPASS", "KEEPBINARY", "LANGUAGE",
                     83:        "MYNAME", "TEXTMODE", "TMP", "TZFIX", "VERBOSE", "BAKRING",
                     84:        "ARMORLINES", "COMPLETES_NEEDED", "MARGINALS_NEEDED", "PAGER",
                     85:        "CERT_DEPTH", "CHARSET"
                     86: };
                     87: 
                     88: INPUT_TYPE intrinsicType[] =
                     89: {      BOOL, BOOL, BOOL, BOOL, STRING,
                     90:        STRING, BOOL, STRING, NUMERIC, BOOL, STRING,
                     91:        NUMERIC, NUMERIC, NUMERIC, STRING,
                     92:        NUMERIC, STRING
                     93: };
                     94: 
                     95: /* Possible settings for variables */
                     96: 
                     97: #define NO_SETTINGS                    2
                     98: 
                     99: char *settings[] = { "OFF", "ON" };
                    100: 
                    101: 
                    102: /* Search a list of keywords for a match */
                    103: 
                    104: int lookup( char *key, int keyLength, char *keyWords[], int range )
                    105:        {
                    106:        int index;
                    107: 
                    108:        /* Make the search case insensitive */
                    109:        for( index = 0; index < keyLength; index++ )
                    110:                key[ index ] = toupper( key[ index ] );
                    111: 
                    112:        for( index = 0; index < range; index++ )
                    113:                if( !strncmp( key, keyWords[ index ], keyLength ) )
                    114:                        return( index );
                    115: 
                    116:        /* Key not found */
                    117:        return( ERROR );
                    118:        }
                    119: 
                    120: /* Extract a token from a buffer */
                    121: int extractToken( char *buffer, int *endIndex, int *length )
                    122: {
                    123:        int index = 0, tokenStart;
                    124:        char ch;
                    125: 
                    126:        /* Skip whitespace */
                    127:        for( ch = buffer[ index ]; ch && ( ch == ' ' || ch == '\t' ); ch = buffer[ index ] )
                    128:                index++;
                    129:        tokenStart = index;
                    130: 
                    131:        /* Find end of setting */
                    132:        while( index < LINEBUF_SIZE && ( ch = buffer[ index ] ) != '\0' && ch != ' ' && ch != '\t' )
                    133:                index++;
                    134:        *endIndex += index;
                    135:        *length = index - tokenStart;
                    136: 
                    137:        /* Return start position of token in buffer */
                    138:        return( tokenStart );
                    139: }
                    140: 
                    141: 
                    142: /* Get a string constant */
                    143: int getaString( char *buffer, int *endIndex )
                    144:        {
                    145:        boolean noQuote = FALSE;
                    146:        int stringIndex = 0, bufIndex = 1;
                    147:        char ch = *buffer;
                    148: 
                    149:        /* Skip whitespace */
                    150:        while( ch && ( ch == ' ' || ch == '\t' ) )
                    151:                ch = buffer[ bufIndex++ ];
                    152: 
                    153:        /* Check for non-string */
                    154:        if( ch != '\"' )
                    155:                {
                    156:                *endIndex += bufIndex;
                    157: 
                    158:                /* Check for special case of null string */
                    159:                if( !ch )
                    160:                        {
                    161:                        *str = '\0';
                    162:                        return( OK );
                    163:                        }
                    164: 
                    165:                /* Use nasty non-rigorous string format */
                    166:                noQuote = TRUE;
                    167:                }
                    168: 
                    169:        /* Get first char of string */
                    170:        if( !noQuote )
                    171:                ch = buffer[ bufIndex++ ];
                    172: 
                    173:        /* Get string into string */
                    174:        while( ch && ch != '\"' )
                    175:                {
                    176:                /* Exit on '#' if using non-rigorous format */
                    177:                if( noQuote && ch == '#' )
                    178:                        break;
                    179: 
                    180:                str[ stringIndex++ ] = ch;
                    181:                ch = buffer[ bufIndex++ ];
                    182:                }
                    183: 
                    184:        /* If using the non-rigorous format, stomp trailing spaces */
                    185:        if( noQuote )
                    186:                while( stringIndex > 0 && str[ stringIndex - 1 ] == ' ' )
                    187:                        stringIndex--;
                    188: 
                    189:        str[ stringIndex++ ] = '\0';
                    190:        *endIndex += bufIndex;
                    191: 
                    192:        /* Check for missing string terminator */
                    193:        if( ch != '\"' && !noQuote )
                    194:                {
                    195:                printf( "Unterminated string in line %d\n", line );
                    196:                hasError = TRUE;
                    197:                errCount++;
                    198:                return( ERROR );
                    199:                }
                    200: 
                    201:        return( OK );
                    202:        }
                    203: 
                    204: /* Get an assignment to an intrinsic */
                    205: int getAssignment( char *buffer, int *endIndex, INPUT_TYPE settingType )
                    206: {
                    207:        int settingIndex = 0, length;
                    208: 
                    209:        buffer += extractToken( buffer, endIndex, &length );
                    210: 
                    211:        /* Check for an assignment operator */
                    212:        if ( *buffer != '=' )
                    213:        {
                    214:                printf( "Expected '=' in line %d\n", line );
                    215:                hasError = TRUE;
                    216:                errCount++;
                    217:                return( ERROR );
                    218:        }
                    219:        buffer++;               /* Skip '=' */
                    220: 
                    221:        buffer += extractToken( buffer, endIndex, &length );
                    222: 
                    223:        switch( settingType )
                    224:        {
                    225:                case BOOL:
                    226:                        /* Check for known intrinsic - really more general than just
                    227:                           checking for TRUE or FALSE */
                    228:                        if( ( settingIndex = lookup( buffer, length, settings, NO_SETTINGS ) ) == ERROR )
                    229:                        {
                    230:                                printf( "Unknown setting '%s' in line %d\n", buffer, line );
                    231:                                hasError = TRUE;
                    232:                                errCount++;
                    233:                                return( ERROR );
                    234:                        }
                    235: 
                    236:                        flag = ( settingIndex == 0 ) ? FALSE : TRUE;
                    237:                        break;
                    238: 
                    239:                case STRING:
                    240:                        /* Get a string */
                    241:                        getaString( buffer, &length );
                    242:                        break;
                    243: 
                    244:                case NUMERIC:
                    245:                        /* Get numeric input.  Error checking is a pain since atoi()
                    246:                                has no real equivalent of NAN */
                    247:                        value = atoi( buffer );
                    248:                        break;
                    249:        }
                    250: 
                    251:        return( settingIndex );
                    252: }
                    253: 
                    254: 
                    255: /* Process a config file */
                    256: int processConfigFile( char *configFileName )
                    257: {
                    258:        FILE *configFilePtr;
                    259:        int ch = 0, theCh;
                    260:        int errType, errPos = 0, lineBufCount, intrinsicIndex;
                    261:        int index;
                    262:        char inBuffer[ LINEBUF_SIZE ];
                    263: 
                    264:        line = 1;
                    265:        errCount = 0;
                    266: 
                    267:        if( ( configFilePtr = fopen( configFileName, "r" ) ) == NULL )
                    268:        {
                    269:                printf( "Cannot open configuration file %s\n", configFileName );
                    270:                return( OK );   /* treat like empty config file */
                    271:        }
                    272: 
                    273:        /* Process each line in the configFile */
                    274:        while( ch != EOF )
                    275:        {
                    276:                /* Skip whitespace */
                    277:                while( ( ( ch = getc( configFilePtr ) ) == ' ' || ch == '\t' ) && ch != EOF );
                    278: 
                    279:                /* Get a line into the inBuffer */
                    280:                hasError = FALSE;
                    281:                lineBufCount = 0;
                    282:                errType = NO_ERROR;
                    283:                while( ch != '\r' && ch != '\n' && ch != CPM_EOF && ch != EOF )
                    284:                {
                    285:                        /* Check for an illegal char in the data */
                    286:                        if( ( ch < ' ' || ch > '~' ) && ch != '\r' && ch != '\n' &&
                    287:                                ch != ' ' && ch != '\t' && ch != CPM_EOF && ch != EOF )
                    288:                        {
                    289:                                if( errType == NO_ERROR )
                    290:                                        /* Save position of first illegal char */
                    291:                                        errPos = lineBufCount;
                    292:                                errType = ILLEGAL_CHAR_ERROR;
                    293:                        }
                    294: 
                    295:                        /* Make sure the path is of the correct length.  Note that the
                    296:                           code is ordered so that a LINELENGTH_ERROR takes precedence over
                    297:                           an ILLEGAL_CHAR_ERROR */
                    298:                        if( lineBufCount > LINEBUF_SIZE )
                    299:                                errType = LINELENGTH_ERROR;
                    300:                        else
                    301:                                inBuffer[ lineBufCount++ ] = ch;
                    302: 
                    303:                        if( ( ch = getc( configFilePtr ) ) == '#' )
                    304:                        {
                    305:                                /* Skip comment section and trailing whitespace */
                    306:                                while( ch != '\r' && ch != '\n' && ch != CPM_EOF && ch != EOF )
                    307:                                        ch = getc( configFilePtr );
                    308:                                break;
                    309:                        }
                    310:                }
                    311: 
                    312:                /* Skip trailing whitespace and add der terminador */
                    313:                while( ( theCh = inBuffer[ lineBufCount - 1 ] ) == ' ' || theCh == '\t' )
                    314:                        lineBufCount--;
                    315:                inBuffer[ lineBufCount ] = '\0';
                    316: 
                    317:                /* Process the line unless its a blank or comment line */
                    318:                if( lineBufCount && *inBuffer != '#' )
                    319:                {
                    320:                        switch( errType )
                    321:                        {
                    322:                                case LINELENGTH_ERROR:
                    323:                                        inBuffer[ 80 - strlen( "Line '%s...' too long\n" ) - 3 ] = '\0';
                    324:                                                                /* Truncate to fit screen size (3 = '%s' + 1) */
                    325:                                        printf( "Line '%s...' too long\n", inBuffer );
                    326:                                        errCount++;
                    327:                                        break;
                    328: 
                    329:                                case ILLEGAL_CHAR_ERROR:
                    330:                                        printf( "> %s\n  ", inBuffer );
                    331:                                        while( errPos-- )
                    332:                                                putchar( ' ' );
                    333:                                        printf( "^ Bad character in command on line %d\n", line );
                    334:                                        errCount++;
                    335:                                        break;
                    336: 
                    337:                                default:
                    338:                                        for( index = 0;
                    339:                                                 index < LINEBUF_SIZE && ( ch = inBuffer[ index ] ) != '\0' && ch != ' ' && ch != '\t';
                    340:                                                 index++ );
                    341:                                        if( ( intrinsicIndex = lookup( inBuffer, index, intrinsics, NO_INTRINSICS ) ) == ERROR )
                    342:                                        {
                    343:                                                printf( "Unknown command '%s' in line %d\n", inBuffer, line );
                    344:                                                errCount++;
                    345:                                        }
                    346:                                        else
                    347:                                        {
                    348:                                                /* Get the value to set to, either as a string, a
                    349:                                                   numeric value, or a boolean flag */
                    350:                                                getAssignment( inBuffer + index, &index, intrinsicType[ intrinsicIndex ] );
                    351: 
                    352:                                                if( !hasError )
                    353:                                                        switch( intrinsicIndex )
                    354:                                                        {
                    355:                                                                case ARMOR:
                    356:                                                                        emit_radix_64 = flag;
                    357:                                                                        break;
                    358: 
                    359:                                                                case COMPRESS:
                    360:                                                                        compress_enabled = flag;
                    361:                                                                        break;
                    362: 
                    363:                                                                case SHOWPASS:
                    364:                                                                        showpass = flag;
                    365:                                                                        break;
                    366: 
                    367:                                                                case KEEPBINARY:
                    368:                                                                        keepctx = flag;
                    369:                                                                        break;
                    370: 
                    371:                                                                case LANGUAGE:
                    372:                                                                        strncpy(language, str, 15);
                    373:                                                                        break;
                    374: 
                    375:                                                                case BAKRING:
                    376:                                                                        strcpy(floppyring, str);
                    377:                                                                        break;
                    378: 
                    379:                                                                case MYNAME:
                    380:                                                                        strcpy(my_name, str);
                    381:                                                                        break;
                    382: 
                    383:                                                                case TEXTMODE:
                    384:                                                                        if( flag )
                    385:                                                                                lit_mode = MODE_TEXT;
                    386:                                                                        break;
                    387: 
                    388:                                                                case TMP:
                    389:                                                                        /* directory pathname to store temp files */
                    390:                                                                        strcpy(tmpdir, str);
                    391:                                                                        break;
                    392: 
                    393:                                                                case TZFIX:
                    394:                                                                        /* How many hours to add to time() to get GMT. */
                    395:                                                                        /* Compute seconds from hours to shift to GMT: */
                    396:                                                                        timeshift = 3600L * (long) value;
                    397:                                                                        break;
                    398: 
                    399:                                                                case VERBOSE:
                    400:                                                                        verbose = flag;
                    401:                                                                        break;
                    402:                                                                
                    403:                                                                case ARMORLINES:
                    404:                                                                        pem_lines = value;
                    405:                                                                        break;
                    406: 
                    407:                                                                case MARGINALS_NEEDED:
                    408:                                                                        marg_min = value;
                    409:                                                                        if (marg_min < 1) 
                    410:                                                                                marg_min = 1;
                    411:                                                                        break;
                    412: 
                    413:                                                                case COMPLETES_NEEDED:
                    414:                                                                        compl_min = value;
                    415:                                                                        if (compl_min < 1) 
                    416:                                                                                compl_min = 1;
                    417:                                                                        if (compl_min > 4) 
                    418:                                                                                compl_min = 4;
                    419:                                                                        break;
                    420: 
                    421:                                                                case CERT_DEPTH:
                    422:                                                                        max_cert_depth = value;
                    423:                                                                        if (max_cert_depth < 0) 
                    424:                                                                                max_cert_depth = 0;
                    425:                                                                        if (max_cert_depth > 8) 
                    426:                                                                                max_cert_depth = 8;
                    427:                                                                        break;
                    428: 
                    429:                                                                case PAGER:
                    430:                                                                        strcpy(pager, str);
                    431:                                                                        break;
                    432:                                                                
                    433:                                                                case CHARSET:
                    434:                                                                        strcpy(charset, str);
                    435:                                                                        break;
                    436: 
                    437:                                                        }
                    438:                                        }
                    439:                        }
                    440:                }
                    441: 
                    442:                /* Handle special-case of ^Z if configFile came off an MSDOS system */
                    443:                if( ch == CPM_EOF )
                    444:                        ch = EOF;
                    445: 
                    446:                /* Exit if there are too many errors */
                    447:                if( errCount >= MAX_ERRORS )
                    448:                        break;
                    449: 
                    450:                line++;
                    451:        }
                    452: 
                    453:        fclose( configFilePtr );
                    454: 
                    455:        /* Exit if there were errors */
                    456:        if( errCount )
                    457:        {
                    458:                printf( "%s%d errors detected\n", ( errCount >= MAX_ERRORS ) ?
                    459:                                "Maximum level of " : "", errCount );
                    460:                return( ERROR );
                    461:        }
                    462: 
                    463:        return( OK );
                    464: }

unix.superglobalmegacorp.com

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