1*d5c9a868SElliott Hughes /* Copyright 1996-2005,2007-2009,2011 Alain Knaff.
2*d5c9a868SElliott Hughes * This file is part of mtools.
3*d5c9a868SElliott Hughes *
4*d5c9a868SElliott Hughes * Mtools is free software: you can redistribute it and/or modify
5*d5c9a868SElliott Hughes * it under the terms of the GNU General Public License as published by
6*d5c9a868SElliott Hughes * the Free Software Foundation, either version 3 of the License, or
7*d5c9a868SElliott Hughes * (at your option) any later version.
8*d5c9a868SElliott Hughes *
9*d5c9a868SElliott Hughes * Mtools is distributed in the hope that it will be useful,
10*d5c9a868SElliott Hughes * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*d5c9a868SElliott Hughes * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12*d5c9a868SElliott Hughes * GNU General Public License for more details.
13*d5c9a868SElliott Hughes *
14*d5c9a868SElliott Hughes * You should have received a copy of the GNU General Public License
15*d5c9a868SElliott Hughes * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
16*d5c9a868SElliott Hughes *
17*d5c9a868SElliott Hughes */
18*d5c9a868SElliott Hughes #include "sysincludes.h"
19*d5c9a868SElliott Hughes #include "mtools.h"
20*d5c9a868SElliott Hughes #include "codepage.h"
21*d5c9a868SElliott Hughes #include "mtoolsPaths.h"
22*d5c9a868SElliott Hughes
23*d5c9a868SElliott Hughes /* global variables */
24*d5c9a868SElliott Hughes /* they are not really harmful here, because there is only one configuration
25*d5c9a868SElliott Hughes * file per invocations */
26*d5c9a868SElliott Hughes
27*d5c9a868SElliott Hughes #define MAX_LINE_LEN 256
28*d5c9a868SElliott Hughes
29*d5c9a868SElliott Hughes /* scanner */
30*d5c9a868SElliott Hughes static char buffer[MAX_LINE_LEN+1]; /* buffer for the whole line */
31*d5c9a868SElliott Hughes static char *pos; /* position in line */
32*d5c9a868SElliott Hughes static char *token; /* last scanned token */
33*d5c9a868SElliott Hughes static size_t token_length; /* length of the token */
34*d5c9a868SElliott Hughes static FILE *fp; /* file pointer for configuration file */
35*d5c9a868SElliott Hughes static int linenumber; /* current line number. Only used for printing
36*d5c9a868SElliott Hughes * error messages */
37*d5c9a868SElliott Hughes static int lastTokenLinenumber; /* line numnber for last token */
38*d5c9a868SElliott Hughes static const char *filename=NULL; /* current file name. Used for printing
39*d5c9a868SElliott Hughes * error messages, and for storing in
40*d5c9a868SElliott Hughes * the device definition (mtoolstest) */
41*d5c9a868SElliott Hughes static int file_nr=0;
42*d5c9a868SElliott Hughes
43*d5c9a868SElliott Hughes
44*d5c9a868SElliott Hughes static unsigned int flag_mask; /* mask of currently set flags */
45*d5c9a868SElliott Hughes
46*d5c9a868SElliott Hughes /* devices */
47*d5c9a868SElliott Hughes static unsigned int cur_devs; /* current number of defined devices */
48*d5c9a868SElliott Hughes static int cur_dev; /* device being filled in. If negative, none */
49*d5c9a868SElliott Hughes static int trusted=0; /* is the currently parsed device entry trusted? */
50*d5c9a868SElliott Hughes static unsigned int nr_dev; /* number of devices that the current table can
51*d5c9a868SElliott Hughes hold */
52*d5c9a868SElliott Hughes struct device *devices; /* the device table */
53*d5c9a868SElliott Hughes static int token_nr; /* number of tokens in line */
54*d5c9a868SElliott Hughes
55*d5c9a868SElliott Hughes static char default_drive='\0'; /* default drive */
56*d5c9a868SElliott Hughes
57*d5c9a868SElliott Hughes /* "environment" variables */
58*d5c9a868SElliott Hughes unsigned int mtools_skip_check=0;
59*d5c9a868SElliott Hughes unsigned int mtools_fat_compatibility=0;
60*d5c9a868SElliott Hughes unsigned int mtools_ignore_short_case=0;
61*d5c9a868SElliott Hughes uint8_t mtools_rate_0=0;
62*d5c9a868SElliott Hughes uint8_t mtools_rate_any=0;
63*d5c9a868SElliott Hughes unsigned int mtools_no_vfat=0;
64*d5c9a868SElliott Hughes unsigned int mtools_numeric_tail=1;
65*d5c9a868SElliott Hughes unsigned int mtools_dotted_dir=0;
66*d5c9a868SElliott Hughes unsigned int mtools_twenty_four_hour_clock=1;
67*d5c9a868SElliott Hughes unsigned int mtools_lock_timeout=30;
68*d5c9a868SElliott Hughes unsigned int mtools_default_codepage=850;
69*d5c9a868SElliott Hughes const char *mtools_date_string="yyyy-mm-dd";
70*d5c9a868SElliott Hughes char *country_string=0;
71*d5c9a868SElliott Hughes
72*d5c9a868SElliott Hughes typedef struct switches_l {
73*d5c9a868SElliott Hughes const char *name;
74*d5c9a868SElliott Hughes caddr_t address;
75*d5c9a868SElliott Hughes enum {
76*d5c9a868SElliott Hughes T_INT,
77*d5c9a868SElliott Hughes T_STRING,
78*d5c9a868SElliott Hughes T_UINT,
79*d5c9a868SElliott Hughes T_UINT8,
80*d5c9a868SElliott Hughes T_UINT16,
81*d5c9a868SElliott Hughes T_UQSTRING
82*d5c9a868SElliott Hughes } type;
83*d5c9a868SElliott Hughes } switches_t;
84*d5c9a868SElliott Hughes
85*d5c9a868SElliott Hughes static switches_t global_switches[] = {
86*d5c9a868SElliott Hughes { "MTOOLS_LOWER_CASE", (caddr_t) & mtools_ignore_short_case, T_UINT },
87*d5c9a868SElliott Hughes { "MTOOLS_FAT_COMPATIBILITY", (caddr_t) & mtools_fat_compatibility, T_UINT },
88*d5c9a868SElliott Hughes { "MTOOLS_SKIP_CHECK", (caddr_t) & mtools_skip_check, T_UINT },
89*d5c9a868SElliott Hughes { "MTOOLS_NO_VFAT", (caddr_t) & mtools_no_vfat, T_UINT },
90*d5c9a868SElliott Hughes { "MTOOLS_RATE_0", (caddr_t) &mtools_rate_0, T_UINT8 },
91*d5c9a868SElliott Hughes { "MTOOLS_RATE_ANY", (caddr_t) &mtools_rate_any, T_UINT8 },
92*d5c9a868SElliott Hughes { "MTOOLS_NAME_NUMERIC_TAIL", (caddr_t) &mtools_numeric_tail, T_UINT },
93*d5c9a868SElliott Hughes { "MTOOLS_DOTTED_DIR", (caddr_t) &mtools_dotted_dir, T_UINT },
94*d5c9a868SElliott Hughes { "MTOOLS_TWENTY_FOUR_HOUR_CLOCK",
95*d5c9a868SElliott Hughes (caddr_t) &mtools_twenty_four_hour_clock, T_UINT },
96*d5c9a868SElliott Hughes { "MTOOLS_DATE_STRING",
97*d5c9a868SElliott Hughes (caddr_t) &mtools_date_string, T_STRING },
98*d5c9a868SElliott Hughes { "MTOOLS_LOCK_TIMEOUT", (caddr_t) &mtools_lock_timeout, T_UINT },
99*d5c9a868SElliott Hughes { "DEFAULT_CODEPAGE", (caddr_t) &mtools_default_codepage, T_UINT }
100*d5c9a868SElliott Hughes };
101*d5c9a868SElliott Hughes
102*d5c9a868SElliott Hughes typedef struct {
103*d5c9a868SElliott Hughes const char *name;
104*d5c9a868SElliott Hughes unsigned int flag;
105*d5c9a868SElliott Hughes } flags_t;
106*d5c9a868SElliott Hughes
107*d5c9a868SElliott Hughes static flags_t openflags[] = {
108*d5c9a868SElliott Hughes #ifdef O_SYNC
109*d5c9a868SElliott Hughes { "sync", O_SYNC },
110*d5c9a868SElliott Hughes #endif
111*d5c9a868SElliott Hughes #ifdef O_NDELAY
112*d5c9a868SElliott Hughes { "nodelay", O_NDELAY },
113*d5c9a868SElliott Hughes #endif
114*d5c9a868SElliott Hughes #ifdef O_EXCL
115*d5c9a868SElliott Hughes { "exclusive", O_EXCL },
116*d5c9a868SElliott Hughes #endif
117*d5c9a868SElliott Hughes { "none", 0 } /* hack for those compilers that choke on commas
118*d5c9a868SElliott Hughes * after the last element of an array */
119*d5c9a868SElliott Hughes };
120*d5c9a868SElliott Hughes
121*d5c9a868SElliott Hughes static flags_t misc_flags[] = {
122*d5c9a868SElliott Hughes #ifdef USE_XDF
123*d5c9a868SElliott Hughes { "use_xdf", USE_XDF_FLAG },
124*d5c9a868SElliott Hughes #endif
125*d5c9a868SElliott Hughes { "scsi", SCSI_FLAG },
126*d5c9a868SElliott Hughes { "nolock", NOLOCK_FLAG },
127*d5c9a868SElliott Hughes { "mformat_only", MFORMAT_ONLY_FLAG },
128*d5c9a868SElliott Hughes { "filter", FILTER_FLAG },
129*d5c9a868SElliott Hughes { "privileged", PRIV_FLAG },
130*d5c9a868SElliott Hughes { "vold", VOLD_FLAG },
131*d5c9a868SElliott Hughes { "remote", FLOPPYD_FLAG },
132*d5c9a868SElliott Hughes { "swap", SWAP_FLAG },
133*d5c9a868SElliott Hughes };
134*d5c9a868SElliott Hughes
135*d5c9a868SElliott Hughes static struct {
136*d5c9a868SElliott Hughes const char *name;
137*d5c9a868SElliott Hughes signed char fat_bits;
138*d5c9a868SElliott Hughes unsigned int tracks;
139*d5c9a868SElliott Hughes unsigned short heads;
140*d5c9a868SElliott Hughes unsigned short sectors;
141*d5c9a868SElliott Hughes } default_formats[] = {
142*d5c9a868SElliott Hughes { "hd514", 12, 80, 2, 15 },
143*d5c9a868SElliott Hughes { "high-density-5-1/4", 12, 80, 2, 15 },
144*d5c9a868SElliott Hughes { "1.2m", 12, 80, 2, 15 },
145*d5c9a868SElliott Hughes
146*d5c9a868SElliott Hughes { "hd312", 12, 80, 2, 18 },
147*d5c9a868SElliott Hughes { "high-density-3-1/2", 12, 80, 2, 18 },
148*d5c9a868SElliott Hughes { "1.44m", 12, 80, 2, 18 },
149*d5c9a868SElliott Hughes
150*d5c9a868SElliott Hughes { "dd312", 12, 80, 2, 9 },
151*d5c9a868SElliott Hughes { "double-density-3-1/2", 12, 80, 2, 9 },
152*d5c9a868SElliott Hughes { "720k", 12, 80, 2, 9 },
153*d5c9a868SElliott Hughes
154*d5c9a868SElliott Hughes { "dd514", 12, 40, 2, 9 },
155*d5c9a868SElliott Hughes { "double-density-5-1/4", 12, 40, 2, 9 },
156*d5c9a868SElliott Hughes { "360k", 12, 40, 2, 9 },
157*d5c9a868SElliott Hughes
158*d5c9a868SElliott Hughes { "320k", 12, 40, 2, 8 },
159*d5c9a868SElliott Hughes { "180k", 12, 40, 1, 9 },
160*d5c9a868SElliott Hughes { "160k", 12, 40, 1, 8 }
161*d5c9a868SElliott Hughes };
162*d5c9a868SElliott Hughes
163*d5c9a868SElliott Hughes #define OFFS(x) ((caddr_t)&((struct device *)0)->x)
164*d5c9a868SElliott Hughes
165*d5c9a868SElliott Hughes static switches_t dswitches[]= {
166*d5c9a868SElliott Hughes { "FILE", OFFS(name), T_STRING },
167*d5c9a868SElliott Hughes { "OFFSET", OFFS(offset), T_UINT },
168*d5c9a868SElliott Hughes { "PARTITION", OFFS(partition), T_UINT },
169*d5c9a868SElliott Hughes { "FAT", OFFS(fat_bits), T_INT },
170*d5c9a868SElliott Hughes { "FAT_BITS", OFFS(fat_bits), T_UINT },
171*d5c9a868SElliott Hughes { "MODE", OFFS(mode), T_UINT },
172*d5c9a868SElliott Hughes { "TRACKS", OFFS(tracks), T_UINT },
173*d5c9a868SElliott Hughes { "CYLINDERS", OFFS(tracks), T_UINT },
174*d5c9a868SElliott Hughes { "HEADS", OFFS(heads), T_UINT16 },
175*d5c9a868SElliott Hughes { "SECTORS", OFFS(sectors), T_UINT16 },
176*d5c9a868SElliott Hughes { "HIDDEN", OFFS(hidden), T_UINT },
177*d5c9a868SElliott Hughes { "PRECMD", OFFS(precmd), T_STRING },
178*d5c9a868SElliott Hughes { "BLOCKSIZE", OFFS(blocksize), T_UINT },
179*d5c9a868SElliott Hughes { "CODEPAGE", OFFS(codepage), T_UINT },
180*d5c9a868SElliott Hughes { "DATA_MAP", OFFS(data_map), T_UQSTRING }
181*d5c9a868SElliott Hughes };
182*d5c9a868SElliott Hughes
183*d5c9a868SElliott Hughes #if (defined HAVE_TOUPPER_L || defined HAVE_STRNCASECMP_L)
184*d5c9a868SElliott Hughes static locale_t C=NULL;
185*d5c9a868SElliott Hughes
init_canon(void)186*d5c9a868SElliott Hughes static void init_canon(void) {
187*d5c9a868SElliott Hughes if(C == NULL)
188*d5c9a868SElliott Hughes C = newlocale(LC_CTYPE_MASK, "C", NULL);
189*d5c9a868SElliott Hughes }
190*d5c9a868SElliott Hughes #endif
191*d5c9a868SElliott Hughes
192*d5c9a868SElliott Hughes #ifdef HAVE_TOUPPER_L
canon_drv(int drive)193*d5c9a868SElliott Hughes static int canon_drv(int drive) {
194*d5c9a868SElliott Hughes int ret;
195*d5c9a868SElliott Hughes init_canon();
196*d5c9a868SElliott Hughes ret = toupper_l(drive, C);
197*d5c9a868SElliott Hughes return ret;
198*d5c9a868SElliott Hughes }
199*d5c9a868SElliott Hughes #else
canon_drv(int drive)200*d5c9a868SElliott Hughes static int canon_drv(int drive) {
201*d5c9a868SElliott Hughes return toupper(drive);
202*d5c9a868SElliott Hughes }
203*d5c9a868SElliott Hughes #endif
204*d5c9a868SElliott Hughes
205*d5c9a868SElliott Hughes #ifdef HAVE_STRNCASECMP_L
cmp_tok(const char * a,const char * b,size_t len)206*d5c9a868SElliott Hughes static int cmp_tok(const char *a, const char *b, size_t len) {
207*d5c9a868SElliott Hughes init_canon();
208*d5c9a868SElliott Hughes return strncasecmp_l(a, b, len, C);
209*d5c9a868SElliott Hughes }
210*d5c9a868SElliott Hughes #else
cmp_tok(const char * a,const char * b,size_t len)211*d5c9a868SElliott Hughes static int cmp_tok(const char *a, const char *b, size_t len) {
212*d5c9a868SElliott Hughes return strncasecmp(a, b, len);
213*d5c9a868SElliott Hughes }
214*d5c9a868SElliott Hughes #endif
215*d5c9a868SElliott Hughes
216*d5c9a868SElliott Hughes
ch_canon_drv(char drive)217*d5c9a868SElliott Hughes static char ch_canon_drv(char drive) {
218*d5c9a868SElliott Hughes return (char) canon_drv( (unsigned char) drive);
219*d5c9a868SElliott Hughes }
220*d5c9a868SElliott Hughes
maintain_default_drive(char drive)221*d5c9a868SElliott Hughes static void maintain_default_drive(char drive)
222*d5c9a868SElliott Hughes {
223*d5c9a868SElliott Hughes if(default_drive == ':')
224*d5c9a868SElliott Hughes return; /* we have an image */
225*d5c9a868SElliott Hughes if(default_drive == '\0' ||
226*d5c9a868SElliott Hughes default_drive > drive)
227*d5c9a868SElliott Hughes default_drive = drive;
228*d5c9a868SElliott Hughes }
229*d5c9a868SElliott Hughes
get_default_drive(void)230*d5c9a868SElliott Hughes char get_default_drive(void)
231*d5c9a868SElliott Hughes {
232*d5c9a868SElliott Hughes if(default_drive != '\0')
233*d5c9a868SElliott Hughes return default_drive;
234*d5c9a868SElliott Hughes else
235*d5c9a868SElliott Hughes return 'A';
236*d5c9a868SElliott Hughes }
237*d5c9a868SElliott Hughes
238*d5c9a868SElliott Hughes static void syntax(const char *msg, int thisLine) NORETURN;
syntax(const char * msg,int thisLine)239*d5c9a868SElliott Hughes static void syntax(const char *msg, int thisLine)
240*d5c9a868SElliott Hughes {
241*d5c9a868SElliott Hughes char drive='\0';
242*d5c9a868SElliott Hughes if(thisLine)
243*d5c9a868SElliott Hughes lastTokenLinenumber = linenumber;
244*d5c9a868SElliott Hughes if(cur_dev >= 0)
245*d5c9a868SElliott Hughes drive = devices[cur_dev].drive;
246*d5c9a868SElliott Hughes fprintf(stderr,"Syntax error at line %d ", lastTokenLinenumber);
247*d5c9a868SElliott Hughes if(drive) fprintf(stderr, "for drive %c: ", drive);
248*d5c9a868SElliott Hughes if(token) fprintf(stderr, "column %ld ", (long)(token - buffer));
249*d5c9a868SElliott Hughes fprintf(stderr, "in file %s: %s", filename, msg);
250*d5c9a868SElliott Hughes if(errno != 0)
251*d5c9a868SElliott Hughes fprintf(stderr, " (%s)", strerror(errno));
252*d5c9a868SElliott Hughes fprintf(stderr, "\n");
253*d5c9a868SElliott Hughes exit(1);
254*d5c9a868SElliott Hughes }
255*d5c9a868SElliott Hughes
256*d5c9a868SElliott Hughes #pragma GCC diagnostic push
257*d5c9a868SElliott Hughes #pragma GCC diagnostic ignored "-Wcast-align"
get_env_conf(void)258*d5c9a868SElliott Hughes static void get_env_conf(void)
259*d5c9a868SElliott Hughes {
260*d5c9a868SElliott Hughes char *s;
261*d5c9a868SElliott Hughes unsigned int i;
262*d5c9a868SElliott Hughes
263*d5c9a868SElliott Hughes for(i=0; i< sizeof(global_switches) / sizeof(*global_switches); i++) {
264*d5c9a868SElliott Hughes s = getenv(global_switches[i].name);
265*d5c9a868SElliott Hughes if(s) {
266*d5c9a868SElliott Hughes errno = 0;
267*d5c9a868SElliott Hughes switch(global_switches[i].type) {
268*d5c9a868SElliott Hughes case T_INT:
269*d5c9a868SElliott Hughes * ((int *)global_switches[i].address) = strtoi(s,0,0);
270*d5c9a868SElliott Hughes break;
271*d5c9a868SElliott Hughes case T_UINT:
272*d5c9a868SElliott Hughes * ((unsigned int *)global_switches[i].address) = strtoui(s,0,0);
273*d5c9a868SElliott Hughes break;
274*d5c9a868SElliott Hughes case T_UINT8:
275*d5c9a868SElliott Hughes * ((uint8_t *)global_switches[i].address) = strtou8(s,0,0);
276*d5c9a868SElliott Hughes break;
277*d5c9a868SElliott Hughes case T_UINT16:
278*d5c9a868SElliott Hughes * ((uint16_t *)global_switches[i].address) = strtou16(s,0,0);
279*d5c9a868SElliott Hughes break;
280*d5c9a868SElliott Hughes case T_STRING:
281*d5c9a868SElliott Hughes case T_UQSTRING:
282*d5c9a868SElliott Hughes * ((char **)global_switches[i].address) = s;
283*d5c9a868SElliott Hughes break;
284*d5c9a868SElliott Hughes }
285*d5c9a868SElliott Hughes if(errno != 0) {
286*d5c9a868SElliott Hughes fprintf(stderr, "Bad number %s for %s (%s)\n", s,
287*d5c9a868SElliott Hughes global_switches[i].name,
288*d5c9a868SElliott Hughes strerror(errno));
289*d5c9a868SElliott Hughes exit(1);
290*d5c9a868SElliott Hughes }
291*d5c9a868SElliott Hughes }
292*d5c9a868SElliott Hughes }
293*d5c9a868SElliott Hughes }
294*d5c9a868SElliott Hughes #pragma GCC diagnostic pop
295*d5c9a868SElliott Hughes
mtools_getline(void)296*d5c9a868SElliott Hughes static int mtools_getline(void)
297*d5c9a868SElliott Hughes {
298*d5c9a868SElliott Hughes if(!fp || !fgets(buffer, MAX_LINE_LEN+1, fp))
299*d5c9a868SElliott Hughes return -1;
300*d5c9a868SElliott Hughes linenumber++;
301*d5c9a868SElliott Hughes pos = buffer;
302*d5c9a868SElliott Hughes token_nr = 0;
303*d5c9a868SElliott Hughes buffer[MAX_LINE_LEN] = '\0';
304*d5c9a868SElliott Hughes if(strlen(buffer) == MAX_LINE_LEN)
305*d5c9a868SElliott Hughes syntax("line too long", 1);
306*d5c9a868SElliott Hughes return 0;
307*d5c9a868SElliott Hughes }
308*d5c9a868SElliott Hughes
skip_junk(int expect)309*d5c9a868SElliott Hughes static void skip_junk(int expect)
310*d5c9a868SElliott Hughes {
311*d5c9a868SElliott Hughes lastTokenLinenumber = linenumber;
312*d5c9a868SElliott Hughes while(!pos || !*pos || strchr(" #\n\t", *pos)) {
313*d5c9a868SElliott Hughes if(!pos || !*pos || *pos == '#') {
314*d5c9a868SElliott Hughes if(mtools_getline()) {
315*d5c9a868SElliott Hughes pos = 0;
316*d5c9a868SElliott Hughes if(expect)
317*d5c9a868SElliott Hughes syntax("end of file unexpected", 1);
318*d5c9a868SElliott Hughes return;
319*d5c9a868SElliott Hughes }
320*d5c9a868SElliott Hughes } else
321*d5c9a868SElliott Hughes pos++;
322*d5c9a868SElliott Hughes }
323*d5c9a868SElliott Hughes token_nr++;
324*d5c9a868SElliott Hughes }
325*d5c9a868SElliott Hughes
326*d5c9a868SElliott Hughes /* get the next token */
get_next_token(void)327*d5c9a868SElliott Hughes static char *get_next_token(void)
328*d5c9a868SElliott Hughes {
329*d5c9a868SElliott Hughes skip_junk(0);
330*d5c9a868SElliott Hughes if(!pos) {
331*d5c9a868SElliott Hughes token_length = 0;
332*d5c9a868SElliott Hughes token = 0;
333*d5c9a868SElliott Hughes return 0;
334*d5c9a868SElliott Hughes }
335*d5c9a868SElliott Hughes token = pos;
336*d5c9a868SElliott Hughes token_length = strcspn(token, " \t\n#:=");
337*d5c9a868SElliott Hughes pos += token_length;
338*d5c9a868SElliott Hughes return token;
339*d5c9a868SElliott Hughes }
340*d5c9a868SElliott Hughes
match_token(const char * template)341*d5c9a868SElliott Hughes static int match_token(const char *template)
342*d5c9a868SElliott Hughes {
343*d5c9a868SElliott Hughes return (strlen(template) == token_length &&
344*d5c9a868SElliott Hughes !cmp_tok(template, token, token_length));
345*d5c9a868SElliott Hughes }
346*d5c9a868SElliott Hughes
expect_char(char c)347*d5c9a868SElliott Hughes static void expect_char(char c)
348*d5c9a868SElliott Hughes {
349*d5c9a868SElliott Hughes char buf[11];
350*d5c9a868SElliott Hughes
351*d5c9a868SElliott Hughes skip_junk(1);
352*d5c9a868SElliott Hughes if(*pos != c) {
353*d5c9a868SElliott Hughes sprintf(buf, "expected %c", c);
354*d5c9a868SElliott Hughes syntax(buf, 1);
355*d5c9a868SElliott Hughes }
356*d5c9a868SElliott Hughes pos++;
357*d5c9a868SElliott Hughes }
358*d5c9a868SElliott Hughes
get_string(void)359*d5c9a868SElliott Hughes static char *get_string(void)
360*d5c9a868SElliott Hughes {
361*d5c9a868SElliott Hughes char *end, *str;
362*d5c9a868SElliott Hughes
363*d5c9a868SElliott Hughes skip_junk(1);
364*d5c9a868SElliott Hughes if(*pos != '"')
365*d5c9a868SElliott Hughes syntax(" \" expected", 0);
366*d5c9a868SElliott Hughes str = pos+1;
367*d5c9a868SElliott Hughes end = strchr(str, '\"');
368*d5c9a868SElliott Hughes if(!end)
369*d5c9a868SElliott Hughes syntax("unterminated string constant", 1);
370*d5c9a868SElliott Hughes str = strndup(str, ptrdiff(end, str));
371*d5c9a868SElliott Hughes pos = end+1;
372*d5c9a868SElliott Hughes return str;
373*d5c9a868SElliott Hughes }
374*d5c9a868SElliott Hughes
get_unquoted_string(void)375*d5c9a868SElliott Hughes static char *get_unquoted_string(void)
376*d5c9a868SElliott Hughes {
377*d5c9a868SElliott Hughes if(*pos == '"')
378*d5c9a868SElliott Hughes return get_string();
379*d5c9a868SElliott Hughes else {
380*d5c9a868SElliott Hughes char *str=get_next_token();
381*d5c9a868SElliott Hughes return strndup(str, token_length);
382*d5c9a868SElliott Hughes }
383*d5c9a868SElliott Hughes }
384*d5c9a868SElliott Hughes
get_unumber(unsigned long max)385*d5c9a868SElliott Hughes static unsigned long get_unumber(unsigned long max)
386*d5c9a868SElliott Hughes {
387*d5c9a868SElliott Hughes char *last;
388*d5c9a868SElliott Hughes unsigned long n;
389*d5c9a868SElliott Hughes
390*d5c9a868SElliott Hughes skip_junk(1);
391*d5c9a868SElliott Hughes last = pos;
392*d5c9a868SElliott Hughes n=strtoul(pos, &pos, 0);
393*d5c9a868SElliott Hughes if(errno)
394*d5c9a868SElliott Hughes syntax("bad number", 0);
395*d5c9a868SElliott Hughes if(last == pos)
396*d5c9a868SElliott Hughes syntax("numeral expected", 0);
397*d5c9a868SElliott Hughes if(n > max)
398*d5c9a868SElliott Hughes syntax("number too big", 0);
399*d5c9a868SElliott Hughes pos++;
400*d5c9a868SElliott Hughes token_nr++;
401*d5c9a868SElliott Hughes return n;
402*d5c9a868SElliott Hughes }
403*d5c9a868SElliott Hughes
get_number(void)404*d5c9a868SElliott Hughes static int get_number(void)
405*d5c9a868SElliott Hughes {
406*d5c9a868SElliott Hughes char *last;
407*d5c9a868SElliott Hughes int n;
408*d5c9a868SElliott Hughes
409*d5c9a868SElliott Hughes skip_junk(1);
410*d5c9a868SElliott Hughes last = pos;
411*d5c9a868SElliott Hughes n=(int) strtol(pos, &pos, 0);
412*d5c9a868SElliott Hughes if(errno)
413*d5c9a868SElliott Hughes syntax("bad number", 0);
414*d5c9a868SElliott Hughes if(last == pos)
415*d5c9a868SElliott Hughes syntax("numeral expected", 0);
416*d5c9a868SElliott Hughes pos++;
417*d5c9a868SElliott Hughes token_nr++;
418*d5c9a868SElliott Hughes return n;
419*d5c9a868SElliott Hughes }
420*d5c9a868SElliott Hughes
421*d5c9a868SElliott Hughes /* purge all entries pertaining to a given drive from the table */
purge(char drive,int fn)422*d5c9a868SElliott Hughes static void purge(char drive, int fn)
423*d5c9a868SElliott Hughes {
424*d5c9a868SElliott Hughes unsigned int i, j;
425*d5c9a868SElliott Hughes
426*d5c9a868SElliott Hughes drive = ch_canon_drv(drive);
427*d5c9a868SElliott Hughes for(j=0, i=0; i < cur_devs; i++) {
428*d5c9a868SElliott Hughes if(devices[i].drive != drive ||
429*d5c9a868SElliott Hughes devices[i].file_nr == fn)
430*d5c9a868SElliott Hughes devices[j++] = devices[i];
431*d5c9a868SElliott Hughes }
432*d5c9a868SElliott Hughes cur_devs = j;
433*d5c9a868SElliott Hughes }
434*d5c9a868SElliott Hughes
grow(void)435*d5c9a868SElliott Hughes static void grow(void)
436*d5c9a868SElliott Hughes {
437*d5c9a868SElliott Hughes if(cur_devs >= nr_dev - 2) {
438*d5c9a868SElliott Hughes nr_dev = (cur_devs + 2) << 1;
439*d5c9a868SElliott Hughes if(!(devices=Grow(devices, nr_dev, struct device))){
440*d5c9a868SElliott Hughes printOom();
441*d5c9a868SElliott Hughes exit(1);
442*d5c9a868SElliott Hughes }
443*d5c9a868SElliott Hughes }
444*d5c9a868SElliott Hughes }
445*d5c9a868SElliott Hughes
446*d5c9a868SElliott Hughes
init_drive(void)447*d5c9a868SElliott Hughes static void init_drive(void)
448*d5c9a868SElliott Hughes {
449*d5c9a868SElliott Hughes memset((char *)&devices[cur_dev], 0, sizeof(struct device));
450*d5c9a868SElliott Hughes devices[cur_dev].ssize = 2;
451*d5c9a868SElliott Hughes }
452*d5c9a868SElliott Hughes
453*d5c9a868SElliott Hughes /* prepends a device to the table */
prepend(void)454*d5c9a868SElliott Hughes static void prepend(void)
455*d5c9a868SElliott Hughes {
456*d5c9a868SElliott Hughes unsigned int i;
457*d5c9a868SElliott Hughes
458*d5c9a868SElliott Hughes grow();
459*d5c9a868SElliott Hughes for(i=cur_devs; i>0; i--)
460*d5c9a868SElliott Hughes devices[i] = devices[i-1];
461*d5c9a868SElliott Hughes cur_dev = 0;
462*d5c9a868SElliott Hughes cur_devs++;
463*d5c9a868SElliott Hughes init_drive();
464*d5c9a868SElliott Hughes }
465*d5c9a868SElliott Hughes
466*d5c9a868SElliott Hughes
467*d5c9a868SElliott Hughes /* appends a device to the table */
append(void)468*d5c9a868SElliott Hughes static void append(void)
469*d5c9a868SElliott Hughes {
470*d5c9a868SElliott Hughes grow();
471*d5c9a868SElliott Hughes cur_dev = (int) cur_devs;
472*d5c9a868SElliott Hughes cur_devs++;
473*d5c9a868SElliott Hughes init_drive();
474*d5c9a868SElliott Hughes }
475*d5c9a868SElliott Hughes
476*d5c9a868SElliott Hughes
finish_drive_clause(void)477*d5c9a868SElliott Hughes static void finish_drive_clause(void)
478*d5c9a868SElliott Hughes {
479*d5c9a868SElliott Hughes if(cur_dev == -1) {
480*d5c9a868SElliott Hughes trusted = 0;
481*d5c9a868SElliott Hughes return;
482*d5c9a868SElliott Hughes }
483*d5c9a868SElliott Hughes if(!devices[cur_dev].name)
484*d5c9a868SElliott Hughes syntax("missing filename", 0);
485*d5c9a868SElliott Hughes if(devices[cur_dev].tracks ||
486*d5c9a868SElliott Hughes devices[cur_dev].heads ||
487*d5c9a868SElliott Hughes devices[cur_dev].sectors) {
488*d5c9a868SElliott Hughes if(!devices[cur_dev].tracks ||
489*d5c9a868SElliott Hughes !devices[cur_dev].heads ||
490*d5c9a868SElliott Hughes !devices[cur_dev].sectors)
491*d5c9a868SElliott Hughes syntax("incomplete geometry: either indicate all of track/heads/sectors or none of them", 0);
492*d5c9a868SElliott Hughes if(!(devices[cur_dev].misc_flags &
493*d5c9a868SElliott Hughes (MFORMAT_ONLY_FLAG | FILTER_FLAG)))
494*d5c9a868SElliott Hughes syntax("if you supply a geometry, you also must supply one of the `mformat_only' or `filter' flags", 0);
495*d5c9a868SElliott Hughes }
496*d5c9a868SElliott Hughes devices[cur_dev].file_nr = file_nr;
497*d5c9a868SElliott Hughes devices[cur_dev].cfg_filename = filename;
498*d5c9a868SElliott Hughes if(!trusted && (devices[cur_dev].misc_flags & PRIV_FLAG)) {
499*d5c9a868SElliott Hughes fprintf(stderr,
500*d5c9a868SElliott Hughes "Warning: privileged flag ignored for drive %c: defined in file %s\n",
501*d5c9a868SElliott Hughes canon_drv(devices[cur_dev].drive), filename);
502*d5c9a868SElliott Hughes devices[cur_dev].misc_flags &= ~PRIV_FLAG;
503*d5c9a868SElliott Hughes }
504*d5c9a868SElliott Hughes trusted = 0;
505*d5c9a868SElliott Hughes cur_dev = -1;
506*d5c9a868SElliott Hughes }
507*d5c9a868SElliott Hughes
508*d5c9a868SElliott Hughes #pragma GCC diagnostic push
509*d5c9a868SElliott Hughes #pragma GCC diagnostic ignored "-Wcast-align"
set_var(struct switches_l * switches,int nr,caddr_t base_address)510*d5c9a868SElliott Hughes static int set_var(struct switches_l *switches, int nr,
511*d5c9a868SElliott Hughes caddr_t base_address)
512*d5c9a868SElliott Hughes {
513*d5c9a868SElliott Hughes int i;
514*d5c9a868SElliott Hughes for(i=0; i < nr; i++) {
515*d5c9a868SElliott Hughes if(match_token(switches[i].name)) {
516*d5c9a868SElliott Hughes expect_char('=');
517*d5c9a868SElliott Hughes /* All pointers cast back to pointers with alignment
518*d5c9a868SElliott Hughes * constraints were such pointers with alignment
519*d5c9a868SElliott Hughes * constraints initially, thus they do indeed fit the
520*d5c9a868SElliott Hughes * constraint */
521*d5c9a868SElliott Hughes
522*d5c9a868SElliott Hughes if(switches[i].type == T_UINT)
523*d5c9a868SElliott Hughes * ((unsigned int *)((long)switches[i].address+base_address)) =
524*d5c9a868SElliott Hughes (unsigned int) get_unumber(UINT_MAX);
525*d5c9a868SElliott Hughes else if(switches[i].type == T_UINT8)
526*d5c9a868SElliott Hughes * ((uint8_t *)((long)switches[i].address+base_address)) =
527*d5c9a868SElliott Hughes (uint8_t) get_unumber(UINT8_MAX);
528*d5c9a868SElliott Hughes else if(switches[i].type == T_UINT16)
529*d5c9a868SElliott Hughes * ((uint16_t *)((long)switches[i].address+base_address)) =
530*d5c9a868SElliott Hughes (uint16_t) get_unumber(UINT16_MAX);
531*d5c9a868SElliott Hughes else if(switches[i].type == T_INT)
532*d5c9a868SElliott Hughes * ((int *)((long)switches[i].address+base_address)) =
533*d5c9a868SElliott Hughes get_number();
534*d5c9a868SElliott Hughes else if (switches[i].type == T_STRING)
535*d5c9a868SElliott Hughes * ((char**)((long)switches[i].address+base_address))=
536*d5c9a868SElliott Hughes get_string();
537*d5c9a868SElliott Hughes else if (switches[i].type == T_UQSTRING)
538*d5c9a868SElliott Hughes * ((char**)((long)switches[i].address+base_address))=
539*d5c9a868SElliott Hughes get_unquoted_string();
540*d5c9a868SElliott Hughes return 0;
541*d5c9a868SElliott Hughes }
542*d5c9a868SElliott Hughes }
543*d5c9a868SElliott Hughes return 1;
544*d5c9a868SElliott Hughes }
545*d5c9a868SElliott Hughes #pragma GCC diagnostic pop
546*d5c9a868SElliott Hughes
set_openflags(struct device * dev)547*d5c9a868SElliott Hughes static int set_openflags(struct device *dev)
548*d5c9a868SElliott Hughes {
549*d5c9a868SElliott Hughes unsigned int i;
550*d5c9a868SElliott Hughes
551*d5c9a868SElliott Hughes for(i=0; i < sizeof(openflags) / sizeof(*openflags); i++) {
552*d5c9a868SElliott Hughes if(match_token(openflags[i].name)) {
553*d5c9a868SElliott Hughes dev->mode |= openflags[i].flag;
554*d5c9a868SElliott Hughes return 0;
555*d5c9a868SElliott Hughes }
556*d5c9a868SElliott Hughes }
557*d5c9a868SElliott Hughes return 1;
558*d5c9a868SElliott Hughes }
559*d5c9a868SElliott Hughes
set_misc_flags(struct device * dev)560*d5c9a868SElliott Hughes static int set_misc_flags(struct device *dev)
561*d5c9a868SElliott Hughes {
562*d5c9a868SElliott Hughes unsigned int i;
563*d5c9a868SElliott Hughes for(i=0; i < sizeof(misc_flags) / sizeof(*misc_flags); i++) {
564*d5c9a868SElliott Hughes if(match_token(misc_flags[i].name)) {
565*d5c9a868SElliott Hughes flag_mask |= misc_flags[i].flag;
566*d5c9a868SElliott Hughes skip_junk(0);
567*d5c9a868SElliott Hughes if(pos && *pos == '=') {
568*d5c9a868SElliott Hughes pos++;
569*d5c9a868SElliott Hughes switch(get_number()) {
570*d5c9a868SElliott Hughes case 0:
571*d5c9a868SElliott Hughes return 0;
572*d5c9a868SElliott Hughes case 1:
573*d5c9a868SElliott Hughes break;
574*d5c9a868SElliott Hughes default:
575*d5c9a868SElliott Hughes syntax("expected 0 or 1", 0);
576*d5c9a868SElliott Hughes }
577*d5c9a868SElliott Hughes }
578*d5c9a868SElliott Hughes dev->misc_flags |= misc_flags[i].flag;
579*d5c9a868SElliott Hughes return 0;
580*d5c9a868SElliott Hughes }
581*d5c9a868SElliott Hughes }
582*d5c9a868SElliott Hughes return 1;
583*d5c9a868SElliott Hughes }
584*d5c9a868SElliott Hughes
set_def_format(struct device * dev)585*d5c9a868SElliott Hughes static int set_def_format(struct device *dev)
586*d5c9a868SElliott Hughes {
587*d5c9a868SElliott Hughes unsigned int i;
588*d5c9a868SElliott Hughes
589*d5c9a868SElliott Hughes for(i=0; i < sizeof(default_formats)/sizeof(*default_formats); i++) {
590*d5c9a868SElliott Hughes if(match_token(default_formats[i].name)) {
591*d5c9a868SElliott Hughes if(!dev->ssize)
592*d5c9a868SElliott Hughes dev->ssize = 2;
593*d5c9a868SElliott Hughes if(!dev->tracks)
594*d5c9a868SElliott Hughes dev->tracks = default_formats[i].tracks;
595*d5c9a868SElliott Hughes if(!dev->heads)
596*d5c9a868SElliott Hughes dev->heads = default_formats[i].heads;
597*d5c9a868SElliott Hughes if(!dev->sectors)
598*d5c9a868SElliott Hughes dev->sectors = default_formats[i].sectors;
599*d5c9a868SElliott Hughes if(!dev->fat_bits)
600*d5c9a868SElliott Hughes dev->fat_bits = default_formats[i].fat_bits;
601*d5c9a868SElliott Hughes return 0;
602*d5c9a868SElliott Hughes }
603*d5c9a868SElliott Hughes }
604*d5c9a868SElliott Hughes return 1;
605*d5c9a868SElliott Hughes }
606*d5c9a868SElliott Hughes
607*d5c9a868SElliott Hughes static void parse_all(int privilege);
608*d5c9a868SElliott Hughes
set_cmd_line_image(char * img)609*d5c9a868SElliott Hughes void set_cmd_line_image(char *img) {
610*d5c9a868SElliott Hughes char *ofsp;
611*d5c9a868SElliott Hughes
612*d5c9a868SElliott Hughes prepend();
613*d5c9a868SElliott Hughes devices[cur_dev].drive = ':';
614*d5c9a868SElliott Hughes default_drive = ':';
615*d5c9a868SElliott Hughes
616*d5c9a868SElliott Hughes ofsp = strstr(img, "@@");
617*d5c9a868SElliott Hughes if (ofsp == NULL) {
618*d5c9a868SElliott Hughes /* no separator => no offset */
619*d5c9a868SElliott Hughes devices[cur_dev].name = strdup(img);
620*d5c9a868SElliott Hughes devices[cur_dev].offset = 0;
621*d5c9a868SElliott Hughes } else {
622*d5c9a868SElliott Hughes devices[cur_dev].name = strndup(img, ptrdiff(ofsp, img));
623*d5c9a868SElliott Hughes devices[cur_dev].offset = str_to_offset(ofsp+2);
624*d5c9a868SElliott Hughes }
625*d5c9a868SElliott Hughes
626*d5c9a868SElliott Hughes devices[cur_dev].fat_bits = 0;
627*d5c9a868SElliott Hughes devices[cur_dev].tracks = 0;
628*d5c9a868SElliott Hughes devices[cur_dev].heads = 0;
629*d5c9a868SElliott Hughes devices[cur_dev].sectors = 0;
630*d5c9a868SElliott Hughes if (strchr(devices[cur_dev].name, '|')) {
631*d5c9a868SElliott Hughes char *pipechar = strchr(devices[cur_dev].name, '|');
632*d5c9a868SElliott Hughes *pipechar = 0;
633*d5c9a868SElliott Hughes strncpy(buffer, pipechar+1, MAX_LINE_LEN);
634*d5c9a868SElliott Hughes buffer[MAX_LINE_LEN] = '\0';
635*d5c9a868SElliott Hughes fp = NULL;
636*d5c9a868SElliott Hughes filename = "{command line}";
637*d5c9a868SElliott Hughes linenumber = 0;
638*d5c9a868SElliott Hughes lastTokenLinenumber = 0;
639*d5c9a868SElliott Hughes pos = buffer;
640*d5c9a868SElliott Hughes token = 0;
641*d5c9a868SElliott Hughes parse_all(0);
642*d5c9a868SElliott Hughes }
643*d5c9a868SElliott Hughes }
644*d5c9a868SElliott Hughes
check_number_parse_errno(char c,const char * oarg,char * endptr)645*d5c9a868SElliott Hughes void check_number_parse_errno(char c, const char *oarg, char *endptr) {
646*d5c9a868SElliott Hughes if(endptr && *endptr) {
647*d5c9a868SElliott Hughes fprintf(stderr, "Bad number %s\n", oarg);
648*d5c9a868SElliott Hughes exit(1);
649*d5c9a868SElliott Hughes }
650*d5c9a868SElliott Hughes if(errno) {
651*d5c9a868SElliott Hughes fprintf(stderr, "Bad number %s for -%c (%s)\n", oarg,
652*d5c9a868SElliott Hughes c, strerror(errno));
653*d5c9a868SElliott Hughes exit(1);
654*d5c9a868SElliott Hughes }
655*d5c9a868SElliott Hughes }
656*d5c9a868SElliott Hughes
tou16(int in,const char * comment)657*d5c9a868SElliott Hughes static uint16_t tou16(int in, const char *comment) {
658*d5c9a868SElliott Hughes if(in > (int) UINT16_MAX) {
659*d5c9a868SElliott Hughes fprintf(stderr, "Number of %s %d too big\n", comment, in);
660*d5c9a868SElliott Hughes exit(1);
661*d5c9a868SElliott Hughes }
662*d5c9a868SElliott Hughes if(in < 0) {
663*d5c9a868SElliott Hughes fprintf(stderr, "Number of %s %d negative\n", comment, in);
664*d5c9a868SElliott Hughes exit(1);
665*d5c9a868SElliott Hughes }
666*d5c9a868SElliott Hughes return (uint16_t) in;
667*d5c9a868SElliott Hughes }
668*d5c9a868SElliott Hughes
parse_old_device_line(char drive)669*d5c9a868SElliott Hughes static void parse_old_device_line(char drive)
670*d5c9a868SElliott Hughes {
671*d5c9a868SElliott Hughes char name[MAXPATHLEN];
672*d5c9a868SElliott Hughes int items;
673*d5c9a868SElliott Hughes long offset;
674*d5c9a868SElliott Hughes
675*d5c9a868SElliott Hughes int heads, sectors, tracks;
676*d5c9a868SElliott Hughes
677*d5c9a868SElliott Hughes /* finish any old drive */
678*d5c9a868SElliott Hughes finish_drive_clause();
679*d5c9a868SElliott Hughes
680*d5c9a868SElliott Hughes /* purge out data of old configuration files */
681*d5c9a868SElliott Hughes purge(drive, file_nr);
682*d5c9a868SElliott Hughes
683*d5c9a868SElliott Hughes /* reserve slot */
684*d5c9a868SElliott Hughes append();
685*d5c9a868SElliott Hughes items = sscanf(token,"%c %s %i %i %i %i %li",
686*d5c9a868SElliott Hughes &devices[cur_dev].drive,name,&devices[cur_dev].fat_bits,
687*d5c9a868SElliott Hughes &tracks,&heads,§ors, &offset);
688*d5c9a868SElliott Hughes devices[cur_dev].heads = tou16(heads, "heads");
689*d5c9a868SElliott Hughes devices[cur_dev].sectors = tou16(sectors, "sectors");
690*d5c9a868SElliott Hughes devices[cur_dev].tracks = (unsigned int) tracks;
691*d5c9a868SElliott Hughes devices[cur_dev].offset = (off_t) offset;
692*d5c9a868SElliott Hughes switch(items){
693*d5c9a868SElliott Hughes case 2:
694*d5c9a868SElliott Hughes devices[cur_dev].fat_bits = 0;
695*d5c9a868SElliott Hughes /* fall thru */
696*d5c9a868SElliott Hughes case 3:
697*d5c9a868SElliott Hughes devices[cur_dev].sectors = 0;
698*d5c9a868SElliott Hughes devices[cur_dev].heads = 0;
699*d5c9a868SElliott Hughes devices[cur_dev].tracks = 0;
700*d5c9a868SElliott Hughes /* fall thru */
701*d5c9a868SElliott Hughes case 6:
702*d5c9a868SElliott Hughes devices[cur_dev].offset = 0;
703*d5c9a868SElliott Hughes /* fall thru */
704*d5c9a868SElliott Hughes default:
705*d5c9a868SElliott Hughes break;
706*d5c9a868SElliott Hughes case 0:
707*d5c9a868SElliott Hughes case 1:
708*d5c9a868SElliott Hughes case 4:
709*d5c9a868SElliott Hughes case 5:
710*d5c9a868SElliott Hughes syntax("bad number of parameters", 1);
711*d5c9a868SElliott Hughes }
712*d5c9a868SElliott Hughes if(!devices[cur_dev].tracks){
713*d5c9a868SElliott Hughes devices[cur_dev].sectors = 0;
714*d5c9a868SElliott Hughes devices[cur_dev].heads = 0;
715*d5c9a868SElliott Hughes }
716*d5c9a868SElliott Hughes
717*d5c9a868SElliott Hughes devices[cur_dev].drive = ch_canon_drv(devices[cur_dev].drive);
718*d5c9a868SElliott Hughes maintain_default_drive(devices[cur_dev].drive);
719*d5c9a868SElliott Hughes if (!(devices[cur_dev].name = strdup(name))) {
720*d5c9a868SElliott Hughes printOom();
721*d5c9a868SElliott Hughes exit(1);
722*d5c9a868SElliott Hughes }
723*d5c9a868SElliott Hughes devices[cur_dev].misc_flags |= MFORMAT_ONLY_FLAG;
724*d5c9a868SElliott Hughes finish_drive_clause();
725*d5c9a868SElliott Hughes pos=0;
726*d5c9a868SElliott Hughes }
727*d5c9a868SElliott Hughes
parse_one(int privilege)728*d5c9a868SElliott Hughes static int parse_one(int privilege)
729*d5c9a868SElliott Hughes {
730*d5c9a868SElliott Hughes int action=0;
731*d5c9a868SElliott Hughes
732*d5c9a868SElliott Hughes get_next_token();
733*d5c9a868SElliott Hughes if(!token)
734*d5c9a868SElliott Hughes return 0;
735*d5c9a868SElliott Hughes
736*d5c9a868SElliott Hughes if((match_token("drive") && ((action = 1)))||
737*d5c9a868SElliott Hughes (match_token("drive+") && ((action = 2))) ||
738*d5c9a868SElliott Hughes (match_token("+drive") && ((action = 3))) ||
739*d5c9a868SElliott Hughes (match_token("clear_drive") && ((action = 4))) ) {
740*d5c9a868SElliott Hughes /* finish off the previous drive */
741*d5c9a868SElliott Hughes finish_drive_clause();
742*d5c9a868SElliott Hughes
743*d5c9a868SElliott Hughes get_next_token();
744*d5c9a868SElliott Hughes if(token_length != 1)
745*d5c9a868SElliott Hughes syntax("drive letter expected", 0);
746*d5c9a868SElliott Hughes
747*d5c9a868SElliott Hughes if(action==1 || action==4)
748*d5c9a868SElliott Hughes /* replace existing drive */
749*d5c9a868SElliott Hughes purge(token[0], file_nr);
750*d5c9a868SElliott Hughes if(action==4)
751*d5c9a868SElliott Hughes return 1;
752*d5c9a868SElliott Hughes if(action==3)
753*d5c9a868SElliott Hughes prepend();
754*d5c9a868SElliott Hughes else
755*d5c9a868SElliott Hughes append();
756*d5c9a868SElliott Hughes memset((char*)(devices+cur_dev), 0, sizeof(*devices));
757*d5c9a868SElliott Hughes trusted = privilege;
758*d5c9a868SElliott Hughes flag_mask = 0;
759*d5c9a868SElliott Hughes devices[cur_dev].drive = ch_canon_drv(token[0]);
760*d5c9a868SElliott Hughes maintain_default_drive(devices[cur_dev].drive);
761*d5c9a868SElliott Hughes expect_char(':');
762*d5c9a868SElliott Hughes return 1;
763*d5c9a868SElliott Hughes }
764*d5c9a868SElliott Hughes if(token_nr == 1 && token_length == 1) {
765*d5c9a868SElliott Hughes parse_old_device_line(token[0]);
766*d5c9a868SElliott Hughes return 1;
767*d5c9a868SElliott Hughes }
768*d5c9a868SElliott Hughes
769*d5c9a868SElliott Hughes if((cur_dev < 0 ||
770*d5c9a868SElliott Hughes (set_var(dswitches,
771*d5c9a868SElliott Hughes sizeof(dswitches)/sizeof(*dswitches),
772*d5c9a868SElliott Hughes (caddr_t)&devices[cur_dev]) &&
773*d5c9a868SElliott Hughes set_openflags(&devices[cur_dev]) &&
774*d5c9a868SElliott Hughes set_misc_flags(&devices[cur_dev]) &&
775*d5c9a868SElliott Hughes set_def_format(&devices[cur_dev]))) &&
776*d5c9a868SElliott Hughes set_var(global_switches,
777*d5c9a868SElliott Hughes sizeof(global_switches)/sizeof(*global_switches), 0))
778*d5c9a868SElliott Hughes syntax("unrecognized keyword", 1);
779*d5c9a868SElliott Hughes return 1;
780*d5c9a868SElliott Hughes }
781*d5c9a868SElliott Hughes
parse_all(int privilege)782*d5c9a868SElliott Hughes static void parse_all(int privilege) {
783*d5c9a868SElliott Hughes errno=0;
784*d5c9a868SElliott Hughes while (parse_one(privilege));
785*d5c9a868SElliott Hughes }
786*d5c9a868SElliott Hughes
787*d5c9a868SElliott Hughes
parse(const char * name,int privilege)788*d5c9a868SElliott Hughes static int parse(const char *name, int privilege)
789*d5c9a868SElliott Hughes {
790*d5c9a868SElliott Hughes if(fp) {
791*d5c9a868SElliott Hughes fprintf(stderr, "File descriptor already set!\n");
792*d5c9a868SElliott Hughes exit(1);
793*d5c9a868SElliott Hughes }
794*d5c9a868SElliott Hughes fp = fopen(name, "r");
795*d5c9a868SElliott Hughes if(!fp)
796*d5c9a868SElliott Hughes return 0;
797*d5c9a868SElliott Hughes file_nr++;
798*d5c9a868SElliott Hughes filename = name; /* no strdup needed: although lifetime of variable
799*d5c9a868SElliott Hughes exceeds this function (due to dev->cfg_filename),
800*d5c9a868SElliott Hughes we know that the name is always either
801*d5c9a868SElliott Hughes 1. a constant
802*d5c9a868SElliott Hughes 2. a statically allocate buffer
803*d5c9a868SElliott Hughes 3. an environment variable that stays unchanged
804*d5c9a868SElliott Hughes */
805*d5c9a868SElliott Hughes linenumber = 0;
806*d5c9a868SElliott Hughes lastTokenLinenumber = 0;
807*d5c9a868SElliott Hughes pos = 0;
808*d5c9a868SElliott Hughes token = 0;
809*d5c9a868SElliott Hughes cur_dev = -1; /* no current device */
810*d5c9a868SElliott Hughes
811*d5c9a868SElliott Hughes parse_all(privilege);
812*d5c9a868SElliott Hughes finish_drive_clause();
813*d5c9a868SElliott Hughes fclose(fp);
814*d5c9a868SElliott Hughes filename = NULL;
815*d5c9a868SElliott Hughes fp = NULL;
816*d5c9a868SElliott Hughes return 1;
817*d5c9a868SElliott Hughes }
818*d5c9a868SElliott Hughes
read_config(void)819*d5c9a868SElliott Hughes void read_config(void)
820*d5c9a868SElliott Hughes {
821*d5c9a868SElliott Hughes char *homedir;
822*d5c9a868SElliott Hughes char *envConfFile;
823*d5c9a868SElliott Hughes static char conf_file[MAXPATHLEN+sizeof(CFG_FILE1)];
824*d5c9a868SElliott Hughes
825*d5c9a868SElliott Hughes
826*d5c9a868SElliott Hughes /* copy compiled-in devices */
827*d5c9a868SElliott Hughes file_nr = 0;
828*d5c9a868SElliott Hughes cur_devs = nr_const_devices;
829*d5c9a868SElliott Hughes nr_dev = nr_const_devices + 2;
830*d5c9a868SElliott Hughes devices = NewArray(nr_dev, struct device);
831*d5c9a868SElliott Hughes if(!devices) {
832*d5c9a868SElliott Hughes printOom();
833*d5c9a868SElliott Hughes exit(1);
834*d5c9a868SElliott Hughes }
835*d5c9a868SElliott Hughes if(nr_const_devices)
836*d5c9a868SElliott Hughes memcpy(devices, const_devices,
837*d5c9a868SElliott Hughes nr_const_devices*sizeof(struct device));
838*d5c9a868SElliott Hughes
839*d5c9a868SElliott Hughes (void) ((parse(CONF_FILE,1) |
840*d5c9a868SElliott Hughes parse(LOCAL_CONF_FILE,1) |
841*d5c9a868SElliott Hughes parse(SYS_CONF_FILE,1)) ||
842*d5c9a868SElliott Hughes (parse(OLD_CONF_FILE,1) |
843*d5c9a868SElliott Hughes parse(OLD_LOCAL_CONF_FILE,1)));
844*d5c9a868SElliott Hughes /* the old-name configuration files only get executed if none of the
845*d5c9a868SElliott Hughes * new-name config files were used */
846*d5c9a868SElliott Hughes
847*d5c9a868SElliott Hughes homedir = get_homedir();
848*d5c9a868SElliott Hughes if ( homedir ){
849*d5c9a868SElliott Hughes strncpy(conf_file, homedir, MAXPATHLEN );
850*d5c9a868SElliott Hughes conf_file[MAXPATHLEN]='\0';
851*d5c9a868SElliott Hughes strcat( conf_file, CFG_FILE1);
852*d5c9a868SElliott Hughes parse(conf_file,0);
853*d5c9a868SElliott Hughes }
854*d5c9a868SElliott Hughes memset((char *)&devices[cur_devs],0,sizeof(struct device));
855*d5c9a868SElliott Hughes
856*d5c9a868SElliott Hughes envConfFile = getenv("MTOOLSRC");
857*d5c9a868SElliott Hughes if(envConfFile)
858*d5c9a868SElliott Hughes parse(envConfFile,0);
859*d5c9a868SElliott Hughes
860*d5c9a868SElliott Hughes /* environmental variables */
861*d5c9a868SElliott Hughes get_env_conf();
862*d5c9a868SElliott Hughes if(mtools_skip_check)
863*d5c9a868SElliott Hughes mtools_fat_compatibility=1;
864*d5c9a868SElliott Hughes }
865*d5c9a868SElliott Hughes
866*d5c9a868SElliott Hughes void mtoolstest(int argc, char **argv, int type UNUSEDP) NORETURN;
mtoolstest(int argc,char ** argv,int type UNUSEDP)867*d5c9a868SElliott Hughes void mtoolstest(int argc, char **argv, int type UNUSEDP)
868*d5c9a868SElliott Hughes {
869*d5c9a868SElliott Hughes /* testing purposes only */
870*d5c9a868SElliott Hughes struct device *dev;
871*d5c9a868SElliott Hughes char drive='\0';
872*d5c9a868SElliott Hughes
873*d5c9a868SElliott Hughes if(argc > 1 && argv[1][0] && argv[1][1] == ':') {
874*d5c9a868SElliott Hughes drive = ch_canon_drv(argv[1][0]);
875*d5c9a868SElliott Hughes }
876*d5c9a868SElliott Hughes
877*d5c9a868SElliott Hughes for (dev=devices; dev->name; dev++) {
878*d5c9a868SElliott Hughes if(drive && drive != dev->drive)
879*d5c9a868SElliott Hughes continue;
880*d5c9a868SElliott Hughes printf("drive %c:\n", dev->drive);
881*d5c9a868SElliott Hughes printf("\t#fn=%d mode=%d ",
882*d5c9a868SElliott Hughes dev->file_nr, dev->mode);
883*d5c9a868SElliott Hughes if(dev->cfg_filename)
884*d5c9a868SElliott Hughes printf("defined in %s\n", dev->cfg_filename);
885*d5c9a868SElliott Hughes else
886*d5c9a868SElliott Hughes printf("builtin\n");
887*d5c9a868SElliott Hughes printf("\tfile=\"%s\" fat_bits=%d \n",
888*d5c9a868SElliott Hughes dev->name,dev->fat_bits);
889*d5c9a868SElliott Hughes printf("\ttracks=%d heads=%d sectors=%d hidden=%d\n",
890*d5c9a868SElliott Hughes dev->tracks, dev->heads, dev->sectors, dev->hidden);
891*d5c9a868SElliott Hughes printf("\toffset=0x%lx\n", (long) dev->offset);
892*d5c9a868SElliott Hughes printf("\tpartition=%d\n", dev->partition);
893*d5c9a868SElliott Hughes
894*d5c9a868SElliott Hughes if(dev->misc_flags)
895*d5c9a868SElliott Hughes printf("\t");
896*d5c9a868SElliott Hughes
897*d5c9a868SElliott Hughes if(DO_SWAP(dev))
898*d5c9a868SElliott Hughes printf("swap ");
899*d5c9a868SElliott Hughes if(IS_SCSI(dev))
900*d5c9a868SElliott Hughes printf("scsi ");
901*d5c9a868SElliott Hughes if(IS_PRIVILEGED(dev))
902*d5c9a868SElliott Hughes printf("privileged");
903*d5c9a868SElliott Hughes if(IS_MFORMAT_ONLY(dev))
904*d5c9a868SElliott Hughes printf("mformat_only ");
905*d5c9a868SElliott Hughes if(SHOULD_USE_VOLD(dev))
906*d5c9a868SElliott Hughes printf("vold ");
907*d5c9a868SElliott Hughes #ifdef USE_XDF
908*d5c9a868SElliott Hughes if(SHOULD_USE_XDF(dev))
909*d5c9a868SElliott Hughes printf("use_xdf ");
910*d5c9a868SElliott Hughes #endif
911*d5c9a868SElliott Hughes if(dev->misc_flags)
912*d5c9a868SElliott Hughes printf("\n");
913*d5c9a868SElliott Hughes
914*d5c9a868SElliott Hughes if(dev->mode)
915*d5c9a868SElliott Hughes printf("\t");
916*d5c9a868SElliott Hughes #ifdef O_SYNC
917*d5c9a868SElliott Hughes if(dev->mode & O_SYNC)
918*d5c9a868SElliott Hughes printf("sync ");
919*d5c9a868SElliott Hughes #endif
920*d5c9a868SElliott Hughes #ifdef O_NDELAY
921*d5c9a868SElliott Hughes if((dev->mode & O_NDELAY))
922*d5c9a868SElliott Hughes printf("nodelay ");
923*d5c9a868SElliott Hughes #endif
924*d5c9a868SElliott Hughes #ifdef O_EXCL
925*d5c9a868SElliott Hughes if((dev->mode & O_EXCL))
926*d5c9a868SElliott Hughes printf("exclusive ");
927*d5c9a868SElliott Hughes #endif
928*d5c9a868SElliott Hughes if(dev->mode)
929*d5c9a868SElliott Hughes printf("\n");
930*d5c9a868SElliott Hughes
931*d5c9a868SElliott Hughes if(dev->precmd)
932*d5c9a868SElliott Hughes printf("\tprecmd=%s\n", dev->precmd);
933*d5c9a868SElliott Hughes
934*d5c9a868SElliott Hughes printf("\n");
935*d5c9a868SElliott Hughes }
936*d5c9a868SElliott Hughes
937*d5c9a868SElliott Hughes printf("mtools_fat_compatibility=%d\n",mtools_fat_compatibility);
938*d5c9a868SElliott Hughes printf("mtools_skip_check=%d\n",mtools_skip_check);
939*d5c9a868SElliott Hughes printf("mtools_lower_case=%d\n",mtools_ignore_short_case);
940*d5c9a868SElliott Hughes
941*d5c9a868SElliott Hughes exit(0);
942*d5c9a868SElliott Hughes }
943*d5c9a868SElliott Hughes
944*d5c9a868SElliott Hughes /*
945*d5c9a868SElliott Hughes * Local Variables:
946*d5c9a868SElliott Hughes * c-basic-offset: 4
947*d5c9a868SElliott Hughes * End:
948*d5c9a868SElliott Hughes */
949