highlight location of ntpq :config syntax errors with ^.
bk: 4ab707bcBH594vNjY_NxzQrhXq4cTw
* [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.
};
struct setvar_node {
- char * data;
+ char * var;
+ char * val;
int isdefault;
};
}
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);
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");
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;
}
)
{
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);
}
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);
}
}
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;
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;
{ "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 },
}
+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
} 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);
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.
* 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);
/* 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);
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 *);
/*
/*
- * * dumpcfg - dump ntp server configuration
+ * saveconfig - dump ntp server configuration to server file
*/
static void
saveconfig(
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);
}
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);