From: Dave Hart Date: Mon, 21 Sep 2009 04:57:32 +0000 (+0000) Subject: correct parsing and processing of setvar directive. X-Git-Tag: NTP_4_2_5P218~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9306709eeb052cb6724034c50231eaa1bb22762c;p=thirdparty%2Fntp.git correct parsing and processing of setvar directive. highlight location of ntpq :config syntax errors with ^. bk: 4ab707bcBH594vNjY_NxzQrhXq4cTw --- diff --git a/ChangeLog b/ChangeLog index 9536cbc48..f7cca1e9c 100644 --- 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. diff --git a/include/ntp_config.h b/include/ntp_config.h index d54ecde04..4b3000e46 100644 --- a/include/ntp_config.h +++ b/include/ntp_config.h @@ -111,7 +111,8 @@ struct filegen_node { }; struct setvar_node { - char * data; + char * var; + char * val; int isdefault; }; diff --git a/ntpd/ntp_config.c b/ntpd/ntp_config.c index b49a7c480..1cdc3708c 100644 --- a/ntpd/ntp_config.c +++ b/ntpd/ntp_config.c @@ -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; diff --git a/ntpd/ntp_scanner.c b/ntpd/ntp_scanner.c index 21c6fcd59..29afb63dc 100644 --- a/ntpd/ntp_scanner.c +++ b/ntpd/ntp_scanner.c @@ -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); diff --git a/ntpd/ntp_scanner.h b/ntpd/ntp_scanner.h index 9b0c13b5c..96a9f016d 100644 --- a/ntpd/ntp_scanner.h +++ b/ntpd/ntp_scanner.h @@ -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); diff --git a/ntpq/ntpq-subs.c b/ntpq/ntpq-subs.c index 132a649e3..a45b6c59e 100644 --- a/ntpq/ntpq-subs.c +++ b/ntpq/ntpq-subs.c @@ -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); } diff --git a/ntpq/ntpq.h b/ntpq/ntpq.h index cd7362b56..4da356c4e 100644 --- a/ntpq/ntpq.h +++ b/ntpq/ntpq.h @@ -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);