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

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

unix.superglobalmegacorp.com

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