home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / TE2DDIR.ZIP / TE2DDIR.C
C/C++ Source or Header  |  1990-07-12  |  19KB  |  559 lines

  1. //
  2. //  Te2DDir.C -- TE/2 Dialing Directory Manipulation Functions
  3. //
  4. //    CopyRight 1990 by Oberon Software, Mankato, MN
  5. //    All Rights Reserved
  6. //
  7. //  The code in this file may be freely used for the creation of utility
  8. //  programs which manipulate TE/2 Dialing Directories such as:
  9. //      Sorting Utilities
  10. //      Printing Utilities
  11. //      Conversion Utilities
  12. //
  13. //  You may not commericially distribute and/or charge for any program
  14. //  made which contains any of the code contained in this file.  If you
  15. //  do create a useful utility for manipulating TE/2 Directory Files with
  16. //  some or all of this code you are urged to upload the program to the
  17. //  Oberon Software User Support BBS (507-388-1154) so that it may be
  18. //  made available to other users.
  19. //
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24.  
  25. #define INCL_BASE
  26. #include <os2.h>
  27.  
  28.  
  29. // --------------------------------------------------------------------------
  30. // ---- Constants
  31.  
  32.   // ---- Parity designation codes for directory entries
  33. #define NO_PARITY         0       // No Parity
  34. #define ODD_PARITY        1       // Odd Parity
  35. #define EVEN_PARITY       2       // Even Parity
  36. #define MARK_PARITY       3       // Mark Parity
  37. #define SPACE_PARITY      4       // Space Parity
  38.  
  39.   // ---- StopBit designation codes for directory entries
  40. #define STOPBITS_1        0       // 1 Stopbit
  41. #define STOPBITS_15       1       // 1.5 Stopbits
  42. #define STOPBITS_2        2       // 2 Stopbits
  43.  
  44.   // ---- Protocol designation codes for directory entries
  45. #define PROTOCOL_ASCII    0       // Ascii protocol (upload only)
  46. #define PROTOCOL_XMODEM   1       // XModem (CRC)
  47. #define PROTOCOL_XMODEM1K 2       // XModem-1K
  48. #define PROTOCOL_YMODEM   3       // YModem
  49. #define PROTOCOL_ZMODEM   4       // ZModem
  50. #define PROTOCOL_YMODEMG  5       // YModem-G (not used before 1.00c)
  51. #define PROTOCOL_CISQB    6       // CIS BPlus (for future use)
  52.  
  53.   // ---- Emulation designation codes for directory entries
  54. #define EMULATE_TTY       0       // Teletype emulation
  55. #define EMULATE_ANSI      1       // ANSI-BBS
  56. #define EMULATE_XANSI     2       // ANSI-TE/2
  57. #define EMULATE_VT100     3       // VT100
  58.  
  59.   // ---- Other important constants
  60. #define ORIG_MAXDENTRY    50      // # of entries in pre-1.00c files
  61. #define MAXDENTRY         200     // # of entries in files since 1.00c
  62. #define TAGLEN            5       // Length of TAG field
  63. #define NAMELEN           25      // Length of NAME field
  64. #define NUMLEN            29      // Length of NUMBER field
  65. #define SCRIPTLEN         63      // Length of SCRIPT field
  66. #define ACCCODES          10      // Number of access code entries/file
  67. #define ACCCLEN           NUMLEN  // Length of access code entry
  68. #define RDF_BUFSIZ        80      // Length of a utility buffer
  69.  
  70.  
  71. // --------------------------------------------------------------------------
  72. // ---- Typedefs
  73.  
  74.   // ---- Directory entry structure
  75. typedef struct _DDENTRY
  76. {
  77.   char     tag[TAGLEN+1];       // May be any asciiz data
  78.   char     name[NAMELEN+1];     // May be any asciiz data
  79.   char     number[NUMLEN+1];    // May be any asciiz data
  80.   USHORT   baud;                // 110, 150, 300, 600, 1200, 2400, 4800, 9600,
  81.                                 //   19200, 38400, or 57600
  82.   USHORT   parity;              // NO_PARITY, ODD_PARITY, EVEN_PARITY,
  83.                                 //   MARK_PARITY, or SPACE_PARITY
  84.   USHORT   wordlen;             // 7 or 8
  85.   USHORT   stopbits;            // STOPBITS_1, STOPBITS_15, or STOPBITS_2
  86.   USHORT   duplex;              // TRUE == Half Duplex, FALSE == Full Duplex
  87.   USHORT   protocol;            // PROTOCOL_ASCII, PROTOCOL_XMODEM,
  88.                                 //   PROTOCOL_XMODEM1K, PROTOCOL_YMODEM,
  89.                                 //   PROTOCOL_ZMODEM, PROTOCOL_YMODEMG, or
  90.                                 //   PROTOCOL_CISQB
  91.   USHORT   emulate;             // EMULATE_TTY, EMULATE_ANSI, EMULATE_XANSI,
  92.                                 //   or EMULATE_VT100
  93.   char     script[SCRIPTLEN+1]; // May be any asciiz data
  94.   USHORT   connected;           // Count of times connected
  95.   DATETIME lastconnect;         // Date/Time of last connect
  96. } DDENTRY;
  97.  
  98.  
  99. // --------------------------------------------------------------------------
  100. // ---- Local data
  101.  
  102.   // ---- Array of pointers to directory entries, will be allocated and
  103.   //      filled by ReadDirectoryFile()
  104. static DDENTRY *directory[MAXDENTRY];
  105.  
  106.   // ---- Array of string buffers to hold access codes associated with
  107.   //      a dialing directory file.
  108. static char accCodes[ACCCODES][ACCCLEN+1];
  109.  
  110.   // ---- Signiture strings found in the header record of a directory
  111.   //      file from various versions of TE/2
  112. static char *dirFileSig_v0    = "TE/2 Directory v1.0";
  113. static char *dirFileSig_v100F = "TE/2 Directory v1.00α1";
  114. static char *dirFileSig       = "TE/2 Directory v1.00α2";
  115.  
  116.   // ---- An empty DATETIME structure used for default value of "lastconnect"
  117.   //      in older directory files
  118. static DATETIME nulDate   = { '\0', '\0', '\0', '\0', '\0', '\0', 0, 0, '\0' };
  119.  
  120.  
  121. // --------------------------------------------------------------------------
  122.  
  123.   // ---- Function prototypes
  124.  
  125. static int freadStrg(char *buf, FILE *fp);  // Read asciiz from file
  126. static int fwriteStrg(char *buf, FILE *fp); // Write asciiz to file
  127.  
  128. static int ReadV0Directory(FILE *fp);       // Read a very old dir file
  129. static int ReadV100FDirectory(FILE *fp);    // Read an old dir file
  130. static int ReadCurrentDirectory(FILE *fp);  // Read a current dir file
  131.  
  132. int  ReadDirectoryFile(char *fname);        // Read any vsn dir file
  133. int  WriteDirectoryFile(char *fname);       // Write a current vsn dir file
  134.  
  135. void EmptyDirectory(void);                  // free all allocated memory
  136.  
  137.  
  138. // --------------------------------------------------------------------------
  139. // ---- Functions
  140.  
  141.  
  142.   // -----------------------------------------------------------------------
  143.   // Read an ASCIIZ string from a file, expects 'buf' to be large enough
  144.   // to hold any conceivable number of characters (i.e., there is no
  145.   // error checking).
  146.  
  147. static int freadStrg(char *buf, FILE *fp)
  148. {
  149.   int  i = 0, err = FALSE;
  150.   char c;
  151.  
  152.   do
  153.   {
  154.     if (fread(&c, sizeof(char), 1, fp) != 1)
  155.     {
  156.       err = TRUE;
  157.       break;
  158.     }
  159.     buf[i++] = c;
  160.   }
  161.   while (c);
  162.  
  163.   return err;
  164. }
  165.  
  166.  
  167.  
  168.   // -----------------------------------------------------------------------
  169.   // Write an ASCIIZ string to a file
  170.  
  171. static int fwriteStrg(char *buf, FILE *fp)
  172. {
  173.   int  i = 0, err = FALSE;
  174.   char c;
  175.  
  176.   do
  177.   {
  178.     c = buf[i++];
  179.     if (fwrite(&c, sizeof(char), 1, fp) != 1)
  180.     {
  181.       err = TRUE;
  182.       break;
  183.     }
  184.   }
  185.   while (c);
  186.  
  187.   return err;
  188. }
  189.  
  190.  
  191. // --------------------------------------------------------------------------
  192.  
  193.  
  194.   // -----------------------------------------------------------------------
  195.   // General Notes about the Read*Directory() functions:
  196.   //
  197.   //   The "directory" array is an array of pointers to directory entry
  198.   //   structures, it contains all NULL pointers by default.  Each
  199.   //   function will allocate entries as needed as it encounters valid
  200.   //   entries in the directory file.  Empty entries in the file consist
  201.   //   of a single, zero byte.  When an empty entry is encountered, it's
  202.   //   pointer in the array is left NULL.
  203.   //
  204.   //   These functions may be called more than once to reread the same
  205.   //   or other directory files.  Space for entries will be reused,
  206.   //   allocated, and/or freed as required.
  207.   //
  208.   //   Each function returns TRUE if the file was read with no errors
  209.   //   detected, FALSE if any error occured.  If FALSE is returned, the
  210.   //   directory may be partially read and available for examination.
  211.   //
  212.   //   After the caller is done with the "directory" array, the
  213.   //   EmptyDirectory() function should be called to make sure that all
  214.   //   allocated memory has been freed.
  215.   // -----------------------------------------------------------------------
  216.  
  217.  
  218.   // -----------------------------------------------------------------------
  219.   // Read a "version 0" directory file into memory.  This is the file format
  220.   // created by TE/2 Version 1.00b.  Expects the current position in the
  221.   // file to be pointing past the header information at the first real entry.
  222.  
  223. static int ReadV0Directory(FILE *fp)
  224. {
  225.   int  i, j, err;
  226.   char buf = 0;
  227.  
  228.   for (i = 0; i < ORIG_MAXDENTRY; i++)
  229.   {
  230.     if (fread(&buf, sizeof(char), 1, fp) == 1)
  231.     {
  232.       if (buf)  // If there is an entry at this position
  233.       {
  234.         // Either create an entry structure if this is a first read or
  235.         //   clean up an existing one for reuse.
  236.         if (!directory[i])
  237.           directory[i] = calloc(1, sizeof(DDENTRY));
  238.         else
  239.           memset(directory[i], 0, sizeof(DDENTRY));
  240.  
  241.         // Read the data that's there
  242.         err  =  freadStrg(directory[i]->tag, fp);
  243.         err |=  freadStrg(directory[i]->name, fp);
  244.         err |=  freadStrg(directory[i]->number, fp);
  245.         err |= (fread(&(directory[i]->baud),     sizeof(USHORT), 1, fp) != 1);
  246.         err |= (fread(&(directory[i]->parity),   sizeof(USHORT), 1, fp) != 1);
  247.         err |= (fread(&(directory[i]->wordlen),  sizeof(USHORT), 1, fp) != 1);
  248.         err |= (fread(&(directory[i]->stopbits), sizeof(USHORT), 1, fp) != 1);
  249.         err |= (fread(&(directory[i]->duplex),   sizeof(USHORT), 1, fp) != 1);
  250.         err |= (fread(&(directory[i]->protocol), sizeof(USHORT), 1, fp) != 1);
  251.         err |=  freadStrg(directory[i]->script, fp);
  252.         if (err) break;
  253.  
  254.         // Insert default values, this version of the file didn't contain
  255.         //   these fields.
  256.         directory[i]->emulate = EMULATE_XANSI;
  257.         directory[i]->connected = 0;
  258.         directory[i]->lastconnect = nulDate;
  259.       }
  260.       else if (directory[i])
  261.       {
  262.         // No entry at this position in this file.  If there was already
  263.         // space allocated, free it.
  264.         free(directory[i]);
  265.         directory[i] = NULL;
  266.       }
  267.     }
  268.     else
  269.       break;
  270.   }
  271.  
  272.   if (!err)
  273.   {
  274.     // This version of the file did not contain as many records as later
  275.     // ones.  Make up the difference here with NULL entries.
  276.     for (j = i; j < MAXDENTRY; j++)
  277.       if (directory[j])
  278.       {
  279.         free(directory[j]);
  280.         directory[j] = NULL;
  281.       }
  282.  
  283.     // This version of the file didn't contain any Access Codes.  Fill in
  284.     // with NULL entries.
  285.     for (j = 0; j < ACCCODES; j++)
  286.       memset(accCodes[j], 0, ACCCLEN+1);
  287.   }
  288.  
  289.   // Return TRUE on a successful read, FALSE if an error occured
  290.   return (i == ORIG_MAXDENTRY);
  291. }
  292.  
  293.  
  294.  
  295.  
  296.   // -----------------------------------------------------------------------
  297.   // Read a "version 100F" directory file into memory.  This is the file
  298.   // format created by TE/2 starting with Version 1.00c and continued
  299.   // through version 1.00f. Expects the current position in the file to
  300.   // be pointing past the header information at the first real entry.
  301.  
  302. static int ReadV100FDirectory(FILE *fp)
  303. {
  304.   int  i, j, err;
  305.   char buf = 0;
  306.  
  307.   for (i = 0; i < MAXDENTRY; i++)
  308.   {
  309.     if (fread(&buf, sizeof(char), 1, fp) == 1)
  310.     {
  311.       if (buf)
  312.       {
  313.         // Either create an entry structure if this is a first read or
  314.         //   clean up an existing one for reuse.
  315.         if (!directory[i])
  316.           directory[i] = calloc(1, sizeof(DDENTRY));
  317.         else
  318.           memset(directory[i], 0, sizeof(DDENTRY));
  319.  
  320.         // Read the data that's there
  321.         err  =  freadStrg(directory[i]->tag, fp);
  322.         err |=  freadStrg(directory[i]->name, fp);
  323.         err |=  freadStrg(directory[i]->number, fp);
  324.         err |= (fread(&(directory[i]->baud),     sizeof(USHORT), 1, fp) != 1);
  325.         err |= (fread(&(directory[i]->parity),   sizeof(USHORT), 1, fp) != 1);
  326.         err |= (fread(&(directory[i]->wordlen),  sizeof(USHORT), 1, fp) != 1);
  327.         err |= (fread(&(directory[i]->stopbits), sizeof(USHORT), 1, fp) != 1);
  328.         err |= (fread(&(directory[i]->duplex),   sizeof(USHORT), 1, fp) != 1);
  329.         err |= (fread(&(directory[i]->protocol), sizeof(USHORT), 1, fp) != 1);
  330.         err |= (fread(&(directory[i]->emulate),  sizeof(USHORT), 1, fp) != 1);
  331.         err |=  freadStrg(directory[i]->script, fp);
  332.         if (err) break;
  333.  
  334.         // Insert default values, this version of the file didn't contain
  335.         //   these fields.
  336.         directory[i]->connected = 0;
  337.         directory[i]->lastconnect = nulDate;
  338.       }
  339.       else if (directory[i])
  340.       {
  341.         // No entry at this position in this file.  If there was already
  342.         // space allocated, free it.
  343.         free(directory[i]);
  344.         directory[i] = NULL;
  345.       }
  346.     }
  347.     else
  348.       break;
  349.   }
  350.  
  351.   if (!err)
  352.   {
  353.     // This version of the file didn't contain any Access Codes.  Fill in
  354.     // with NULL entries.
  355.     for (j = 0; j < ACCCODES; j++)
  356.       memset(accCodes[j], 0, ACCCLEN+1);
  357.   }
  358.  
  359.   // Return TRUE on a successful read, FALSE if an error occured
  360.   return (i == MAXDENTRY);
  361. }
  362.  
  363.  
  364.  
  365.  
  366.   // -----------------------------------------------------------------------
  367.   // Read a "current version" directory file into memory.  This is the
  368.   // file format created by TE/2 starting with Version 1.10a. Expects
  369.   // the current position in the file to be pointing past the header
  370.   // information at the first real entry.
  371.  
  372. static int ReadCurrentDirectory(FILE *fp)
  373. {
  374.   int  i, j, err;
  375.   char buf = 0;
  376.  
  377.   for (i = 0; i < MAXDENTRY; i++)
  378.   {
  379.     if (fread(&buf, sizeof(char), 1, fp) == 1)
  380.     {
  381.       if (buf)
  382.       {
  383.         // Either create an entry structure if this is a first read or
  384.         //   clean up an existing one for reuse.
  385.         if (!directory[i])
  386.           directory[i] = calloc(1, sizeof(DDENTRY));
  387.         else
  388.           memset(directory[i], 0, sizeof(DDENTRY));
  389.  
  390.         // Read the data
  391.         err  =  freadStrg(directory[i]->tag, fp);
  392.         err |=  freadStrg(directory[i]->name, fp);
  393.         err |=  freadStrg(directory[i]->number, fp);
  394.         err |= (fread(&(directory[i]->baud),        sizeof(USHORT),   1, fp) != 1);
  395.         err |= (fread(&(directory[i]->parity),      sizeof(USHORT),   1, fp) != 1);
  396.         err |= (fread(&(directory[i]->wordlen),     sizeof(USHORT),   1, fp) != 1);
  397.         err |= (fread(&(directory[i]->stopbits),    sizeof(USHORT),   1, fp) != 1);
  398.         err |= (fread(&(directory[i]->duplex),      sizeof(USHORT),   1, fp) != 1);
  399.         err |= (fread(&(directory[i]->protocol),    sizeof(USHORT),   1, fp) != 1);
  400.         err |= (fread(&(directory[i]->emulate),     sizeof(USHORT),   1, fp) != 1);
  401.         err |=  freadStrg(directory[i]->script, fp);
  402.         err |= (fread(&(directory[i]->connected),   sizeof(USHORT),   1, fp) != 1);
  403.         err |= (fread(&(directory[i]->lastconnect), sizeof(DATETIME), 1, fp) != 1);
  404.         if (err) break;
  405.       }
  406.       else if (directory[i])
  407.       {
  408.         // No entry at this position in this file.  If there was already
  409.         // space allocated, free it.
  410.         free(directory[i]);
  411.         directory[i] = NULL;
  412.       }
  413.     }
  414.     else
  415.       break;
  416.   }
  417.  
  418.   if (!err && !feof(fp))
  419.   {
  420.     // Read the Access Codes associated with this directory
  421.     for (j = 0; j < ACCCODES && !err; j++)
  422.       err |= freadStrg(accCodes[j], fp);
  423.   }
  424.  
  425.   // Return TRUE on a successful read, FALSE if an error occured
  426.   return ((i == MAXDENTRY) && !err);
  427. }
  428.  
  429.  
  430.  
  431.  
  432.   // -----------------------------------------------------------------------
  433.   // Read any format directory file into memory.
  434.  
  435. int ReadDirectoryFile(char *fname)
  436. {
  437.   FILE *fp;
  438.   int  i, rVal = FALSE;
  439.   char buf[RDF_BUFSIZ];
  440.  
  441.   if (fp = fopen(fname, "rb"))
  442.   {
  443.     // "dirFileSig", the signiture on a current version directory file is
  444.     // the longest signiture in any version.  We'll read enough of the
  445.     // header to get the whole string; we may need to seek back in the
  446.     // file if it's an older version.
  447.  
  448.     i = strlen(dirFileSig);
  449.     if (fread(buf, sizeof(char), i, fp) == i)
  450.     {
  451.       if (strncmp(buf, dirFileSig, i) == 0)
  452.       {
  453.         // Current style directory, second alpha, labeled α2
  454.         rVal = ReadCurrentDirectory(fp);
  455.       }
  456.       else if (strncmp(buf, dirFileSig_v100F, strlen(dirFileSig_v100F)) == 0)
  457.       {
  458.         // Version 1.00.c through 1.00.f style directory
  459.         fseek(fp, (long)(strlen(dirFileSig_v100F)), SEEK_SET);
  460.         rVal = ReadV100FDirectory(fp);
  461.       }
  462.       else if (strncmp(buf, dirFileSig_v0, strlen(dirFileSig_v0)) == 0)
  463.       {
  464.         // Earliest style, first alpha
  465.         fseek(fp, (long)(strlen(dirFileSig_v0)), SEEK_SET);
  466.         rVal = ReadV0Directory(fp);
  467.       }
  468.     }
  469.     fclose(fp);
  470.   }
  471.  
  472.   return rVal;
  473. }
  474.  
  475.  
  476.  
  477.   // -----------------------------------------------------------------------
  478.   // Write a directory file of the current format.
  479.  
  480. int WriteDirectoryFile(char *fname)
  481. {
  482.   FILE *fp;
  483.   int  i, j, err, rVal = FALSE;
  484.   char c;
  485.  
  486.   if (fp = fopen(fname, "wb"))
  487.   {
  488.     i = strlen(dirFileSig);
  489.     if (fwrite(dirFileSig, sizeof(char), i, fp) == i)
  490.     {
  491.       for (i = 0; i < MAXDENTRY; i++)
  492.       {
  493.         if (directory[i])
  494.         {
  495.           c = 1;
  496.           if (fwrite(&c, sizeof(char), 1, fp) == 1)
  497.           {
  498.             err  =  fwriteStrg(directory[i]->tag, fp);
  499.             err |=  fwriteStrg(directory[i]->name, fp);
  500.             err |=  fwriteStrg(directory[i]->number, fp);
  501.             err |= (fwrite(&(directory[i]->baud),        sizeof(USHORT),   1, fp) != 1);
  502.             err |= (fwrite(&(directory[i]->parity),      sizeof(USHORT),   1, fp) != 1);
  503.             err |= (fwrite(&(directory[i]->wordlen),     sizeof(USHORT),   1, fp) != 1);
  504.             err |= (fwrite(&(directory[i]->stopbits),    sizeof(USHORT),   1, fp) != 1);
  505.             err |= (fwrite(&(directory[i]->duplex),      sizeof(USHORT),   1, fp) != 1);
  506.             err |= (fwrite(&(directory[i]->protocol),    sizeof(USHORT),   1, fp) != 1);
  507.             err |= (fwrite(&(directory[i]->emulate),     sizeof(USHORT),   1, fp) != 1);
  508.             err |=  fwriteStrg(directory[i]->script, fp);
  509.             err |= (fwrite(&(directory[i]->connected),   sizeof(USHORT),   1, fp) != 1);
  510.             err |= (fwrite(&(directory[i]->lastconnect), sizeof(DATETIME), 1, fp) != 1);
  511.             if (err) break;
  512.           }
  513.           else
  514.             break;
  515.         }
  516.         else
  517.         {
  518.           c = 0;
  519.           if (fwrite(&c, sizeof(char), 1, fp) != 1)
  520.             break;
  521.         }
  522.       }
  523.       rVal = (i == MAXDENTRY);
  524.  
  525.       if (!err && !feof(fp))
  526.       {
  527.         for (j = 0; j < ACCCODES; j++)
  528.           err |= fwriteStrg(accCodes[j], fp);
  529.       }
  530.  
  531.     }
  532.     fclose(fp);
  533.   }
  534.  
  535.   return rVal;
  536. }
  537.  
  538.  
  539.  
  540.   // -----------------------------------------------------------------------
  541.   // Free all allocated memory associated with the directory
  542.  
  543.  
  544. void EmptyDirectory()
  545. {
  546.   int i;
  547.  
  548.   for (i = 0; i < MAXDENTRY; i++)
  549.   {
  550.     if (directory[i])
  551.     {
  552.       free(directory[i]);
  553.       directory[i] = NULL;
  554.     }
  555.   }
  556. }
  557.  
  558.  
  559.