xref: /minix3/external/bsd/dhcp/dist/common/execute.c (revision d56f51ea7d8b9045e5c8e2028422523d3f9a5840)
1 /*	$NetBSD: execute.c,v 1.1.1.3 2014/07/12 11:57:44 spz Exp $	*/
2 /* execute.c
3 
4    Support for executable statements. */
5 
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
10  *
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.
14  *
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.
22  *
23  *   Internet Systems Consortium, Inc.
24  *   950 Charter Street
25  *   Redwood City, CA 94063
26  *   <info@isc.org>
27  *   https://www.isc.org/
28  *
29  */
30 
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: execute.c,v 1.1.1.3 2014/07/12 11:57:44 spz Exp $");
33 
34 #include "dhcpd.h"
35 #include <omapip/omapip_p.h>
36 #include <sys/types.h>
37 #include <sys/wait.h>
38 
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;
51 {
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;
58 
59 	if (!statements)
60 		return 1;
61 
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;
85 
86 		      case on_statement:
87 			/*
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.
91 			 */
92 			if ((on_star == NULL) && (lease != NULL))
93 			    on_star = &lease->on_star;
94 
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);
107 			    }
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);
119 			    }
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);
131 			    }
132 			}
133 			break;
134 
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;
155 				}
156 				executable_statement_dereference (&e, MDL);
157 			}
158 			break;
159 
160 			/* These have no effect when executed. */
161 		      case case_statement:
162 		      case default_statement:
163 			break;
164 
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));
170 
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;
186 
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;
198 
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;
205 
206                         /* save room for the command and the NULL terminator */
207                         argv = dmalloc((argc + 2) * sizeof(*argv), MDL);
208                         if (!argv)
209                                 break;
210 
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;
217                         }
218 
219                         log_debug("execute_statement argv[0] = %s", argv[0]);
220 
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]);
236                                         }
237                                         data_string_forget (&ds, MDL);
238                                         if (!argv[i]) {
239                                                 log_debug("execute_statement failed argv[%d]", i);
240                                                 goto execute_out;
241                                         }
242                                 } else {
243                                         log_debug("execute: bad arg %d", i);
244                                         goto execute_out;
245                                 }
246                         }
247                         argv[i] = NULL;
248 
249 	                if ((p = fork()) > 0) {
250 		        	int status;
251 		        	waitpid(p, &status, 0);
252 
253                         	if (status) {
254                                 	log_error("execute: %s exit status %d",
255                                           	   argv[0], status);
256                                 }
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");
263                         }
264 
265                       execute_out:
266                         for (i = 0; i <= argc; i++) {
267                                 if(argv[i])
268                                 	dfree(argv[i], MDL);
269                         }
270 
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;
277                       }
278 
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;
291 
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;
300 
301 		      case break_statement:
302 #if defined (DEBUG_EXPRESSIONS)
303 			log_debug ("exec: break");
304 #endif
305 			return 1;
306 
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;
341 
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;
349 			}
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;
355 			    }
356 			}
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;
378 				    }
379 				}
380 			}
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;
397 				    }
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));
406 				    }
407 				}
408 			}
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;
416 
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;
435 
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;
444 
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;
464 				    }
465 				}
466 			} else
467 				binding = NULL;
468 
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;
477 			}
478 
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);
498 			}
499 			if (ns)
500 				binding_scope_dereference(&ns, MDL);
501 			break;
502 
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));
509 
510 #if defined (DEBUG_EXPRESSIONS)
511 			log_debug ("exec: log");
512 #endif
513 
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;
532 				}
533 				data_string_forget (&ds, MDL);
534 			}
535 
536 			break;
537 
538 		      default:
539 			log_error ("bogus statement type %d", r -> op);
540 			break;
541 		}
542 		executable_statement_dereference (&r, MDL);
543 		if (next) {
544 			executable_statement_reference (&r, next, MDL);
545 			executable_statement_dereference (&next, MDL);
546 		}
547 	}
548 
549 	return 1;
550 }
551 
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. */
558 
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;
572 {
573 	struct group *limit;
574 
575 	/* If we've recursed as far as we can, return. */
576 	if (!group)
577 		return;
578 
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:
582 
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;
588 			}
589 			subnet 10.20.30.0 netmask 255.255.255.0 {
590 				domain-name "manhattan.fugue.com";
591 			}
592 		}
593 
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. */
601 
602 	for (limit = limiting_group; limit; limit = limit -> next) {
603 		if (group == limit)
604 			return;
605 	}
606 
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);
615 }
616 
617 /* Dereference or free any subexpressions of a statement being freed. */
618 
619 int executable_statement_dereference (ptr, file, line)
620 	struct executable_statement **ptr;
621 	const char *file;
622 	int line;
623 {
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
631 	}
632 
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;
638 	}
639 
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
650 	}
651 
652 	if ((*ptr) -> next)
653 		executable_statement_dereference (&(*ptr) -> next, file, line);
654 
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;
661 
662 	      case on_statement:
663 		if ((*ptr) -> data.on.statements)
664 			executable_statement_dereference
665 				(&(*ptr) -> data.on.statements, file, line);
666 		break;
667 
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;
676 
677 	      case case_statement:
678 		if ((*ptr) -> data.s_switch.expr)
679 			expression_dereference (&(*ptr) -> data.c_case,
680 						file, line);
681 		break;
682 
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;
694 
695 	      case eval_statement:
696 		if ((*ptr) -> data.eval)
697 			expression_dereference (&(*ptr) -> data.eval,
698 						file, line);
699 		break;
700 
701 	      case return_statement:
702 		if ((*ptr) -> data.eval)
703 			expression_dereference (&(*ptr) -> data.eval,
704 						file, line);
705 		break;
706 
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;
714 
715 	      case unset_statement:
716 		if ((*ptr)->data.unset)
717 			dfree ((*ptr)->data.unset, file, line);
718 		break;
719 
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;
727 
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;
737 
738 	      default:
739 		/* Nothing to do. */
740 		break;
741 	}
742 
743 	dfree ((*ptr), file, line);
744 	*ptr = (struct executable_statement *)0;
745 	return 1;
746 }
747 
748 void write_statements (file, statements, indent)
749 	FILE *file;
750 	struct executable_statement *statements;
751 	int indent;
752 {
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;
759 
760 	if (!statements)
761 		return;
762 
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;
768 
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 ";
776 			}
777 			if (r -> data.on.evtypes & ON_COMMIT) {
778 				fprintf (file, "%scommit", s);
779 				s = " or ";
780 			}
781 			if (r -> data.on.evtypes & ON_RELEASE) {
782 				fprintf (file, "%srelease", s);
783 				/* s = " or "; */
784 			}
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, ";");
794 			}
795 			break;
796 
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;
812 
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;
822 
823 		      case default_statement:
824 			indent_spaces (file, indent - 1);
825 			fprintf (file, "default: ");
826 			break;
827 
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;
849 			}
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);
855 			}
856 			indent_spaces (file, indent);
857 			fprintf (file, "}");
858 			break;
859 
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;
867 
868 		      case return_statement:
869 			indent_spaces (file, indent);
870 			fprintf (file, "return;");
871 			break;
872 
873 		      case add_statement:
874 			indent_spaces (file, indent);
875 			fprintf (file, "add \"%s\"", r -> data.add -> name);
876 			break;
877 
878 		      case break_statement:
879 			indent_spaces (file, indent);
880 			fprintf (file, "break;");
881 			break;
882 
883 		      case supersede_option_statement:
884 		      case send_option_statement:
885 			s = "supersede";
886 			goto option_statement;
887 
888 		      case default_option_statement:
889 			s = "default";
890 			goto option_statement;
891 
892 		      case append_option_statement:
893 			s = "append";
894 			goto option_statement;
895 
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 = ".";
912 			}
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);
928 
929 			fprintf (file, ";"); /* XXX */
930 			break;
931 
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;
944 
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;
953 
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;
980 			}
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 						  "", "", ");");
985 
986 			break;
987 
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);
999                         }
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;
1006 
1007 		      default:
1008 			log_fatal ("bogus statement type %d\n", r -> op);
1009 		}
1010 	}
1011 }
1012 
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. */
1018 
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)
1027 {
1028 	int status, sub;
1029 	struct executable_statement *s;
1030 
1031 	if (is_data_expression (expr)) {
1032 		struct data_string cd, ds;
1033 		memset (&ds, 0, sizeof ds);
1034 		memset (&cd, 0, sizeof cd);
1035 
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))
1049 				{
1050 					data_string_forget (&cd, MDL);
1051 					data_string_forget (&ds, MDL);
1052 					executable_statement_reference
1053 						(ep, s->next, MDL);
1054 					return 1;
1055 				}
1056 				data_string_forget (&cd, MDL);
1057 			}
1058 		    }
1059 		    data_string_forget (&ds, MDL);
1060 		}
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);
1067 
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;
1079 				}
1080 			}
1081 		    }
1082 		}
1083 	}
1084 
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;
1093 	}
1094 	return 0;
1095 }
1096 
1097 int executable_statement_foreach (struct executable_statement *stmt,
1098 				  int (*callback) (struct
1099 						   executable_statement *,
1100 						   void *, int),
1101 				  void *vp, int condp)
1102 {
1103 	struct executable_statement *foo;
1104 	int ok = 0;
1105 
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;
1170 	    }
1171 	}
1172 	return ok;
1173 }
1174