/* * SambaSentinel.c * * (C) 2001 Robert Kling * robkli-8@student.luth.se * http://boombox.campus.luth.se * * 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. * * * See INSTALL file for instructions on compiling this program. */ #include #include #include #include #include #include "gtk_common.h" #include "pixmaps/network.xpm" #include "pixmaps/doc.xpm" #include "pixmaps/sound.xpm" #include "pixmaps/search.xpm" #include "pixmaps/exe.xpm" #include "pixmaps/none.xpm" #include "pixmaps/txt.xpm" #include "pixmaps/offline.xpm" #define LIVE_BUILD 1 #define DEBUG_PARSING 0 #define GREP_PROCS "smbstatus -S | grep -E \"\\([[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.\"" #define GREP_FILES "smbstatus -L | grep DENY" #define VERSION "0.1" #define REV_DATE "2001-02-26" #define KILL_SIGNAL 9 #define MAX_PROCS 20 #define MAX_FILES 100 #define NOF_COLUMNS 7 /** GTK callback functions **/ gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data); gint kill_process(GtkMenuItem *item, gpointer *data); gint add_ban_menu_item(GtkMenuItem *item, gpointer *data); gint remove_ban_callback(GtkMenuItem *item, gpointer *data); gint browse_with_jags(GtkMenuItem *item, gpointer *data); gint about_dialog(GtkMenuItem *item, gpointer *data); gint select_row(GtkWidget *widget, gint row, gint column, GdkEventButton *event, gpointer data); gint hs_files(GtkWidget *widget, GdkEvent *event, gpointer data); /** Other functions **/ void print_help_and_exit(); void setup_main_window(); void setup_popup_menu(); void select_row_with_pid(GtkWidget *widget, int pid); int f_skip_forward(FILE *which_file, int nof_tokens); void *status_thread(void *); typedef struct { unsigned pid; char service[64]; char machine_name[128]; char machine_ip[20]; char uid[64]; char gid[64]; int file_cnt; char *files[MAX_FILES]; } samba_proc; char *titles[NOF_COLUMNS] = {"PID", "Computer", "IP", "UID", "GID", "Share", "Files"}; char cwidths[NOF_COLUMNS] = { 40 , 75 , 95 , 65 , 65 , 55 , 35 }; char *rowptr[NOF_COLUMNS]; char *file_title[1] = { "Files" }; pthread_t t_status_thread; pthread_mutex_t mutex; /** ** The following variables MUST ONLY be accessed WITHIN a mutex ** lock or before the status thread is started. **/ samba_proc *proc_list[MAX_PROCS]; char *ban_list[20]; int ban_cnt; int proc_cnt, time_to_die; int selected_pid, update_int = 5; /** ** End of "mutex-variables". **/ int selected_row; GtkWidget *window, *button, *hbox, *vbox, *clist_procs, *clist_files; GtkWidget *statusbar, *scr_win_procs, *scr_win_files, *box; GtkWidget *popup_menu, *ban_popup_menu, *kill_menu_item, *ban_menu_item, *menuitem; GtkWidget *remove_ban_menu_item, *about_menu_item, *jags_menu_item; GdkPixmap *proc_pixmap, *sound_pixmap, *file_pixmap; GdkBitmap *proc_mask, *sound_mask, *file_mask; GtkStyle *style; /*** *** Main ***/ int main(int argc, char **argv) { if (argc > 1) { update_int = atoi(argv[1]); if (update_int < 1) print_help_and_exit(); } pthread_mutex_init(&mutex, NULL); g_thread_init(NULL); gtk_init(&argc, &argv); setup_main_window(); setup_popup_menu(); /** Start t_status_thread that runs smbstatus **/ pthread_create(&t_status_thread, NULL, (void *) status_thread, NULL); /** gtk_main is where the program will be until the user quits **/ gdk_threads_enter(); gtk_main(); gdk_threads_leave(); /** Tell t_status_thread that its time to quit and wait for it to do so **/ pthread_mutex_lock(&mutex); time_to_die = 1; pthread_mutex_unlock(&mutex); printf("\nSAMBA_SENTINEL: Graciously waiting for t_status_thread to exit: "); fflush(stdout); pthread_join(t_status_thread, NULL); printf("done.\n"); return 0; } /*** *** Print help and exit (if faulty commandline parameter(s)) ***/ void print_help_and_exit() { printf("\nSambaSentinel v%s (%s)\n\nUsage: SambaSentinel [seconds between updates]\n\n", VERSION, REV_DATE); exit(0); } /*** *** Setup and draw the main window ***/ void setup_main_window() { GtkWidget *test; int i, j; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(gtk_main_quit), NULL); gtk_widget_set_usize( GTK_WIDGET (window), 500, 150); gtk_window_set_title(GTK_WINDOW (window), "SambaSentinel v0.1"); gtk_container_set_border_width(GTK_CONTAINER (window), 3); /** Vertical Pack Box **/ vbox = gtk_vbox_new(FALSE, 1); gtk_container_add(GTK_CONTAINER (window), vbox); gtk_widget_show(vbox); /** Scrolled Window (for clist_procs) **/ scr_win_procs = gtk_scrolled_window_new(NULL, NULL); gtk_container_set_border_width (GTK_CONTAINER (scr_win_procs), 0); gtk_widget_set_usize(scr_win_procs, 100, 50); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scr_win_procs), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start(GTK_BOX(vbox), scr_win_procs, TRUE, TRUE, 0); gtk_widget_show(scr_win_procs); /** CList (for procs) **/ clist_procs = gtk_clist_new_with_titles(NOF_COLUMNS, titles); gtk_container_set_border_width (GTK_CONTAINER (clist_procs), 0); gtk_clist_set_button_actions(GTK_CLIST(clist_procs), 2, 1); gtk_signal_connect(GTK_OBJECT(clist_procs), "select_row", GTK_SIGNAL_FUNC(select_row), NULL); gtk_signal_connect(GTK_OBJECT(clist_procs), "unselect_row", GTK_SIGNAL_FUNC(select_row), NULL); gtk_clist_column_titles_passive(GTK_CLIST(clist_procs)); gtk_clist_set_row_height(GTK_CLIST(clist_procs), 14); gtk_clist_set_shadow_type(GTK_CLIST(clist_procs), GTK_SHADOW_IN); for (i = 0; i < NOF_COLUMNS; i++) { //gtk_clist_set_column_auto_resize(GTK_CLIST(clist_procs), i, TRUE); gtk_clist_set_column_width(GTK_CLIST(clist_procs), i, cwidths[i]); } gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scr_win_procs), clist_procs); gtk_widget_show(clist_procs); /** Scrolled Window (for clist_files) **/ scr_win_files = gtk_scrolled_window_new(NULL, NULL); gtk_container_set_border_width (GTK_CONTAINER (scr_win_files), 0); gtk_widget_set_usize(scr_win_files, 100, 50); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scr_win_files), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start(GTK_BOX(vbox), scr_win_files, TRUE, TRUE, 0); gtk_widget_show(scr_win_files); /** CList (for files) **/ clist_files = gtk_clist_new_with_titles(1,file_title); gtk_clist_set_button_actions(GTK_CLIST(clist_files), 0, 0); gtk_clist_set_button_actions(GTK_CLIST(clist_files), 1, 0); gtk_clist_set_button_actions(GTK_CLIST(clist_files), 2, 0); gtk_container_set_border_width (GTK_CONTAINER (clist_files), 0); gtk_clist_column_titles_passive(GTK_CLIST(clist_files)); gtk_clist_set_row_height(GTK_CLIST(clist_files), 14); gtk_clist_set_shadow_type(GTK_CLIST(clist_files), GTK_SHADOW_ETCHED_IN); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scr_win_files), clist_files); gtk_widget_show(clist_files); /** Horizontal Pack Box **/ hbox = gtk_hbox_new(TRUE, 1); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); /** Show/Hide files Button **/ //button = gtk_button_new_with_label ("Show/Hide files"); button = gtk_button_new_with_label_with_pixmap("Hide/Show files", doc_xpm); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (hs_files), (gpointer) "Show/Hide files"); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); gtk_widget_set_usize(button, 100, 23); gtk_widget_show(button); /** Kill Button **/ //button = gtk_button_new_with_label ("Kill process"); button = gtk_button_new_with_label_with_pixmap("Kill process", exe_xpm); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (kill_process), NULL); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); gtk_widget_show(button); /** Ban Button **/ //button = gtk_button_new_with_label ("Ban user"); button = gtk_button_new_with_label_with_pixmap("Ban user", exe_xpm); //gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (delete_event), (gpointer) "Quit"); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); gtk_widget_set_sensitive(button, FALSE); gtk_widget_show(button); /** Quit Button **/ //button = gtk_button_new_with_label ("Quit"); button = gtk_button_new_with_label_with_pixmap("Quit", offline_xpm); gtk_signal_connect(GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (delete_event), (gpointer) "Quit"); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0); gtk_widget_show(button); /** Statusbar **/ statusbar = gtk_statusbar_new(); gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0); gtk_widget_set_usize(statusbar, 100, 20); gtk_widget_show(statusbar); /** Pretty much done.. so just show everything. **/ gtk_widget_show(window); /** Create the pixmaps for computer and files **/ style = gtk_widget_get_style( window ); //proc_pixmap = gdk_pixmap_create_from_xpm(window->window, &proc_mask, &proc_style->bg[GTK_STATE_NORMAL], "network.xpm" ); proc_pixmap = gdk_pixmap_create_from_xpm_d(window->window, &proc_mask, &style->bg[GTK_STATE_NORMAL], network_xpm ); //file_style = gtk_widget_get_style( window ); //file_pixmap = gdk_pixmap_create_from_xpm(window->window, &file_mask, &file_style->bg[GTK_STATE_NORMAL], "doc.xpm" ); file_pixmap = gdk_pixmap_create_from_xpm_d(window->window, &file_mask, &style->bg[GTK_STATE_NORMAL], doc_xpm ); //sound_style = gtk_widget_get_style( window ); //sound_pixmap = gdk_pixmap_create_from_xpm(window->window, &sound_mask, &sound_style->bg[GTK_STATE_NORMAL], "sound.xpm" ); sound_pixmap = gdk_pixmap_create_from_xpm_d(window->window, &sound_mask, &style->bg[GTK_STATE_NORMAL], sound_xpm ); } /*** *** Setup the right-mouse-button-clicked-on-process popup-menu ***/ void setup_popup_menu() { popup_menu = gtk_menu_new(); ban_popup_menu = gtk_menu_new(); menuitem = gtk_menu_item_new_with_label_with_pixmap("SambaSentinel", none_xpm); gtk_widget_show (menuitem); gtk_container_add (GTK_CONTAINER (popup_menu), menuitem); gtk_widget_set_sensitive (menuitem, FALSE); menuitem = gtk_menu_item_new(); gtk_widget_show (menuitem); gtk_container_add (GTK_CONTAINER (popup_menu), menuitem); gtk_widget_set_sensitive(menuitem, FALSE); kill_menu_item = gtk_menu_item_new_with_label_with_pixmap("Kill process", exe_xpm); gtk_widget_show (kill_menu_item); gtk_container_add (GTK_CONTAINER(popup_menu), kill_menu_item); gtk_signal_connect (GTK_OBJECT(kill_menu_item), "activate", GTK_SIGNAL_FUNC (kill_process), NULL); ban_menu_item = gtk_menu_item_new_with_label_with_pixmap("Ban computer", none_xpm); gtk_widget_show (ban_menu_item); gtk_container_add (GTK_CONTAINER (popup_menu), ban_menu_item); gtk_signal_connect(GTK_OBJECT(ban_menu_item), "activate", GTK_SIGNAL_FUNC (add_ban_menu_item), NULL); gtk_widget_set_sensitive(ban_menu_item, FALSE); //remove_ban_menu_item = gtk_menu_item_new_with_label("Un-ban computer"); remove_ban_menu_item = gtk_menu_item_new_with_label_with_pixmap("Un-ban computer", none_xpm); gtk_widget_show (remove_ban_menu_item); gtk_container_add (GTK_CONTAINER (popup_menu), remove_ban_menu_item); gtk_menu_item_set_submenu(GTK_MENU_ITEM(remove_ban_menu_item), ban_popup_menu); gtk_widget_set_sensitive(remove_ban_menu_item, FALSE); jags_menu_item = gtk_menu_item_new_with_label_with_pixmap("Browse with Jags", search_xpm); gtk_widget_show (jags_menu_item); gtk_container_add (GTK_CONTAINER (popup_menu), jags_menu_item); gtk_signal_connect (GTK_OBJECT(jags_menu_item), "activate", GTK_SIGNAL_FUNC (browse_with_jags), NULL); about_menu_item = gtk_menu_item_new_with_label_with_pixmap("About", txt_xpm); gtk_widget_show(about_menu_item); gtk_container_add(GTK_CONTAINER (popup_menu), about_menu_item); gtk_signal_connect(GTK_OBJECT(about_menu_item), "activate", GTK_SIGNAL_FUNC (about_dialog), NULL); } /*** *** Main program quit callback ***/ gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) { gtk_main_quit(); return FALSE; } /*** *** Add a computer to the ban-list and sub-popup-menu (not active yet) ***/ gint add_ban_menu_item(GtkMenuItem *item, gpointer *data) { GtkWidget *new_menu_item; char str[64]; gtk_clist_remove(GTK_CLIST(clist_procs), selected_row); gtk_clist_clear(GTK_CLIST(clist_files)); pthread_mutex_lock(&mutex); strncpy(str, proc_list[selected_row]->machine_name, 63); pthread_mutex_unlock(&mutex); ban_list[ban_cnt] = malloc(strlen(str)+1); strcpy(ban_list[ban_cnt], str); new_menu_item = gtk_menu_item_new_with_label(str); gtk_widget_show(new_menu_item); gtk_container_add(GTK_CONTAINER (ban_popup_menu), GTK_WIDGET(new_menu_item)); gtk_signal_connect (GTK_OBJECT(new_menu_item), "activate", GTK_SIGNAL_FUNC(remove_ban_callback), ban_list[ban_cnt++]); return TRUE; } /*** *** Remove a computer from the ban-list and sub-popup-menu (not active yet) ***/ gint remove_ban_callback(GtkMenuItem *item, gpointer *data) { int i; pthread_mutex_lock(&mutex); for (i = 0; i < ban_cnt; i++) if (strcmp(ban_list[i], (char *)data) == 0) { free(ban_list[i]); for (i; i < ban_cnt; i++) ban_list[i] = ban_list[i+1]; ban_cnt--; break; } pthread_mutex_unlock(&mutex); gtk_widget_destroy(GTK_WIDGET(item)); return TRUE; } /*** *** Popup the about dialog-window ***/ gint about_dialog(GtkMenuItem *item, gpointer *data) { char str[356]; sprintf(str,"SambaSentinel v%s\n\n" "Copyright (C) 2001 Robert Kling\n" "http://boombox.campus.luth.se", VERSION, REV_DATE); popup_dialog(130, FALSE, "About", str, "Close"); return TRUE; } /*** *** Browse with Jags callback, check for availibilty etc. ***/ gint browse_with_jags(GtkMenuItem *item, gpointer *data) { char str[128] = { "jags --help 1> /dev/null" }; int sysret; sysret = system(str); switch (sysret) { case 0: pthread_mutex_unlock(&mutex); sprintf(str,"jags -c %s 1> /dev/null &", proc_list[selected_row]->machine_name); pthread_mutex_unlock(&mutex); system(str); break; case -1: popup_dialog(100, TRUE, "(SambaSentinel) Browse with Jags", "An unknown error occured when trying to start Jags.", "Close"); break; default: popup_dialog(100, TRUE, "(SambaSentinel) Browse with Jags", "There appear to be a problem starting Jags. Are you sure you have it installed?", "Close"); break; } return TRUE; } /*** *** Kill process callback ***/ gint kill_process(GtkMenuItem *item, gpointer *data) { char str[128]; int sysret; if (selected_pid != 0) { sysret = kill(selected_pid, KILL_SIGNAL); if (sysret) { switch (errno) { case EINVAL: sprintf(str,"ERROR: kill signal %d is not allowed on your system..",KILL_SIGNAL); popup_dialog(100, TRUE, "(SambaSentinel) Kill process", str, "Close"); break; case ESRCH: sprintf(str,"ERROR: process %d does not exist.",selected_pid); popup_dialog(100, TRUE, "(SambaSentinel) Kill process", str, "Close"); break; case EPERM: sprintf(str,"ERROR: You dont have permission to kill the selected process."); popup_dialog(100, TRUE, "(SambaSentinel) Kill process", str, "Close"); break; } } else { gtk_clist_remove(GTK_CLIST(clist_procs), selected_row); gtk_clist_clear(GTK_CLIST(clist_files)); } } return TRUE; } /*** *** Select row callback (for processes) ***/ gint select_row(GtkWidget *widget, gint row, gint column, GdkEventButton *event, gpointer data) { char newtitle[64] = "File accesses by "; char *ptr[1]; int j; pthread_mutex_lock(&mutex); gtk_clist_freeze(GTK_CLIST(clist_files)); gtk_clist_clear(GTK_CLIST(clist_files)); strncat(newtitle, proc_list[row]->machine_name, 42); gtk_clist_set_column_title( GTK_CLIST(clist_files), 0, newtitle); selected_pid = proc_list[row]->pid; selected_row = row; for (j = 0; j < proc_list[row]->file_cnt; j++) { ptr[0] = proc_list[row]->files[j]; gtk_clist_append(GTK_CLIST(clist_files), ptr); if ((char *)strstr(ptr[0], ".mp3") != NULL) gtk_clist_set_pixtext(GTK_CLIST(clist_files), j, 0, ptr[0], 5, sound_pixmap, sound_mask ); else gtk_clist_set_pixtext(GTK_CLIST(clist_files), j, 0, ptr[0], 5, file_pixmap, file_mask ); } gtk_clist_thaw(GTK_CLIST(clist_files)); pthread_mutex_unlock(&mutex); if ((event != NULL) && (event->button == 3)) { gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL, NULL, NULL, 0, event->time); // Does anybody know how to give the popup focus so that menuitems 'react' when the mouse is over them? //gtk_widget_grab_focus(GTK_WIDGET(popup_menu)); } return TRUE; } /*** *** Hide and show files callback ***/ gint hs_files(GtkWidget *widget, GdkEvent *event, gpointer data) { static int files_visible = 1; if (files_visible) { gtk_widget_hide(scr_win_files); files_visible = 0; } else { gtk_widget_show(scr_win_files); files_visible = 1; } return TRUE; } /*** *** The status thread that continously runs smbstatus and updates the lists ***/ void *status_thread(void *arg) { int i, j, id; char slask[256], slask2[256], name[256]; FILE *fp; while (1) { #if LIVE_BUILD strcpy(slask2, GREP_PROCS); strcat(slask2, " >"); strcpy(slask, getenv("HOME")); strcat(slask, "/.smbprocs.tmp"); strcat(slask2, slask); system(slask2); if ((fp = fopen(slask,"r")) == NULL) exit(0); #else if ((fp = fopen("procs.txt","r")) == NULL) exit(0); #endif proc_cnt = 0; pthread_mutex_lock(&mutex); while (!feof(fp) && (proc_cnt < MAX_PROCS)) { if (proc_list[proc_cnt] != NULL) { for (i = 0; i < proc_list[proc_cnt]->file_cnt; i++) free(proc_list[proc_cnt]->files[i]); free(proc_list[proc_cnt]); } proc_list[proc_cnt] = (samba_proc *)calloc(1,sizeof(samba_proc)); proc_list[proc_cnt]->file_cnt = 0; fscanf(fp,"%s",slask); if (feof(fp)) break; strncpy(proc_list[proc_cnt]->service, slask, 64); //printf("\n%s",slask); fscanf(fp,"%s",slask); strncpy(proc_list[proc_cnt]->uid, slask, 64); //printf("\n%s",slask); fscanf(fp,"%s",slask); strncpy(proc_list[proc_cnt]->gid, slask, 64); //printf("\n%s",slask); fscanf(fp,"%s",slask); proc_list[proc_cnt]->pid = atoi(slask); //printf("\n%s",slask); fscanf(fp,"%s",slask); strncpy(proc_list[proc_cnt]->machine_name, slask, 128); //printf("\n%s",slask); fscanf(fp,"%s",slask); strncpy(proc_list[proc_cnt]->machine_ip, slask+1, 20); proc_list[proc_cnt]->machine_ip[strlen(proc_list[proc_cnt]->machine_ip)-1] = 0; //printf("\n%s",slask); f_skip_forward(fp,5); proc_cnt++; } fclose(fp); #if LIVE_BUILD strcpy(slask2, GREP_FILES); strcat(slask2, " >"); //strcpy(slask2, "smbstatus -L | grep DENY > "); strcpy(slask, getenv("HOME")); strcat(slask, "/.smbfiles.tmp"); strcat(slask2, slask); system(slask2); if ((fp = fopen(slask,"r")) == NULL) exit(0); #else if ((fp = fopen("files.txt","r")) == NULL) exit(0); #endif while (!feof(fp)) { fscanf(fp,"%s",slask); //printf("\n%s",slask); for (i = 0; i < proc_cnt; i++) if (atoi(slask) == proc_list[i]->pid) break; for (j = 1; j < 4; j++) { fscanf(fp,"%s",slask); //printf("\nj = %d %s",j,slask); } fscanf(fp,"%s",name); fgets(slask, 255, fp); strcat(name,slask); name[strlen(name)-1] = 0; //printf("\n%s",name); if ((i < proc_cnt) && (proc_list[i]->file_cnt < MAX_FILES)) { proc_list[i]->files[proc_list[i]->file_cnt] = (char *)malloc(strlen(name)+1); strcpy(proc_list[i]->files[proc_list[i]->file_cnt], name); proc_list[i]->file_cnt++; } } fclose(fp); gdk_threads_enter(); id = gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar), ""); gtk_statusbar_push(GTK_STATUSBAR(statusbar), id, "Updating list.." ); gtk_clist_freeze(GTK_CLIST(clist_procs)); gtk_clist_clear(GTK_CLIST(clist_procs)); for (i = 0; i < proc_cnt; i++) { #if DEBUG_PARSING printf("\n\nService: %s",proc_list[i]->service); printf("\nPID : %d",proc_list[i]->pid); printf("\nMachine: %s",proc_list[i]->machine_name); printf("\nIP : %s",proc_list[i]->machine_ip); printf("\nFiles :\n"); for (j = 0; j < proc_list[i]->file_cnt; j++) printf("%s\n",proc_list[i]->files[j]); #endif sprintf(slask,"%d",proc_list[i]->pid); rowptr[0] = slask; rowptr[1] = proc_list[i]->machine_name; rowptr[2] = proc_list[i]->machine_ip; rowptr[3] = proc_list[i]->uid; rowptr[4] = proc_list[i]->gid; rowptr[5] = proc_list[i]->service; sprintf(slask2,"%d",proc_list[i]->file_cnt); rowptr[6] = slask2; gtk_clist_append(GTK_CLIST(clist_procs), rowptr); gtk_clist_set_pixtext(GTK_CLIST(clist_procs), i, 1, rowptr[1], 5, proc_pixmap, proc_mask ); } gtk_clist_thaw(GTK_CLIST(clist_procs)); for (i = 0; i < proc_cnt; i++) if (proc_list[i]->pid == selected_pid) { pthread_mutex_unlock(&mutex); select_row_with_pid(clist_procs, selected_pid); break; } else if (i == proc_cnt-1) selected_pid = 0; gdk_threads_leave(); pthread_mutex_unlock(&mutex); for (i = 0; i < update_int; i++) { usleep(1000000); if (i == 0) gtk_statusbar_pop(GTK_STATUSBAR(statusbar), id); pthread_mutex_lock(&mutex); if (time_to_die) { pthread_mutex_unlock(&mutex); pthread_exit(NULL); } else pthread_mutex_unlock(&mutex); } } // end of while } /*** *** A function to select the process with a given pid (called after update) ***/ void select_row_with_pid(GtkWidget *widget, int pid) { char *test; int i = 0, j; for (i = 0; i < proc_cnt; i++) { gtk_clist_get_text( GTK_CLIST(widget), i, 0, &test); sscanf(test, "%d", &j); if (j == pid) { gtk_clist_select_row(GTK_CLIST(clist_procs), i, 0); break; } } } /*** *** Skip nof_tokes in a file ***/ int f_skip_forward(FILE *which_file, int nof_tokens) { int i = 0; char slask[128]; while (!feof(which_file) && (i++ < nof_tokens)) fscanf(which_file,"%s",slask); if (i == nof_tokens) return 1; else return 0; }