home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / samba.idb / usr / samba / src / source / make_smbcodepage.c.z / make_smbcodepage.c
Encoding:
C/C++ Source or Header  |  1998-10-28  |  12.1 KB  |  473 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    Create codepage files from codepage_def.XXX files.
  5.  
  6.    Copyright (C) Jeremy Allison 1997-1998.
  7.  
  8.    This program is free software; you can redistribute it and/or modify
  9.    it under the terms of the GNU General Public License as published by
  10.    the Free Software Foundation; either version 2 of the License, or
  11.    (at your option) any later version.
  12.    
  13.    This program is distributed in the hope that it will be useful,
  14.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    GNU General Public License for more details.
  17.    
  18.    You should have received a copy of the GNU General Public License
  19.    along with this program; if not, write to the Free Software
  20.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21. */
  22.  
  23. #include "includes.h"
  24.  
  25. static char *prog_name = NULL;
  26.  
  27. /*
  28.  * Print program usage and die.
  29.  */
  30.  
  31. void codepage_usage(char *progname)
  32. {
  33.   fprintf(stderr, "Usage is : %s [c|d] <codepage> <inputfile> <outputfile>\n",
  34.          progname);
  35.   exit(1);
  36. }
  37.  
  38. /*
  39.  * Read a line from a buffer into a line buffer. Ensure null
  40.  * terminated.
  41.  */
  42.  
  43. void read_line( char **buf, char *line_buf, int size)
  44. {
  45.   char *p = *buf;
  46.   int num = 0;
  47.  
  48.   for(; *p && (*p != '\n'); p++)
  49.   {
  50.     if(num < (size - 1))
  51.       line_buf[num++] = *p;
  52.   }
  53.   if(*p)
  54.     p++; /* Go past the '\n' */
  55.   line_buf[num] = '\0';
  56.   *buf = p;
  57. }
  58.  
  59. /*
  60.  * Strip comment lines and blank lines from the data.
  61.  * Copies into a new buffer and frees the old.
  62.  * Returns the number of lines copied.
  63.  */
  64.  
  65. int clean_data( char **buf, uint32 *size)
  66. {
  67.   pstring linebuf;
  68.   char *p = *buf;
  69.   int num_lines = 0;
  70.   char *newbuf = (char *)malloc( *size + 1);
  71.   char *newbuf_p = NULL;
  72.  
  73.   if(newbuf == NULL)
  74.   {
  75.     fprintf(stderr, "%s: malloc fail for size %d.\n", prog_name, *size + 1);
  76.     exit(1);
  77.   }
  78.  
  79.   newbuf_p = newbuf;
  80.   *newbuf_p = '\0';
  81.  
  82.   while( *p )
  83.   {
  84.     char *cp;
  85.  
  86.     read_line( &p, linebuf, sizeof(linebuf));
  87.     /* Null terminate after comment. */
  88.     if((cp = strchr( linebuf, '#'))!= NULL)
  89.       *cp = '\0';
  90.  
  91.     for(cp = linebuf;*cp && isspace(*cp); cp++)
  92.       ;
  93.  
  94.     if(*cp == '\0')
  95.       continue;
  96.  
  97.     safe_strcpy(newbuf_p, cp, *size - (newbuf_p - newbuf));
  98.     num_lines++;
  99.     newbuf_p += (strlen(newbuf_p) + 1);
  100.   }
  101.  
  102.   free(*buf);
  103.   *buf = newbuf;
  104.   return num_lines;
  105. }
  106.  
  107. /*
  108.  * Parse a byte from a codepage file.
  109.  */
  110.  
  111. BOOL parse_byte(char *buf, unsigned char *bp)
  112. {
  113.   unsigned int b;
  114.   char *endptr = NULL;
  115.  
  116.   b = (unsigned int)strtol(buf, &endptr, 0);
  117.   if(endptr == buf || b > 255)
  118.     return False;
  119.  
  120.   *bp = (unsigned char)b;
  121.   return True;
  122. }
  123.  
  124. /*
  125.  * Parse a bool from a codepage file.
  126.  */
  127.  
  128. BOOL parse_bool(char *buf, unsigned char *bp)
  129. {
  130.   if(isdigit(*buf))
  131.   {
  132.     char *endptr = NULL;
  133.  
  134.     *bp = (unsigned char)strtol(buf, &endptr, 0);
  135.     if(endptr == buf )
  136.       return False;
  137.     if(*bp != 0)
  138.       *bp = 1;
  139.   } else {
  140.     if(strcasecmp(buf, "True") && strcasecmp(buf, "False"))
  141.       return False;
  142.     if(strcasecmp(buf, "True")==0)
  143.       *bp = 1;
  144.     else
  145.       *bp = 0;
  146.   }
  147.   return True;
  148. }
  149.  
  150. /*
  151.  * Print a parse error and exit.
  152.  */
  153.  
  154. void parse_error(char *buf, char *msg)
  155. {
  156.   fprintf(stderr, "%s: %s whilst parsing line \n%s\n", prog_name,
  157.           msg, buf);
  158.   exit(1);
  159. }
  160.     
  161. /*
  162.  * Create a compiled codepage file from a codepage definition file.
  163.  */
  164.  
  165. int do_compile(int codepage, char *input_file, char *output_file)
  166. {
  167.   FILE *fp = NULL;
  168.   uint32 size = 0;
  169.   char *buf = NULL;
  170.   char output_buf[CODEPAGE_HEADER_SIZE + 4 * MAXCODEPAGELINES];
  171.   int num_lines = 0;
  172.   int i = 0;
  173.   struct stat st;
  174.  
  175.   /* Get the size of the input file. Read the entire thing into memory. */
  176.   if(stat((char *)input_file, &st)!= 0)
  177.   {
  178.     fprintf(stderr, "%s: failed to get the file size for file %s. Error was %s\n",
  179.             prog_name, input_file, strerror(errno));
  180.     exit(1);
  181.   }
  182.  
  183.   size = (uint32)st.st_size;
  184.  
  185.   /* I don't believe these things should be bigger than 100k :-) */
  186.   if(size > 100*1024)
  187.   {
  188.     fprintf(stderr, "%s: filesize %d is too large for a codepage definition file. \
  189. The maximum size I will believe is 100k.\n", prog_name, size);
  190.     exit(1);
  191.   }
  192.  
  193.   if((fp = fopen(input_file, "r")) == NULL)
  194.   {
  195.     fprintf(stderr, "%s: cannot open file %s for input.\n", prog_name, input_file);
  196.     exit(1);
  197.   }
  198.  
  199.   /* As we will be reading text, allocate one more byte for a '\0' */
  200.   if((buf = (char *)malloc( size + 1 )) == NULL)
  201.   {
  202.     fprintf(stderr, "%s: malloc fail for size %d.\n", prog_name, size + 1);
  203.     fclose(fp);
  204.     exit(1);
  205.   }
  206.  
  207.   if(fread( buf, 1, size, fp) != size)
  208.   {
  209.     fprintf(stderr, "%s: read failed for file %s. Error was %s.\n", prog_name,
  210.             input_file, strerror(errno));
  211.     free((char *)buf);
  212.     fclose(fp);
  213.     exit(1);
  214.   }
  215.  
  216.   /* Null terminate the text read. */
  217.   buf[size] = '\0';
  218.  
  219.   /* Go through the data line by line, strip out comments (anything
  220.      after a '#' to end-of-line) and blank lines. The rest should be
  221.      the codepage data.
  222.    */
  223.  
  224.   num_lines = clean_data( &buf, &size);
  225.  
  226.   /* There can be a maximum of MAXCODEPAGELINES lines. */
  227.   if(num_lines > MAXCODEPAGELINES)
  228.   {
  229.     fprintf(stderr, "%s: There can be a maximum %d lines of data in a codepage \
  230. definition file. File %s has %d.\n", prog_name, MAXCODEPAGELINES, input_file, num_lines);
  231.     exit(1);
  232.   }
  233.  
  234.   /* Setup the output file header. */
  235.   SSVAL(output_buf,CODEPAGE_VERSION_OFFSET,CODEPAGE_FILE_VERSION_ID);
  236.   SSVAL(output_buf,CODEPAGE_CLIENT_CODEPAGE_OFFSET,(uint16)codepage);
  237.   SIVAL(output_buf,CODEPAGE_LENGTH_OFFSET,(num_lines * 4));
  238.  
  239.   /* Now convert the lines into the compiled form. */
  240.   for(i = 0; i < num_lines; i++)
  241.   {
  242.     char token_buf[512];
  243.     char *p = buf;
  244.     unsigned char b = 0;
  245.  
  246.     /* Get the 'lower' value. */
  247.     if(!next_token(&p, token_buf, NULL))
  248.       parse_error(buf, "cannot parse first value");
  249.     if(!parse_byte( token_buf, &b))
  250.       parse_error(buf, "first value doesn't resolve to a byte");
  251.  
  252.     /* Add this to the output buffer. */
  253.     SCVAL(output_buf,CODEPAGE_HEADER_SIZE+(i*4),b);
  254.  
  255.     /* Get the 'upper' value. */
  256.     if(!next_token(&p, token_buf, NULL))
  257.       parse_error(buf, "cannot parse second value");
  258.     if(!parse_byte( token_buf, &b))
  259.       parse_error(buf, "second value doesn't resolve to a byte");
  260.  
  261.     /* Add this to the output buffer. */
  262.     SCVAL(output_buf,CODEPAGE_HEADER_SIZE+(i*4) + 1,b);
  263.  
  264.     /* Get the 'upper to lower' value. */
  265.     if(!next_token(&p, token_buf, NULL))
  266.       parse_error(buf, "cannot parse third value");
  267.     if(!parse_bool( token_buf, &b))
  268.       parse_error(buf, "third value doesn't resolve to a boolean");
  269.  
  270.     /* Add this to the output buffer. */
  271.     SCVAL(output_buf,CODEPAGE_HEADER_SIZE+(i*4) + 2,b);
  272.  
  273.     /* Get the 'lower to upper' value. */
  274.     if(!next_token(&p, token_buf, NULL))
  275.       parse_error(buf, "cannot parse fourth value");
  276.     if(!parse_bool( token_buf, &b))
  277.       parse_error(buf, "fourth value doesn't resolve to a boolean");
  278.  
  279.     /* Add this to the output buffer. */
  280.     SCVAL(output_buf,CODEPAGE_HEADER_SIZE+(i*4) + 3,b);
  281.  
  282.     buf += (strlen(buf) + 1);
  283.   }
  284.  
  285.   /* Now write out the output_buf. */
  286.   if((fp = fopen(output_file, "w"))==NULL)
  287.   {
  288.     fprintf(stderr, "%s: Cannot open output file %s. Error was %s.\n",
  289.             prog_name, output_file, strerror(errno));
  290.     exit(1);
  291.   }
  292.  
  293.   if(fwrite(output_buf, 1, CODEPAGE_HEADER_SIZE + (num_lines*4), fp) !=
  294.          CODEPAGE_HEADER_SIZE + (num_lines*4))
  295.   {
  296.     fprintf(stderr, "%s: Cannot write output file %s. Error was %s.\n",
  297.             prog_name, output_file, strerror(errno));
  298.     exit(1);
  299.   }  
  300.  
  301.   fclose(fp);
  302.  
  303.   return 0;
  304. }
  305.  
  306. /*
  307.  * Placeholder for now.
  308.  */
  309.  
  310. int do_decompile( int codepage, char *input_file, char *output_file)
  311. {
  312.   uint32 size = 0;
  313.   struct stat st;
  314.   char header_buf[CODEPAGE_HEADER_SIZE];
  315.   char *buf = NULL;
  316.   FILE *fp = NULL;
  317.   int num_lines = 0;
  318.   int i = 0;
  319.  
  320.   /* Get the size of the input file. Read the entire thing into memory. */
  321.   if(stat((char *)input_file, &st)!= 0)
  322.   {
  323.     fprintf(stderr, "%s: failed to get the file size for file %s. Error was %s\n",
  324.             prog_name, input_file, strerror(errno));
  325.     exit(1);
  326.   }
  327.  
  328.   size = (uint32)st.st_size;
  329.  
  330.   if( size < CODEPAGE_HEADER_SIZE || size > (CODEPAGE_HEADER_SIZE + 256))
  331.   { 
  332.     fprintf(stderr, "%s: file %s is an incorrect size for a \
  333. code page file.\n", prog_name, input_file);
  334.     exit(1);
  335.   } 
  336.   
  337.   /* Read the first 8 bytes of the codepage file - check
  338.      the version number and code page number. All the data
  339.      is held in little endian format.
  340.    */
  341.     
  342.   if((fp = fopen( input_file, "r")) == NULL)
  343.   { 
  344.     fprintf(stderr, "%s: cannot open file %s. Error was %s\n",
  345.               prog_name, input_file, strerror(errno));
  346.     exit(1);
  347.   } 
  348.   
  349.   if(fread( header_buf, 1, CODEPAGE_HEADER_SIZE, fp)!=CODEPAGE_HEADER_SIZE)
  350.   { 
  351.     fprintf(stderr, "%s: cannot read header from file %s. Error was %s\n",
  352.               prog_name, input_file, strerror(errno));
  353.     exit(1);
  354.   } 
  355.   
  356.   /* Check the version value */
  357.   if(SVAL(header_buf,CODEPAGE_VERSION_OFFSET) != CODEPAGE_FILE_VERSION_ID)
  358.   { 
  359.     fprintf(stderr, "%s: filename %s has incorrect version id. \
  360. Needed %hu, got %hu.\n",
  361.           prog_name, input_file, (uint16)CODEPAGE_FILE_VERSION_ID, 
  362.           SVAL(header_buf,CODEPAGE_VERSION_OFFSET));
  363.     exit(1);
  364.   } 
  365.   
  366.   /* Check the codepage matches */
  367.   if(SVAL(header_buf,CODEPAGE_CLIENT_CODEPAGE_OFFSET) != (uint16)codepage)
  368.   { 
  369.     fprintf(stderr, "%s: filename %s has incorrect codepage. \
  370. Needed %hu, got %hu.\n",
  371.            prog_name, input_file, (uint16)codepage, 
  372.            SVAL(header_buf,CODEPAGE_CLIENT_CODEPAGE_OFFSET));
  373.     exit(1);
  374.   } 
  375.   
  376.   /* Check the length is correct. */
  377.   if(IVAL(header_buf,CODEPAGE_LENGTH_OFFSET) !=
  378.                  (unsigned int)(size - CODEPAGE_HEADER_SIZE))
  379.   { 
  380.     fprintf(stderr, "%s: filename %s has incorrect size headers. \
  381. Needed %u, got %u.\n", prog_name, input_file, size - CODEPAGE_HEADER_SIZE,
  382.                IVAL(header_buf,CODEPAGE_LENGTH_OFFSET));
  383.     exit(1);
  384.   } 
  385.   
  386.   size -= CODEPAGE_HEADER_SIZE; /* Remove header */
  387.     
  388.   /* Make sure the size is a multiple of 4. */
  389.   if((size % 4 ) != 0)
  390.   { 
  391.     fprintf(stderr, "%s: filename %s has a codepage size not a \
  392. multiple of 4.\n", prog_name, input_file);
  393.     exit(1);
  394.   } 
  395.   
  396.   /* Allocate space for the code page file and read it all in. */
  397.   if((buf = (char *)malloc( size )) == NULL)
  398.   { 
  399.     fprintf (stderr, "%s: malloc fail for size %d.\n",
  400.              prog_name, size );
  401.     exit(1);
  402.   } 
  403.   
  404.   if(fread( buf, 1, size, fp)!=size)
  405.   { 
  406.     fprintf(stderr, "%s: read fail on file %s. Error was %s.\n",
  407.               prog_name, input_file, strerror(errno));
  408.     exit(1);
  409.   } 
  410.   
  411.   fclose(fp);
  412.     
  413.   /* Now dump the codepage into an ascii file. */
  414.   if((fp = fopen(output_file, "w")) == NULL)
  415.   {
  416.     fprintf(stderr, "%s: cannot open file %s. Error was %s\n",
  417.               prog_name, output_file, strerror(errno));
  418.     exit(1);
  419.   } 
  420.  
  421.   fprintf(fp, "#\n# Codepage definition file for IBM Code Page %d.\n#\n",
  422.           codepage);
  423.   fprintf(fp, "# This file was automatically generated.\n#\n");
  424.   fprintf(fp, "# defines lower->upper mapping.\n");
  425.   fprintf(fp, "#\n#The columns are :\n# lower\tupper\tu-t-l\tl-t-u\n#\n");
  426.  
  427.   num_lines = size / 4;
  428.   for( i = 0; i < num_lines; i++)
  429.   {
  430.     fprintf(fp, "0x%02X\t0x%02X\t%s\t%s\n", CVAL(buf, (i*4)), CVAL(buf, (i*4)+1),
  431.            CVAL(buf, (i*4)+2) ? "True" : "False",
  432.            CVAL(buf, (i*4)+3) ? "True" : "False");
  433.   }
  434.   fclose(fp);
  435.   return 0;
  436. }
  437.  
  438. int main(int argc, char **argv)
  439. {
  440.   int codepage = 0;
  441.   char *input_file = NULL;
  442.   char *output_file = NULL;
  443.   BOOL compile = False;
  444.  
  445.   prog_name = argv[0];
  446.  
  447.   if(argc != 5)
  448.     codepage_usage(prog_name);
  449.  
  450.   if(argv[1][0] != 'c' && argv[1][0] != 'C' && argv[1][0] != 'd' &&
  451.      argv[1][0] != 'D')
  452.     codepage_usage(prog_name);
  453.  
  454.   input_file = argv[3];
  455.   output_file = argv[4];
  456.  
  457.   /* Are we compiling or decompiling. */
  458.   if(argv[1][0] == 'c' || argv[1][0] == 'C')
  459.     compile = True;
  460.  
  461.   /* Convert the second argument into a client codepage value. */
  462.   if((codepage = atoi(argv[2])) == 0)
  463.   {
  464.     fprintf(stderr, "%s: %s is not a valid codepage.\n", prog_name, argv[2]);
  465.     exit(1);
  466.   }
  467.  
  468.   if(compile)
  469.     return do_compile( codepage, input_file, output_file);
  470.   else
  471.     return do_decompile( codepage, input_file, output_file);
  472. }
  473.