home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / hamradio / 7plus202.zip / 7PL2SRC.LZH / UTILS.C < prev   
C/C++ Source or Header  |  1992-06-11  |  21KB  |  1,122 lines

  1. #include "7plus.h"
  2. #include "globals.h"
  3. #ifdef __unix__
  4.  #include <time.h>
  5.  #ifdef __M_XENIX__
  6.   struct utimbuf {
  7.    time_t actime;
  8.    time_t modtime;
  9.   };
  10.   extern time_t mktime (struct tm *utm);
  11.  #else
  12.   #include <utime.h>
  13.  #endif
  14.  #include <sys/stat.h>
  15. #endif
  16.  
  17. static char no[] = NO, yes[] = YES, always[] = ALWAYS;
  18.  
  19. /*
  20. *** get a line from file. don't care about type of line separator.
  21. ***
  22. ***
  23.  */
  24.  
  25. char *my_fgets (char *string, register n, FILE *rein)
  26. {
  27.   register in, i;
  28.  
  29.   if (feof (rein))
  30.     return (NULL);
  31.  
  32.   i = 0;
  33.   while ((in = fgetc (rein)) != EOF)
  34.   {
  35.     if (in == 0x0d)
  36.     {
  37.       if ((in = fgetc (rein)) != 0x0a)
  38.         if (in != EOF)
  39.           ungetc (in, rein);
  40.       in = 0x0a;
  41.     }
  42.     string[i++] = (char) in;
  43.     if (i == n || in == 0x0a)
  44.       break;
  45.   }
  46.   string[i] = EOS;
  47.   return (string);
  48.  
  49. /*
  50. ***
  51. *** Write a byte to file.
  52. ***
  53.  */
  54.  
  55. int my_putc (int outchar, FILE *out)
  56. {
  57.   register x;
  58.  
  59.   if ((x = putc ((char) outchar, out)) == EOF)
  60.   {
  61.     printf ("\007\nWrite error! Can't continue.\n");
  62.     exit (1);
  63.   }
  64.   return (x);
  65. }
  66.  
  67. /*
  68. *** Get crc and line number from code line.
  69. ***
  70. ***
  71.  */
  72.  
  73. void crc_n_lnum (uint *crc, int *linenumber, char *line)
  74. {
  75.   register ulong cs;
  76.  
  77.   cs = 0xb640L * decode[(byte)line[66]] +
  78.        0xd8L   * decode[(byte)line[65]] +
  79.                  decode[(byte)line[64]];
  80.  
  81.   *linenumber = (int) (cs >> 14);   /* upper 9 bits are the line number */
  82.   *crc = (uint) (cs & 0x3fffL);     /* lower 14 bits are the CRC */
  83. }
  84.  
  85. /*
  86. *** Get crc2 from code line.
  87. ***
  88. ***
  89.  */
  90.  
  91. void crc2 (uint *crc, char *line)
  92. {
  93.  
  94.   *crc = 0xd8 * decode[(byte)line[68]] +
  95.                 decode[(byte)line[67]];
  96. }
  97.  
  98. /*
  99. *** Whip up 2nd CRC
  100. ***
  101. ***
  102.  */
  103.  
  104. void add_crc2 (char *line)
  105. {
  106.   register uint crc;
  107.   register int i;
  108.  
  109.   /* Whip up 2nd CRC */
  110.   crc = 0;
  111.   for (i=66;i>-1;i--)
  112.     crc = crctab[crc>>8] ^ (((crc&255)<<8) | (byte) line[i]);
  113.   crc &= 0x7fff;
  114.  
  115.   i = 67;
  116.   line[i++] = code[crc % 0xd8];
  117.   line[i++] = code[crc / 0xd8];
  118.   line[i] = EOS;
  119. }
  120.  
  121. /*
  122. *** mini-crc for header. safe enough...
  123. ***
  124. ***
  125.  */
  126.  
  127. int mcrc (char *line, int flag)
  128. {
  129.   register int i, j;
  130.   register uint crc;
  131.   char test[3], *p;
  132.  
  133.   sprintf (test, "\xb0\xb1");
  134.  
  135.   if ((p = strstr (line, test)) == NULL)
  136.     return (0);
  137.  
  138.   j = (int) (p - line) + 4;
  139.  
  140.   for (i=crc=0; i<j; i++)
  141.     crc = crctab[crc>>8] ^ (((crc&255)<<8) | (byte)line[i]);
  142.   crc %= 216;
  143.   if (!flag)
  144.   {
  145.     if (crc == (uint) decode[(byte)line[j]])
  146.       return (1);
  147.     else
  148.       return (0);
  149.   }
  150.   else
  151.     line[j] = code[(byte)crc];
  152.  
  153.   return (crc);
  154. }
  155.  
  156. /*
  157. *** read info from indexfile
  158. ***
  159. ***
  160.  */
  161.  
  162. int read_index (FILE *ifile, struct m_index *index)
  163. {
  164.   int j;
  165.   ulong i, begin, end;
  166.  
  167.   #ifdef _CHSIZE_OK
  168.    fseek (ifile, -4L, SEEK_END);
  169.    fseek (ifile, read_ulong (ifile), SEEK_SET);
  170.   #endif
  171.  
  172.   /* clear index */
  173.   for (j = 0;j < 8160; j++)
  174.     index->lines_ok[j] = 0;
  175.  
  176.   my_fgets (index->full_name, 12, ifile);
  177.   if (strcmp(index->full_name, "7PLUS-index\x0a"))
  178.   {
  179.     printf ("\007No index info found.\n");
  180.     return (1);
  181.   }
  182.   my_fgets (index->filename, 13, ifile);
  183.   index->filename[(int)strlen(index->filename)-1] = EOS;
  184.   my_fgets (index->full_name, 257, ifile);
  185.   index->full_name[(int)strlen(index->full_name)-1] = EOS;
  186.   index->timestamp = read_ulong (ifile);
  187.   index->splitsize = read_uint  (ifile);
  188.   index->lines_left= (long) read_ulong (ifile);
  189.  
  190.   /* convert defect list into bitvektor */
  191.   while (1==1)
  192.   {
  193.     if ((begin = read_ulong (ifile)) == 0xffffffffUL)
  194.       break;
  195.     end = read_ulong (ifile);
  196.  
  197.     if ((end>>4) > (begin>>4))
  198.       for (i = begin;i < ((begin |15UL) + 1UL); i++)
  199.         index->lines_ok[(int)i>>4] |= (1U << (uint)(i&15UL));
  200.     else
  201.     {
  202.       for (i = begin;i < end; i++)
  203.         index->lines_ok[(int)i>>4] |= (1U << (uint)(i&15UL));
  204.       continue;
  205.     }
  206.  
  207.     for (i = (begin>>4) +1; i < (end>>4); i++)
  208.       index->lines_ok[(int)i] = 0xffffU;
  209.  
  210.     if (end&15)
  211.       for (i = end &0xfffffff0UL; i < end; i++)
  212.         index->lines_ok[(int)i>>4] |= (1U << (uint)(i&15UL));
  213.   }
  214.   index->length = read_ulong (ifile);
  215.  
  216.   #ifdef _CHSIZE_OK
  217.    fseek (ifile, 0UL, SEEK_SET);
  218.   #endif
  219.  
  220.   return (0);
  221. }
  222.  
  223. /*
  224. *** write info to indexfile
  225. ***
  226. ***
  227.  */
  228.  
  229. int write_index (FILE *ifile, struct m_index *index, int flag)
  230. {
  231.   int j, part, prevpart, lines;
  232.   ulong i, begin, end;
  233.  
  234.   part = prevpart = lines = 0;
  235.   begin = end = 0UL;
  236.  
  237.   if (!flag)
  238.   {
  239.     #ifdef _CHSIZE_OK
  240.      fseek (ifile, index->length, SEEK_SET);
  241.     #endif
  242.  
  243.     fprintf (ifile, "7PLUS-index\n");
  244.     fprintf (ifile, "%s\n", index->filename);
  245.     fprintf (ifile, "%s\n", index->full_name);
  246.     write_ulong (ifile, index->timestamp);
  247.     write_uint  (ifile, index->splitsize);
  248.     write_ulong (ifile, (ulong) index->lines_left);
  249.   }
  250.   /* convert bitvektor into defect list */
  251.   i = 0UL;
  252.   j = 0;
  253.   while (1==1)
  254.   {
  255.     while (j < 8160 && !(index->lines_ok[j] &(uint)(1 << (i & 15UL))))
  256.     {
  257.       if (!(i&15UL) && index->lines_ok[j] == 0U)
  258.       {
  259.         j++;
  260.         i = (ulong) j<<4;
  261.       }
  262.       else
  263.       {
  264.         i++;
  265.         j = (int) i>>4;
  266.       }
  267.     }
  268.  
  269.     if (j == 8160)
  270.       break;
  271.  
  272.     begin = i;
  273.  
  274.     do
  275.     {
  276.       if (!(i&15UL) && index->lines_ok[j] == 0xffffU)
  277.       {
  278.         j++;
  279.         i = (ulong) j<<4;
  280.       }
  281.       else
  282.       {
  283.         i++;
  284.         j = (int) i>>4;
  285.       }
  286.     }
  287.     while (j < 8160 && (index->lines_ok[j] &(uint)(1 << (i & 15UL))));
  288.  
  289.     end = i;
  290.  
  291.     if (!flag)
  292.     {
  293.       write_ulong (ifile, begin);
  294.       write_ulong (ifile, end);
  295.     }
  296.     else
  297.     {
  298.       for (i = begin; i < end; i++)
  299.       {
  300.         part = (int) i / index->splitsize +1;
  301.         if (part != prevpart)
  302.         {
  303.           if (prevpart)
  304.           {
  305.             if (!(lines % 18) && lines)
  306.               fprintf (ifile, delimit);
  307.             lines = 0;
  308.             fprintf (ifile, "FFF%s", delimit);
  309.           }
  310.           prevpart = part;
  311.           fprintf (ifile, "%02X%s", part, delimit);
  312.         }
  313.  
  314.         lines++; /* Number of missing or corrupted lines in this part. */
  315.         fprintf (ifile, "%03X", i % index->splitsize);
  316.         if (!(lines % 18) && lines)
  317.         {
  318.           fprintf (ifile, delimit);
  319.           lines = 0;
  320.         }
  321.         else
  322.           fprintf (ifile, " ");
  323.       }
  324.     }
  325.   }
  326.  
  327.   if (!flag)
  328.   {
  329.     write_ulong (ifile, 0xffffffffUL);
  330.     write_ulong (ifile, index->length);
  331.     #ifdef _CHSIZE_OK
  332.      chsize (fileno (ifile), ftell (ifile));
  333.     #endif
  334.   }
  335.   else
  336.   {
  337.     if (!(lines % 18) && lines)
  338.       fprintf (ifile, delimit);
  339.     fprintf (ifile, "FFF%s", delimit);
  340.   }
  341.   return (0);
  342. }
  343.  
  344. /*
  345. *** Reading/writing unsigned long(32bit)/int(16)
  346. ***
  347. ***
  348.  */
  349.  
  350. ulong read_ulong (FILE *in)
  351. {
  352.   return ((ulong)fgetc (in)       +
  353.          ((ulong)fgetc (in) <<8 ) +
  354.          ((ulong)fgetc (in) <<16) +
  355.          ((ulong)fgetc (in) <<24));
  356. }
  357.  
  358. uint read_uint (FILE *in)
  359. {
  360.   return ((uint)fgetc (in)       +
  361.          ((uint)fgetc (in) <<8 ));
  362. }
  363.  
  364. void write_ulong (FILE *out, ulong val)
  365. {
  366.   my_putc ((int) (val     &0xffUL), out);
  367.   my_putc ((int)((val>>8 )&0xffUL), out);
  368.   my_putc ((int)((val>>16)&0xffUL), out);
  369.   my_putc ((int)((val>>24)&0xffUL), out);
  370. }
  371.  
  372. void write_uint (FILE *out, uint val)
  373. {
  374.   my_putc ((int) (val    &0xffU), out);
  375.   my_putc ((int)((val>>8)&0xffU), out);
  376. }
  377.  
  378. /*
  379. *** read a file, search for s1, calculate CRC until s2 is found.
  380. *** flag == 1: compare calculated an read CRC.
  381. *** flag == 0: insert CRC into file.
  382.  */
  383.  
  384. int crc_file (char *file, char *s1, char *s2, int flag)
  385. {
  386.   char line[81], *p;
  387.   uint crc, cs;
  388.   int i, j, k;
  389.   FILE *in;
  390.  
  391.   crc = cs = 0;
  392.   p = NULLCP;
  393.  
  394.   if (!(in = fopen (file, OPEN_RANDOM_BINARY)))
  395.   {
  396.     printf (cant, file);
  397.     return (2);
  398.   }
  399.  
  400.   i = (int) strlen (s1);
  401.   k = (int) strlen (s2);
  402.  
  403.   j = 1;
  404.  
  405.   do
  406.   {
  407.     if (my_fgets (line, 80, in) == NULL)
  408.       break;
  409.  
  410.     j = strncmp (line, s1, i);
  411.   }
  412.   while (j);
  413.  
  414.   if (j)
  415.     p = s1;
  416.   else
  417.   {
  418.     p = s2;
  419.     do
  420.     {
  421.       for (i=0;i!=(int)strlen(line);i++)
  422.         crc = crctab[crc>>8] ^ (((crc&255)<<8) | (byte)line[i]);
  423.  
  424.       j = strncmp (line, s2, k);
  425.  
  426.       if (!j)
  427.         continue;
  428.  
  429.       if (my_fgets (line, 80, in) == NULL)
  430.         break;
  431.     }
  432.     while (j);
  433.   }
  434.  
  435.   if (j)
  436.   {
  437.     printf ("\n\007Can't calculate CRC\n");
  438.     printf ("String '%s' not found in '%s'.\nBreak.\n", p, file);
  439.     return (7);
  440.   }
  441.  
  442.   /* evaluate CRC */
  443.   if (flag)
  444.   {
  445.     my_fgets (line, 80, in);
  446.     fclose (in);
  447.     if (!line || strncmp ("CRC ", line, 4))
  448.     {
  449.       printf ("\n'%s': no CRC found.\n(File may be corrupted or from version \
  450. earlier than 7PLUS v1.5)\n", file);
  451.       return (17);
  452.     }
  453.     cs = get_hex (line+4);
  454.     if (cs == crc)
  455.       return (0);
  456.  
  457.     printf ("\007\n'%s' is corrupted. Break.\n", file);
  458.     return (7);
  459.   }
  460.  
  461.   /* insert CRC into file */
  462.   fseek (in, ftell (in), SEEK_SET);
  463.   fprintf (in, "CRC %04X", crc);
  464.   fclose (in);
  465.  
  466.   return (0);
  467. }
  468.  
  469. /*
  470. *** Copy a file.
  471. ***
  472. ***
  473.  */
  474.  
  475. int copy_file (char *to, char *from, ulong timestamp)
  476. {
  477.   FILE *_from, *_to;
  478.   int _char, stat;
  479.  
  480.   stat = 0;
  481.  
  482.   _from = fopen (from, OPEN_READ_BINARY);
  483.   _to   = fopen (to,   OPEN_WRITE_BINARY);
  484.  
  485.   while ((_char = getc (_from)) != EOF)
  486.     if ((stat = putc (_char, _to)) == EOF)
  487.       break;
  488.  
  489.   fclose (_from);
  490.  
  491.  #ifdef _UXTIMESTAMP
  492.   fclose (_to);
  493.   if (timestamp)
  494.     set_uxfiletime (to, timestamp);
  495.  #else
  496.   if (timestamp)
  497.     set_filetime (_to, timestamp);
  498.  
  499.   fclose (_to);
  500.  #endif
  501.  
  502.   if (stat == EOF)
  503.   {
  504.     printf ("\007\nFatal error. Can't write '%s'! Break.\n", to);
  505.     exit (1);
  506.   }
  507.   return (0);
  508. }
  509.  
  510. /*
  511. *** Replace one file with another
  512. ***
  513. ***
  514.  */
  515.  
  516. void replace (char *old, char *new, ulong timestamp)
  517. {
  518.   unlink (old);
  519.  
  520.   if (rename (new, old))
  521.   {
  522.     copy_file (old, new, timestamp);
  523.     unlink (new);
  524.   }
  525.   else
  526.   {
  527.     if (timestamp)
  528.     {
  529.      #ifdef _UXTIMESTAMP
  530.       set_uxfiletime (old, timestamp);
  531.      #else
  532.       FILE *_file;
  533.  
  534.       _file = fopen (old, OPEN_APPEND_BINARY);
  535.       set_filetime (_file, timestamp);
  536.       fclose (_file);
  537.      #endif
  538.     }
  539.   }
  540. }
  541.  
  542. /*
  543. *** Kill all files that aren't needed any more
  544. ***
  545. ***
  546.  */
  547.  
  548. void kill_em (char *name, char *inpath, char *one, char *two,
  549.               char *three, char *four, char *five)
  550. {
  551.   char *p, newname[MAXPATH];
  552.   int i, j, k, len;
  553.  
  554.   k = 0;
  555.  
  556.   for (i = 0; i < 5; i++)
  557.   {
  558.     if (!i)
  559.       printf ("\n");
  560.  
  561.     switch (i)
  562.     {
  563.       case 0:  p = one;
  564.                break;
  565.       case 1:  p = two;
  566.                break;
  567.       case 2:  p = three;
  568.                break;
  569.       case 3:  p = four;
  570.                break;
  571.       case 4:  p = five;
  572.  
  573.       default: p = NULLCP;
  574.     }
  575.     if (!p)
  576.      break;
  577.  
  578.     len = strlen(p);
  579.  
  580.     for (j = 1; j <256; j++)
  581.     {
  582.       if (len == 3)
  583.         sprintf (newname, "%s%s.%s", inpath, name, p);
  584.       else
  585.         sprintf (newname, "%s%s.%s%02x", inpath, name, p, j);
  586.  
  587.       if (unlink (newname))
  588.         break;
  589.  
  590.       k++;
  591.  
  592.       printf ("Deleting: %s\r", newname);
  593.       fflush (stdout);
  594.  
  595.       if (len == 3)
  596.         break;
  597.     }
  598.   }
  599.   if (k)
  600.     printf ("\n");
  601. }
  602.  
  603. /*
  604. ***
  605. ***
  606. ***
  607.  */
  608.  
  609. void kill_dest (FILE *in, FILE *out, char *name)
  610. {
  611.     if (out)
  612.       fclose (out);
  613.     if (in)
  614.       fclose (in);
  615.     if (*name)
  616.       unlink (name);
  617. }
  618.  
  619. /*
  620. ***
  621. ***  test if a file exists at all
  622. ***
  623.  */
  624.  
  625. int test_exist (char *filename)
  626. {
  627.   FILE *in = NULLFP;
  628.  
  629.   if ((in = fopen (filename, OPEN_READ_TEXT)) != NULLFP)
  630.   {
  631.     fclose (in);
  632.     return (0);
  633.   }
  634.   return (1);
  635. }
  636.  
  637.  
  638. /*
  639. ***  test if outputfile already exists. prompt for overwrite or
  640. ***  new name.
  641. ***
  642.  */
  643.  
  644. int test_file (FILE *in, char *destnam, int flag, int namsize)
  645. {
  646.    FILE *out;
  647.    int  i, ret;
  648.  
  649.    ret = 0;
  650.  
  651.    if (noquery)
  652.      return (ret);
  653.  
  654.    /* Loop as long as file can be opened. */
  655.    while ((out = fopen (destnam, OPEN_READ_BINARY)) != NULLFP)
  656.    {
  657.      ret = 1;
  658.      printf ("\007\nOutputfile '%s' already exists, overwrite? [y/n/a] ", destnam);
  659.      do
  660.      {
  661.        i = toupper (getch());
  662.  
  663.        if (i == 'N')
  664.        {
  665.          if (flag)
  666.          {
  667.            printf ("%s\n\nEnter new name (max %d chars)\n", no, namsize);
  668.            printf ("or simply press ENTER to break : ");
  669.            if (namsize == 12)
  670.              strlwr (destnam);
  671.            scanf ("%s", destnam);
  672.            destnam[namsize] = EOS;
  673.          }
  674.          else
  675.            *destnam = EOS;
  676.          if (!strlen (destnam))
  677.          {
  678.            if (!flag)
  679.              printf ("%s\n", no);
  680.            printf ("Break.\n");
  681.            if (in)
  682.              fclose (in);
  683.            exit (10);
  684.          }
  685.          i = 0xff; /* indicate, that new name has been specified */
  686.        }
  687.      }
  688.      while (i != 'Y' && i != 'A' && i != 0xff);
  689.  
  690.      if (i != 0xff)
  691.      {
  692.        if (i == 'A')
  693.        {
  694.          printf ("%s\n", always);
  695.          noquery = 1;
  696.        }
  697.        else
  698.          printf ("%s\n", yes);
  699.      }
  700.      printf ("\n");
  701.  
  702.      fclose (out);
  703.  
  704.      if (i != 0xff)
  705.        break;
  706.    }
  707.  
  708.    return (ret);
  709. }
  710.  
  711.  
  712. /*
  713. *** initialize decoding table
  714. ***
  715. ***
  716.  */
  717.  
  718. void init_decodetab (void)
  719. {
  720.   register i;
  721.   register byte j;
  722.  
  723.   for (i = 0; i < 256; i++)
  724.     decode[i] = 255;
  725.  
  726.   j = 0;
  727.   for (i = 0x21; i < 0x2a; i++)
  728.     decode[i] = j++;
  729.  
  730.   for (i = 0x2b; i < 0x7f; i++)
  731.     decode[i] = j++;
  732.  
  733.   for (i = 0x80; i < 0x91; i++)
  734.     decode[i] = j++;
  735.  
  736.   decode[0x92] = j++;
  737.  
  738.   for (i = 0x94; i < 0xfd; i++)
  739.     decode[i] = j++;
  740. }
  741.  
  742. /*
  743. *** initialize encoding table
  744. ***
  745. ***
  746.  */
  747.  
  748. void init_codetab (void)
  749. {
  750.   register byte i, j;
  751.  
  752.   j = 0;
  753.  
  754.   for (i = 0x21; i < 0x2a; i++, j++)
  755.     code[j] = i;
  756.  
  757.   for (i = 0x2b; i < 0x7f; i++, j++)
  758.     code[j] = i;
  759.  
  760.   for (i = 0x80; i < 0x91; i++, j++)
  761.     code[j] = i;
  762.  
  763.   code[j++] = 146;
  764.  
  765.   for (i = 0x94; i < 0xfd; i++, j++)
  766.     code[j] = i;
  767. }
  768.  
  769. /*
  770. *** Tnx to DC4OX.
  771. ***
  772. *** calculate CRC-table
  773. ***
  774.  */
  775.  
  776. void init_crctab (void)
  777. {
  778.   uint m, n, r, mask;
  779.  
  780.   static uint bitrmdrs[] = { 0x9188,0x48C4,0x2462,0x1231,
  781.                              0x8108,0x4084,0x2042,0x1021 };
  782.  
  783.   for (n = 0; n < 256; ++n)
  784.   {
  785.     for (mask = 0x0080, r = 0, m = 0; m < 8; ++m, mask >>= 1)
  786.       if (n & mask)
  787.         r = bitrmdrs[m] ^ r;
  788.     crctab[n] = r;
  789.   }
  790. }
  791.  
  792. /*
  793. *** Create a MSDOS/ATARI compatible filename.
  794. ***
  795. ***
  796.  */
  797.  
  798. void build_DOS_name (char *name)
  799. {
  800.   char tmp[MAXFNAME];
  801.   register i, j;
  802.  
  803.   i = j = 0;
  804.  
  805.   strcpy (tmp, name);
  806.   strlwr (tmp);
  807.  
  808.   if (*tmp)
  809.   {
  810.     do
  811.     {
  812.       tmp[i] &= 127;
  813.       if (strchr (" <>=,;:*?&[]()/.\\\"~+@", tmp[i]) == NULL)
  814.         name[j++] = tmp[i];
  815.     }
  816.     while (tmp[++i]);
  817.  
  818.     name[j] = EOS;
  819.   }
  820. }
  821.  
  822. #ifdef _UXTIMESTAMP
  823.  /*
  824.   * these functions have to convert a MS/DOS time to a UNIX time
  825.   * and vice versa.
  826.   * here comes the MS/DOS time structure
  827.   */
  828.  struct ftime
  829.  {
  830.    unsigned  ft_tsec  : 5;   /* 0..59 /2 (!) */
  831.    unsigned  ft_min   : 6;   /* 0..59 */
  832.    unsigned  ft_hour  : 5;   /* 0..23 */
  833.    unsigned  ft_day   : 5;   /* 1..31 */
  834.    unsigned  ft_month : 4;   /* 1..12 */
  835.    unsigned  ft_year  : 7; /* Year minus 1980 */
  836.  };
  837.  
  838.  /*
  839.   * Get UNIX file's timestamp and package it into a 32-bit word (MS_DOS-format)
  840.   */
  841.  ulong get_uxfiletime (char *filename)
  842.  {
  843.    time_t atime;
  844.    struct ftime fti;
  845.    ulong *retval = (ulong *) &fti;
  846.    struct tm *utm;
  847.    struct stat fst;
  848.  
  849.    *retval = 0UL;
  850.  
  851.    /* get UNIX file status */
  852.    if (stat (filename, &fst) == 0)
  853.    {
  854.       /* get time of last modification and convert it to MS/DOS time */
  855.      utm = gmtime (&fst.st_mtime);
  856.  
  857.      if (utm)
  858.      {
  859.        fti.ft_tsec  = utm->tm_sec / 2;
  860.        fti.ft_min   = utm->tm_min;
  861.        fti.ft_hour  = utm->tm_hour;
  862.        fti.ft_day   = utm->tm_mday;
  863.        fti.ft_month = utm->tm_mon + 1;
  864.        fti.ft_year  = utm->tm_year - 80;
  865.        return (*retval);
  866.      }
  867.    }
  868.  
  869.    /* error exit */
  870.    printf ("\007\nCan't get file's timestamp!\n");
  871.    return (*retval);
  872.  }
  873.  
  874.  /*
  875.   * Set UNIX file's timestamp
  876.   */
  877.  void set_uxfiletime (char *filename, ulong ftimestamp)
  878.  {
  879.    time_t atime;
  880.    struct utimbuf utim;
  881.    struct ftime *fti;
  882.    struct tm utm;
  883.  
  884.    /* convert MS/DOS ftimestamp to UNIX atime */
  885.    fti = (struct ftime *) &ftimestamp;
  886.    utm.tm_sec   = fti->ft_tsec * 2;
  887.    utm.tm_min   = fti->ft_min;
  888.    utm.tm_hour  = fti->ft_hour;
  889.    utm.tm_mday  = fti->ft_day;
  890.    utm.tm_mon   = fti->ft_month - 1;
  891.    utm.tm_year  = fti->ft_year + 80;
  892.    utm.tm_wday  = utm.tm_yday  =  utm.tm_isdst = 0;
  893.    atime = mktime (&utm);
  894.  
  895.    if (atime != -1)
  896.    {
  897.      /* set access time and modification time */
  898.      utim.actime = atime;
  899.      utim.modtime = atime;
  900.      if (utime (filename, &utim) >= 0)
  901.        return;
  902.    }
  903.  
  904.    /* error exit */
  905.    printf ("\007\nCan't set file's timestamp!");
  906.    return;
  907.  }
  908. #else /* not UNIX */
  909.  /*
  910.  *** Get file's timestamp and package it into a 32-bit word (MS_DOS-format)
  911.  ***
  912.  ***
  913.   */
  914.  ulong get_filetime (FILE *_file)
  915.  {
  916.  #ifdef _TIMESTAMP
  917.    ulong    ftimestamp;
  918.  
  919.    if (getftime (fileno(_file), (struct ftime *)&ftimestamp) == EOF)
  920.      printf ("\007\nCan't get file's timestamp!\n");
  921.  
  922.   #ifdef __TOS__
  923.    ftimestamp = swapl(ftimestamp);
  924.   #endif
  925.  
  926.    return (ftimestamp);
  927.  #else
  928.    /* This is the case with the AMIGA at this time */
  929.    printf ("\007\nWARNING: Function get_filetime() not yet implemented on this system!!\n");
  930.    return (0UL);
  931.  #endif _TIMESTAMP
  932.  }
  933.  
  934.  /*
  935.  *** Set file's timestamp
  936.  ***
  937.  ***
  938.   */
  939.  void set_filetime (FILE *_file, ulong ftimestamp)
  940.  {
  941.  #ifdef _TIMESTAMP
  942.  
  943.   #ifdef __TOS__
  944.    ftimestamp = swapl(timestamp);
  945.   #endif
  946.  
  947.    if (setftime (fileno(_file), (struct ftime *)&ftimestamp) == EOF)
  948.      printf ("\007\nCan't set file's timestamp!");
  949.  
  950.  #else
  951.    /* This is the case with the AMIGA at this time */
  952.    printf ("\007\nWARNING: Function set_filetime() not yet implemented on this system!!\n");
  953.  #endif _TIMESTAMP
  954.  }
  955. #endif
  956.  
  957. /*
  958. *** get_hex: some compilers have real big trouble when reading hex values from
  959. ***          a file with fscanf() that have leading zeros! e.g. 00A will be
  960. ***          read as two separate values (0 and A)! grr!!
  961. ***          get_hex skips all leading zeros to eliminate the problem.
  962. ***
  963.  */
  964.  
  965. uint get_hex (char *hex)
  966. {
  967.   register i = 0;
  968.   uint   ret = 0;
  969.  
  970.   while (hex[i] == '0')
  971.     i++;
  972.   sscanf(hex+i, "%x", &ret);
  973.   return (ret);
  974. }
  975.  
  976.  
  977. #ifdef _FNSPLIT
  978. /*
  979. ***       filenamesplit
  980. ***       (by DL1MEN, taken from SP-ST, modified for portability)
  981. ***
  982. ***       split filename up into drive, path, name and extension.
  983. ***
  984.  */
  985.  
  986. void fnsplit(char *pth, char *dr, char *pa, char *fn, char *ft)
  987. {
  988.   char drv[MAXDRIVE], pat[MAXDIR], fna[MAXFILE], fty[MAXEXT], tmp[MAXPATH];
  989.   char *p;
  990.  
  991.   strcpy(tmp,pth);
  992.  
  993.   if ((p = strchr(tmp,':')) != NULL)
  994.   {
  995.     *p++ = EOS;
  996.     strcpy(drv,tmp);
  997.   }
  998.   else
  999.   {
  1000.     p = tmp;
  1001.     drv[0] = EOS;
  1002.   }
  1003.   if ((pth = strrchr(p, PATHCHAR)) != NULL)
  1004.   {
  1005.     *pth++ = EOS;
  1006.     strcpy(pat,p);
  1007.   }
  1008.   else
  1009.   {
  1010.     pth = p;
  1011.     pat[0] = EOS;
  1012.   }
  1013.   if ((p = strchr(pth,'.')) != NULL)
  1014.   {
  1015.     strcpy(fty,p);
  1016.     fty[MAXEXT-1] = EOS;
  1017.     *p = EOS;
  1018.   }
  1019.   else
  1020.     fty[0] = EOS;
  1021.  
  1022.   strcpy(fna,pth);
  1023.   fna[MAXFILE-1] = EOS;
  1024.  
  1025.   if (dr)
  1026.   {
  1027.     strcpy(dr,drv);
  1028.     if (drv[0])
  1029.       strcat(dr,":");
  1030.   }
  1031.   if (pa)
  1032.   {
  1033.     strcpy(pa,pat);
  1034.     if (pat[0])
  1035.       strcat(pa, PATHSEP);
  1036.   }
  1037.   if (fn)
  1038.     strcpy(fn,fna);
  1039.   if (ft)
  1040.    strcpy(ft,fty);
  1041. }
  1042. #endif /** _FNSPLIT **/
  1043.  
  1044. #ifdef _ICMP
  1045. /* The following functions are unfortunately not avialable on all compilers */
  1046.  
  1047. /*
  1048. *** strupr - convert string to upper case.
  1049. ***
  1050. ***
  1051.  */
  1052.  
  1053. char *strupr (char *string)
  1054. {
  1055.   char *strcnvt (char *string, int flag);
  1056.  
  1057.   return (strcnvt (string, 1));
  1058. }
  1059.  
  1060. /*
  1061. *** strlwr - convert string to lower case.
  1062. ***
  1063. ***
  1064.  */
  1065.  
  1066. char *strlwr (char *string)
  1067. {
  1068.   char *strcnvt (char *string, int flag);
  1069.  
  1070.   return (strcnvt (string, 0));
  1071. }
  1072.  
  1073. /*
  1074. *** strcnvt - convert string to upper (flag == 1) or lower (flag == 0) case.
  1075. ***
  1076. ***
  1077.  */
  1078.  
  1079. char *strcnvt (char *string, int flag)
  1080. {
  1081.   register i = 0;
  1082.  
  1083.   while (string[i])
  1084.   {  
  1085.     string[i] = (flag)?toupper (string[i]):tolower (string[i]);
  1086.     i++;
  1087.   }
  1088.  
  1089.   return (string);
  1090. }
  1091.  
  1092. /*
  1093. *** stricmp - same as strcmp(), but ignores case.
  1094. *** s1 and s2 are not modified.
  1095. ***
  1096.  */
  1097.  
  1098. int stricmp (const char *s1, const char *s2)
  1099. {
  1100.   return (strnicmp (s1, s2, (size_t) 80));
  1101. }
  1102.  
  1103. /*
  1104. *** strnicmp - same as strncmp(), but ignores case.
  1105. *** s1 and s2 are not modified.
  1106. ***
  1107.  */
  1108.  
  1109. int strnicmp (const char *s1, const char *s2, size_t n)
  1110. {
  1111.   char _s1[81], _s2[81];
  1112.  
  1113.   strncpy (_s1, s1, 80);
  1114.   strncpy (_s2, s2, 80);
  1115.   strupr (_s1);
  1116.   strupr (_s2);
  1117.  
  1118.   return (strncmp (_s1, _s2, n));
  1119. }
  1120. #endif /** _ICMP **/
  1121.