HAMMER 61B/Many: Stabilization
[dragonfly.git] / contrib / dhcp-3.0 / common / execute.c
blob39653309e9de3e88951937c4e1bbec537b390c33
1 /* execute.c
3 Support for executable statements. */
5 /*
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1998-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
35 #ifndef lint
36 static char copyright[] =
37 "$Id: execute.c,v 1.44.2.12 2004/11/24 17:39:15 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
38 #endif /* not lint */
40 #include "dhcpd.h"
41 #include <omapip/omapip_p.h>
43 int execute_statements (result, packet, lease, client_state,
44 in_options, out_options, scope, statements)
45 struct binding_value **result;
46 struct packet *packet;
47 struct lease *lease;
48 struct client_state *client_state;
49 struct option_state *in_options;
50 struct option_state *out_options;
51 struct binding_scope **scope;
52 struct executable_statement *statements;
54 struct executable_statement *r, *e, *next;
55 int rc;
56 int status;
57 unsigned long num;
58 struct binding_scope *outer;
59 struct binding *binding;
60 struct data_string ds;
61 struct binding_scope *ns;
63 if (!statements)
64 return 1;
66 r = (struct executable_statement *)0;
67 next = (struct executable_statement *)0;
68 e = (struct executable_statement *)0;
69 executable_statement_reference (&r, statements, MDL);
70 while (r && !(result && *result)) {
71 if (r -> next)
72 executable_statement_reference (&next, r -> next, MDL);
73 switch (r -> op) {
74 case statements_statement:
75 #if defined (DEBUG_EXPRESSIONS)
76 log_debug ("exec: statements");
77 #endif
78 status = execute_statements (result, packet, lease,
79 client_state, in_options,
80 out_options, scope,
81 r -> data.statements);
82 #if defined (DEBUG_EXPRESSIONS)
83 log_debug ("exec: statements returns %d", status);
84 #endif
85 if (!status)
86 return 0;
87 break;
89 case on_statement:
90 if (lease) {
91 if (r -> data.on.evtypes & ON_EXPIRY) {
92 #if defined (DEBUG_EXPRESSIONS)
93 log_debug ("exec: on expiry");
94 #endif
95 if (lease -> on_expiry)
96 executable_statement_dereference
97 (&lease -> on_expiry, MDL);
98 if (r -> data.on.statements)
99 executable_statement_reference
100 (&lease -> on_expiry,
101 r -> data.on.statements, MDL);
103 if (r -> data.on.evtypes & ON_RELEASE) {
104 #if defined (DEBUG_EXPRESSIONS)
105 log_debug ("exec: on release");
106 #endif
107 if (lease -> on_release)
108 executable_statement_dereference
109 (&lease -> on_release, MDL);
110 if (r -> data.on.statements)
111 executable_statement_reference
112 (&lease -> on_release,
113 r -> data.on.statements, MDL);
115 if (r -> data.on.evtypes & ON_COMMIT) {
116 #if defined (DEBUG_EXPRESSIONS)
117 log_debug ("exec: on commit");
118 #endif
119 if (lease -> on_commit)
120 executable_statement_dereference
121 (&lease -> on_commit, MDL);
122 if (r -> data.on.statements)
123 executable_statement_reference
124 (&lease -> on_commit,
125 r -> data.on.statements, MDL);
128 break;
130 case switch_statement:
131 #if defined (DEBUG_EXPRESSIONS)
132 log_debug ("exec: switch");
133 #endif
134 status = (find_matching_case
135 (&e, packet, lease, client_state,
136 in_options, out_options, scope,
137 r -> data.s_switch.expr,
138 r -> data.s_switch.statements));
139 #if defined (DEBUG_EXPRESSIONS)
140 log_debug ("exec: switch: case %lx", (unsigned long)e);
141 #endif
142 if (status) {
143 if (!(execute_statements
144 (result, packet, lease, client_state,
145 in_options, out_options, scope, e))) {
146 executable_statement_dereference
147 (&e, MDL);
148 return 0;
150 executable_statement_dereference (&e, MDL);
152 break;
154 /* These have no effect when executed. */
155 case case_statement:
156 case default_statement:
157 break;
159 case if_statement:
160 status = (evaluate_boolean_expression
161 (&rc, packet,
162 lease, client_state, in_options,
163 out_options, scope, r -> data.ie.expr));
165 #if defined (DEBUG_EXPRESSIONS)
166 log_debug ("exec: if %s", (status
167 ? (rc ? "true" : "false")
168 : "NULL"));
169 #endif
170 /* XXX Treat NULL as false */
171 if (!status)
172 rc = 0;
173 if (!execute_statements
174 (result, packet, lease, client_state,
175 in_options, out_options, scope,
176 rc ? r -> data.ie.tc : r -> data.ie.fc))
177 return 0;
178 break;
180 case eval_statement:
181 status = evaluate_expression
182 ((struct binding_value **)0,
183 packet, lease, client_state, in_options,
184 out_options, scope, r -> data.eval, MDL);
185 #if defined (DEBUG_EXPRESSIONS)
186 log_debug ("exec: evaluate: %s",
187 (status ? "succeeded" : "failed"));
188 #endif
189 break;
191 case return_statement:
192 status = evaluate_expression
193 (result, packet,
194 lease, client_state, in_options,
195 out_options, scope, r -> data.retval, MDL);
196 #if defined (DEBUG_EXPRESSIONS)
197 log_debug ("exec: return: %s",
198 (status ? "succeeded" : "failed"));
199 #endif
200 break;
202 case add_statement:
203 #if defined (DEBUG_EXPRESSIONS)
204 log_debug ("exec: add %s", (r -> data.add -> name
205 ? r -> data.add -> name
206 : "<unnamed class>"));
207 #endif
208 classify (packet, r -> data.add);
209 break;
211 case break_statement:
212 #if defined (DEBUG_EXPRESSIONS)
213 log_debug ("exec: break");
214 #endif
215 return 1;
217 case supersede_option_statement:
218 case send_option_statement:
219 #if defined (DEBUG_EXPRESSIONS)
220 log_debug ("exec: %s option %s.%s",
221 (r -> op == supersede_option_statement
222 ? "supersede" : "send"),
223 r -> data.option -> option -> universe -> name,
224 r -> data.option -> option -> name);
225 goto option_statement;
226 #endif
227 case default_option_statement:
228 #if defined (DEBUG_EXPRESSIONS)
229 log_debug ("exec: default option %s.%s",
230 r -> data.option -> option -> universe -> name,
231 r -> data.option -> option -> name);
232 goto option_statement;
233 #endif
234 case append_option_statement:
235 #if defined (DEBUG_EXPRESSIONS)
236 log_debug ("exec: append option %s.%s",
237 r -> data.option -> option -> universe -> name,
238 r -> data.option -> option -> name);
239 goto option_statement;
240 #endif
241 case prepend_option_statement:
242 #if defined (DEBUG_EXPRESSIONS)
243 log_debug ("exec: prepend option %s.%s",
244 r -> data.option -> option -> universe -> name,
245 r -> data.option -> option -> name);
246 option_statement:
247 #endif
248 set_option (r -> data.option -> option -> universe,
249 out_options, r -> data.option, r -> op);
250 break;
252 case set_statement:
253 case define_statement:
254 if (!scope) {
255 log_error ("set %s: no scope",
256 r -> data.set.name);
257 status = 0;
258 break;
260 if (!*scope) {
261 if (!binding_scope_allocate (scope, MDL)) {
262 log_error ("set %s: can't allocate scope",
263 r -> data.set.name);
264 status = 0;
265 break;
268 binding = find_binding (*scope, r -> data.set.name);
269 #if defined (DEBUG_EXPRESSIONS)
270 log_debug ("exec: set %s", r -> data.set.name);
271 #endif
272 if (!binding) {
273 binding = dmalloc (sizeof *binding, MDL);
274 if (binding) {
275 memset (binding, 0, sizeof *binding);
276 binding -> name =
277 dmalloc (strlen
278 (r -> data.set.name) + 1,
279 MDL);
280 if (binding -> name) {
281 strcpy (binding -> name,
282 r -> data.set.name);
283 binding -> next = (*scope) -> bindings;
284 (*scope) -> bindings = binding;
285 } else {
286 badalloc:
287 dfree (binding, MDL);
288 binding = (struct binding *)0;
292 if (binding) {
293 if (binding -> value)
294 binding_value_dereference
295 (&binding -> value, MDL);
296 if (r -> op == set_statement) {
297 status = (evaluate_expression
298 (&binding -> value, packet,
299 lease, client_state,
300 in_options, out_options,
301 scope, r -> data.set.expr,
302 MDL));
303 } else {
304 if (!(binding_value_allocate
305 (&binding -> value, MDL))) {
306 dfree (binding, MDL);
307 binding = (struct binding *)0;
309 if (binding -> value) {
310 binding -> value -> type =
311 binding_function;
312 (fundef_reference
313 (&binding -> value -> value.fundef,
314 r -> data.set.expr -> data.func,
315 MDL));
319 #if defined (DEBUG_EXPRESSIONS)
320 log_debug ("exec: set %s%s", r -> data.set.name,
321 (binding && status ? "" : " (failed)"));
322 #endif
323 break;
325 case unset_statement:
326 if (!scope || !*scope) {
327 status = 0;
328 break;
330 binding = find_binding (*scope, r -> data.unset);
331 if (binding) {
332 if (binding -> value)
333 binding_value_dereference
334 (&binding -> value, MDL);
335 status = 1;
336 } else
337 status = 0;
338 #if defined (DEBUG_EXPRESSIONS)
339 log_debug ("exec: unset %s: %s", r -> data.unset,
340 (status ? "found" : "not found"));
341 #endif
342 break;
344 case let_statement:
345 #if defined (DEBUG_EXPRESSIONS)
346 log_debug ("exec: let %s", r -> data.let.name);
347 #endif
348 ns = (struct binding_scope *)0;
349 binding_scope_allocate (&ns, MDL);
350 e = r;
352 next_let:
353 if (ns) {
354 binding = dmalloc (sizeof *binding, MDL);
355 memset (binding, 0, sizeof *binding);
356 if (!binding) {
357 blb:
358 binding_scope_dereference (&ns, MDL);
359 } else {
360 binding -> name =
361 dmalloc (strlen
362 (e -> data.let.name + 1),
363 MDL);
364 if (binding -> name)
365 strcpy (binding -> name,
366 e -> data.let.name);
367 else {
368 dfree (binding, MDL);
369 binding = (struct binding *)0;
370 goto blb;
373 } else
374 binding = NULL;
376 if (ns && binding) {
377 status = (evaluate_expression
378 (&binding -> value, packet, lease,
379 client_state,
380 in_options, out_options,
381 scope, e -> data.set.expr, MDL));
382 binding -> next = ns -> bindings;
383 ns -> bindings = binding;
386 #if defined (DEBUG_EXPRESSIONS)
387 log_debug ("exec: let %s%s", e -> data.let.name,
388 (binding && status ? "" : "failed"));
389 #endif
390 if (!e -> data.let.statements) {
391 } else if (e -> data.let.statements -> op ==
392 let_statement) {
393 e = e -> data.let.statements;
394 goto next_let;
395 } else if (ns) {
396 if (scope && *scope)
397 binding_scope_reference (&ns -> outer,
398 *scope, MDL);
399 execute_statements
400 (result, packet, lease,
401 client_state,
402 in_options, out_options,
403 &ns, e -> data.let.statements);
405 if (ns)
406 binding_scope_dereference (&ns, MDL);
407 break;
409 case log_statement:
410 memset (&ds, 0, sizeof ds);
411 status = (evaluate_data_expression
412 (&ds, packet,
413 lease, client_state, in_options,
414 out_options, scope, r -> data.log.expr,
415 MDL));
417 #if defined (DEBUG_EXPRESSIONS)
418 log_debug ("exec: log");
419 #endif
421 if (status) {
422 switch (r -> data.log.priority) {
423 case log_priority_fatal:
424 log_fatal ("%.*s", (int)ds.len,
425 ds.data);
426 break;
427 case log_priority_error:
428 log_error ("%.*s", (int)ds.len,
429 ds.data);
430 break;
431 case log_priority_debug:
432 log_debug ("%.*s", (int)ds.len,
433 ds.data);
434 break;
435 case log_priority_info:
436 log_info ("%.*s", (int)ds.len,
437 ds.data);
438 break;
440 data_string_forget (&ds, MDL);
443 break;
445 default:
446 log_error ("bogus statement type %d", r -> op);
447 break;
449 executable_statement_dereference (&r, MDL);
450 if (next) {
451 executable_statement_reference (&r, next, MDL);
452 executable_statement_dereference (&next, MDL);
456 return 1;
459 /* Execute all the statements in a particular scope, and all statements in
460 scopes outer from that scope, but if a particular limiting scope is
461 reached, do not execute statements in that scope or in scopes outer
462 from it. More specific scopes need to take precedence over less
463 specific scopes, so we recursively traverse the scope list, executing
464 the most outer scope first. */
466 void execute_statements_in_scope (result, packet,
467 lease, client_state, in_options, out_options,
468 scope, group, limiting_group)
469 struct binding_value **result;
470 struct packet *packet;
471 struct lease *lease;
472 struct client_state *client_state;
473 struct option_state *in_options;
474 struct option_state *out_options;
475 struct binding_scope **scope;
476 struct group *group;
477 struct group *limiting_group;
479 struct group *limit;
481 /* If we've recursed as far as we can, return. */
482 if (!group)
483 return;
485 /* As soon as we get to a scope that is outer than the limiting
486 scope, we are done. This is so that if somebody does something
487 like this, it does the expected thing:
489 domain-name "fugue.com";
490 shared-network FOO {
491 host bar {
492 domain-name "othello.fugue.com";
493 fixed-address 10.20.30.40;
495 subnet 10.20.30.0 netmask 255.255.255.0 {
496 domain-name "manhattan.fugue.com";
500 The problem with the above arrangement is that the host's
501 group nesting will be host -> shared-network -> top-level,
502 and the limiting scope when we evaluate the host's scope
503 will be the subnet -> shared-network -> top-level, so we need
504 to know when we evaluate the host's scope to stop before we
505 evaluate the shared-networks scope, because it's outer than
506 the limiting scope, which means we've already evaluated it. */
508 for (limit = limiting_group; limit; limit = limit -> next) {
509 if (group == limit)
510 return;
513 if (group -> next)
514 execute_statements_in_scope (result, packet,
515 lease, client_state,
516 in_options, out_options, scope,
517 group -> next, limiting_group);
518 execute_statements (result, packet, lease, client_state, in_options,
519 out_options, scope, group -> statements);
522 /* Dereference or free any subexpressions of a statement being freed. */
524 int executable_statement_dereference (ptr, file, line)
525 struct executable_statement **ptr;
526 const char *file;
527 int line;
529 struct executable_statement *bp;
531 if (!ptr || !*ptr) {
532 log_error ("%s(%d): null pointer", file, line);
533 #if defined (POINTER_DEBUG)
534 abort ();
535 #else
536 return 0;
537 #endif
540 (*ptr) -> refcnt--;
541 rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC);
542 if ((*ptr) -> refcnt > 0) {
543 *ptr = (struct executable_statement *)0;
544 return 1;
547 if ((*ptr) -> refcnt < 0) {
548 log_error ("%s(%d): negative refcnt!", file, line);
549 #if defined (DEBUG_RC_HISTORY)
550 dump_rc_history (*ptr);
551 #endif
552 #if defined (POINTER_DEBUG)
553 abort ();
554 #else
555 return 0;
556 #endif
559 if ((*ptr) -> next)
560 executable_statement_dereference (&(*ptr) -> next, file, line);
562 switch ((*ptr) -> op) {
563 case statements_statement:
564 if ((*ptr) -> data.statements)
565 executable_statement_dereference
566 (&(*ptr) -> data.statements, file, line);
567 break;
569 case on_statement:
570 if ((*ptr) -> data.on.statements)
571 executable_statement_dereference
572 (&(*ptr) -> data.on.statements, file, line);
573 break;
575 case switch_statement:
576 if ((*ptr) -> data.s_switch.statements)
577 executable_statement_dereference
578 (&(*ptr) -> data.on.statements, file, line);
579 if ((*ptr) -> data.s_switch.expr)
580 expression_dereference (&(*ptr) -> data.s_switch.expr,
581 file, line);
582 break;
584 case case_statement:
585 if ((*ptr) -> data.s_switch.expr)
586 expression_dereference (&(*ptr) -> data.c_case,
587 file, line);
588 break;
590 case if_statement:
591 if ((*ptr) -> data.ie.expr)
592 expression_dereference (&(*ptr) -> data.ie.expr,
593 file, line);
594 if ((*ptr) -> data.ie.tc)
595 executable_statement_dereference
596 (&(*ptr) -> data.ie.tc, file, line);
597 if ((*ptr) -> data.ie.fc)
598 executable_statement_dereference
599 (&(*ptr) -> data.ie.fc, file, line);
600 break;
602 case eval_statement:
603 if ((*ptr) -> data.eval)
604 expression_dereference (&(*ptr) -> data.eval,
605 file, line);
606 break;
608 case return_statement:
609 if ((*ptr) -> data.eval)
610 expression_dereference (&(*ptr) -> data.eval,
611 file, line);
612 break;
614 case set_statement:
615 if ((*ptr)->data.set.name)
616 dfree ((*ptr)->data.set.name, file, line);
617 if ((*ptr)->data.set.expr)
618 expression_dereference (&(*ptr) -> data.set.expr,
619 file, line);
620 break;
622 case unset_statement:
623 if ((*ptr)->data.unset)
624 dfree ((*ptr)->data.unset, file, line);
625 break;
627 case supersede_option_statement:
628 case send_option_statement:
629 case default_option_statement:
630 case append_option_statement:
631 case prepend_option_statement:
632 if ((*ptr) -> data.option)
633 option_cache_dereference (&(*ptr) -> data.option,
634 file, line);
635 break;
637 default:
638 /* Nothing to do. */
639 break;
642 dfree ((*ptr), file, line);
643 *ptr = (struct executable_statement *)0;
644 return 1;
647 void write_statements (file, statements, indent)
648 FILE *file;
649 struct executable_statement *statements;
650 int indent;
652 struct executable_statement *r, *x;
653 int result;
654 int status;
655 const char *s, *t, *dot;
656 int col;
658 if (!statements)
659 return;
661 for (r = statements; r; r = r -> next) {
662 switch (r -> op) {
663 case statements_statement:
664 write_statements (file, r -> data.statements, indent);
665 break;
667 case on_statement:
668 indent_spaces (file, indent);
669 fprintf (file, "on ");
670 s = "";
671 if (r -> data.on.evtypes & ON_EXPIRY) {
672 fprintf (file, "%sexpiry", s);
673 s = " or ";
675 if (r -> data.on.evtypes & ON_COMMIT) {
676 fprintf (file, "%scommit", s);
677 s = "or";
679 if (r -> data.on.evtypes & ON_RELEASE) {
680 fprintf (file, "%srelease", s);
681 s = "or";
683 if (r -> data.on.statements) {
684 fprintf (file, " {");
685 write_statements (file,
686 r -> data.on.statements,
687 indent + 2);
688 indent_spaces (file, indent);
689 fprintf (file, "}");
690 } else {
691 fprintf (file, ";");
693 break;
695 case switch_statement:
696 indent_spaces (file, indent);
697 fprintf (file, "switch (");
698 col = write_expression (file,
699 r -> data.s_switch.expr,
700 indent + 7, indent + 7, 1);
701 col = token_print_indent (file, col, indent + 7,
702 "", "", ")");
703 token_print_indent (file,
704 col, indent, " ", "", "{");
705 write_statements (file, r -> data.s_switch.statements,
706 indent + 2);
707 indent_spaces (file, indent);
708 fprintf (file, "}");
709 break;
711 case case_statement:
712 indent_spaces (file, indent - 1);
713 fprintf (file, "case ");
714 col = write_expression (file,
715 r -> data.s_switch.expr,
716 indent + 5, indent + 5, 1);
717 token_print_indent (file, col, indent + 5,
718 "", "", ":");
719 break;
721 case default_statement:
722 indent_spaces (file, indent - 1);
723 fprintf (file, "default: ");
724 break;
726 case if_statement:
727 indent_spaces (file, indent);
728 fprintf (file, "if ");
729 x = r;
730 col = write_expression (file,
731 x -> data.ie.expr,
732 indent + 3, indent + 3, 1);
733 else_if:
734 token_print_indent (file, col, indent, " ", "", "{");
735 write_statements (file, x -> data.ie.tc, indent + 2);
736 if (x -> data.ie.fc &&
737 x -> data.ie.fc -> op == if_statement &&
738 !x -> data.ie.fc -> next) {
739 indent_spaces (file, indent);
740 fprintf (file, "} elsif ");
741 x = x -> data.ie.fc;
742 col = write_expression (file,
743 x -> data.ie.expr,
744 indent + 6,
745 indent + 6, 1);
746 goto else_if;
748 if (x -> data.ie.fc) {
749 indent_spaces (file, indent);
750 fprintf (file, "} else {");
751 write_statements (file, x -> data.ie.fc,
752 indent + 2);
754 indent_spaces (file, indent);
755 fprintf (file, "}");
756 break;
758 case eval_statement:
759 indent_spaces (file, indent);
760 fprintf (file, "eval ");
761 col = write_expression (file, r -> data.eval,
762 indent + 5, indent + 5, 1);
763 fprintf (file, ";");
764 break;
766 case return_statement:
767 indent_spaces (file, indent);
768 fprintf (file, "return;");
769 break;
771 case add_statement:
772 indent_spaces (file, indent);
773 fprintf (file, "add \"%s\"", r -> data.add -> name);
774 break;
776 case break_statement:
777 indent_spaces (file, indent);
778 fprintf (file, "break;");
779 break;
781 case supersede_option_statement:
782 case send_option_statement:
783 s = "supersede";
784 goto option_statement;
786 case default_option_statement:
787 s = "default";
788 goto option_statement;
790 case append_option_statement:
791 s = "append";
792 goto option_statement;
794 case prepend_option_statement:
795 s = "prepend";
796 option_statement:
797 /* Note: the reason we don't try to pretty print
798 the option here is that the format of the option
799 may change in dhcpd.conf, and then when this
800 statement was read back, it would cause a syntax
801 error. */
802 if (r -> data.option -> option -> universe ==
803 &dhcp_universe) {
804 t = "";
805 dot = "";
806 } else {
807 t = (r -> data.option -> option ->
808 universe -> name);
809 dot = ".";
811 indent_spaces (file, indent);
812 fprintf (file, "%s %s%s%s = ", s, t, dot,
813 r -> data.option -> option -> name);
814 col = (indent + strlen (s) + strlen (t) +
815 strlen (dot) + strlen (r -> data.option ->
816 option -> name) + 4);
817 if (r -> data.option -> expression)
818 write_expression
819 (file,
820 r -> data.option -> expression,
821 col, indent + 8, 1);
822 else
823 token_indent_data_string
824 (file, col, indent + 8, "", "",
825 &r -> data.option -> data);
827 fprintf (file, ";"); /* XXX */
828 break;
830 case set_statement:
831 indent_spaces (file, indent);
832 fprintf (file, "set ");
833 col = token_print_indent (file, indent + 4, indent + 4,
834 "", "", r -> data.set.name);
835 col = token_print_indent (file, col, indent + 4,
836 " ", " ", "=");
837 col = write_expression (file, r -> data.set.expr,
838 indent + 3, indent + 3, 0);
839 col = token_print_indent (file, col, indent + 4,
840 " ", "", ";");
841 break;
843 case unset_statement:
844 indent_spaces (file, indent);
845 fprintf (file, "unset ");
846 col = token_print_indent (file, indent + 6, indent + 6,
847 "", "", r -> data.set.name);
848 col = token_print_indent (file, col, indent + 6,
849 " ", "", ";");
850 break;
852 case log_statement:
853 indent_spaces (file, indent);
854 fprintf (file, "log ");
855 col = token_print_indent (file, indent + 4, indent + 4,
856 "", "", "(");
857 switch (r -> data.log.priority) {
858 case log_priority_fatal:
859 col = token_print_indent
860 (file, col, indent + 4, "",
861 " ", "fatal,");
862 break;
863 case log_priority_error:
864 col = token_print_indent
865 (file, col, indent + 4, "",
866 " ", "error,");
867 break;
868 case log_priority_debug:
869 col = token_print_indent
870 (file, col, indent + 4, "",
871 " ", "debug,");
872 break;
873 case log_priority_info:
874 col = token_print_indent
875 (file, col, indent + 4, "",
876 " ", "info,");
877 break;
879 col = write_expression (file, r -> data.log.expr,
880 indent + 4, indent + 4, 0);
881 col = token_print_indent (file, col, indent + 4,
882 "", "", ");");
884 break;
886 default:
887 log_fatal ("bogus statement type %d\n", r -> op);
892 /* Find a case statement in the sequence of executable statements that
893 matches the expression, and if found, return the following statement.
894 If no case statement matches, try to find a default statement and
895 return that (the default statement can precede all the case statements).
896 Otherwise, return the null statement. */
898 int find_matching_case (struct executable_statement **ep,
899 struct packet *packet, struct lease *lease,
900 struct client_state *client_state,
901 struct option_state *in_options,
902 struct option_state *out_options,
903 struct binding_scope **scope,
904 struct expression *expr,
905 struct executable_statement *stmt)
907 int status, sub;
908 struct executable_statement *s;
909 unsigned long foo;
911 if (is_data_expression (expr)) {
912 struct executable_statement *e;
913 struct data_string cd, ds;
914 memset (&ds, 0, sizeof ds);
915 memset (&cd, 0, sizeof cd);
917 status = (evaluate_data_expression (&ds, packet, lease,
918 client_state, in_options,
919 out_options, scope, expr,
920 MDL));
921 if (status) {
922 for (s = stmt; s; s = s -> next) {
923 if (s -> op == case_statement) {
924 sub = (evaluate_data_expression
925 (&cd, packet, lease, client_state,
926 in_options, out_options,
927 scope, s -> data.c_case, MDL));
928 if (sub && cd.len == ds.len &&
929 !memcmp (cd.data, ds.data, cd.len))
931 data_string_forget (&cd, MDL);
932 data_string_forget (&ds, MDL);
933 executable_statement_reference
934 (ep, s -> next, MDL);
935 return 1;
937 data_string_forget (&cd, MDL);
940 data_string_forget (&ds, MDL);
942 } else {
943 unsigned long n, c;
944 status = evaluate_numeric_expression (&n, packet, lease,
945 client_state,
946 in_options, out_options,
947 scope, expr);
949 if (status) {
950 for (s = stmt; s; s = s -> next) {
951 if (s -> op == case_statement) {
952 sub = (evaluate_numeric_expression
953 (&c, packet, lease, client_state,
954 in_options, out_options,
955 scope, s -> data.c_case));
956 if (sub && n == c) {
957 executable_statement_reference
958 (ep, s -> next, MDL);
959 return 1;
966 /* If we didn't find a matching case statement, look for a default
967 statement and return the statement following it. */
968 for (s = stmt; s; s = s -> next)
969 if (s -> op == default_statement)
970 break;
971 if (s) {
972 executable_statement_reference (ep, s -> next, MDL);
973 return 1;
975 return 0;
978 int executable_statement_foreach (struct executable_statement *stmt,
979 int (*callback) (struct
980 executable_statement *,
981 void *, int),
982 void *vp, int condp)
984 struct executable_statement *foo;
985 int ok = 0;
986 int result;
988 for (foo = stmt; foo; foo = foo -> next) {
989 if ((*callback) (foo, vp, condp) != 0)
990 ok = 1;
991 switch (foo -> op) {
992 case null_statement:
993 break;
994 case if_statement:
995 if (executable_statement_foreach (foo -> data.ie.tc,
996 callback, vp, 1))
997 ok = 1;
998 if (executable_statement_foreach (foo -> data.ie.fc,
999 callback, vp, 1))
1000 ok = 1;
1001 break;
1002 case add_statement:
1003 break;
1004 case eval_statement:
1005 break;
1006 case break_statement:
1007 break;
1008 case default_option_statement:
1009 break;
1010 case supersede_option_statement:
1011 break;
1012 case append_option_statement:
1013 break;
1014 case prepend_option_statement:
1015 break;
1016 case send_option_statement:
1017 break;
1018 case statements_statement:
1019 if ((executable_statement_foreach
1020 (foo -> data.statements, callback, vp, condp)))
1021 ok = 1;
1022 break;
1023 case on_statement:
1024 if ((executable_statement_foreach
1025 (foo -> data.on.statements, callback, vp, 1)))
1026 ok = 1;
1027 break;
1028 case switch_statement:
1029 if ((executable_statement_foreach
1030 (foo -> data.s_switch.statements, callback, vp, 1)))
1031 ok = 1;
1032 break;
1033 case case_statement:
1034 break;
1035 case default_statement:
1036 break;
1037 case set_statement:
1038 break;
1039 case unset_statement:
1040 break;
1041 case let_statement:
1042 if ((executable_statement_foreach
1043 (foo -> data.let.statements, callback, vp, 0)))
1044 ok = 1;
1045 break;
1046 case define_statement:
1047 break;
1048 case log_statement:
1049 case return_statement:
1050 break;
1053 return ok;