Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / dhcp / common / execute.c
blob0877a2ad30570a354889471334841a8d65b06f82
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.7 2005/08/11 17:13:21 drochner 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 struct binding *binding;
58 struct data_string ds;
59 struct binding_scope *ns;
61 if (!statements)
62 return 1;
64 r = (struct executable_statement *)0;
65 next = (struct executable_statement *)0;
66 e = (struct executable_statement *)0;
67 executable_statement_reference (&r, statements, MDL);
68 while (r && !(result && *result)) {
69 if (r -> next)
70 executable_statement_reference (&next, r -> next, MDL);
71 switch (r -> op) {
72 case statements_statement:
73 #if defined (DEBUG_EXPRESSIONS)
74 log_debug ("exec: statements");
75 #endif
76 status = execute_statements (result, packet, lease,
77 client_state, in_options,
78 out_options, scope,
79 r -> data.statements);
80 #if defined (DEBUG_EXPRESSIONS)
81 log_debug ("exec: statements returns %d", status);
82 #endif
83 if (!status)
84 return 0;
85 break;
87 case on_statement:
88 if (lease) {
89 if (r -> data.on.evtypes & ON_EXPIRY) {
90 #if defined (DEBUG_EXPRESSIONS)
91 log_debug ("exec: on expiry");
92 #endif
93 if (lease -> on_expiry)
94 executable_statement_dereference
95 (&lease -> on_expiry, MDL);
96 if (r -> data.on.statements)
97 executable_statement_reference
98 (&lease -> on_expiry,
99 r -> data.on.statements, MDL);
101 if (r -> data.on.evtypes & ON_RELEASE) {
102 #if defined (DEBUG_EXPRESSIONS)
103 log_debug ("exec: on release");
104 #endif
105 if (lease -> on_release)
106 executable_statement_dereference
107 (&lease -> on_release, MDL);
108 if (r -> data.on.statements)
109 executable_statement_reference
110 (&lease -> on_release,
111 r -> data.on.statements, MDL);
113 if (r -> data.on.evtypes & ON_COMMIT) {
114 #if defined (DEBUG_EXPRESSIONS)
115 log_debug ("exec: on commit");
116 #endif
117 if (lease -> on_commit)
118 executable_statement_dereference
119 (&lease -> on_commit, MDL);
120 if (r -> data.on.statements)
121 executable_statement_reference
122 (&lease -> on_commit,
123 r -> data.on.statements, MDL);
126 break;
128 case switch_statement:
129 #if defined (DEBUG_EXPRESSIONS)
130 log_debug ("exec: switch");
131 #endif
132 status = (find_matching_case
133 (&e, packet, lease, client_state,
134 in_options, out_options, scope,
135 r -> data.s_switch.expr,
136 r -> data.s_switch.statements));
137 #if defined (DEBUG_EXPRESSIONS)
138 log_debug ("exec: switch: case %lx", (unsigned long)e);
139 #endif
140 if (status) {
141 if (!(execute_statements
142 (result, packet, lease, client_state,
143 in_options, out_options, scope, e))) {
144 executable_statement_dereference
145 (&e, MDL);
146 return 0;
148 executable_statement_dereference (&e, MDL);
150 break;
152 /* These have no effect when executed. */
153 case case_statement:
154 case default_statement:
155 break;
157 case if_statement:
158 status = (evaluate_boolean_expression
159 (&rc, packet,
160 lease, client_state, in_options,
161 out_options, scope, r -> data.ie.expr));
163 #if defined (DEBUG_EXPRESSIONS)
164 log_debug ("exec: if %s", (status
165 ? (rc ? "true" : "false")
166 : "NULL"));
167 #endif
168 /* XXX Treat NULL as false */
169 if (!status)
170 rc = 0;
171 if (!execute_statements
172 (result, packet, lease, client_state,
173 in_options, out_options, scope,
174 rc ? r -> data.ie.tc : r -> data.ie.fc))
175 return 0;
176 break;
178 case eval_statement:
179 status = evaluate_expression
180 ((struct binding_value **)0,
181 packet, lease, client_state, in_options,
182 out_options, scope, r -> data.eval, MDL);
183 #if defined (DEBUG_EXPRESSIONS)
184 log_debug ("exec: evaluate: %s",
185 (status ? "succeeded" : "failed"));
186 #endif
187 break;
189 case return_statement:
190 status = evaluate_expression
191 (result, packet,
192 lease, client_state, in_options,
193 out_options, scope, r -> data.retval, MDL);
194 #if defined (DEBUG_EXPRESSIONS)
195 log_debug ("exec: return: %s",
196 (status ? "succeeded" : "failed"));
197 #endif
198 break;
200 case add_statement:
201 #if defined (DEBUG_EXPRESSIONS)
202 log_debug ("exec: add %s", (r -> data.add -> name
203 ? r -> data.add -> name
204 : "<unnamed class>"));
205 #endif
206 classify (packet, r -> data.add);
207 break;
209 case break_statement:
210 #if defined (DEBUG_EXPRESSIONS)
211 log_debug ("exec: break");
212 #endif
213 return 1;
215 case supersede_option_statement:
216 case send_option_statement:
217 #if defined (DEBUG_EXPRESSIONS)
218 log_debug ("exec: %s option %s.%s",
219 (r -> op == supersede_option_statement
220 ? "supersede" : "send"),
221 r -> data.option -> option -> universe -> name,
222 r -> data.option -> option -> name);
223 goto option_statement;
224 #endif
225 case default_option_statement:
226 #if defined (DEBUG_EXPRESSIONS)
227 log_debug ("exec: default option %s.%s",
228 r -> data.option -> option -> universe -> name,
229 r -> data.option -> option -> name);
230 goto option_statement;
231 #endif
232 case append_option_statement:
233 #if defined (DEBUG_EXPRESSIONS)
234 log_debug ("exec: append option %s.%s",
235 r -> data.option -> option -> universe -> name,
236 r -> data.option -> option -> name);
237 goto option_statement;
238 #endif
239 case prepend_option_statement:
240 #if defined (DEBUG_EXPRESSIONS)
241 log_debug ("exec: prepend option %s.%s",
242 r -> data.option -> option -> universe -> name,
243 r -> data.option -> option -> name);
244 option_statement:
245 #endif
246 set_option (r -> data.option -> option -> universe,
247 out_options, r -> data.option, r -> op);
248 break;
250 case set_statement:
251 case define_statement:
252 if (!scope) {
253 log_error ("set %s: no scope",
254 r -> data.set.name);
255 status = 0;
256 break;
258 if (!*scope) {
259 if (!binding_scope_allocate (scope, MDL)) {
260 log_error ("set %s: can't allocate scope",
261 r -> data.set.name);
262 status = 0;
263 break;
266 binding = find_binding (*scope, r -> data.set.name);
267 #if defined (DEBUG_EXPRESSIONS)
268 log_debug ("exec: set %s", r -> data.set.name);
269 #endif
270 if (!binding) {
271 binding = dmalloc (sizeof *binding, MDL);
272 if (binding) {
273 memset (binding, 0, sizeof *binding);
274 binding -> name =
275 dmalloc (strlen
276 (r -> data.set.name) + 1,
277 MDL);
278 if (binding -> name) {
279 strcpy (binding -> name,
280 r -> data.set.name);
281 binding -> next = (*scope) -> bindings;
282 (*scope) -> bindings = binding;
283 } else {
284 dfree (binding, MDL);
285 binding = (struct binding *)0;
289 if (binding) {
290 if (binding -> value)
291 binding_value_dereference
292 (&binding -> value, MDL);
293 if (r -> op == set_statement) {
294 status = (evaluate_expression
295 (&binding -> value, packet,
296 lease, client_state,
297 in_options, out_options,
298 scope, r -> data.set.expr,
299 MDL));
300 } else {
301 if (!(binding_value_allocate
302 (&binding -> value, MDL))) {
303 dfree (binding, MDL);
304 binding = (struct binding *)0;
306 if (binding -> value) {
307 binding -> value -> type =
308 binding_function;
309 (fundef_reference
310 (&binding -> value -> value.fundef,
311 r -> data.set.expr -> data.func,
312 MDL));
316 #if defined (DEBUG_EXPRESSIONS)
317 log_debug ("exec: set %s%s", r -> data.set.name,
318 (binding && status ? "" : " (failed)"));
319 #endif
320 break;
322 case unset_statement:
323 if (!scope || !*scope) {
324 status = 0;
325 break;
327 binding = find_binding (*scope, r -> data.unset);
328 if (binding) {
329 if (binding -> value)
330 binding_value_dereference
331 (&binding -> value, MDL);
332 status = 1;
333 } else
334 status = 0;
335 #if defined (DEBUG_EXPRESSIONS)
336 log_debug ("exec: unset %s: %s", r -> data.unset,
337 (status ? "found" : "not found"));
338 #endif
339 break;
341 case let_statement:
342 #if defined (DEBUG_EXPRESSIONS)
343 log_debug ("exec: let %s", r -> data.let.name);
344 #endif
345 ns = (struct binding_scope *)0;
346 binding = (struct binding *)0;
347 binding_scope_allocate (&ns, MDL);
348 e = r;
350 next_let:
351 if (ns) {
352 binding = dmalloc (sizeof *binding, MDL);
353 memset (binding, 0, sizeof *binding);
354 if (!binding) {
355 blb:
356 binding_scope_dereference (&ns, MDL);
357 } else {
358 binding -> name =
359 dmalloc (strlen
360 (e -> data.let.name + 1),
361 MDL);
362 if (binding -> name)
363 strcpy (binding -> name,
364 e -> data.let.name);
365 else {
366 dfree (binding, MDL);
367 binding = (struct binding *)0;
368 goto blb;
371 } else
372 binding = NULL;
374 if (ns && binding) {
375 status = (evaluate_expression
376 (&binding -> value, packet, lease,
377 client_state,
378 in_options, out_options,
379 scope, e -> data.set.expr, MDL));
380 binding -> next = ns -> bindings;
381 ns -> bindings = binding;
384 #if defined (DEBUG_EXPRESSIONS)
385 log_debug ("exec: let %s%s", e -> data.let.name,
386 (binding && status ? "" : "failed"));
387 #endif
388 if (!e -> data.let.statements) {
389 } else if (e -> data.let.statements -> op ==
390 let_statement) {
391 e = e -> data.let.statements;
392 goto next_let;
393 } else if (ns) {
394 if (scope && *scope)
395 binding_scope_reference (&ns -> outer,
396 *scope, MDL);
397 execute_statements
398 (result, packet, lease,
399 client_state,
400 in_options, out_options,
401 &ns, e -> data.let.statements);
403 if (ns)
404 binding_scope_dereference (&ns, MDL);
405 break;
407 case log_statement:
408 memset (&ds, 0, sizeof ds);
409 status = (evaluate_data_expression
410 (&ds, packet,
411 lease, client_state, in_options,
412 out_options, scope, r -> data.log.expr,
413 MDL));
415 #if defined (DEBUG_EXPRESSIONS)
416 log_debug ("exec: log");
417 #endif
419 if (status) {
420 switch (r -> data.log.priority) {
421 case log_priority_fatal:
422 log_fatal ("%.*s", (int)ds.len,
423 ds.data);
424 break;
425 case log_priority_error:
426 log_error ("%.*s", (int)ds.len,
427 ds.data);
428 break;
429 case log_priority_debug:
430 log_debug ("%.*s", (int)ds.len,
431 ds.data);
432 break;
433 case log_priority_info:
434 log_info ("%.*s", (int)ds.len,
435 ds.data);
436 break;
438 data_string_forget (&ds, MDL);
441 break;
443 default:
444 log_error ("bogus statement type %d", r -> op);
445 break;
447 executable_statement_dereference (&r, MDL);
448 if (next) {
449 executable_statement_reference (&r, next, MDL);
450 executable_statement_dereference (&next, MDL);
454 return 1;
457 /* Execute all the statements in a particular scope, and all statements in
458 scopes outer from that scope, but if a particular limiting scope is
459 reached, do not execute statements in that scope or in scopes outer
460 from it. More specific scopes need to take precedence over less
461 specific scopes, so we recursively traverse the scope list, executing
462 the most outer scope first. */
464 void execute_statements_in_scope (result, packet,
465 lease, client_state, in_options, out_options,
466 scope, group, limiting_group)
467 struct binding_value **result;
468 struct packet *packet;
469 struct lease *lease;
470 struct client_state *client_state;
471 struct option_state *in_options;
472 struct option_state *out_options;
473 struct binding_scope **scope;
474 struct group *group;
475 struct group *limiting_group;
477 struct group *limit;
479 /* If we've recursed as far as we can, return. */
480 if (!group)
481 return;
483 /* As soon as we get to a scope that is outer than the limiting
484 scope, we are done. This is so that if somebody does something
485 like this, it does the expected thing:
487 domain-name "fugue.com";
488 shared-network FOO {
489 host bar {
490 domain-name "othello.fugue.com";
491 fixed-address 10.20.30.40;
493 subnet 10.20.30.0 netmask 255.255.255.0 {
494 domain-name "manhattan.fugue.com";
498 The problem with the above arrangement is that the host's
499 group nesting will be host -> shared-network -> top-level,
500 and the limiting scope when we evaluate the host's scope
501 will be the subnet -> shared-network -> top-level, so we need
502 to know when we evaluate the host's scope to stop before we
503 evaluate the shared-networks scope, because it's outer than
504 the limiting scope, which means we've already evaluated it. */
506 for (limit = limiting_group; limit; limit = limit -> next) {
507 if (group == limit)
508 return;
511 if (group -> next)
512 execute_statements_in_scope (result, packet,
513 lease, client_state,
514 in_options, out_options, scope,
515 group -> next, limiting_group);
516 execute_statements (result, packet, lease, client_state, in_options,
517 out_options, scope, group -> statements);
520 /* Dereference or free any subexpressions of a statement being freed. */
522 int executable_statement_dereference (ptr, file, line)
523 struct executable_statement **ptr;
524 const char *file;
525 int line;
528 if (!ptr || !*ptr) {
529 log_error ("%s(%d): null pointer", file, line);
530 #if defined (POINTER_DEBUG)
531 abort ();
532 #else
533 return 0;
534 #endif
537 (*ptr) -> refcnt--;
538 rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC);
539 if ((*ptr) -> refcnt > 0) {
540 *ptr = (struct executable_statement *)0;
541 return 1;
544 if ((*ptr) -> refcnt < 0) {
545 log_error ("%s(%d): negative refcnt!", file, line);
546 #if defined (DEBUG_RC_HISTORY)
547 dump_rc_history (*ptr);
548 #endif
549 #if defined (POINTER_DEBUG)
550 abort ();
551 #else
552 return 0;
553 #endif
556 if ((*ptr) -> next)
557 executable_statement_dereference (&(*ptr) -> next, file, line);
559 switch ((*ptr) -> op) {
560 case statements_statement:
561 if ((*ptr) -> data.statements)
562 executable_statement_dereference
563 (&(*ptr) -> data.statements, file, line);
564 break;
566 case on_statement:
567 if ((*ptr) -> data.on.statements)
568 executable_statement_dereference
569 (&(*ptr) -> data.on.statements, file, line);
570 break;
572 case switch_statement:
573 if ((*ptr) -> data.s_switch.statements)
574 executable_statement_dereference
575 (&(*ptr) -> data.on.statements, file, line);
576 if ((*ptr) -> data.s_switch.expr)
577 expression_dereference (&(*ptr) -> data.s_switch.expr,
578 file, line);
579 break;
581 case case_statement:
582 if ((*ptr) -> data.s_switch.expr)
583 expression_dereference (&(*ptr) -> data.c_case,
584 file, line);
585 break;
587 case if_statement:
588 if ((*ptr) -> data.ie.expr)
589 expression_dereference (&(*ptr) -> data.ie.expr,
590 file, line);
591 if ((*ptr) -> data.ie.tc)
592 executable_statement_dereference
593 (&(*ptr) -> data.ie.tc, file, line);
594 if ((*ptr) -> data.ie.fc)
595 executable_statement_dereference
596 (&(*ptr) -> data.ie.fc, file, line);
597 break;
599 case eval_statement:
600 if ((*ptr) -> data.eval)
601 expression_dereference (&(*ptr) -> data.eval,
602 file, line);
603 break;
605 case return_statement:
606 if ((*ptr) -> data.eval)
607 expression_dereference (&(*ptr) -> data.eval,
608 file, line);
609 break;
611 case set_statement:
612 if ((*ptr)->data.set.name)
613 dfree ((*ptr)->data.set.name, file, line);
614 if ((*ptr)->data.set.expr)
615 expression_dereference (&(*ptr) -> data.set.expr,
616 file, line);
617 break;
619 case unset_statement:
620 if ((*ptr)->data.unset)
621 dfree ((*ptr)->data.unset, file, line);
622 break;
624 case supersede_option_statement:
625 case send_option_statement:
626 case default_option_statement:
627 case append_option_statement:
628 case prepend_option_statement:
629 if ((*ptr) -> data.option)
630 option_cache_dereference (&(*ptr) -> data.option,
631 file, line);
632 break;
634 default:
635 /* Nothing to do. */
636 break;
639 dfree ((*ptr), file, line);
640 *ptr = (struct executable_statement *)0;
641 return 1;
644 void write_statements (file, statements, indent)
645 FILE *file;
646 struct executable_statement *statements;
647 int indent;
649 struct executable_statement *r, *x;
650 const char *s, *t, *dot;
651 int col;
653 if (!statements)
654 return;
656 col = 0; /* XXXGCC -Wuninitialized */
658 for (r = statements; r; r = r -> next) {
659 switch (r -> op) {
660 case statements_statement:
661 write_statements (file, r -> data.statements, indent);
662 break;
664 case on_statement:
665 indent_spaces (file, indent);
666 fprintf (file, "on ");
667 s = "";
668 if (r -> data.on.evtypes & ON_EXPIRY) {
669 fprintf (file, "%sexpiry", s);
670 s = " or ";
672 if (r -> data.on.evtypes & ON_COMMIT) {
673 fprintf (file, "%scommit", s);
674 s = "or";
676 if (r -> data.on.evtypes & ON_RELEASE) {
677 fprintf (file, "%srelease", s);
678 s = "or";
680 if (r -> data.on.statements) {
681 fprintf (file, " {");
682 write_statements (file,
683 r -> data.on.statements,
684 indent + 2);
685 indent_spaces (file, indent);
686 fprintf (file, "}");
687 } else {
688 fprintf (file, ";");
690 break;
692 case switch_statement:
693 indent_spaces (file, indent);
694 fprintf (file, "switch (");
695 col = write_expression (file,
696 r -> data.s_switch.expr,
697 indent + 7, indent + 7, 1);
698 col = token_print_indent (file, col, indent + 7,
699 "", "", ")");
700 token_print_indent (file,
701 col, indent, " ", "", "{");
702 write_statements (file, r -> data.s_switch.statements,
703 indent + 2);
704 indent_spaces (file, indent);
705 fprintf (file, "}");
706 break;
708 case case_statement:
709 indent_spaces (file, indent - 1);
710 fprintf (file, "case ");
711 col = write_expression (file,
712 r -> data.s_switch.expr,
713 indent + 5, indent + 5, 1);
714 token_print_indent (file, col, indent + 5,
715 "", "", ":");
716 break;
718 case default_statement:
719 indent_spaces (file, indent - 1);
720 fprintf (file, "default: ");
721 break;
723 case if_statement:
724 indent_spaces (file, indent);
725 fprintf (file, "if ");
726 x = r;
727 col = write_expression (file,
728 x -> data.ie.expr,
729 indent + 3, indent + 3, 1);
730 else_if:
731 token_print_indent (file, col, indent, " ", "", "{");
732 write_statements (file, x -> data.ie.tc, indent + 2);
733 if (x -> data.ie.fc &&
734 x -> data.ie.fc -> op == if_statement &&
735 !x -> data.ie.fc -> next) {
736 indent_spaces (file, indent);
737 fprintf (file, "} elsif ");
738 x = x -> data.ie.fc;
739 col = write_expression (file,
740 x -> data.ie.expr,
741 indent + 6,
742 indent + 6, 1);
743 goto else_if;
745 if (x -> data.ie.fc) {
746 indent_spaces (file, indent);
747 fprintf (file, "} else {");
748 write_statements (file, x -> data.ie.fc,
749 indent + 2);
751 indent_spaces (file, indent);
752 fprintf (file, "}");
753 break;
755 case eval_statement:
756 indent_spaces (file, indent);
757 fprintf (file, "eval ");
758 col = write_expression (file, r -> data.eval,
759 indent + 5, indent + 5, 1);
760 fprintf (file, ";");
761 break;
763 case return_statement:
764 indent_spaces (file, indent);
765 fprintf (file, "return;");
766 break;
768 case add_statement:
769 indent_spaces (file, indent);
770 fprintf (file, "add \"%s\"", r -> data.add -> name);
771 break;
773 case break_statement:
774 indent_spaces (file, indent);
775 fprintf (file, "break;");
776 break;
778 case supersede_option_statement:
779 case send_option_statement:
780 s = "supersede";
781 goto option_statement;
783 case default_option_statement:
784 s = "default";
785 goto option_statement;
787 case append_option_statement:
788 s = "append";
789 goto option_statement;
791 case prepend_option_statement:
792 s = "prepend";
793 option_statement:
794 /* Note: the reason we don't try to pretty print
795 the option here is that the format of the option
796 may change in dhcpd.conf, and then when this
797 statement was read back, it would cause a syntax
798 error. */
799 if (r -> data.option -> option -> universe ==
800 &dhcp_universe) {
801 t = "";
802 dot = "";
803 } else {
804 t = (r -> data.option -> option ->
805 universe -> name);
806 dot = ".";
808 indent_spaces (file, indent);
809 fprintf (file, "%s %s%s%s = ", s, t, dot,
810 r -> data.option -> option -> name);
811 col = (indent + strlen (s) + strlen (t) +
812 strlen (dot) + strlen (r -> data.option ->
813 option -> name) + 4);
814 if (r -> data.option -> expression)
815 write_expression
816 (file,
817 r -> data.option -> expression,
818 col, indent + 8, 1);
819 else
820 token_indent_data_string
821 (file, col, indent + 8, "", "",
822 &r -> data.option -> data);
824 fprintf (file, ";"); /* XXX */
825 break;
827 case set_statement:
828 indent_spaces (file, indent);
829 fprintf (file, "set ");
830 col = token_print_indent (file, indent + 4, indent + 4,
831 "", "", r -> data.set.name);
832 col = token_print_indent (file, col, indent + 4,
833 " ", " ", "=");
834 col = write_expression (file, r -> data.set.expr,
835 indent + 3, indent + 3, 0);
836 col = token_print_indent (file, col, indent + 4,
837 " ", "", ";");
838 break;
840 case unset_statement:
841 indent_spaces (file, indent);
842 fprintf (file, "unset ");
843 col = token_print_indent (file, indent + 6, indent + 6,
844 "", "", r -> data.set.name);
845 col = token_print_indent (file, col, indent + 6,
846 " ", "", ";");
847 break;
849 case log_statement:
850 indent_spaces (file, indent);
851 fprintf (file, "log ");
852 col = token_print_indent (file, indent + 4, indent + 4,
853 "", "", "(");
854 switch (r -> data.log.priority) {
855 case log_priority_fatal:
856 col = token_print_indent
857 (file, col, indent + 4, "",
858 " ", "fatal,");
859 break;
860 case log_priority_error:
861 col = token_print_indent
862 (file, col, indent + 4, "",
863 " ", "error,");
864 break;
865 case log_priority_debug:
866 col = token_print_indent
867 (file, col, indent + 4, "",
868 " ", "debug,");
869 break;
870 case log_priority_info:
871 col = token_print_indent
872 (file, col, indent + 4, "",
873 " ", "info,");
874 break;
876 col = write_expression (file, r -> data.log.expr,
877 indent + 4, indent + 4, 0);
878 col = token_print_indent (file, col, indent + 4,
879 "", "", ");");
881 break;
883 default:
884 log_fatal ("bogus statement type %d\n", r -> op);
889 /* Find a case statement in the sequence of executable statements that
890 matches the expression, and if found, return the following statement.
891 If no case statement matches, try to find a default statement and
892 return that (the default statement can precede all the case statements).
893 Otherwise, return the null statement. */
895 int find_matching_case (struct executable_statement **ep,
896 struct packet *packet, struct lease *lease,
897 struct client_state *client_state,
898 struct option_state *in_options,
899 struct option_state *out_options,
900 struct binding_scope **scope,
901 struct expression *expr,
902 struct executable_statement *stmt)
904 int status, sub;
905 struct executable_statement *s;
907 if (is_data_expression (expr)) {
908 struct data_string cd, ds;
909 memset (&ds, 0, sizeof ds);
910 memset (&cd, 0, sizeof cd);
912 status = (evaluate_data_expression (&ds, packet, lease,
913 client_state, in_options,
914 out_options, scope, expr,
915 MDL));
916 if (status) {
917 for (s = stmt; s; s = s -> next) {
918 if (s -> op == case_statement) {
919 sub = (evaluate_data_expression
920 (&cd, packet, lease, client_state,
921 in_options, out_options,
922 scope, s -> data.c_case, MDL));
923 if (sub && cd.len == ds.len &&
924 !memcmp (cd.data, ds.data, cd.len))
926 data_string_forget (&cd, MDL);
927 data_string_forget (&ds, MDL);
928 executable_statement_reference
929 (ep, s -> next, MDL);
930 return 1;
932 data_string_forget (&cd, MDL);
935 data_string_forget (&ds, MDL);
937 } else {
938 unsigned long n, c;
939 status = evaluate_numeric_expression (&n, packet, lease,
940 client_state,
941 in_options, out_options,
942 scope, expr);
944 if (status) {
945 for (s = stmt; s; s = s -> next) {
946 if (s -> op == case_statement) {
947 sub = (evaluate_numeric_expression
948 (&c, packet, lease, client_state,
949 in_options, out_options,
950 scope, s -> data.c_case));
951 if (sub && n == c) {
952 executable_statement_reference
953 (ep, s -> next, MDL);
954 return 1;
961 /* If we didn't find a matching case statement, look for a default
962 statement and return the statement following it. */
963 for (s = stmt; s; s = s -> next)
964 if (s -> op == default_statement)
965 break;
966 if (s) {
967 executable_statement_reference (ep, s -> next, MDL);
968 return 1;
970 return 0;
973 int executable_statement_foreach (struct executable_statement *stmt,
974 int (*callback) (struct
975 executable_statement *,
976 void *, int),
977 void *vp, int condp)
979 struct executable_statement *foo;
980 int ok = 0;
982 for (foo = stmt; foo; foo = foo -> next) {
983 if ((*callback) (foo, vp, condp) != 0)
984 ok = 1;
985 switch (foo -> op) {
986 case null_statement:
987 break;
988 case if_statement:
989 if (executable_statement_foreach (foo -> data.ie.tc,
990 callback, vp, 1))
991 ok = 1;
992 if (executable_statement_foreach (foo -> data.ie.fc,
993 callback, vp, 1))
994 ok = 1;
995 break;
996 case add_statement:
997 break;
998 case eval_statement:
999 break;
1000 case break_statement:
1001 break;
1002 case default_option_statement:
1003 break;
1004 case supersede_option_statement:
1005 break;
1006 case append_option_statement:
1007 break;
1008 case prepend_option_statement:
1009 break;
1010 case send_option_statement:
1011 break;
1012 case statements_statement:
1013 if ((executable_statement_foreach
1014 (foo -> data.statements, callback, vp, condp)))
1015 ok = 1;
1016 break;
1017 case on_statement:
1018 if ((executable_statement_foreach
1019 (foo -> data.on.statements, callback, vp, 1)))
1020 ok = 1;
1021 break;
1022 case switch_statement:
1023 if ((executable_statement_foreach
1024 (foo -> data.s_switch.statements, callback, vp, 1)))
1025 ok = 1;
1026 break;
1027 case case_statement:
1028 break;
1029 case default_statement:
1030 break;
1031 case set_statement:
1032 break;
1033 case unset_statement:
1034 break;
1035 case let_statement:
1036 if ((executable_statement_foreach
1037 (foo -> data.let.statements, callback, vp, 0)))
1038 ok = 1;
1039 break;
1040 case define_statement:
1041 break;
1042 case log_statement:
1043 case return_statement:
1044 break;
1047 return ok;