/* This file is part of the Project Athena Zephyr Notification System. * It is one of the source files comprising zwgc, the Zephyr WindowGram * client. * * Created by: Marc Horowitz * * $Id$ * * Copyright (c) 1989 by the Massachusetts Institute of Technology. * For copying and distribution information, see the file * "mit-copyright.h". */ #include #if (!defined(lint) && !defined(SABER)) static const char rcsid_exec_c[] = "$Id$"; #endif #include /****************************************************************************/ /* */ /* Module containing code to execute a program: */ /* */ /****************************************************************************/ #include #include "new_memory.h" #include "node.h" #include "exec.h" #include "eval.h" #include "buffer.h" #include "port.h" #include "variables.h" #include "notice.h" #ifdef CMU_ZWGCPLUS #include "plus.h" #endif static int exec_subtree(Node *); static int exec_fields(Node *); /****************************************************************************/ /* */ /* Utility subroutines: */ /* */ /****************************************************************************/ static string eval_exprlist_to_string(Node *exprlist) { string result = string_Copy(""); string temp; int first_time = 1; for (; exprlist; exprlist=exprlist->next) { if (!first_time) result = string_Concat2(result, " "); else first_time = 0; temp = eval_expr(exprlist); result = string_Concat2(result, temp); free(temp); } return(result); } static char ** eval_exprlist_to_args(Node *exprlist) { char **result = (char **)malloc(sizeof(char *)); int argc = 0; for (; exprlist; exprlist=exprlist->next) { result[argc] = eval_expr(exprlist); argc++; result = (char **)realloc(result, (argc+1)*sizeof(char *)); } result[argc] = NULL; return(result); } static void free_args(char **args) { char **p; for (p=args; *p; p++) { free(*p); } free(args); } /****************************************************************************/ /* */ /* Subroutines to handle each particular statement type: */ /* */ /****************************************************************************/ #define NOBREAK 0 #define BREAK 1 #define EXIT 2 /*ARGSUSED*/ static int exec_noop(Node *node) { return(NOBREAK); } /*ARGSUSED*/ static int exec_break(Node *node) { return(BREAK); } /*ARGSUSED*/ static int exec_exit(Node *node) { return(EXIT); } static int exec_set(Node *node) { var_set_variable_then_free_value(node->d.nodes.first->d.string_constant, eval_expr(node->d.nodes.second)); return(NOBREAK); } static int exec_execport(Node *node) { string name = eval_expr(node->d.nodes.first); char **argv = eval_exprlist_to_args(node->d.nodes.second); create_subprocess_port(name, argv); free(name); free_args(argv); return(NOBREAK); } static int exec_appendport(Node *node) { string name, filename; name = eval_expr(node->d.nodes.first); filename = eval_expr(node->d.nodes.second); create_file_append_port(name, filename); free(name); free(filename); return(NOBREAK); } static int exec_inputport(Node *node) { string name, filename; name = eval_expr(node->d.nodes.first); filename = eval_expr(node->d.nodes.second); create_file_input_port(name, filename); free(name); free(filename); return(NOBREAK); } static int exec_outputport(Node *node) { string name, filename; name = eval_expr(node->d.nodes.first); filename = eval_expr(node->d.nodes.second); create_file_output_port(name, filename); free(name); free(filename); return(NOBREAK); } static int exec_closeinput(Node *node) { string name; name = eval_expr(node->d.nodes.first); close_port_input(name); free(name); return(NOBREAK); } static int exec_closeoutput(Node *node) { string name; name = eval_expr(node->d.nodes.first); close_port_output(name); free(name); return(NOBREAK); } static int exec_closeport(Node *node) { string name; name = eval_expr(node->d.nodes.first); close_port_input(name); close_port_output(name); free(name); return(NOBREAK); } static int exec_put(Node *node) { string name, temp; if (node->d.nodes.second) temp = eval_exprlist_to_string(node->d.nodes.second); else temp = string_Copy(buffer_to_string()); if (node->d.nodes.first) { name = eval_expr(node->d.nodes.first); write_on_port(name, temp, strlen(temp)); free(name); } else write_on_port(var_get_variable("output_driver"), temp, strlen(temp)); free(temp); return(NOBREAK); } static int exec_print(Node *node) { string temp; temp = eval_exprlist_to_string(node->d.nodes.first); append_buffer(temp); free(temp); return(NOBREAK); } /*ARGSUSED*/ static int exec_clearbuf(Node *node) { clear_buffer(); return(NOBREAK); } static int exec_case(Node *node) { string constant,temp; Node *match, *cond; int equal_p; constant = string_Downcase(eval_expr(node->d.nodes.first)); for (match=node->d.nodes.second; match; match=match->next) { cond = match->d.nodes.first; if (!cond) { /* default case */ free(constant); return(exec_subtree(match->d.nodes.second)); } for (; cond; cond=cond->next) { temp = string_Downcase(eval_expr(cond)); equal_p = string_Eq(constant, temp); free(temp); if (equal_p) { free(constant); return(exec_subtree(match->d.nodes.second)); } } } free(constant); return(NOBREAK); } static int exec_while(Node *node) { int continue_code = NOBREAK; while (eval_bool_expr(node->d.nodes.first)) { continue_code = exec_subtree(node->d.nodes.second); if (continue_code != NOBREAK) break; } if (continue_code == BREAK) continue_code = NOBREAK; return(continue_code); } static int exec_if(Node *node) { Node *conds; for (conds=node->d.nodes.first; conds; conds=conds->next) if (eval_bool_expr(conds->d.nodes.first)) return(exec_subtree(conds->d.nodes.second)); return(NOBREAK); } static int exec_exec(Node *node) { int pid; char **argv = eval_exprlist_to_args(node->d.nodes.first); pid = fork(); if (pid == -1) { fprintf(stderr, "zwgc: error while attempting to fork: "); perror(""); } else if (pid == 0) { /* in child */ execvp(argv[0], argv); fprintf(stderr,"zwgc: unable to exec %s: ", argv[0]); perror(""); _exit(errno); } free_args(argv); return(NOBREAK); } static struct _Opstuff { int (*exec)(Node *); } const opstuff[] = { { exec_noop }, /* string_constant */ { exec_noop }, /* varref */ { exec_noop }, /* varname */ { exec_noop }, /* not */ { exec_noop }, /* plus */ { exec_noop }, /* and */ { exec_noop }, /* or */ { exec_noop }, /* eq */ { exec_noop }, /* neq */ { exec_noop }, /* regeq */ { exec_noop }, /* regneq */ { exec_noop }, /* buffer */ { exec_noop }, /* substitute */ { exec_noop }, /* protect */ { exec_noop }, /* verbatim */ { exec_noop }, /* stylestrip */ { exec_noop }, /* getenv */ { exec_noop }, /* upcase */ { exec_noop }, /* downcase */ { exec_noop }, /* zvar */ { exec_noop }, /* get */ { exec_noop }, /* lany */ { exec_noop }, /* rany */ { exec_noop }, /* lbreak */ { exec_noop }, /* rbreak */ { exec_noop }, /* lspan */ { exec_noop }, /* rspan */ { exec_noop }, /* noop statement */ { exec_set }, { exec_fields }, { exec_print }, { exec_clearbuf }, { exec_appendport }, { exec_execport }, { exec_inputport }, { exec_outputport }, { exec_put }, { exec_closeinput }, { exec_closeoutput }, { exec_closeport }, { exec_exec }, { exec_if }, { exec_case }, { exec_while }, { exec_break }, { exec_exit }, { exec_noop }, /* if */ { exec_noop }, /* elseif */ { exec_noop }, /* else */ { exec_noop }, /* matchlist */ { exec_noop }, /* default */ }; static int exec_subtree(Node *node) { int retval = NOBREAK; for (; node; node=node->next) { retval = (opstuff[node->opcode].exec)(node); if (retval != NOBREAK) return(retval); } return(NOBREAK); } /***************************************************************************/ static char *notice_fields; static int notice_fields_length = 0; static int number_of_fields = 0; static int exec_fields(Node *node) { for (node=node->d.nodes.first; node; node=node->next) { var_set_variable_then_free_value(node->d.string_constant, get_next_field(¬ice_fields, ¬ice_fields_length)); if (number_of_fields) number_of_fields--; } var_set_variable_to_number("number_of_fields", number_of_fields); return(NOBREAK); } void exec_process_packet(Node *program, ZNotice_t *notice) { #ifdef CMU_ZWGCPLUS set_stored_notice(notice); #endif notice_fields = notice->z_message; notice_fields_length = notice->z_message_len; var_set_number_variables_to_fields(notice_fields, notice_fields_length); number_of_fields = count_nulls(notice_fields, notice_fields_length)+1; /* workaround for bug in old zwrite */ if (notice_fields[notice_fields_length-1] == '\0') number_of_fields--; var_set_variable_to_number("number_of_fields", number_of_fields); clear_buffer(); (void)exec_subtree(program); #ifdef CMU_ZWGCPLUS plus_queue_notice(notice); plus_window_deletions(notice); /* OOPS */ set_stored_notice(NULL); #endif }