]> pd.if.org Git - zpackage/blob - zpm-runscript.c
ignore missing runscript by default
[zpackage] / zpm-runscript.c
1 #define _POSIX_C_SOURCE 200809L
2
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <sys/types.h>
6 #include <sys/wait.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #include <unistd.h>
10 #include <errno.h>
11
12
13 #include <sys/mman.h>
14
15 #include "zpm.h"
16
17 /*
18  * -f package file, otherwise localdb
19  * -p phase, defaults to 'configure'
20  * -s script name, defaults to /var/tmp/zpm-script
21  * -r chroot to directory
22  * -o script output, /var/tmp/zpm-script.out, '-' for stdout
23  *
24  * arg is package id
25  */
26
27 void usage(void) {
28         fprintf(stderr, "usage: db hash file\n");
29 }
30
31 int run(char *program, char **args, char *output, int *status) {
32         /* if stdout is a terminal, leave stdout where it goes,
33          * if it's not a terminal, redirect stdout to output.
34          * in either case, send stderr to output, unless null
35          * if output is null, just run the program
36          */
37         int interactive = 0;
38         pid_t pid;
39         int rv;
40
41         errno = 0;
42
43         interactive = isatty(1);
44
45         pid = fork();
46
47         if (pid == -1) {
48                 *status = 1;
49                 return -1;
50         }
51
52         if (pid == 0) {
53                 /* child */
54                 if (output) {
55                         close(2);
56                         rv = open(output, O_NOFOLLOW|O_TRUNC|O_CREAT|O_WRONLY,
57                                         0600);
58                         if (rv == -1) {
59                                 perror("cannot open output file");
60                         }
61                         if (!interactive) {
62                                 rv = dup2(2,1);
63                                 if (rv == -1) {
64                                         perror("unable to redirect stdout");
65                                         exit(EXIT_FAILURE);
66                                 }
67                         }
68                 }
69
70                 rv = execvp(program, args);
71                 if (rv == -1) {
72                         perror("cannot exec");
73                         exit(EXIT_FAILURE);
74                 }
75         }
76
77         pid = wait(status);
78         if (pid == -1) {
79                 perror("error waiting for child");
80                 return -2;
81         }
82
83         if (WIFEXITED(*status)) {
84                 return WEXITSTATUS(*status);
85         }
86
87         return -3;
88 }
89
90 int main(int ac, char **av){
91         struct zpm zpm;
92         int rv;
93         int status;
94         int failures = 0;
95         char *pkgstr;
96         int opt;
97         int required = 0;
98
99         char hash[ZPM_HASH_STRLEN+1];
100         char *args[3];
101         char *pkgid;
102
103         char *chroot = 0;
104         char *db = "/var/lib/zpm/zpm.db";
105         char *script = "/var/tmp/zpm-script";
106         char *output = "/var/tmp/zpm-script.out";
107         char *phase = "configure";
108
109         if (getenv("ZPMDB")) {
110                 db = getenv("ZPMDB");
111         }
112         /* ZPM_PACKAGE_FILE ? */
113
114         while ((opt = getopt(ac, av, "f:p:s:r:R")) != -1) {
115                 switch (opt) {
116                         case 'f': db = optarg; break;
117                         case 'p': phase = optarg; break;
118                         case 's': script = optarg; break;
119                         case 'r': chroot = optarg; break;
120                         case 'R': required = 1; break;
121                         default:
122                                   usage();
123                                   exit(EXIT_FAILURE);
124                                   break;
125                 }
126         }
127         int argn = optind;
128
129         if (argn >= ac) {
130                 usage();
131                 exit(EXIT_FAILURE);
132         }
133
134         pkgstr = av[argn];
135
136         if (!zpm_open(&zpm, db)) {
137                 fprintf(stderr, "unable to open zpm database: %s\n", db);
138                 if (zpm.errmsg) {
139                         fprintf(stderr, "error detail: %s\n", zpm.errmsg);
140                 }
141                 exit(EXIT_FAILURE);
142         }
143
144         pkgid = zpm_findpkg(&zpm, pkgstr);
145         if (pkgid) {
146                 if (zpm_script_hash(&zpm, pkgid, phase, hash)) {
147                         rv = zpm_extract(&zpm, hash, script, 0700);
148
149                         /* perhaps also pass in the phase name?  or ENV? */
150                         /* TODO sanitize environment ? */
151                         args[0] = script;
152                         args[1] = pkgid;
153                         args[2] = 0;
154                         if (chroot) {
155                                 fprintf(stderr, "failing to chroot %s\n", chroot);
156                         }
157                         rv = run(script, args, output, &status);
158                         if (rv) {
159                                 //                      cat(output);
160                                 fprintf(stderr, "package %s script failed with code %d\n",
161                                                 pkgid, rv);
162                         }
163                         /* TODO log output */
164                         unlink(script);
165                         unlink(output);
166                         if (rv) {
167                                 failures++;
168                         }
169                 } else {
170                         if (required) {
171                                 fprintf(stderr, "no script for %s %s\n", phase, pkgid);
172                                 failures++;
173                         }
174                 }
175                 free(pkgid);
176         } else {
177                 fprintf(stderr, "unable to find package for %s in %s\n",
178                                 pkgstr, db);
179                 failures++;
180         }
181
182         zpm_close(&zpm);
183
184         return failures ? EXIT_FAILURE : EXIT_SUCCESS;
185 }