BSD 4_3_Net_2 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Sat, 21 Jan 1989 07:20:52 +0000 (23:20 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Sat, 21 Jan 1989 07:20:52 +0000 (23:20 -0800)
Work on file usr/src/kerberosIV/krb/kparse.c

Synthesized-from: CSRG/cd2/net.2

usr/src/kerberosIV/krb/kparse.c [new file with mode: 0644]

diff --git a/usr/src/kerberosIV/krb/kparse.c b/usr/src/kerberosIV/krb/kparse.c
new file mode 100644 (file)
index 0000000..5f53460
--- /dev/null
@@ -0,0 +1,764 @@
+/*
+ * $Source: /mit/kerberos/src/lib/krb/RCS/kparse.c,v $
+ * $Author: jtkohl $
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Purpose:
+ * This module was developed to parse the "~/.klogin" files for
+ * Kerberos-authenticated rlogin/rcp/rsh services.  However, it is
+ * general purpose and can be used to parse any such parameter file.
+ *
+ * The parameter file should consist of one or more entries, with each
+ * entry on a separate line and consisting of zero or more
+ * "keyword=value" combinations.  The keyword is case insensitive, but
+ * the value is not.  Any string may be enclosed in quotes, and
+ * c-style "\" literals are supported.  A comma may be used to
+ * separate the k/v combinations, and multiple commas are ignored.
+ * Whitespace (blank or tab) may be used freely and is ignored.
+ *
+ * Full error processing is available.  When PS_BAD_KEYWORD or
+ * PS_SYNTAX is returned from fGetParameterSet(), the string ErrorMsg
+ * contains a meaningful error message.
+ *
+ * Keywords and their default values are programmed by an external
+ * table.
+ *
+ * Routines:
+ * fGetParameterSet()      parse one line of the parameter file
+ * fGetKeywordValue()      parse one "keyword=value" combo
+ * fGetToken()             parse one token
+ */
+
+#ifndef        lint
+static char rcsid_kparse_c[] =
+"$Header: kparse.c,v 4.5 89/01/21 17:20:39 jtkohl Exp $";
+#endif lint
+
+#include <mit-copyright.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <kparse.h>
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+#define void int
+
+#define MAXKEY          80
+#define MAXVALUE        80
+
+char *malloc();
+char *strcpy();
+
+int LineNbr=1;         /* current line nbr in parameter file */
+char ErrorMsg[80];     /* meaningful only when KV_SYNTAX, PS_SYNTAX,
+                         * or PS_BAD_KEYWORD is returned by
+                         * fGetKeywordValue or fGetParameterSet */
+\f
+int fGetParameterSet( fp,parm,parmcount )
+    FILE *fp;
+    parmtable parm[];
+    int parmcount;
+{
+    int rc,i;
+    char keyword[MAXKEY];
+    char value[MAXVALUE];
+
+    while (TRUE) {
+        rc=fGetKeywordValue(fp,keyword,MAXKEY,value,MAXVALUE);
+
+        switch (rc) {
+
+        case KV_EOF:
+            return(PS_EOF);
+
+        case KV_EOL:
+            return(PS_OKAY);
+
+        case KV_SYNTAX:
+            return(PS_SYNTAX);
+
+        case KV_OKAY:
+            /*
+             * got a reasonable keyword/value pair.  Search the
+             * parameter table to see if we recognize the keyword; if
+             * not, return an error.  If we DO recognize it, make sure
+             * it has not already been given.  If not already given,
+             * save the value.
+             */
+            for (i=0; i<parmcount; i++) {
+                if (strcmp(strutol(keyword),parm[i].keyword)==0) {
+                    if (parm[i].value) {
+                        sprintf(ErrorMsg,"duplicate keyword \"%s\" found",
+                                keyword);
+                        return(PS_BAD_KEYWORD);
+                    }
+                    parm[i].value = strsave( value );
+                    break;
+                }
+            }
+            if (i >= parmcount) {
+                sprintf(ErrorMsg, "unrecognized keyword \"%s\" found",
+                       keyword);
+                return(PS_BAD_KEYWORD);
+            }
+            break;
+
+        default:
+            sprintf(ErrorMsg,
+                   "panic: bad return (%d) from fGetToken()",rc);
+            break;
+        }
+    }
+}
+\f
+/*
+ * Routine: ParmCompare
+ *
+ * Purpose:
+ * ParmCompare checks a specified value for a particular keyword.
+ * fails if keyword not found or keyword found but the value was
+ * different. Like strcmp, ParmCompare returns 0 for a match found, -1
+ * otherwise
+ */
+int ParmCompare( parm, parmcount, keyword, value )
+    parmtable parm[];
+    int parmcount;
+    char *keyword;
+    char *value;
+{
+    int i;
+
+    for (i=0; i<parmcount; i++) {
+        if (strcmp(parm[i].keyword,keyword)==0) {
+            if (parm[i].value) {
+                return(strcmp(parm[i].value,value));
+            } else {
+                return(strcmp(parm[i].defvalue,value));
+            }
+        }
+    }
+    return(-1);
+}
+
+void FreeParameterSet(parm,parmcount)
+    parmtable parm[];
+    int parmcount;
+{
+    int i;
+
+    for (i=0; i<parmcount; i++) {
+        if (parm[i].value) {
+            free(parm[i].value);
+            parm[i].value = (char *)NULL;
+        }
+    }
+}
+\f
+int fGetKeywordValue( fp, keyword, klen, value, vlen )
+    FILE *fp;
+    char *keyword;
+    int klen;
+    char *value;
+    int vlen;
+{
+    int rc;
+    int gotit;
+
+    *keyword = *value = '\0';   /* preset strings to NULL */
+
+    /*
+     * Looking for a keyword.
+     *          return an exception for EOF or BAD_QSTRING
+     *          ignore leading WHITEspace
+     *          ignore any number of leading commas
+     *          newline means we have all the parms for this
+     *                 statement; give an indication that there is
+     *                 nothing more on this line.
+     *          stop looking if we find QSTRING, STRING, or NUMBER
+     *          return syntax error for any other PUNKtuation
+     */
+    gotit = FALSE;
+    do {
+        rc = fGetToken(fp,keyword,klen);
+
+        switch (rc) {
+
+        case GTOK_WHITE:
+            break;
+
+        case GTOK_EOF:
+            return(KV_EOF);
+
+        case GTOK_BAD_QSTRING:
+            sprintf(ErrorMsg,"unterminated string \"%s found",keyword);
+            return(KV_SYNTAX);
+
+        case GTOK_PUNK:
+            if (strcmp("\n",keyword)==0) {
+                return(KV_EOL);
+            } else if (strcmp(",",keyword)!=0) {
+                sprintf(ErrorMsg,"expecting rvalue, found \'%s\'",keyword);
+            }
+            break;
+
+        case GTOK_STRING:
+        case GTOK_QSTRING:
+        case GTOK_NUMBER:
+            gotit = TRUE;
+            break;
+
+        default:
+            sprintf(ErrorMsg,"panic: bad return (%d) from fGetToken()",rc);
+            return(KV_SYNTAX);
+        }
+
+    } while (!gotit);
+
+    /*
+     * now we expect an equal sign.
+     *          skip any whitespace
+     *          stop looking if we find an equal sign
+     *          anything else causes a syntax error
+     */
+    gotit = FALSE;
+    do {
+        rc = fGetToken(fp,value,vlen);
+
+        switch (rc) {
+
+        case GTOK_WHITE:
+            break;
+
+        case GTOK_BAD_QSTRING:
+            sprintf(ErrorMsg,
+                   "expecting \'=\', found unterminated string \"%s",
+                    value);
+            return(KV_SYNTAX);
+
+        case GTOK_PUNK:
+            if (strcmp("=",value)==0) {
+                gotit = TRUE;
+            } else {
+                if (strcmp("\n",value)==0) {
+                    sprintf(ErrorMsg,"expecting \"=\", found newline");
+                    fUngetChar('\n',fp);
+                } else {
+                    sprintf(ErrorMsg,
+                           "expecting rvalue, found \'%s\'",keyword);
+                }
+                return(KV_SYNTAX);
+            }
+            break;
+
+        case GTOK_STRING:
+        case GTOK_QSTRING:
+        case GTOK_NUMBER:
+            sprintf(ErrorMsg,"expecting \'=\', found \"%s\"",value);
+            return(KV_SYNTAX);
+
+        case GTOK_EOF:
+            sprintf(ErrorMsg,"expecting \'=\', found EOF");
+            return(KV_SYNTAX);
+
+        default:
+            sprintf(ErrorMsg,
+                   "panic: bad return (%d) from fGetToken()",rc);
+            return(KV_SYNTAX);
+        }
+
+    } while ( !gotit );
+
+    /*
+     * got the keyword and equal sign, now get a value.
+     *          ignore any whitespace
+     *          any punctuation is a syntax error
+     */
+    gotit = FALSE;
+    do {
+        rc = fGetToken(fp,value,vlen);
+
+        switch (rc) {
+
+        case GTOK_WHITE:
+            break;
+
+        case GTOK_EOF:
+            sprintf(ErrorMsg,"expecting rvalue, found EOF");
+            return(KV_SYNTAX);
+
+        case GTOK_BAD_QSTRING:
+            sprintf(ErrorMsg,"unterminated quoted string \"%s",value);
+            return(KV_SYNTAX);
+
+        case GTOK_PUNK:
+            if (strcmp("\n",value)==0) {
+                sprintf(ErrorMsg,"expecting rvalue, found newline");
+                fUngetChar('\n',fp);
+            } else {
+                sprintf(ErrorMsg,
+                       "expecting rvalue, found \'%s\'",value);
+            }
+            return(KV_SYNTAX);
+            break;
+
+        case GTOK_STRING:
+        case GTOK_QSTRING:
+        case GTOK_NUMBER:
+            gotit = TRUE;
+            return(KV_OKAY);
+
+        default:
+            sprintf(ErrorMsg,
+                   "panic: bad return (%d) from fGetToken()",rc);
+            return(KV_SYNTAX);
+        }
+
+    } while ( !gotit );
+    /*NOTREACHED*/
+}
+\f
+/*
+ * Routine Name: fGetToken
+ *
+ * Function: read the next token from the specified file.
+ * A token is defined as a group of characters
+ * terminated by a white space char (SPACE, CR,
+ * LF, FF, TAB). The token returned is stripped of
+ * both leading and trailing white space, and is
+ * terminated by a NULL terminator.  An alternate
+ * definition of a token is a string enclosed in
+ * single or double quotes.
+ *
+ * Explicit Parameters:
+ * fp              pointer to the input FILE
+ * dest    pointer to destination buffer
+ * maxlen  length of the destination buffer. The buffer
+ * length INCLUDES the NULL terminator.
+ *
+ * Implicit Parameters: stderr  where the "token too long" message goes
+ *
+ * External Procedures: fgetc
+ *
+ * Side Effects:                None
+ *
+ * Return Value:                A token classification value, as
+ *                             defined in kparse.h. Note that the
+ *                             classification for end of file is
+ *                             always zero.
+ */
+int fGetToken(fp, dest, maxlen)
+    FILE *fp;
+    char *dest;
+    int  maxlen;
+{
+    int ch='\0';
+    int len=0;
+    char *p = dest;
+    int digits;
+
+    ch=fGetChar(fp);
+
+    /*
+     * check for a quoted string.  If found, take all characters
+     * that fit until a closing quote is found.  Note that this
+     * algorithm will not behave well for a string which is too long.
+     */
+    if (ISQUOTE(ch)) {
+        int done = FALSE;
+        do {
+            ch = fGetChar(fp);
+            done = ((maxlen<++len)||ISLINEFEED(ch)||(ch==EOF)
+                   ||ISQUOTE(ch));
+            if (ch=='\\')
+                ch = fGetLiteral(fp);
+            if (!done)
+                *p++ = ch;
+            else if ((ch!=EOF) && !ISQUOTE(ch))
+                fUngetChar(ch,fp);
+        } while (!done);
+        *p = '\0';
+        if (ISLINEFEED(ch)) return(GTOK_BAD_QSTRING);
+        return(GTOK_QSTRING);
+    }
+
+    /*
+     * Not a quoted string.  If its a token character (rules are
+     * defined via the ISTOKENCHAR macro, in kparse.h) take it and all
+     * token chars following it until we run out of space.
+     */
+    digits=TRUE;
+    if (ISTOKENCHAR(ch)) {
+        while ( (ISTOKENCHAR(ch)) && len<maxlen-1 ) {
+            if (!isdigit(ch)) digits=FALSE;
+            *p++ = ch;
+            len++;
+            ch = fGetChar(fp);
+        };
+        *p = '\0';
+
+        if (ch!=EOF) {
+            fUngetChar(ch,fp);
+        }
+        if (digits) {
+            return(GTOK_NUMBER);
+        } else {
+            return(GTOK_STRING);
+        }
+    }
+
+    /*
+     * Neither a quoted string nor a token character.  Return a string
+     * with just that one character in it.
+     */
+    if (ch==EOF) {
+        return(GTOK_EOF);
+    }
+    if (!ISWHITESPACE(ch)) {
+        *p++ = ch;
+        *p='\0';
+    } else {
+        *p++ = ' ';            /* white space is always the
+                                * blank character */
+        *p='\0';
+        /*
+         * The character is a white space. Flush all additional white
+         * space.
+         */
+        while (ISWHITESPACE(ch) && ((ch=fGetChar(fp)) != EOF))
+            ;
+        if (ch!=EOF) {
+            fUngetChar(ch,fp);
+        }
+        return(GTOK_WHITE);
+    }
+    return(GTOK_PUNK);
+}
+\f
+/*
+ * fGetLiteral is called after we find a '\' in the input stream.  A
+ * string of numbers following the backslash are converted to the
+ * appropriate value; hex (0xn), octal (0n), and decimal (otherwise)
+ * are all supported.  If the char after the \ is not a number, we
+ * special case certain values (\n, \f, \r, \b) or return a literal
+ * otherwise (useful for \", for example).
+ */
+fGetLiteral(fp)
+    FILE *fp;
+{
+    int ch;
+    int n=0;
+    int base;
+
+    ch = fGetChar(fp);
+
+    if (!isdigit(ch)) {
+        switch (ch) {
+        case 'n':       return('\n');
+        case 'f':       return('\f');
+        case 'r':       return('\r');
+        case 'b':       return('\b');
+        default:        return(ch);
+        }
+    }
+
+    /*
+     * got a number.  might be decimal (no prefix), octal (prefix 0),
+     * or hexadecimal (prefix 0x).  Set the base appropriately.
+     */
+    if (ch!='0') {
+        base=10;                /* its a decimal number */
+    } else {
+        /*
+         * found a zero, its either hex or octal
+         */
+        ch = fGetChar(fp);
+        if ((ch!='x') && (ch!='X')) {
+            base=010;
+        } else {
+            ch = fGetChar(fp);
+            base=0x10;
+        }
+    }
+
+    switch (base) {
+
+    case 010:                   /* octal */
+        while (ISOCTAL(ch)) {
+            n = (n*base) + ch - '0';
+            ch = fGetChar(fp);
+        }
+        break;
+
+    case 10:                    /* decimal */
+        while (isdigit(ch)) {
+            n = (n*base) + ch - '0';
+            ch = fGetChar(fp);
+        }
+        break;
+    case 0x10:                  /* hexadecimal */
+        while (isxdigit(ch)) {
+            if (isdigit(ch)) {
+                n = (n*base) + ch - '0';
+            } else {
+                n = (n*base) + toupper(ch) - 'A' + 0xA ;
+            }
+            ch = fGetChar(fp);
+        }
+        break;
+    default:
+        fprintf(stderr,"fGetLiteral() died real bad. Fix gettoken.c.");
+        exit(1);
+        break;
+    }
+    fUngetChar(ch,fp);
+    return(n);
+}
+\f
+/*
+ * exactly the same as ungetc(3) except that the line number of the
+ * input file is maintained.
+ */
+fUngetChar(ch,fp)
+    int ch;
+    FILE *fp;
+{
+    if (ch=='\n') LineNbr--;
+    return(ungetc(ch,fp));
+}
+
+
+/*
+ * exactly the same as fgetc(3) except that the line number of the
+ * input file is maintained.
+ */
+fGetChar(fp)
+    FILE *fp;
+{
+    int ch = fgetc(fp);
+    if (ch=='\n') LineNbr++;
+    return(ch);
+}
+
+
+/*
+ * Routine Name: strsave
+ *
+ * Function: return a pointer to a saved copy of the
+ * input string. the copy will be allocated
+ * as large as necessary.
+ *
+ * Explicit Parameters: pointer to string to save
+ *
+ * Implicit Parameters: None
+ *
+ * External Procedures: malloc,strcpy,strlen
+ *
+ * Side Effects: None
+ *
+ * Return Value: pointer to copied string
+ *
+ */
+char * strsave(p)
+    char *p;
+{
+    return(strcpy(malloc(strlen(p)+1),p));
+}
+
+
+/*
+ * strutol changes all characters in a string to lower case, in place.
+ * the pointer to the beginning of the string is returned.
+ */
+
+char * strutol( start )
+    char *start;
+{
+    char *q;
+    for (q=start; *q; q++)
+        if (isupper(*q))
+           *q=tolower(*q);
+    return(start);
+}
+\f
+#ifdef GTOK_TEST            /* mainline test routine for fGetToken() */
+
+#define MAXTOKEN 100
+
+char *pgm = "gettoken";
+
+main(argc,argv)
+    int argc;
+    char **argv;
+{
+    char *p;
+    int type;
+    FILE *fp;
+
+    if (--argc) {
+        fp = fopen(*++argv,"ra");
+        if (fp == (FILE *)NULL) {
+            fprintf(stderr,"can\'t open \"%s\"\n",*argv);
+        }
+    } else
+        fp = stdin;
+
+    p = malloc(MAXTOKEN);
+    while (type = fGetToken(fp,p,MAXTOKEN)) {
+        switch(type) {
+        case GTOK_BAD_QSTRING:
+           printf("BAD QSTRING!\t");
+           break;
+        case GTOK_EOF:
+           printf("EOF!\t");
+           break;
+        case GTOK_QSTRING:
+           printf("QSTRING\t");
+           break;
+        case GTOK_STRING:
+           printf("STRING\t");
+           break;
+        case GTOK_NUMBER:
+           printf("NUMBER\t");
+           break;
+        case GTOK_PUNK:
+           printf("PUNK\t");
+           break;
+        case GTOK_WHITE:
+           printf("WHITE\t");
+           break;
+        default:
+           printf("HUH?\t");
+           break;
+        }
+        if (*p=='\n')
+            printf("\\n\n");
+       else
+            printf("%s\n",p);
+    }
+    exit(0);
+}
+#endif
+\f
+#ifdef KVTEST
+
+main(argc,argv)
+    int argc;
+    char **argv;
+{
+    int rc,ch;
+    FILE *fp;
+    char key[MAXKEY],valu[MAXVALUE];
+    char *filename;
+
+    if (argc != 2) {
+        fprintf(stderr,"usage: test <filename>\n");
+        exit(1);
+    }
+
+    if (!(fp=fopen(*++argv,"r"))) {
+        fprintf(stderr,"can\'t open input file \"%s\"\n",filename);
+        exit(1);
+    }
+    filename = *argv;
+
+    while ((rc=fGetKeywordValue(fp,key,MAXKEY,valu,MAXVALUE))!=KV_EOF){
+
+        switch (rc) {
+
+        case KV_EOL:
+            printf("%s, line %d: nada mas.\n",filename,LineNbr-1);
+            break;
+
+        case KV_SYNTAX:
+            printf("%s, line %d: syntax error: %s\n",
+                   filename,LineNbr,ErrorMsg);
+            while ( ((ch=fGetChar(fp))!=EOF) && (ch!='\n') );
+            break;
+
+        case KV_OKAY:
+            printf("%s, line %d: okay, %s=\"%s\"\n",
+                   filename,LineNbr,key,valu);
+            break;
+
+        default:
+            printf("panic: bad return (%d) from fGetKeywordValue\n",rc);
+            break;
+        }
+    }
+    printf("EOF");
+    fclose(fp);
+    exit(0);
+}
+#endif
+\f
+#ifdef PSTEST
+
+parmtable kparm[] = {
+    /*  keyword, default, found value */
+    { "user",       "",    (char *)NULL },
+    { "realm",   "Athena", (char *)NULL },
+    { "instance",   "",    (char *)NULL }
+};
+
+main(argc,argv)
+    int argc;
+    char **argv;
+{
+    int rc,i,ch;
+    FILE *fp;
+    char *filename;
+
+    if (argc != 2) {
+        fprintf(stderr,"usage: test <filename>\n");
+        exit(1);
+    }
+
+    if (!(fp=fopen(*++argv,"r"))) {
+        fprintf(stderr,"can\'t open input file \"%s\"\n",filename);
+        exit(1);
+    }
+    filename = *argv;
+
+    while ((rc=fGetParameterSet(fp,kparm,PARMCOUNT(kparm))) != PS_EOF) {
+
+        switch (rc) {
+
+        case PS_BAD_KEYWORD:
+            printf("%s, line %d: %s\n",filename,LineNbr,ErrorMsg);
+            while ( ((ch=fGetChar(fp))!=EOF) && (ch!='\n') );
+            break;
+
+        case PS_SYNTAX:
+            printf("%s, line %d: syntax error: %s\n",
+                   filename,LineNbr,ErrorMsg);
+            while ( ((ch=fGetChar(fp))!=EOF) && (ch!='\n') );
+            break;
+
+        case PS_OKAY:
+            printf("%s, line %d: valid parameter set found:\n",
+                   filename,LineNbr-1);
+            for (i=0; i<PARMCOUNT(kparm); i++) {
+                printf("\t%s = \"%s\"\n",kparm[i].keyword,
+                       (kparm[i].value ? kparm[i].value
+                       : kparm[i].defvalue));
+            }
+            break;
+
+        default:
+            printf("panic: bad return (%d) from fGetParameterSet\n",rc);
+            break;
+        }
+        FreeParameterSet(kparm,PARMCOUNT(kparm));
+    }
+    printf("EOF");
+    fclose(fp);
+    exit(0);
+}
+#endif