From: Ted Lemon Date: Wed, 22 Sep 1999 01:45:57 +0000 (+0000) Subject: Implement printing out of expressions so that they can be output to the lease databas... X-Git-Tag: V3-BETA-1-PATCH-2~5^2~63 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fa098be8f9b723c78a0cb4479b8d297dbece3c9e;p=thirdparty%2Fdhcp.git Implement printing out of expressions so that they can be output to the lease database file and later read back in. --- diff --git a/common/execute.c b/common/execute.c index 06d4efd60..87df6cb4d 100644 --- a/common/execute.c +++ b/common/execute.c @@ -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); + } + } +} diff --git a/common/print.c b/common/print.c index 0942df5b8..df5f93353 100644 --- a/common/print.c +++ b/common/print.c @@ -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); +} + diff --git a/common/tree.c b/common/tree.c index 2d4c6dda7..575fe3fa2 100644 --- a/common/tree.c +++ b/common/tree.c @@ -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" @@ -313,14 +313,14 @@ static int do_host_lookup (result, dns) break; case TRY_AGAIN: log_error ("%s: temporary name server failure", - dns -> hostname); + dns -> hostname); break; case NO_RECOVERY: log_error ("%s: name server failed", dns -> hostname); break; case NO_DATA: log_error ("%s: no A record associated with address", - dns -> hostname); + dns -> hostname); } #endif /* !NO_H_ERRNO */ @@ -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; +} diff --git a/includes/dhcpd.h b/includes/dhcpd.h index e32ca9adf..d7fffefbd 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -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) \ diff --git a/server/db.c b/server/db.c index 29a015d12..21aba8a10 100644 --- a/server/db.c +++ b/server/db.c @@ -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) {