2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-04 16:25:21 +00:00

Implement printing out of expressions so that they can be output to the lease database file and later read back in.

This commit is contained in:
Ted Lemon
1999-09-22 01:45:57 +00:00
parent fd10f7c61a
commit fa098be8f9
5 changed files with 620 additions and 7 deletions

View File

@@ -22,7 +22,7 @@
#ifndef lint
static char copyright[] =
"$Id: execute.c,v 1.18 1999/09/15 17:22:52 mellon Exp $ Copyright (c) 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
"$Id: execute.c,v 1.19 1999/09/22 01:45:49 mellon Exp $ Copyright (c) 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -308,3 +308,151 @@ int executable_statement_dereference (ptr, name)
*ptr = (struct executable_statement *)0;
return 1;
}
void write_statements (file, statements, indent)
FILE *file;
struct executable_statement *statements;
int indent;
{
struct executable_statement *r, *x;
int result;
int status;
char *s, *t, *dot;
int col;
if (!statements)
return;
for (r = statements; r; r = r -> next) {
switch (r -> op) {
case statements_statement:
write_statements (file, r -> data.statements, indent);
break;
case on_statement:
switch (r -> data.on.evtype) {
case expiry:
s = "expiry";
break;
case commit:
s = "commit";
break;
case release:
s = "release";
break;
default:
log_fatal ("unknown event type %d %s",
r -> data.on.evtype,
"in on statement.");
}
indent_spaces (file, indent);
fprintf (file, "on %s {", s);
write_statements (file, r -> data.on.statements,
indent + 2);
indent_spaces (file, indent);
fprintf (file, "}");
break;
case if_statement:
indent_spaces (file, indent);
fprintf (file, "if ");
x = r;
col = write_expression (file,
x -> data.ie.expr,
indent + 3, indent + 3);
else_if:
token_print_indent (file, col, indent, " ", "", "{");
write_statements (file, x -> data.ie.true, indent + 2);
if (x -> data.ie.false &&
x -> data.ie.false -> op == if_statement &&
!x -> data.ie.false -> next) {
indent_spaces (file, indent);
fprintf (file, "} elsif ");
x = x -> data.ie.false;
col = write_expression (file,
x -> data.ie.expr,
indent + 6,
indent + 6);
goto else_if;
}
if (x -> data.ie.false) {
indent_spaces (file, indent);
fprintf (file, "} else {");
write_statements (file, x -> data.ie.false,
indent + 2);
}
indent_spaces (file, indent);
fprintf (file, "}");
break;
case eval_statement:
indent_spaces (file, indent);
fprintf (file, "eval ");
col = write_expression (file, r -> data.eval,
indent + 5, indent + 5);
fprintf (file, ";");
break;
case add_statement:
indent_spaces (file, indent);
fprintf (file, "add \"%s\"", r -> data.add -> name);
break;
case break_statement:
indent_spaces (file, indent);
fprintf (file, "break;");
break;
case supersede_option_statement:
s = "supersede";
goto option_statement;
case default_option_statement:
s = "default";
goto option_statement;
case append_option_statement:
s = "append";
goto option_statement;
case prepend_option_statement:
s = "prepend";
option_statement:
/* Note: the reason we don't try to pretty print
the option here is that the format of the option
may change in dhcpd.conf, and then when this
statement was read back, it would cause a syntax
error. */
if (r -> data.option -> option -> universe ==
&dhcp_universe) {
t = (char *)0;
dot = "";
} else {
t = (r -> data.option -> option ->
universe -> name);
dot = ".";
}
indent_spaces (file, indent);
fprintf (file, "%s %s%s%s = ", s, t, dot,
r -> data.option -> option -> name);
col = (indent + strlen (s) + strlen (t) +
strlen (dot) + strlen (r -> data.option ->
option -> name) + 4);
if (r -> data.option -> expression)
write_expression
(file,
r -> data.option -> expression,
col, indent + 8);
else
token_indent_data_string
(file, col, indent + 8, "", "",
&r -> data.option -> data);
fprintf (file, ";"); /* XXX */
break;
default:
log_fatal ("bogus statement type %d\n", r -> op);
}
}
}

View File

@@ -22,7 +22,7 @@
#ifndef lint
static char copyright[] =
"$Id: print.c,v 1.23 1999/07/13 18:00:12 mellon Exp $ Copyright (c) 1995, 1996, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
"$Id: print.c,v 1.24 1999/09/22 01:45:49 mellon Exp $ Copyright (c) 1995, 1996, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -520,3 +520,112 @@ void print_expression (name, expr)
log_info ("%s: %s", name, buf);
}
int token_print_indent_concat (FILE *file, int col, int indent, char *prefix,
char *suffix, ...)
{
va_list list;
char *buf;
int len;
char *s, *t, *u;
va_start (list, suffix);
s = va_arg (list, char *);
len = 0;
while (s) {
len += strlen (s);
s = va_arg (list, char *);
}
va_end (list);
t = malloc (len + 1);
if (!t)
log_fatal ("token_print_indent: no memory for copy buffer");
va_start (list, suffix);
s = va_arg (list, char *);
u = t;
while (s) {
len = strlen (s);
strcpy (u, s);
u += len;
}
va_end (list);
len = token_print_indent (file, col, indent,
prefix, suffix, t);
free (t);
return col;
}
int token_indent_data_string (FILE *file, int col, int indent,
char *prefix, char *suffix,
struct data_string *data)
{
int i;
char *buf;
char obuf [3];
/* See if this is just ASCII. */
for (i = 0; i < data -> len; i++)
if (!isascii (data -> data [i]) ||
!isprint (data -> data [i]))
break;
/* If we have a purely ASCII string, output it as text. */
if (i == data -> len) {
char *buf = malloc (data -> len + 3);
if (buf) {
buf [0] = '"';
memcpy (buf + 1, data -> data, data -> len);
buf [data -> len + 1] = '"';
buf [data -> len + 2] = 0;
i = token_print_indent (file, col, indent,
prefix, suffix, buf);
free (buf);
return i;
}
}
for (i = 0; i < data -> len; i++) {
sprintf (obuf, "%2.2x", data -> data [i]);
col = token_print_indent (file, col, indent,
i == 0 ? prefix : "",
(i + 1 == data -> len
? suffix
: ""), obuf);
if (i + 1 != data -> len)
col = token_print_indent (file, col, indent,
prefix, suffix, obuf);
}
return col;
}
int token_print_indent (FILE *file, int col, int indent,
char *prefix, char *suffix, char *buf)
{
int len = strlen (buf) + strlen (prefix);
if (col + len > 79 && indent + len < 79) {
fputc ('\n', file);
indent_spaces (file, indent);
col = indent;
} else if (prefix && *prefix) {
fputs (prefix, file);
col += strlen (prefix);
}
fputs (buf, file);
col += len;
if (col + strlen (suffix) > 79) {
fputc ('\n', file);
indent_spaces (file, indent);
col = indent;
}
return col;
}
void indent_spaces (FILE *file, int indent)
{
int i;
for (i = 0; i < indent; i++)
fputc (' ', file);
}

View File

@@ -22,7 +22,7 @@
#ifndef lint
static char copyright[] =
"$Id: tree.c,v 1.48 1999/09/16 01:10:19 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
"$Id: tree.c,v 1.49 1999/09/22 01:45:49 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -1839,3 +1839,334 @@ enum expression_context op_context (op)
}
return context_any;
}
int write_expression (file, expr, col, indent)
FILE *file;
struct expression *expr;
int col;
int indent;
{
struct expression *e;
char *s;
char obuf [65];
int scol;
int width;
switch (expr -> op) {
case expr_none:
col = token_print_indent (file, col, indent, "", "", "null");
break;
case expr_check:
col = token_print_indent (file, col, indent, "", "", "check");
col = token_print_indent_concat (file, col, indent,
" ", "", "\"",
expr -> data.check -> name,
"\"", (char *)0);
break;
case expr_equal:
s = "=";
binary:
col = write_expression (file,
expr -> data.equal [0], col, indent);
col = token_print_indent (file, col, indent, " ", " ", s);
col = write_expression (file,
expr -> data.equal [0], col, indent);
break;
case expr_substring:
col = token_print_indent (file, col, indent, "", "",
"substring");
col = token_print_indent (file, col, indent, " ", "", "(");
scol = col;
col = write_expression (file, expr -> data.substring.expr,
col, scol);
col = token_print_indent (file, col, indent, "", " ", ",");
col = write_expression (file, expr -> data.substring.offset,
col, indent);
col = token_print_indent (file, col, scol, "", " ", ",");
col = write_expression (file, expr -> data.substring.len,
col, scol);
col = token_print_indent (file, col, indent, "", "", ")");
break;
case expr_suffix:
col = token_print_indent (file, col, indent, "", "", "suffix");
col = token_print_indent (file, col, indent, " ", "", "(");
scol = col;
col = write_expression (file, expr -> data.suffix.expr,
col, scol);
col = token_print_indent (file, col, scol, "", " ", ",");
col = write_expression (file, expr -> data.suffix.len,
col, scol);
col = token_print_indent (file, col, indent, "", "", ")");
break;
case expr_concat:
e = expr;
col = token_print_indent (file, col, indent, "", "",
"concat");
col = token_print_indent (file, col, indent, " ", "", "(");
scol = col;
concat_again:
col = write_expression (file, e -> data.concat [0],
col, scol);
col = token_print_indent (file, col, scol, "", " ", ",");
if (e -> data.concat [1] -> op == expr_concat) {
e = e -> data.concat [1];
goto concat_again;
}
col = write_expression (file, e -> data.concat [1],
col, scol);
col = token_print_indent (file, col, indent, "", "", ")");
break;
case expr_host_lookup:
col = token_print_indent (file, col, indent, "", "",
"gethostbyname");
col = token_print_indent (file, col, indent, " ", "", "(");
col = token_print_indent_concat
(file, col, indent, "", "",
"\"", expr -> data.host_lookup -> hostname, "\"",
(char *)0);
col = token_print_indent (file, col, indent, "", "", ")");
break;
case expr_and:
s = "and";
goto binary;
case expr_or:
s = "or";
goto binary;
case expr_not:
col = token_print_indent (file, col, indent, "", " ", "not");
col = write_expression (file,
expr -> data.not, col, indent);
break;
case expr_option:
s = "option";
print_option_name:
col = token_print_indent (file, col, indent, "", "", s);
if (expr -> data.option -> universe != &dhcp_universe) {
col = token_print_indent (file, col, indent,
" ", "",
(expr -> data.option ->
universe -> name));
col = token_print_indent (file, col, indent, "", "",
".");
col = token_print_indent (file, col, indent, "", "",
expr -> data.option -> name);
} else {
col = token_print_indent (file, col, indent, " ", "",
expr -> data.option -> name);
}
break;
case expr_hardware:
col = token_print_indent (file, col, indent, "", "",
"hardware");
break;
case expr_packet:
col = token_print_indent (file, col, indent, "", "",
"packet");
col = token_print_indent (file, col, indent, " ", "", "(");
scol = col;
col = write_expression (file, expr -> data.packet.offset,
col, indent);
col = token_print_indent (file, col, scol, "", " ", ",");
col = write_expression (file, expr -> data.packet.len,
col, scol);
col = token_print_indent (file, col, indent, "", "", ")");
break;
case expr_const_data:
col = token_indent_data_string (file, col, indent, "", "",
&expr -> data.const_data);
break;
case expr_extract_int8:
width = 8;
extract_int:
col = token_print_indent (file, col, indent, "", "",
"extract-int");
col = token_print_indent (file, col, indent, " ", "", "(");
scol = col;
col = write_expression (file, expr -> data.extract_int,
col, indent);
col = token_print_indent (file, col, scol, "", " ", ",");
sprintf (obuf, "%d", width);
col = token_print_indent (file, col, scol, " ", "", obuf);
col = token_print_indent (file, col, indent, "", "", ")");
break;
case expr_extract_int16:
width = 16;
goto extract_int;
case expr_extract_int32:
width = 32;
goto extract_int;
case expr_encode_int8:
width = 8;
encode_int:
col = token_print_indent (file, col, indent, "", "",
"encode-int");
col = token_print_indent (file, col, indent, " ", "", "(");
scol = col;
col = write_expression (file, expr -> data.extract_int,
col, indent);
col = token_print_indent (file, col, scol, "", " ", ",");
sprintf (obuf, "%d", width);
col = token_print_indent (file, col, scol, " ", "", obuf);
col = token_print_indent (file, col, indent, "", "",
")");
break;
case expr_encode_int16:
width = 16;
goto encode_int;
case expr_encode_int32:
width = 32;
goto encode_int;
case expr_const_int:
sprintf (obuf, "%lu", expr -> data.const_int);
col = token_print_indent (file, col, indent, "", "", obuf);
break;
case expr_exists:
s = "exists";
goto print_option_name;
case expr_encapsulate:
col = token_print_indent (file, col, indent, "", "",
"encapsulate");
col = token_indent_data_string (file, col, indent, " ", "",
&expr -> data.encapsulate);
break;
case expr_known:
col = token_print_indent (file, col, indent, "", "", "known");
break;
case expr_reverse:
col = token_print_indent (file, col, indent, "", "",
"reverse");
col = token_print_indent (file, col, indent, " ", "", "(");
scol = col;
col = write_expression (file, expr -> data.reverse.width,
col, scol);
col = token_print_indent (file, col, scol, "", " ", ",");
col = write_expression (file, expr -> data.reverse.buffer,
col, scol);
col = token_print_indent (file, col, indent, "", "",
")");
break;
case expr_leased_address:
col = token_print_indent (file, col, indent, "", "",
"leased-address");
break;
case expr_binary_to_ascii:
col = token_print_indent (file, col, indent, "", "",
"binary-to-ascii");
col = token_print_indent (file, col, indent, " ", "",
"(");
scol = col;
col = write_expression (file, expr -> data.b2a.base,
col, scol);
col = token_print_indent (file, col, scol, "", " ",
",");
col = write_expression (file, expr -> data.b2a.width,
col, scol);
col = token_print_indent (file, col, scol, "", " ",
",");
col = write_expression (file, expr -> data.b2a.seperator,
col, scol);
col = token_print_indent (file, col, scol, "", " ",
",");
col = write_expression (file, expr -> data.b2a.buffer,
col, scol);
col = token_print_indent (file, col, indent, "", "",
")");
break;
case expr_config_option:
s = "exists";
goto print_option_name;
case expr_host_decl_name:
col = token_print_indent (file, col, indent, "", "",
"host-decl-name");
break;
case expr_pick_first_value:
e = expr;
col = token_print_indent (file, col, indent, "", "",
"concat");
col = token_print_indent (file, col, indent, " ", "",
"(");
scol = col;
pick_again:
col = write_expression (file,
e -> data.pick_first_value.car,
col, scol);
col = token_print_indent (file, col, scol, "", " ",
",");
if (e -> data.pick_first_value.cdr -> op ==
expr_pick_first_value) {
e = e -> data.pick_first_value.cdr;
goto pick_again;
}
col = write_expression (file,
e -> data.pick_first_value.cdr,
col, scol);
col = token_print_indent (file, col, indent, "", "",
")");
break;
case expr_lease_time:
col = token_print_indent (file, col, indent, "", "",
"lease-time");
break;
case expr_dns_update:
col = token_print_indent (file, col, indent, "", "",
"dns-update");
col = token_print_indent (file, col, indent, " ", "",
"(");
scol = col;
col = write_expression (file, expr -> data.dns_update.type,
col, scol);
col = token_print_indent (file, col, scol, "", " ",
",");
col = write_expression (file, expr -> data.dns_update.expr1,
col, scol);
col = token_print_indent (file, col, scol, "", " ",
",");
col = write_expression (file, expr -> data.dns_update.expr2,
col, scol);
col = token_print_indent (file, col, scol, "", " ",
",");
col = write_expression (file, expr -> data.dns_update.ttl,
col, scol);
col = token_print_indent (file, col, indent, "", "",
")");
break;
default:
log_fatal ("invalid expression type in print_expression: %d",
expr -> op);
}
return col;
}

View File

@@ -1010,6 +1010,7 @@ int is_data_expression PROTO ((struct expression *));
int is_numeric_expression PROTO ((struct expression *));
int op_precedence PROTO ((enum expr_op, enum expr_op));
enum expression_context op_context PROTO ((enum expr_op));
int write_expression (FILE *, struct expression *, int, int);
/* dhcp.c */
extern int outstanding_pings;
@@ -1148,6 +1149,8 @@ int executable_statement_reference PROTO ((struct executable_statement **,
char *));
int executable_statement_dereference PROTO ((struct executable_statement **,
char *));
void write_statements (FILE *, struct executable_statement *, int);
int packet_allocate PROTO ((struct packet **, char *));
int packet_reference PROTO ((struct packet **, struct packet *, char *));
int packet_dereference PROTO ((struct packet **, char *));
@@ -1165,6 +1168,11 @@ char *print_dotted_quads PROTO ((int, u_int8_t *));
char *print_dec_1 PROTO ((int));
char *print_dec_2 PROTO ((int));
void print_expression PROTO ((char *, struct expression *));
int token_print_indent_concat (FILE *, int, int, char *, char *, ...);
int token_indent_data_string (FILE *, int, int, char *, char *,
struct data_string *);
int token_print_indent (FILE *, int, int, char *, char *, char *);
void indent_spaces (FILE *, int);
/* socket.c */
#if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE) \

View File

@@ -22,7 +22,7 @@
#ifndef lint
static char copyright[] =
"$Id: db.c,v 1.27 1999/09/09 23:33:18 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
"$Id: db.c,v 1.28 1999/09/22 01:45:57 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -156,7 +156,6 @@ int write_lease (lease)
}
}
if (lease -> hostname && db_printable (lease -> hostname)) {
errno = 0;
errno = 0;
fprintf (db_file, "\n\thostname \"%s\";",
lease -> hostname);
@@ -164,6 +163,24 @@ int write_lease (lease)
++errors;
}
}
if (lease -> on_expiry) {
errno = 0;
fprintf (db_file, "\n\ton expiry {");
if (errno)
++errors;
write_statements (db_file, lease -> on_expiry, 10);
/* XXX */
fprintf (db_file, "\n\t}");
}
if (lease -> on_release) {
errno = 0;
fprintf (db_file, "\n\ton release {");
if (errno)
++errors;
write_statements (db_file, lease -> on_release, 10);
/* XXX */
fprintf (db_file, "\n\t}");
}
errno = 0;
fputs ("\n}\n", db_file);
if (errno) {