~ubuntu-branches/ubuntu/raring/base-installer/raring

1 by Colin Watson
* Updated translations:
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
12
#include "waypoints.h"
13
14
#define DEBCONF_BASE          "base-installer/debootstrap/"
15
16
struct debconfclient *debconf = NULL;
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
17
int progress_start_position = 0;
1 by Colin Watson
* Updated translations:
18
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
19
/* args = read_arg_lines("EA: ", ifp, &arg_count, &line); */
1 by Colin Watson
* Updated translations:
20
char **
21
read_arg_lines(const char *prefix, FILE *ifp, int *arg_count, char **final_line,
22
	       int *llen)
23
{
24
    static char **args = NULL;
25
    static int arg_max = 0;
26
    size_t dummy = 0;
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;
37
        if ((*llen = getline(final_line, &dummy, ifp)) <= 0)
38
        {
39
            return NULL;
40
        }
41
        (*final_line)[*llen-1] = 0;
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));
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
49
            /* we got arguments. */
1 by Colin Watson
* Updated translations:
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
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
84
/* changes in 'code' */
1 by Colin Watson
* Updated translations:
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);
93
    if (debconf_metaget(debconf, p, "description") == 0)
94
        return p;
95
    else
96
    {
97
        free(p);
98
        return NULL;
99
    }
100
}
101
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
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
1 by Colin Watson
* Updated translations:
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;
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
117
118
    prev_waypoint = waypoints[current_section].startpercent;
1 by Colin Watson
* Updated translations:
119
    if (current_section > 0)
120
        section_span = waypoints[current_section].endpercent - prev_waypoint;
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
121
    else
1 by Colin Watson
* Updated translations:
122
        section_span = 0;
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
123
1 by Colin Watson
* Updated translations:
124
    if (phigh > 0)
125
        section_fraction = (float) plow / (float) phigh;
126
    else
127
        section_fraction = 0;
128
    if (section_fraction > 1)
129
        section_fraction = 1;
130
			
131
    percent = prev_waypoint + (section_span * section_fraction);
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
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
139
140
    debconf_progress_set(debconf, progress_start_position + percent);
1 by Colin Watson
* Updated translations:
141
}
142
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;
155
    char *ptr, *line, *template, *section_text = NULL;
156
    int llen;
157
    size_t dummy = 0;
158
    int current_section = 0;
5 by Colin Watson
Restore usplash as base-installer/kernel/linux/extra-packages-2.6
159
    int child_exit = 0;
1 by Colin Watson
* Updated translations:
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);
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
175
        /* These are needed to hack around a hack (!) in update-inetd
176
         * and to not confuse debconf's postinst */
1 by Colin Watson
* Updated translations:
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
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
191
    progress_start_position = get_progress_start_position();
192
1 by Colin Watson
* Updated translations:
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;
201
    llen = getline(&line, &dummy, ifp);
202
    while (!child_exit && llen > 0)
203
    {
204
        line[llen-1] = 0;
205
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
206
	/* fprintf(stderr, "got line: %s\n", line); */
1 by Colin Watson
* Updated translations:
207
	
208
        ptr = line;
209
        switch (ptr[0])
210
        {
211
            case 'E':
212
                {
213
                    ptr += 3;
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
214
                    /* ptr now contains the identifier of the error. */
1 by Colin Watson
* Updated translations:
215
                    template = find_template("error", ptr);
216
                    args = read_arg_lines("EA: ", ifp, &arg_count, &line,
217
					  &llen);
218
                    if (args == NULL)
219
                    {
220
                        child_exit = 1;
221
                        break;
222
                    }
223
                    if (template != NULL)
224
                    {
225
                        n_subst(template, arg_count, args);
226
                        debconf_input(debconf, "critical", template);
227
                        debconf_go(debconf);
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;
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
234
                        /* fallback error message */
1 by Colin Watson
* Updated translations:
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);
240
                        free(ptr);
241
                    }
242
                    else
243
                    {
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
244
                        /* err, don't really know what to do here... there
245
                         * should always be a fallback... */
1 by Colin Watson
* Updated translations:
246
                    }
247
                    return -1;
248
                }
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
249
            case 'W':
1 by Colin Watson
* Updated translations:
250
                {
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
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
		    
1 by Colin Watson
* Updated translations:
257
                    args = read_arg_lines("WA: ", ifp, &arg_count, &line,
258
					  &llen);
259
                    if (args == NULL)
260
                    {
261
                        child_exit = 1;
262
                        break;
263
                    }
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
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)
1 by Colin Watson
* Updated translations:
275
                    {
276
                        ptr = n_sprintf(line+4, arg_count, args);
277
                        if (ptr == NULL)
278
                            return -1;
5 by Colin Watson
Restore usplash as base-installer/kernel/linux/extra-packages-2.6
279
                        /* Fallback warning message. Unlike the above,
280
			 * display this as an error, since it could be
281
			 * arbitrarily bad. */
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
282
                        debconf_subst(debconf, DEBCONF_BASE "fallback-warning",
283
				      "INFO", ptr);
284
			debconf_subst(debconf, DEBCONF_BASE "fallback-warning",
285
			              "SECTION", section_text);
5 by Colin Watson
Restore usplash as base-installer/kernel/linux/extra-packages-2.6
286
                        debconf_input(debconf, "critical",
287
				      DEBCONF_BASE "fallback-warning");
288
                        debconf_go(debconf);
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
289
                        free(ptr);
290
                    }
291
                    else
292
                    {
293
                        /* err, don't really know what to do here... there
294
                         * should always be a fallback... */
295
                    }
1 by Colin Watson
* Updated translations:
296
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
297
		    break;
1 by Colin Watson
* Updated translations:
298
                }
299
            case 'P':
300
                {
301
                    int plow = 0, phigh = 0;
302
                    char what[1024] = "";
303
		    char *section_template;
304
305
                    sscanf(line+3, "%d %d %s", &plow, &phigh, what);
306
                    if (what[0])
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
		    
336
                    args = read_arg_lines("PA: ", ifp, &arg_count, &line,
337
					  &llen);
338
                    if (args == NULL)
339
                    {
340
                        child_exit = 1;
341
                        break;
342
                    }
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
                    }
349
		    else
350
			continue;
351
		    
352
                    break;
353
                }
354
            case 'I':
355
                {
356
                    ptr += 3;
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
357
                    /* ptr now contains the identifier of the info */
1 by Colin Watson
* Updated translations:
358
                    template = find_template("info", ptr);
359
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
360
                    /* fprintf(stderr, "info template: %s\n", template); */
1 by Colin Watson
* Updated translations:
361
		    
362
                    if (strcmp(ptr, "basesuccess") == 0 && template != NULL)
363
                    {
364
                        /* all done */
365
                        child_exit = 1;
366
                        break;
367
                    }
368
                    args = read_arg_lines("IA: ", ifp, &arg_count, &line,
369
					  &llen);
370
                    if (args == NULL)
371
                    {
372
                        child_exit = 1;
373
                        break;
374
                    }
375
                    if (template != NULL)
376
                    {
377
                        n_subst(template, arg_count, args);
378
			debconf_subst(debconf, template,
379
			              "SECTION", section_text);
380
                        debconf_progress_info(debconf, template);
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;
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
387
                        /* fallback info message */
1 by Colin Watson
* Updated translations:
388
                        debconf_subst(debconf, DEBCONF_BASE "fallback-info",
389
				      "INFO", ptr);
390
			debconf_subst(debconf, DEBCONF_BASE "fallback-info",
391
			              "SECTION", section_text);
392
                        debconf_progress_info(debconf,
393
					      DEBCONF_BASE "fallback-info");
394
                        free(ptr);
395
                    }
396
                    else
397
                    {
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
398
                        /* err, don't really know what to do here... there
399
                         * should always be a fallback... */
1 by Colin Watson
* Updated translations:
400
                    }
4 by Colin Watson
Drop back to initrd-tools on hppa and ia64, where initramfs-tools
401
402
		    break;
1 by Colin Watson
* Updated translations:
403
                }
404
        }
405
406
	if (child_exit)
407
	    break;
408
409
        line = NULL;
410
	llen = getline(&line, &dummy, ifp);
411
    }
412
413
    if (waitpid(pid, &status, 0) != -1 && (WIFEXITED(status) != 0))
414
    {
415
        rv = WEXITSTATUS(status);
416
        if (rv != 0)
417
        {
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);
422
        }
423
        return rv;
424
    }
425
    else
426
    {
427
        kill(SIGKILL, pid);
428
        debconf_input(debconf, "critical", DEBCONF_BASE "error-abnormal");
429
        debconf_go(debconf);
430
        return 1;
431
    }
432
}
433
434
int
435
main(int argc, char *argv[])
436
{
437
    char **args;
438
    int i;
439
440
    di_system_init("run-debootstrap");
441
    debconf = debconfclient_new();
442
    args = (char **)malloc(sizeof(char *) * (argc + 1));
443
    args[0] = "/usr/sbin/debootstrap";
444
    for (i = 1; i < argc; i++)
445
        args[i] = argv[i];
446
    args[argc] = NULL;
447
    return exec_debootstrap(args);
448
}