4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2001, the ROX-Filer team.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <sys/param.h>
34 #include "gui_support.h"
42 /* Static prototypes */
43 static void write_data(gpointer data
, gint fd
, GdkInputCondition cond
);
44 static gboolean
follow_symlink(char *full_path
,
45 FilerWindow
*filer_window
,
46 FilerWindow
*src_window
);
47 static gboolean
open_file(guchar
*path
, MIME_type
*type
);
48 static void dir_show_help(DirItem
*item
, char *path
);
50 typedef struct _PipedData PipedData
;
61 /****************************************************************
62 * EXTERNAL INTERFACE *
63 ****************************************************************/
66 /* An application has been double-clicked (or run in some other way) */
67 void run_app(char *path
)
70 char *argv
[] = {NULL
, NULL
};
72 apprun
= g_string_new(path
);
73 argv
[0] = g_string_append(apprun
, "/AppRun")->str
;
75 if (!spawn_full(argv
, home_dir
))
76 report_rox_error(_("Failed to fork() child process"));
78 g_string_free(apprun
, TRUE
);
81 /* Execute this program, passing all the URIs in the list as arguments.
82 * URIs that are files on the local machine will be passed as simple
83 * pathnames. The uri_list should be freed after this function returns.
85 void run_with_files(char *path
, GList
*uri_list
)
91 if (stat(path
, &info
))
93 delayed_rox_error(_("Program %s not found - deleted?"), path
);
97 argv
= g_malloc(sizeof(char *) * (g_list_length(uri_list
) + 2));
99 if (S_ISDIR(info
.st_mode
))
100 argv
[argc
++] = make_path(path
, "AppRun")->str
;
106 char *uri
= (char *) uri_list
->data
;
109 local
= get_local_path(uri
);
111 argv
[argc
++] = local
;
114 uri_list
= uri_list
->next
;
119 if (!spawn_full(argv
, home_dir
))
120 delayed_rox_error(_("Failed to fork() child process"));
123 /* Run the program as '<path> -', piping the data to it via stdin.
124 * You can g_free() the data as soon as this returns.
126 void run_with_data(char *path
, gpointer data
, gulong length
)
128 char *argv
[] = {NULL
, "-", NULL
};
133 if (stat(path
, &info
))
135 delayed_rox_error(_("Program %s not found - deleted?"), path
);
139 if (S_ISDIR(info
.st_mode
))
140 argv
[0] = make_path(path
, "AppRun")->str
;
146 delayed_rox_error("pipe: %s", g_strerror(errno
));
149 close_on_exec(fds
[1], TRUE
);
150 close_on_exec(fds
[0], TRUE
);
155 delayed_rox_error("fork: %s", g_strerror(errno
));
159 /* We are the child */
161 if (dup2(fds
[0], 0) == -1)
162 g_warning("dup2() failed: %s\n",
166 close_on_exec(0, FALSE
);
167 if (execv(argv
[0], argv
))
168 g_warning("execv(%s) failed: %s\n",
169 argv
[0], g_strerror(errno
));
173 /* We are the parent */
174 set_blocking(fds
[1], FALSE
);
175 pd
= g_new(PipedData
, 1);
176 pd
->data
= g_malloc(length
);
177 memcpy(pd
->data
, data
, length
);
180 pd
->tag
= gdk_input_add(fds
[1], GDK_INPUT_WRITE
,
188 /* Load a file, open a directory or run an application. Or, if 'edit' is set:
189 * edit a file, open an application, follow a symlink or mount a device.
191 * filer_window is the window to use for displaying a directory.
192 * NULL will always use a new directory when needed.
193 * src_window is the window to copy options from, or NULL.
195 * Returns TRUE on success.
197 gboolean
run_diritem(guchar
*full_path
,
199 FilerWindow
*filer_window
,
200 FilerWindow
*src_window
,
203 if (item
->flags
& ITEM_FLAG_SYMLINK
&& edit
)
204 return follow_symlink(full_path
, filer_window
, src_window
);
206 switch (item
->base_type
)
209 if (item
->flags
& ITEM_FLAG_APPDIR
&& !edit
)
215 if (item
->flags
& ITEM_FLAG_MOUNT_POINT
&& edit
)
219 paths
= g_list_prepend(NULL
, full_path
);
220 action_mount(paths
, filer_window
== NULL
);
222 if (item
->flags
& ITEM_FLAG_MOUNTED
||
228 filer_change_to(filer_window
, full_path
, NULL
);
230 filer_opendir(full_path
, src_window
);
233 if ((item
->mime_type
== &special_exec
) && !edit
)
235 char *argv
[] = {NULL
, NULL
};
236 guchar
*dir
= filer_window
? filer_window
->path
241 if (spawn_full(argv
, dir
))
246 _("Failed to fork() child"));
251 return open_file(full_path
, edit
? &text_plain
254 delayed_rox_error(_("File doesn't exist, or I can't "
255 "access it: %s"), full_path
);
259 _("I don't know how to open '%s'"), full_path
);
264 /* Attempt to open this item */
265 gboolean
run_by_path(guchar
*full_path
)
270 /* XXX: Loads an image - wasteful */
271 diritem_stat(full_path
, &item
, FALSE
);
272 retval
= run_diritem(full_path
, &item
, NULL
, NULL
, FALSE
);
273 diritem_clear(&item
);
278 void show_item_help(guchar
*path
, DirItem
*item
)
280 switch (item
->base_type
)
283 if (item
->flags
& ITEM_FLAG_EXEC_FILE
)
284 delayed_error(_("Executable file"),
285 _("This is a file with an eXecute bit "
286 "set - it can be run as a program."));
288 delayed_error(_("File"), _(
289 "This is a data file. Try using the "
290 "Info menu item to find out more..."));
293 if (item
->flags
& ITEM_FLAG_MOUNT_POINT
)
294 delayed_error(_("Mount point"), _(
295 "A mount point is a directory which another "
296 "filing system can be mounted on. Everything "
297 "on the mounted filesystem then appears to be "
298 "inside the directory."));
300 dir_show_help(item
, path
);
302 case TYPE_CHAR_DEVICE
:
303 case TYPE_BLOCK_DEVICE
:
304 delayed_error(_("Device file"), _(
305 "Device files allow you to read from or write "
306 "to a device driver as though it was an "
310 delayed_error(_("Named pipe"), _(
311 "Pipes allow different programs to "
312 "communicate. One program writes data to the "
313 "pipe while another one reads it out again."));
316 delayed_error(_("Socket"), _(
317 "Sockets allow processes to communicate."));
320 delayed_error(_("Unknown type"), _(
321 "I couldn't find out what kind of file this "
322 "is. Maybe it doesn't exist anymore or you "
323 "don't have search permission on the directory "
329 /* Open a directory viewer showing this file, and wink it */
330 void open_to_show(guchar
*path
)
335 g_return_if_fail(path
!= NULL
);
337 dir
= g_strdup(path
);
338 slash
= strrchr(dir
, '/');
339 if (slash
== dir
|| !slash
)
341 /* Item in the root (or root itself!) */
342 new = filer_opendir("/", NULL
);
344 display_set_autoselect(new, dir
+ 1);
350 new = filer_opendir(dir
, NULL
);
352 display_set_autoselect(new, slash
+ 1);
358 /* Invoked using -x, this indicates that the filesystem has been modified
359 * and we should look at this item again.
361 void examine(guchar
*path
)
365 if (mc_stat(path
, &info
) != 0)
367 /* Deleted? Do a paranoid update of everything... */
368 filer_check_mounted(path
);
372 /* Update directory containing this item... */
373 dir_check_this(path
);
375 /* If this is itself a directory then rescan its contents... */
376 if (S_ISDIR(info
.st_mode
))
379 /* If it's on the pinboard, update the icon... */
380 icons_may_update(path
);
384 /****************************************************************
385 * INTERNAL FUNCTIONS *
386 ****************************************************************/
389 static void write_data(gpointer data
, gint fd
, GdkInputCondition cond
)
391 PipedData
*pd
= (PipedData
*) data
;
393 while (pd
->sent
< pd
->length
)
397 sent
= write(fd
, pd
->data
+ pd
->sent
, pd
->length
- pd
->sent
);
404 _("Could not send data to program: %s"),
413 gdk_input_remove(pd
->tag
);
419 /* Follow the link 'full_path' and display it in filer_window, or a
420 * new window if that is NULL.
422 static gboolean
follow_symlink(char *full_path
,
423 FilerWindow
*filer_window
,
424 FilerWindow
*src_window
)
428 char path
[MAXPATHLEN
+ 1];
431 got
= readlink(full_path
, path
, MAXPATHLEN
);
434 delayed_rox_error(_("Could not read link: %s"),
439 g_return_val_if_fail(got
<= MAXPATHLEN
, FALSE
);
442 /* Make a relative path absolute */
446 slash
= strrchr(full_path
, '/');
447 g_return_val_if_fail(slash
!= NULL
, FALSE
);
449 tmp
= g_strndup(full_path
, slash
- full_path
);
450 real
= pathdup(make_path(tmp
, path
)->str
);
451 /* NB: full_path may be invalid here... */
455 real
= pathdup(path
);
457 slash
= strrchr(real
, '/');
462 _("Broken symlink (or you don't have permission "
463 "to follow it): %s"), full_path
);
475 filer_change_to(filer_window
, new_dir
, slash
+ 1);
480 new = filer_opendir(new_dir
, src_window
);
481 display_set_autoselect(new, slash
+ 1);
489 /* Load this file into an appropriate editor */
490 static gboolean
open_file(guchar
*path
, MIME_type
*type
)
492 g_return_val_if_fail(type
!= NULL
, FALSE
);
494 if (type_open(path
, type
))
498 _("No run action specified for files of this type (%s/%s) - "
499 "you can set a run action by choosing `Set Run Action' "
500 "from the File menu, or you can just drag the file to an "
508 /* Show the help for a directory - tries to open App/Help, but if
509 * that doesn't work then it displays a default message.
511 static void dir_show_help(DirItem
*item
, char *path
)
516 help_dir
= g_strconcat(path
, "/Help", NULL
);
518 if (mc_stat(help_dir
, &info
) == 0)
519 filer_opendir(help_dir
, NULL
);
520 else if (item
->flags
& ITEM_FLAG_APPDIR
)
521 delayed_error(_("Application"),
522 _("This is an application directory - you can "
523 "run it as a program, or open it (hold down "
524 "Shift while you open it). Most applications provide "
525 "their own help here, but this one doesn't."));
527 delayed_error(_("Directory"), _(
528 "This is a directory. It contains an index to "
529 "other items - open it to see the list."));