4 * Copyright (c) Tuomo Valkonen 1999-2007.
6 * See the included file LICENSE for details.
10 #include <sys/types.h>
11 #include <sys/signal.h>
21 #include <libtu/output.h>
22 #include <libtu/misc.h>
23 #include <libtu/locale.h>
24 #include <libtu/types.h>
30 /*{{{ Exec/spawn/fork */
32 #define SHELL_PATH "/bin/sh"
33 #define SHELL_NAME "sh"
34 #define SHELL_ARG "-c"
37 void mainloop_do_exec(const char *cmd)
43 argv[2]=(char*)cmd; /* stupid execve... */
45 execvp(SHELL_PATH, argv);
49 static int mypipe(int *fds)
53 cloexec_braindamage_fix(fds[0]);
54 cloexec_braindamage_fix(fds[1]);
56 warn_err_obj("pipe()");
62 static bool unblock(int fd)
64 int fl=fcntl(fd, F_GETFL);
66 fl=fcntl(fd, F_SETFL, fl|O_NONBLOCK);
71 static void duppipe(int fd, int idx, int *fds)
80 pid_t mainloop_fork(void (*fn)(void *p), void *fnp,
81 int *infd, int *outfd, int *errfd)
111 if(!unblock(outfds[0]))
118 if(!unblock(errfds[0]))
133 duppipe(0, 0, infds);
135 duppipe(1, 1, outfds);
137 duppipe(2, 1, errfds);
165 void (*initenv)(void *p);
170 static void do_spawn(void *spawnp)
172 SpawnP *p=(SpawnP*)spawnp;
175 p->initenv(p->initenvp);
176 mainloop_do_exec(p->cmd);
180 pid_t mainloop_do_spawn(const char *cmd,
181 void (*initenv)(void *p), void *p,
182 int *infd, int *outfd, int *errfd)
187 spawnp.initenv=initenv;
190 return mainloop_fork(do_spawn, (void*)&spawnp, infd, outfd, errfd);
194 pid_t mainloop_spawn(const char *cmd)
196 return mainloop_do_spawn(cmd, NULL, NULL, NULL, NULL, NULL);
203 /*{{{ popen_bgread */
208 bool mainloop_process_pipe_extlfn(int fd, ExtlFn fn)
213 n=read(fd, buf, BL-1);
215 if(errno==EAGAIN || errno==EINTR)
218 warn_err_obj(TR("reading a pipe"));
222 extl_call(fn, "s", NULL, &buf);
225 /* Call with no argument/NULL string to signify EOF */
226 extl_call(fn, NULL, NULL);
232 static void process_pipe(int fd, void *p)
234 if(!mainloop_process_pipe_extlfn(fd, *(ExtlFn*)p)){
235 /* We get here on EOL or if the handler failed */
236 mainloop_unregister_input_fd(fd);
238 extl_unref_fn(*(ExtlFn*)p);
244 bool mainloop_register_input_fd_extlfn(int fd, ExtlFn fn)
246 ExtlFn *p=ALLOC(ExtlFn);
248 *(ExtlFn*)p=extl_ref_fn(fn);
249 if(mainloop_register_input_fd(fd, p, process_pipe))
251 extl_unref_fn(*(ExtlFn*)p);
258 pid_t mainloop_popen_bgread(const char *cmd,
259 void (*initenv)(void *p), void *p,
260 ExtlFn handler, ExtlFn errhandler)
264 ExtlFn none=extl_fn_none();
266 pid=mainloop_do_spawn(cmd, initenv, p, NULL,
267 (handler!=none ? &fd : NULL),
268 (errhandler!=none ? &errfd : NULL));
272 if(!mainloop_register_input_fd_extlfn(fd, handler))
275 if(errhandler!=extl_fn_none()){
276 if(!mainloop_register_input_fd_extlfn(errfd, errhandler))
298 void cloexec_braindamage_fix(int fd)
300 fcntl(fd, F_SETFD, FD_CLOEXEC);