#include #include #include #include #include #include #include /** * NOTE: requires fdescfs to be mounted to run interpreted files (starting with #!) */ #define DEFAULT_FD 3 char *args[] = { "batchrun", NULL }; void set_async(int fd, int on) { int flags; if ((flags = fcntl(fd, F_GETFL)) == -1) err(1, "fcntl()"); if (on) { flags |= O_NONBLOCK; } else { flags &= ~O_NONBLOCK; } if (fcntl(fd, F_SETFL, flags) == -1) err(1, "fcntl()"); } int main(int argc, char **argv) { char buf[2], *end = NULL; ssize_t ret; int tries = 0, fd = DEFAULT_FD; if (argc > 1) { fd = strtol(argv[1], &end, 10); if (end == argv[1]) errx(1, "Filedescriptor supplied (\"%s\") is not a number", argv[1]); } set_async(fd, 1); retry: if (tries++ >= 3) errx(1, "Failed to read file header"); ret = pread(fd, buf, sizeof(buf), 0); if (ret == 2) { if (strncmp(buf, "#!", 2) != 0) { fcntl(fd, F_SETFD, FD_CLOEXEC); } } else if (ret == -1) { if (errno == EINTR) goto retry; else if (errno != EAGAIN) err(1, "pread()"); } else if (ret != 0) { goto retry; } set_async(fd, 0); fexecve(fd, args, NULL); err(1, "fexecve()"); }