xl2tpd: moved to github
[packages.git] / admin / debootstrap / files / pkgdetails.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include <stdarg.h>
6 #include <errno.h>
7
8 #define MAX_LINE 1000
9 #define MAX_PKGS 100
10
11 char *checksum_field=NULL;
12
13 static void oom_die(void)
14 {
15     fputs("Out of memory!\n", stderr);
16     exit(1);
17 }
18
19 static char *xvasprintf(const char *fmt, va_list ap) {
20     char *ret;
21
22     if (vasprintf (&ret, fmt, ap) < 0) {
23         if (errno == ENOMEM)
24             oom_die();
25         return NULL;
26     }
27     return ret;
28 }
29
30 static char *xasprintf(const char *fmt, ...) {
31     va_list ap;
32     char *ret;
33
34     va_start(ap, fmt);
35     ret = xvasprintf(fmt, ap);
36     va_end(ap);
37     return ret;
38 }
39
40 static char *fieldcpy(char *dst, char *fld) {
41     while (*fld && *fld != ':') 
42         fld++;
43     if (!*(fld++)) 
44         return NULL;
45     while (isspace(*fld)) fld++;
46     return strcpy(dst, fld);
47 }
48
49 static void outputdeps(char *deps) {
50     char *pch = deps;
51
52     while (1) {
53         while (isspace(*pch)) pch++;
54         if (!*pch) break;
55
56         while (*pch && *pch != '(' && *pch != '|' && *pch != ','
57                && !isspace(*pch))
58         {
59             fputc(*pch++, stdout);
60         }
61         fputc('\n', stdout);
62         while (*pch && *pch++ != ',') (void)NULL;
63     }
64 }
65
66 static void dogetdeps(char *pkgsfile, char **in_pkgs, int pkgc) {
67     char buf[MAX_LINE];
68     char cur_pkg[MAX_LINE];
69     char cur_deps[MAX_LINE];
70     char cur_predeps[MAX_LINE];
71     char prev_pkg[MAX_LINE];
72     char *pkgs[MAX_PKGS];
73     int i;
74     int skip;
75     FILE *f;
76     int output_pkg = -1;
77
78     cur_pkg[0] = cur_deps[0] = cur_predeps[0] = prev_pkg[0] = '\0';
79
80     for (i = 0; i < pkgc; i++) pkgs[i] = in_pkgs[i];
81
82     f = fopen(pkgsfile, "r");
83     if (f == NULL) {
84         perror(pkgsfile);
85         exit(1);
86     }
87
88     skip = 1;
89     while (fgets(buf, sizeof(buf), f)) {
90         if (*buf && buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
91         if (strncasecmp(buf, "Package:", 8) == 0) {
92             int any = 0;
93             skip = 1;
94             fieldcpy(cur_pkg, buf);
95             if (strcmp(cur_pkg, prev_pkg) != 0) {
96                 if (output_pkg != -1)
97                     pkgs[output_pkg] = NULL;
98                 if (cur_deps[0])
99                     outputdeps(cur_deps);
100                 if (cur_predeps[0])
101                     outputdeps(cur_predeps);
102                 strcpy(prev_pkg, cur_pkg);
103             }
104             cur_deps[0] = cur_predeps[0] = '\0';
105             output_pkg = -1;
106             for (i = 0; i < pkgc; i++) {
107                 if (!pkgs[i]) continue;
108                 any = 1;
109                 if (strcmp(cur_pkg, pkgs[i]) == 0) {
110                     skip = 0;
111                     output_pkg = i;
112                     break;
113                 }
114             }
115             if (!any) break;
116         } else if (!skip && strncasecmp(buf, "Depends:", 8) == 0)
117             fieldcpy(cur_deps, buf);
118         else if (!skip && strncasecmp(buf, "Pre-Depends:", 12) == 0)
119             fieldcpy(cur_predeps, buf);
120     }
121     if (cur_deps[0])
122         outputdeps(cur_deps);
123     if (cur_predeps[0])
124         outputdeps(cur_predeps);
125     fclose(f);
126 }
127
128 static void dopkgmirrorpkgs(int uniq, char *mirror, char *pkgsfile, 
129         char *fieldname, char **in_pkgs, int pkgc) 
130 {
131     char buf[MAX_LINE];
132     char cur_field[MAX_LINE];
133     char cur_pkg[MAX_LINE];
134     char cur_ver[MAX_LINE];
135     char cur_arch[MAX_LINE];
136     char cur_size[MAX_LINE];
137     char cur_checksum[MAX_LINE];
138     char cur_filename[MAX_LINE];
139     char prev_pkg[MAX_LINE];
140     char *pkgs[MAX_PKGS];
141     int i;
142     FILE *f;
143     char *output = NULL;
144     int output_pkg = -1;
145
146     cur_field[0] = cur_pkg[0] = cur_ver[0] = cur_arch[0] = cur_filename[0] = prev_pkg[0] = '\0';
147
148     for (i = 0; i < pkgc; i++) pkgs[i] = in_pkgs[i];
149
150     f = fopen(pkgsfile, "r");
151     if (f == NULL) {
152         perror(pkgsfile);
153         exit(1);
154     }
155     while (fgets(buf, sizeof(buf), f)) {
156         if (*buf && buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
157         if (strncasecmp(buf, fieldname, strlen(fieldname)) == 0) {
158             fieldcpy(cur_field, buf);
159         }
160         if (strncasecmp(buf, "Package:", 8) == 0) {
161             fieldcpy(cur_pkg, buf);
162             if (strcmp(cur_pkg, prev_pkg) != 0) {
163                 if (output)
164                     fputs(output, stdout);
165                 if (uniq && output_pkg != -1)
166                     pkgs[output_pkg] = NULL;
167                 strcpy(prev_pkg, cur_pkg);
168             }
169             free(output);
170             output = NULL;
171             output_pkg = -1;
172         } else if (strncasecmp(buf, "Version:", 8) == 0) {
173             fieldcpy(cur_ver, buf);
174         } else if (strncasecmp(buf, "Architecture:", 13) == 0) {
175             fieldcpy(cur_arch, buf);
176         } else if (strncasecmp(buf, "Size:", 5) == 0) {
177             fieldcpy(cur_size, buf);
178         } else if (strncasecmp(buf, checksum_field, strlen(checksum_field)) == 0
179                    && buf[strlen(checksum_field)] == ':') {
180             fieldcpy(cur_checksum, buf);
181         } else if (strncasecmp(buf, "Filename:", 9) == 0) {
182             fieldcpy(cur_filename, buf);
183         } else if (!*buf) {
184             int any = 0;
185             for (i = 0; i < pkgc; i++) {
186                 if (!pkgs[i]) continue;
187                 any = 1;
188                 if (strcmp(cur_field, pkgs[i]) == 0) {
189                     free(output);
190                     output = xasprintf("%s %s %s %s %s %s %s\n", cur_pkg, cur_ver, cur_arch, mirror, cur_filename, cur_checksum, cur_size);
191                     output_pkg = i;
192                     break;
193                 }
194             }
195             if (!any) break;
196             cur_field[0] = '\0';
197         }
198     }
199     if (output)
200         fputs(output, stdout);
201     if (uniq && output_pkg != -1)
202         pkgs[output_pkg] = NULL;
203     fclose(f);
204
205     /* any that weren't found are returned as "pkg -" */
206     if (uniq) {
207         for (i = 0; i < pkgc; i++) {
208             if (pkgs[i]) {
209                 printf("%s -\n", pkgs[i]);
210             }
211         }
212     }
213 }
214
215 static void dopkgstanzas(char *pkgsfile, char **pkgs, int pkgc)
216 {
217     char buf[MAX_LINE];
218     char *accum;
219     size_t accum_size = 0, accum_alloc = MAX_LINE * 2;
220     char cur_pkg[MAX_LINE];
221     FILE *f;
222
223     accum = malloc(accum_alloc);
224     if (!accum)
225         oom_die();
226
227     f = fopen(pkgsfile, "r");
228     if (f == NULL) {
229         perror(pkgsfile);
230         free(accum);
231         exit(1);
232     }
233     while (fgets(buf, sizeof(buf), f)) {
234         if (*buf) {
235             size_t len = strlen(buf);
236             if (accum_size + len + 1 > accum_alloc) {
237                 accum_alloc = (accum_size + len + 1) * 2;
238                 accum = realloc(accum, accum_alloc);
239                 if (!accum)
240                     oom_die();
241             }
242             strcpy(accum + accum_size, buf);
243             accum_size += len;
244         }
245         if (*buf && buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
246         if (strncasecmp(buf, "Package:", 8) == 0) {
247             fieldcpy(cur_pkg, buf);
248         } else if (!*buf) {
249             int i;
250             for (i = 0; i < pkgc; i++) {
251                 if (!pkgs[i]) continue;
252                 if (strcmp(cur_pkg, pkgs[i]) == 0) {
253                     fputs(accum, stdout);
254                     if (accum[accum_size - 1] != '\n')
255                         fputs("\n\n", stdout);
256                     else if (accum[accum_size - 2] != '\n')
257                         fputc('\n', stdout);
258                     break;
259                 }
260             }
261             *accum = '\0';
262             accum_size = 0;
263         }
264     }
265     fclose(f);
266
267     free(accum);
268 }
269
270 static int dotranslatewgetpercent(int low, int high, int end, char *str) {
271     int ch;
272     int val, lastval;
273
274     /* print out anything that looks like a % on its own line, appropriately
275      * scaled */
276
277     lastval = val = 0;
278     while ( (ch = getchar()) != EOF ) {
279         if (isdigit(ch)) {
280             val *= 10; val += ch - '0';
281         } else if (ch == '%') {
282             float f = (float) val / 100.0 * (high - low) + low;
283             if (str) {
284                 printf("P: %d %d %s\n", (int) f, end, str);
285             } else {
286                 printf("P: %d %d\n", (int) f, end);
287             }
288             lastval = val;
289         } else {
290             val = 0;
291         }
292     }
293     return lastval == 100;
294 }
295
296 int main(int argc, char *argv[]) {
297     checksum_field=getenv("DEBOOTSTRAP_CHECKSUM_FIELD");
298     if (checksum_field == NULL) {
299         checksum_field="MD5sum";
300     }
301
302     if ((argc == 6 || argc == 5) && strcmp(argv[1], "WGET%") == 0) {
303         if (dotranslatewgetpercent(atoi(argv[2]), atoi(argv[3]), 
304                                    atoi(argv[4]), argc == 6 ? argv[5] : NULL))
305         {
306             exit(0);
307         } else {
308             exit(1);
309         }
310     } else if (argc >= 4 && strcmp(argv[1], "GETDEPS") == 0) {
311         int i;
312         for (i = 3; argc - i > MAX_PKGS; i += MAX_PKGS) {
313             dogetdeps(argv[2], argv+i, MAX_PKGS);
314         }
315         dogetdeps(argv[2], argv+i, argc-i);
316         exit(0);
317     } else if (argc >= 5 && strcmp(argv[1], "PKGS") == 0) {
318         int i;
319         for (i = 4; argc - i > MAX_PKGS; i += MAX_PKGS) {
320             dopkgmirrorpkgs(1, argv[2], argv[3], "Package:", argv+i, MAX_PKGS);
321         }
322         dopkgmirrorpkgs(1, argv[2], argv[3], "Package:", argv+i, argc-i);
323         exit(0);
324     } else if (argc >= 6 && strcmp(argv[1], "FIELD") == 0) {
325         int i;
326         for (i = 5; argc - i > MAX_PKGS; i += MAX_PKGS) {
327             dopkgmirrorpkgs(0, argv[3], argv[4], argv[2], argv+i, MAX_PKGS);
328         }
329         dopkgmirrorpkgs(0, argv[3], argv[4], argv[2], argv+i, argc-i);
330         exit(0);
331     } else if (argc >= 4 && strcmp(argv[1], "STANZAS") == 0) {
332         int i;
333         for (i = 3; argc - i > MAX_PKGS; i += MAX_PKGS) {
334             dopkgstanzas(argv[2], argv+i, MAX_PKGS);
335         }
336         dopkgstanzas(argv[2], argv+i, argc-i);
337         exit(0);
338     } else {
339         fprintf(stderr, "usage: %s PKGS mirror packagesfile pkgs..\n", argv[0]);
340         fprintf(stderr, "   or: %s FIELD field mirror packagesfile pkgs..\n", 
341                 argv[0]);
342         fprintf(stderr, "   or: %s GETDEPS packagesfile pkgs..\n", argv[0]);
343         fprintf(stderr, "   or: %s STANZAS packagesfile pkgs..\n", argv[0]);
344         fprintf(stderr, "   or: %s WGET%% low high end reason\n", argv[0]);
345         exit(1);
346     }
347 }