]> pd.if.org Git - zpackage/commitdiff
add program to run a command for each package file
authorNathan Wagner <nw@hydaspes.if.org>
Tue, 11 Sep 2018 10:57:01 +0000 (10:57 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Wed, 12 Sep 2018 11:11:14 +0000 (11:11 +0000)
.gitignore
zpm-foreach-path.c [new file with mode: 0644]

index cf56615f5abfde217838f63f87cd1fbb98d3a019..94ec0189ca834a3f48caf7abd8ad4f609e385fe5 100644 (file)
@@ -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 (file)
index 0000000..30340a0
--- /dev/null
@@ -0,0 +1,283 @@
+#define _POSIX_C_SOURCE 2
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <limits.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <string.h>
+
+#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;i<ncols;i++) {
+               argv[i+1] = vals[i] ? vals[i] : conf->nullstr;
+       }
+       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;i<ncols;i++) {
+               argv[i+4] = vals[i] ? vals[i] : conf->nullstr;
+       }
+       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;i<ncols;i++) {
+//             if (i>3) 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;
+}