1 /* $NetBSD: execute.c,v 1.1.1.3 2014/07/12 11:57:44 spz Exp $ */
4 Support for executable statements. */
7 * Copyright (c) 2009,2013,2014 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 1998-2003 by Internet Software Consortium
11 * Permission to use, copy, modify, and distribute this software for any
12 * purpose with or without fee is hereby granted, provided that the above
13 * copyright notice and this permission notice appear in all copies.
15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Internet Systems Consortium, Inc.
25 * Redwood City, CA 94063
27 * https://www.isc.org/
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: execute.c,v 1.1.1.3 2014/07/12 11:57:44 spz Exp $");
35 #include <omapip/omapip_p.h>
36 #include <sys/types.h>
39 int execute_statements (result
, packet
, lease
, client_state
,
40 in_options
, out_options
, scope
, statements
,
42 struct binding_value
**result
;
43 struct packet
*packet
;
45 struct client_state
*client_state
;
46 struct option_state
*in_options
;
47 struct option_state
*out_options
;
48 struct binding_scope
**scope
;
49 struct executable_statement
*statements
;
50 struct on_star
*on_star
;
52 struct executable_statement
*r
, *e
, *next
;
55 struct binding
*binding
;
56 struct data_string ds
;
57 struct binding_scope
*ns
;
65 executable_statement_reference (&r
, statements
, MDL
);
66 while (r
&& !(result
&& *result
)) {
68 executable_statement_reference (&next
, r
->next
, MDL
);
70 case statements_statement
:
71 #if defined (DEBUG_EXPRESSIONS)
72 log_debug ("exec: statements");
74 status
= execute_statements (result
, packet
, lease
,
75 client_state
, in_options
,
79 #if defined (DEBUG_EXPRESSIONS)
80 log_debug ("exec: statements returns %d", status
);
88 * if we haven't been passed an on_star block but
89 * do have a lease, use the one from the lease
90 * This handles the previous v4 calls.
92 if ((on_star
== NULL
) && (lease
!= NULL
))
93 on_star
= &lease
->on_star
;
95 if (on_star
!= NULL
) {
96 if (r
->data
.on
.evtypes
& ON_EXPIRY
) {
97 #if defined (DEBUG_EXPRESSIONS)
98 log_debug ("exec: on expiry");
100 if (on_star
->on_expiry
)
101 executable_statement_dereference
102 (&on_star
->on_expiry
, MDL
);
103 if (r
->data
.on
.statements
)
104 executable_statement_reference
105 (&on_star
->on_expiry
,
106 r
->data
.on
.statements
, MDL
);
108 if (r
->data
.on
.evtypes
& ON_RELEASE
) {
109 #if defined (DEBUG_EXPRESSIONS)
110 log_debug ("exec: on release");
112 if (on_star
->on_release
)
113 executable_statement_dereference
114 (&on_star
->on_release
, MDL
);
115 if (r
->data
.on
.statements
)
116 executable_statement_reference
117 (&on_star
->on_release
,
118 r
->data
.on
.statements
, MDL
);
120 if (r
->data
.on
.evtypes
& ON_COMMIT
) {
121 #if defined (DEBUG_EXPRESSIONS)
122 log_debug ("exec: on commit");
124 if (on_star
->on_commit
)
125 executable_statement_dereference
126 (&on_star
->on_commit
, MDL
);
127 if (r
->data
.on
.statements
)
128 executable_statement_reference
129 (&on_star
->on_commit
,
130 r
->data
.on
.statements
, MDL
);
135 case switch_statement
:
136 #if defined (DEBUG_EXPRESSIONS)
137 log_debug ("exec: switch");
139 status
= (find_matching_case
140 (&e
, packet
, lease
, client_state
,
141 in_options
, out_options
, scope
,
142 r
->data
.s_switch
.expr
,
143 r
->data
.s_switch
.statements
));
144 #if defined (DEBUG_EXPRESSIONS)
145 log_debug ("exec: switch: case %lx", (unsigned long)e
);
148 if (!(execute_statements
149 (result
, packet
, lease
, client_state
,
150 in_options
, out_options
, scope
, e
,
152 executable_statement_dereference
156 executable_statement_dereference (&e
, MDL
);
160 /* These have no effect when executed. */
162 case default_statement
:
166 status
= (evaluate_boolean_expression
168 lease
, client_state
, in_options
,
169 out_options
, scope
, r
->data
.ie
.expr
));
171 #if defined (DEBUG_EXPRESSIONS)
172 log_debug ("exec: if %s", (status
173 ? (rc
? "true" : "false")
176 /* XXX Treat NULL as false */
179 if (!execute_statements
180 (result
, packet
, lease
, client_state
,
181 in_options
, out_options
, scope
,
182 rc
? r
->data
.ie
.tc
: r
->data
.ie
.fc
,
188 status
= evaluate_expression
189 (NULL
, packet
, lease
, client_state
, in_options
,
190 out_options
, scope
, r
->data
.eval
, MDL
);
191 #if defined (DEBUG_EXPRESSIONS)
192 log_debug ("exec: evaluate: %s",
193 (status
? "succeeded" : "failed"));
199 case execute_statement
: {
200 #ifdef ENABLE_EXECUTE
201 struct expression
*expr
;
203 int i
, argc
= r
->data
.execute
.argc
;
206 /* save room for the command and the NULL terminator */
207 argv
= dmalloc((argc
+ 2) * sizeof(*argv
), MDL
);
211 argv
[0] = dmalloc(strlen(r
->data
.execute
.command
) + 1,
214 strcpy(argv
[0], r
->data
.execute
.command
);
219 log_debug("execute_statement argv[0] = %s", argv
[0]);
221 for (i
= 1, expr
= r
->data
.execute
.arglist
; expr
;
222 expr
= expr
->data
.arg
.next
, i
++) {
223 memset (&ds
, 0, sizeof(ds
));
224 status
= (evaluate_data_expression
226 lease
, client_state
, in_options
,
228 expr
->data
.arg
.val
, MDL
));
230 argv
[i
] = dmalloc(ds
.len
+ 1, MDL
);
232 memcpy(argv
[i
], ds
.data
,
235 log_debug("execute_statement argv[%d] = %s", i
, argv
[i
]);
237 data_string_forget (&ds
, MDL
);
239 log_debug("execute_statement failed argv[%d]", i
);
243 log_debug("execute: bad arg %d", i
);
249 if ((p
= fork()) > 0) {
251 waitpid(p
, &status
, 0);
254 log_error("execute: %s exit status %d",
258 execvp(argv
[0], argv
);
259 log_error("Unable to execute %s: %m", argv
[0]);
262 log_error("execute: fork() failed");
266 for (i
= 0; i
<= argc
; i
++) {
272 #else /* !ENABLE_EXECUTE */
273 log_fatal("Impossible case at %s:%d (ENABLE_EXECUTE "
274 "is not defined).", MDL
);
275 #endif /* ENABLE_EXECUTE */
279 case return_statement
:
280 status
= evaluate_expression
282 lease
, client_state
, in_options
,
283 out_options
, scope
, r
-> data
.retval
, MDL
);
284 #if defined (DEBUG_EXPRESSIONS)
285 log_debug ("exec: return: %s",
286 (status
? "succeeded" : "failed"));
293 #if defined (DEBUG_EXPRESSIONS)
294 log_debug ("exec: add %s", (r
->data
.add
->name
296 : "<unnamed class>"));
298 classify (packet
, r
->data
.add
);
301 case break_statement
:
302 #if defined (DEBUG_EXPRESSIONS)
303 log_debug ("exec: break");
307 case supersede_option_statement
:
308 case send_option_statement
:
309 #if defined (DEBUG_EXPRESSIONS)
310 log_debug ("exec: %s option %s.%s",
311 (r
->op
== supersede_option_statement
312 ? "supersede" : "send"),
313 r
->data
.option
->option
->universe
->name
,
314 r
->data
.option
->option
->name
);
315 goto option_statement
;
317 case default_option_statement
:
318 #if defined (DEBUG_EXPRESSIONS)
319 log_debug ("exec: default option %s.%s",
320 r
->data
.option
->option
->universe
->name
,
321 r
->data
.option
->option
->name
);
322 goto option_statement
;
324 case append_option_statement
:
325 #if defined (DEBUG_EXPRESSIONS)
326 log_debug ("exec: append option %s.%s",
327 r
->data
.option
->option
->universe
->name
,
328 r
->data
.option
->option
->name
);
329 goto option_statement
;
331 case prepend_option_statement
:
332 #if defined (DEBUG_EXPRESSIONS)
333 log_debug ("exec: prepend option %s.%s",
334 r
->data
.option
->option
->universe
->name
,
335 r
->data
.option
->option
->name
);
338 set_option (r
->data
.option
->option
->universe
,
339 out_options
, r
->data
.option
, r
->op
);
343 case define_statement
:
346 log_error("set %s: no scope",
351 if (!binding_scope_allocate(scope
, MDL
)) {
352 log_error("set %s: can't allocate scope",
357 binding
= find_binding(*scope
, r
->data
.set
.name
);
358 #if defined (DEBUG_EXPRESSIONS)
359 log_debug("exec: set %s", r
->data
.set
.name
);
363 if (binding
== NULL
) {
364 binding
= dmalloc(sizeof(*binding
), MDL
);
365 if (binding
!= NULL
) {
366 memset(binding
, 0, sizeof(*binding
));
369 (r
->data
.set
.name
) + 1,
371 if (binding
->name
!= NULL
) {
372 strcpy(binding
->name
, r
->data
.set
.name
);
373 binding
->next
= (*scope
)->bindings
;
374 (*scope
)->bindings
= binding
;
381 if (binding
!= NULL
) {
382 if (binding
->value
!= NULL
)
383 binding_value_dereference
384 (&binding
->value
, MDL
);
385 if (r
->op
== set_statement
) {
386 status
= (evaluate_expression
387 (&binding
->value
, packet
,
389 in_options
, out_options
,
390 scope
, r
->data
.set
.expr
,
393 if (!(binding_value_allocate
394 (&binding
->value
, MDL
))) {
398 if ((binding
!= NULL
) &&
399 (binding
->value
!= NULL
)) {
400 binding
->value
->type
=
403 (&binding
->value
->value
.fundef
,
404 r
->data
.set
.expr
->data
.func
,
409 #if defined (DEBUG_EXPRESSIONS)
410 log_debug ("exec: set %s%s", r
-> data
.set
.name
,
411 (binding
&& status
? "" : " (failed)"));
417 case unset_statement
:
418 if (!scope
|| !*scope
)
420 binding
= find_binding (*scope
, r
->data
.unset
);
423 binding_value_dereference
424 (&binding
->value
, MDL
);
428 #if defined (DEBUG_EXPRESSIONS)
429 log_debug ("exec: unset %s: %s", r
->data
.unset
,
430 (status
? "found" : "not found"));
437 #if defined (DEBUG_EXPRESSIONS)
438 log_debug("exec: let %s", r
->data
.let
.name
);
442 binding_scope_allocate (&ns
, MDL
);
447 binding
= dmalloc(sizeof(*binding
), MDL
);
448 memset(binding
, 0, sizeof(*binding
));
451 binding_scope_dereference(&ns
, MDL
);
455 (e
->data
.let
.name
+ 1),
458 strcpy(binding
->name
,
470 status
= (evaluate_expression
471 (&binding
->value
, packet
, lease
,
473 in_options
, out_options
,
474 scope
, e
->data
.set
.expr
, MDL
));
475 binding
->next
= ns
->bindings
;
476 ns
->bindings
= binding
;
479 #if defined (DEBUG_EXPRESSIONS)
480 log_debug("exec: let %s%s", e
->data
.let
.name
,
481 (binding
&& status
? "" : "failed"));
485 if (!e
->data
.let
.statements
) {
486 } else if (e
->data
.let
.statements
->op
==
488 e
= e
->data
.let
.statements
;
492 binding_scope_reference(&ns
->outer
,
495 (result
, packet
, lease
, client_state
,
496 in_options
, out_options
,
497 &ns
, e
->data
.let
.statements
, on_star
);
500 binding_scope_dereference(&ns
, MDL
);
504 memset (&ds
, 0, sizeof ds
);
505 status
= (evaluate_data_expression
507 lease
, client_state
, in_options
,
508 out_options
, scope
, r
->data
.log
.expr
, MDL
));
510 #if defined (DEBUG_EXPRESSIONS)
511 log_debug ("exec: log");
515 switch (r
->data
.log
.priority
) {
516 case log_priority_fatal
:
517 log_fatal ("%.*s", (int)ds
.len
,
520 case log_priority_error
:
521 log_error ("%.*s", (int)ds
.len
,
524 case log_priority_debug
:
525 log_debug ("%.*s", (int)ds
.len
,
528 case log_priority_info
:
529 log_info ("%.*s", (int)ds
.len
,
533 data_string_forget (&ds
, MDL
);
539 log_error ("bogus statement type %d", r
-> op
);
542 executable_statement_dereference (&r
, MDL
);
544 executable_statement_reference (&r
, next
, MDL
);
545 executable_statement_dereference (&next
, MDL
);
552 /* Execute all the statements in a particular scope, and all statements in
553 scopes outer from that scope, but if a particular limiting scope is
554 reached, do not execute statements in that scope or in scopes outer
555 from it. More specific scopes need to take precedence over less
556 specific scopes, so we recursively traverse the scope list, executing
557 the most outer scope first. */
559 void execute_statements_in_scope (result
, packet
,
560 lease
, client_state
, in_options
, out_options
,
561 scope
, group
, limiting_group
, on_star
)
562 struct binding_value
**result
;
563 struct packet
*packet
;
565 struct client_state
*client_state
;
566 struct option_state
*in_options
;
567 struct option_state
*out_options
;
568 struct binding_scope
**scope
;
570 struct group
*limiting_group
;
571 struct on_star
*on_star
;
575 /* If we've recursed as far as we can, return. */
579 /* As soon as we get to a scope that is outer than the limiting
580 scope, we are done. This is so that if somebody does something
581 like this, it does the expected thing:
583 domain-name "fugue.com";
586 domain-name "othello.fugue.com";
587 fixed-address 10.20.30.40;
589 subnet 10.20.30.0 netmask 255.255.255.0 {
590 domain-name "manhattan.fugue.com";
594 The problem with the above arrangement is that the host's
595 group nesting will be host -> shared-network -> top-level,
596 and the limiting scope when we evaluate the host's scope
597 will be the subnet -> shared-network -> top-level, so we need
598 to know when we evaluate the host's scope to stop before we
599 evaluate the shared-networks scope, because it's outer than
600 the limiting scope, which means we've already evaluated it. */
602 for (limit
= limiting_group
; limit
; limit
= limit
-> next
) {
608 execute_statements_in_scope (result
, packet
,
610 in_options
, out_options
, scope
,
611 group
->next
, limiting_group
,
613 execute_statements (result
, packet
, lease
, client_state
, in_options
,
614 out_options
, scope
, group
->statements
, on_star
);
617 /* Dereference or free any subexpressions of a statement being freed. */
619 int executable_statement_dereference (ptr
, file
, line
)
620 struct executable_statement
**ptr
;
625 log_error ("%s(%d): null pointer", file
, line
);
626 #if defined (POINTER_DEBUG)
634 rc_register (file
, line
, ptr
, *ptr
, (*ptr
) -> refcnt
, 1, RC_MISC
);
635 if ((*ptr
) -> refcnt
> 0) {
636 *ptr
= (struct executable_statement
*)0;
640 if ((*ptr
) -> refcnt
< 0) {
641 log_error ("%s(%d): negative refcnt!", file
, line
);
642 #if defined (DEBUG_RC_HISTORY)
643 dump_rc_history (*ptr
);
645 #if defined (POINTER_DEBUG)
653 executable_statement_dereference (&(*ptr
) -> next
, file
, line
);
655 switch ((*ptr
) -> op
) {
656 case statements_statement
:
657 if ((*ptr
) -> data
.statements
)
658 executable_statement_dereference
659 (&(*ptr
) -> data
.statements
, file
, line
);
663 if ((*ptr
) -> data
.on
.statements
)
664 executable_statement_dereference
665 (&(*ptr
) -> data
.on
.statements
, file
, line
);
668 case switch_statement
:
669 if ((*ptr
) -> data
.s_switch
.statements
)
670 executable_statement_dereference
671 (&(*ptr
) -> data
.on
.statements
, file
, line
);
672 if ((*ptr
) -> data
.s_switch
.expr
)
673 expression_dereference (&(*ptr
) -> data
.s_switch
.expr
,
678 if ((*ptr
) -> data
.s_switch
.expr
)
679 expression_dereference (&(*ptr
) -> data
.c_case
,
684 if ((*ptr
) -> data
.ie
.expr
)
685 expression_dereference (&(*ptr
) -> data
.ie
.expr
,
687 if ((*ptr
) -> data
.ie
.tc
)
688 executable_statement_dereference
689 (&(*ptr
) -> data
.ie
.tc
, file
, line
);
690 if ((*ptr
) -> data
.ie
.fc
)
691 executable_statement_dereference
692 (&(*ptr
) -> data
.ie
.fc
, file
, line
);
696 if ((*ptr
) -> data
.eval
)
697 expression_dereference (&(*ptr
) -> data
.eval
,
701 case return_statement
:
702 if ((*ptr
) -> data
.eval
)
703 expression_dereference (&(*ptr
) -> data
.eval
,
708 if ((*ptr
)->data
.set
.name
)
709 dfree ((*ptr
)->data
.set
.name
, file
, line
);
710 if ((*ptr
)->data
.set
.expr
)
711 expression_dereference (&(*ptr
) -> data
.set
.expr
,
715 case unset_statement
:
716 if ((*ptr
)->data
.unset
)
717 dfree ((*ptr
)->data
.unset
, file
, line
);
720 case execute_statement
:
721 if ((*ptr
)->data
.execute
.command
)
722 dfree ((*ptr
)->data
.execute
.command
, file
, line
);
723 if ((*ptr
)->data
.execute
.arglist
)
724 expression_dereference (&(*ptr
) -> data
.execute
.arglist
,
728 case supersede_option_statement
:
729 case send_option_statement
:
730 case default_option_statement
:
731 case append_option_statement
:
732 case prepend_option_statement
:
733 if ((*ptr
) -> data
.option
)
734 option_cache_dereference (&(*ptr
) -> data
.option
,
743 dfree ((*ptr
), file
, line
);
744 *ptr
= (struct executable_statement
*)0;
748 void write_statements (file
, statements
, indent
)
750 struct executable_statement
*statements
;
753 #if defined ENABLE_EXECUTE
754 struct expression
*expr
;
756 struct executable_statement
*r
, *x
;
757 const char *s
, *t
, *dot
;
763 for (r
= statements
; r
; r
= r
-> next
) {
765 case statements_statement
:
766 write_statements (file
, r
-> data
.statements
, indent
);
770 indent_spaces (file
, indent
);
771 fprintf (file
, "on ");
773 if (r
-> data
.on
.evtypes
& ON_EXPIRY
) {
774 fprintf (file
, "%sexpiry", s
);
777 if (r
-> data
.on
.evtypes
& ON_COMMIT
) {
778 fprintf (file
, "%scommit", s
);
781 if (r
-> data
.on
.evtypes
& ON_RELEASE
) {
782 fprintf (file
, "%srelease", s
);
785 if (r
-> data
.on
.statements
) {
786 fprintf (file
, " {");
787 write_statements (file
,
788 r
-> data
.on
.statements
,
790 indent_spaces (file
, indent
);
797 case switch_statement
:
798 indent_spaces (file
, indent
);
799 fprintf (file
, "switch (");
800 col
= write_expression (file
,
801 r
-> data
.s_switch
.expr
,
802 indent
+ 7, indent
+ 7, 1);
803 col
= token_print_indent (file
, col
, indent
+ 7,
805 token_print_indent (file
,
806 col
, indent
, " ", "", "{");
807 write_statements (file
, r
-> data
.s_switch
.statements
,
809 indent_spaces (file
, indent
);
814 indent_spaces (file
, indent
- 1);
815 fprintf (file
, "case ");
816 col
= write_expression (file
,
817 r
-> data
.s_switch
.expr
,
818 indent
+ 5, indent
+ 5, 1);
819 token_print_indent (file
, col
, indent
+ 5,
823 case default_statement
:
824 indent_spaces (file
, indent
- 1);
825 fprintf (file
, "default: ");
829 indent_spaces (file
, indent
);
830 fprintf (file
, "if ");
832 col
= write_expression (file
,
834 indent
+ 3, indent
+ 3, 1);
836 token_print_indent (file
, col
, indent
, " ", "", "{");
837 write_statements (file
, x
-> data
.ie
.tc
, indent
+ 2);
838 if (x
-> data
.ie
.fc
&&
839 x
-> data
.ie
.fc
-> op
== if_statement
&&
840 !x
-> data
.ie
.fc
-> next
) {
841 indent_spaces (file
, indent
);
842 fprintf (file
, "} elsif ");
844 col
= write_expression (file
,
850 if (x
-> data
.ie
.fc
) {
851 indent_spaces (file
, indent
);
852 fprintf (file
, "} else {");
853 write_statements (file
, x
-> data
.ie
.fc
,
856 indent_spaces (file
, indent
);
861 indent_spaces (file
, indent
);
862 fprintf (file
, "eval ");
863 (void) write_expression (file
, r
-> data
.eval
,
864 indent
+ 5, indent
+ 5, 1);
868 case return_statement
:
869 indent_spaces (file
, indent
);
870 fprintf (file
, "return;");
874 indent_spaces (file
, indent
);
875 fprintf (file
, "add \"%s\"", r
-> data
.add
-> name
);
878 case break_statement
:
879 indent_spaces (file
, indent
);
880 fprintf (file
, "break;");
883 case supersede_option_statement
:
884 case send_option_statement
:
886 goto option_statement
;
888 case default_option_statement
:
890 goto option_statement
;
892 case append_option_statement
:
894 goto option_statement
;
896 case prepend_option_statement
:
899 /* Note: the reason we don't try to pretty print
900 the option here is that the format of the option
901 may change in dhcpd.conf, and then when this
902 statement was read back, it would cause a syntax
904 if (r
-> data
.option
-> option
-> universe
==
909 t
= (r
-> data
.option
-> option
->
913 indent_spaces (file
, indent
);
914 fprintf (file
, "%s %s%s%s = ", s
, t
, dot
,
915 r
-> data
.option
-> option
-> name
);
916 col
= (indent
+ strlen (s
) + strlen (t
) +
917 strlen (dot
) + strlen (r
-> data
.option
->
918 option
-> name
) + 4);
919 if (r
-> data
.option
-> expression
)
922 r
-> data
.option
-> expression
,
925 token_indent_data_string
926 (file
, col
, indent
+ 8, "", "",
927 &r
-> data
.option
-> data
);
929 fprintf (file
, ";"); /* XXX */
933 indent_spaces (file
, indent
);
934 fprintf (file
, "set ");
935 col
= token_print_indent (file
, indent
+ 4, indent
+ 4,
936 "", "", r
-> data
.set
.name
);
937 (void) token_print_indent (file
, col
, indent
+ 4,
939 col
= write_expression (file
, r
-> data
.set
.expr
,
940 indent
+ 3, indent
+ 3, 0);
941 (void) token_print_indent (file
, col
, indent
+ 4,
945 case unset_statement
:
946 indent_spaces (file
, indent
);
947 fprintf (file
, "unset ");
948 col
= token_print_indent (file
, indent
+ 6, indent
+ 6,
949 "", "", r
-> data
.set
.name
);
950 (void) token_print_indent (file
, col
, indent
+ 6,
955 indent_spaces (file
, indent
);
956 fprintf (file
, "log ");
957 col
= token_print_indent (file
, indent
+ 4, indent
+ 4,
959 switch (r
-> data
.log
.priority
) {
960 case log_priority_fatal
:
961 (void) token_print_indent
962 (file
, col
, indent
+ 4, "",
965 case log_priority_error
:
966 (void) token_print_indent
967 (file
, col
, indent
+ 4, "",
970 case log_priority_debug
:
971 (void) token_print_indent
972 (file
, col
, indent
+ 4, "",
975 case log_priority_info
:
976 (void) token_print_indent
977 (file
, col
, indent
+ 4, "",
981 col
= write_expression (file
, r
-> data
.log
.expr
,
982 indent
+ 4, indent
+ 4, 0);
983 (void) token_print_indent (file
, col
, indent
+ 4,
988 case execute_statement
:
989 #ifdef ENABLE_EXECUTE
990 indent_spaces (file
, indent
);
991 col
= token_print_indent(file
, indent
+ 4, indent
+ 4,
993 col
= token_print_indent(file
, col
, indent
+ 4, " ", "",
995 col
= token_print_indent(file
, col
, indent
+ 4, "\"", "\"", r
->data
.execute
.command
);
996 for (expr
= r
->data
.execute
.arglist
; expr
; expr
= expr
->data
.arg
.next
) {
997 col
= token_print_indent(file
, col
, indent
+ 4, "", " ", ",");
998 col
= write_expression (file
, expr
->data
.arg
.val
, col
, indent
+ 4, 0);
1000 (void) token_print_indent(file
, col
, indent
+ 4, "", "", ");");
1001 #else /* !ENABLE_EXECUTE */
1002 log_fatal("Impossible case at %s:%d (ENABLE_EXECUTE "
1003 "is not defined).", MDL
);
1004 #endif /* ENABLE_EXECUTE */
1008 log_fatal ("bogus statement type %d\n", r
-> op
);
1013 /* Find a case statement in the sequence of executable statements that
1014 matches the expression, and if found, return the following statement.
1015 If no case statement matches, try to find a default statement and
1016 return that (the default statement can precede all the case statements).
1017 Otherwise, return the null statement. */
1019 int find_matching_case (struct executable_statement
**ep
,
1020 struct packet
*packet
, struct lease
*lease
,
1021 struct client_state
*client_state
,
1022 struct option_state
*in_options
,
1023 struct option_state
*out_options
,
1024 struct binding_scope
**scope
,
1025 struct expression
*expr
,
1026 struct executable_statement
*stmt
)
1029 struct executable_statement
*s
;
1031 if (is_data_expression (expr
)) {
1032 struct data_string cd
, ds
;
1033 memset (&ds
, 0, sizeof ds
);
1034 memset (&cd
, 0, sizeof cd
);
1036 status
= (evaluate_data_expression (&ds
, packet
, lease
,
1037 client_state
, in_options
,
1038 out_options
, scope
, expr
,
1041 for (s
= stmt
; s
; s
= s
-> next
) {
1042 if (s
-> op
== case_statement
) {
1043 sub
= (evaluate_data_expression
1044 (&cd
, packet
, lease
, client_state
,
1045 in_options
, out_options
,
1046 scope
, s
->data
.c_case
, MDL
));
1047 if (sub
&& cd
.len
== ds
.len
&&
1048 !memcmp (cd
.data
, ds
.data
, cd
.len
))
1050 data_string_forget (&cd
, MDL
);
1051 data_string_forget (&ds
, MDL
);
1052 executable_statement_reference
1056 data_string_forget (&cd
, MDL
);
1059 data_string_forget (&ds
, MDL
);
1063 status
= evaluate_numeric_expression (&n
, packet
, lease
,
1065 in_options
, out_options
,
1069 for (s
= stmt
; s
; s
= s
->next
) {
1070 if (s
-> op
== case_statement
) {
1071 sub
= (evaluate_numeric_expression
1072 (&c
, packet
, lease
, client_state
,
1073 in_options
, out_options
,
1074 scope
, s
->data
.c_case
));
1075 if (sub
&& n
== c
) {
1076 executable_statement_reference
1085 /* If we didn't find a matching case statement, look for a default
1086 statement and return the statement following it. */
1087 for (s
= stmt
; s
; s
= s
->next
)
1088 if (s
->op
== default_statement
)
1091 executable_statement_reference (ep
, s
->next
, MDL
);
1097 int executable_statement_foreach (struct executable_statement
*stmt
,
1098 int (*callback
) (struct
1099 executable_statement
*,
1101 void *vp
, int condp
)
1103 struct executable_statement
*foo
;
1106 for (foo
= stmt
; foo
; foo
= foo
->next
) {
1107 if ((*callback
) (foo
, vp
, condp
) != 0)
1110 case null_statement
:
1113 if (executable_statement_foreach (foo
->data
.ie
.tc
,
1116 if (executable_statement_foreach (foo
->data
.ie
.fc
,
1122 case eval_statement
:
1124 case break_statement
:
1126 case default_option_statement
:
1128 case supersede_option_statement
:
1130 case append_option_statement
:
1132 case prepend_option_statement
:
1134 case send_option_statement
:
1136 case statements_statement
:
1137 if ((executable_statement_foreach
1138 (foo
->data
.statements
, callback
, vp
, condp
)))
1142 if ((executable_statement_foreach
1143 (foo
->data
.on
.statements
, callback
, vp
, 1)))
1146 case switch_statement
:
1147 if ((executable_statement_foreach
1148 (foo
->data
.s_switch
.statements
, callback
, vp
, 1)))
1151 case case_statement
:
1153 case default_statement
:
1157 case unset_statement
:
1160 if ((executable_statement_foreach
1161 (foo
->data
.let
.statements
, callback
, vp
, 0)))
1164 case define_statement
:
1167 case return_statement
:
1168 case execute_statement
: