xarchive  0.2.8-6
About: XArchive is a GTK+ front-end for command line archiving tools.
  Fossies Dox: xarchive-0.2.8-6.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

main.c
Go to the documentation of this file.
1 /*
2  * Xarchive - a gtk2.0 front-end for various command like archive tools
3  * Copyright (C) 2005 Lee Bigelow <ligelowbee@yahoo.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */
19 
20 #include"main.h"
21 
22 #ifndef HAVE_CANONICALIZE_FILE_NAME
23 char *
25 {
26  char *name, rzpath[256];
27  name = realpath(path, rzpath);
28  return name;
29 }
30 #endif
31 
32 #ifndef HAVE_GETLINE
33 ssize_t
34 getline(char **lineptr, size_t *n, FILE *stream)
35 {
36  char *line;
37  size_t len;
38 
39  line = fgetln(stream, &len);
40  if (!line) return -1;
41  if (len >= *n)
42  {
43  char *tmp;
44  tmp = realloc(*lineptr, len+1);
45  if (!tmp) return -1;
46  *lineptr = tmp;
47  *n = len + 1;
48  }
49  memcpy(*lineptr, line, len);
50  (*lineptr)[len] = 0;
51  return len;
52 }
53 #endif
54 
55 void
57 {
58  int maxline=MAXLINE;
59  gchar *dataline = (gchar *) g_malloc (MAXLINE + 1);
60  gchar *cmd, *extname;
61  FILE *fdata;
62  gchar delimit[]=";\n";
63  GPtrArray *ext_array = NULL;
64 
65  /* read extentions into dataline from wrapper */
66  cmd = g_strdup_printf("%s -i", wrapent->path);
67  fdata = popen(cmd, "r");
68  if (getline(&dataline, &maxline, fdata) > 0)
69  {
70  /*get first ext token and add it to array */
71  if ((extname = strtok(dataline, delimit)) != NULL)
72  {
73  ext_array = g_ptr_array_new();
74  g_ptr_array_add(ext_array, g_strdup_printf("*.%s",extname));
75  }
76  while ((extname = strtok(NULL,delimit)) != NULL)
77  {
78  g_ptr_array_add(ext_array, g_strdup_printf("*.%s",extname));
79  }
80  wrapent->ext_array = ext_array;
81  pclose(fdata);
82  }
83  g_free(cmd);
84 }
85 
87 make_wrapper(gchar *dir,gchar *fname)
88 {
89  WrapperEntry *wrapent;
90 
91  wrapent = (WrapperEntry *) g_malloc (sizeof(WrapperEntry));
92  wrapent->path = g_strdup_printf("%s/%s", dir, fname);
93  wrapent->ext_array = NULL;
94 
95  return wrapent;
96 }
97 
98 gint
99 is_wrapper(const struct dirent *dirent)
100 {
101  /* used as a filter for scandir */
102  /* check if name contains "wrap" */
103  if (fnmatch("*wrap*",dirent->d_name,FNM_PERIOD|FNM_CASEFOLD) == 0)
104  return 1;
105 
106  return 0;
107 }
108 
109 void
111 {
112  gchar *home;
113  gint nwraps, i, cnt;
114  struct dirent **dirents;
115  WrapperEntry *wrapent = NULL;
116 
117  home = g_strdup_printf("%s/.xarchive/wrappers", getenv("HOME"));
118  char *dir[] =
119  {
120  home,
121  WRAPPER_DIR,
122  canonicalize_file_name("../wrappers"),
123  NULL
124  };
125  WRAPPER_ARRAY = g_ptr_array_sized_new(10);
126  for ( i=0; dir[i] != NULL; i++)
127  {
128  g_print("dir: %s\n",dir[i]);
129  nwraps = scandir(dir[i], &dirents, is_wrapper, alphasort);
130  if (nwraps > 0)
131  {
132  g_print("Found %d wrappers\n", nwraps);
133  /* fill wrapper list*/
134  for (cnt=0; cnt < nwraps; cnt++)
135  {
136  wrapent = make_wrapper(dir[i],dirents[cnt]->d_name);
137  setup_exts(wrapent);
138  g_ptr_array_add(WRAPPER_ARRAY, wrapent);
139  }
140  free(dirents);
141  }
142  else g_print("no wrappers in %s\n", dir[i]);
143  }
144  g_free(home);
145  if (WRAPPER_ARRAY->len == 0)
146  {
147  g_print("No wrappers found\n");
148  }
149 }
150 
151 extern gchar *
153 {
154  GString *info_text;
155  WrapperEntry *wrapent;
156  gchar *ext;
157  gint w,e;
158 
159  info_text = g_string_new("Wrappers found and their supported file extensions:\n");
160  if (WRAPPER_ARRAY == NULL)
161  return g_strdup_printf("No wrappers found..\n"
162  "Please check your wrapper dirs:\n\n"
163  "%s\n"
164  "%s/.xarchive/wrappers",
165  WRAPPER_DIR, getenv("HOME"));
166  for (w = 0; w < WRAPPER_ARRAY->len; w++)
167  {
168  wrapent = (WrapperEntry *) g_ptr_array_index(WRAPPER_ARRAY, w);
169  g_string_append_printf(info_text,"\n%s\n Extentions: ",
170  wrapent->path);
171  if (wrapent->ext_array == NULL)
172  {
173  g_string_append_printf(info_text,
174  "** Needed program not found, ignored **\n");
175  continue;
176  }
177  for (e = 0; e < wrapent->ext_array->len; e++)
178  {
179  ext = (gchar *) g_ptr_array_index(wrapent->ext_array, e);
180  g_string_append_printf(info_text,"%s ", ext);
181  }
182  g_string_append_c(info_text, '\n');
183  }
184  return g_string_free(info_text, FALSE);
185 }
186 
187 gchar *
188 get_wrapper(gchar *archive)
189 {
190  /* returns path string of appropriate wrapper for archive, or NULL */
191  WrapperEntry *wrapent;
192  gchar *ext;
193  gint w, e;
194 
195  if (WRAPPER_ARRAY == NULL)
196  return NULL;
197  for (w=0; w < WRAPPER_ARRAY->len; w++)
198  {
199  wrapent = (WrapperEntry *) g_ptr_array_index(WRAPPER_ARRAY, w);
200  if (wrapent->ext_array == NULL)
201  continue;
202  for(e = 0; e < wrapent->ext_array->len; e++)
203  {
204  ext = (gchar *) g_ptr_array_index(wrapent->ext_array, e);
205  if (fnmatch(ext, archive, FNM_CASEFOLD) == 0)
206  return wrapent->path;
207  }
208  }
209  return NULL;
210 }
211 
212 int
213 get_archive_data(gchar **argv)
214 {
215  /* read in archive contents from wrapper line by line
216  * sending each line to the widgets add_row function */
217  enum {name=0,size,attr,user,group,date,time,link,num_ent};
218  FILE *fdata;
219  gint cnt, maxline=MAXLINE, i = 20, error = 0;
220  gchar *ent[num_ent], *esc_archive;
221  gchar *dataline = (gchar *) g_malloc (MAXLINE + 1);
222  gchar delimit[]=";\n";
223  gchar *cmd = NULL;
224  gboolean stopit = FALSE;
225  GtkWidget *pbwin, *pbar;
226  GtkListStore *liststore;
227  GtkTreeView *treeview;
228 
229  treeview = get_current_tree();
230  liststore = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
231  g_object_ref(G_OBJECT(liststore));
232  gtk_tree_view_set_model(treeview, NULL);
233 
234  pbar = gtk_progress_bar_new();
235  pbwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
236  setup_opening_progress_bar(pbwin, pbar, &stopit);
237 
238  esc_archive = my_strescape(argv[2]);
239  cmd = g_strdup_printf("%s %s %s", argv[0], argv[1], esc_archive);
240  g_free(esc_archive);
241  fdata = popen(cmd, "r");
242  while ( (error == 0) && (getline(&dataline, &maxline, fdata) > 0))
243  {
244  if (i == 20)
245  {
246  gtk_progress_bar_pulse(GTK_PROGRESS_BAR(pbar));
247  while (gtk_events_pending())
248  gtk_main_iteration();
249  i = 0;
250  }
251  i++;
252 
253  if (stopit == TRUE)
254  {
255  error = -1;
256  break;
257  }
258  ent[name] = strtok(dataline,delimit);
259  for (cnt = size; cnt < num_ent; cnt++)
260  {
261  ent[cnt] = strtok(NULL,delimit);
262  if ( (ent[cnt] == NULL) && (cnt < link) )
263  {
264  g_print("Error running cmd: %s\n", cmd);
266  GTK_MESSAGE_ERROR, "Error reading file");
267  error = -1;
268  break;
269  }
270  }
271  if (error == 0) add_row(liststore, ent);
272  }
273  pclose(fdata);
274  free(dataline);
275 
276  gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(liststore));
277  g_object_unref(G_OBJECT(liststore));
278 
279  gtk_widget_destroy(pbwin);
280  while(gtk_events_pending())
281  gtk_main_iteration();
282 
283  return error;
284 }
285 
286 gint
287 wrapper_cmd(gint ar_func, gchar *argv[], gchar *dir)
288 {
289  /* order: AR_OPEN, AR_NEW, AR_EXTRACT, AR_ADD, AR_REMOVE, AR_VIEW */
290  gchar *wrap_opt[]= { "-o", "-n", "-e", "-a", "-r", "-v" };
291  gint wrapper_status = 0, i;
292  GPid pid;
293  GError *error;
294 
295  if ((argv[WRAPPER_INDEX] = g_strdup(get_wrapper(argv[ARCHIVE_INDEX])))
296  == NULL )
297  {
298  g_print("from main.c: No wrapper found for archive %s\n",
299  argv[ARCHIVE_INDEX]);
300  return -1;
301  }
302 
303  argv[OPTION_INDEX] = g_strdup(wrap_opt[ar_func]);
304 
305  g_print("from wrapper_cmd: ");
306  for (i=0; argv[i] != NULL; i++)
307  g_print("%s ", argv[i]);
308  g_print("\n");
309 
310  switch ( ar_func )
311  {
312  case AR_OPEN:
313  if (get_archive_data(argv) < 0) return -1;
314  break;
315  case AR_ADD:
316  case AR_NEW:
317  case AR_REMOVE:
318  case AR_VIEW:
319  case AR_EXTRACT:
320  g_spawn_async(dir, /* working dir */
321  argv, /* argument vector */
322  NULL, /* env vector */
323  G_SPAWN_DO_NOT_REAP_CHILD, /* GSpawnFlags */
324  NULL, /* child setup function */
325  NULL, /* child setup data */
326  &pid, /* GPid process pid */
327  &error); /* GError error */
328  /* wait for the command and run the progress bar */
329  wait_with_progress_bar(pid, &wrapper_status, ar_func);
330  break;
331  default:
332  break;
333  }
334 
335  g_print("wrapper exited with: %i\n", WEXITSTATUS(wrapper_status));
336  switch (WEXITSTATUS(wrapper_status))
337  {
338  case 0:
339  return 0;
340  case E_UNSUPPORTED:
342  GTK_MESSAGE_ERROR,
343  "Action not supported by wrapper for this archive type.");
344  return -1;
345  default:
347  GTK_MESSAGE_ERROR,
348  "Wrapper exited with a error.");
349  return -1;
350  }
351 }
352 
353 void
355 {
356  gchar *dir;
357 
358  dir = g_strdup_printf("%s/.xarchive", getenv("HOME"));
359  if (g_file_test(dir, G_FILE_TEST_IS_DIR) == FALSE)
360  g_mkdir(dir, S_IRWXU|S_IRWXG);
361  g_free(dir);
362 
363  dir = g_strdup_printf("%s/.xarchive/wrappers", getenv("HOME"));
364  if (g_file_test(dir, G_FILE_TEST_IS_DIR) == FALSE)
365  g_mkdir(dir, S_IRWXU|S_IRWXG);
366  g_free(dir);
367 }
368 
369 ParsedArgs *
370 parse_options(gint argc, gchar *argv[])
371 {
372 
373  ParsedArgs *pargs = (ParsedArgs *) g_malloc (sizeof(ParsedArgs));
374  GError *error = NULL;
375  GOptionContext *context;
376  gchar *cfname = NULL;
377  gchar *afname = NULL;
378  GOptionEntry entries[] =
379  {
380  { "geometry", 'g', 0, G_OPTION_ARG_STRING, &pargs->geom,
381  "Change intial widget geometry to GEOM.\n"
382  "\t\t\t Format: WxH+Xpos+Ypos, eg 500x300+10+10\n",
383  "GEOM" },
384  { "create", 'c', 0, G_OPTION_ARG_FILENAME, &cfname,
385  "Create an archive named ARCHIVE containing FILES.\n"
386  "\t\t\t ARCHIVE should be the full path to the archive.\n"
387  "\t\t\t FILES will be shown in a file chooser.\n"
388  "\t\t\t If the name 'ask' is passed as the ARCHIVE name\n"
389  "\t\t\t XArchive will give you a file creation dialog.\n"
390  "\t\t\t May not be used with -a option.\n",
391  "ARCHIVE" },
392  { "add", 'a', 0, G_OPTION_ARG_FILENAME, &afname,
393  "Add FILES to ARCHIVE.\n"
394  "\t\t\t ARCHIVE should be the full path to the archive.\n"
395  "\t\t\t FILES will be shown in a file chooser.\n"
396  "\t\t\t If the name 'ask' is passed as the ARCHIVE name\n"
397  "\t\t\t XArchive will give you a file selector dialog.\n"
398  "\t\t\t May not be used with -c option.\n",
399  "ARCHIVE" },
400  { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &pargs->files,
401  NULL, NULL },
402  { NULL }
403  };
404 
405  pargs->action = AR_OPEN;
406  pargs->archive = NULL;
407  pargs->files = NULL;
408  pargs->geom = NULL;
409 
410  context=g_option_context_new("[FILES...]\n\n"
411  "\tWithout an option each file in the list\n"
412  "\tof passed FILES is treated as an archive\n"
413  "\tand an attempt is made to open them.\n"
414  "\tWith no FILES passed an info page is shown."
415  );
416  g_option_context_add_main_entries (context, entries, NULL);
417  g_option_context_add_group (context, gtk_get_option_group (TRUE));
418  g_option_context_parse (context, &argc, &argv, &error);
419  g_option_context_free(context);
420 
421  if (error != NULL || (cfname != NULL && afname != NULL))
422  {
423  g_printerr("Error parsing options\n"
424  "Note: you can use -c ** OR ** -a, not both.\n"
425  "Please see: xarchive --help\n"
426  "or: man xarchive\n");
427  exit(EXIT_FAILURE);
428  }
429  if (cfname != NULL)
430  {
431  pargs->archive = cfname;
432  pargs->action = AR_NEW;
433  }
434  else if (afname != NULL)
435  {
436  pargs->archive = afname;
437  pargs->action = AR_ADD;
438  }
439 
440  return pargs;
441 }
442 
443 int
444 main( gint argc, gchar *argv[] )
445 {
446  gchar *wrapinf;
447  ParsedArgs *pargs;
448 
449  pargs = parse_options(argc, argv);
451  setup_wrappers();
452 
453  wrapinf = wrapper_info();
454  g_print("%s\n%s\n\n", PACKAGE_STRING, PACKAGE_BUGREPORT);
455  puts(wrapinf);
456  g_free(wrapinf);
457 
458  make_widgets(pargs);
459 
460  return 0;
461 }
OPTION_INDEX
Definition: common.h:14
wrapper_info
gchar * wrapper_info(void)
Definition: main.c:152
is_wrapper
gint is_wrapper(const struct dirent *dirent)
Definition: main.c:99
E_UNSUPPORTED
#define E_UNSUPPORTED
Definition: common.h:9
AR_VIEW
Definition: common.h:12
AR_OPEN
Definition: common.h:12
parsed_arguments::geom
char * geom
Definition: common.h:24
setup_opening_progress_bar
void setup_opening_progress_bar(GtkWidget *pbwin, GtkWidget *pbar, gboolean *stopit)
Definition: widgets_gtk.c:420
main
int main(gint argc, gchar *argv[])
Definition: main.c:444
wrapper_entry
Definition: main.h:15
parsed_arguments::files
char ** files
Definition: common.h:22
setup_exts
void setup_exts(WrapperEntry *wrapent)
Definition: main.c:56
wrapper_entry::path
gchar * path
Definition: main.h:17
getline
ssize_t getline(char **lineptr, size_t *n, FILE *stream)
Definition: main.c:34
setup_home_directory
void setup_home_directory(void)
Definition: main.c:354
AR_REMOVE
Definition: common.h:12
get_archive_data
int get_archive_data(gchar **argv)
Definition: main.c:213
AR_ADD
Definition: common.h:12
WRAPPER_ARRAY
GPtrArray * WRAPPER_ARRAY
Definition: main.h:22
wrapper_cmd
gint wrapper_cmd(gint ar_func, gchar *argv[], gchar *dir)
Definition: main.c:287
PACKAGE_STRING
#define PACKAGE_STRING
Definition: config.h:112
setup_wrappers
void setup_wrappers(void)
Definition: main.c:110
get_wrapper
gchar * get_wrapper(gchar *archive)
Definition: main.c:188
MAIN_WINDOW
GtkWidget * MAIN_WINDOW
Definition: widgets_gtk.h:35
parsed_arguments
Definition: common.h:19
wrapper_entry::ext_array
GPtrArray * ext_array
Definition: main.h:18
AR_NEW
Definition: common.h:12
my_strescape
gchar * my_strescape(gchar *string)
Definition: my_strescape.c:50
wait_with_progress_bar
void wait_with_progress_bar(GPid pid, gint *wrapper_status, gint ar_func)
Definition: widgets_gtk.c:449
add_row
void add_row(GtkListStore *liststore, gchar **ent)
Definition: widgets_gtk.c:228
PACKAGE_BUGREPORT
#define PACKAGE_BUGREPORT
Definition: config.h:106
canonicalize_file_name
char * canonicalize_file_name(char *path)
Definition: main.c:24
get_current_tree
GtkTreeView * get_current_tree(void)
Definition: widgets_gtk.c:192
AR_EXTRACT
Definition: common.h:12
parsed_arguments::archive
char * archive
Definition: common.h:23
ARCHIVE_INDEX
Definition: common.h:14
MAXLINE
#define MAXLINE
Definition: common.h:8
main.h
make_wrapper
WrapperEntry * make_wrapper(gchar *dir, gchar *fname)
Definition: main.c:87
make_widgets
gint make_widgets(ParsedArgs *pargs)
Definition: widgets_gtk.c:2002
parsed_arguments::action
int action
Definition: common.h:21
parse_options
ParsedArgs * parse_options(gint argc, gchar *argv[])
Definition: main.c:370
WRAPPER_INDEX
Definition: common.h:14
message
gboolean message(GtkWidget *parentwin, gint type, gchar *text)
Definition: widgets_gtk.c:551