/** * @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 #include #include #include #include #include #include #include #include #include #include /** 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); }