1 #ifdef COPYRIGHT_INFORMATION
2 #include "gplv3.h"
3 #endif
4 /*
5  * Copyright (C) 2003-2012 Edscott Wilson Garcia
6  * EMail: edscott@users.sf.net
7  *
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23 
24 static char *ftypes[] = {
25     N_("Any"),
26     N_("Regular"),
27     N_("Directory"),
28     N_("Symbolic Link"),
29     N_("Socket"),
30     N_("Block device"),
31     N_("Character device"),
32     N_("FIFO"),
33     NULL
34 };
35 
36 static char *ft[] = {
37     "any",
38     "reg",
39     "dir",
40     "sym",
41     "sock",
42     "blk",
43     "chr",
44     "fifo",
45     NULL
46 };
47 
48 
49 static gint result_limit_counter;
50 // These externals are in find-module_gui.c
51 extern gint result_limit;
52 extern gint size_greater;
53 extern gint size_smaller;
54 extern gint last_minutes;
55 extern gint last_hours;
56 extern gint last_days;
57 extern gint last_months;
58 extern gboolean default_recursive;
59 extern gboolean default_recursiveH;
60 extern gboolean default_xdev;
61 extern gboolean default_line_count;
62 extern gboolean default_case_sensitive;
63 extern gboolean default_ext_regexp;
64 extern gboolean default_look_in_binaries;
65 extern gint default_type_index;
66 extern gboolean default_anywhere;
67 extern gboolean default_match_words;
68 extern gboolean default_match_lines;
69 extern gboolean default_match_no_match;
70 extern gboolean have_grep;
71 extern gboolean have_gnu_grep;
72 extern GSList *find_list;
73 extern gchar  *last_workdir;
74 
75 static gchar *
76 #if GTK_MAJOR_VERSION==2 && GTK_MINOR_VERSION<24
77 get_combo_entry (void* combo_info, GtkComboBoxEntry *combobox);
78 #else
79 get_combo_entry (void* combo_info, GtkComboBox *combobox);
80 #endif
81 
82 static void
grep_options(GtkComboBox * widget,gpointer data)83 grep_options (GtkComboBox *widget, gpointer data) {
84     find_struct_t *find_struct_p = data;
85     gchar *s = get_combo_entry (find_struct_p->findgrep_combo_info, find_struct_p->combogrep);
86     gboolean state=FALSE;
87     if (s && strlen(s)) {
88 	// sensitive
89 	state=TRUE;
90     }
91     g_free(s);
92     gtk_widget_set_sensitive (
93 	    GTK_WIDGET(g_object_get_data(
94 		    G_OBJECT(find_struct_p->dialog), "case_sensitive")), state);
95     gtk_widget_set_sensitive (
96 	    GTK_WIDGET(g_object_get_data(
97 		    G_OBJECT(find_struct_p->dialog), "line_count")), state);
98    if (have_gnu_grep)
99     {
100 	gtk_widget_set_sensitive (
101 	    GTK_WIDGET(g_object_get_data(
102 		    G_OBJECT(find_struct_p->dialog), "ext_regexp")), state);
103 	gtk_widget_set_sensitive (
104 	    GTK_WIDGET(g_object_get_data(
105 		    G_OBJECT(find_struct_p->dialog), "look_in_binaries")), state);
106     }
107     gtk_widget_set_sensitive (
108 	    GTK_WIDGET(g_object_get_data(
109 		    G_OBJECT(find_struct_p->dialog), "label40")), state);
110     gtk_widget_set_sensitive (
111 	    GTK_WIDGET(g_object_get_data(
112 		    G_OBJECT(find_struct_p->dialog), "anywhere")), state);
113     gtk_widget_set_sensitive (
114 	    GTK_WIDGET(g_object_get_data(
115 		    G_OBJECT(find_struct_p->dialog), "match_words")), state);
116     gtk_widget_set_sensitive (
117 	    GTK_WIDGET(g_object_get_data(
118 		    G_OBJECT(find_struct_p->dialog), "match_lines")), state);
119     gtk_widget_set_sensitive (
120 	    GTK_WIDGET(g_object_get_data(
121 		    G_OBJECT(find_struct_p->dialog), "match_no_match")), state);
122 
123 }
124 
125 static gboolean will_destroy = FALSE;
126 
127 static void *
hide_cancel_button(gpointer data)128 hide_cancel_button(gpointer data){
129     GtkWidget *cancel = data;
130     gtk_widget_set_sensitive(cancel, FALSE);
131     gtk_widget_hide(cancel);
132     return NULL;
133 }
134 
135 static void *
exit_loop(gpointer data)136 exit_loop(gpointer data){
137     gtk_main_quit();
138     return NULL;
139 }
140 
141 // This is a thread function, must have GDK mutex set for gtk commands...
142 static
143 void
stderr_f(void * user_data,void * stream,int childFD)144 stderr_f (void *user_data, void *stream, int childFD) {
145     // Grep behaviour has changed. stderr had become more verbose.
146     // So let us just dump it.
147     return;
148 }
149 
150 // This is a thread function...
151 static
152 void
stdout_f(void * user_data,void * stream,int childFD)153 stdout_f (void *user_data, void *stream, int childFD) {
154     widgets_t *widgets_p = user_data;
155     char *line;
156     line = (char *)stream;
157     NOOP ("FORK stdout: %s\n", line);
158 
159     if(line[0] == '\n') return;
160 
161     if (result_limit > 0 && result_limit==result_limit_counter) {
162 	gchar *g=g_strdup_printf("%s. %s %d", _("Results"), _("Upper limit:"), result_limit);
163 	if (will_destroy) {  // Standalone
164 	    fprintf(stdout, "%c%s%s\n", 27, rfm_lp_color(GREEN), g);
165 	    fprintf(stdout, "%c%s%s\n", 27, rfm_lp_color(BLUE),_("Counting files..."));
166 	    fprintf(stdout, "%c[0m", 27 );fflush(stdout);
167 	} else {
168 	    rfm_threaded_diagnostics (widgets_p, "xffm/stock_dialog-warning", NULL);
169 	    rfm_threaded_diagnostics (widgets_p, "xffm_tag/green", g_strconcat(g, "\n", NULL));
170 	    rfm_threaded_diagnostics (widgets_p, "xffm/stock_dialog-info", NULL);
171 	    rfm_threaded_diagnostics (widgets_p, "xffm_tag/blue",  g_strconcat(_("Counting files..."), "\n", NULL));
172 	}
173 	g_free(g);
174     }
175 
176     if(strncmp (line, "fgr search complete!", strlen ("fgr search complete!")) == 0) {
177 #if 0
178 	if (will_destroy) {  // Standalone
179 	    fprintf(stdout, "%c%s%s\n", 27, rfm_lp_color(BLUE),  _("Search Complete"));
180 	    fprintf(stdout, "%c[0m", 27 );fflush(stdout);
181 	} else {
182 	    rfm_threaded_diagnostics (widgets_p, "xffm/stock_find", NULL);
183 	    rfm_threaded_diagnostics (widgets_p, "xffm_tag/blue", g_strconcat(_("Search Complete"), NULL));
184 	    rfm_threaded_diagnostics (widgets_p, NULL, g_strconcat("\n", NULL));
185 
186 	}
187 #endif
188     } else if(strncmp (line, "Tubo-id exit:", strlen ("Tubo-id exit:")) == 0) {
189 
190             if(strchr (line, '\n')) *strchr (line, '\n') = 0;
191 	    GtkWidget *cancel = widgets_p->data;
192 	    if (cancel && GTK_IS_WIDGET(cancel)) {
193 		rfm_context_function(hide_cancel_button, cancel);
194 	    }
195 	    gchar *plural_text =
196 		g_strdup_printf (
197 			ngettext ("Found %d match", "Found %d matches",
198 			    result_limit_counter), result_limit_counter);
199 	    gchar *fgr = g_find_program_in_path("fgr");
200 	    gchar *m = g_strdup_printf(_("%s Finished : %s"), fgr, plural_text);
201 	    g_free(fgr);
202 	    g_free(plural_text);
203 	    if (will_destroy) {  // Standalone
204 		fprintf(stdout, "%c%s%s.\n", 27, rfm_lp_color(RED), m);
205 		fprintf(stdout, "%c[0m\n", 27 );fflush(stdout);
206 		rfm_context_function(exit_loop, widgets_p->paper);
207 	    } else {
208                 gchar *g = g_strdup_printf("%c[31m%s\n",27, m);
209 		rfm_threaded_diagnostics (widgets_p, "xffm/emblem_redball", g);
210 	    }
211 	    g_free(m);
212     } else {
213 	result_limit_counter++;
214 	if (result_limit ==0 ||
215 	    (result_limit > 0 && result_limit > result_limit_counter) ) {
216 	    if (will_destroy) {  // Standalone
217 		fprintf(stdout, "%s", line);
218 		fprintf(stdout, "%c[0m", 27 );fflush(stdout);
219 	    } else {
220 		rfm_threaded_diagnostics (widgets_p, NULL, g_strdup(line));
221 	    }
222 	    gchar *file = g_strdup(line);
223 	    if (strchr(file, '\n')) *strchr(file, '\n') = 0;
224 	    find_list = g_slist_prepend(find_list, file);
225 	}
226     }
227     return;
228 }
229 
230 
231 
232 static void
path_filechooser(GtkButton * button,gpointer user_data)233 path_filechooser (GtkButton * button, gpointer user_data) {
234     filechooser_t *filechooser_p = (filechooser_t *) user_data;
235     const gchar *text;
236     if(filechooser_p->filechooser_action == GTK_FILE_CHOOSER_ACTION_OPEN) {
237         text = _("Select Files...");
238     } else if(filechooser_p->filechooser_action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) {
239         text = _("Select folder to search in");
240     } else {
241         text = "FIXME";
242     }
243     NOOP ("FIND: parent=0x%lu action=%d, text=%s\n", (long unsigned)filechooser_p->parent, filechooser_p->filechooser_action, text);
244     GtkWidget *dialog = gtk_file_chooser_dialog_new (text,
245                                                      GTK_WINDOW (filechooser_p->parent),
246                                                      filechooser_p->filechooser_action,
247                                                      _("Cancel"),
248                                                      GTK_RESPONSE_CANCEL,
249                                                      _("Open"),
250                                                      GTK_RESPONSE_ACCEPT,
251                                                      NULL);
252     gtk_file_chooser_set_action ((GtkFileChooser *) dialog, filechooser_p->filechooser_action);
253     if(filechooser_p->folder) {
254         gtk_file_chooser_set_current_folder ((GtkFileChooser *) dialog, filechooser_p->folder);
255     }
256 
257     gint response = rfm_dialog_run_response(dialog);
258 
259     if(response == GTK_RESPONSE_ACCEPT) {
260         char *filename;
261         void *combo_info = filechooser_p->combo_info;
262         filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
263 	if (rfm_void(RFM_MODULE_DIR, "combobox", "module_active")){
264 	    COMBOBOX_set_entry (combo_info, filename);
265 	} else {
266 	    gtk_entry_set_text (filechooser_p->entry, filename);
267 	}
268         NOOP ("Got %s\n", filename);
269         g_free (filename);
270     }
271     gtk_widget_destroy (dialog);
272 
273 }
274 
275 static void
save_ff_text(char * p)276 save_ff_text (char *p) {
277     gchar *fname;
278     if(!p || !strlen (p))
279         return;
280     fname = g_build_filename (FIND_DBH_FILE, NULL);
281     COMBOBOX_save_to_history (fname, p);
282     g_free (fname);
283 }
284 
285 static void
save_fpath_text(const char * p)286 save_fpath_text (const char *p) {
287     gchar *fname;
288     NOOP ("save_fpath_text-> %s\n", p);
289     if(!p || !strlen (p))
290         return;
291     {
292         fname = g_build_filename (FIND_PATHS_DBH_FILE, NULL);
293     }
294     NOOP ("saving to history-> %s\n", p);
295     COMBOBOX_save_to_history (fname, p);
296     g_free (fname);
297 }
298 
299 static void
save_fgrep_text(char * p)300 save_fgrep_text (char *p) {
301     gchar *fname;
302     if(!p || !strlen (p))
303         return;
304     fname = g_build_filename (FIND_GREP_DBH_FILE, NULL);
305     COMBOBOX_save_to_history (fname, p);
306     g_free (fname);
307 }
308 
309 static void
cancel_all(find_struct_t * find_struct_p)310 cancel_all (find_struct_t *find_struct_p) {
311     // Send a KILL to each fgr that is still running. This is done
312     // by sending a SIGUSR2 to the controller (SIGUSR1 would pass on a TERM).
313     GSList *tmp = find_struct_p->controllers;
314     for (; tmp && tmp->data; tmp=tmp->next){
315 	kill(GPOINTER_TO_INT(tmp->data), SIGUSR2);
316     }
317     g_slist_free(find_struct_p->controllers);
318     find_struct_p->controllers=NULL;
319 }
320 
321 static void
cancel_callback(GtkWidget * button,gpointer data)322 cancel_callback (GtkWidget * button, gpointer data) {
323     GtkWidget *dialog=g_object_get_data(G_OBJECT(button), "dialog");
324     find_struct_t *find_struct_p = g_object_get_data(G_OBJECT(dialog), "find_struct_p");
325     cancel_all(find_struct_p);
326     gtk_widget_set_sensitive(button, FALSE);
327 }
328 
329 
330 static void
destroy_find(GtkWidget * dialog,gpointer data)331 destroy_find (GtkWidget * dialog, gpointer data) {
332     gtk_widget_hide (dialog);
333     find_struct_t *find_struct_p = g_object_get_data(G_OBJECT(dialog), "find_struct_p");
334     if (!find_struct_p) {
335 	return;
336     }
337     g_object_set_data(G_OBJECT(dialog),"find_struct_p", NULL);
338     //widgets_t *widgets_p=g_object_get_data(G_OBJECT(dialog), "widgets_p");
339     COMBOBOX_destroy_combo(find_struct_p->findpath_combo_info);
340     COMBOBOX_destroy_combo(find_struct_p->find_combo_info);
341     COMBOBOX_destroy_combo(find_struct_p->findgrep_combo_info);
342 
343     g_free(find_struct_p);
344     g_object_set_data(G_OBJECT(dialog), "widgets_p", NULL);
345     g_free(g_object_get_data(G_OBJECT(dialog), "radio_p" ));
346 
347     gtk_widget_destroy (dialog);
348     if (find_list) {
349 	GSList *list = find_list;
350 	for (;list && list->data; list=list->next){
351 	    g_free(list->data);
352 	}
353 	g_slist_free(find_list);
354 	find_list = NULL;
355     }
356     gtk_main_quit();
357 }
358 
359 static void
on_find_close(GtkButton * button,gpointer data)360 on_find_close (GtkButton * button, gpointer data) {
361     GtkWidget *dialog=g_object_get_data(G_OBJECT(button), "dialog");
362     destroy_find (dialog, data);
363 }
364 
365 
366 static gchar *
367 #if GTK_MAJOR_VERSION==2 && GTK_MINOR_VERSION<24
get_combo_entry(void * combo_info,GtkComboBoxEntry * combobox)368 get_combo_entry (void* combo_info, GtkComboBoxEntry *combobox) {
369 #else
370 get_combo_entry (void* combo_info, GtkComboBox *combobox) {
371 #endif
372     const gchar *choice;
373     gchar *s = NULL;
374 
375     if (rfm_void(RFM_MODULE_DIR, "combobox", "module_active")){
376 	choice = (gchar *) COMBOBOX_get_entry (combo_info);
377     } else {
378 	choice = gtk_entry_get_text (GTK_ENTRY(
379 		    gtk_bin_get_child(GTK_BIN(combobox))));
380     }
381     /*NOOP("choice== %s\n", choice);
382        NOOP("choice== %s\n", choice); */
383 
384     if(choice) {
385         s = g_locale_from_utf8 (choice, -1, NULL, NULL, NULL);
386     }
387     if(s)
388         s = g_strchug (s);
389     if(s)
390         s = g_strchomp (s);
391     if(!s)
392         s = g_strdup ("");
393 
394     return s;
395 }
396 
397 static const gchar *
398 get_time_type(GtkWidget *dialog){
399     if (gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "radio1"))){
400 	return "-M";
401     }
402     if (gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "radio2"))){
403 	return "-C";
404     }
405     return "-A";
406 }
407 
408 static void
409 on_find_clicked_action (GtkButton * button, gpointer data, gboolean destroy) {
410     gchar *sg=NULL;
411     gchar *sl=NULL;
412     gchar *lm=NULL;
413     gchar *ld=NULL;
414     gchar *lh=NULL;
415     gchar *lmm=NULL;
416     gchar *pw_uid=NULL;
417     gchar *pw_gid=NULL;
418 
419     short int i, j;
420     gchar *s;
421     gchar *argument[MAX_COMMAND_ARGS];
422     gchar *find_filter = NULL,
423         *filter = NULL,
424         *path = NULL,
425         *token = NULL;
426     find_struct_t *find_struct_p = data;
427 
428 
429     GtkWidget *dialog=g_object_get_data(G_OBJECT(button), "dialog");
430     will_destroy = destroy;
431 
432 
433     widgets_t *widgets_p = g_object_get_data(G_OBJECT(dialog), "widgets_p");
434     if(!widgets_p) {
435         g_warning ("on_find_clicked: !widgets_p\n");
436         return;
437     }
438     GtkWidget *cancel = g_object_get_data(G_OBJECT(dialog), "cancel_button");
439     gtk_widget_show(cancel);
440     gtk_widget_set_sensitive(cancel, TRUE);
441     widgets_p->data = cancel;
442 
443 
444 
445     rfm_show_text (widgets_p);
446 
447     /* get options */
448 
449 /* get the parameters set by the user... *****/
450 
451 /* limit */
452     result_limit = gtk_spin_button_get_value_as_int (
453 	    GTK_SPIN_BUTTON (g_object_get_data(G_OBJECT(dialog), "upper_limit_spin")));
454     result_limit_counter=0;
455 
456 /* the rest */
457 
458     s = get_combo_entry (find_struct_p->findpath_combo_info, find_struct_p->combopath);
459     if(!s || strlen (s) == 0 || !rfm_g_file_test (s, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
460         rfm_diagnostics (widgets_p, "xffm/stock_dialog-error", strerror (ENOENT), ": ", s, NULL);
461         rfm_diagnostics (widgets_p, NULL, "\n", NULL);
462 	g_free(s);
463         return;
464     }
465 
466     /* tilde expansion */
467     else if(s[strlen (s) - 1] == '~'){
468 	g_free(s);
469         s = g_strdup("~/");
470     }
471     /* environment variables */
472     else if(s[0] == '$') {
473         const gchar *p = getenv (s + 1);
474         if(p){
475 	    g_free(s);
476             s = g_strdup(p);
477 	}else {
478 	    g_free(s);
479             s = g_strdup("/");
480 	}
481     }
482 
483     save_fpath_text (s);
484 
485 
486     g_free (widgets_p->workdir);
487     widgets_p->workdir=g_strdup (s);
488     g_free(last_workdir);
489     last_workdir = g_strdup (s);
490     path = g_strdup (".");
491     g_free(s);
492 
493     s = get_combo_entry (find_struct_p->find_combo_info, find_struct_p->combo);
494     if(s && strlen (s)) {
495         filter = g_strdup (s);
496         save_ff_text (filter);
497     }
498     g_free(s);
499 
500     s = get_combo_entry (find_struct_p->findgrep_combo_info, find_struct_p->combogrep);
501 
502     if(s && strlen (s)) {
503         token = g_strdup (s);
504         save_fgrep_text (token);
505     } else {
506         /* if no grep pattern given, its a plain find and
507          * we should show the diagnostics */
508     }
509     g_free(s);
510 
511     /* select list */
512 #if GTK_MAJOR_VERSION==2 && GTK_MINOR_VERSION<24
513     s = gtk_combo_box_get_active_text ((GtkComboBox *)
514 	    g_object_get_data(G_OBJECT(dialog), "file_type_om"));
515 #else
516     s = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT(
517 	    g_object_get_data(G_OBJECT(dialog), "file_type_om")));
518 #endif
519     default_type_index=gtk_combo_box_get_active((GtkComboBox *)
520 	    g_object_get_data(G_OBJECT(dialog), "file_type_om"));
521 
522     i = 0;
523     {
524         argument[i++] = "fgr";
525 
526         /*argument[i++] = "-P"; */
527 
528         if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "recursive"))) {
529 	    default_recursive=TRUE;
530             if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "recursiveH"))) {
531                 argument[i++] = "-r";
532 		default_recursiveH=TRUE;
533             } else {
534                 argument[i++] = "-R";
535 		default_recursiveH=FALSE;
536             }
537         } else {
538 	    default_recursive=FALSE;
539 	}
540 
541         if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "size_greater"))) {
542 	     size_greater = gtk_spin_button_get_value_as_int (
543 		GTK_SPIN_BUTTON (g_object_get_data(G_OBJECT(dialog), "size_greater_spin")));
544              argument[i++] = "-s";
545 	     argument[i++] = sg = g_strdup_printf("+%d", size_greater);
546 	}
547         if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "size_smaller"))) {
548 	     size_smaller = gtk_spin_button_get_value_as_int (
549 		GTK_SPIN_BUTTON (g_object_get_data(G_OBJECT(dialog), "size_smaller_spin")));
550              argument[i++] = "-s";
551 	     argument[i++] = sl = g_strdup_printf("-%d", size_smaller);
552 	}
553         if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "last_months"))) {
554 	    argument[i++] = (gchar *)get_time_type(dialog);
555 	    last_months = gtk_spin_button_get_value_as_int (
556 		GTK_SPIN_BUTTON (g_object_get_data(G_OBJECT(dialog), "last_months_spin")));
557              argument[i++] = "-m";
558 	     argument[i++] = lm = g_strdup_printf("%d", last_months);
559 	}
560 	else if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "last_days"))) {
561 	    argument[i++] = (gchar *)get_time_type(dialog);
562 	     last_days = gtk_spin_button_get_value_as_int (
563 		GTK_SPIN_BUTTON (g_object_get_data(G_OBJECT(dialog), "last_days_spin")));
564              argument[i++] = "-d";
565 	     argument[i++] = ld = g_strdup_printf("%d", last_days);
566 	}
567 	else if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "last_hours"))) {
568 	    argument[i++] = (gchar *)get_time_type(dialog);
569 	     last_hours = gtk_spin_button_get_value_as_int (
570 		GTK_SPIN_BUTTON (g_object_get_data(G_OBJECT(dialog), "last_hours_spin")));
571              argument[i++] = "-h";
572 	     argument[i++] = lh = g_strdup_printf("%d", last_hours);
573 	}
574 	else if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "last_minutes"))) {
575 	    argument[i++] = (gchar *)get_time_type(dialog);
576 	     last_minutes = gtk_spin_button_get_value_as_int (
577 		GTK_SPIN_BUTTON (g_object_get_data(G_OBJECT(dialog), "last_minutes_spin")));
578              argument[i++] = "-k";
579 	     argument[i++] = lmm = g_strdup_printf("%d", last_minutes);
580 	}
581 
582 
583 
584         if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "suidexe"))){
585             argument[i++] = "-p";
586 	    if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "suid_radio"))){
587 		argument[i++] = "suid";
588 	    } else {
589 		argument[i++] = "exe";
590 	    }
591 	}
592         if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "octal_p"))){
593             argument[i++] = "-o";
594 	    const gchar *c = gtk_entry_get_text ((GtkEntry *)g_object_get_data(G_OBJECT(dialog), "permissions_entry"));
595 	    if (c && strlen(c)) argument[i++] = (gchar *)c;
596 	    else argument[i++] = "0666";
597 	}
598 
599         if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "uid"))){
600 	    GtkWidget *entry = gtk_bin_get_child(GTK_BIN(g_object_get_data(G_OBJECT(dialog), "uid_combo")));
601 	    const gchar *val = gtk_entry_get_text (GTK_ENTRY (entry));
602 	    if(val && strlen(val)) {
603 		argument[i++] = "-u";
604 		struct passwd *pw = getpwnam (val);
605 		if(pw) {
606 		    pw_uid = g_strdup_printf("%d", pw->pw_uid);
607 		} else {
608 		    pw_uid = g_strdup_printf("%d",atoi(val));
609 		}
610 		argument[i++] = pw_uid;
611 
612 	    }
613 	}
614         if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "gid"))){
615 	    GtkWidget *entry = gtk_bin_get_child(GTK_BIN(g_object_get_data(G_OBJECT(dialog), "gid_combo")));
616 	    const gchar *val = gtk_entry_get_text (GTK_ENTRY (entry));
617 	    if(val && strlen(val)) {
618 		argument[i++] = "-g";
619 		struct group *gr = getgrnam (val);
620 		if(gr) {
621 		    pw_gid = g_strdup_printf("%d", gr->gr_gid);
622 		} else {
623 		    pw_gid = g_strdup_printf("%d",atoi(val));
624 		}
625 		argument[i++] = pw_gid;
626 
627 	    }
628 	}
629 
630 
631 
632         if(!gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "case_sensitive"))){
633             argument[i++] = "-i";
634 	    default_case_sensitive=FALSE;
635 	} else {
636 	    default_case_sensitive=TRUE;
637 	}
638         if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "line_count"))){
639             argument[i++] = "-c";
640 	    default_line_count=TRUE;
641 	} else {
642 	    default_case_sensitive=FALSE;
643 	}
644         if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "xdev"))){
645             argument[i++] = "-a";
646 	    default_xdev=TRUE;
647 	} else {
648 	    default_xdev=FALSE;
649 	}
650         if(token) {
651             if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "ext_regexp"))){
652                 argument[i++] = "-E";
653 		default_ext_regexp=TRUE;
654 	    } else {
655                 argument[i++] = "-e";
656 		default_ext_regexp=FALSE;
657 	    }
658             argument[i++] = token;
659 
660             /* options for grep: ***** */
661             if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "look_in_binaries"))){
662 		default_look_in_binaries=TRUE;
663 	    } else {
664                 argument[i++] = "-I";
665 		default_look_in_binaries=FALSE;
666 	    }
667 	    default_anywhere=default_match_words=default_match_lines=default_match_no_match=FALSE;
668             if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "anywhere"))) {
669 		default_anywhere=TRUE;
670 	    }
671             else if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "match_words"))){
672                 argument[i++] = "-w";
673 		default_match_words=TRUE;
674 	    }
675             else if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "match_lines"))){
676                 argument[i++] = "-x";
677 		default_match_lines=TRUE;
678 	    }
679             else if(gtk_toggle_button_get_active ((GtkToggleButton *) g_object_get_data(G_OBJECT(dialog), "match_no_match"))){
680                 argument[i++] = "-L";
681 		default_match_no_match=TRUE;
682 	    }
683         }
684 
685         for(j = 0; ftypes[j] != NULL; j++) {
686             if(s && strcmp (s, _(ftypes[j])) == 0) {
687                 argument[i++] = "-t";
688                 argument[i++] = ft[j];
689                 break;
690             }
691         }
692 
693         /* apply wildcard filter if not specified (with dotfiles option) */
694         argument[i++] = "-f";
695         if(filter && strlen (filter)) {
696             argument[i++] = filter;
697         } else {
698             argument[i++] = "*";
699             argument[i++] = "-D";
700         }
701 
702         /* last argument is the path (which could be NULL) */
703         argument[i++] = path;
704     }
705 
706     argument[i++] = "-v"; // (verbose output)
707 
708     argument[i] = (char *)0;
709 
710     if (will_destroy) {  // Standalone
711 	fprintf(stdout, "%c%s", 27, rfm_lp_color(BLUE));
712 	gchar **ap = argument;
713 	for (;ap && *ap; ap++) {
714 	    if (strchr(*ap, '*') || strchr(*ap, '?') || strchr(*ap, ' ')) {
715 		fprintf(stdout, " \"%s\"", *ap);
716 	    }
717 	    else fprintf(stdout, " %s", *ap);
718 	}
719 	fprintf(stdout, "\n");
720 	fprintf(stdout, "%c%s%s\n", 27, rfm_lp_color(GREEN),  _("Searching..."));
721 	fprintf(stdout, "%c[0m", 27 );fflush(stdout);
722     } else {
723 	rfm_diagnostics (widgets_p, "xffm/emblem_find", NULL);
724 	rfm_diagnostics (widgets_p, "xffm_tag/green", _("Searching..."), "\n", NULL);
725     }
726 
727     if (find_list) {
728 	GSList *list = find_list;
729 	for (;list && list->data; list=list->next){
730 	    g_free(list->data);
731 	}
732 	g_slist_free(find_list);
733 	find_list = NULL;
734     }
735 
736 
737 
738     void **arg = (void **)malloc(7*sizeof(void *));
739     if (!arg) g_error("malloc: %s\n", strerror(errno));
740     arg[0] =  widgets_p;
741     arg[1] =  (void *)argument;
742     arg[2] =   NULL;
743     arg[3] =   NULL;
744     arg[4] =   (void *)stdout_f;
745     arg[5] =   (void *)stderr_f;
746     arg[6] =   NULL;
747 
748     pid_t controller =
749         GPOINTER_TO_INT(rfm_natural(RFM_MODULE_DIR, "run", arg, "m_thread_run_argv"));
750 //          m_thread_run_argv(arg);
751 //	rfm_thread_run_argv_full (widgets_p, argument, FALSE, NULL, stdout_f, stderr_f, NULL);
752     g_free(sg);
753     g_free(sl);
754     g_free(lm);
755     g_free(ld);
756     g_free(lh);
757     g_free(lmm);
758     g_free(pw_uid);
759     g_free(pw_gid);
760     // When the dialog is destroyed on action, then output is going to a
761     // widgets_p away from dialog window, so we let the process run on and on.
762     if (!destroy) {
763 	find_struct_p->controllers =
764 	    g_slist_prepend(find_struct_p->controllers, GINT_TO_POINTER(controller));
765     }
766 
767 
768     NOOP ("FGR: --> ");
769     rfm_show_text (widgets_p);
770     for(j = 0; j < i; j++) {
771         NOOP (" %s", argument[j]);
772     }
773     NOOP ("\n");
774     if (destroy) {
775 	// In this case we let the fgr process run on and on
776 	// (see above)
777 	gtk_widget_destroy (dialog);
778     }
779     g_free(s);
780     g_free (token);
781     g_free (filter);
782     g_free (find_filter);
783     g_free (path);
784 }
785 
786 static void
787 on_find_clicked (GtkButton * button, gpointer data) {
788     on_find_clicked_action (button, data, TRUE);
789 }
790 
791 static void
792 on_apply_clicked (GtkButton * button, gpointer data) {
793     on_find_clicked_action (button, data, FALSE);
794 }
795 
796 static void
797 on_find_clicked_wrapper (GtkEntry * entry, gpointer data) {
798     on_find_clicked_action ((GtkButton *) entry, data, FALSE);
799 }
800 
801