home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / macutils.lzh / MACUTILS / MCVERT / mcvert.c < prev    next >
C/C++ Source or Header  |  1996-02-03  |  15KB  |  408 lines

  1. /* mcvert.c - version 1.05 - 10 January, 1990
  2.  * Written by Doug Moore - Rice University - dougm@rice.edu - April '87
  3.  * Sun bug fixes, assorted stuff - Jim Sasaki, March '89
  4.  * Changed default max_line_size from 2000 to unlimited - Doug Moore, April, '89
  5.  * Sun 3/60 doesn't like odd-sized structs.  Bug fixed - Doug Moore, April, '89
  6.  *                                              - aided by Spencer W. Thomas
  7.  * Didn't handle properly many hqx files combined in one file.  Bug fixed -
  8.  *                                           Doug Moore, June, '89
  9.  * Modified to handle MacBinaryII specification. Jim Van Verth, Sept, '89
  10.  *
  11.  * Fixed a bug when there are blank lines in hqx data, as happens when newline
  12.  * get translated to CRLF and then to \n\n, common for some file transfers.
  13.  * The last hqx line would be lost if the previous line was blank or junk.
  14.  *    Glenn Trewitt, Stanford University, 1990    (1.05)
  15.  *
  16.  * This program may be freely distributed for non-profit purposes.  It may not
  17.  * be sold, by itself or as part of a collection of software.  It may be freely
  18.  * modified as long as no modified version is distributed.  Modifications of
  19.  * interest to all can be incorporated into the program by sending them to me
  20.  * for distribution.  Parts of the code can be used in other programs.  I am not
  21.  * responsible for any damage caused by this program.  I hope you enjoy it.
  22.  */
  23.  
  24. #include "mactypes.h"
  25.  
  26. #define HQX 0
  27. #define TEXT 1
  28. #define DATA 2
  29. #define RSRC 3
  30. #define HOST 4
  31. #define FORWARDS 0
  32. #define BACKWARDS 1
  33.  
  34. FILE *verbose;
  35. char **hqxnames, **hqxnames_left;
  36. char *dir, *ext, *text_author;
  37. char *maxlines_str;
  38. int maxlines;
  39.  
  40. main(argc, argv)
  41. int argc;
  42. char **argv;
  43. {   char *flags, *getenv();
  44.     int direction, mode, unpit_flag;
  45.  
  46.     argv++;
  47.     argc--;
  48.     verbose = stderr;
  49.     direction = FORWARDS;
  50.     mode = HQX;
  51.     unpit_flag = 0;
  52.  
  53.     if ((text_author = getenv("MAC_EDITOR"))    == NULL)    text_author = "MACA";
  54.     if ((ext =         getenv("MAC_EXT"))       == NULL)    ext = ".bin";
  55.     if ((dir =         getenv("MAC_DLOAD_DIR")) == NULL)    dir = ".";
  56. #ifndef OSK
  57.     if ((maxlines_str = getenv("MAC_LINE_LIMIT")) == NULL)  maxlines = 0;
  58. #else
  59.     if ((maxlines_str = getenv("MAC_LINE_LIMIT")) == NULL)  maxlines = 200;
  60. #endif
  61.     else                                         maxlines = atoi(maxlines_str);
  62.     
  63.     /* Make command line arguments globally accessible */
  64.     hqxnames = (char **) calloc(argc+1, sizeof(char *));
  65.     hqxnames_left = hqxnames;
  66.     while (argc--)  *hqxnames_left++ = *argv++;
  67.     *hqxnames_left = "-";
  68.     hqxnames_left = hqxnames;
  69.  
  70.     while (strcmp(*hqxnames_left, "-")) {
  71.         if (hqxnames_left[0][0] == '-') {
  72.             flags = *hqxnames_left++;
  73.             while (*++flags)
  74.                 switch (*flags) {
  75.                 case 'x':
  76.                     mode = HQX;
  77.                     break;
  78.                 case 'u':
  79.                     mode = TEXT;
  80.                     break;
  81.                 case 'd':
  82.                     mode = DATA;
  83.                     break;
  84.                 case 'r':
  85.                     mode = RSRC;
  86.                     break;
  87.         case 'h':
  88.             mode = HOST;
  89.             break;
  90.                 case 'D':
  91.                     direction = FORWARDS;
  92.                     break;
  93.                 case 'U':
  94.                     direction = BACKWARDS;
  95.                     break;
  96.                 case 'q':
  97.                     unpit_flag = 0;
  98.                     break;
  99.                 case 'p':
  100.                     unpit_flag = 1;
  101.                     break;
  102.                 case 's':
  103. #ifndef OSK
  104.                     verbose = fopen("/dev/null", "w");
  105. #else
  106.                     verbose =fopen("/nil","w");
  107. #endif
  108.  
  109.                     break;
  110.                 case 'v':
  111.                     verbose = stderr;
  112.                     break;
  113.                 default:
  114. #ifndef OSK
  115.                  error( "Usage: mcvert [ -[r|d|u|x|h] [D|U] [p|q] [s|v] ] filename...", NULL);
  116.  
  117. #else
  118.    fprintf(stderr,"Mcvert V1.05 By Doug Moore\n");
  119.    fprintf(stderr,"OSK Port by Dean Leiber \n\n");
  120.    fprintf(stderr,"Usage: Mcvert [-rduxh] [DUpqsv] filename(s)\n");
  121.    fprintf(stderr," Options:\n");
  122.    fprintf(stderr,"          -r = Resource Fork Only \n");
  123.    fprintf(stderr,"          -d = Data Fork Only\n");
  124.    fprintf(stderr,"          -u = Mac <-> Unix Text Conversion\n");
  125.    fprintf(stderr,"          -x = Convert [*Default*]\n");
  126.    fprintf(stderr,"          -h = Host\n");
  127.    fprintf(stderr," Modifiers:\n");
  128. fprintf(stderr,"          -D = Conversion for Download (BinHex -> Macbinary) [*Default*]\n");
  129. fprintf(stderr,"          -U = Conversion for Upload   (Macbinary -> BinHex)\n");
  130.    fprintf(stderr,"          -p = PackIT (.PIT) File explode\n");
  131.    fprintf(stderr,"          -q = No PIT extraction [*Default*]\n");
  132.    fprintf(stderr,"          -s = Silent\n");
  133.    fprintf(stderr,"          -v = Verbose [*Default*]\n");
  134.    fprintf(stderr," Enviromental Vars:\n");
  135. fprintf(stderr," MAC_EDITOR     [Default = MACA]  - For Option \"-uD\"\n");
  136. fprintf(stderr," MAC_DLOAD_DIR  [Default = \".\" ]  - Dir for \"-D\"\n");
  137. fprintf(stderr," MAC_EXT        [Default = .bin]  - Extension for \"-U,-D\"\n");
  138. fprintf(stderr," MAC_LINE_LIMIT [Default = 200 ]  - Length of file for \"-U\"\n");
  139. #endif
  140.  
  141.                     }
  142.             }
  143.  
  144.         if (direction == BACKWARDS)
  145.             if (mode == HQX && unpit_flag) re_hqx();/* no re_pit() yet */
  146.             else if (mode == HQX) re_hqx();
  147.             else re_other(mode);
  148.         else
  149.             if (mode == HQX) un_hqx(unpit_flag);
  150.             else un_other(mode);
  151.         }
  152.     }
  153.  
  154. /* An array useful for CRC calculations that use 0x1021 as the "seed" */
  155. word magic[] = {
  156.     0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
  157.     0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
  158.     0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
  159.     0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
  160.     0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
  161.     0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
  162.     0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
  163.     0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
  164.     0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
  165.     0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
  166.     0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
  167.     0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
  168.     0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
  169.     0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
  170.     0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
  171.     0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
  172.     0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
  173.     0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
  174.     0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
  175.     0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
  176.     0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
  177.     0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
  178.     0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
  179.     0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
  180.     0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
  181.     0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
  182.     0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
  183.     0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
  184.     0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
  185.     0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
  186.     0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
  187.     0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
  188.     };
  189.  
  190.  
  191. /*
  192.  * calc_crc() --
  193.  *   Compute the MacBinary II-style CRC for the data pointed to by p, with the
  194.  *   crc seeded to seed.
  195.  *
  196.  *   Modified by Jim Van Verth to use the magic array for efficiency.
  197.  */
  198. short calc_mb_crc(p, len, seed)
  199. unsigned char *p;
  200. long len;
  201. short seed;
  202. {
  203.   short hold;      /* crc computed so far */
  204.   long  i;         /* index into data */
  205.  
  206.   extern unsigned short magic[];   /* the magic array */
  207.  
  208.   hold = seed;     /* start with seed */
  209.   for (i = 0; i < len; i++, p++) {
  210.     hold ^= (*p << 8);
  211.     hold = (hold << 8) ^ magic[(unsigned char)(hold >> 8)];
  212.   }
  213.  
  214.   return (hold);
  215. } /* calc_crc() */
  216.  
  217.  
  218. /* Report a fatal error */
  219. error(msg, name)
  220. char msg[], name[];
  221. {   fprintf(stderr, msg, name);
  222.     putc('\n', stderr);
  223.     exit(1);
  224.     }
  225.  
  226. /* replace illegal Unix characters in file name */
  227. /* make sure host file name doesn't get truncated beyond recognition */
  228. unixify(np)
  229. register byte *np;
  230. {   register ulong c;
  231.     c = strlen(np);
  232.     if (c > SYSNAMELEN - 4) c = SYSNAMELEN - 4;
  233.     np[c] = '\0';
  234.     np--;
  235.     while (c = *++np)
  236.         if (c <= ' ' || c == '/' || c > '~') *np = '_';
  237.     }
  238.  
  239. /* Convert Unix time (GMT since 1-1-1970) to Mac
  240.                                     time (local since 1-1-1904) */
  241. #define MACTIMEDIFF 0x7c25b080 /* Mac time of 00:00:00 GMT, Jan 1, 1970 */
  242.  
  243. ulong time2mac(time)
  244. ulong time;
  245. {   struct timeb tp;
  246.     ftime(&tp);
  247.     return long2mac(time + MACTIMEDIFF
  248.                     - 60 * (tp.timezone - 60 * tp.dstflag));
  249.     }
  250.  
  251.  
  252. /* This procedure copies the input file to the output file, basically, although
  253.     in TEXT mode it changes LF's to CR's and in any mode it forges a Mac info 
  254.     header.  Author type for TEXT mode can come from the MAC_EDITOR environ-
  255.     ment variable if it is defined. */
  256.  
  257. un_other(mode)
  258. int mode;
  259. {   register ulong b;
  260.     register ulong nchars;
  261.     char txtfname[BINNAMELEN], binfname[BINNAMELEN];
  262.     FILE *txtfile, *binfile; 
  263.     char *suffix;
  264.     struct stat stbuf;
  265.     info_header info;
  266.     int extra_chars;
  267.     ulong dlen, rlen, mtim, ctim;
  268.     short _crc, calc_mb_crc();
  269.  
  270.     if (mode == DATA) suffix = ".data";
  271.     else if (mode == RSRC) suffix = ".rsrc";
  272.     else suffix = ".text";
  273.  
  274.     while (hqxnames_left[0][0] != '-') {
  275.  
  276.         strcpy(txtfname, *hqxnames_left++);
  277.         if (!(txtfile = fopen(txtfname, "r"))) {
  278.             /* Maybe we are supposed to figure out the suffix ourselves? */
  279.             strcat(txtfname, suffix);
  280.             if (!(txtfile = fopen(txtfname, "r")))
  281.                 error("Cannot open %s", txtfname);
  282.             }
  283.  
  284.         if (stat(txtfname, &stbuf))
  285.             error("Cannot read %s", txtfname);
  286.  
  287.         /* stuff header data into the info header */
  288.         bzero(&info, sizeof(info_header));
  289.         info.nlen = strlen(txtfname);
  290.         info.nlen = (info.nlen > NAMELEN) ? NAMELEN : info.nlen;
  291.     info.name[info.nlen] = '\0';
  292.         strcpy(info.name, txtfname);           /* name */
  293.         mtim = time2mac(stbuf.st_mtime);
  294.         ctim = time2mac(stbuf.st_ctime);
  295.         bcopy(&mtim, info.mtim, 4);
  296.         bcopy(&ctim, info.ctim, 4);
  297.     info.uploadvers = '\201';
  298.     info.readvers = '\201';
  299.  
  300.         if (mode == RSRC) {
  301.             /* dlen is already zero */
  302.             rlen = long2mac(stbuf.st_size);
  303.             bcopy(&rlen, info.rlen, 4);
  304.             bcopy("APPL", info.type, 4);
  305.             bcopy("CCOM", info.auth, 4);
  306.             }
  307.         else {
  308.             dlen = long2mac(stbuf.st_size);
  309.             bcopy(&dlen, info.dlen, 4);
  310.             /* rlen is already zero */
  311.             bcopy("TEXT", info.type, 4);
  312.             if (mode == DATA) bcopy("????", info.auth, 4);
  313.             else bcopy(text_author, info.auth, 4);
  314.             }
  315.  
  316.     /* calculate CRC */
  317.     _crc = calc_mb_crc(&info, 124, 0);
  318.     info.crc[0] = (char) (_crc >> 8);
  319.     info.crc[1] = (char) _crc;
  320.  
  321.         /* Create the .bin file and write the info to it */
  322.         sprintf(binfname, "%s/%s%s", dir, txtfname, ext);
  323.         if ((binfile = fopen(binfname, "w")) == NULL)
  324.             error("Cannot open %s", binfname);
  325.         fprintf(verbose,
  326.                 "Converting     %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
  327.                 txtfname, info.type, info.auth);
  328.         fwrite(&info, sizeof(info), 1, binfile);
  329.  
  330.         nchars = stbuf.st_size;
  331.         extra_chars = 127 - (nchars+127) % 128;
  332.         if (mode == TEXT) while (nchars--) {
  333.             b = getc(txtfile);
  334.             if (b == LF) b = CR;
  335.             putc(b, binfile);
  336.             }
  337.         else while (nchars--) putc(getc(txtfile), binfile);
  338.  
  339.         while (extra_chars--) putc(0, binfile);
  340.         fclose(binfile);
  341.         fclose(txtfile);
  342.         }
  343.     }
  344.  
  345. /* This procedure copies the input file to the output file, basically, although
  346.     in TEXT mode it changes CR's to LF's and in any mode it skips over the Mac
  347.     info header. */
  348.  
  349. re_other(mode)
  350. int mode;
  351. {   register ulong b;
  352.     register ulong nchars;
  353.     char txtfname[BINNAMELEN], binfname[BINNAMELEN];
  354.     FILE *txtfile, *binfile; 
  355.     char *suffix;
  356.     info_header info;
  357.  
  358.     if (mode == DATA) suffix = ".data";
  359.     else if (mode == RSRC) suffix = ".rsrc";
  360.     else suffix = ".text";
  361.  
  362.     while (hqxnames_left[0][0] != '-') {
  363.  
  364.         strcpy(binfname, *hqxnames_left++);
  365.         if ((binfile = fopen(binfname, "r")) == NULL) {
  366.             /* Maybe we are supposed to figure out the suffix ourselves? */
  367.             strcat(binfname, ext);
  368.             if (!(binfile = fopen(binfname, "r")))
  369.                 error("Cannot open %s", binfname);
  370.             }
  371.  
  372.         /* Read the info from the .bin file, create the output file */
  373.         fread(&info, sizeof(info), 1, binfile);
  374.         strncpy(txtfname, info.name, info.nlen);
  375.     txtfname[info.nlen] = '\0';
  376.         fprintf(verbose,
  377.                 "Converting     %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
  378.                 txtfname, info.type, info.auth);
  379.         if ((txtfile = fopen(txtfname, "r")) == NULL) {
  380.             if ((txtfile = fopen(txtfname, "w")) == NULL)
  381.                 error("Cannot open %s", txtfname);
  382.             }
  383.         else {
  384.             fclose(txtfile);
  385.             strcat(txtfname, suffix);
  386.             if ((txtfile = fopen(txtfname, "w")) == NULL)
  387.                 error("Cannot open %s", txtfname);
  388.             }
  389.  
  390.         nchars = mac2long(* (ulong *) info.dlen);
  391.         if (mode == TEXT) while (nchars--) {
  392.             b = getc(binfile);
  393.             if (b == CR) b = LF;
  394.             putc(b, txtfile);
  395.             }
  396.         else if (mode == DATA) while (nchars--)
  397.             putc(getc(binfile), txtfile);
  398.         else {
  399.             while (nchars--) getc(binfile);
  400.             nchars = mac2long(* (ulong *) info.rlen);
  401.             while (nchars--) putc(getc(binfile), txtfile);
  402.             }
  403.  
  404.         fclose(binfile);
  405.         fclose(txtfile);
  406.         }
  407.     }
  408.