r208: Added Bernard Jungen's patch:
[rox-filer.git] / ROX-Filer / src / run.c
blob3b23142f96be6f1c1a94716949b8f425db16cd06
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 1999, Thomas Leonard, <tal197@ecs.soton.ac.uk>.
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)
10 * any later version.
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
15 * more details.
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
22 /* run.c */
24 #include <sys/stat.h>
25 #include <errno.h>
27 #include "stdlib.h"
28 #include "support.h"
29 #include "gui_support.h"
30 #include "filer.h"
31 #include "menu.h"
32 #include "main.h"
34 /* Static prototypes */
35 static void write_data(gpointer data, gint fd, GdkInputCondition cond);
37 typedef struct _PipedData PipedData;
39 struct _PipedData
41 gpointer data;
42 gint tag;
43 gulong sent;
44 gulong length;
48 /****************************************************************
49 * EXTERNAL INTERFACE *
50 ****************************************************************/
53 /* An application has been double-clicked (or run in some other way) */
54 void run_app(char *path)
56 GString *apprun;
57 char *argv[] = {NULL, NULL};
59 apprun = g_string_new(path);
60 argv[0] = g_string_append(apprun, "/AppRun")->str;
62 if (!spawn_full(argv, home_dir))
63 report_error("ROX-Filer", "Failed to fork() child process");
65 g_string_free(apprun, TRUE);
68 /* Execute this program, passing all the URIs in the list as arguments.
69 * URIs that are files on the local machine will be passed as simple
70 * pathnames. The uri_list should be freed after this function returns.
72 void run_with_files(char *path, GSList *uri_list)
74 char **argv;
75 int argc = 0;
76 struct stat info;
78 if (stat(path, &info))
80 delayed_error("ROX-Filer", "Program not found - deleted?");
81 return;
84 argv = g_malloc(sizeof(char *) * (g_slist_length(uri_list) + 2));
86 if (S_ISDIR(info.st_mode))
87 argv[argc++] = make_path(path, "AppRun")->str;
88 else
89 argv[argc++] = path;
91 while (uri_list)
93 char *uri = (char *) uri_list->data;
94 char *local;
96 local = get_local_path(uri);
97 if (local)
98 argv[argc++] = local;
99 else
100 argv[argc++] = uri;
101 uri_list = uri_list->next;
104 argv[argc++] = NULL;
106 if (!spawn_full(argv, home_dir))
107 delayed_error("ROX-Filer", "Failed to fork() child process");
110 /* Run the program as '<path> -', piping the data to it via stdin.
111 * You can g_free() the data as soon as this returns.
113 void run_with_data(char *path, gpointer data, gulong length)
115 char *argv[] = {NULL, "-", NULL};
116 struct stat info;
117 int fds[2];
118 PipedData *pd;
120 if (stat(path, &info))
122 delayed_error("ROX-Filer", "Program not found - deleted?");
123 return;
126 if (S_ISDIR(info.st_mode))
127 argv[0] = make_path(path, "AppRun")->str;
128 else
129 argv[0] = path;
131 if (pipe(fds))
133 delayed_error("pipe() failed", g_strerror(errno));
134 return;
136 close_on_exec(fds[1], TRUE);
137 close_on_exec(fds[0], TRUE);
139 switch (fork())
141 case -1:
142 delayed_error("fork() failed", g_strerror(errno));
143 close(fds[1]);
144 break;
145 case 0:
146 /* We are the child */
147 chdir(home_dir);
148 dup2(to_error_log, STDERR_FILENO);
149 close_on_exec(STDERR_FILENO, FALSE);
150 if (dup2(fds[0], 0) == -1)
151 g_warning("dup2() failed: %s\n",
152 g_strerror(errno));
153 else
155 close_on_exec(0, FALSE);
156 if (execv(argv[0], argv))
157 g_warning("execv(%s) failed: %s\n",
158 argv[0], g_strerror(errno));
160 _exit(1);
161 default:
162 /* We are the parent */
163 set_blocking(fds[1], FALSE);
164 pd = g_new(PipedData, 1);
165 pd->data = g_malloc(length);
166 memcpy(pd->data, data, length);
167 pd->length = length;
168 pd->sent = 0;
169 pd->tag = gdk_input_add(fds[1], GDK_INPUT_WRITE,
170 write_data, pd);
171 break;
174 close(fds[0]);
178 /****************************************************************
179 * INTERNAL FUNCTIONS *
180 ****************************************************************/
183 static void write_data(gpointer data, gint fd, GdkInputCondition cond)
185 PipedData *pd = (PipedData *) data;
187 while (pd->sent < pd->length)
189 int sent;
191 sent = write(fd, pd->data + pd->sent, pd->length - pd->sent);
193 if (sent < 0)
195 if (errno == EAGAIN)
196 return;
197 delayed_error("ROX-Filer - Sending data to program",
198 g_strerror(errno));
199 goto finish;
202 pd->sent += sent;
205 finish:
206 gdk_input_remove(pd->tag);
207 g_free(pd->data);
208 g_free(pd);
209 close(fd);