~ubuntu-installer/base-installer/master

111 by Martin Sjögren
First hash of a progress bar implementation
1
#include <sys/types.h>
2
#include <sys/wait.h>
3
#include <stdio.h>
4
#include <stdlib.h>
5
#include <unistd.h>
6
#include <string.h>
7
#include <ctype.h>
8
9
#include <cdebconf/debconfclient.h>
10
#include <debian-installer.h>
11
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
12
#include "waypoints.h"
13
111 by Martin Sjögren
First hash of a progress bar implementation
14
#define DEBCONF_BASE          "base-installer/debootstrap/"
15
16
struct debconfclient *debconf = NULL;
1240 by Colin Watson
Start run-debootstrap progress bar at the appropriate waypoint rather than
17
int progress_start_position = 0;
111 by Martin Sjögren
First hash of a progress bar implementation
18
1209 by Colin Watson
Use C-style comments in run-debootstrap.
19
/* args = read_arg_lines("EA: ", ifp, &arg_count, &line); */
111 by Martin Sjögren
First hash of a progress bar implementation
20
char **
408 by Matt Kraai
Fix the handling of P codes without a PF code (closes: #225858).
21
read_arg_lines(const char *prefix, FILE *ifp, int *arg_count, char **final_line,
22
	       int *llen)
111 by Martin Sjögren
First hash of a progress bar implementation
23
{
24
    static char **args = NULL;
25
    static int arg_max = 0;
159 by Richard Hirst
26
    size_t dummy = 0;
111 by Martin Sjögren
First hash of a progress bar implementation
27
28
    if (args == NULL)
29
    {
30
        arg_max = 4;
31
        args = malloc(sizeof(char *) * arg_max);
32
    }
33
    *arg_count = 0;
34
    while (1)
35
    {
36
        *final_line = NULL;
408 by Matt Kraai
Fix the handling of P codes without a PF code (closes: #225858).
37
        if ((*llen = getline(final_line, &dummy, ifp)) <= 0)
111 by Martin Sjögren
First hash of a progress bar implementation
38
        {
39
            return NULL;
40
        }
408 by Matt Kraai
Fix the handling of P codes without a PF code (closes: #225858).
41
        (*final_line)[*llen-1] = 0;
111 by Martin Sjögren
First hash of a progress bar implementation
42
        if (strstr(*final_line, prefix) == *final_line)
43
        {
44
            if (*arg_count >= arg_max) {
45
                arg_max += 4;
46
                args = realloc(args, sizeof(char *) * arg_max);
47
            }
48
            args[(*arg_count)++] = strdup(*final_line+strlen(prefix));
1209 by Colin Watson
Use C-style comments in run-debootstrap.
49
            /* we got arguments. */
111 by Martin Sjögren
First hash of a progress bar implementation
50
        }
51
        else
52
            break;
53
    }
54
    return args;
55
}
56
57
char *
58
n_sprintf(char *fmt, int arg_count, char **args)
59
{
60
    char *ret;
61
62
    switch (arg_count)
63
    {
64
        case 0: ret = strdup(fmt); break;
65
        case 1: asprintf(&ret, fmt, args[0]); break;
66
        case 2: asprintf(&ret, fmt, args[0], args[1]); break;
67
        case 3: asprintf(&ret, fmt, args[0], args[1], args[2]); break;
68
        default: ret = NULL; break;
69
    }
70
    return ret;
71
}
72
73
void
74
n_subst(char *template, int arg_count, char **args)
75
{
76
    int i;
77
78
    for (i = 0; i < arg_count; i++)
79
    {
80
        debconf->commandf(debconf, "SUBST %s SUBST%d %s", template, i, args[i]);
81
    }
82
}
83
1209 by Colin Watson
Use C-style comments in run-debootstrap.
84
/* changes in 'code' */
111 by Martin Sjögren
First hash of a progress bar implementation
85
char *
86
find_template(const char *prefix, char *code)
87
{
88
    char *p;
89
90
    for (p = code; *p; p++)
91
        *p = tolower(*p);
92
    asprintf(&p, DEBCONF_BASE "%s/%s", prefix, code);
176 by Petter Reinholdtsen
Start using debconf_* macro in run-debootstrap.c.
93
    if (debconf_metaget(debconf, p, "description") == 0)
111 by Martin Sjögren
First hash of a progress bar implementation
94
        return p;
95
    else
96
    {
97
        free(p);
98
        return NULL;
99
    }
100
}
101
1240 by Colin Watson
Start run-debootstrap progress bar at the appropriate waypoint rather than
102
int get_progress_start_position (void) {
103
    const char *progress_env = getenv("PB_PROGRESS");
104
    if (progress_env)
105
        return atoi(progress_env);
106
    else
107
        return 0;
108
}
109
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
110
/* Calculate progress bar location, starting at
111
 * previous waypoint, and advancing the percent of
112
 * the current section that corresponds to the percent
113
 * of the debootstrap progress indicator. */
114
void set_progress (int current_section, int phigh, int plow) {
115
    float section_fraction;
116
    int section_span, prev_waypoint, percent;
1220 by Colin Watson
List both starting and ending percentages for waypoints, in order to be able
117
118
    prev_waypoint = waypoints[current_section].startpercent;
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
119
    if (current_section > 0)
120
        section_span = waypoints[current_section].endpercent - prev_waypoint;
1220 by Colin Watson
List both starting and ending percentages for waypoints, in order to be able
121
    else
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
122
        section_span = 0;
1220 by Colin Watson
List both starting and ending percentages for waypoints, in order to be able
123
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
124
    if (phigh > 0)
125
        section_fraction = (float) plow / (float) phigh;
126
    else
127
        section_fraction = 0;
936 by Colin Watson
Add guard against overflow of progress bar sections.
128
    if (section_fraction > 1)
129
        section_fraction = 1;
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
130
			
131
    percent = prev_waypoint + (section_span * section_fraction);
1209 by Colin Watson
Use C-style comments in run-debootstrap.
132
133
#if 0
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
#endif
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
139
1240 by Colin Watson
Start run-debootstrap progress bar at the appropriate waypoint rather than
140
    debconf_progress_set(debconf, progress_start_position + percent);
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
141
}
142
111 by Martin Sjögren
First hash of a progress bar implementation
143
/*
144
 * Copied from boot-floppies/utilities/dbootstrap/extract_base.c
145
 * and modified to use cdebconf progress bars
146
 */
147
static int
148
exec_debootstrap(char **argv){
149
    char **args = NULL;
150
    int arg_count;
151
    int from_db[2]; /* 0=read, 1=write */
152
    FILE *ifp;
153
    pid_t pid;
154
    int status, rv;
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
155
    char *ptr, *line, *template, *section_text = NULL;
156
    int llen;
159 by Richard Hirst
157
    size_t dummy = 0;
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
158
    int current_section = 0;
1494 by Joey Hess
* Remove sigchld handler in run_debootstrap. It caused it to stop processing
159
    int child_exit = 0;
111 by Martin Sjögren
First hash of a progress bar implementation
160
161
    pipe(from_db);
162
163
    if ((pid = fork()) == 0)
164
    {
165
        close(from_db[0]);
166
167
        if (dup2(from_db[1], 3) == -1)
168
            perror("dup2");
169
        close(from_db[1]);
170
171
        if (freopen("/dev/null", "r", stdin) == NULL)
172
            perror("freopen");
173
174
        setenv("PERL_BADLANG", "0", 1);
1209 by Colin Watson
Use C-style comments in run-debootstrap.
175
        /* These are needed to hack around a hack (!) in update-inetd
176
         * and to not confuse debconf's postinst */
111 by Martin Sjögren
First hash of a progress bar implementation
177
        unsetenv("DEBIAN_HAS_FRONTEND");
178
        unsetenv("DEBIAN_FRONTEND");
179
        unsetenv("DEBCONF_FRONTEND");
180
        unsetenv("DEBCONF_REDIR");
181
        if (execv(argv[0], argv) != 0)
182
            perror("execv");
183
        return -1;
184
    }
185
    else if (pid == -1)
186
    {
187
        perror("fork");
188
        return -1;
189
    }
190
1240 by Colin Watson
Start run-debootstrap progress bar at the appropriate waypoint rather than
191
    progress_start_position = get_progress_start_position();
192
111 by Martin Sjögren
First hash of a progress bar implementation
193
    close(from_db[1]);
194
195
    if ((ifp = fdopen(from_db[0], "r")) == NULL) {
196
        perror("fdopen");
197
        return -1;
198
    }
199
200
    line = NULL;
408 by Matt Kraai
Fix the handling of P codes without a PF code (closes: #225858).
201
    llen = getline(&line, &dummy, ifp);
202
    while (!child_exit && llen > 0)
111 by Martin Sjögren
First hash of a progress bar implementation
203
    {
204
        line[llen-1] = 0;
358 by Joey Hess
some debugging printfs I find useful (commented out)
205
1209 by Colin Watson
Use C-style comments in run-debootstrap.
206
	/* fprintf(stderr, "got line: %s\n", line); */
358 by Joey Hess
some debugging printfs I find useful (commented out)
207
	
111 by Martin Sjögren
First hash of a progress bar implementation
208
        ptr = line;
209
        switch (ptr[0])
210
        {
211
            case 'E':
212
                {
213
                    ptr += 3;
1209 by Colin Watson
Use C-style comments in run-debootstrap.
214
                    /* ptr now contains the identifier of the error. */
111 by Martin Sjögren
First hash of a progress bar implementation
215
                    template = find_template("error", ptr);
408 by Matt Kraai
Fix the handling of P codes without a PF code (closes: #225858).
216
                    args = read_arg_lines("EA: ", ifp, &arg_count, &line,
217
					  &llen);
111 by Martin Sjögren
First hash of a progress bar implementation
218
                    if (args == NULL)
219
                    {
220
                        child_exit = 1;
221
                        break;
222
                    }
223
                    if (template != NULL)
224
                    {
225
                        n_subst(template, arg_count, args);
176 by Petter Reinholdtsen
Start using debconf_* macro in run-debootstrap.c.
226
                        debconf_input(debconf, "critical", template);
227
                        debconf_go(debconf);
111 by Martin Sjögren
First hash of a progress bar implementation
228
                    }
229
                    else if (strstr(line, "EF:") == line)
230
                    {
231
                        ptr = n_sprintf(line+4, arg_count, args);
232
                        if (ptr == NULL)
233
                            return -1;
1209 by Colin Watson
Use C-style comments in run-debootstrap.
234
                        /* fallback error message */
176 by Petter Reinholdtsen
Start using debconf_* macro in run-debootstrap.c.
235
                        debconf_subst(debconf, DEBCONF_BASE "fallback-error",
236
				      "ERROR", ptr);
237
                        debconf_input(debconf, "critical",
238
				      DEBCONF_BASE "fallback-error");
239
                        debconf_go(debconf);
111 by Martin Sjögren
First hash of a progress bar implementation
240
                        free(ptr);
241
                    }
242
                    else
243
                    {
1209 by Colin Watson
Use C-style comments in run-debootstrap.
244
                        /* err, don't really know what to do here... there
245
                         * should always be a fallback... */
111 by Martin Sjögren
First hash of a progress bar implementation
246
                    }
247
                    return -1;
248
                }
1267 by Joey Hess
- Improve run-debootstrap's warning handling, display warning on progress
249
            case 'W':
111 by Martin Sjögren
First hash of a progress bar implementation
250
                {
1267 by Joey Hess
- Improve run-debootstrap's warning handling, display warning on progress
251
                    ptr += 3;
252
                    /* ptr now contains the identifier of the warning */
253
                    template = find_template("warning", ptr);
254
255
                    /* fprintf(stderr, "warning template: %s\n", template); */
256
		    
408 by Matt Kraai
Fix the handling of P codes without a PF code (closes: #225858).
257
                    args = read_arg_lines("WA: ", ifp, &arg_count, &line,
258
					  &llen);
205 by Steinar H. Gunderson
Make base-installer handle warnings from debconf better, although still not very good.
259
                    if (args == NULL)
111 by Martin Sjögren
First hash of a progress bar implementation
260
                    {
205 by Steinar H. Gunderson
Make base-installer handle warnings from debconf better, although still not very good.
261
                        child_exit = 1;
262
                        break;
111 by Martin Sjögren
First hash of a progress bar implementation
263
                    }
1267 by Joey Hess
- Improve run-debootstrap's warning handling, display warning on progress
264
                    if (template != NULL)
265
                    {
266
			/* It's hard to choose whether to display a warning
267
			 * as an error/informational template or as a
268
			 * progress item. Currently a progress item seems
269
			 * to fit best with how debootstrap uses warnings
270
			 * that we care about. */
271
                        n_subst(template, arg_count, args);
272
                        debconf_progress_info(debconf, template);
273
                    }
274
                    else if (strstr(line, "WF:") == line)
205 by Steinar H. Gunderson
Make base-installer handle warnings from debconf better, although still not very good.
275
                    {
276
                        ptr = n_sprintf(line+4, arg_count, args);
277
                        if (ptr == NULL)
278
                            return -1;
1471 by Joey Hess
* Display fallback warning messages as using an error template instead
279
                        /* Fallback warning message. Unlike the above,
280
			 * display this as an error, since it could be
281
			 * arbitrarily bad. */
1267 by Joey Hess
- Improve run-debootstrap's warning handling, display warning on progress
282
                        debconf_subst(debconf, DEBCONF_BASE "fallback-warning",
283
				      "INFO", ptr);
284
			debconf_subst(debconf, DEBCONF_BASE "fallback-warning",
285
			              "SECTION", section_text);
1471 by Joey Hess
* Display fallback warning messages as using an error template instead
286
                        debconf_input(debconf, "critical",
287
				      DEBCONF_BASE "fallback-warning");
288
                        debconf_go(debconf);
1267 by Joey Hess
- Improve run-debootstrap's warning handling, display warning on progress
289
                        free(ptr);
290
                    }
291
                    else
292
                    {
1209 by Colin Watson
Use C-style comments in run-debootstrap.
293
                        /* err, don't really know what to do here... there
294
                         * should always be a fallback... */
205 by Steinar H. Gunderson
Make base-installer handle warnings from debconf better, although still not very good.
295
                    }
1267 by Joey Hess
- Improve run-debootstrap's warning handling, display warning on progress
296
297
		    break;
111 by Martin Sjögren
First hash of a progress bar implementation
298
                }
299
            case 'P':
300
                {
301
                    int plow = 0, phigh = 0;
302
                    char what[1024] = "";
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
303
		    char *section_template;
111 by Martin Sjögren
First hash of a progress bar implementation
304
305
                    sscanf(line+3, "%d %d %s", &plow, &phigh, what);
306
                    if (what[0])
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
307
		    {
308
			int i;
309
			for (i = 0; waypoints[i].progress_id != NULL; i++)
310
			{
311
			    if (strcmp(waypoints[i].progress_id, what) == 0)
312
			        {
313
                                    set_progress(i, phigh, plow);
314
315
				    /* Get the description of the section
316
				     * template for this waypoint. */
317
				    if (current_section == i)
318
					    break; /* optimisation */
319
			            current_section = i;
320
			            section_template = find_template("section", what);
321
			            if (section_template)
322
				    {
323
                                            if (! debconf_metaget(debconf, section_template, "description"))
324
					    {
325
                                                free(section_text);
326
                                                section_text = strdup(debconf->value);
327
				            }
328
                                            free(section_template);
329
			            }
330
331
			            break;
332
				}
333
			}
334
		    }
335
		    
408 by Matt Kraai
Fix the handling of P codes without a PF code (closes: #225858).
336
                    args = read_arg_lines("PA: ", ifp, &arg_count, &line,
337
					  &llen);
111 by Martin Sjögren
First hash of a progress bar implementation
338
                    if (args == NULL)
339
                    {
340
                        child_exit = 1;
341
                        break;
342
                    }
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
343
                    if (strstr(line, "PF:") == line)
344
		    {
345
                        /* Does not currently need to do anything;
346
			 * the implementation of debootstrap could change
347
			 * though.. */
348
                    }
408 by Matt Kraai
Fix the handling of P codes without a PF code (closes: #225858).
349
		    else
350
			continue;
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
351
		    
111 by Martin Sjögren
First hash of a progress bar implementation
352
                    break;
353
                }
354
            case 'I':
355
                {
356
                    ptr += 3;
1209 by Colin Watson
Use C-style comments in run-debootstrap.
357
                    /* ptr now contains the identifier of the info */
111 by Martin Sjögren
First hash of a progress bar implementation
358
                    template = find_template("info", ptr);
358 by Joey Hess
some debugging printfs I find useful (commented out)
359
1209 by Colin Watson
Use C-style comments in run-debootstrap.
360
                    /* fprintf(stderr, "info template: %s\n", template); */
358 by Joey Hess
some debugging printfs I find useful (commented out)
361
		    
111 by Martin Sjögren
First hash of a progress bar implementation
362
                    if (strcmp(ptr, "basesuccess") == 0 && template != NULL)
363
                    {
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
364
                        /* all done */
111 by Martin Sjögren
First hash of a progress bar implementation
365
                        child_exit = 1;
366
                        break;
367
                    }
408 by Matt Kraai
Fix the handling of P codes without a PF code (closes: #225858).
368
                    args = read_arg_lines("IA: ", ifp, &arg_count, &line,
369
					  &llen);
111 by Martin Sjögren
First hash of a progress bar implementation
370
                    if (args == NULL)
371
                    {
372
                        child_exit = 1;
373
                        break;
374
                    }
375
                    if (template != NULL)
376
                    {
377
                        n_subst(template, arg_count, args);
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
378
			debconf_subst(debconf, template,
379
			              "SECTION", section_text);
176 by Petter Reinholdtsen
Start using debconf_* macro in run-debootstrap.c.
380
                        debconf_progress_info(debconf, template);
111 by Martin Sjögren
First hash of a progress bar implementation
381
                    }
382
                    else if (strstr(line, "IF:") == line)
383
                    {
384
                        ptr = n_sprintf(line+4, arg_count, args);
385
                        if (ptr == NULL)
386
                            return -1;
1209 by Colin Watson
Use C-style comments in run-debootstrap.
387
                        /* fallback info message */
176 by Petter Reinholdtsen
Start using debconf_* macro in run-debootstrap.c.
388
                        debconf_subst(debconf, DEBCONF_BASE "fallback-info",
389
				      "INFO", ptr);
338 by Joey Hess
- Have debootstrap log to the d-i messages file.
390
			debconf_subst(debconf, DEBCONF_BASE "fallback-info",
391
			              "SECTION", section_text);
176 by Petter Reinholdtsen
Start using debconf_* macro in run-debootstrap.c.
392
                        debconf_progress_info(debconf,
393
					      DEBCONF_BASE "fallback-info");
111 by Martin Sjögren
First hash of a progress bar implementation
394
                        free(ptr);
395
                    }
396
                    else
397
                    {
1209 by Colin Watson
Use C-style comments in run-debootstrap.
398
                        /* err, don't really know what to do here... there
399
                         * should always be a fallback... */
111 by Martin Sjögren
First hash of a progress bar implementation
400
                    }
1267 by Joey Hess
- Improve run-debootstrap's warning handling, display warning on progress
401
402
		    break;
111 by Martin Sjögren
First hash of a progress bar implementation
403
                }
404
        }
408 by Matt Kraai
Fix the handling of P codes without a PF code (closes: #225858).
405
406
	if (child_exit)
407
	    break;
408
111 by Martin Sjögren
First hash of a progress bar implementation
409
        line = NULL;
408 by Matt Kraai
Fix the handling of P codes without a PF code (closes: #225858).
410
	llen = getline(&line, &dummy, ifp);
111 by Martin Sjögren
First hash of a progress bar implementation
411
    }
412
413
    if (waitpid(pid, &status, 0) != -1 && (WIFEXITED(status) != 0))
414
    {
415
        rv = WEXITSTATUS(status);
416
        if (rv != 0)
417
        {
176 by Petter Reinholdtsen
Start using debconf_* macro in run-debootstrap.c.
418
            debconf->commandf(debconf, "SUBST %serror-exitcode EXITCODE %d",
419
			      DEBCONF_BASE, rv);
420
            debconf_input(debconf, "critical", DEBCONF_BASE "error-exitcode");
421
            debconf_go(debconf);
111 by Martin Sjögren
First hash of a progress bar implementation
422
        }
423
        return rv;
424
    }
425
    else
426
    {
427
        kill(SIGKILL, pid);
176 by Petter Reinholdtsen
Start using debconf_* macro in run-debootstrap.c.
428
        debconf_input(debconf, "critical", DEBCONF_BASE "error-abnormal");
429
        debconf_go(debconf);
111 by Martin Sjögren
First hash of a progress bar implementation
430
        return 1;
431
    }
432
}
433
434
int
435
main(int argc, char *argv[])
436
{
437
    char **args;
438
    int i;
435 by Matt Kraai
Always call di_system_init.
439
192 by Petter Reinholdtsen
Make source build using both version 3 and 4 of libd-i.
440
    di_system_init("run-debootstrap");
111 by Martin Sjögren
First hash of a progress bar implementation
441
    debconf = debconfclient_new();
442
    args = (char **)malloc(sizeof(char *) * (argc + 1));
443
    args[0] = "/usr/sbin/debootstrap";
2635 by Cyril Brulebois
Print all run-debootstrap arguments to stdout for improved logging.
444
    printf("%s", args[0]);
445
    for (i = 1; i < argc; i++) {
111 by Martin Sjögren
First hash of a progress bar implementation
446
        args[i] = argv[i];
2635 by Cyril Brulebois
Print all run-debootstrap arguments to stdout for improved logging.
447
        printf(" %s", argv[i]);
448
    }
449
    printf("\n");
450
    fflush(stdout);
111 by Martin Sjögren
First hash of a progress bar implementation
451
    args[argc] = NULL;
452
    return exec_debootstrap(args);
453
}