]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
correct parsing and processing of setvar directive.
authorDave Hart <hart@ntp.org>
Mon, 21 Sep 2009 04:57:32 +0000 (04:57 +0000)
committerDave Hart <hart@ntp.org>
Mon, 21 Sep 2009 04:57:32 +0000 (04:57 +0000)
highlight location of ntpq :config syntax errors with ^.

bk: 4ab707bcBH594vNjY_NxzQrhXq4cTw

ChangeLog
include/ntp_config.h
ntpd/ntp_config.c
ntpd/ntp_scanner.c
ntpd/ntp_scanner.h
ntpq/ntpq-subs.c
ntpq/ntpq.h

index 9536cbc4873a7fc9051050c13634c9ffa93d5381..f7cca1e9c789b5291d6abeca8bd5e63c919e5d03 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,6 @@
 * [Bug 1314] saveconfig emits -4 and -6 on when not given.
+* correct parsing and processing of setvar directive.
+* highlight location of ntpq :config syntax errors with ^.
 * clarify (former) NO_ARG, SINGLE_ARG, MULTIPLE_ARG renaming to
   FOLLBY_TOKEN, FOLLBY_STRING, FOLLBY_STRINGS_TO_EOC.
 * parser, saveconfig cleanup to store T_ identifiers in syntax tree.
index d54ecde0425e836beade1c5280b5c33f5c549205..4b3000e46a20010532261f8500ecb602ff635f0b 100644 (file)
@@ -111,7 +111,8 @@ struct filegen_node {
 };
 
 struct setvar_node {
-       char *  data;
+       char *  var;
+       char *  val;
        int     isdefault;
 };
 
index b49a7c480897d7591a62ab3acaacbe16c60e508a..1cdc3708c4dfdf03af418d7284716b20ce7b15b8 100644 (file)
@@ -610,53 +610,50 @@ dump_config_tree(
        }
 
        list_ptr = queue_head(ptree->filegen_opts);
-       if (list_ptr != NULL) {
-
-               for(;   list_ptr != NULL;
-                       list_ptr = next_node(list_ptr)) {
-
-                       fgen_node = list_ptr;
-                       opt_ptr = queue_head(fgen_node->options);
+       for(;   list_ptr != NULL;
+               list_ptr = next_node(list_ptr)) {
 
-                       if (opt_ptr != NULL)
-                               fprintf(df, "filegen %s", 
-                                       keyword(fgen_node->filegen_token));
+               fgen_node = list_ptr;
+               opt_ptr = queue_head(fgen_node->options);
 
-                       for(;   opt_ptr != NULL;
-                               opt_ptr = next_node(opt_ptr)) {
-                               
-                               atrv = (struct attr_val *) opt_ptr;
+               if (opt_ptr != NULL)
+                       fprintf(df, "filegen %s", 
+                               keyword(fgen_node->filegen_token));
 
-                               switch (atrv->attr) {
+               for(;   opt_ptr != NULL;
+                       opt_ptr = next_node(opt_ptr)) {
+                       
+                       atrv = opt_ptr;
 
-                               default:
-                                       fprintf(df, "\n# dump error:\n"
-                                               "# unknown filegen option token %d\n"
-                                               "filegen %s",
-                                               atrv->type,
-                                               keyword(fgen_node->filegen_token));
-                                       break;
+                       switch (atrv->attr) {
 
-                               case T_File:
-                                       fprintf(df, " file %s",
-                                               atrv->value.s);
-                                       break;
+                       default:
+                               fprintf(df, "\n# dump error:\n"
+                                       "# unknown filegen option token %s\n"
+                                       "filegen %s",
+                                       token_name(atrv->attr),
+                                       keyword(fgen_node->filegen_token));
+                               break;
 
-                               case T_Type:
-                                       fprintf(df, " type %s",
-                                               keyword(atrv->value.i));
-                                       break;
+                       case T_File:
+                               fprintf(df, " file %s",
+                                       atrv->value.s);
+                               break;
 
-                               case T_Flag:
-                                       fprintf(df, " %s",
-                                               keyword(atrv->value.i));
-                                       break;
-                               }
+                       case T_Type:
+                               fprintf(df, " type %s",
+                                       keyword(atrv->value.i));
+                               break;
 
+                       case T_Flag:
+                               fprintf(df, " %s",
+                                       keyword(atrv->value.i));
+                               break;
                        }
 
-                       fprintf(df, "\n");
                }
+
+               fprintf(df, "\n");
        }
 
        list_ptr = queue_head(ptree->auth.crypto_cmd_list);
@@ -1026,7 +1023,11 @@ dump_config_tree(
                list_ptr = next_node(list_ptr)) {
 
                setv_node = list_ptr;
-               fprintf(df, "setvar %s", setv_node->data);
+               s1 = quote_if_needed(setv_node->var);
+               s2 = quote_if_needed(setv_node->val);
+               fprintf(df, "setvar %s = %s", s1, s2);
+               free(s1);
+               free(s2);
 
                if (setv_node->isdefault)
                        fprintf(df, " default");
@@ -1442,20 +1443,19 @@ create_setvar_node(
        int     isdefault
        )
 {
-       int octets;
-       char *s;
+       char *  pch;
        struct setvar_node *my_node;
 
-       octets = strlen(var) + strlen(val) + 4; /* " = " + NUL */
-       s = emalloc(octets);
-       snprintf(s, octets, "%s = %s", var, val);
-       free(var);
-       free(val);
+       /* do not allow = in the variable name */
+       if (NULL != (pch = strchr(var, '=')))
+               *pch = '\0';
 
        /* Now store the string into a setvar_node */
        my_node = get_node(sizeof *my_node);
-       my_node->data = s;
+       my_node->var = var;
+       my_node->val = val;
        my_node->isdefault = isdefault;
+
        return my_node;
 }
 
@@ -2759,15 +2759,25 @@ config_setvar(
        )
 {
        struct setvar_node *my_node;
+       size_t  varlen, vallen, octets;
+       char *  str;
 
+       str = NULL;
        my_node = queue_head(ptree->setvar);
        while (my_node != NULL) {
-               set_sys_var(my_node->data, strlen(my_node->data) + 1,
-                           (my_node->isdefault)
-                               ? DEF
-                               : 0);
+               varlen = strlen(my_node->var);
+               vallen = strlen(my_node->val);
+               octets = varlen + vallen + 1 + 1;
+               str = erealloc(str, octets);
+               snprintf(str, octets, "%s=%s", my_node->var,
+                        my_node->val);
+               set_sys_var(str, octets, (my_node->isdefault)
+                                               ? DEF 
+                                               : 0);
                my_node = next_node(my_node);
        }
+       if (str != NULL)
+               free(str);
 }
 
 
@@ -2780,7 +2790,8 @@ free_config_setvar(
        struct setvar_node *my_node;
 
        while (NULL != (my_node = dequeue(ptree->setvar))) {
-               free(my_node->data);
+               free(my_node->var);
+               free(my_node->val);
                free_node(my_node);
        }
 }
@@ -2976,10 +2987,6 @@ config_fudge(
                memset(&clock_stat, 0, sizeof(clock_stat));
                curr_opt = queue_head(curr_fudge->options);
                while (curr_opt != NULL) {
-                       /* The attribute field is used to store the flag.
-                        * Set haveflags with it
-                        */
-                       clock_stat.haveflags |= curr_opt->attr;
                        switch (curr_opt->attr) {
                        case T_Time1:
                                clock_stat.haveflags |= CLK_HAVETIME1;
@@ -3685,7 +3692,7 @@ config_remotely(
        memset(&remote_cuckoo, 0, sizeof(remote_cuckoo));
        remote_cuckoo.fname = origin;
        remote_cuckoo.line_no = 1;
-       remote_cuckoo.line_no = 1;
+       remote_cuckoo.col_no = 1;
        ip_file = &remote_cuckoo;
        input_from_file = 0;
 
index 21c6fcd5961d178d94378941e456173a86960b7e..29afb63dc06c737bb83713cc5675dec4c19b6a5b 100644 (file)
@@ -75,7 +75,7 @@ struct key_tok ntp_keyword_list[] = {
 { "discard",           T_Discard,              FOLLBY_TOKEN },
 { "restrict",          T_Restrict,             FOLLBY_TOKEN },
 { "server",            T_Server,               FOLLBY_STRING },
-{ "setvar",            T_Setvar,               FOLLBY_TOKEN },
+{ "setvar",            T_Setvar,               FOLLBY_STRING },
 { "statistics",                T_Statistics,           FOLLBY_TOKEN },
 { "statsdir",          T_Statsdir,             FOLLBY_STRING },
 { "tick",              T_Tick,                 FOLLBY_TOKEN },
@@ -680,6 +680,27 @@ is_EOC(
 }
 
 
+char *
+quote_if_needed(char *str)
+{
+       char *ret;
+       size_t len;
+       size_t octets;
+
+       len = strlen(str);
+       octets = len + 2 + 1;
+       ret = emalloc(octets);
+       if ('"' != str[0] 
+           && (strcspn(str, special_chars) < len 
+               || strchr(str, ' ') != NULL)) {
+               snprintf(ret, octets, "\"%s\"", str);
+       } else
+               strncpy(ret, str, octets);
+
+       return ret;
+}
+
+
 static int
 create_string_token(
        char *lexeme
@@ -749,6 +770,17 @@ yylex(
                } else if (is_special(ch) && FOLLBY_TOKEN == followedby) {
                        /* special chars are their own token values */
                        token = ch;
+                       /*
+                        * '=' implies a single string following as in:
+                        * setvar Owner = "The Boss" default
+                        * This could alternatively be handled by
+                        * removing '=' from special_chars and adding
+                        * it to the keyword table.
+                        */
+                       if ('=' == ch)
+                               followedby = FOLLBY_STRING;
+                       yytext[0] = (char)ch;
+                       yytext[1] = '\0';
                        goto normal_return;
                } else
                        push_back_char(ch);
@@ -794,8 +826,6 @@ yylex(
                                if (i >= COUNTOF(yytext))
                                        goto lex_too_long;
                        }
-                       if (yytext[i] == '"')
-                               yytext[i] =  ' ';
                }
                /* Pushback the last character read that is not a part
                 * of this lexeme.
@@ -803,9 +833,9 @@ yylex(
                 * newline character. This is to prevent a parse error
                 * when there is no newline at the end of a file.
                 */
-               if (yytext[i] == EOF)
+               if (EOF == yytext[i])
                        push_back_char('\n');
-               else
+               else if ('"' != yytext[i])
                        push_back_char(yytext[i]); 
                yytext[i] = '\0';
        } while (i == 0);
index 9b0c13b5c2589858519a09700e744adaa936f121..96a9f016d2e23bb50dcf6830138cc06a1c0c4507 100644 (file)
@@ -81,12 +81,13 @@ extern struct FILE_INFO *fp[];
 /* VARIOUS SUBROUTINE DECLARATIONS
  * -------------------------------
  */
-extern char * keyword(int token);
-struct state *create_states(char *text, 
-                           int token, 
-                           follby followedby,
-                           struct state *pre_state);
-struct state *create_keyword_scanner(void);
+extern char *  keyword(int token);
+extern char *  quote_if_needed(char *str);
+struct state * create_states(char *text, 
+                             int token, 
+                             follby followedby,
+                             struct state *pre_state);
+struct state * create_keyword_scanner(void);
 void delete_keyword_scanner(struct state *my_key_scanner);
 int yylex(void);
 
index 132a649e30a897d9e5bb311528a47a8b3d7aa4d4..a45b6c59e785b59206040e1edd6326d8963a7bb9 100644 (file)
@@ -54,17 +54,17 @@ static      void    radiostatus (struct parse *, FILE *);
 static void    pstatus         (struct parse *, FILE *);
 static long    when            (l_fp *, l_fp *, l_fp *);
 static char *  prettyinterval  (char *, long);
-static int doprintpeers        (struct varlist *, int, int, int, char *, FILE *, int);
-static int dogetpeers  (struct varlist *, int, FILE *, int);
+static int     doprintpeers    (struct varlist *, int, int, int, char *, FILE *, int);
+static int     dogetpeers      (struct varlist *, int, FILE *, int);
 static void    dopeers         (int, FILE *, int);
 static void    peers           (struct parse *, FILE *);
 static void    lpeers          (struct parse *, FILE *);
 static void    doopeers        (int, FILE *, int);
 static void    opeers          (struct parse *, FILE *);
 static void    lopeers         (struct parse *, FILE *);
-static  void    config         (struct parse *, FILE *);
+static  void   config          (struct parse *, FILE *);
 static         void    saveconfig      (struct parse *, FILE *);
-static  void    config_from_file (struct parse *, FILE *);
+static  void   config_from_file(struct parse *, FILE *);
 
 
 /*
@@ -1145,7 +1145,7 @@ lpassociations(
 
 
 /*
- *  * dumpcfg - dump ntp server configuration
+ *  saveconfig - dump ntp server configuration to server file
  */
 static void
 saveconfig(
@@ -1833,25 +1833,41 @@ config (
        FILE *fp
        )
 {
-       char *rcmd;
+       char *cfgcmd;
        u_short rstatus;
        int rsize;
        char *rdata;
        int res;
+       int col;
+       int i;
 
-       rcmd = pcmd->argval[0].string;
+       cfgcmd = pcmd->argval[0].string;
 
        if (debug > 2) {
                printf("In Config\n");
                printf("Keyword = %s\n", pcmd->keyword);
-               printf("Command = %s\n", rcmd);
+               printf("Command = %s\n", cfgcmd);
        }
 
-       res = doquery(CTL_OP_CONFIGURE, 0, 1, strlen(rcmd), rcmd,
+       res = doquery(CTL_OP_CONFIGURE, 0, 1, strlen(cfgcmd), cfgcmd,
                      &rstatus, &rsize, &rdata);
+
        if (rsize > 0 && '\n' == rdata[rsize - 1])
                rsize--;
        rdata[rsize] = '\0';
+
+       col = -1;
+       if (1 == sscanf(rdata, "column %d syntax error", &col)
+           && col >= 0 && (size_t)col <= strlen(cfgcmd) + 1) {
+               if (interactive) {
+                       printf("______");       /* "ntpq> " */
+                       printf("________");     /* ":config " */
+               } else
+                       printf("%s\n", cfgcmd);
+               for (i = 1; i < col; i++)
+                       putchar('_');
+               printf("^\n");
+       }
        printf("%s\n", rdata);
 }
 
index cd7362b56dd1aca37415cc2aeb6091278012f50b..4da356c4e7b4f1d31080cfd2e7a5e7d0265dd198 100644 (file)
@@ -79,6 +79,8 @@ struct ctl_var {
        const char *text;
 };
 
+extern int     interactive;    /* are we prompting? */
+
 extern void    asciize         (int, char *, FILE *);
 extern int     getnetnum       (const char *, sockaddr_u *, char *, int);
 extern void    sortassoc       (void);