source: trunk/minix/commands/i386/mtools-3.9.7/config.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 18.6 KB
Line 
1#include "sysincludes.h"
2#include "mtools.h"
3#include "codepage.h"
4#include "mtoolsPaths.h"
5
6/* global variables */
7/* they are not really harmful here, because there is only one configuration
8 * file per invocations */
9
10#ifndef NO_CONFIG
11
12#define MAX_LINE_LEN 256
13
14/* scanner */
15static char buffer[MAX_LINE_LEN+1]; /* buffer for the whole line */
16static char *pos; /* position in line */
17static char *token; /* last scanned token */
18static int token_length; /* length of the token */
19static FILE *fp; /* file pointer for configuration file */
20static int linenumber; /* current line number. Only used for printing
21 * error messages */
22static int lastTokenLinenumber; /* line numnber for last token */
23static const char *filename; /* current file name. Only used for printing
24 * error messages */
25static int file_nr=0;
26
27
28static int flag_mask; /* mask of currently set flags */
29
30/* devices */
31static int cur_devs; /* current number of defined devices */
32static int cur_dev; /* device being filled in. If negative, none */
33static int trusted=0; /* is the currently parsed device entry trusted? */
34static int nr_dev; /* number of devices that the current table can hold */
35static int token_nr; /* number of tokens in line */
36static char letters[][2] = { /* drive letter to letter-as-a-string */
37 "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
38 "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
39};
40
41#endif /* !NO_CONFIG */
42
43struct device *devices; /* the device table */
44
45/* "environment" variables */
46unsigned int mtools_skip_check=0;
47unsigned int mtools_fat_compatibility=0;
48unsigned int mtools_ignore_short_case=0;
49unsigned int mtools_rate_0=0;
50unsigned int mtools_rate_any=0;
51unsigned int mtools_no_vfat=0;
52unsigned int mtools_numeric_tail=1;
53unsigned int mtools_dotted_dir=0;
54unsigned int mtools_twenty_four_hour_clock=1;
55char *mtools_date_string="mm-dd-yyyy";
56char *country_string=0;
57
58#ifndef NO_CONFIG
59
60typedef struct switches_l {
61 const char *name;
62 caddr_t address;
63 enum {
64 T_INT,
65 T_STRING,
66 T_UINT
67 } type;
68} switches_t;
69
70static switches_t switches[] = {
71 { "MTOOLS_LOWER_CASE", (caddr_t) & mtools_ignore_short_case, T_UINT },
72 { "MTOOLS_FAT_COMPATIBILITY", (caddr_t) & mtools_fat_compatibility, T_UINT },
73 { "MTOOLS_SKIP_CHECK", (caddr_t) & mtools_skip_check, T_UINT },
74 { "MTOOLS_NO_VFAT", (caddr_t) & mtools_no_vfat, T_UINT },
75 { "MTOOLS_RATE_0", (caddr_t) &mtools_rate_0, T_UINT },
76 { "MTOOLS_RATE_ANY", (caddr_t) &mtools_rate_any, T_UINT },
77 { "MTOOLS_NAME_NUMERIC_TAIL", (caddr_t) &mtools_numeric_tail, T_UINT },
78 { "MTOOLS_DOTTED_DIR", (caddr_t) &mtools_dotted_dir, T_UINT },
79 { "MTOOLS_TWENTY_FOUR_HOUR_CLOCK",
80 (caddr_t) &mtools_twenty_four_hour_clock, T_UINT },
81 { "MTOOLS_DATE_STRING",
82 (caddr_t) &mtools_date_string, T_STRING },
83 { "COUNTRY", (caddr_t) &country_string, T_STRING }
84};
85
86typedef struct {
87 const char *name;
88 int flag;
89} flags_t;
90
91static flags_t openflags[] = {
92#ifdef O_SYNC
93 { "sync", O_SYNC },
94#endif
95#ifdef O_NDELAY
96 { "nodelay", O_NDELAY },
97#endif
98#ifdef O_EXCL
99 { "exclusive", O_EXCL },
100#endif
101 { "none", 0 } /* hack for those compilers that choke on commas
102 * after the last element of an array */
103};
104
105static flags_t misc_flags[] = {
106#ifdef USE_XDF
107 { "use_xdf", USE_XDF_FLAG },
108#endif
109 { "scsi", SCSI_FLAG },
110 { "nolock", NOLOCK_FLAG },
111 { "mformat_only", MFORMAT_ONLY_FLAG },
112 { "filter", FILTER_FLAG },
113 { "privileged", PRIV_FLAG },
114 { "vold", VOLD_FLAG },
115 { "remote", FLOPPYD_FLAG }
116};
117
118static struct {
119 const char *name;
120 signed char fat_bits;
121 int tracks;
122 unsigned short heads;
123 unsigned short sectors;
124} default_formats[] = {
125 { "hd514", 12, 80, 2, 15 },
126 { "high-density-5-1/4", 12, 80, 2, 15 },
127 { "1.2m", 12, 80, 2, 15 },
128
129 { "hd312", 12, 80, 2, 18 },
130 { "high-density-3-1/2", 12, 80, 2, 18 },
131 { "1.44m", 12, 80, 2, 18 },
132
133 { "dd312", 12, 80, 2, 9 },
134 { "double-density-3-1/2", 12, 80, 2, 9 },
135 { "720k", 12, 80, 2, 9 },
136
137 { "dd514", 12, 40, 2, 9 },
138 { "double-density-5-1/4", 12, 40, 2, 9 },
139 { "360k", 12, 40, 2, 9 },
140
141 { "320k", 12, 40, 2, 8 },
142 { "180k", 12, 40, 1, 9 },
143 { "160k", 12, 40, 1, 8 }
144};
145
146#define OFFS(x) ((caddr_t)&((struct device *)0)->x)
147
148static switches_t dswitches[]= {
149 { "FILE", OFFS(name), T_STRING },
150 { "OFFSET", OFFS(offset), T_UINT },
151 { "PARTITION", OFFS(partition), T_UINT },
152 { "FAT", OFFS(fat_bits), T_INT },
153 { "FAT_BITS", OFFS(fat_bits), T_UINT },
154 { "MODE", OFFS(mode), T_UINT },
155 { "TRACKS", OFFS(tracks), T_UINT },
156 { "CYLINDERS", OFFS(tracks), T_UINT },
157 { "HEADS", OFFS(heads), T_UINT },
158 { "SECTORS", OFFS(sectors), T_UINT },
159 { "HIDDEN", OFFS(hidden), T_UINT },
160 { "PRECMD", OFFS(precmd), T_STRING },
161 { "BLOCKSIZE", OFFS(blocksize), T_UINT }
162};
163
164static void syntax(const char *msg, int thisLine)
165{
166 char *drive=NULL;
167 if(thisLine)
168 lastTokenLinenumber = linenumber;
169 if(cur_dev >= 0)
170 drive = devices[cur_dev].drive;
171 fprintf(stderr,"Syntax error at line %d ", lastTokenLinenumber);
172 if(drive) fprintf(stderr, "for drive %s: ", drive);
173 if(token) fprintf(stderr, "column %ld ", (long)(token - buffer));
174 fprintf(stderr, "in file %s: %s\n", filename, msg);
175 exit(1);
176}
177
178static void get_env_conf(void)
179{
180 char *s;
181 int i;
182
183 for(i=0; i< sizeof(switches) / sizeof(*switches); i++) {
184 s = getenv(switches[i].name);
185 if(s) {
186 if(switches[i].type == T_INT)
187 * ((int *)switches[i].address) = (int) strtol(s,0,0);
188 if(switches[i].type == T_UINT)
189 * ((int *)switches[i].address) = (unsigned int) strtoul(s,0,0);
190 else if (switches[i].type == T_STRING)
191 * ((char **)switches[i].address) = s;
192 }
193 }
194}
195
196static int mtools_getline(void)
197{
198 if(!fgets(buffer, MAX_LINE_LEN, fp))
199 return -1;
200 linenumber++;
201 pos = buffer;
202 token_nr = 0;
203 buffer[MAX_LINE_LEN] = '\0';
204 if(strlen(buffer) == MAX_LINE_LEN)
205 syntax("line too long", 1);
206 return 0;
207}
208
209static void skip_junk(int expect)
210{
211 lastTokenLinenumber = linenumber;
212 while(!pos || !*pos || strchr(" #\n\t", *pos)) {
213 if(!pos || !*pos || *pos == '#') {
214 if(mtools_getline()) {
215 pos = 0;
216 if(expect)
217 syntax("end of file unexpected", 1);
218 return;
219 }
220 } else
221 pos++;
222 }
223 token_nr++;
224}
225
226/* get the next token */
227static char *get_next_token(void)
228{
229 skip_junk(0);
230 if(!pos) {
231 token_length = 0;
232 token = 0;
233 return 0;
234 }
235 token = pos;
236 token_length = strcspn(token, " \t\n#:=");
237 pos += token_length;
238 return token;
239}
240
241static int match_token(const char *template)
242{
243 return (strlen(template) == token_length &&
244 !strncasecmp(template, token, token_length));
245}
246
247static void expect_char(char c)
248{
249 char buf[11];
250
251 skip_junk(1);
252 if(*pos != c) {
253 sprintf(buf, "expected %c", c);
254 syntax(buf, 1);
255 }
256 pos++;
257}
258
259static char *get_string(void)
260{
261 char *end, *str;
262
263 skip_junk(1);
264 if(*pos != '"')
265 syntax(" \" expected", 0);
266 str = pos+1;
267 end = strchr(str, '\"');
268 if(!end)
269 syntax("unterminated string constant", 1);
270 *end = '\0';
271 pos = end+1;
272 return str;
273}
274
275static unsigned int get_unumber(void)
276{
277 char *last;
278 unsigned int n;
279
280 skip_junk(1);
281 last = pos;
282 n=(unsigned int) strtoul(pos, &pos, 0);
283 if(last == pos)
284 syntax("numeral expected", 0);
285 pos++;
286 token_nr++;
287 return n;
288}
289
290static unsigned int get_number(void)
291{
292 char *last;
293 int n;
294
295 skip_junk(1);
296 last = pos;
297 n=(int) strtol(pos, &pos, 0);
298 if(last == pos)
299 syntax("numeral expected", 0);
300 pos++;
301 token_nr++;
302 return n;
303}
304
305/* purge all entries pertaining to a given drive from the table */
306static void purge(char drive, int fn)
307{
308 int i,j;
309
310 drive = toupper(drive);
311 for(j=0, i=0; i < cur_devs; i++) {
312 if(devices[i].drive[0] != drive ||
313 devices[i].drive[1] != 0 ||
314 devices[i].file_nr == fn)
315 devices[j++] = devices[i];
316 }
317 cur_devs = j;
318}
319
320static void grow(void)
321{
322 if(cur_devs >= nr_dev - 2) {
323 nr_dev = (cur_devs + 2) << 1;
324 if(!(devices=Grow(devices, nr_dev, struct device))){
325 printOom();
326 exit(1);
327 }
328 }
329}
330
331
332static void init_drive(void)
333{
334 memset((char *)&devices[cur_dev], 0, sizeof(struct device));
335 devices[cur_dev].ssize = 2;
336}
337
338/* prepends a device to the table */
339static void prepend(void)
340{
341 int i;
342
343 grow();
344 for(i=cur_devs; i>0; i--)
345 devices[i] = devices[i-1];
346 cur_dev = 0;
347 cur_devs++;
348 init_drive();
349}
350
351
352/* appends a device to the table */
353static void append(void)
354{
355 grow();
356 cur_dev = cur_devs;
357 cur_devs++;
358 init_drive();
359}
360
361
362static void finish_drive_clause(void)
363{
364 char *drive;
365 if(cur_dev == -1) {
366 trusted = 0;
367 return;
368 }
369 drive = devices[cur_dev].drive;
370 if(!devices[cur_dev].name)
371 syntax("missing filename", 0);
372 if(devices[cur_dev].tracks ||
373 devices[cur_dev].heads ||
374 devices[cur_dev].sectors) {
375 if(!devices[cur_dev].tracks ||
376 !devices[cur_dev].heads ||
377 !devices[cur_dev].sectors)
378 syntax("incomplete geometry: either indicate all of track/heads/sectors or none of them", 0);
379 if(!(devices[cur_dev].misc_flags &
380 (MFORMAT_ONLY_FLAG | FILTER_FLAG)))
381 syntax("if you supply a geometry, you also must supply one of the `mformat_only' or `filter' flags", 0);
382 }
383 devices[cur_dev].file_nr = file_nr;
384 devices[cur_dev].cfg_filename = filename;
385 if(! (flag_mask & PRIV_FLAG) && IS_SCSI(&devices[cur_dev]))
386 devices[cur_dev].misc_flags |= PRIV_FLAG;
387 if(!trusted && (devices[cur_dev].misc_flags & PRIV_FLAG)) {
388 fprintf(stderr,
389 "Warning: privileged flag ignored for drive %s: defined in file %s\n",
390 devices[cur_dev].drive, filename);
391 devices[cur_dev].misc_flags &= ~PRIV_FLAG;
392 }
393 trusted = 0;
394 cur_dev = -1;
395}
396
397static int set_var(struct switches_l *switches, int nr,
398 caddr_t base_address)
399{
400 int i;
401 for(i=0; i < nr; i++) {
402 if(match_token(switches[i].name)) {
403 expect_char('=');
404 if(switches[i].type == T_UINT)
405 * ((int *)((long)switches[i].address+base_address)) =
406 get_unumber();
407 if(switches[i].type == T_INT)
408 * ((int *)((long)switches[i].address+base_address)) =
409 get_number();
410 else if (switches[i].type == T_STRING)
411 * ((char**)((long)switches[i].address+base_address))=
412 strdup(get_string());
413 return 0;
414 }
415 }
416 return 1;
417}
418
419static int set_openflags(struct device *dev)
420{
421 int i;
422
423 for(i=0; i < sizeof(openflags) / sizeof(*openflags); i++) {
424 if(match_token(openflags[i].name)) {
425 dev->mode |= openflags[i].flag;
426 return 0;
427 }
428 }
429 return 1;
430}
431
432static int set_misc_flags(struct device *dev)
433{
434 int i;
435
436 for(i=0; i < sizeof(misc_flags) / sizeof(*misc_flags); i++) {
437 if(match_token(misc_flags[i].name)) {
438 flag_mask |= misc_flags[i].flag;
439 skip_junk(0);
440 if(pos && *pos == '=') {
441 pos++;
442 switch(get_number()) {
443 case 0:
444 return 0;
445 case 1:
446 break;
447 default:
448 syntax("expected 0 or 1", 0);
449 }
450 }
451 dev->misc_flags |= misc_flags[i].flag;
452 return 0;
453 }
454 }
455 return 1;
456}
457
458static int set_def_format(struct device *dev)
459{
460 int i;
461
462 for(i=0; i < sizeof(default_formats)/sizeof(*default_formats); i++) {
463 if(match_token(default_formats[i].name)) {
464 if(!dev->ssize)
465 dev->ssize = 2;
466 if(!dev->tracks)
467 dev->tracks = default_formats[i].tracks;
468 if(!dev->heads)
469 dev->heads = default_formats[i].heads;
470 if(!dev->sectors)
471 dev->sectors = default_formats[i].sectors;
472 if(!dev->fat_bits)
473 dev->fat_bits = default_formats[i].fat_bits;
474 return 0;
475 }
476 }
477 return 1;
478}
479
480static void get_codepage(void)
481{
482 int i;
483 unsigned short n;
484
485 if(!Codepage)
486 Codepage = New(Codepage_t);
487 for(i=0; i<128; i++) {
488 n = get_number();
489 if(n > 0xff)
490 n = 0x5f;
491 Codepage->tounix[i] = n;
492 }
493}
494
495static void get_toupper(void)
496{
497 int i;
498
499 if(!mstoupper)
500 mstoupper = safe_malloc(128);
501 for(i=0; i<128; i++)
502 mstoupper[i] = get_number();
503}
504
505static void parse_old_device_line(char drive)
506{
507 char name[MAXPATHLEN];
508 int items;
509 long offset;
510 char newdrive;
511
512 /* finish any old drive */
513 finish_drive_clause();
514
515 /* purge out data of old configuration files */
516 purge(drive, file_nr);
517
518 /* reserve slot */
519 append();
520 items = sscanf(token,"%c %s %i %i %i %i %li",
521 &newdrive,name,&devices[cur_dev].fat_bits,
522 &devices[cur_dev].tracks,&devices[cur_dev].heads,
523 &devices[cur_dev].sectors, &offset);
524 devices[cur_dev].offset = (off_t) offset;
525 switch(items){
526 case 2:
527 devices[cur_dev].fat_bits = 0;
528 /* fall thru */
529 case 3:
530 devices[cur_dev].sectors = 0;
531 devices[cur_dev].heads = 0;
532 devices[cur_dev].tracks = 0;
533 /* fall thru */
534 case 6:
535 devices[cur_dev].offset = 0;
536 /* fall thru */
537 default:
538 break;
539 case 0:
540 case 1:
541 case 4:
542 case 5:
543 syntax("bad number of parameters", 1);
544 exit(1);
545 }
546 if(!devices[cur_dev].tracks){
547 devices[cur_dev].sectors = 0;
548 devices[cur_dev].heads = 0;
549 }
550
551 devices[cur_dev].drive = letters[toupper(newdrive) - 'A'];
552 if (!(devices[cur_dev].name = strdup(name))) {
553 printOom();
554 exit(1);
555 }
556 finish_drive_clause();
557 pos=0;
558}
559
560static int parse_one(int privilege)
561{
562 int action=0;
563
564 get_next_token();
565 if(!token)
566 return 0;
567
568 if((match_token("drive") && ((action = 1)))||
569 (match_token("drive+") && ((action = 2))) ||
570 (match_token("+drive") && ((action = 3))) ||
571 (match_token("clear_drive") && ((action = 4))) ) {
572 /* finish off the previous drive */
573 finish_drive_clause();
574
575 get_next_token();
576 if(token_length != 1)
577 syntax("drive letter expected", 0);
578
579 if(action==1 || action==4)
580 /* replace existing drive */
581 purge(token[0], file_nr);
582 if(action==4)
583 return 1;
584 if(action==3)
585 prepend();
586 else
587 append();
588 memset((char*)(devices+cur_dev), 0, sizeof(*devices));
589 trusted = privilege;
590 flag_mask = 0;
591 devices[cur_dev].drive = letters[toupper(token[0]) - 'A'];
592 expect_char(':');
593 return 1;
594 }
595 if(token_nr == 1 && token_length == 1) {
596 parse_old_device_line(token[0]);
597 return 1;
598 }
599 if(match_token("default_fucase")) {
600 free(mstoupper);
601 mstoupper=0;
602 }
603 if(match_token("default_tounix")) {
604 Free(Codepage);
605 Codepage = 0;
606 }
607 if(match_token("fucase")) {
608 expect_char(':');
609 get_toupper();
610 return 1;
611 }
612 if(match_token("tounix")) {
613 expect_char(':');
614 get_codepage();
615 return 1;
616 }
617
618 if((cur_dev < 0 ||
619 (set_var(dswitches,
620 sizeof(dswitches)/sizeof(*dswitches),
621 (caddr_t)&devices[cur_dev]) &&
622 set_openflags(&devices[cur_dev]) &&
623 set_misc_flags(&devices[cur_dev]) &&
624 set_def_format(&devices[cur_dev]))) &&
625 set_var(switches,
626 sizeof(switches)/sizeof(*switches), 0))
627 syntax("unrecognized keyword", 1);
628 return 1;
629}
630
631static int parse(const char *name, int privilege)
632{
633 fp = fopen(name, "r");
634 if(!fp)
635 return 0;
636 file_nr++;
637 filename = strdup(name);
638 linenumber = 0;
639 lastTokenLinenumber = 0;
640 pos = 0;
641 token = 0;
642 cur_dev = -1; /* no current device */
643
644 while(parse_one(privilege));
645 finish_drive_clause();
646 fclose(fp);
647 return 1;
648}
649
650void read_config(void)
651{
652 char *homedir;
653 char *envConfFile;
654 char conf_file[MAXPATHLEN+sizeof(CFG_FILE1)];
655
656
657 /* copy compiled-in devices */
658 file_nr = 0;
659 cur_devs = nr_const_devices;
660 nr_dev = nr_const_devices + 2;
661 devices = NewArray(nr_dev, struct device);
662 if(!devices) {
663 printOom();
664 exit(1);
665 }
666 if(nr_const_devices)
667 memcpy(devices, const_devices,
668 nr_const_devices*sizeof(struct device));
669
670 (void) ((parse(CONF_FILE,1) |
671 parse(LOCAL_CONF_FILE,1) |
672 parse(SYS_CONF_FILE,1)) ||
673 (parse(OLD_CONF_FILE,1) |
674 parse(OLD_LOCAL_CONF_FILE,1)));
675 /* the old-name configuration files only get executed if none of the
676 * new-name config files were used */
677
678 homedir = get_homedir();
679 if ( homedir ){
680 strncpy(conf_file, homedir, MAXPATHLEN );
681 conf_file[MAXPATHLEN]='\0';
682 strcat( conf_file, CFG_FILE1);
683 parse(conf_file,0);
684 }
685 memset((char *)&devices[cur_devs],0,sizeof(struct device));
686
687 envConfFile = getenv("MTOOLSRC");
688 if(envConfFile)
689 parse(envConfFile,0);
690
691 /* environmental variables */
692 get_env_conf();
693 if(mtools_skip_check)
694 mtools_fat_compatibility=1;
695 init_codepage();
696}
697
698void mtoolstest(int argc, char **argv, int type)
699{
700 /* testing purposes only */
701 struct device *dev;
702 int i,j;
703 char *drive=NULL;
704 char *path;
705
706 if (argc > 1 && (path = skip_drive(argv[1])) > argv[1]) {
707 drive = get_drive(argv[1], NULL);
708 }
709
710 for (dev=devices; dev->name; dev++) {
711 if(drive && strcmp(drive, dev->drive) != 0)
712 continue;
713 printf("drive %s:\n", dev->drive);
714 printf("\t#fn=%d mode=%d ",
715 dev->file_nr, dev->mode);
716 if(dev->cfg_filename)
717 printf("defined in %s\n", dev->cfg_filename);
718 else
719 printf("builtin\n");
720 printf("\tfile=\"%s\" fat_bits=%d \n",
721 dev->name,dev->fat_bits);
722 printf("\ttracks=%d heads=%d sectors=%d hidden=%d\n",
723 dev->tracks, dev->heads, dev->sectors, dev->hidden);
724 printf("\toffset=0x%lx\n", (long) dev->offset);
725 printf("\tpartition=%d\n", dev->partition);
726
727 if(dev->misc_flags)
728 printf("\t");
729
730 if(IS_SCSI(dev))
731 printf("scsi ");
732 if(IS_PRIVILEGED(dev))
733 printf("privileged");
734 if(IS_MFORMAT_ONLY(dev))
735 printf("mformat_only ");
736 if(SHOULD_USE_VOLD(dev))
737 printf("vold ");
738#ifdef USE_XDF
739 if(SHOULD_USE_XDF(dev))
740 printf("use_xdf ");
741#endif
742 if(dev->misc_flags)
743 printf("\n");
744
745 if(dev->mode)
746 printf("\t");
747#ifdef O_SYNC
748 if(dev->mode & O_SYNC)
749 printf("sync ");
750#endif
751#ifdef O_NDELAY
752 if((dev->mode & O_NDELAY))
753 printf("nodelay ");
754#endif
755#ifdef O_EXCL
756 if((dev->mode & O_EXCL))
757 printf("exclusive ");
758#endif
759 if(dev->mode)
760 printf("\n");
761
762 if(dev->precmd)
763 printf("\tprecmd=%s\n", dev->precmd);
764
765 printf("\n");
766 }
767
768 printf("tounix:\n");
769 for(i=0; i < 16; i++) {
770 putchar('\t');
771 for(j=0; j<8; j++)
772 printf("0x%02x ",
773 (unsigned char)Codepage->tounix[i*8+j]);
774 putchar('\n');
775 }
776 printf("\nfucase:\n");
777 for(i=0; i < 16; i++) {
778 putchar('\t');
779 for(j=0; j<8; j++)
780 printf("0x%02x ",
781 (unsigned char)mstoupper[i*8+j]);
782 putchar('\n');
783 }
784 if(country_string)
785 printf("COUNTRY=%s\n", country_string);
786 printf("mtools_fat_compatibility=%d\n",mtools_fat_compatibility);
787 printf("mtools_skip_check=%d\n",mtools_skip_check);
788 printf("mtools_lower_case=%d\n",mtools_ignore_short_case);
789
790 exit(0);
791}
792
793#else /* NO_CONFIG */
794
795void read_config(void)
796{
797 /* only compiled-in devices */
798 devices = NewArray(nr_const_devices + 1, struct device);
799 if(!devices) {
800 fprintf(stderr,"Out of memory error\n");
801 exit(1);
802 }
803 if(nr_const_devices)
804 memcpy(devices, const_devices,
805 nr_const_devices*sizeof(struct device));
806}
807
808#endif /* NO_CONFIG */
Note: See TracBrowser for help on using the repository browser.