r215: Made some changes to allow compilation on IRIX.
[rox-filer.git] / ROX-Filer / src / run.c
blobf79253afbf175119f58c290604d28cafa51f8ffc
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2000, 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 "config.h"
26 #include <sys/stat.h>
27 #include <errno.h>
29 #include "stdlib.h"
30 #include "support.h"
31 #include "gui_support.h"
32 #include "filer.h"
33 #include "menu.h"
34 #include "main.h"
36 /* Static prototypes */
37 static void write_data(gpointer data, gint fd, GdkInputCondition cond);
39 typedef struct _PipedData PipedData;
41 struct _PipedData
43 guchar *data;
44 gint tag;
45 gulong sent;
46 gulong length;
50 /****************************************************************
51 * EXTERNAL INTERFACE *
52 ****************************************************************/
55 /* An application has been double-clicked (or run in some other way) */
56 void run_app(char *path)
58 GString *apprun;
59 char *argv[] = {NULL, NULL};
61 apprun = g_string_new(path);
62 argv[0] = g_string_append(apprun, "/AppRun")->str;
64 if (!spawn_full(argv, home_dir))
65 report_error("ROX-Filer", "Failed to fork() child process");
67 g_string_free(apprun, TRUE);
70 /* Execute this program, passing all the URIs in the list as arguments.
71 * URIs that are files on the local machine will be passed as simple
72 * pathnames. The uri_list should be freed after this function returns.
74 void run_with_files(char *path, GSList *uri_list)
76 char **argv;
77 int argc = 0;
78 struct stat info;
80 if (stat(path, &info))
82 delayed_error("ROX-Filer", "Program not found - deleted?");
83 return;
86 argv = g_malloc(sizeof(char *) * (g_slist_length(uri_list) + 2));
88 if (S_ISDIR(info.st_mode))
89 argv[argc++] = make_path(path, "AppRun")->str;
90 else
91 argv[argc++] = path;
93 while (uri_list)
95 char *uri = (char *) uri_list->data;
96 char *local;
98 local = get_local_path(uri);
99 if (local)
100 argv[argc++] = local;
101 else
102 argv[argc++] = uri;
103 uri_list = uri_list->next;
106 argv[argc++] = NULL;
108 if (!spawn_full(argv, home_dir))
109 delayed_error("ROX-Filer", "Failed to fork() child process");
112 /* Run the program as '<path> -', piping the data to it via stdin.
113 * You can g_free() the data as soon as this returns.
115 void run_with_data(char *path, gpointer data, gulong length)
117 char *argv[] = {NULL, "-", NULL};
118 struct stat info;
119 int fds[2];
120 PipedData *pd;
122 if (stat(path, &info))
124 delayed_error("ROX-Filer", "Program not found - deleted?");
125 return;
128 if (S_ISDIR(info.st_mode))
129 argv[0] = make_path(path, "AppRun")->str;
130 else
131 argv[0] = path;
133 if (pipe(fds))
135 delayed_error("pipe() failed", g_strerror(errno));
136 return;
138 close_on_exec(fds[1], TRUE);
139 close_on_exec(fds[0], TRUE);
141 switch (fork())
143 case -1:
144 delayed_error("fork() failed", g_strerror(errno));
145 close(fds[1]);
146 break;
147 case 0:
148 /* We are the child */
149 chdir(home_dir);
150 dup2(to_error_log, STDERR_FILENO);
151 close_on_exec(STDERR_FILENO, FALSE);
152 if (dup2(fds[0], 0) == -1)
153 g_warning("dup2() failed: %s\n",
154 g_strerror(errno));
155 else
157 close_on_exec(0, FALSE);
158 if (execv(argv[0], argv))
159 g_warning("execv(%s) failed: %s\n",
160 argv[0], g_strerror(errno));
162 _exit(1);
163 default:
164 /* We are the parent */
165 set_blocking(fds[1], FALSE);
166 pd = g_new(PipedData, 1);
167 pd->data = g_malloc(length);
168 memcpy(pd->data, data, length);
169 pd->length = length;
170 pd->sent = 0;
171 pd->tag = gdk_input_add(fds[1], GDK_INPUT_WRITE,
172 write_data, pd);
173 break;
176 close(fds[0]);
180 /****************************************************************
181 * INTERNAL FUNCTIONS *
182 ****************************************************************/
185 static void write_data(gpointer data, gint fd, GdkInputCondition cond)
187 PipedData *pd = (PipedData *) data;
189 while (pd->sent < pd->length)
191 int sent;
193 sent = write(fd, pd->data + pd->sent, pd->length - pd->sent);
195 if (sent < 0)
197 if (errno == EAGAIN)
198 return;
199 delayed_error("ROX-Filer - Sending data to program",
200 g_strerror(errno));
201 goto finish;
204 pd->sent += sent;
207 finish:
208 gdk_input_remove(pd->tag);
209 g_free(pd->data);
210 g_free(pd);
211 close(fd);