From: Nathan Wagner Date: Tue, 11 Sep 2018 10:57:01 +0000 (+0000) Subject: add program to run a command for each package file X-Git-Tag: v0.1.6~54 X-Git-Url: https://pd.if.org/git/?p=zpackage;a=commitdiff_plain;h=c5dc5d419b273de4b95acbf5e9aeeee370531157 add program to run a command for each package file --- diff --git a/.gitignore b/.gitignore index cf56615..94ec018 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ elftype *.a uncompress zpm-addfile +zpm-foreach-path zpm-vercmp zpm-extract zpm-init diff --git a/zpm-foreach-path.c b/zpm-foreach-path.c new file mode 100644 index 0000000..30340a0 --- /dev/null +++ b/zpm-foreach-path.c @@ -0,0 +1,283 @@ +#define _POSIX_C_SOURCE 2 +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "sqlite3.h" +#include "zpm.h" + +struct config { + char *dbfile; + char *cmd; + char *program; + char *pkgid; + char *nullstr; + int errcontinue; + int errors; + int (*callback)(void*,int,char**,char**); +}; + +static void usage() { + printf("usage: ...\n"); +} + +static int run_program(void *f, int ncols, char **vals, char **cols) { + struct config *conf = f; + int i; + char *argv[ncols+1]; + pid_t pid; + int status; + int rv; + + argv[0] = conf->program; + + for (i=0;inullstr; + } + argv[i+1] = 0; + + pid = fork(); + + if (pid == -1) { + perror("cannot fork"); + return 1; + } + + if (pid == 0) { + /* child */ + rv = execvp(conf->program, argv); + if (rv == -1) { + perror("cannot exec"); + exit(EXIT_FAILURE); + } + } + + rv = wait(&status); + if (rv == -1) { + perror("error waiting for child"); + exit(EXIT_FAILURE); + } + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + return 0; + } else if (conf->errcontinue) { + conf->errors++; + return 0; + } + return 1; +} + +static int run_shell(void *f, int ncols, char **vals, char **cols) { + struct config *conf = f; + int i; + char *argv[ncols+4]; + pid_t pid; + int status; + int rv; + + argv[0] = "sh"; + argv[1] = "-c"; + argv[2] = conf->cmd; + argv[3] = "sh"; + + for (i=0;inullstr; + } + argv[i+4] = 0; + + pid = fork(); + + if (pid == -1) { + perror("cannot fork"); + return 1; + } + + if (pid == 0) { + /* child */ + rv = execvp("sh", argv); + if (rv == -1) { + perror("cannot exec"); + exit(EXIT_FAILURE); + } + } + + rv = wait(&status); + if (rv == -1) { + perror("error waiting for child"); + } + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + return 0; + } else if (conf->errcontinue) { + conf->errors++; + return 0; + } + return 1; +} + +static int printpaths(void *f, int ncols, char **vals, char **cols) { + + /* suppress unused warnings */ + + if (ncols < 4) { + fprintf(stderr, "can't find path names\n"); + return 1; + } +// printf("path cols %d %p %p\n", ncols, vals, cols); + fprintf(stdout, "%s\n", vals[3]); +#if 0 + cols = 0; + f = 0; + int i; + if (cols == 0) { + fprintf(stderr, "sqlite can't get column names\n"); + } + for (i=0;i3) fprintf(out, "\t"); + fprintf(stdout, "%s\n", vals[i]); + } +#endif + return 0; +} + +void parse_package(char *pstr, char *name, char *ver, int *rel) { + if (name) *name = 0; + if (ver) *ver = 0; + if (rel) *rel = -1; + + /* string - ver - rel */ + /* rel is all digits */ + /* possible forms: + * ^(.+)-([0-9][^-]*)-([\d+])$ + * ^(.+)-([0-9][^-]*)$ + * ^(.+)$ + * The main problem in parsing is that the package name itself + * can contain a '-', so you can't just split on '-' + * Also, the version can be just digits. + */ + + /* everything up to the first '-' is in the name */ + while (*pstr) { + if (*pstr == '-' && isdigit(*(pstr+1))) { + break; + } + if (name) { + *name++ = *pstr; + } + pstr++; + } + if (name) *name = 0; + if (*pstr == '-') { + pstr++; + } + while (*pstr && *pstr != '-') { + if (ver) { + *ver++ = *pstr; + } + pstr++; + } + if (ver) *ver = 0; + if (*pstr == '-') { + pstr++; + } + if (rel && *pstr) { + *rel = atoi(pstr); + } +} + +#ifdef PATH_MAX +#define PATHLEN PATH_MAX +#else +#define PATHLEN 4096 +#endif + +int main(int ac, char **av){ + struct zpm pkg; + char *s; + int opt; + + struct config conf = { "/var/lib/db.zpm", 0, 0, 0, "", 0, 0, printpaths + }; + + + if ((s = getenv("ZPMDB"))) { + /* TODO does this need to be copied ? */ + conf.dbfile = s; + } + + /* + * -c 'shell command' + * -f 'package database', otherwise regular default of env ZPMDB, + * or /var/lib/zpm/zpm.db, or die + * + * arg 1: pkgid triple, but will do a pkg find + * arg 2: program to run. equivalent of 'printf "%s\n" "$path" + * otherwise' + */ + + while ((opt = getopt(ac, av, "f:c:n:C")) != -1) { + switch (opt) { + case 'f': conf.dbfile = optarg; + break; + case 'c': conf.cmd = optarg; + conf.callback = run_shell; + break; + case 'C': + conf.errcontinue = 1; + break; + case 'n': + conf.nullstr = optarg; + break; + default: + usage(); + exit(EXIT_FAILURE); + break; + } + } + int argn = optind; + + if (!zpm_open(&pkg, conf.dbfile)) { + fprintf(stderr, "can't open zpm db %s\n", conf.dbfile); + exit(EXIT_FAILURE); + } + char *errmsg = 0; + + if (argn < ac) { + conf.pkgid = av[argn]; + // fprintf(stderr, "set pkgid to %s\n", conf.pkgid); + argn++; + } else { + fprintf(stderr, "must specify pkgid\n"); + exit(EXIT_FAILURE); + } + + /* TODO lookup pkgid via zpm-findpkg equivalent */ + + if (argn < ac) { + conf.program = av[argn]; + conf.callback = run_program; + argn++; + /* TODO set conf.args to remaining arguments */ + } + + /* install a collation function */ + // zpm_addvercmp(&pkg); + + if (!zpm_foreach_path(&pkg, conf.pkgid, conf.callback, &conf, &errmsg)) { + if (errmsg) { + fprintf(stderr, "database error: %s\n", errmsg); + exit(EXIT_FAILURE); + } + if (pkg.error == 1) { + fprintf(stderr, "unable to allocate memory\n"); + } + exit(EXIT_FAILURE); + } + + zpm_close(&pkg); + return conf.errors ? 1 : 0; +}