|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.