pexec

execute a program from standard input
git clone git://git.2f30.org/pexec.git
Log | Files | Refs

commit 599ecdb2636f77f0f13135adadece6c3778081ea
Author: sin <sin@2f30.org>
Date:   Fri, 23 Mar 2018 11:20:49 +0000

Initial commit

Diffstat:
pexec.c | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 113 insertions(+), 0 deletions(-)

diff --git a/pexec.c b/pexec.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2018 Dimitris Papastamos <sin@2f30.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * execute a program from stdin + * + * example: pexec /bin/ls -la /tmp < /bin/ls + * + * This is true cloud computing! + */ + +#include <sys/syscall.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +static int +memfd_create(const char *name, unsigned int flags) +{ + return syscall(__NR_memfd_create, name, flags); +} + +static ssize_t +xread(int fd, void *buf, size_t nbytes) +{ + unsigned char *bp = buf; + ssize_t total = 0; + + while (nbytes > 0) { + ssize_t n; + + n = read(fd, &bp[total], nbytes); + if (n < 0) + err(1, "read"); + else if (n == 0) + return total; + total += n; + nbytes -= n; + } + return total; +} + +static ssize_t +xwrite(int fd, const void *buf, size_t nbytes) +{ + const unsigned char *bp = buf; + ssize_t total = 0; + + while (nbytes > 0) { + ssize_t n; + + n = write(fd, &bp[total], nbytes); + if (n < 0) + err(1, "write"); + else if (n == 0) + return total; + total += n; + nbytes -= n; + } + return total; +} + +static void +pexec(int fd, int argc, char *argv[]) +{ + extern char **environ; + + argc--, argv++; + if (fexecve(fd, argv, environ) < 0) + err(1, "fexecve"); +} + +static void +usage(void) +{ + fprintf(stderr, "usage: pexec argv[0] [argv[1]...]\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char buf[BUFSIZ]; + ssize_t n; + int fd; + + if (argc < 2) + usage(); + + fd = memfd_create("exec", 0); + if (fd < 0) + err(1, "memfd_create"); + + while ((n = xread(STDIN_FILENO, buf, BUFSIZ)) > 0) + xwrite(fd, buf, n); + + pexec(fd, argc, argv); + /* unreachable */ +}