home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 February / PCO_0299.ISO / filesbbs / dos / indigo01.exe / MSGID.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-21  |  6.5 KB  |  209 lines

  1. // This program is free software; you can redistribute it and/or modify it
  2. // under the terms of the GNU General Public License as published by the Free
  3. // Software Foundation; either version 2 of the License, or (at your option)
  4. // any later version.
  5.  
  6. // You should have received a copy of the GNU General Public License along
  7. // with this program; if not, write to the Free Software Foundation, Inc., 675
  8. // Mass Ave, Cambridge, MA 02139, USA.
  9.  
  10. // msgid.cpp
  11. // Routines to handle MSGID generation.
  12. // It can either do independent MSGID generation, or use an IDSERVER.DAT file.
  13.  
  14. #include "msgid.h"
  15. #include "crc32.h"
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #ifdef __EMX__
  20. #include <sys/time.h>
  21. #include <dos.h>
  22. #define INCL_DOSPROCESS
  23. #include <os2.h>
  24. #endif
  25. #ifdef __TURBOC__
  26. #include <time.h>
  27. #include <dos.h>
  28. #endif
  29.  
  30. // Constants for the IDSERVER.DAT.
  31. #define SERVERVERSION   0
  32. #define SERVERSIGNATURE 0x1a534449
  33.  
  34. // Class: MsgidStd
  35. // This is the independent MSGID generation.
  36.  
  37. // constructor
  38. // Initializes the MSGID number to a function of the current system time.
  39. MsgidStd::MsgidStd()
  40. {
  41. #ifdef __EMX__
  42.     // EMX (GNU C++ for OS/2): Get the time of in seconds and milliseconds
  43.     // since 1970-01-01.
  44.     struct timeval tv;
  45.     struct timezone tz;
  46.     gettimeofday(&tv, &tz);
  47. #define SECONDS tv.tv_sec
  48. #define LOWPART (tv.tv_usec / 10)
  49. #endif
  50. #ifdef __TURBOC__
  51.     // Borland Turbo C++: Get the time of day in both seconds since
  52.     // 1970-01-01, and a structure that contains a resolution down to
  53.     // 100ths of a second.
  54.     struct time t;
  55.     gettime(&t);
  56.     time_t now = time(NULL);
  57. #define SECONDS now
  58. #define LOWPART t.ti_hund
  59. #endif
  60.     // Create the MSGID number.
  61.     msgIdNum = (SECONDS << 4) + (LOWPART & 0x0f);
  62. #undef SECONDS
  63. #undef LOWPART
  64. }
  65.  
  66. // method: getSerial
  67. // Gets the requested number of MSGID serial numbers.
  68. UINT32 MsgidStd::getSerial(int number)
  69. {
  70.     UINT32 retval = msgIdNum;
  71.     msgIdNum += number;
  72.     return retval;
  73. }
  74.  
  75. // Class: MsgidServ
  76. // This is the MSGID generation that uses the IDSERVER.DAT file.
  77.  
  78. // constructor
  79. // Set up the path.
  80. MsgidServ::MsgidServ(const char *name)
  81. {
  82.     strcpy(serverFileName, name);
  83.     if ('\\' != serverFileName[strlen(serverFileName) - 1])
  84.         strcat(serverFileName, "\\");
  85.     strcat(serverFileName, "idserver.dat");
  86. }
  87.  
  88. // method: getSerial
  89. // Gets the specified amount of MSGID serial numbers.
  90. UINT32 MsgidServ::getSerial(int number)
  91. {
  92.     FILE *serverfile = fopen(serverFileName, "rb+");
  93.     if (NULL == serverfile) {
  94.         // Unable to open. Try creating it instead.
  95.         serverfile = fopen(serverFileName, "wb");
  96.         if (NULL != serverfile) { // We were able to create it, initialize it.
  97.             createfile(serverfile);
  98.         }
  99.         else {
  100.             // Unable to create it, it's probably locked. Try to open it
  101.             // five times.
  102.             unsigned i = 0;
  103.             while (i < 5) {
  104. #ifdef __MSDOS__
  105.                 // We have to wait between the calls, so for MS-DOS we call
  106.                 // the "release timeslices" function (Int 21, function 1680).
  107.                 union REGS r;
  108.                 r.x.ax = 0x1680;
  109.                 int86(0x21, &r, &r);
  110.                 if (0x80 == r.h.al) {
  111.                     // We could not release timeslices (no multitasker is
  112.                     // available), so we do some busy waiting (ugly).
  113.                     float is_never_used;
  114.                     for (unsigned k = 0; k < 65535; k ++)
  115.                         is_never_used = k / 3.0;
  116.                 }
  117.                 else {
  118.                     // And release a bit more.
  119.                     r.x.ax = 0x1680;
  120.                     int86(0x21, &r, &r);
  121.                 }
  122. #endif
  123. #ifdef __EMX__
  124.                 // We have to wait between calls, so for OS/2 we call the
  125.                 // "sleep" function, and sleeps for a second.
  126.                 DosSleep(1000);
  127. #endif
  128.                 // Try to open it again.
  129.                 serverfile = fopen(serverFileName, "rb+");
  130.                 i = serverfile ? 10 : i + 1; // Flag if we could open it.
  131.             }
  132.             if (10 != i) {
  133.                 // Failed opening the file. Return a random number instead.
  134.                 // (ugly)
  135. #ifdef __TURBOC__
  136.                 return random(0xffff) << 16 | random(0xfff);
  137. #endif
  138. #ifdef __EMX__
  139.                 return random();
  140. #endif
  141.             }
  142.         }
  143.     }
  144.     
  145.     // Okay, now the file is open.
  146.     fseek(serverfile, 0, SEEK_SET);
  147.     idServerDat serverdat;
  148.     fread(&serverdat, sizeof(idServerDat), 1, serverfile);
  149.  
  150.     // Check the signature. If it's wrong, reinitialize the file.
  151.     if (SERVERSIGNATURE != serverdat.signature) { // Wrong signature.
  152.         fseek(serverfile, 0, SEEK_SET);
  153.         createfile(serverfile);
  154.     }
  155.  
  156.     // If there is a CRC32 value, check if it's correct.
  157.     // (I wonder why you really need a CRC32 value on this kind of file...?)
  158.     if (SERVERSIGNATURE != serverdat.crc32) {
  159.         UINT32 crc = 0xffffffff;
  160.         for (UINT8 *byte_p = (UINT8 *) &serverdat;
  161.              byte_p < (UINT8 *) &serverdat.crc32; byte_p ++)
  162.             crc = UPDC32(*byte_p, crc);
  163.         if (serverdat.crc32 != crc) // CRC error
  164.             createfile(serverfile);
  165.     }
  166.  
  167.     // Get a serial number from the file
  168.     UINT32 retval = serverdat.nextserial;
  169.     // and update the number in the file.
  170.     serverdat.nextserial += number;
  171.     
  172.     // Calculate a new CRC32 value
  173.     UINT32 crc = 0xffffffff;
  174.     for (UINT8 *byte_p = (UINT8 *) &serverdat;
  175.          byte_p < (UINT8 *) &serverdat.crc32; byte_p ++)
  176.         crc = UPDC32(*byte_p, crc);
  177.     // and write it.
  178.     serverdat.crc32 = crc;
  179.     fseek(serverfile, 0, SEEK_SET);
  180.     fwrite(&serverdat, sizeof(idServerDat), 1, serverfile);
  181.  
  182.     // Close the file.
  183.     fclose(serverfile);
  184.  
  185.     // Done!
  186.     return retval;
  187. }
  188.  
  189. // method: createfile (private)
  190. // Creates a new idserver file.
  191. void MsgidServ::createfile(FILE *server)
  192. {
  193.     idServerDat serverdat;
  194.  
  195.     // Reset the struct.
  196.     memset(&serverdat, 0, sizeof(idServerDat));
  197.  
  198.     // Put in the data. It's unnessecary to CRC32 it now.
  199.     serverdat.revision = SERVERVERSION;
  200.     serverdat.crc32 = serverdat.signature = SERVERSIGNATURE;
  201.  
  202.     // Initialize the MSGID value.
  203.     serverdat.nextserial = serverdat.initserial = ((UINT32) time(NULL)) << 5;
  204.  
  205.     // Write the file.
  206.     fseek(server, 0, SEEK_SET);
  207.     fwrite(&serverdat, sizeof(idServerDat), 1, server);
  208. }
  209.