Remove building with NOCRYPTO option
[minix.git] / external / bsd / dhcp / dist / common / execute.c
blob4d283e8af4454ccf6db6d81e0c10132ce937e643
1 /* $NetBSD: execute.c,v 1.1.1.3 2014/07/12 11:57:44 spz Exp $ */
2 /* execute.c
4 Support for executable statements. */
6 /*
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.
24 * 950 Charter Street
25 * Redwood City, CA 94063
26 * <info@isc.org>
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 $");
34 #include "dhcpd.h"
35 #include <omapip/omapip_p.h>
36 #include <sys/types.h>
37 #include <sys/wait.h>
39 int execute_statements (result, packet, lease, client_state,
40 in_options, out_options, scope, statements,
41 on_star)
42 struct binding_value **result;
43 struct packet *packet;
44 struct lease *lease;
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;
53 int rc;
54 int status;
55 struct binding *binding;
56 struct data_string ds;
57 struct binding_scope *ns;
59 if (!statements)
60 return 1;
62 r = NULL;
63 next = NULL;
64 e = NULL;
65 executable_statement_reference (&r, statements, MDL);
66 while (r && !(result && *result)) {
67 if (r->next)
68 executable_statement_reference (&next, r->next, MDL);
69 switch (r->op) {
70 case statements_statement:
71 #if defined (DEBUG_EXPRESSIONS)
72 log_debug ("exec: statements");
73 #endif
74 status = execute_statements (result, packet, lease,
75 client_state, in_options,
76 out_options, scope,
77 r->data.statements,
78 on_star);
79 #if defined (DEBUG_EXPRESSIONS)
80 log_debug ("exec: statements returns %d", status);
81 #endif
82 if (!status)
83 return 0;
84 break;
86 case on_statement:
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");
99 #endif
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");
111 #endif
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");
123 #endif
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);
133 break;
135 case switch_statement:
136 #if defined (DEBUG_EXPRESSIONS)
137 log_debug ("exec: switch");
138 #endif
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);
146 #endif
147 if (status) {
148 if (!(execute_statements
149 (result, packet, lease, client_state,
150 in_options, out_options, scope, e,
151 on_star))) {
152 executable_statement_dereference
153 (&e, MDL);
154 return 0;
156 executable_statement_dereference (&e, MDL);
158 break;
160 /* These have no effect when executed. */
161 case case_statement:
162 case default_statement:
163 break;
165 case if_statement:
166 status = (evaluate_boolean_expression
167 (&rc, packet,
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")
174 : "NULL"));
175 #endif
176 /* XXX Treat NULL as false */
177 if (!status)
178 rc = 0;
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,
183 on_star))
184 return 0;
185 break;
187 case eval_statement:
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"));
194 #else
195 POST(status);
196 #endif
197 break;
199 case execute_statement: {
200 #ifdef ENABLE_EXECUTE
201 struct expression *expr;
202 char **argv;
203 int i, argc = r->data.execute.argc;
204 pid_t p;
206 /* save room for the command and the NULL terminator */
207 argv = dmalloc((argc + 2) * sizeof(*argv), MDL);
208 if (!argv)
209 break;
211 argv[0] = dmalloc(strlen(r->data.execute.command) + 1,
212 MDL);
213 if (argv[0]) {
214 strcpy(argv[0], r->data.execute.command);
215 } else {
216 goto execute_out;
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
225 (&ds, packet,
226 lease, client_state, in_options,
227 out_options, scope,
228 expr->data.arg.val, MDL));
229 if (status) {
230 argv[i] = dmalloc(ds.len + 1, MDL);
231 if (argv[i]) {
232 memcpy(argv[i], ds.data,
233 ds.len);
234 argv[i][ds.len] = 0;
235 log_debug("execute_statement argv[%d] = %s", i, argv[i]);
237 data_string_forget (&ds, MDL);
238 if (!argv[i]) {
239 log_debug("execute_statement failed argv[%d]", i);
240 goto execute_out;
242 } else {
243 log_debug("execute: bad arg %d", i);
244 goto execute_out;
247 argv[i] = NULL;
249 if ((p = fork()) > 0) {
250 int status;
251 waitpid(p, &status, 0);
253 if (status) {
254 log_error("execute: %s exit status %d",
255 argv[0], status);
257 } else if (p == 0) {
258 execvp(argv[0], argv);
259 log_error("Unable to execute %s: %m", argv[0]);
260 _exit(127);
261 } else {
262 log_error("execute: fork() failed");
265 execute_out:
266 for (i = 0; i <= argc; i++) {
267 if(argv[i])
268 dfree(argv[i], MDL);
271 dfree(argv, MDL);
272 #else /* !ENABLE_EXECUTE */
273 log_fatal("Impossible case at %s:%d (ENABLE_EXECUTE "
274 "is not defined).", MDL);
275 #endif /* ENABLE_EXECUTE */
276 break;
279 case return_statement:
280 status = evaluate_expression
281 (result, packet,
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"));
287 #else
288 POST(status);
289 #endif
290 break;
292 case add_statement:
293 #if defined (DEBUG_EXPRESSIONS)
294 log_debug ("exec: add %s", (r->data.add->name
295 ? r->data.add->name
296 : "<unnamed class>"));
297 #endif
298 classify (packet, r->data.add);
299 break;
301 case break_statement:
302 #if defined (DEBUG_EXPRESSIONS)
303 log_debug ("exec: break");
304 #endif
305 return 1;
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;
316 #endif
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;
323 #endif
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;
330 #endif
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);
336 option_statement:
337 #endif
338 set_option (r->data.option->option->universe,
339 out_options, r->data.option, r->op);
340 break;
342 case set_statement:
343 case define_statement:
344 status = 1;
345 if (!scope) {
346 log_error("set %s: no scope",
347 r->data.set.name);
348 break;
350 if (!*scope) {
351 if (!binding_scope_allocate(scope, MDL)) {
352 log_error("set %s: can't allocate scope",
353 r->data.set.name);
354 break;
357 binding = find_binding(*scope, r->data.set.name);
358 #if defined (DEBUG_EXPRESSIONS)
359 log_debug("exec: set %s", r->data.set.name);
360 #else
361 POST(status);
362 #endif
363 if (binding == NULL) {
364 binding = dmalloc(sizeof(*binding), MDL);
365 if (binding != NULL) {
366 memset(binding, 0, sizeof(*binding));
367 binding->name =
368 dmalloc(strlen
369 (r->data.set.name) + 1,
370 MDL);
371 if (binding->name != NULL) {
372 strcpy(binding->name, r->data.set.name);
373 binding->next = (*scope)->bindings;
374 (*scope)->bindings = binding;
375 } else {
376 dfree(binding, MDL);
377 binding = NULL;
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,
388 lease, client_state,
389 in_options, out_options,
390 scope, r->data.set.expr,
391 MDL));
392 } else {
393 if (!(binding_value_allocate
394 (&binding->value, MDL))) {
395 dfree(binding, MDL);
396 binding = NULL;
398 if ((binding != NULL) &&
399 (binding->value != NULL)) {
400 binding->value->type =
401 binding_function;
402 (fundef_reference
403 (&binding->value->value.fundef,
404 r->data.set.expr->data.func,
405 MDL));
409 #if defined (DEBUG_EXPRESSIONS)
410 log_debug ("exec: set %s%s", r -> data.set.name,
411 (binding && status ? "" : " (failed)"));
412 #else
413 POST(status);
414 #endif
415 break;
417 case unset_statement:
418 if (!scope || !*scope)
419 break;
420 binding = find_binding (*scope, r->data.unset);
421 if (binding) {
422 if (binding->value)
423 binding_value_dereference
424 (&binding->value, MDL);
425 status = 1;
426 } else
427 status = 0;
428 #if defined (DEBUG_EXPRESSIONS)
429 log_debug ("exec: unset %s: %s", r->data.unset,
430 (status ? "found" : "not found"));
431 #else
432 POST(status);
433 #endif
434 break;
436 case let_statement:
437 #if defined (DEBUG_EXPRESSIONS)
438 log_debug("exec: let %s", r->data.let.name);
439 #endif
440 status = 0;
441 ns = NULL;
442 binding_scope_allocate (&ns, MDL);
443 e = r;
445 next_let:
446 if (ns) {
447 binding = dmalloc(sizeof(*binding), MDL);
448 memset(binding, 0, sizeof(*binding));
449 if (!binding) {
450 blb:
451 binding_scope_dereference(&ns, MDL);
452 } else {
453 binding->name =
454 dmalloc(strlen
455 (e->data.let.name + 1),
456 MDL);
457 if (binding->name)
458 strcpy(binding->name,
459 e->data.let.name);
460 else {
461 dfree(binding, MDL);
462 binding = NULL;
463 goto blb;
466 } else
467 binding = NULL;
469 if (ns && binding) {
470 status = (evaluate_expression
471 (&binding->value, packet, lease,
472 client_state,
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"));
482 #else
483 POST(status);
484 #endif
485 if (!e->data.let.statements) {
486 } else if (e->data.let.statements->op ==
487 let_statement) {
488 e = e->data.let.statements;
489 goto next_let;
490 } else if (ns) {
491 if (scope && *scope)
492 binding_scope_reference(&ns->outer,
493 *scope, MDL);
494 execute_statements
495 (result, packet, lease, client_state,
496 in_options, out_options,
497 &ns, e->data.let.statements, on_star);
499 if (ns)
500 binding_scope_dereference(&ns, MDL);
501 break;
503 case log_statement:
504 memset (&ds, 0, sizeof ds);
505 status = (evaluate_data_expression
506 (&ds, packet,
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");
512 #endif
514 if (status) {
515 switch (r->data.log.priority) {
516 case log_priority_fatal:
517 log_fatal ("%.*s", (int)ds.len,
518 ds.data);
519 break;
520 case log_priority_error:
521 log_error ("%.*s", (int)ds.len,
522 ds.data);
523 break;
524 case log_priority_debug:
525 log_debug ("%.*s", (int)ds.len,
526 ds.data);
527 break;
528 case log_priority_info:
529 log_info ("%.*s", (int)ds.len,
530 ds.data);
531 break;
533 data_string_forget (&ds, MDL);
536 break;
538 default:
539 log_error ("bogus statement type %d", r -> op);
540 break;
542 executable_statement_dereference (&r, MDL);
543 if (next) {
544 executable_statement_reference (&r, next, MDL);
545 executable_statement_dereference (&next, MDL);
549 return 1;
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;
564 struct lease *lease;
565 struct client_state *client_state;
566 struct option_state *in_options;
567 struct option_state *out_options;
568 struct binding_scope **scope;
569 struct group *group;
570 struct group *limiting_group;
571 struct on_star *on_star;
573 struct group *limit;
575 /* If we've recursed as far as we can, return. */
576 if (!group)
577 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";
584 shared-network FOO {
585 host bar {
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) {
603 if (group == limit)
604 return;
607 if (group -> next)
608 execute_statements_in_scope (result, packet,
609 lease, client_state,
610 in_options, out_options, scope,
611 group->next, limiting_group,
612 on_star);
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;
621 const char *file;
622 int line;
624 if (!ptr || !*ptr) {
625 log_error ("%s(%d): null pointer", file, line);
626 #if defined (POINTER_DEBUG)
627 abort ();
628 #else
629 return 0;
630 #endif
633 (*ptr) -> refcnt--;
634 rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC);
635 if ((*ptr) -> refcnt > 0) {
636 *ptr = (struct executable_statement *)0;
637 return 1;
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);
644 #endif
645 #if defined (POINTER_DEBUG)
646 abort ();
647 #else
648 return 0;
649 #endif
652 if ((*ptr) -> next)
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);
660 break;
662 case on_statement:
663 if ((*ptr) -> data.on.statements)
664 executable_statement_dereference
665 (&(*ptr) -> data.on.statements, file, line);
666 break;
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,
674 file, line);
675 break;
677 case case_statement:
678 if ((*ptr) -> data.s_switch.expr)
679 expression_dereference (&(*ptr) -> data.c_case,
680 file, line);
681 break;
683 case if_statement:
684 if ((*ptr) -> data.ie.expr)
685 expression_dereference (&(*ptr) -> data.ie.expr,
686 file, line);
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);
693 break;
695 case eval_statement:
696 if ((*ptr) -> data.eval)
697 expression_dereference (&(*ptr) -> data.eval,
698 file, line);
699 break;
701 case return_statement:
702 if ((*ptr) -> data.eval)
703 expression_dereference (&(*ptr) -> data.eval,
704 file, line);
705 break;
707 case set_statement:
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,
712 file, line);
713 break;
715 case unset_statement:
716 if ((*ptr)->data.unset)
717 dfree ((*ptr)->data.unset, file, line);
718 break;
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,
725 file, line);
726 break;
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,
735 file, line);
736 break;
738 default:
739 /* Nothing to do. */
740 break;
743 dfree ((*ptr), file, line);
744 *ptr = (struct executable_statement *)0;
745 return 1;
748 void write_statements (file, statements, indent)
749 FILE *file;
750 struct executable_statement *statements;
751 int indent;
753 #if defined ENABLE_EXECUTE
754 struct expression *expr;
755 #endif
756 struct executable_statement *r, *x;
757 const char *s, *t, *dot;
758 int col;
760 if (!statements)
761 return;
763 for (r = statements; r; r = r -> next) {
764 switch (r -> op) {
765 case statements_statement:
766 write_statements (file, r -> data.statements, indent);
767 break;
769 case on_statement:
770 indent_spaces (file, indent);
771 fprintf (file, "on ");
772 s = "";
773 if (r -> data.on.evtypes & ON_EXPIRY) {
774 fprintf (file, "%sexpiry", s);
775 s = " or ";
777 if (r -> data.on.evtypes & ON_COMMIT) {
778 fprintf (file, "%scommit", s);
779 s = " or ";
781 if (r -> data.on.evtypes & ON_RELEASE) {
782 fprintf (file, "%srelease", s);
783 /* s = " or "; */
785 if (r -> data.on.statements) {
786 fprintf (file, " {");
787 write_statements (file,
788 r -> data.on.statements,
789 indent + 2);
790 indent_spaces (file, indent);
791 fprintf (file, "}");
792 } else {
793 fprintf (file, ";");
795 break;
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,
804 "", "", ")");
805 token_print_indent (file,
806 col, indent, " ", "", "{");
807 write_statements (file, r -> data.s_switch.statements,
808 indent + 2);
809 indent_spaces (file, indent);
810 fprintf (file, "}");
811 break;
813 case case_statement:
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,
820 "", "", ":");
821 break;
823 case default_statement:
824 indent_spaces (file, indent - 1);
825 fprintf (file, "default: ");
826 break;
828 case if_statement:
829 indent_spaces (file, indent);
830 fprintf (file, "if ");
831 x = r;
832 col = write_expression (file,
833 x -> data.ie.expr,
834 indent + 3, indent + 3, 1);
835 else_if:
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 ");
843 x = x -> data.ie.fc;
844 col = write_expression (file,
845 x -> data.ie.expr,
846 indent + 6,
847 indent + 6, 1);
848 goto else_if;
850 if (x -> data.ie.fc) {
851 indent_spaces (file, indent);
852 fprintf (file, "} else {");
853 write_statements (file, x -> data.ie.fc,
854 indent + 2);
856 indent_spaces (file, indent);
857 fprintf (file, "}");
858 break;
860 case eval_statement:
861 indent_spaces (file, indent);
862 fprintf (file, "eval ");
863 (void) write_expression (file, r -> data.eval,
864 indent + 5, indent + 5, 1);
865 fprintf (file, ";");
866 break;
868 case return_statement:
869 indent_spaces (file, indent);
870 fprintf (file, "return;");
871 break;
873 case add_statement:
874 indent_spaces (file, indent);
875 fprintf (file, "add \"%s\"", r -> data.add -> name);
876 break;
878 case break_statement:
879 indent_spaces (file, indent);
880 fprintf (file, "break;");
881 break;
883 case supersede_option_statement:
884 case send_option_statement:
885 s = "supersede";
886 goto option_statement;
888 case default_option_statement:
889 s = "default";
890 goto option_statement;
892 case append_option_statement:
893 s = "append";
894 goto option_statement;
896 case prepend_option_statement:
897 s = "prepend";
898 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
903 error. */
904 if (r -> data.option -> option -> universe ==
905 &dhcp_universe) {
906 t = "";
907 dot = "";
908 } else {
909 t = (r -> data.option -> option ->
910 universe -> name);
911 dot = ".";
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)
920 write_expression
921 (file,
922 r -> data.option -> expression,
923 col, indent + 8, 1);
924 else
925 token_indent_data_string
926 (file, col, indent + 8, "", "",
927 &r -> data.option -> data);
929 fprintf (file, ";"); /* XXX */
930 break;
932 case set_statement:
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,
938 " ", " ", "=");
939 col = write_expression (file, r -> data.set.expr,
940 indent + 3, indent + 3, 0);
941 (void) token_print_indent (file, col, indent + 4,
942 " ", "", ";");
943 break;
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,
951 " ", "", ";");
952 break;
954 case log_statement:
955 indent_spaces (file, indent);
956 fprintf (file, "log ");
957 col = token_print_indent (file, indent + 4, indent + 4,
958 "", "", "(");
959 switch (r -> data.log.priority) {
960 case log_priority_fatal:
961 (void) token_print_indent
962 (file, col, indent + 4, "",
963 " ", "fatal,");
964 break;
965 case log_priority_error:
966 (void) token_print_indent
967 (file, col, indent + 4, "",
968 " ", "error,");
969 break;
970 case log_priority_debug:
971 (void) token_print_indent
972 (file, col, indent + 4, "",
973 " ", "debug,");
974 break;
975 case log_priority_info:
976 (void) token_print_indent
977 (file, col, indent + 4, "",
978 " ", "info,");
979 break;
981 col = write_expression (file, r -> data.log.expr,
982 indent + 4, indent + 4, 0);
983 (void) token_print_indent (file, col, indent + 4,
984 "", "", ");");
986 break;
988 case execute_statement:
989 #ifdef ENABLE_EXECUTE
990 indent_spaces (file, indent);
991 col = token_print_indent(file, indent + 4, indent + 4,
992 "", "", "execute");
993 col = token_print_indent(file, col, indent + 4, " ", "",
994 "(");
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 */
1005 break;
1007 default:
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)
1028 int status, sub;
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,
1039 MDL));
1040 if (status) {
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
1053 (ep, s->next, MDL);
1054 return 1;
1056 data_string_forget (&cd, MDL);
1059 data_string_forget (&ds, MDL);
1061 } else {
1062 unsigned long n, c;
1063 status = evaluate_numeric_expression (&n, packet, lease,
1064 client_state,
1065 in_options, out_options,
1066 scope, expr);
1068 if (status) {
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
1077 (ep, s->next, MDL);
1078 return 1;
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)
1089 break;
1090 if (s) {
1091 executable_statement_reference (ep, s->next, MDL);
1092 return 1;
1094 return 0;
1097 int executable_statement_foreach (struct executable_statement *stmt,
1098 int (*callback) (struct
1099 executable_statement *,
1100 void *, int),
1101 void *vp, int condp)
1103 struct executable_statement *foo;
1104 int ok = 0;
1106 for (foo = stmt; foo; foo = foo->next) {
1107 if ((*callback) (foo, vp, condp) != 0)
1108 ok = 1;
1109 switch (foo->op) {
1110 case null_statement:
1111 break;
1112 case if_statement:
1113 if (executable_statement_foreach (foo->data.ie.tc,
1114 callback, vp, 1))
1115 ok = 1;
1116 if (executable_statement_foreach (foo->data.ie.fc,
1117 callback, vp, 1))
1118 ok = 1;
1119 break;
1120 case add_statement:
1121 break;
1122 case eval_statement:
1123 break;
1124 case break_statement:
1125 break;
1126 case default_option_statement:
1127 break;
1128 case supersede_option_statement:
1129 break;
1130 case append_option_statement:
1131 break;
1132 case prepend_option_statement:
1133 break;
1134 case send_option_statement:
1135 break;
1136 case statements_statement:
1137 if ((executable_statement_foreach
1138 (foo->data.statements, callback, vp, condp)))
1139 ok = 1;
1140 break;
1141 case on_statement:
1142 if ((executable_statement_foreach
1143 (foo->data.on.statements, callback, vp, 1)))
1144 ok = 1;
1145 break;
1146 case switch_statement:
1147 if ((executable_statement_foreach
1148 (foo->data.s_switch.statements, callback, vp, 1)))
1149 ok = 1;
1150 break;
1151 case case_statement:
1152 break;
1153 case default_statement:
1154 break;
1155 case set_statement:
1156 break;
1157 case unset_statement:
1158 break;
1159 case let_statement:
1160 if ((executable_statement_foreach
1161 (foo->data.let.statements, callback, vp, 0)))
1162 ok = 1;
1163 break;
1164 case define_statement:
1165 break;
1166 case log_statement:
1167 case return_statement:
1168 case execute_statement:
1169 break;
1172 return ok;