+++ /dev/null
-#define _POSIX_C_SOURCE 200809L
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <sys/mman.h>
-
-#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: zpm script ...\n");
-}
-
-int setdir(char *rootdir) {
- if (chdir(rootdir ? rootdir : "/") == -1) {
- perror("can not chdir to rootdir");
- return 0;
- }
-#if 0
- if (rootdir && strcmp(rootdir, "/")) {
- if (geteuid() == 0) {
- /* chroot is deprecated, and not in posix. need to use
- * OS/kernel specific code.
- */
- fprintf(stderr, "support for chroot equivalent not supported on this OS\n");
- } else {
- fprintf(stderr, "unable to chroot as non root user\n");
- }
- }
-#endif
- return 1;
-}
-
-
-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 or "-", 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 && strcmp(output, "-") != 0) {
- 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;
-}
-
-#define RUN 1
-#define SET 2
-#define LIST 3
-
-#define SOFT 1
-#define HARD 2
-
-static int list_scripts(void *ud, const char *pkg, const char *stage,
- const char *hash) {
- printf("%s %s %.8s\n", pkg, stage, hash);
- return 0;
-}
-
-int main(int ac, char **av){
- struct zpm zpm;
- int rv;
- int status;
- int required = 0;
- int fail = 0;
- char *pkgstr;
- int opt;
-
- char hash[ZPM_HASH_STRLEN+1];
- char *args[4];
- char *pkgid;
-
- char *rootdir = 0;
- char *db = "/var/lib/zpm/local.db";
- char *script = "/var/tmp/zpm-script";
- char *output = "/var/tmp/zpm-script.out";
- char *phase = 0;
- char *envvar = 0;
- int quiet = 0;
- int scriptishash = 0;
- int mode = RUN;
-
- if (getenv("ZPMDB")) {
- db = getenv("ZPMDB");
- }
- /* ZPM_PACKAGE_FILE ? */
-
- rootdir = getenv("ZPM_ROOT_DIR");
-
- envvar = getenv("ZPM_SCRIPT_FILE");
- if (envvar) {
- script = envvar;
- }
-
- envvar = getenv("ZPM_SCRIPT_OUTPUT");
- if (envvar) {
- output = envvar;
- }
-
- /* run, set, show, hash */
- /* set -S, if -H set the hash, output hash, unless quiet
- * show: -o, or stdout,
- * All modes: [-f pkgfile] default to zpmdb
- * All modes: [-p phase], default to configure
- * All modes: [-R rootdir], chdir, attempt to chroot
- * All modes: [-N], required, error if no such script
- *
- * run: zpm-script -r -p foo <pkgid args...>
- * set: zpm-script -s <pkgid [script]>
- * set: zpm-script -s -h <pkgid [hash]>
- * show: zpm-script -l [-a] [-o outfile] <pkgid>
- * show hash: zpm-script -lh <pkgid>
- */
- while ((opt = getopt(ac, av, "f:p:rslRFho:S:q")) != -1) {
- switch (opt) {
- case 'f': db = optarg; break;
- case 'p': phase = optarg; break;
- case 'r': mode = RUN; break;
- case 's': mode = SET; break;
- case 'l': mode = LIST; break;
- case 'R': rootdir = optarg; break;
- case 'F': required = 1; break;
-
- case 'h': scriptishash = 1; break;
- case 'o': output = optarg; break;
- case 'S': script = optarg; break;
- case 'q': quiet = 1; break;
-
- default:
- usage();
- exit(EXIT_FAILURE);
- break;
- }
- }
- int argn = optind;
-
- if (argn >= ac) {
- usage();
- exit(EXIT_FAILURE);
- }
-
- 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);
- }
-
- /* first non option arg is always a package id */
- pkgstr = av[argn];
- pkgid = zpm_findpkg(&zpm, pkgstr, NULL);
-
- if (!pkgid) {
- fprintf(stderr, "no package for %s\n", pkgstr);
- zpm_close(&zpm);
- exit(EXIT_FAILURE);
- }
-
- argn++;
-
- if (mode == SET) {
- char *sethash = 0;
- char *setscript = 0;
- int rv = 0;
-
- if (!phase) {
- phase = "configure";
- }
-
- if (argn < ac) {
- if (scriptishash) {
- sethash = av[argn];
- } else {
- setscript = av[argn];
- }
- }
-
- if (setscript) {
- rv = zpm_import(&zpm,setscript,0,hash);
- if (!rv) {
- fprintf(stderr, "unable to import %s\n",
- setscript);
- fail = HARD;
- } else {
- sethash = hash;
- }
- }
-
- if (!fail && !zpm_script_set(&zpm,pkgid,phase,sethash)) {
- fprintf(stderr, "unable to set %s script hash %s\n",
- pkgid,
- sethash ? sethash : "null");
- fprintf(stderr, "zpm error: %s\n", zpm.errmsg);
- fail = HARD;
- }
- } else if (mode == LIST) {
- if (!phase) {
- zpm_foreach_script(&zpm, pkgid, phase, 0, list_scripts);
- } else if (!zpm_script_hash(&zpm, pkgid, phase, hash)) {
- fail = SOFT;
- } else if (scriptishash) {
- if (!quiet) {
- printf("%s\n", hash);
- }
- } else {
- if (!output) {
- output = "-";
- }
- if (!zpm_extract(&zpm, hash, output, 0700)) {
- fail = HARD;
- }
- }
- } else {
- /* run a script */
- if (!phase) {
- phase = "configure";
- }
-
- if (!output) {
- output = "/var/tmp/zpm-script.out";
- }
-
- if (!script) {
- script = "/var/tmp/zpm-script";
- }
-
- /* since the script file name doesn't really
- * mean anything, pass in the phase as arg 0
- */
- /* TODO sanitize environment ? */
- args[0] = phase;
- args[1] = pkgid;
- args[2] = 0;
- args[3] = 0;
-
- if (argn <= ac) {
- args[2] = av[argn];
- }
-
- if (!zpm_script_hash(&zpm, pkgid, phase, hash)) {
- fail = SOFT;
- goto cleanup;
- }
-
- if (!setdir(rootdir)) {
- fail = HARD;
- goto cleanup;
- }
-
- if (!zpm_extract(&zpm, hash, script, 0700)) {
- fprintf(stderr, "unable to extract script");
- fail = HARD;
- zpm_note_add(&zpm, pkgid, NULL, hash, "unable to extract %s script", phase);
- goto cleanup;
- }
-
- rv = run(script, args, output, &status);
- if (rv) {
- fprintf(stderr, "package %s script failed with code %d\n",
- pkgid, rv);
-
- zpm_import(&zpm, output, 0, hash);
- zpm_note_add(&zpm, pkgid, NULL, hash, "package %s script failed with code %d", phase, rv);
-
- fail = HARD;
- }
-
- /* TODO log output */
- if (script) {
- unlink(script);
- }
- if (output) {
- unlink(output);
- }
- }
-
-cleanup:
- free(pkgid);
- zpm_close(&zpm);
-
- return (fail == HARD || (required && fail)) ? EXIT_FAILURE : 0;
-}