~ubuntu-branches/ubuntu/hardy/silo/hardy-updates

« back to all changes in this revision

Viewing changes to second/cfg.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabio M. Di Nitto
  • Date: 2007-10-25 09:28:08 UTC
  • mfrom: (15.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20071025092808-1yhj12t7s4zqsfu5
Tags: 1.4.13a+git20070930-1ubuntu1
* Merge from debian unstable, remaining changes:
  - Build with -fno-stack-protector.
  - Change silo.postinst to automatically update the boot block without
    invoking siloconfig and keep asking questions on upgrades.
  - Convert silo.conf to use /dev/disk/by-uuid.
  - Ubuntu maintainer foobar.
  - Fix debian/rules call to dh_installdocs.
  - Drop the requirement of gcc-4.1 and start using default gcc.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Handling and parsing of silo.conf
 
2
   
 
3
   Copyright (C) 1995 Werner Almesberger
 
4
                 1996,1998 Jakub Jelinek
 
5
                 2001 Ben Collins
 
6
   
 
7
   This program is free software; you can redistribute it and/or modify
 
8
   it under the terms of the GNU General Public License as published by
 
9
   the Free Software Foundation; either version 2 of the License, or
 
10
   (at your option) any later version.
 
11
   
 
12
   This program is distributed in the hope that it will be useful,
 
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
   GNU General Public License for more details.
 
16
 
 
17
   You should have received a copy of the GNU General Public License
 
18
   along with this program; if not, write to the Free Software
 
19
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
 
20
   USA.  */
 
21
 
 
22
/* This file gets included by the silo program (userspace), try to be nice */
 
23
#ifndef SILOCONFCHECK
 
24
 
 
25
#include <silo.h>
 
26
#include <stringops.h>
 
27
#include <setjmp.h>
 
28
#ifndef NULL
 
29
#define NULL (void *)0
 
30
#endif
 
31
#include <promlib.h>
 
32
 
 
33
#endif /* !SILOCONFCHECK */
 
34
 
 
35
typedef enum {
 
36
    cft_strg, cft_flag, cft_end
 
37
} CONFIG_TYPE;
 
38
 
 
39
typedef struct {
 
40
    CONFIG_TYPE type;
 
41
    char *name;
 
42
    void *data;
 
43
} CONFIG;
 
44
 
 
45
#define MAX_TOKEN 200
 
46
#define MAX_VAR_NAME MAX_TOKEN
 
47
#ifndef EOF
 
48
#define EOF -1
 
49
#endif
 
50
 
 
51
CONFIG cf_options[] =
 
52
{
 
53
    {cft_strg, "device", NULL},
 
54
    {cft_strg, "partition", NULL},
 
55
    {cft_strg, "default", NULL},
 
56
    {cft_strg, "timeout", NULL},
 
57
    {cft_strg, "message", NULL},
 
58
    {cft_strg, "root", NULL},
 
59
    {cft_strg, "ramdisk", NULL},
 
60
    {cft_flag, "read-only", NULL},
 
61
    {cft_flag, "read-write", NULL},
 
62
    {cft_strg, "append", NULL},
 
63
    {cft_strg, "initrd", NULL},
 
64
    {cft_flag, "initrd-prompt", NULL},
 
65
    {cft_strg, "initrd-size", NULL},
 
66
    {cft_flag, "pause-after", NULL},
 
67
    {cft_strg, "pause-message", NULL},
 
68
    {cft_flag, "fill-reboot-cmd", NULL},
 
69
    {cft_strg, "password", NULL},
 
70
    {cft_flag, "restricted", NULL},
 
71
    {cft_strg, "proll", NULL},
 
72
    {cft_flag, "partition-boot", NULL},
 
73
    {cft_strg, "secondary", NULL},
 
74
    {cft_end, NULL, NULL}};
 
75
 
 
76
CONFIG cf_image[] =
 
77
{
 
78
    {cft_strg, "image", NULL},
 
79
    {cft_strg, "other", NULL},
 
80
    {cft_strg, "label", NULL},
 
81
    {cft_strg, "alias", NULL},
 
82
    {cft_strg, "device", NULL},
 
83
    {cft_strg, "partition", NULL},
 
84
    {cft_strg, "root", NULL},
 
85
    {cft_strg, "ramdisk", NULL},
 
86
    {cft_flag, "read-only", NULL},
 
87
    {cft_flag, "read-write", NULL},
 
88
    {cft_strg, "append", NULL},
 
89
    {cft_strg, "literal", NULL},
 
90
    {cft_strg, "initrd", NULL},
 
91
    {cft_flag, "initrd-prompt", NULL},
 
92
    {cft_strg, "initrd-size", NULL},
 
93
    {cft_flag, "pause-after", NULL},
 
94
    {cft_strg, "pause-message", NULL},
 
95
    {cft_flag, "solaris", NULL},
 
96
    {cft_flag, "fill-reboot-cmd", NULL},
 
97
    {cft_strg, "bootblock", NULL},
 
98
    {cft_flag, "single-key", NULL},
 
99
    {cft_strg, "proll", NULL},
 
100
    {cft_end, NULL, NULL}};
 
101
 
 
102
static char flag_set;
 
103
static char *last_token = NULL, *last_item = NULL, *last_value = NULL;
 
104
static int line_num;
 
105
static int back = 0;            /* can go back by one char */
 
106
static char *currp;
 
107
static char *endp;
 
108
static char *file_name;
 
109
static CONFIG *curr_table = cf_options;
 
110
static jmp_buf env;
 
111
 
 
112
static struct IMAGES {
 
113
    CONFIG table[sizeof (cf_image) / sizeof (cf_image[0])];
 
114
    struct IMAGES *next;
 
115
} *images = NULL;
 
116
 
 
117
void cfg_error (char *msg,...)
 
118
{
 
119
    va_list ap;
 
120
 
 
121
    va_start (ap, msg);
 
122
    printf ("Config file error: ");
 
123
    vprintf (msg, ap);
 
124
    va_end (ap);
 
125
    printf (" near line %d in file %s\n", line_num, file_name);
 
126
    longjmp (env, 1);
 
127
}
 
128
 
 
129
inline int my_getc ()
 
130
{
 
131
    if (currp == endp)
 
132
        return EOF;
 
133
    return *currp++;
 
134
}
 
135
 
 
136
#define next_raw next
 
137
static int next (void)
 
138
{
 
139
    int ch;
 
140
 
 
141
    if (!back)
 
142
        return my_getc ();
 
143
    ch = back;
 
144
    back = 0;
 
145
    return ch;
 
146
}
 
147
 
 
148
static void again (int ch)
 
149
{
 
150
    back = ch;
 
151
}
 
152
 
 
153
static char *cfg_get_token (void)
 
154
{
 
155
    char buf[MAX_TOKEN + 1];
 
156
    char *here;
 
157
    int ch, escaped;
 
158
 
 
159
    if (last_token) {
 
160
        here = last_token;
 
161
        last_token = NULL;
 
162
        return here;
 
163
    }
 
164
    while (1) {
 
165
        while (ch = next (), ch == ' ' || ch == '\t' || ch == '\n')
 
166
            if (ch == '\n')
 
167
                line_num++;
 
168
        if (ch == EOF)
 
169
            return NULL;
 
170
        if (ch != '#')
 
171
            break;
 
172
        while (ch = next_raw (), ch != '\n')
 
173
            if (ch == EOF)
 
174
                return NULL;
 
175
        line_num++;
 
176
    }
 
177
    if (ch == '=')
 
178
        return strdup ("=");
 
179
    if (ch == '"') {
 
180
        here = buf;
 
181
        while (here - buf < MAX_TOKEN) {
 
182
            if ((ch = next ()) == EOF)
 
183
                cfg_error ("EOF in quoted string");
 
184
            if (ch == '"') {
 
185
                *here = 0;
 
186
                return strdup (buf);
 
187
            }
 
188
            if (ch == '\\') {
 
189
                ch = next ();
 
190
                if (ch != '"' && ch != '\\' && ch != '\n')
 
191
                    cfg_error ("Bad use of \\ in quoted string");
 
192
                if (ch == '\n') {
 
193
                    while ((ch = next ()), ch == ' ' || ch == '\t');
 
194
                    if (!ch)
 
195
                        continue;
 
196
                    again (ch);
 
197
                    ch = ' ';
 
198
                }
 
199
            }
 
200
            if (ch == '\n' || ch == '\t')
 
201
                cfg_error ("\\n and \\t are not allowed in quoted strings");
 
202
            *here++ = ch;
 
203
        }
 
204
        cfg_error ("Quoted string is too long");
 
205
        return 0;               /* not reached */
 
206
    }
 
207
    here = buf;
 
208
    escaped = 0;
 
209
    while (here - buf < MAX_TOKEN) {
 
210
        if (escaped) {
 
211
            if (ch == EOF)
 
212
                cfg_error ("\\ precedes EOF");
 
213
            if (ch == '\n')
 
214
                line_num++;
 
215
            else
 
216
                *here++ = ch == '\t' ? ' ' : ch;
 
217
            escaped = 0;
 
218
        } else {
 
219
            if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '#' ||
 
220
                ch == '=' || ch == EOF) {
 
221
                again (ch);
 
222
                *here = 0;
 
223
                return strdup (buf);
 
224
            }
 
225
            if (!(escaped = (ch == '\\')))
 
226
                *here++ = ch;
 
227
        }
 
228
        ch = next ();
 
229
    }
 
230
    cfg_error ("Token is too long");
 
231
    return 0;                   /* not reached */
 
232
}
 
233
 
 
234
static void cfg_return_token (char *token)
 
235
{
 
236
    last_token = token;
 
237
}
 
238
 
 
239
static int cfg_next (char **item, char **value)
 
240
{
 
241
    char *this;
 
242
 
 
243
    if (last_item) {
 
244
        *item = last_item;
 
245
        *value = last_value;
 
246
        last_item = NULL;
 
247
        return 1;
 
248
    }
 
249
    *value = NULL;
 
250
    if (!(*item = cfg_get_token ()))
 
251
        return 0;
 
252
    if (!strcmp (*item, "="))
 
253
        cfg_error ("Syntax error");
 
254
    if (!(this = cfg_get_token ()))
 
255
        return 1;
 
256
    if (strcmp (this, "=")) {
 
257
        cfg_return_token (this);
 
258
        return 1;
 
259
    }
 
260
    if (!(*value = cfg_get_token ()))
 
261
        cfg_error ("Value expected at EOF");
 
262
    if (!strcmp (*value, "="))
 
263
        cfg_error ("Syntax error after %s", *item);
 
264
    return 1;
 
265
}
 
266
 
 
267
static void cfg_return (char *item, char *value)
 
268
{
 
269
    last_item = item;
 
270
    last_value = value;
 
271
}
 
272
 
 
273
static int cfg_set (char *item, char *value)
 
274
{
 
275
    CONFIG *walk;
 
276
 
 
277
    if (!strncasecmp (item, "image", 5) || !strcasecmp (item, "other")) {
 
278
        struct IMAGES **p = &images;
 
279
 
 
280
        if (item[5] == '[' && item[strlen(item) - 1] == ']') {
 
281
                char *p, *q = item;
 
282
                
 
283
                item[5] = 0;
 
284
                for (p = item + 6; q; p = q) {
 
285
                        q = strchr(p, ',');
 
286
                        if (q)
 
287
                                *q++ = 0;
 
288
                        if (strncasecmp (p, "sun4", 4))
 
289
                                return 0;
 
290
                        switch (tolower(p[4])) {
 
291
                        case 0:
 
292
                        case ']': if (architecture == sun4) goto cfg_set_cont; break;
 
293
                        case 'c': if (architecture == sun4c) goto cfg_set_cont; break;
 
294
                        case 'd': if (architecture == sun4d) goto cfg_set_cont; break;
 
295
                        case 'e': if (architecture == sun4e) goto cfg_set_cont; break;
 
296
                        case 'm': if (architecture == sun4m) goto cfg_set_cont; break;
 
297
                        case 'u': if (architecture == sun4u) goto cfg_set_cont; break;
 
298
                        default: return 0;
 
299
                        }
 
300
                }
 
301
                curr_table = (CONFIG *)malloc(sizeof (cf_image));
 
302
                memcpy (curr_table, cf_image, sizeof (cf_image));
 
303
                goto cfg_set_redo;
 
304
        }
 
305
        if (item[5])
 
306
                return 0;
 
307
 cfg_set_cont:
 
308
        while (*p)
 
309
            p = &((*p)->next);
 
310
        *p = malloc (sizeof (struct IMAGES));
 
311
        (*p)->next = 0;
 
312
        curr_table = ((*p)->table);
 
313
        memcpy (curr_table, cf_image, sizeof (cf_image));
 
314
    }
 
315
 cfg_set_redo:
 
316
    for (walk = curr_table; walk->type != cft_end; walk++) {
 
317
        if (walk->name && !strcasecmp (walk->name, item)) {
 
318
            if (value && walk->type != cft_strg)
 
319
                cfg_error ("'%s' doesn't have a value", walk->name);
 
320
            if (!value && walk->type == cft_strg)
 
321
                cfg_error ("Value expected for '%s'", walk->name);
 
322
            if (walk->data)
 
323
                cfg_error ("Duplicate entry '%s'", walk->name);
 
324
            if (walk->type == cft_flag)
 
325
                walk->data = &flag_set;
 
326
            else if (walk->type == cft_strg)
 
327
                walk->data = value;
 
328
            break;
 
329
        }
 
330
    }
 
331
    if (walk->type != cft_end) {
 
332
        if (!strcasecmp (item, "other")) {
 
333
            item = "image";
 
334
            goto cfg_set_redo;
 
335
        }
 
336
        return 1;
 
337
    }
 
338
    cfg_return (item, value);
 
339
    return 0;
 
340
}
 
341
 
 
342
int cfg_parse (char *cfg_file, char *buff, int len)
 
343
{
 
344
    char *item, *value;
 
345
 
 
346
    file_name = cfg_file;
 
347
    currp = buff;
 
348
    endp = currp + len;
 
349
    if (setjmp (env))
 
350
        return -1;
 
351
    while (1) {
 
352
        if (!cfg_next (&item, &value))
 
353
            return 0;
 
354
        if (!cfg_set (item, value))
 
355
            return -1;
 
356
        free (item);
 
357
    }
 
358
}
 
359
 
 
360
static char *cfg_get_strg_i (CONFIG * table, char *item)
 
361
{
 
362
    CONFIG *walk;
 
363
 
 
364
    for (walk = table; walk->type != cft_end; walk++)
 
365
        if (walk->name && !strcasecmp (walk->name, item))
 
366
            return walk->data;
 
367
    return 0;
 
368
}
 
369
 
 
370
char *cfg_get_strg (char *image, char *item)
 
371
{
 
372
    struct IMAGES *p;
 
373
    char *label, *alias;
 
374
    char *ret;
 
375
 
 
376
    if (!image)
 
377
        return cfg_get_strg_i (cf_options, item);
 
378
    for (p = images; p; p = p->next) {
 
379
        label = cfg_get_strg_i (p->table, "label");
 
380
        if (!label) {
 
381
            label = cfg_get_strg_i (p->table, "image");
 
382
            alias = strrchr (label, '/');
 
383
            if (alias)
 
384
                label = alias + 1;
 
385
        }
 
386
        alias = cfg_get_strg_i (p->table, "alias");
 
387
        if (!strcmp (label, image) || (alias && !strcmp (alias, image))) {
 
388
            ret = cfg_get_strg_i (p->table, item);
 
389
            if (!ret)
 
390
                ret = cfg_get_strg_i (cf_options, item);
 
391
            return ret;
 
392
        }
 
393
    }
 
394
    return 0;
 
395
}
 
396
 
 
397
int cfg_get_flag (char *image, char *item)
 
398
{
 
399
    return !!cfg_get_strg (image, item);
 
400
}
 
401
 
 
402
static int printl_count = 0;
 
403
static void printlabel (const char *label, char **addr, const char *match)
 
404
{
 
405
    int len = strlen (label);
 
406
 
 
407
    if (match == NULL ||
 
408
        (strlen(label) >= strlen(match) &&
 
409
        !strncmp(match, label, strlen(match)))) {
 
410
 
 
411
        if (*addr != NULL) {
 
412
            strcpy(*addr, label);
 
413
            *addr += strlen(label) + 1;
 
414
            **addr = '\0';
 
415
        } else {
 
416
            if (!(printl_count % 3))
 
417
                printf ("\n");
 
418
            printf ("%s", label);
 
419
            while (len++ < 25)
 
420
                putchar (' ');
 
421
        }
 
422
        printl_count++;
 
423
    }
 
424
}
 
425
 
 
426
int cfg_print_images (char *addr, char *match)
 
427
{
 
428
    struct IMAGES *p;
 
429
    char *label, *alias;
 
430
 
 
431
    printl_count = 0;
 
432
    if (addr) addr[0] = '\0';
 
433
 
 
434
    for (p = images; p; p = p->next) {
 
435
        label = cfg_get_strg_i (p->table, "label");
 
436
        if (!label) {
 
437
            label = cfg_get_strg_i (p->table, "image");
 
438
            alias = strrchr (label, '/');
 
439
            if (alias)
 
440
                label = alias + 1;
 
441
        }
 
442
        alias = cfg_get_strg_i (p->table, "alias");
 
443
        printlabel(label, &addr, match);
 
444
        if (alias)
 
445
            printlabel (alias, &addr, match);
 
446
    }
 
447
    if (!addr && printl_count)
 
448
        printf ("\n");
 
449
    return printl_count;
 
450
}
 
451
 
 
452
char *cfg_get_default (void)
 
453
{
 
454
    char *label;
 
455
    char *ret = cfg_get_strg_i (cf_options, "default");
 
456
 
 
457
    if (ret)
 
458
        return ret;
 
459
    if (!images)
 
460
        return 0;
 
461
    ret = cfg_get_strg_i (images->table, "label");
 
462
    if (!ret) {
 
463
        ret = cfg_get_strg_i (images->table, "image");
 
464
        label = strrchr (ret, '/');
 
465
        if (label)
 
466
            ret = label + 1;
 
467
    }
 
468
    return ret;
 
469
}