/* $Header: /CVSROOT/debris/drisexec.h,v 1.5 2005/08/15 01:04:52 tino Exp $ * * DebRIS: DEBian Remote Install Scripter * invokation of other processes * * $Log: drisexec.h,v $ * Revision 1.5 2005/08/15 01:04:52 tino * all functions now have a prefix (dris_) * * Revision 1.4 2005/08/13 22:59:12 tino * additional functions, see ChangeLog * * Revision 1.3 2005/07/25 03:22:19 tino * extended * * Revision 1.2 2005/07/24 22:17:46 tino * using snprintf instead of sprintf. * printf replaced by info * * Revision 1.1 2005/06/01 02:12:34 tino * first version. As SirbeD is missing, this just does nothing yet. */ #define FORK_MAXARGS 100 static void printer(const char *buf, size_t len) { int pos; for (pos=0; poslen; dris_buf_printf(config.out, s, list); printer(config.out->buf+old, config.out->len-old); } static void dris_out(const char *s, ...) { va_list list; va_start(list, s); dris_vout(s, list); va_end(list); } static void dris_exec2(char *arg0, char *cmd) { char *args[FORK_MAXARGS]; int i; for (i=0; (args[i++]=dris_nextarg(&cmd))!=0 && cmd && ibuf); if ((chld=fork())==0) { /* assign stdout */ if (fd!=1) dup2(fd, 1); if (fd>1) close(fd); /* assign stdin */ snprintf(tmp, sizeof tmp, "/tmp/debris.%lu.in.tmp", config.pid); if ((fd=open(tmp, O_CREAT|O_TRUNC|O_RDWR, 0600))<0) dris_ex("fork: cannot create stdin %s", tmp); if (config.in->len > config.data) dris_writeall(fd, config.in->buf+config.data, config.in->len-config.data); if (lseek(fd, 0, SEEK_SET)) dris_ex("fork: cannot rewind (lseek 0) %s", tmp); if (fd) dup2(fd, 0); if (fd>1) close(fd); /* run */ dris_exec(config.in->buf); dris_ex("fork: cannot exec %s", config.in->buf); } dris_info2("[%lu] child: %d\n", config.pid, (long)chld); if (chld==(pid_t)-1) { dris_err("cannot fork %s", config.in->buf); close(fd); return 0; } config.fd = fd; return chld; } static int waitfor(pid_t chld) { if (!chld || chld==(pid_t)-1) return -1; if (!config.verbose && config.fd>=0) { close(config.fd); config.fd = -1; } for (;;) { pid_t pid; int retval; alarm(1); pid = waitpid((pid_t)0, &retval, 0); alarm(0); if (pid==chld) { if (WIFEXITED(retval)) return WEXITSTATUS(retval); if (WIFSIGNALED(retval)) { dris_info("-> signal %d\n", WTERMSIG(retval)); return -2; } else if (WIFSTOPPED(retval)) dris_info("-> jobcontrol %d\n", WSTOPSIG(retval)); else { dris_info("-> unknown reason %d\n", retval); return -3; } } if (config.fd>=0) { char buf[BUFSIZ]; int got; if ((got=read(config.fd, buf, sizeof buf))==0) continue; if (got>0) printer(buf, got); else if (errno!=EINTR && errno!=EAGAIN) { close(config.fd); config.fd = -1; } } } }