]> pd.if.org Git - zpackage/blob - src/foreach-path.c
allow partial package ids in packagehash
[zpackage] / src / foreach-path.c
1 #define _POSIX_C_SOURCE 2
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <ctype.h>
5 #include <limits.h>
6 #include <unistd.h>
7 #include <sys/types.h>
8 #include <sys/wait.h>
9
10 #include <string.h>
11
12 #include "sqlite3.h"
13 #include "zpm.h"
14
15 struct config {
16         char *dbfile;
17         char *cmd;
18         char *program;
19         char *pkgid;
20         char *nullstr;
21         char *filter;
22         int errcontinue;
23         int errors;
24         int (*callback)(void*,int,char**,char**);
25 };
26
27 static void usage() {
28         printf("usage: zpm foreach-path [-fncC] args ...\n");
29 }
30
31 static int run_program(void *f, int ncols, char **vals, char **cols) {
32         struct config *conf = f;
33         int i;
34         char *argv[ncols+1];
35         pid_t pid;
36         int status;
37         int rv;
38
39         argv[0] = conf->program;
40
41         for (i=0;i<ncols;i++) {
42                 argv[i+1] = vals[i] ? vals[i] : conf->nullstr;
43         }
44         argv[i+1] = 0;
45
46         pid = fork();
47
48         if (pid == -1) {
49                 perror("cannot fork");
50                 return 1;
51         }
52
53         if (pid == 0) {
54                 /* child */
55                 rv = execvp(conf->program, argv);
56                 if (rv == -1) {
57                         perror("cannot exec");
58                         exit(EXIT_FAILURE);
59                 }
60         }
61
62         rv = wait(&status);
63         if (rv == -1) {
64                 perror("error waiting for child");
65                 exit(EXIT_FAILURE);
66         }
67         if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
68                 return 0;
69         } else if (conf->errcontinue) {
70                 conf->errors++;
71                 return 0;
72         }
73         return 1;
74 }
75
76 static int run_shell(void *f, int ncols, char **vals, char **cols) {
77         struct config *conf = f;
78         int i;
79         char *argv[ncols+4];
80         pid_t pid;
81         int status;
82         int rv;
83
84         argv[0] = "sh";
85         argv[1] = "-c";
86         argv[2] = conf->cmd;
87         argv[3] = "sh";
88
89         for (i=0;i<ncols;i++) {
90                 argv[i+4] = vals[i] ? vals[i] : conf->nullstr;
91         }
92         argv[i+4] = 0;
93
94         pid = fork();
95
96         if (pid == -1) {
97                 perror("cannot fork");
98                 return 1;
99         }
100
101         if (pid == 0) {
102                 /* child */
103                 rv = execvp("sh", argv);
104                 if (rv == -1) {
105                         perror("cannot exec");
106                         exit(EXIT_FAILURE);
107                 }
108         }
109
110         rv = wait(&status);
111         if (rv == -1) {
112                 perror("error waiting for child");
113         }
114         if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
115                 return 0;
116         } else if (conf->errcontinue) {
117                 conf->errors++;
118                 return 0;
119         }
120         return 1;
121 }
122
123 static int printpaths(void *f, int ncols, char **vals, char **cols) {
124
125         /* suppress unused warnings */
126
127         if (ncols < 6) {
128                 fprintf(stderr, "can't find path names\n");
129                 return 1;
130         }
131 //      printf("path cols %d %p %p\n", ncols, vals, cols);
132         fprintf(stdout, "%s\n", vals[5]);
133 #if 0
134         cols = 0;
135         f = 0;
136         int i;
137         if (cols == 0) {
138                 fprintf(stderr, "sqlite can't get column names\n");
139         }
140         for (i=0;i<ncols;i++) {
141 //              if (i>3) fprintf(out, "\t");
142                 fprintf(stdout, "%s\n", vals[i]);
143         }
144 #endif
145         return 0;
146 }
147
148 #ifdef PATH_MAX
149 #define PATHLEN PATH_MAX
150 #else
151 #define PATHLEN 4096
152 #endif
153
154 int main(int ac, char **av){
155         struct zpm pkg;
156         int opt;
157
158         struct config conf = { 0 };
159
160         conf.dbfile = getenv("ZPMDB");
161         conf.callback = printpaths;
162         conf.nullstr = "";
163
164         if (!conf.dbfile) {
165                 conf.dbfile = "/var/lib/zpm/local.db";
166         }
167
168         /*
169          * -c 'shell command'
170          * -f 'package database', otherwise regular default of env ZPMDB,
171          * or /var/lib/zpm/zpm.db, or die
172          *
173          *  arg 1: pkgid triple, but will do a pkg find
174          *  arg 2: program to run.  equivalent of 'printf "%s\n" "$path"
175          *  otherwise' 
176          */
177
178         while ((opt = getopt(ac, av, "f:c:n:Cp:F:")) != -1) {
179                 switch (opt) {
180                         case 'f': conf.dbfile = optarg;
181                                   break;
182                         case 'c': conf.cmd = optarg;
183                                   conf.callback = run_shell;
184                                   break;
185                         case 'C':
186                                   conf.errcontinue = 1;
187                                   break;
188                         case 'n':
189                                   conf.nullstr = optarg;
190                                   break;
191                         case 'p':
192                                   conf.pkgid = optarg;
193                                   break;
194                         case 'F': conf.filter = optarg;
195                                   break;
196                         default:
197                                   usage();
198                                   exit(EXIT_FAILURE);
199                                   break;
200                 }
201         }
202         int argn = optind;
203
204         if (!zpm_open(&pkg, conf.dbfile)) {
205                 fprintf(stderr, "can't open zpm db %s\n", conf.dbfile);
206                 exit(EXIT_FAILURE);
207         }
208         char *errmsg = 0;
209
210         /* TODO lookup pkgid via zpm-findpkg equivalent */
211
212         if (argn < ac) {
213                 conf.program = av[argn];
214                 conf.callback = run_program;
215                 argn++;
216                 /* TODO set conf.args to remaining arguments */
217         }
218
219         if (!zpm_foreach_path(&pkg, conf.pkgid, conf.filter, conf.callback, &conf, &errmsg)) {
220                 if (errmsg) {
221                         fprintf(stderr, "database error: %s\n", errmsg);
222                         exit(EXIT_FAILURE);
223                 }
224                 if (pkg.error == 1) {
225                         fprintf(stderr, "unable to allocate memory\n");
226                 }
227                 exit(EXIT_FAILURE);
228         }
229
230         zpm_close(&pkg);
231         return conf.errors ? 1 : 0;
232 }