]> pd.if.org Git - zpackage/blobdiff - src/foreach-path.c
move C source files into src
[zpackage] / src / foreach-path.c
diff --git a/src/foreach-path.c b/src/foreach-path.c
new file mode 100644 (file)
index 0000000..41fb1c6
--- /dev/null
@@ -0,0 +1,232 @@
+#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;
+       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;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 < 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;i<ncols;i++) {
+//             if (i>3) 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;
+}