Logo Search packages:      
Sourcecode: dcgui version File versions  Download package

running_hub_clist.c

/* dc_gui2 - a GTK+2 GUI for DCTC
 * Copyright (C) 2002 Eric Prevoteau
 *
 * running_hub_clist.c: Copyright (C) Eric Prevoteau <www@a2pb.gotdns.org>
 *
 * 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.
 */
/*
$Id: running_hub_clist.c,v 1.5 2003/12/26 14:35:04 uid68112 Exp $
*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <fcntl.h>
#include <signal.h>
#include <dirent.h>
#include <gnome.h>

#include "gtkcellrenderertextx.h"
#include "misc_gtk.h"
#include "running_hub_clist.h"
#include "main.h"
#include "gui_define.h"
#include "macro.h"
#include "status.h"
#include "init_fnc.h"
#include "bookmark.h"

/****************************************************************************************************************************/
/* search inside the "hub_recent_clist", the "hub_puplic_clist" and the "seen_hub_clist" for a hub having the given address */
/****************************************************************************************************************************/
/* the returned string must be freed */
/*************************************/
static char *get_hubname_from_recent(const char *hub_addr)
{
      GtkTreeIter iter;
      GtkWidget *w;

      w=get_widget_by_widget_name(main_window,"hub_recent_clist");
      if(w)
      {
            GtkTreeModel *gtm;

            gtm=gtk_tree_view_get_model(GTK_TREE_VIEW(w));
            if(get_iter_from_string(gtm,REHC_HUB_ADDR_COL,hub_addr,&iter)==TRUE)
            {
                  char *t;

                  gtk_tree_model_get(gtm,&iter,REHC_HUB_NAME,&t,-1);
                  return t;
            }
      }

      w=get_widget_by_widget_name(main_window,"hub_public_clist");
      if(w)
      {
            GtkTreeModel *gtm;

            gtm=gtk_tree_view_get_model(GTK_TREE_VIEW(w));
            if(get_iter_from_string(gtm,PHC_HUB_ADDR_COL,hub_addr,&iter)==TRUE)
            {
                  char *t;

                  gtk_tree_model_get(gtm,&iter,PHC_HUB_NAME,&t,-1);
                  return t;
            }
      }

      w=get_widget_by_widget_name(main_window,"seen_hub_clist");
      if(w)
      {
            GtkTreeModel *gtm;

            gtm=gtk_tree_view_get_model(GTK_TREE_VIEW(w));
            if(get_iter_from_string(gtm,SHC_HUB_ADDR_COL,hub_addr,&iter)==TRUE)
            {
                  char *t;

                  gtk_tree_model_get(gtm,&iter,SHC_HUB_NAME,&t,-1);
                  return t;
            }
      }

      return NULL;
}

/**********************************************************/
/* copie the given file (filename) into another file (fd) */
/* output: 0=ok, 1=error                                  */
/**********************************************************/
static int copy_file(char *filename, int dest_fd)
{
      char buf[512];
      FILE *f;
      int ln;
      int err=0;

      f=fopen(filename,"rb");
      if(f==NULL)
            return 1;

      while( (ln=fread(buf,1,sizeof(buf),f))!=0)
      {
            if(write(dest_fd,buf,ln)!=ln)
            {
                  err=1;
                  break;
            }
      }
      fclose(f);
      return err;
}

/*********************************************************************************************/
/* merge .done files into done+exited if there is no socket linked with them and remove them */
/*********************************************************************************************/
static void clean_directory(char *base_dir)
{
      int fd;
      GString *p;
      GString *q;

      p=g_string_new(base_dir);
      q=g_string_new(NULL);
      g_string_sprintfa(p,"/done+exited");

      fd=open(p->str,O_CREAT|O_RDWR,0666);
      if(fd==-1)
      {
            perror("clean_directory - open fails");
      }
      else
      {
            if(flock(fd,LOCK_EX)!=0)
            {
                  perror("clean_directory - lock fails");
            }
            else
            {
                  DIR *dir;
                  struct stat st;

                  lseek(fd,0,SEEK_END);

                  dir=opendir(base_dir);
                  if(dir!=NULL)
                  {
                        struct dirent *obj;

                        while((obj=readdir(dir))!=NULL)
                        {
                              int a;

                              if(strncmp(obj->d_name,"dctc-",5))
                                    continue;

                              a=strlen(obj->d_name);
                              if(a<4)
                                    continue;

                              if((a>=4)&&(!strcmp(obj->d_name+a-4,".udp")))         /* ignore .udp file */
                                    continue;

                              if((a>=9)&&(!strcmp(obj->d_name+a-9,".userinfo")))          /* ignore .udp file */
                                    continue;

                              if((a>=5)&&(!strcmp(obj->d_name+a-5,".done")))
                              {
                                    g_string_sprintf(q,"%s/%s",base_dir,obj->d_name);
                                    q=g_string_truncate(q,q->len-5);          /* remove the .done */
      
                                    if(stat(q->str,&st))
                                    {
                                          process_no_more_exist:
                                          g_string_sprintf(q,"%s/%s",base_dir,obj->d_name);
                                          /* copy q->str into fd */
                                          if(!copy_file(q->str,fd))
                                                unlink(q->str);
                                    }
                                    else
                                    {
                                          /* unix socket exist but does the process exists ? */
                                          pid_t num;
      
                                          /* extract the number */
                                          if(sscanf(obj->d_name+5,"%08X",&num)==1)
                                          {
                                                if(kill(num,SIGQUIT)!=0)
                                                {
                                                      /* process is dead, remove the socket */
                                                      unlink(q->str);

                                                      /* and the udp socket */
                                                      q=g_string_append(q,".udp");
                                                      unlink(q->str);

                                                      q=g_string_truncate(q,q->len-4);    /* remove the ".udp" */
                                                      q=g_string_append(q,".userinfo");
                                                      unlink(q->str);
                                                
                                                      del_client_status(num);

                                                      goto process_no_more_exist;
                                                }
                                          }
                                    }
                              }
                              else
                              {
                                    /* well, the file start with dctc but has no .done at the end */
                                    /* it is the socket */
                                    pid_t num;
      
                                    /* extract the number */
                                    if(sscanf(obj->d_name+5,"%08X",&num)==1)
                                    {
                                          if(kill(num,SIGQUIT)!=0)
                                          {
                                                g_string_sprintf(q,"%s/%s",base_dir,obj->d_name);
                                                /* process is dead, remove the socket */
                                                unlink(q->str);

                                                /* and the udp socket */
                                                {
                                                      GString *p;

                                                      p=g_string_new(q->str);
                                                      p=g_string_append(p,".udp");
                                                      unlink(p->str);

                                                      /* and the userinfo file */
                                                      p=g_string_assign(p,q->str);
                                                      p=g_string_append(p,".userinfo");
                                                      unlink(p->str);

                                                      g_string_free(p,TRUE);
                                                }


                                                q=g_string_append(q,".done");
                                                /* copy q->str into fd */
                                                if(!copy_file(q->str,fd))
                                                      unlink(q->str);

                                                del_client_status(num);
                                          }
                                    }
                              }
                        }
                        closedir(dir);
                  }
                  flock(fd,LOCK_UN);
            }
            close(fd);
      }

      g_string_free(p,TRUE);
      g_string_free(q,TRUE);
}

/********************************************************************************/
/* fill the clist named "running_hub_clist" with the list of all running client */
/********************************************************************************/
/* NOTE: each clist row data is the pid of the process */
/*******************************************************/
void fill_running_hub_clist(void)
{
      running_client_list_periodic_refresh(NULL);
}

/******************************************************************************************************/
/* search in the tree model to find an iter having the column RHC_PROCESS_PID_COL value == to the_pid */
/******************************************************************************************************/
/* output: TRUE if the iter is valid, else FALSE (not found) */
/*************************************************************/
static int get_iter_from_pid(GtkTreeModel *gtm, pid_t the_pid, GtkTreeIter *iter)
{
      int valid;

      valid=gtk_tree_model_get_iter_first (gtm, iter);
      
      while(valid)
      {
            glong cur_pid;

            gtk_tree_model_get(gtm,iter,RHC_PROCESS_PID_COL,&cur_pid,-1);

            if(cur_pid==the_pid)
                  return TRUE;

            valid = gtk_tree_model_iter_next (gtm, iter);
      }
      return valid;
}

static int compare_pid(const void *a, const void *b)
{
      return *((pid_t*)a) - *((pid_t*)b);
}

/**********************************************************/
/* periodic functions to call to refresh running hub list */
/**********************************************************/
gint running_client_list_periodic_refresh(gpointer data)
{
      GtkWidget *rhcw;

      rhcw=get_widget_by_widget_name(main_window,"running_hub_clist");
      if(rhcw)
      {
            GtkListStore *gls;
            GtkTreeModel *gtm;
            GtkTreeIter iter;
            GArray *pid_array;
            pid_t the_pid;

            gls=GTK_LIST_STORE(gtm=gtk_tree_view_get_model(GTK_TREE_VIEW(rhcw)));

            clean_directory(dctc_dir->str);

            pid_array=g_array_new(FALSE,FALSE,sizeof(pid_t));

            /* we read the directory ~/.dctc/running */
            /* each entry has the format "dctc-xxxxxxxx-aaaaaaaaaaaa" where xxxxxxxx is the dctc pid (8 hexdigits) and aaaaaaaaa is the hubname */
            {
                  DIR *dir;

                  dir=opendir(dctc_dir->str);
                  if(dir!=NULL)
                  {
                        struct dirent *obj;

                        while((obj=readdir(dir))!=NULL)
                        {
                              int a;
                              char *hn;
                              int stt;
                              unsigned long cli_param[NB_LONG_PER_ENTRY];

                              if(strncmp(obj->d_name,"dctc-",5))
                                    continue;

                              a=strlen(obj->d_name);
                              if((a>5)&&(!strcmp(obj->d_name+a-5,".done")))
                                    continue;
                              if((a>4)&&(!strcmp(obj->d_name+a-4,".udp")))
                                    continue;
                              if((a>9)&&(!strcmp(obj->d_name+a-9,".userinfo")))
                                    continue;

                              hn=get_hubname_from_recent(obj->d_name+5+8+1);

                              sscanf(obj->d_name+5,"%08X",&the_pid);

                              if(get_iter_from_pid(gtm,the_pid,&iter)!=TRUE)
                              {
                                    gtk_list_store_append(gls,&iter);
                                    /* only set never changing values */
                                    if(utf8_mode==TRUE)
                                    {
                                          gtk_list_store_set(gls,&iter, RHC_HUB_ADDR_COL,obj->d_name+5+8+1, 
                                                                                                      RHC_HUB_NAME_COL, (hn!=NULL)?hn:"",
                                                                                                      RHC_PROCESS_ID_COL,obj->d_name,
                                                                                                      RHC_PROCESS_PID_COL, the_pid,
                                                                                                      RHC_HUB_NAME, (hn!=NULL)?hn:"",
                                                                                                      -1);
                                    }
                                    else
                                    {
                                          gchar *utf8;

                                          utf8=g_locale_to_utf8((hn!=NULL)?hn:"",-1,NULL,NULL,NULL);
                                          gtk_list_store_set(gls,&iter, RHC_HUB_ADDR_COL,obj->d_name+5+8+1, 
                                                                                                      RHC_HUB_NAME_COL, utf8,
                                                                                                      RHC_PROCESS_ID_COL,obj->d_name,
                                                                                                      RHC_PROCESS_PID_COL, the_pid,
                                                                                                      RHC_HUB_NAME, (hn!=NULL)?hn:"",
                                                                                                      -1);
                                          g_free(utf8);
                                    }
                              }

                              if(hn!=NULL)
                              {
                                    g_free(hn);
                                    hn=NULL;
                              }

                              stt=get_client_status(the_pid,cli_param);
                              switch(stt)
                              {
                                    default:
                                    case NOT_EXIST:
                                                                        gtk_list_store_set(gls,&iter, RHC_NB_USERS_COL, 0, 
                                                                                                                                    RHC_NB_GDL_COL, 0, 
                                                                                                                                    RHC_NB_UL_COL, 0, 
                                                                                                                                    RHC_LINE_BACKGROUND,NULL,
                                                                                                                                    RHC_FLAGS_COL,(gulong)0,
                                                                                                                                    -1);
                                                                        break;

                                    case IS_OFFLINE:
                                                                        gtk_list_store_set(gls,&iter, RHC_NB_USERS_COL, 0, 
                                                                                                                                    RHC_NB_GDL_COL, (unsigned int)cli_param[GSTATUS_NB_GDL], 
                                                                                                                                    RHC_NB_UL_COL, (unsigned int)cli_param[GSTATUS_NB_UL], 
                                                                                                                                    RHC_LINE_BACKGROUND,"LightGoldenrod1",
                                                                                                                                    RHC_FLAGS_COL,(gulong)(((FLAG1_STRUCT)(cli_param[GSTATUS_FLAG1])).full),
                                                                                                                                    -1);
                                                                        break;

                                    case IS_ONLINE:
                                                                        gtk_list_store_set(gls,&iter, RHC_NB_USERS_COL, (unsigned int)cli_param[GSTATUS_NB_USERS], 
                                                                                                                                    RHC_NB_GDL_COL, (unsigned int)cli_param[GSTATUS_NB_GDL], 
                                                                                                                                    RHC_NB_UL_COL, (unsigned int)cli_param[GSTATUS_NB_UL], 
                                                                                                                                    RHC_LINE_BACKGROUND,"green",
                                                                                                                                    RHC_FLAGS_COL,(gulong)(((FLAG1_STRUCT)(cli_param[GSTATUS_FLAG1])).full),
                                                                                                                                    -1);
                                                                        break;

                              }
                              /* add the pid to the list of encountered pid */
                              pid_array=g_array_append_val(pid_array,the_pid);
                        }
                        closedir(dir);
                  }
            }

            /* now, we must remove clist row having a pid not in pid_array */
            {
                  int valid;

                  /* the number of clist rows and pid are different, we must really do some cleaning */
                  qsort(pid_array->data,pid_array->len,sizeof(pid_t),compare_pid);

#if 1
                  restart:
#endif
                  valid=gtk_tree_model_get_iter_first (gtm, &iter);

                  while(valid)
                  {
                        glong the_pid;
                        pid_t cpid;

                        gtk_tree_model_get(gtm,&iter,RHC_PROCESS_PID_COL,&the_pid,-1);
                        cpid=the_pid;

                        if(bsearch(&cpid,pid_array->data,pid_array->len,sizeof(pid_t),compare_pid)==NULL)
                        {
                              /* the value no more exists */
#if 0
                              /* FIXME don't ask me why, according to the manual, the following line is enough */
                              /* but it produce a warning when I compile it (at least with gtk 2.0.6) */
                              valid=gtk_list_store_remove(gls,&iter);
#else
                              gtk_list_store_remove(gls,&iter);
                              goto restart;
#endif
                        }
                        else
                              valid = gtk_tree_model_iter_next (gtm, &iter);
                  }
            }

            g_array_free(pid_array,TRUE);

            colorize_favorite(gtk_tree_view_get_model(GTK_TREE_VIEW(get_widget_by_widget_name(main_window,"hub_favorite_clist"))),
                                                FHC_HUB_ADDR_COL,
                                                gtm,
                                                RHC_HUB_ADDR_COL);
      }
      return TRUE;      /* don't stop periodic calling */
}

/***************************************************/
/* build modele and view for the running hub clist */
/***************************************************/
void bmav4_running_hub_clist(void)
{
      GtkListStore *model;
      GtkWidget *view;
      GtkCellRenderer *rend;
      GtkTreeSelection *slc;

      model=gtk_list_store_new(NB_RHC_COL,G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT,
                                                                              G_TYPE_UINT, G_TYPE_UINT,
                                                                              G_TYPE_STRING, G_TYPE_LONG, G_TYPE_STRING,
                                                                              G_TYPE_STRING,G_TYPE_ULONG, G_TYPE_BOOLEAN);

      view=get_widget_by_widget_name(main_window,"running_hub_clist");

      gtk_tree_view_set_model(GTK_TREE_VIEW(view),GTK_TREE_MODEL(model));
      gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view),TRUE);

      slc=gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
      gtk_tree_selection_set_mode(slc,GTK_SELECTION_MULTIPLE);
      
      rend=gtk_cell_renderer_textx_new();
      g_object_set(rend,"rowspacing",TRUE,NULL);
      MY_RS_gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),RHC_HUB_ADDR_COL,_("Hub address"),rend,"text",RHC_HUB_ADDR_COL,"background",RHC_LINE_BACKGROUND,NULL);

      rend=gtk_cell_renderer_textx_new();
      g_object_set(rend,"rowspacing",TRUE,NULL);
      MY_RS_gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),RHC_HUB_NAME_COL,_("Hubname"),rend,"text",RHC_HUB_NAME_COL,"background",RHC_LINE_BACKGROUND,NULL);

      rend=gtk_cell_renderer_textx_new();
      g_object_set(rend,"xalign",(gfloat)1.0,NULL);
      g_object_set(rend,"rowspacing",TRUE,NULL);
      MY_RS_gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),RHC_NB_USERS_COL,_("#users"),rend,"text",RHC_NB_USERS_COL,"background",RHC_LINE_BACKGROUND,NULL);

      rend=gtk_cell_renderer_textx_new();
      g_object_set(rend,"xalign",(gfloat)1.0,NULL);
      g_object_set(rend,"rowspacing",TRUE,NULL);
      MY_RS_gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),RHC_NB_GDL_COL,_("#GDLs"),rend,"text",RHC_NB_GDL_COL,"background",RHC_LINE_BACKGROUND,NULL);

      rend=gtk_cell_renderer_textx_new();
      g_object_set(rend,"xalign",(gfloat)1.0,NULL);
      g_object_set(rend,"rowspacing",TRUE,NULL);
      MY_RS_gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),RHC_NB_UL_COL,_("#ULs"),rend,"text",RHC_NB_UL_COL,"background",RHC_LINE_BACKGROUND,NULL);

      /* The view now holds a reference.  We can get rid of our own
       * reference */
      g_object_unref (G_OBJECT (model));
}


Generated by  Doxygen 1.6.0   Back to index