/[d-i]/trunk/tools/base-installer/run-debootstrap.c
ViewVC logotype

Contents of /trunk/tools/base-installer/run-debootstrap.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8041 - (show annotations) (download)
Thu Jan 22 02:27:03 2004 UTC (9 years, 4 months ago) by kraai
File MIME type: text/plain
File size: 12437 byte(s)
Fix the handling of P codes without a PF code (closes: #225858).
1 #include <sys/types.h>
2 #include <sys/wait.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <signal.h>
7 #include <string.h>
8 #include <ctype.h>
9
10 #include <cdebconf/debconfclient.h>
11 #include <debian-installer.h>
12
13 #include "waypoints.h"
14
15 #define DEBCONF_BASE "base-installer/debootstrap/"
16
17 volatile int child_exit = 0;
18 struct debconfclient *debconf = NULL;
19
20 static void
21 sig_child(int sig)
22 {
23 child_exit = 1;
24 }
25
26 // args = read_arg_lines("EA: ", ifp, &arg_count, &line);
27 char **
28 read_arg_lines(const char *prefix, FILE *ifp, int *arg_count, char **final_line,
29 int *llen)
30 {
31 static char **args = NULL;
32 static int arg_max = 0;
33 size_t dummy = 0;
34
35 if (args == NULL)
36 {
37 arg_max = 4;
38 args = malloc(sizeof(char *) * arg_max);
39 }
40 *arg_count = 0;
41 while (1)
42 {
43 *final_line = NULL;
44 if ((*llen = getline(final_line, &dummy, ifp)) <= 0)
45 {
46 return NULL;
47 }
48 (*final_line)[*llen-1] = 0;
49 if (strstr(*final_line, prefix) == *final_line)
50 {
51 if (*arg_count >= arg_max) {
52 arg_max += 4;
53 args = realloc(args, sizeof(char *) * arg_max);
54 }
55 args[(*arg_count)++] = strdup(*final_line+strlen(prefix));
56 // we got arguments.
57 }
58 else
59 break;
60 }
61 return args;
62 }
63
64 char *
65 n_sprintf(char *fmt, int arg_count, char **args)
66 {
67 char *ret;
68
69 switch (arg_count)
70 {
71 case 0: ret = strdup(fmt); break;
72 case 1: asprintf(&ret, fmt, args[0]); break;
73 case 2: asprintf(&ret, fmt, args[0], args[1]); break;
74 case 3: asprintf(&ret, fmt, args[0], args[1], args[2]); break;
75 default: ret = NULL; break;
76 }
77 return ret;
78 }
79
80 void
81 n_subst(char *template, int arg_count, char **args)
82 {
83 int i;
84
85 for (i = 0; i < arg_count; i++)
86 {
87 debconf->commandf(debconf, "SUBST %s SUBST%d %s", template, i, args[i]);
88 }
89 }
90
91 // changes in 'code'
92 char *
93 find_template(const char *prefix, char *code)
94 {
95 char *p;
96
97 for (p = code; *p; p++)
98 *p = tolower(*p);
99 asprintf(&p, DEBCONF_BASE "%s/%s", prefix, code);
100 if (debconf_metaget(debconf, p, "description") == 0)
101 return p;
102 else
103 {
104 free(p);
105 return NULL;
106 }
107 }
108
109 /* Calculate progress bar location, starting at
110 * previous waypoint, and advancing the percent of
111 * the current section that corresponds to the percent
112 * of the debootstrap progress indicator. */
113 void set_progress (int current_section, int phigh, int plow) {
114 float section_fraction;
115 int section_span, prev_waypoint, percent;
116
117 if (current_section > 0)
118 {
119 prev_waypoint = waypoints[current_section - 1].endpercent;
120 section_span = waypoints[current_section].endpercent - prev_waypoint;
121 }
122 else {
123 prev_waypoint = 0;
124 section_span = 0;
125 }
126
127 if (phigh > 0)
128 section_fraction = (float) plow / (float) phigh;
129 else
130 section_fraction = 0;
131
132 percent = prev_waypoint + (section_span * section_fraction);
133
134 //fprintf(stderr, "waypoint: %s (%i); prev endpercent %i; span: %i; fraction: %.9f (%i / %i); percent: %i\n",
135 // waypoints[current_section].progress_id,
136 // current_section, prev_waypoint, section_span,
137 // section_fraction, plow, phigh, percent);
138
139 debconf_progress_set(debconf, percent);
140 }
141
142 /*
143 * Copied from boot-floppies/utilities/dbootstrap/extract_base.c
144 * and modified to use cdebconf progress bars
145 */
146 static int
147 exec_debootstrap(char **argv){
148 char **args = NULL;
149 int arg_count;
150 int from_db[2]; /* 0=read, 1=write */
151 FILE *ifp;
152 pid_t pid;
153 int status, rv;
154 char *ptr, *line, *template, *section_text = NULL;
155 int llen;
156 size_t dummy = 0;
157 int current_section = 0;
158
159 pipe(from_db);
160
161 if ((pid = fork()) == 0)
162 {
163 close(from_db[0]);
164
165 if (dup2(from_db[1], 3) == -1)
166 perror("dup2");
167 close(from_db[1]);
168
169 if (freopen("/dev/null", "r", stdin) == NULL)
170 perror("freopen");
171
172 if (freopen("/var/log/messages", "a", stderr) == NULL)
173 perror("freopen");
174
175 dup2(2, 1);
176
177 setenv("PERL_BADLANG", "0", 1);
178 // These are needed to hack around a hack (!) in update-inetd
179 // and to not confuse debconf's postinst
180 unsetenv("DEBIAN_HAS_FRONTEND");
181 unsetenv("DEBIAN_FRONTEND");
182 unsetenv("DEBCONF_FRONTEND");
183 unsetenv("DEBCONF_REDIR");
184 if (execv(argv[0], argv) != 0)
185 perror("execv");
186 return -1;
187 }
188 else if (pid == -1)
189 {
190 perror("fork");
191 return -1;
192 }
193
194 signal(SIGCHLD, &sig_child);
195
196 close(from_db[1]);
197
198 if ((ifp = fdopen(from_db[0], "r")) == NULL) {
199 perror("fdopen");
200 return -1;
201 }
202
203 line = NULL;
204 llen = getline(&line, &dummy, ifp);
205 while (!child_exit && llen > 0)
206 {
207 line[llen-1] = 0;
208
209 //fprintf(stderr, "got line: %s\n", line);
210
211 ptr = line;
212 switch (ptr[0])
213 {
214 case 'E':
215 {
216 ptr += 3;
217 // ptr now contains the identifier of the error.
218 template = find_template("error", ptr);
219 args = read_arg_lines("EA: ", ifp, &arg_count, &line,
220 &llen);
221 if (args == NULL)
222 {
223 child_exit = 1;
224 break;
225 }
226 if (template != NULL)
227 {
228 n_subst(template, arg_count, args);
229 debconf_input(debconf, "critical", template);
230 debconf_go(debconf);
231 }
232 else if (strstr(line, "EF:") == line)
233 {
234 ptr = n_sprintf(line+4, arg_count, args);
235 if (ptr == NULL)
236 return -1;
237 // fallback error message
238 debconf_subst(debconf, DEBCONF_BASE "fallback-error",
239 "ERROR", ptr);
240 debconf_fset(debconf, DEBCONF_BASE "fallback-error",
241 "seen", "false");
242 debconf_input(debconf, "critical",
243 DEBCONF_BASE "fallback-error");
244 debconf_go(debconf);
245 free(ptr);
246 }
247 else
248 {
249 // err, don't really know what to do here... there
250 // should always be a fallback...
251 }
252 return -1;
253 }
254 case 'W': // FIXME
255 {
256 args = read_arg_lines("WA: ", ifp, &arg_count, &line,
257 &llen);
258 if (args == NULL)
259 {
260 child_exit = 1;
261 break;
262 }
263
264 if (strstr(line, "WF: ") == line)
265 {
266 ptr = n_sprintf(line+4, arg_count, args);
267 if (ptr == NULL)
268 return -1;
269
270 di_log(DI_LOG_LEVEL_OUTPUT, ptr);
271 } else {
272 // err, don't really know what to do here... there
273 // should always be a fallback...
274 }
275 break;
276 }
277 case 'P':
278 {
279 int plow = 0, phigh = 0;
280 char what[1024] = "";
281 char *section_template;
282
283 sscanf(line+3, "%d %d %s", &plow, &phigh, what);
284 if (what[0])
285 {
286 int i;
287 for (i = 0; waypoints[i].progress_id != NULL; i++)
288 {
289 if (strcmp(waypoints[i].progress_id, what) == 0)
290 {
291 set_progress(i, phigh, plow);
292
293 /* Get the description of the section
294 * template for this waypoint. */
295 if (current_section == i)
296 break; /* optimisation */
297 current_section = i;
298 section_template = find_template("section", what);
299 if (section_template)
300 {
301 if (! debconf_metaget(debconf, section_template, "description"))
302 {
303 free(section_text);
304 section_text = strdup(debconf->value);
305 }
306 free(section_template);
307 }
308
309 break;
310 }
311 }
312 }
313
314 args = read_arg_lines("PA: ", ifp, &arg_count, &line,
315 &llen);
316 if (args == NULL)
317 {
318 child_exit = 1;
319 break;
320 }
321 if (strstr(line, "PF:") == line)
322 {
323 /* Does not currently need to do anything;
324 * the implementation of debootstrap could change
325 * though.. */
326 }
327 else
328 continue;
329
330 break;
331 }
332 case 'I':
333 {
334 ptr += 3;
335 // ptr now contains the identifier of the info
336 template = find_template("info", ptr);
337
338 //fprintf(stderr, "info template: %s\n", template);
339
340 if (strcmp(ptr, "basesuccess") == 0 && template != NULL)
341 {
342 /* all done */
343 child_exit = 1;
344 break;
345 }
346 args = read_arg_lines("IA: ", ifp, &arg_count, &line,
347 &llen);
348 if (args == NULL)
349 {
350 child_exit = 1;
351 break;
352 }
353 if (template != NULL)
354 {
355 n_subst(template, arg_count, args);
356 debconf_subst(debconf, template,
357 "SECTION", section_text);
358 debconf_progress_info(debconf, template);
359 }
360 else if (strstr(line, "IF:") == line)
361 {
362 ptr = n_sprintf(line+4, arg_count, args);
363 if (ptr == NULL)
364 return -1;
365 // fallback info message
366 debconf_subst(debconf, DEBCONF_BASE "fallback-info",
367 "INFO", ptr);
368 debconf_subst(debconf, DEBCONF_BASE "fallback-info",
369 "SECTION", section_text);
370 debconf_progress_info(debconf,
371 DEBCONF_BASE "fallback-info");
372 free(ptr);
373 }
374 else
375 {
376 // err, don't really know what to do here... there
377 // should always be a fallback...
378 }
379 }
380 }
381
382 if (child_exit)
383 break;
384
385 line = NULL;
386 llen = getline(&line, &dummy, ifp);
387 }
388
389 if (waitpid(pid, &status, 0) != -1 && (WIFEXITED(status) != 0))
390 {
391 rv = WEXITSTATUS(status);
392 if (rv != 0)
393 {
394 debconf->commandf(debconf, "SUBST %serror-exitcode EXITCODE %d",
395 DEBCONF_BASE, rv);
396 debconf_fset(debconf, DEBCONF_BASE "error-exitcode", "seen",
397 "false");
398 debconf_input(debconf, "critical", DEBCONF_BASE "error-exitcode");
399 debconf_go(debconf);
400 }
401 return rv;
402 }
403 else
404 {
405 kill(SIGKILL, pid);
406 debconf_fset(debconf, DEBCONF_BASE "error-abnormal", "seen", "false");
407 debconf_input(debconf, "critical", DEBCONF_BASE "error-abnormal");
408 debconf_go(debconf);
409 return 1;
410 }
411 }
412
413 int
414 main(int argc, char *argv[])
415 {
416 char **args;
417 int i;
418 #if defined(di_log) /* Using libd-i library >= 0.16 */
419 di_system_init("run-debootstrap");
420 #endif /* di_log */
421
422 debconf = debconfclient_new();
423 args = (char **)malloc(sizeof(char *) * (argc + 1));
424 args[0] = "/usr/sbin/debootstrap";
425 for (i = 1; i < argc; i++)
426 args[i] = argv[i];
427 args[argc] = NULL;
428 return exec_debootstrap(args);
429 }

  ViewVC Help
Powered by ViewVC 1.1.5