home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
CMDS
/
mtools_3.6.src.lzh
/
MTOOLS_3.6
/
config.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-11-12
|
15KB
|
669 lines
#include "sysincludes.h"
#include "mtools.h"
#include "codepage.h"
#include "paths.h"
/* global variables */
/* they are not really harmful here, because there is only one configuration
* file per invocations */
#define MAX_LINE_LEN 256
#ifdef _OSK
typedef long caddr_t;
#endif
/* scanner */
static char buffer[MAX_LINE_LEN+1]; /* buffer for the whole line */
static char *pos; /* position in line */
static char *token; /* last scanned token */
static int token_length; /* length of the token */
static FILE *fp; /* file pointer for configuration file */
static int linenumber; /* current line number. Only used for printing
* error messages */
static const char *filename; /* current file name. Only used for printing
* error messages */
static int file_nr=0;
/* devices */
static int cur_devs; /* current number of defined devices */
static int cur_dev; /* device being filled in. If negative, none */
static int trusted=0; /* is the currently parsed device entry trusted? */
static int nr_dev; /* number of devices that the current table can hold */
struct device *devices; /* the device table */
static int token_nr; /* number of tokens in line */
/* "environment" variables */
int mtools_skip_check=0;
int mtools_fat_compatibility=0;
int mtools_ignore_short_case=0;
int mtools_rate_0=0;
int mtools_rate_any=0;
int mtools_no_vfat=0;
char *country_string=0;
typedef struct switches_l {
const char *name;
caddr_t address;
enum {
INT,
STRING
} type;
} switches_t;
static switches_t switches[] = {
{ "MTOOLS_LOWER_CASE", (caddr_t) & mtools_ignore_short_case, INT },
{ "MTOOLS_FAT_COMPATIBILITY", (caddr_t) & mtools_fat_compatibility, INT },
{ "MTOOLS_SKIP_CHECK", (caddr_t) & mtools_skip_check, INT },
{ "MTOOLS_NO_VFAT", (caddr_t) & mtools_no_vfat, INT },
{ "MTOOLS_RATE_0", (caddr_t) &mtools_rate_0, INT },
{ "MTOOLS_RATE_ANY", (caddr_t) &mtools_rate_any, INT },
{ "COUNTRY", (caddr_t) &country_string, STRING }
};
static struct {
const char *name;
int flag;
} openflags[] = {
#ifdef O_SYNC
{ "sync", O_SYNC },
#endif
#ifdef O_NDELAY
{ "nodelay", O_NDELAY },
#endif
#ifdef O_EXCL
{ "exclusive", O_EXCL }
#endif
#ifdef _OSK
{ "", 0}
#endif
};
static struct {
const char *name;
signed char fat_bits;
int tracks;
unsigned short heads;
unsigned short sectors;
} default_formats[] = {
{ "hd514", 12, 80, 2, 15 },
{ "high-density-5-1/4", 12, 80, 2, 15 },
{ "1.2m", 12, 80, 2, 15 },
{ "hd312", 12, 80, 2, 18 },
{ "high-density-3-1/2", 12, 80, 2, 18 },
{ "1.44m", 12, 80, 2, 18 },
{ "dd312", 12, 80, 2, 9 },
{ "double-density-3-1/2", 12, 80, 2, 9 },
{ "720k", 12, 80, 2, 9 },
{ "dd514", 12, 40, 2, 9 },
{ "double-density-5-1/4", 12, 40, 2, 9 },
{ "360k", 12, 40, 2, 9 },
{ "320k", 12, 40, 2, 8 },
{ "180k", 12, 40, 1, 9 },
{ "160k", 12, 40, 1, 8 }
};
#define OFFS(x) ((caddr_t)&((struct device *)0)->x)
static switches_t dswitches[]= {
{ "FILE", OFFS(name), STRING },
{ "OFFSET", OFFS(offset), INT },
{ "PARTITION", OFFS(partition), INT },
{ "SCSI", OFFS(scsi), INT },
{ "PRIVILEGED", OFFS(privileged), INT },
{ "NOLOCK", OFFS(nolock), INT },
{ "FAT", OFFS(fat_bits), INT },
{ "FAT_BITS", OFFS(fat_bits), INT },
{ "MODE", OFFS(mode), INT },
{ "TRACKS", OFFS(tracks), INT },
{ "CYLINDERS", OFFS(tracks), INT },
{ "HEADS", OFFS(heads), INT },
{ "SECTORS", OFFS(sectors), INT },
{ "USE_XDF", OFFS(use_xdf), INT },
{ "PRECMD", OFFS(precmd), STRING }
};
static void syntax(const char *msg)
{
fprintf(stderr,"Syntax error at line %d column %ld in file %s: %s\n",
linenumber, (long)(token - buffer), filename, msg);
exit(1);
}
static void get_env_conf(void)
{
char *s;
int i;
for(i=0; i< sizeof(switches) / sizeof(*switches); i++) {
s = getenv(switches[i].name);
if(s) {
if(switches[i].type == INT)
* ((int *)switches[i].address) = strtoul(s,0,0);
else if (switches[i].type == STRING)
* ((char **)switches[i].address) = s;
}
}
}
static int getline(void)
{
if(!fgets(buffer, MAX_LINE_LEN, fp))
return -1;
linenumber++;
pos = buffer;
token_nr = 0;
buffer[MAX_LINE_LEN] = '\0';
if(strlen(buffer) == MAX_LINE_LEN)
syntax("line too long");
return 0;
}
static void skip_junk(int expect)
{
while(!pos || !*pos || strchr(" #\n\t", *pos)) {
if(!pos || !*pos || *pos == '#') {
if(getline()) {
pos = 0;
if(expect)
syntax("end of file unexpected");
return;
}
} else
pos++;
}
token_nr++;
}
/* get the next token */
static char *get_next_token(void)
{
skip_junk(0);
if(!pos) {
token_length = 0;
token = 0;
return 0;
}
token = pos;
token_length = strcspn(token, " \t\n#:=");
pos += token_length;
return token;
}
static int match_token(const char *template)
{
return (strlen(template) == token_length &&
!strncasecmp(template, token, token_length));
}
static void expect_char(char c)
{
char buf[11];
skip_junk(1);
if(*pos != c) {
sprintf(buf, "expected %c", c);
syntax(buf);
}
pos++;
}
static char *get_string(void)
{
char *end, *str;
skip_junk(1);
if(*pos != '"')
syntax(" \" expected");
str = pos+1;
end = strchr(str, '\"');
if(!end)
syntax("unterminated string constant");
*end = '\0';
pos = end+1;
return str;
}
static int get_number(void)
{
char *last;
int n;
skip_junk(1);
last = pos;
n=strtoul(pos, &pos, 0);
if(last == pos)
syntax("numeral expected");
pos++;
token_nr++;
return n;
}
/* purge all entries pertaining to a given drive from the table */
static void purge(char drive, int fn)
{
int i,j;
drive = toupper(drive);
for(j=0, i=0; i < cur_devs; i++) {
if(devices[i].drive != drive ||
devices[i].file_nr == fn)
devices[j++] = devices[i];
}
cur_devs = j;
}
static void grow(void)
{
if(cur_devs >= nr_dev - 2) {
nr_dev = (cur_devs + 2) << 1;
if(!(devices=Grow(devices, nr_dev, struct device))){
fprintf(stderr,"Out of memory error");
exit(1);
}
}
}
static void init_drive(void)
{
memset((char *)&devices[cur_dev], 0, sizeof(struct device));
devices[cur_dev].ssize = 2;
}
/* prepends a device to the table */
static void prepend(void)
{
int i;
grow();
for(i=cur_devs; i>0; i--)
devices[i] = devices[i-1];
cur_dev = 0;
cur_devs++;
init_drive();
}
/* appends a device to the table */
static void append(void)
{
grow();
cur_dev = cur_devs;
cur_devs++;
init_drive();
}
static void finish_drive_clause(void)
{
if(cur_dev == -1) {
trusted = 0;
return;
}
if(!devices[cur_dev].name)
syntax("missing filename");
if((devices[cur_dev].tracks ||
devices[cur_dev].heads ||
devices[cur_dev].sectors) &&
(!devices[cur_dev].tracks ||
!devices[cur_dev].heads ||
!devices[cur_dev].sectors))
syntax("incomplete geometry: either indicate all of track/heads/sectors or none of them");
devices[cur_dev].file_nr = file_nr;
if(devices[cur_dev].privileged == 2)
devices[cur_dev].privileged = devices[cur_dev].scsi;
if(!trusted)
devices[cur_dev].privileged = 0;
trusted = 0;
cur_dev = -1;
}
static int set_var(struct switches_l *switches, int nr,
caddr_t base_address)
{
int i;
for(i=0; i < nr; i++) {
if(match_token(switches[i].name)) {
expect_char('=');
if(switches[i].type == INT)
* ((int *)((long)switches[i].address+base_address)) =
get_number();
else if (switches[i].type == STRING)
* ((char**)((long)switches[i].address+base_address))=
strdup(get_string());
return 0;
}
}
return 1;
}
static int set_openflags(struct device *dev)
{
int i;
for(i=0; i < sizeof(openflags) / sizeof(*openflags); i++) {
if(match_token(openflags[i].name)) {
dev->mode |= openflags[i].flag;
return 0;
}
}
return 1;
}
static int set_def_format(struct device *dev)
{
int i;
for(i=0; i < sizeof(default_formats)/sizeof(*default_formats); i++) {
if(match_token(default_formats[i].name)) {
if(!dev->ssize)
dev->ssize = 2;
if(!dev->tracks)
dev->tracks = default_formats[i].tracks;
if(!dev->heads)
dev->heads = default_formats[i].heads;
if(!dev->sectors)
dev->sectors = default_formats[i].sectors;
if(!dev->fat_bits)
dev->fat_bits = default_formats[i].fat_bits;
return 0;
}
}
return 1;
}
static void get_codepage(void)
{
int i;
unsigned short n;
if(!Codepage)
Codepage = New(Codepage_t);
for(i=0; i<128; i++) {
n = get_number();
if(n > 0xff)
n = 0x5f;
Codepage->tounix[i] = n;
}
}
static void get_toupper(void)
{
int i;
if(!mstoupper)
mstoupper = malloc(128);
for(i=0; i<128; i++)
mstoupper[i] = get_number();
}
static void parse_old_device_line(char drive)
{
char name[MAXPATHLEN];
int items;
long offset;
/* finish any old drive */
finish_drive_clause();
/* purge out data of old configuration files */
purge(drive, file_nr);
/* reserve slot */
append();
items = sscanf(token,"%c %s %i %i %i %i %li",
&devices[cur_dev].drive,name,&devices[cur_dev].fat_bits,
&devices[cur_dev].tracks,&devices[cur_dev].heads,
&devices[cur_dev].sectors, &offset);
devices[cur_dev].offset = offset;
switch(items){
case 2:
devices[cur_dev].fat_bits = 0;
/* fall thru */
case 3:
devices[cur_dev].sectors = 0;
devices[cur_dev].heads = 0;
devices[cur_dev].tracks = 0;
/* fall thru */
case 6:
devices[cur_dev].offset = 0;
/* fall thru */
default:
break;
case 0:
case 1:
case 4:
case 5:
syntax("bad number of parameters");
exit(1);
}
if(!devices[cur_dev].tracks){
devices[cur_dev].sectors = 0;
devices[cur_dev].heads = 0;
}
devices[cur_dev].drive = toupper(devices[cur_dev].drive);
if (!(devices[cur_dev].name = strdup(name))) {
fprintf(stderr,"Out of memory\n");
exit(1);
}
finish_drive_clause();
pos=0;
}
static int parse_one(int privilege)
{
int action=0;
get_next_token();
if(!token)
return 0;
if((match_token("drive") && ((action = 1)))||
(match_token("drive+") && ((action = 2))) ||
(match_token("+drive") && ((action = 3))) ||
(match_token("clear_drive") && ((action = 4))) ) {
/* finish off the previous drive */
finish_drive_clause();
get_next_token();
if(token_length != 1)
syntax("drive letter expected");
if(action==1 || action==4)
/* replace existing drive */
purge(token[0], file_nr);
if(action==4)
return 1;
if(action==3)
prepend();
else
append();
memset((char*)(devices+cur_dev), 0, sizeof(*devices));
trusted = privilege;
devices[cur_dev].privileged = 2;
devices[cur_dev].drive = toupper(token[0]);
expect_char(':');
return 1;
}
if(token_nr == 1 && token_length == 1) {
parse_old_device_line(token[0]);
return 1;
}
if(match_token("default_fucase")) {
free(mstoupper);
mstoupper=0;
}
if(match_token("default_tounix")) {
Free(Codepage);
Codepage = 0;
}
if(match_token("fucase")) {
expect_char(':');
get_toupper();
return 1;
}
if(match_token("tounix")) {
expect_char(':');
get_codepage();
return 1;
}
if((cur_dev < 0 ||
(set_var(dswitches,
sizeof(dswitches)/sizeof(*dswitches),
(caddr_t)&devices[cur_dev]) &&
set_openflags(&devices[cur_dev]) &&
set_def_format(&devices[cur_dev]))) &&
set_var(switches,
sizeof(switches)/sizeof(*switches), 0))
syntax("unrecognized keyword");
return 1;
}
static int parse(const char *name, int privilege)
{
filename = name;
fp = fopen(filename, "r");
if(!fp)
return 0;
file_nr++;
linenumber = 0;
pos = 0;
token = 0;
cur_dev = -1; /* no current device */
while(parse_one(privilege));
finish_drive_clause();
fclose(fp);
return 1;
}
void read_config(void)
{
char *homedir;
char *envConfFile;
char conf_file[MAXPATHLEN+sizeof(CFG_FILE1)];
/* copy compiled-in devices */
file_nr = 0;
cur_devs = nr_const_devices;
nr_dev = nr_const_devices + 2;
devices = NewArray(nr_dev, struct device);
if(!devices) {
fprintf(stderr,"Out of memory error\n");
exit(1);
}
if(nr_const_devices)
memcpy(devices, const_devices,
nr_const_devices*sizeof(struct device));
#ifndef _OSK
(void) ((parse(CONF_FILE,1) |
parse(LOCAL_CONF_FILE,1) |
parse(SYS_CONF_FILE,1)) ||
(parse(OLD_CONF_FILE,1) |
parse(OLD_LOCAL_CONF_FILE,1)));
#else
(void) (parse("/dd/sys/mtools.conf", 1) || parse("/dd/sys/mtools", 1));
#endif
/* the old-name configuration files only get executed if none of the
* new-name config files were used */
homedir = get_homedir();
if ( homedir ){
strncpy(conf_file, homedir, MAXPATHLEN );
conf_file[MAXPATHLEN]='\0';
strcat( conf_file, CFG_FILE1);
parse(conf_file,0);
}
memset((char *)&devices[cur_devs],0,sizeof(struct device));
envConfFile = getenv("MTOOLSRC");
if(envConfFile)
parse(envConfFile,0);
/* environmental variables */
get_env_conf();
if(mtools_skip_check)
mtools_fat_compatibility=1;
init_codepage();
}
void mtoolstest(int argc, char **argv, int type)
{
/* testing purposes only */
struct device *dev;
int i,j;
for (dev=devices; dev->name; dev++) {
printf("drive %c:\n", dev->drive);
printf("\t#fn=%d mode=%d\n",
dev->file_nr, dev->mode);
printf("\tfile=\"%s\" fat_bits=%d \n",
dev->name,dev->fat_bits);
printf("\ttracks=%d heads=%d sectors=%d\n",
dev->tracks, dev->heads, dev->sectors);
printf("\toffset=0x%lx\n", (long) dev->offset);
printf("\tpartition=0x%x\n", dev->partition);
printf("\tscsi=0x%x\n", dev->scsi);
printf("\tnolock=0x%x\n", dev->nolock);
printf("\tprivileged=0x%x\n", dev->privileged);
#ifdef USE_XDF
printf("\tuse_xdf=0x%x\n", dev->use_xdf);
#endif
if(dev->mode)
printf("\t");
#ifdef O_SYNC
if(dev->mode & O_SYNC)
printf("sync ");
#endif
#ifdef O_NDELAY
if((dev->mode & O_NDELAY))
printf("nodelay ");
#endif
#ifdef O_EXCL
if((dev->mode & O_EXCL))
printf("exclusive ");
#endif
if(dev->mode)
printf("\n");
if(dev->precmd)
printf("\tprecmd=%s\n", dev->precmd);
printf("\n");
}
printf("tounix:\n");
for(i=0; i < 16; i++) {
putchar('\t');
for(j=0; j<8; j++)
printf("0x%02x ",
(unsigned char)Codepage->tounix[i*8+j]);
putchar('\n');
}
printf("\nfucase:\n");
for(i=0; i < 16; i++) {
putchar('\t');
for(j=0; j<8; j++)
printf("0x%02x ",
(unsigned char)mstoupper[i*8+j]);
putchar('\n');
}
if(country_string)
printf("COUNTRY=%s\n", country_string);
printf("mtools_fat_compatibility=%d\n",mtools_fat_compatibility);
printf("mtools_skip_check=%d\n",mtools_skip_check);
printf("mtools_lower_case=%d\n",mtools_ignore_short_case);
exit(0);
}