4 * Copyright (c) Tuomo Valkonen 1999-2009.
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
);