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

main.c

/*
 *  Xarchive - a gtk2.0 front-end for various command like archive tools 
 *  Copyright (C) 2005 Lee Bigelow <ligelowbee@yahoo.com> 
 *
 *  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
 */

#include"main.h"

#ifndef HAVE_CANONICALIZE_FILE_NAME
char *
canonicalize_file_name(char *path)
{
  char *name, rzpath[256];
  name = realpath(path, rzpath);
  return name;
}
#endif

#ifndef HAVE_GETLINE
ssize_t
getline(char **lineptr, size_t *n, FILE *stream)
{
  char *line;
  size_t len;

  line = fgetln(stream, &len);
  if (!line) return -1;
  if (len >= *n) 
  {
    char *tmp;
    tmp = realloc(*lineptr, len+1);
    if (!tmp) return -1;
    *lineptr = tmp;
    *n = len + 1;
  }
  memcpy(*lineptr, line, len);
  (*lineptr)[len] = 0;
  return len;
}
#endif

void 
setup_exts(WrapperEntry *wrapent)
{
  int maxline=MAXLINE;
  gchar *dataline = (gchar *) g_malloc (MAXLINE + 1);
  gchar *cmd, *extname;
  FILE *fdata;
  gchar delimit[]=";\n";
  GPtrArray *ext_array = NULL;

  /* read extentions into dataline from wrapper */
  cmd = g_strdup_printf("%s -i", wrapent->path);
  fdata = popen(cmd, "r");
  if (getline(&dataline, &maxline, fdata) > 0) 
  {
    /*get first ext token and add it to array */
    if ((extname = strtok(dataline, delimit)) != NULL)
    {
      ext_array = g_ptr_array_new();
      g_ptr_array_add(ext_array, g_strdup_printf("*.%s",extname));
    } 
    while ((extname = strtok(NULL,delimit)) != NULL)
    {
      g_ptr_array_add(ext_array, g_strdup_printf("*.%s",extname));
    }
    wrapent->ext_array = ext_array;
    pclose(fdata);
  }
  g_free(cmd);
}

WrapperEntry *
make_wrapper(gchar *dir,gchar *fname)
{
  WrapperEntry *wrapent;

  wrapent = (WrapperEntry *) g_malloc (sizeof(WrapperEntry));
  wrapent->path = g_strdup_printf("%s/%s", dir, fname);
  wrapent->ext_array = NULL;
  
  return wrapent;
}

gint 
is_wrapper(const struct dirent *dirent)
{
  /* used as a filter for scandir */
  /* check if name contains "wrap" */
  if (fnmatch("*wrap*",dirent->d_name,FNM_PERIOD|FNM_CASEFOLD) == 0) 
    return 1;
    
  return 0;
}

void 
setup_wrappers(void)
{
  gchar *home;
  gint nwraps, i, cnt;
  struct dirent **dirents;
  WrapperEntry *wrapent = NULL;

  home = g_strdup_printf("%s/.xarchive/wrappers", getenv("HOME"));
  char *dir[] = 
    { 
      home, 
      WRAPPER_DIR, 
      canonicalize_file_name("../wrappers"), 
      NULL 
    };
  WRAPPER_ARRAY = g_ptr_array_sized_new(10);
  for ( i=0; dir[i] != NULL; i++) 
  {
    g_print("dir: %s\n",dir[i]);
    nwraps = scandir(dir[i], &dirents, is_wrapper, alphasort);
    if (nwraps > 0) 
    {
      g_print("Found %d wrappers\n", nwraps);
      /* fill wrapper list*/
      for (cnt=0; cnt < nwraps; cnt++) 
      {
        wrapent = make_wrapper(dir[i],dirents[cnt]->d_name);
        setup_exts(wrapent);
        g_ptr_array_add(WRAPPER_ARRAY, wrapent);
      }
      free(dirents);
    } 
    else g_print("no wrappers in %s\n", dir[i]);
  }
  g_free(home);
  if (WRAPPER_ARRAY->len == 0) 
  {
    g_print("No wrappers found\n");
  }
} 

extern gchar * 
wrapper_info(void)
{
  GString *info_text;
  WrapperEntry *wrapent;
  gchar *ext;
  gint w,e;

  info_text = g_string_new("Wrappers found and their supported file extensions:\n");
  if (WRAPPER_ARRAY == NULL)
    return g_strdup_printf("No wrappers found..\n"
                           "Please check your wrapper dirs:\n\n"
                           "%s\n"
                           "%s/.xarchive/wrappers",
                           WRAPPER_DIR, getenv("HOME"));
  for (w = 0; w < WRAPPER_ARRAY->len; w++)
  {
    wrapent = (WrapperEntry *) g_ptr_array_index(WRAPPER_ARRAY, w);
    g_string_append_printf(info_text,"\n%s\n     Extentions: ",
                         wrapent->path);
    if (wrapent->ext_array == NULL)
    {
      g_string_append_printf(info_text, 
                             "** Needed program not found, ignored **\n");
      continue;
    }
    for (e = 0; e < wrapent->ext_array->len; e++)
    {
      ext = (gchar *) g_ptr_array_index(wrapent->ext_array, e);
      g_string_append_printf(info_text,"%s ", ext);
    }
    g_string_append_c(info_text, '\n');
  }
  return g_string_free(info_text, FALSE);
}

gchar *
get_wrapper(gchar *archive)
{
  /* returns path string of appropriate wrapper for archive, or NULL */
  WrapperEntry *wrapent;
  gchar *ext;
  gint w, e;
  
  if (WRAPPER_ARRAY == NULL) 
    return NULL;
  for (w=0; w < WRAPPER_ARRAY->len; w++)
  {
    wrapent = (WrapperEntry *) g_ptr_array_index(WRAPPER_ARRAY, w);
    if (wrapent->ext_array == NULL) 
      continue;
    for(e = 0; e < wrapent->ext_array->len; e++)
    { 
      ext = (gchar *) g_ptr_array_index(wrapent->ext_array, e);
      if (fnmatch(ext, archive, FNM_CASEFOLD) == 0)
        return wrapent->path;
    }
  }
  return NULL;
}

int 
get_archive_data(gchar **argv)
{
  /* read in archive contents from wrapper line by line
   * sending each line to the widgets add_row function */
  enum {name=0,size,attr,user,group,date,time,link,num_ent};
  FILE *fdata;
  gint cnt, maxline=MAXLINE, i = 20, error = 0;
  gchar *ent[num_ent], *esc_archive;
  gchar *dataline = (gchar *) g_malloc (MAXLINE + 1);
  gchar delimit[]=";\n";
  gchar *cmd = NULL;
  gboolean stopit = FALSE;
  GtkWidget *pbwin, *pbar;
  GtkListStore *liststore;
  GtkTreeView *treeview;
  
  treeview = get_current_tree();
  liststore = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
  g_object_ref(G_OBJECT(liststore));
  gtk_tree_view_set_model(treeview, NULL);

  pbar = gtk_progress_bar_new();
  pbwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  setup_opening_progress_bar(pbwin, pbar, &stopit);

  esc_archive = my_strescape(argv[2]);
  cmd = g_strdup_printf("%s %s %s", argv[0], argv[1], esc_archive);
  g_free(esc_archive);
  fdata = popen(cmd, "r"); 
  while ( (error == 0) && (getline(&dataline, &maxline, fdata) > 0))
  {
    if (i == 20)
    {
      gtk_progress_bar_pulse(GTK_PROGRESS_BAR(pbar));
      while (gtk_events_pending())
        gtk_main_iteration();
      i = 0;
    }
    i++;
    
    if (stopit == TRUE)
    {
      error = -1;
      break;
    }
    ent[name] = strtok(dataline,delimit);
    for (cnt = size; cnt < num_ent; cnt++) 
    { 
      ent[cnt] = strtok(NULL,delimit);
      if ( (ent[cnt] == NULL) && (cnt < link) ) 
      {
        g_print("Error running cmd: %s\n", cmd);
        message(MAIN_WINDOW,
            GTK_MESSAGE_ERROR, "Error reading file");
        error = -1;
        break;
      }
    }
    if (error == 0) add_row(liststore, ent);
  }
  pclose(fdata);
  free(dataline);

  gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(liststore));
  g_object_unref(G_OBJECT(liststore));

  gtk_widget_destroy(pbwin);
  while(gtk_events_pending())
    gtk_main_iteration();

  return error;
}

gint 
wrapper_cmd(gint ar_func, gchar *argv[], gchar *dir)
{
  /* order: AR_OPEN, AR_NEW, AR_EXTRACT, AR_ADD, AR_REMOVE, AR_VIEW */
  gchar *wrap_opt[]= { "-o", "-n", "-e", "-a", "-r", "-v" }; 
  gint wrapper_status = 0, i;
  GPid pid;
  GError *error;
    
  if ((argv[WRAPPER_INDEX] = g_strdup(get_wrapper(argv[ARCHIVE_INDEX]))) 
      == NULL )
  {
    g_print("from main.c: No wrapper found for archive %s\n", 
            argv[ARCHIVE_INDEX]);
    return -1;
  } 

  argv[OPTION_INDEX] = g_strdup(wrap_opt[ar_func]);
  
  g_print("from wrapper_cmd: ");
  for (i=0; argv[i] != NULL; i++)
    g_print("%s ", argv[i]);
  g_print("\n");

  switch ( ar_func ) 
  {
    case AR_OPEN:       
      if (get_archive_data(argv) < 0) return -1;
      break;
    case AR_ADD:
    case AR_NEW:        
    case AR_REMOVE:     
    case AR_VIEW:
    case AR_EXTRACT:
      g_spawn_async(dir, /* working dir */
                    argv, /* argument vector */
                    NULL, /* env vector */
                    G_SPAWN_DO_NOT_REAP_CHILD, /* GSpawnFlags */
                    NULL, /* child setup function */
                    NULL, /* child setup data */
                    &pid, /* GPid process pid */
                    &error); /* GError error */
      /* wait for the command and run the progress bar */
      wait_with_progress_bar(pid, &wrapper_status, ar_func); 
      break;
    default:    
      break;
  }

  g_print("wrapper exited with: %i\n", WEXITSTATUS(wrapper_status));
  switch (WEXITSTATUS(wrapper_status)) 
  {
    case 0:
      return 0;
    case E_UNSUPPORTED:
      message(MAIN_WINDOW,
            GTK_MESSAGE_ERROR, 
              "Action not supported by wrapper for this archive type.");
      return -1;
    default:
      message(MAIN_WINDOW,
            GTK_MESSAGE_ERROR, 
              "Wrapper exited with a error.");
      return -1;
  }
}

void
setup_home_directory(void)
{
  gchar *dir;

  dir = g_strdup_printf("%s/.xarchive", getenv("HOME"));
  if (g_file_test(dir, G_FILE_TEST_IS_DIR) == FALSE)  
    g_mkdir(dir, S_IRWXU|S_IRWXG);
  g_free(dir);

  dir = g_strdup_printf("%s/.xarchive/wrappers", getenv("HOME"));
  if (g_file_test(dir, G_FILE_TEST_IS_DIR) == FALSE)  
    g_mkdir(dir, S_IRWXU|S_IRWXG);
  g_free(dir);
}

ParsedArgs *
parse_options(gint argc, gchar *argv[])
{
  
  ParsedArgs *pargs = (ParsedArgs *) g_malloc (sizeof(ParsedArgs));
  GError *error = NULL;
  GOptionContext *context;
  gchar *cfname = NULL;
  gchar *afname = NULL;
  GOptionEntry entries[] = 
    {
      { "geometry", 'g', 0, G_OPTION_ARG_STRING, &pargs->geom, 
        "Change intial widget geometry to GEOM.\n"
        "\t\t\t   Format: WxH+Xpos+Ypos, eg 500x300+10+10\n", 
        "GEOM" },
      { "create", 'c', 0, G_OPTION_ARG_FILENAME, &cfname, 
        "Create an archive named ARCHIVE containing FILES.\n"
        "\t\t\t   ARCHIVE should be the full path to the archive.\n"
        "\t\t\t   FILES will be shown in a file chooser.\n"
        "\t\t\t   If the name 'ask' is passed as the ARCHIVE name\n"
        "\t\t\t   XArchive will give you a file creation dialog.\n"
        "\t\t\t   May not be used with -a option.\n",
        "ARCHIVE" },
      { "add", 'a', 0, G_OPTION_ARG_FILENAME, &afname,
        "Add FILES to ARCHIVE.\n"
        "\t\t\t   ARCHIVE should be the full path to the archive.\n"
        "\t\t\t   FILES will be shown in a file chooser.\n"
        "\t\t\t   If the name 'ask' is passed as the ARCHIVE name\n"
        "\t\t\t   XArchive will give you a file selector dialog.\n"
        "\t\t\t   May not be used with -c option.\n",
        "ARCHIVE" },
      { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &pargs->files, 
        NULL, NULL },
      { NULL }
    };
  
  pargs->action = AR_OPEN;
  pargs->archive = NULL;
  pargs->files = NULL;
  pargs->geom = NULL;

  context=g_option_context_new("[FILES...]\n\n"
                               "\tWithout an option each file in the list\n"
                               "\tof passed FILES is treated as an archive\n"
                               "\tand an attempt is made to open them.\n"
                               "\tWith no FILES passed an info page is shown."
                               );
  g_option_context_add_main_entries (context, entries, NULL);
  g_option_context_add_group (context, gtk_get_option_group (TRUE));
  g_option_context_parse (context, &argc, &argv, &error);
  g_option_context_free(context);

  if (error != NULL || (cfname != NULL && afname != NULL))
  {
    g_printerr("Error parsing options\n"
               "Note: you can use -c ** OR ** -a, not both.\n"
               "Please see:  xarchive --help\n"
               "or:          man xarchive\n");
    exit(EXIT_FAILURE);
  }
  if (cfname != NULL)
  {
    pargs->archive = cfname;
    pargs->action = AR_NEW;
  }
  else if (afname != NULL)
  {
    pargs->archive = afname;
    pargs->action = AR_ADD;
  }
  
  return pargs;
}     

int 
main( gint argc, gchar *argv[] )
{
  gchar *wrapinf;
  ParsedArgs *pargs;

  pargs = parse_options(argc, argv);
  setup_home_directory();
  setup_wrappers();

  wrapinf = wrapper_info();
  g_print("%s\n%s\n\n", PACKAGE_STRING, PACKAGE_BUGREPORT);
  puts(wrapinf);
  g_free(wrapinf);

  make_widgets(pargs);

  return 0;
}

Generated by  Doxygen 1.6.0   Back to index