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 >
C/C++ Source or Header  |  1997-11-12  |  15KB  |  669 lines

  1. #include "sysincludes.h"
  2. #include "mtools.h"
  3. #include "codepage.h"
  4. #include "paths.h"
  5.  
  6. /* global variables */
  7. /* they are not really harmful here, because there is only one configuration
  8.  * file per invocations */
  9.  
  10. #define MAX_LINE_LEN 256
  11.  
  12. #ifdef _OSK
  13. typedef long caddr_t;
  14. #endif
  15.  
  16. /* scanner */
  17. static char buffer[MAX_LINE_LEN+1]; /* buffer for the whole line */
  18. static char *pos; /* position in line */
  19. static char *token; /* last scanned token */
  20. static int token_length; /* length of the token */
  21. static FILE *fp; /* file pointer for configuration file */
  22. static int linenumber; /* current line number. Only used for printing
  23.             * error messages */
  24. static const char *filename; /* current file name. Only used for printing
  25.                   * error messages */
  26. static int file_nr=0;
  27.  
  28. /* devices */
  29. static int cur_devs; /* current number of defined devices */
  30. static int cur_dev; /* device being filled in. If negative, none */
  31. static int trusted=0; /* is the currently parsed device entry trusted? */
  32. static int nr_dev; /* number of devices that the current table can hold */
  33. struct device *devices; /* the device table */
  34. static int token_nr; /* number of tokens in line */
  35.  
  36. /* "environment" variables */
  37. int mtools_skip_check=0;
  38. int mtools_fat_compatibility=0;
  39. int mtools_ignore_short_case=0;
  40. int mtools_rate_0=0;
  41. int mtools_rate_any=0;
  42. int mtools_no_vfat=0;
  43. char *country_string=0;
  44.  
  45. typedef struct switches_l {
  46.     const char *name;
  47.     caddr_t address;
  48.     enum {
  49.         INT,
  50.         STRING
  51.     } type;
  52. } switches_t;
  53.  
  54. static switches_t switches[] = {
  55.     { "MTOOLS_LOWER_CASE", (caddr_t) & mtools_ignore_short_case, INT },
  56.     { "MTOOLS_FAT_COMPATIBILITY", (caddr_t) & mtools_fat_compatibility, INT },
  57.     { "MTOOLS_SKIP_CHECK", (caddr_t) & mtools_skip_check, INT },
  58.     { "MTOOLS_NO_VFAT", (caddr_t) & mtools_no_vfat, INT },
  59.     { "MTOOLS_RATE_0", (caddr_t) &mtools_rate_0, INT },
  60.     { "MTOOLS_RATE_ANY", (caddr_t) &mtools_rate_any, INT },
  61.     { "COUNTRY", (caddr_t) &country_string, STRING }
  62. };
  63.  
  64. static struct {
  65.     const char *name;
  66.     int flag;
  67. } openflags[] = {
  68. #ifdef O_SYNC
  69.     { "sync",        O_SYNC },
  70. #endif
  71. #ifdef O_NDELAY
  72.     { "nodelay",    O_NDELAY },
  73. #endif
  74. #ifdef O_EXCL
  75.     { "exclusive",    O_EXCL }
  76. #endif
  77. #ifdef _OSK
  78.     { "", 0}
  79. #endif
  80. };
  81.  
  82. static struct {
  83.     const char *name;
  84.     signed char fat_bits;
  85.     int tracks;
  86.     unsigned short heads;
  87.     unsigned short sectors;
  88. } default_formats[] = {
  89.     { "hd514",            12, 80, 2, 15 },
  90.     { "high-density-5-1/4",    12, 80, 2, 15 },
  91.     { "1.2m",            12, 80, 2, 15 },
  92.     
  93.     { "hd312",            12, 80, 2, 18 },
  94.     { "high-density-3-1/2",    12, 80, 2, 18 },
  95.     { "1.44m",             12, 80, 2, 18 },
  96.  
  97.     { "dd312",            12, 80, 2, 9 },
  98.     { "double-density-3-1/2",    12, 80, 2, 9 },
  99.     { "720k",            12, 80, 2, 9 },
  100.  
  101.     { "dd514",            12, 40, 2, 9 },
  102.     { "double-density-5-1/4",    12, 40, 2, 9 },
  103.     { "360k",            12, 40, 2, 9 },
  104.  
  105.     { "320k",            12, 40, 2, 8 },
  106.     { "180k",            12, 40, 1, 9 },
  107.     { "160k",            12, 40, 1, 8 }
  108. };
  109.  
  110. #define OFFS(x) ((caddr_t)&((struct device *)0)->x)
  111.  
  112. static switches_t dswitches[]= {
  113.     { "FILE", OFFS(name), STRING },
  114.     { "OFFSET", OFFS(offset), INT },
  115.     { "PARTITION", OFFS(partition), INT },
  116.     { "SCSI", OFFS(scsi), INT },
  117.     { "PRIVILEGED", OFFS(privileged), INT },
  118.     { "NOLOCK", OFFS(nolock), INT },
  119.     { "FAT", OFFS(fat_bits), INT },
  120.     { "FAT_BITS", OFFS(fat_bits), INT },
  121.     { "MODE", OFFS(mode), INT },
  122.     { "TRACKS",  OFFS(tracks), INT },
  123.     { "CYLINDERS",  OFFS(tracks), INT },
  124.     { "HEADS", OFFS(heads), INT },
  125.     { "SECTORS", OFFS(sectors), INT },
  126.     { "USE_XDF", OFFS(use_xdf), INT },
  127.     { "PRECMD", OFFS(precmd), STRING }
  128.  
  129. };
  130.  
  131. static void syntax(const char *msg)
  132. {
  133.     fprintf(stderr,"Syntax error at line %d column %ld in file %s: %s\n",
  134.         linenumber, (long)(token - buffer), filename, msg);
  135.     exit(1);
  136. }
  137.  
  138. static void get_env_conf(void)
  139. {
  140.     char *s;
  141.     int i;
  142.  
  143.     for(i=0; i< sizeof(switches) / sizeof(*switches); i++) {
  144.     s = getenv(switches[i].name);
  145.     if(s) {
  146.         if(switches[i].type == INT)
  147.         * ((int *)switches[i].address) = strtoul(s,0,0);
  148.         else if (switches[i].type == STRING)
  149.         * ((char **)switches[i].address) = s;
  150.     }
  151.     }
  152. }
  153.  
  154. static int getline(void)
  155. {
  156.     if(!fgets(buffer, MAX_LINE_LEN, fp))
  157.         return -1;
  158.     linenumber++;
  159.     pos = buffer;
  160.     token_nr = 0;
  161.     buffer[MAX_LINE_LEN] = '\0';
  162.     if(strlen(buffer) == MAX_LINE_LEN)
  163.         syntax("line too long");
  164.     return 0;
  165. }
  166.         
  167. static void skip_junk(int expect)
  168. {
  169.     while(!pos || !*pos || strchr(" #\n\t", *pos)) {
  170.         if(!pos || !*pos || *pos == '#') {
  171.             if(getline()) {
  172.                 pos = 0;
  173.                 if(expect)
  174.                     syntax("end of file unexpected");
  175.                 return;
  176.             }
  177.         } else
  178.             pos++;
  179.     }
  180.     token_nr++;
  181. }
  182.  
  183. /* get the next token */
  184. static char *get_next_token(void)
  185. {
  186.     skip_junk(0);
  187.     if(!pos) {
  188.         token_length = 0;
  189.         token = 0;
  190.         return 0;
  191.     }
  192.     token = pos;
  193.     token_length = strcspn(token, " \t\n#:=");
  194.     pos += token_length;
  195.     return token;
  196. }
  197.  
  198. static int match_token(const char *template)
  199. {
  200.     return (strlen(template) == token_length &&
  201.         !strncasecmp(template, token, token_length));
  202. }
  203.  
  204. static void expect_char(char c)
  205. {
  206.     char buf[11];
  207.  
  208.     skip_junk(1);
  209.     if(*pos != c) {
  210.         sprintf(buf, "expected %c", c);
  211.         syntax(buf);
  212.     }
  213.     pos++;
  214. }
  215.  
  216. static char *get_string(void)
  217. {
  218.     char *end, *str;
  219.  
  220.     skip_junk(1);
  221.     if(*pos != '"')
  222.         syntax(" \" expected");
  223.     str = pos+1;
  224.     end = strchr(str, '\"');
  225.     if(!end)
  226.         syntax("unterminated string constant");
  227.     *end = '\0';
  228.     pos = end+1;
  229.     return str;
  230. }
  231.  
  232. static int get_number(void)
  233. {
  234.     char *last;
  235.     int n;
  236.  
  237.     skip_junk(1);
  238.     last = pos;
  239.     n=strtoul(pos, &pos, 0);
  240.     if(last == pos)
  241.         syntax("numeral expected");
  242.     pos++;
  243.     token_nr++;
  244.     return n;
  245. }
  246.  
  247. /* purge all entries pertaining to a given drive from the table */
  248. static void purge(char drive, int fn)
  249. {
  250.     int i,j;
  251.  
  252.     drive = toupper(drive);
  253.     for(j=0, i=0; i < cur_devs; i++) {
  254.         if(devices[i].drive != drive ||
  255.            devices[i].file_nr == fn)
  256.             devices[j++] = devices[i];
  257.     }
  258.     cur_devs = j;
  259. }
  260.  
  261. static void grow(void)
  262. {
  263.     if(cur_devs >= nr_dev - 2) {
  264.         nr_dev = (cur_devs + 2) << 1;
  265.         if(!(devices=Grow(devices, nr_dev, struct device))){
  266.             fprintf(stderr,"Out of memory error");
  267.             exit(1);
  268.         }
  269.     }
  270. }
  271.     
  272.  
  273. static void init_drive(void)
  274. {
  275.     memset((char *)&devices[cur_dev], 0, sizeof(struct device));
  276.     devices[cur_dev].ssize = 2;
  277. }
  278.  
  279. /* prepends a device to the table */
  280. static void prepend(void)
  281. {
  282.     int i;
  283.  
  284.     grow();
  285.     for(i=cur_devs; i>0; i--)
  286.         devices[i] = devices[i-1];
  287.     cur_dev = 0;
  288.     cur_devs++;
  289.     init_drive();
  290. }
  291.  
  292.  
  293. /* appends a device to the table */
  294. static void append(void)
  295. {
  296.     grow();
  297.     cur_dev = cur_devs;
  298.     cur_devs++;
  299.     init_drive();
  300. }
  301.  
  302.  
  303. static void finish_drive_clause(void)
  304. {
  305.     if(cur_dev == -1) {
  306.         trusted = 0;
  307.         return;
  308.     }
  309.     if(!devices[cur_dev].name)
  310.         syntax("missing filename");
  311.     if((devices[cur_dev].tracks ||
  312.         devices[cur_dev].heads ||
  313.         devices[cur_dev].sectors) &&
  314.        (!devices[cur_dev].tracks ||
  315.         !devices[cur_dev].heads ||
  316.         !devices[cur_dev].sectors))
  317.         syntax("incomplete geometry: either indicate all of track/heads/sectors or none of them");
  318.     devices[cur_dev].file_nr = file_nr;
  319.     if(devices[cur_dev].privileged == 2)
  320.         devices[cur_dev].privileged = devices[cur_dev].scsi;
  321.     if(!trusted)
  322.         devices[cur_dev].privileged = 0;
  323.     trusted = 0;
  324.     cur_dev = -1;
  325. }
  326.  
  327. static int set_var(struct switches_l *switches, int nr,
  328.            caddr_t base_address)
  329. {
  330.     int i;
  331.     for(i=0; i < nr; i++) {
  332.         if(match_token(switches[i].name)) {
  333.             expect_char('=');
  334.             if(switches[i].type == INT)
  335.                 * ((int *)((long)switches[i].address+base_address)) = 
  336.                     get_number();
  337.             else if (switches[i].type == STRING)
  338.                 * ((char**)((long)switches[i].address+base_address))=
  339.                    strdup(get_string());
  340.             return 0;
  341.         }
  342.     }
  343.     return 1;
  344. }
  345.  
  346. static int set_openflags(struct device *dev)
  347. {
  348.     int i;
  349.  
  350.     for(i=0; i < sizeof(openflags) / sizeof(*openflags); i++) {
  351.         if(match_token(openflags[i].name)) {
  352.             dev->mode |= openflags[i].flag;
  353.             return 0;
  354.         }
  355.     }
  356.     return 1;
  357. }
  358.  
  359. static int set_def_format(struct device *dev)
  360. {
  361.     int i;
  362.  
  363.     for(i=0; i < sizeof(default_formats)/sizeof(*default_formats); i++) {
  364.         if(match_token(default_formats[i].name)) {
  365.             if(!dev->ssize)
  366.                 dev->ssize = 2;
  367.             if(!dev->tracks)
  368.                 dev->tracks = default_formats[i].tracks;
  369.             if(!dev->heads)
  370.                 dev->heads = default_formats[i].heads;
  371.             if(!dev->sectors)
  372.                 dev->sectors = default_formats[i].sectors;
  373.             if(!dev->fat_bits)
  374.                 dev->fat_bits = default_formats[i].fat_bits;
  375.             return 0;
  376.         }
  377.     }
  378.     return 1;
  379. }    
  380.  
  381. static void get_codepage(void)
  382. {
  383.     int i;
  384.     unsigned short n;
  385.  
  386.     if(!Codepage)
  387.         Codepage = New(Codepage_t);
  388.     for(i=0; i<128; i++) {
  389.         n = get_number();
  390.         if(n > 0xff)
  391.             n = 0x5f;
  392.         Codepage->tounix[i] = n;
  393.     }    
  394. }
  395.  
  396. static void get_toupper(void)
  397. {
  398.     int i;
  399.  
  400.     if(!mstoupper)
  401.         mstoupper = malloc(128);
  402.     for(i=0; i<128; i++)
  403.         mstoupper[i] = get_number();
  404. }
  405.  
  406. static void parse_old_device_line(char drive)
  407. {
  408.     char name[MAXPATHLEN];
  409.     int items;
  410.     long offset;
  411.  
  412.     /* finish any old drive */
  413.     finish_drive_clause();
  414.  
  415.     /* purge out data of old configuration files */
  416.     purge(drive, file_nr);
  417.     
  418.     /* reserve slot */
  419.     append();
  420.     items = sscanf(token,"%c %s %i %i %i %i %li",
  421.                &devices[cur_dev].drive,name,&devices[cur_dev].fat_bits,
  422.                &devices[cur_dev].tracks,&devices[cur_dev].heads,
  423.                &devices[cur_dev].sectors, &offset);
  424.     devices[cur_dev].offset = offset;
  425.     switch(items){
  426.         case 2:
  427.             devices[cur_dev].fat_bits = 0;
  428.             /* fall thru */
  429.         case 3:
  430.             devices[cur_dev].sectors = 0;
  431.             devices[cur_dev].heads = 0;
  432.             devices[cur_dev].tracks = 0;
  433.             /* fall thru */
  434.         case 6:
  435.             devices[cur_dev].offset = 0;
  436.             /* fall thru */
  437.         default:
  438.             break;
  439.         case 0:
  440.         case 1:
  441.         case 4:
  442.         case 5:
  443.             syntax("bad number of parameters");
  444.             exit(1);
  445.     }
  446.     if(!devices[cur_dev].tracks){
  447.         devices[cur_dev].sectors = 0;
  448.         devices[cur_dev].heads = 0;
  449.     }
  450.     
  451.     devices[cur_dev].drive = toupper(devices[cur_dev].drive);
  452.     if (!(devices[cur_dev].name = strdup(name))) {
  453.         fprintf(stderr,"Out of memory\n");
  454.         exit(1);
  455.     }
  456.     finish_drive_clause();
  457.     pos=0;
  458. }
  459.  
  460. static int parse_one(int privilege)
  461. {
  462.     int action=0;
  463.  
  464.     get_next_token();
  465.     if(!token)
  466.         return 0;
  467.  
  468.     if((match_token("drive") && ((action = 1)))||
  469.        (match_token("drive+") && ((action = 2))) ||
  470.        (match_token("+drive") && ((action = 3))) ||
  471.        (match_token("clear_drive") && ((action = 4))) ) {
  472.         /* finish off the previous drive */
  473.         finish_drive_clause();
  474.  
  475.         get_next_token();
  476.         if(token_length != 1)
  477.             syntax("drive letter expected");
  478.  
  479.         if(action==1 || action==4)
  480.             /* replace existing drive */            
  481.             purge(token[0], file_nr);
  482.         if(action==4)
  483.             return 1;
  484.         if(action==3)
  485.             prepend();
  486.         else
  487.             append();
  488.         memset((char*)(devices+cur_dev), 0, sizeof(*devices));
  489.         trusted = privilege;
  490.         devices[cur_dev].privileged = 2;
  491.         devices[cur_dev].drive = toupper(token[0]);
  492.         expect_char(':');
  493.         return 1;
  494.     }
  495.     if(token_nr == 1 && token_length == 1) {
  496.         parse_old_device_line(token[0]);
  497.         return 1;
  498.     }
  499.     if(match_token("default_fucase")) {
  500.         free(mstoupper);
  501.         mstoupper=0;
  502.     }
  503.     if(match_token("default_tounix")) {
  504.         Free(Codepage);
  505.         Codepage = 0;
  506.     }
  507.     if(match_token("fucase")) {
  508.         expect_char(':');
  509.         get_toupper();
  510.         return 1;
  511.     }
  512.     if(match_token("tounix")) {
  513.         expect_char(':');
  514.         get_codepage();
  515.         return 1;
  516.     }
  517.     
  518.     if((cur_dev < 0 || 
  519.         (set_var(dswitches,
  520.              sizeof(dswitches)/sizeof(*dswitches),
  521.              (caddr_t)&devices[cur_dev]) &&
  522.          set_openflags(&devices[cur_dev]) &&
  523.          set_def_format(&devices[cur_dev]))) &&
  524.        set_var(switches,
  525.            sizeof(switches)/sizeof(*switches), 0))
  526.         syntax("unrecognized keyword");
  527.     return 1;
  528. }
  529.  
  530. static int parse(const char *name, int privilege)
  531. {
  532.     filename = name;
  533.     fp = fopen(filename, "r");
  534.     if(!fp)
  535.         return 0;
  536.     file_nr++;
  537.     linenumber = 0;
  538.     pos = 0;
  539.     token = 0;
  540.     cur_dev = -1; /* no current device */
  541.  
  542.     while(parse_one(privilege));
  543.     finish_drive_clause();
  544.     fclose(fp);
  545.     return 1;
  546. }
  547.  
  548. void read_config(void)
  549. {
  550.     char *homedir;
  551.     char *envConfFile;
  552.     char conf_file[MAXPATHLEN+sizeof(CFG_FILE1)];
  553.  
  554.     
  555.     /* copy compiled-in devices */
  556.     file_nr = 0;
  557.     cur_devs = nr_const_devices;
  558.     nr_dev = nr_const_devices + 2;
  559.     devices = NewArray(nr_dev, struct device);
  560.     if(!devices) {
  561.         fprintf(stderr,"Out of memory error\n");
  562.         exit(1);
  563.     }
  564.     if(nr_const_devices)
  565.         memcpy(devices, const_devices,
  566.                nr_const_devices*sizeof(struct device));
  567.  
  568. #ifndef _OSK
  569.     (void) ((parse(CONF_FILE,1) | 
  570.          parse(LOCAL_CONF_FILE,1) |
  571.          parse(SYS_CONF_FILE,1)) ||
  572.         (parse(OLD_CONF_FILE,1) | 
  573.          parse(OLD_LOCAL_CONF_FILE,1)));
  574. #else
  575.     (void) (parse("/dd/sys/mtools.conf", 1) || parse("/dd/sys/mtools", 1));
  576. #endif
  577.     /* the old-name configuration files only get executed if none of the
  578.      * new-name config files were used */
  579.  
  580.     homedir = get_homedir();
  581.     if ( homedir ){
  582.         strncpy(conf_file, homedir, MAXPATHLEN );
  583.         conf_file[MAXPATHLEN]='\0';
  584.         strcat( conf_file, CFG_FILE1);
  585.         parse(conf_file,0);
  586.     }
  587.     memset((char *)&devices[cur_devs],0,sizeof(struct device));
  588.  
  589.     envConfFile = getenv("MTOOLSRC");
  590.     if(envConfFile)
  591.         parse(envConfFile,0);
  592.  
  593.     /* environmental variables */
  594.     get_env_conf();
  595.     if(mtools_skip_check)
  596.         mtools_fat_compatibility=1;
  597.     init_codepage();
  598. }
  599.  
  600. void mtoolstest(int argc, char **argv, int type)
  601. {
  602.     /* testing purposes only */
  603.     struct device *dev;
  604.     int i,j;
  605.     for (dev=devices; dev->name; dev++) {
  606.         printf("drive %c:\n", dev->drive);
  607.         printf("\t#fn=%d mode=%d\n",
  608.                dev->file_nr, dev->mode);
  609.         printf("\tfile=\"%s\" fat_bits=%d \n",
  610.                dev->name,dev->fat_bits);
  611.         printf("\ttracks=%d heads=%d sectors=%d\n",
  612.                dev->tracks, dev->heads, dev->sectors);
  613.         printf("\toffset=0x%lx\n", (long) dev->offset);
  614.         printf("\tpartition=0x%x\n", dev->partition);
  615.         printf("\tscsi=0x%x\n", dev->scsi);
  616.         printf("\tnolock=0x%x\n", dev->nolock);
  617.         printf("\tprivileged=0x%x\n", dev->privileged);
  618.  
  619. #ifdef USE_XDF
  620.         printf("\tuse_xdf=0x%x\n", dev->use_xdf);
  621. #endif
  622.         if(dev->mode)
  623.             printf("\t");
  624. #ifdef O_SYNC
  625.         if(dev->mode & O_SYNC)
  626.             printf("sync ");
  627. #endif
  628. #ifdef O_NDELAY
  629.         if((dev->mode & O_NDELAY))
  630.             printf("nodelay ");
  631. #endif
  632. #ifdef O_EXCL
  633.         if((dev->mode & O_EXCL))
  634.             printf("exclusive ");
  635. #endif
  636.         if(dev->mode)
  637.             printf("\n");
  638.  
  639.         if(dev->precmd)
  640.             printf("\tprecmd=%s\n", dev->precmd);
  641.  
  642.         printf("\n");
  643.     }
  644.     
  645.     printf("tounix:\n");
  646.     for(i=0; i < 16; i++) {
  647.         putchar('\t');
  648.         for(j=0; j<8; j++)
  649.             printf("0x%02x ",
  650.                    (unsigned char)Codepage->tounix[i*8+j]);
  651.         putchar('\n');
  652.     }
  653.     printf("\nfucase:\n");
  654.     for(i=0; i < 16; i++) {
  655.         putchar('\t');
  656.         for(j=0; j<8; j++)
  657.             printf("0x%02x ",
  658.                    (unsigned char)mstoupper[i*8+j]);
  659.         putchar('\n');
  660.     }
  661.     if(country_string)
  662.         printf("COUNTRY=%s\n", country_string);
  663.     printf("mtools_fat_compatibility=%d\n",mtools_fat_compatibility);
  664.     printf("mtools_skip_check=%d\n",mtools_skip_check);
  665.     printf("mtools_lower_case=%d\n",mtools_ignore_short_case);
  666.  
  667.     exit(0);
  668. }
  669.