#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; char *filter; int errcontinue; int errors; int (*callback)(void*,int,char**,char**); }; static void usage() { printf("usage: zpm foreach-path [-fncC] args ...\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 < 6) { 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[5]); #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; } #ifdef PATH_MAX #define PATHLEN PATH_MAX #else #define PATHLEN 4096 #endif int main(int ac, char **av){ struct zpm pkg; int opt; struct config conf = { 0 }; conf.dbfile = getenv("ZPMDB"); conf.callback = printpaths; conf.nullstr = ""; if (!conf.dbfile) { conf.dbfile = "/var/lib/zpm/local.db"; } /* * -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:Cp:F:")) != -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; case 'p': conf.pkgid = optarg; break; case 'F': conf.filter = 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; /* 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 */ } if (!zpm_foreach_path(&pkg, conf.pkgid, conf.filter, 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; }