diff options
Diffstat (limited to 'apol/apol_tcl.cc')
-rw-r--r-- | apol/apol_tcl.cc | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/apol/apol_tcl.cc b/apol/apol_tcl.cc new file mode 100644 index 0000000..0894b5c --- /dev/null +++ b/apol/apol_tcl.cc @@ -0,0 +1,142 @@ +/** + * @file + * + * Support routines for the apol program that are faster/easier when + * written in C than in Tcl. + * + * @author Jeremy A. Mowery jmowery@tresys.com + * @author Jason Tang jtang@tresys.com + * + * Copyright (C) 2006-2007 Tresys Technology, LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <config.h> + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <tcl.h> + +#include <apol/policy.h> +#include <sefs/db.hh> +#include <sefs/filesystem.hh> + +/** severity of most recent message */ +int msg_level = INT_MAX; + +/** pointer to most recent message string */ +char *message = NULL; + +/** + * Take the formated string, allocate space for it, and then write it + * the policy's msg_callback_arg. If there is already a string + * stored, then append to the string if the message level is equal to + * the previous one, overwrite the string if message level is less + * than previous, else ignore the message. + */ +static void apol_tcl_common_route(void *arg, int level, const char *fmt, va_list ap) +{ + char *s, *t; + Tcl_Interp *interp = static_cast < Tcl_Interp * >(arg); + if (level == APOL_MSG_INFO && msg_level >= APOL_MSG_INFO) + { + /* generate an info event */ + free(message); + message = NULL; + if (vasprintf(&s, fmt, ap) < 0) + { + fprintf(stderr, "%s\n", strerror(errno)); + return; + } + message = s; + msg_level = level; + Tcl_Eval(interp, "Apol_Progress_Dialog::_update_message"); + while (Tcl_DoOneEvent(TCL_IDLE_EVENTS | TCL_DONT_WAIT)) ; + } + else if (message == NULL || level < msg_level) + { + /* overwrite the existing stored message string with a + * new, higher priority message */ + free(message); + message = NULL; + if (vasprintf(&s, fmt, ap) < 0) + { + fprintf(stderr, "%s\n", strerror(errno)); + return; + } + message = s; + msg_level = level; + } + else if (level == msg_level) + { + /* append to existing error message */ + if (vasprintf(&s, fmt, ap) < 0) + { + fprintf(stderr, "%s\n", strerror(errno)); + return; + } + if (asprintf(&t, "%s\n%s", message, s) < 0) + { + free(s); + fprintf(stderr, "%s\n", strerror(errno)); + return; + } + free(s); + free(message); + message = t; + } +} + +void apol_tcl_clear_info_string(void) +{ + if (message != NULL) + { + free(message); + message = NULL; + } + msg_level = INT_MAX; +} + +void apol_tcl_route_apol_to_string(void *arg, const apol_policy_t * p + __attribute__ ((unused)), int level, const char *fmt, va_list ap) +{ + apol_tcl_common_route(arg, level, fmt, ap); +} + +void apol_tcl_route_sefs_to_string(void *arg, const sefs_fclist * s + __attribute__ ((unused)), int level, const char *fmt, va_list ap) +{ + apol_tcl_common_route(arg, level, fmt, ap); +} + +int apol_tcl_get_info_level(void) +{ + return msg_level; +} + +char *apol_tcl_get_info_string(void) +{ + return message; +} + +void apol_tcl_set_info_string(apol_policy_t * p, const char *s) +{ + INFO(p, "%s", s); +} |