home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / disk-man / mtools-3.000 / mtools-3 / mtools-3.0 / config.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-08  |  13.3 KB  |  628 lines

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