/* PureAdmin * Copyright (C) 2003 Isak Savo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * Logfile-functions incl. callbacks to manage the logfile-viewer * * Copyright (C) 2003 Isak Savo */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include "globals.h" #include "cfg.h" #include "helper.h" #include "gui_helper.h" #include "logfile.h" #include "famwrap.h" FILE *logfile = NULL; GtkWidget *logview = NULL; GtkTextBuffer *viewbuffer = NULL; GtkTextTag *logview_tags[NUM_LOGTAGS]; static gchar cur_logfile[FILEPATH_MAX]; #define LOG_BUF_LEN 1024 /* Appends a line to the logview. 'buf' must be valid UTF-8 */ static void logview_append_line (const gchar *buf, log_textview_mode mode) { GtkTextIter iter; static GtkTextMark *mark = NULL; gtk_text_buffer_get_end_iter (viewbuffer, &iter); gtk_text_buffer_insert_with_tags (viewbuffer, &iter, buf, -1, logview_tags[mode], NULL); if (!mark) mark = gtk_text_buffer_create_mark (viewbuffer, "last_line", &iter, FALSE); else gtk_text_buffer_move_mark (viewbuffer, mark, &iter); gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (logview), mark, 0, TRUE, 0, 1); } static log_textview_mode get_logline_mode (const gchar *line) { log_textview_mode mode = LOG_INFO; if (strstr (line, "[NOTICE]")) mode = LOG_NOTICE; else if (strstr (line, "[WARNING]")) mode = LOG_WARNING; else if (strstr (line, "[ERROR]")) mode = LOG_ERROR; else if (strstr (line, "[DEBUG]")) mode = LOG_DEBUG; return mode; } /** GLOBAL FUNCTIONS **/ /* init_logfile: Initializes the logwindow * * Returns: TRUE if everything is setup correctly * FALSE if something went wrong (or if FAM is disabled) */ gboolean init_logfile (void) { static GtkWidget *lbl = NULL; PangoFontDescription *font_desc; if (!logview) { logview = MW("logview"); if (!logview) return FALSE; font_desc = pango_font_description_new (); pango_font_description_set_family_static (font_desc, "monospace"); gtk_widget_modify_font (logview, font_desc); pango_font_description_free (font_desc); viewbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview)); } /* This shouldn't even be called when not defined, but let's check it anyway... */ #ifndef HAVE_LIBFAM return FALSE; #endif if (!lbl) lbl = MW("lbl_logfilename"); if (!logfile) { if (!(logfile = fopen (cfg.logfile, "r"))) { pur_log_wrn ("Unable to open logfile %s: %s", cfg.logfile, strerror (errno)); log_display_error_text (2); return FALSE; } /* We use a local copy of the filename, in case someone changes cfg.logfile, and we want to modify the FAM-watch */ strncpy (cur_logfile, cfg.logfile, FILEPATH_MAX); } if (!fam_set_watch (cfg.logfile, read_logfile)) { close_logfile (); log_display_error_text (3); return FALSE; } gtk_label_set_text (GTK_LABEL (lbl), cur_logfile); return TRUE; } /* close_logfile: Closes the logfile and removes any FAM watches * that are open. Also frees all resources allocated. */ void close_logfile (void) { #ifndef HAVE_LIBFAM return; #endif if (cur_logfile && *cur_logfile) fam_delete_watch (); if (logfile) fclose (logfile); logfile = NULL; log_clear_logview (); } /* log_clear_logview: Removes all text in the logview * */ void log_clear_logview (void) { if (viewbuffer) gtk_text_buffer_set_text (viewbuffer, "", -1); } /* log_display_error_text: Display an errormessage explaining why * logfile viewer has been disabled. * * Argument: reason: * 0 ==> FAM isn't installed, * 1 ==> FAM isn't running. * 2 ==> Couldn't open the specified logfile */ void log_display_error_text (gint reason) { GtkWidget *btn, *lbl; GtkTextIter iter; gchar *err_msg = NULL; if (!logview) { logview = MW("logview"); if (!logview) return; viewbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (logview)); } pur_log_dbg ("Displaying logfile errortext, reason: %d", reason); lbl = MW("lbl_logfilename"); gtk_label_set_text (GTK_LABEL (lbl), _("[Logfile viewer Disabled]")); gtk_text_buffer_get_end_iter (viewbuffer, &iter); switch (reason) { case 0: err_msg = g_strdup (_("Logfile viewer has been disabled because FAM isn't installed on this computer. " "If you want to use the logfile viewer you need to install FAM and then recompile PureAdmin\n\n" "Check your distribution for appropriate packages or visit " "http://oss.sgi.com/projects/fam/ for more info about FAM.")); break; case 1: err_msg = g_strdup (_("Logfile viewer has been disabled because PureAdmin couldn't connect to local FAM-service.\n" "FAM is installed so it should be sufficient to either start FAM as a separate server or run it\n" "from inetd (Internet Super Server) by adding an entry to /etc/inetd.conf.\n\n" "Check your configuration for FAM if you want to use the logfile viewer.")); break; case 2: err_msg = g_strdup (_("Logfile viewer has been disable because PureAdmin could not open the specified logfile.\n" "Make sure that you are running as a user that has permission to open the logfile.")); break; case 3: default: err_msg = g_strdup (_("Logfile viewer has been disable because PureAdmin could not watch for changes to the logfile.\n" "Make sure that you are running as a user that has permission to access the logfile.")); break; } gtk_text_buffer_insert_with_tags (viewbuffer, &iter, err_msg, -1, logview_tags[LOG_ERROR], NULL); g_free (err_msg); btn = MW("btn_logview_clear"); gtk_widget_set_sensitive (btn, FALSE); btn = MW("btn_logview_reread"); gtk_widget_set_sensitive (btn, FALSE); } /* read_logfile: Reads the newly added contents of the logfile */ void read_logfile (void) { gchar buf[LOG_BUF_LEN]; gint mode = 0; gchar *utf8_str; if (!logfile) init_logfile (); pur_log_dbg ("Reading logfile"); if (fseek (logfile, 0, SEEK_CUR) != 0) /* To clear an invalid EOF indicator for the stream, and to verify that there is new data to be read...*/ return; while (!feof (logfile)) { memset (buf, '\0', LOG_BUF_LEN); fgets (buf, LOG_BUF_LEN, logfile); if (misc_str_is_only_whitespace (buf)) continue; utf8_str = NULL; if (cfg.logmethod == LOG_SYSLOG && strstr (buf, "pure-ftpd:")) { utf8_str = string_to_utf8 (buf); mode = get_logline_mode (buf); /* Eventually filter old log-messages */ logview_append_line (utf8_str, mode); } else if (cfg.logmethod == LOG_CUSTOM) { utf8_str = string_to_utf8 (buf); logview_append_line (utf8_str, LOG_INFO); } g_free (utf8_str); } }