X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=zpm-runscript.c;fp=zpm-runscript.c;h=e6b1af50f51d97c146c361945488fc50cca4a2ed;hb=0187a28d81a65b5b92c6c2dbaacce07d6277ba33;hp=0000000000000000000000000000000000000000;hpb=45a98e17c91c5617328859416de44fed8298f295;p=zpackage diff --git a/zpm-runscript.c b/zpm-runscript.c new file mode 100644 index 0000000..e6b1af5 --- /dev/null +++ b/zpm-runscript.c @@ -0,0 +1,185 @@ +#define _POSIX_C_SOURCE 200809L + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +#include "zpm.h" + +/* + * -f package file, otherwise localdb + * -p phase, defaults to 'configure' + * -s script name, defaults to /var/tmp/zpm-script + * -r chroot to directory + * -o script output, /var/tmp/zpm-script.out, '-' for stdout + * + * arg is package id + */ + +void usage(void) { + fprintf(stderr, "usage: db hash file\n"); +} + +int run(char *program, char **args, char *output, int *status) { + /* if stdout is a terminal, leave stdout where it goes, + * if it's not a terminal, redirect stdout to output. + * in either case, send stderr to output, unless null + * if output is null, just run the program + */ + int interactive = 0; + pid_t pid; + int rv; + + errno = 0; + + interactive = isatty(1); + + pid = fork(); + + if (pid == -1) { + *status = 1; + return -1; + } + + if (pid == 0) { + /* child */ + if (output) { + close(2); + rv = open(output, O_NOFOLLOW|O_TRUNC|O_CREAT|O_WRONLY, + 0600); + if (rv == -1) { + perror("cannot open output file"); + } + if (!interactive) { + rv = dup2(2,1); + if (rv == -1) { + perror("unable to redirect stdout"); + exit(EXIT_FAILURE); + } + } + } + + rv = execvp(program, args); + if (rv == -1) { + perror("cannot exec"); + exit(EXIT_FAILURE); + } + } + + pid = wait(status); + if (pid == -1) { + perror("error waiting for child"); + return -2; + } + + if (WIFEXITED(*status)) { + return WEXITSTATUS(*status); + } + + return -3; +} + +int main(int ac, char **av){ + struct zpm zpm; + int rv; + int status; + int failures = 0; + char *pkgstr; + int opt; + + char hash[ZPM_HASH_STRLEN+1]; + char *args[3]; + char *pkgid; + + char *chroot = 0; + char *db = "/var/lib/zpm/zpm.db"; + char *script = "/var/tmp/zpm-script"; + char *output = "/var/tmp/zpm-script.out"; + char *phase = "configure"; + + if (getenv("ZPMDB")) { + db = getenv("ZPMDB"); + } + /* ZPM_PACKAGE_FILE ? */ + + while ((opt = getopt(ac, av, "f:p:s:r:")) != -1) { + switch (opt) { + case 'f': db = optarg; + break; + case 'p': phase = optarg; + break; + case 's': script = optarg; + break; + case 'r': chroot = optarg; + break; + default: + usage(); + exit(EXIT_FAILURE); + break; + } + } + int argn = optind; + + if (argn >= ac) { + usage(); + exit(EXIT_FAILURE); + } + + pkgstr = av[argn]; + + if (!zpm_open(&zpm, db)) { + fprintf(stderr, "unable to open zpm database: %s\n", db); + if (zpm.errmsg) { + fprintf(stderr, "error detail: %s\n", zpm.errmsg); + } + exit(EXIT_FAILURE); + } + + pkgid = zpm_findpkg(&zpm, pkgstr); + if (pkgid) { + if (zpm_script_hash(&zpm, pkgid, phase, hash)) { + rv = zpm_extract(&zpm, hash, script, 0700); + + /* perhaps also pass in the phase name? or ENV? */ + /* TODO sanitize environment ? */ + args[0] = script; + args[1] = pkgid; + args[2] = 0; + if (chroot) { + fprintf(stderr, "failing to chroot %s\n", chroot); + } + rv = run(script, args, output, &status); + if (rv) { + // cat(output); + fprintf(stderr, "package %s script failed with code %d\n", + pkgid, rv); + } + /* TODO log output */ + unlink(script); + unlink(output); + if (rv) { + failures++; + } + } else { + fprintf(stderr, "no script for %s %s\n", phase, pkgid); + failures++; + } + free(pkgid); + } else { + fprintf(stderr, "unable to find package for %s in %s\n", + pkgstr, db); + failures++; + } + + zpm_close(&zpm); + + return failures ? EXIT_FAILURE : EXIT_SUCCESS; +}