apol_tcl.cc

Go to the documentation of this file.
00001 /**
00002  * @file
00003  *
00004  * Support routines for the apol program that are faster/easier when
00005  * written in C than in Tcl.
00006  *
00007  * @author Jeremy A. Mowery jmowery@tresys.com
00008  * @author Jason Tang  jtang@tresys.com
00009  *
00010  * Copyright (C) 2006-2007 Tresys Technology, LLC
00011  *
00012  *  This library is free software; you can redistribute it and/or
00013  *  modify it under the terms of the GNU Lesser General Public
00014  *  License as published by the Free Software Foundation; either
00015  *  version 2.1 of the License, or (at your option) any later version.
00016  *
00017  *  This library is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020  *  Lesser General Public License for more details.
00021  *
00022  *  You should have received a copy of the GNU Lesser General Public
00023  *  License along with this library; if not, write to the Free Software
00024  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00025  */
00026 
00027 #include <config.h>
00028 
00029 #include <ctype.h>
00030 #include <errno.h>
00031 #include <limits.h>
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <tcl.h>
00036 
00037 #include <apol/policy.h>
00038 #include <sefs/db.hh>
00039 #include <sefs/filesystem.hh>
00040 
00041 /** severity of most recent message */
00042 int msg_level = INT_MAX;
00043 
00044 /** pointer to most recent message string */
00045 char *message = NULL;
00046 
00047 /**
00048  * Take the formated string, allocate space for it, and then write it
00049  * the policy's msg_callback_arg.  If there is already a string
00050  * stored, then append to the string if the message level is equal to
00051  * the previous one, overwrite the string if message level is less
00052  * than previous, else ignore the message.
00053  */
00054 static void apol_tcl_common_route(void *arg, int level, const char *fmt, va_list ap)
00055 {
00056         char *s, *t;
00057         Tcl_Interp *interp = static_cast < Tcl_Interp * >(arg);
00058         if (level == APOL_MSG_INFO && msg_level >= APOL_MSG_INFO)
00059         {
00060                 /* generate an info event */
00061                 free(message);
00062                 message = NULL;
00063                 if (vasprintf(&s, fmt, ap) < 0)
00064                 {
00065                         fprintf(stderr, "%s\n", strerror(errno));
00066                         return;
00067                 }
00068                 message = s;
00069                 msg_level = level;
00070                 Tcl_Eval(interp, "Apol_Progress_Dialog::_update_message");
00071                 while (Tcl_DoOneEvent(TCL_IDLE_EVENTS | TCL_DONT_WAIT)) ;
00072         }
00073         else if (message == NULL || level < msg_level)
00074         {
00075                 /* overwrite the existing stored message string with a
00076                  * new, higher priority message */
00077                 free(message);
00078                 message = NULL;
00079                 if (vasprintf(&s, fmt, ap) < 0)
00080                 {
00081                         fprintf(stderr, "%s\n", strerror(errno));
00082                         return;
00083                 }
00084                 message = s;
00085                 msg_level = level;
00086         }
00087         else if (level == msg_level)
00088         {
00089                 /* append to existing error message */
00090                 if (vasprintf(&s, fmt, ap) < 0)
00091                 {
00092                         fprintf(stderr, "%s\n", strerror(errno));
00093                         return;
00094                 }
00095                 if (asprintf(&t, "%s\n%s", message, s) < 0)
00096                 {
00097                         free(s);
00098                         fprintf(stderr, "%s\n", strerror(errno));
00099                         return;
00100                 }
00101                 free(s);
00102                 free(message);
00103                 message = t;
00104         }
00105 }
00106 
00107 void apol_tcl_clear_info_string(void)
00108 {
00109         if (message != NULL)
00110         {
00111                 free(message);
00112                 message = NULL;
00113         }
00114         msg_level = INT_MAX;
00115 }
00116 
00117 void apol_tcl_route_apol_to_string(void *arg, const apol_policy_t * p
00118                                    __attribute__ ((unused)), int level, const char *fmt, va_list ap)
00119 {
00120         apol_tcl_common_route(arg, level, fmt, ap);
00121 }
00122 
00123 void apol_tcl_route_sefs_to_string(void *arg, const sefs_fclist * s
00124                                    __attribute__ ((unused)), int level, const char *fmt, va_list ap)
00125 {
00126         apol_tcl_common_route(arg, level, fmt, ap);
00127 }
00128 
00129 int apol_tcl_get_info_level(void)
00130 {
00131         return msg_level;
00132 }
00133 
00134 char *apol_tcl_get_info_string(void)
00135 {
00136         return message;
00137 }
00138 
00139 void apol_tcl_set_info_string(apol_policy_t * p, const char *s)
00140 {
00141         INFO(p, "%s", s);
00142 }