home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 3 Comm
/
03-Comm.zip
/
TE2DDIR.ZIP
/
TE2DDIR.C
Wrap
C/C++ Source or Header
|
1990-07-12
|
19KB
|
559 lines
//
// Te2DDir.C -- TE/2 Dialing Directory Manipulation Functions
//
// CopyRight 1990 by Oberon Software, Mankato, MN
// All Rights Reserved
//
// The code in this file may be freely used for the creation of utility
// programs which manipulate TE/2 Dialing Directories such as:
// Sorting Utilities
// Printing Utilities
// Conversion Utilities
//
// You may not commericially distribute and/or charge for any program
// made which contains any of the code contained in this file. If you
// do create a useful utility for manipulating TE/2 Directory Files with
// some or all of this code you are urged to upload the program to the
// Oberon Software User Support BBS (507-388-1154) so that it may be
// made available to other users.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INCL_BASE
#include <os2.h>
// --------------------------------------------------------------------------
// ---- Constants
// ---- Parity designation codes for directory entries
#define NO_PARITY 0 // No Parity
#define ODD_PARITY 1 // Odd Parity
#define EVEN_PARITY 2 // Even Parity
#define MARK_PARITY 3 // Mark Parity
#define SPACE_PARITY 4 // Space Parity
// ---- StopBit designation codes for directory entries
#define STOPBITS_1 0 // 1 Stopbit
#define STOPBITS_15 1 // 1.5 Stopbits
#define STOPBITS_2 2 // 2 Stopbits
// ---- Protocol designation codes for directory entries
#define PROTOCOL_ASCII 0 // Ascii protocol (upload only)
#define PROTOCOL_XMODEM 1 // XModem (CRC)
#define PROTOCOL_XMODEM1K 2 // XModem-1K
#define PROTOCOL_YMODEM 3 // YModem
#define PROTOCOL_ZMODEM 4 // ZModem
#define PROTOCOL_YMODEMG 5 // YModem-G (not used before 1.00c)
#define PROTOCOL_CISQB 6 // CIS BPlus (for future use)
// ---- Emulation designation codes for directory entries
#define EMULATE_TTY 0 // Teletype emulation
#define EMULATE_ANSI 1 // ANSI-BBS
#define EMULATE_XANSI 2 // ANSI-TE/2
#define EMULATE_VT100 3 // VT100
// ---- Other important constants
#define ORIG_MAXDENTRY 50 // # of entries in pre-1.00c files
#define MAXDENTRY 200 // # of entries in files since 1.00c
#define TAGLEN 5 // Length of TAG field
#define NAMELEN 25 // Length of NAME field
#define NUMLEN 29 // Length of NUMBER field
#define SCRIPTLEN 63 // Length of SCRIPT field
#define ACCCODES 10 // Number of access code entries/file
#define ACCCLEN NUMLEN // Length of access code entry
#define RDF_BUFSIZ 80 // Length of a utility buffer
// --------------------------------------------------------------------------
// ---- Typedefs
// ---- Directory entry structure
typedef struct _DDENTRY
{
char tag[TAGLEN+1]; // May be any asciiz data
char name[NAMELEN+1]; // May be any asciiz data
char number[NUMLEN+1]; // May be any asciiz data
USHORT baud; // 110, 150, 300, 600, 1200, 2400, 4800, 9600,
// 19200, 38400, or 57600
USHORT parity; // NO_PARITY, ODD_PARITY, EVEN_PARITY,
// MARK_PARITY, or SPACE_PARITY
USHORT wordlen; // 7 or 8
USHORT stopbits; // STOPBITS_1, STOPBITS_15, or STOPBITS_2
USHORT duplex; // TRUE == Half Duplex, FALSE == Full Duplex
USHORT protocol; // PROTOCOL_ASCII, PROTOCOL_XMODEM,
// PROTOCOL_XMODEM1K, PROTOCOL_YMODEM,
// PROTOCOL_ZMODEM, PROTOCOL_YMODEMG, or
// PROTOCOL_CISQB
USHORT emulate; // EMULATE_TTY, EMULATE_ANSI, EMULATE_XANSI,
// or EMULATE_VT100
char script[SCRIPTLEN+1]; // May be any asciiz data
USHORT connected; // Count of times connected
DATETIME lastconnect; // Date/Time of last connect
} DDENTRY;
// --------------------------------------------------------------------------
// ---- Local data
// ---- Array of pointers to directory entries, will be allocated and
// filled by ReadDirectoryFile()
static DDENTRY *directory[MAXDENTRY];
// ---- Array of string buffers to hold access codes associated with
// a dialing directory file.
static char accCodes[ACCCODES][ACCCLEN+1];
// ---- Signiture strings found in the header record of a directory
// file from various versions of TE/2
static char *dirFileSig_v0 = "TE/2 Directory v1.0";
static char *dirFileSig_v100F = "TE/2 Directory v1.00α1";
static char *dirFileSig = "TE/2 Directory v1.00α2";
// ---- An empty DATETIME structure used for default value of "lastconnect"
// in older directory files
static DATETIME nulDate = { '\0', '\0', '\0', '\0', '\0', '\0', 0, 0, '\0' };
// --------------------------------------------------------------------------
// ---- Function prototypes
static int freadStrg(char *buf, FILE *fp); // Read asciiz from file
static int fwriteStrg(char *buf, FILE *fp); // Write asciiz to file
static int ReadV0Directory(FILE *fp); // Read a very old dir file
static int ReadV100FDirectory(FILE *fp); // Read an old dir file
static int ReadCurrentDirectory(FILE *fp); // Read a current dir file
int ReadDirectoryFile(char *fname); // Read any vsn dir file
int WriteDirectoryFile(char *fname); // Write a current vsn dir file
void EmptyDirectory(void); // free all allocated memory
// --------------------------------------------------------------------------
// ---- Functions
// -----------------------------------------------------------------------
// Read an ASCIIZ string from a file, expects 'buf' to be large enough
// to hold any conceivable number of characters (i.e., there is no
// error checking).
static int freadStrg(char *buf, FILE *fp)
{
int i = 0, err = FALSE;
char c;
do
{
if (fread(&c, sizeof(char), 1, fp) != 1)
{
err = TRUE;
break;
}
buf[i++] = c;
}
while (c);
return err;
}
// -----------------------------------------------------------------------
// Write an ASCIIZ string to a file
static int fwriteStrg(char *buf, FILE *fp)
{
int i = 0, err = FALSE;
char c;
do
{
c = buf[i++];
if (fwrite(&c, sizeof(char), 1, fp) != 1)
{
err = TRUE;
break;
}
}
while (c);
return err;
}
// --------------------------------------------------------------------------
// -----------------------------------------------------------------------
// General Notes about the Read*Directory() functions:
//
// The "directory" array is an array of pointers to directory entry
// structures, it contains all NULL pointers by default. Each
// function will allocate entries as needed as it encounters valid
// entries in the directory file. Empty entries in the file consist
// of a single, zero byte. When an empty entry is encountered, it's
// pointer in the array is left NULL.
//
// These functions may be called more than once to reread the same
// or other directory files. Space for entries will be reused,
// allocated, and/or freed as required.
//
// Each function returns TRUE if the file was read with no errors
// detected, FALSE if any error occured. If FALSE is returned, the
// directory may be partially read and available for examination.
//
// After the caller is done with the "directory" array, the
// EmptyDirectory() function should be called to make sure that all
// allocated memory has been freed.
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// Read a "version 0" directory file into memory. This is the file format
// created by TE/2 Version 1.00b. Expects the current position in the
// file to be pointing past the header information at the first real entry.
static int ReadV0Directory(FILE *fp)
{
int i, j, err;
char buf = 0;
for (i = 0; i < ORIG_MAXDENTRY; i++)
{
if (fread(&buf, sizeof(char), 1, fp) == 1)
{
if (buf) // If there is an entry at this position
{
// Either create an entry structure if this is a first read or
// clean up an existing one for reuse.
if (!directory[i])
directory[i] = calloc(1, sizeof(DDENTRY));
else
memset(directory[i], 0, sizeof(DDENTRY));
// Read the data that's there
err = freadStrg(directory[i]->tag, fp);
err |= freadStrg(directory[i]->name, fp);
err |= freadStrg(directory[i]->number, fp);
err |= (fread(&(directory[i]->baud), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->parity), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->wordlen), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->stopbits), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->duplex), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->protocol), sizeof(USHORT), 1, fp) != 1);
err |= freadStrg(directory[i]->script, fp);
if (err) break;
// Insert default values, this version of the file didn't contain
// these fields.
directory[i]->emulate = EMULATE_XANSI;
directory[i]->connected = 0;
directory[i]->lastconnect = nulDate;
}
else if (directory[i])
{
// No entry at this position in this file. If there was already
// space allocated, free it.
free(directory[i]);
directory[i] = NULL;
}
}
else
break;
}
if (!err)
{
// This version of the file did not contain as many records as later
// ones. Make up the difference here with NULL entries.
for (j = i; j < MAXDENTRY; j++)
if (directory[j])
{
free(directory[j]);
directory[j] = NULL;
}
// This version of the file didn't contain any Access Codes. Fill in
// with NULL entries.
for (j = 0; j < ACCCODES; j++)
memset(accCodes[j], 0, ACCCLEN+1);
}
// Return TRUE on a successful read, FALSE if an error occured
return (i == ORIG_MAXDENTRY);
}
// -----------------------------------------------------------------------
// Read a "version 100F" directory file into memory. This is the file
// format created by TE/2 starting with Version 1.00c and continued
// through version 1.00f. Expects the current position in the file to
// be pointing past the header information at the first real entry.
static int ReadV100FDirectory(FILE *fp)
{
int i, j, err;
char buf = 0;
for (i = 0; i < MAXDENTRY; i++)
{
if (fread(&buf, sizeof(char), 1, fp) == 1)
{
if (buf)
{
// Either create an entry structure if this is a first read or
// clean up an existing one for reuse.
if (!directory[i])
directory[i] = calloc(1, sizeof(DDENTRY));
else
memset(directory[i], 0, sizeof(DDENTRY));
// Read the data that's there
err = freadStrg(directory[i]->tag, fp);
err |= freadStrg(directory[i]->name, fp);
err |= freadStrg(directory[i]->number, fp);
err |= (fread(&(directory[i]->baud), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->parity), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->wordlen), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->stopbits), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->duplex), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->protocol), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->emulate), sizeof(USHORT), 1, fp) != 1);
err |= freadStrg(directory[i]->script, fp);
if (err) break;
// Insert default values, this version of the file didn't contain
// these fields.
directory[i]->connected = 0;
directory[i]->lastconnect = nulDate;
}
else if (directory[i])
{
// No entry at this position in this file. If there was already
// space allocated, free it.
free(directory[i]);
directory[i] = NULL;
}
}
else
break;
}
if (!err)
{
// This version of the file didn't contain any Access Codes. Fill in
// with NULL entries.
for (j = 0; j < ACCCODES; j++)
memset(accCodes[j], 0, ACCCLEN+1);
}
// Return TRUE on a successful read, FALSE if an error occured
return (i == MAXDENTRY);
}
// -----------------------------------------------------------------------
// Read a "current version" directory file into memory. This is the
// file format created by TE/2 starting with Version 1.10a. Expects
// the current position in the file to be pointing past the header
// information at the first real entry.
static int ReadCurrentDirectory(FILE *fp)
{
int i, j, err;
char buf = 0;
for (i = 0; i < MAXDENTRY; i++)
{
if (fread(&buf, sizeof(char), 1, fp) == 1)
{
if (buf)
{
// Either create an entry structure if this is a first read or
// clean up an existing one for reuse.
if (!directory[i])
directory[i] = calloc(1, sizeof(DDENTRY));
else
memset(directory[i], 0, sizeof(DDENTRY));
// Read the data
err = freadStrg(directory[i]->tag, fp);
err |= freadStrg(directory[i]->name, fp);
err |= freadStrg(directory[i]->number, fp);
err |= (fread(&(directory[i]->baud), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->parity), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->wordlen), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->stopbits), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->duplex), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->protocol), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->emulate), sizeof(USHORT), 1, fp) != 1);
err |= freadStrg(directory[i]->script, fp);
err |= (fread(&(directory[i]->connected), sizeof(USHORT), 1, fp) != 1);
err |= (fread(&(directory[i]->lastconnect), sizeof(DATETIME), 1, fp) != 1);
if (err) break;
}
else if (directory[i])
{
// No entry at this position in this file. If there was already
// space allocated, free it.
free(directory[i]);
directory[i] = NULL;
}
}
else
break;
}
if (!err && !feof(fp))
{
// Read the Access Codes associated with this directory
for (j = 0; j < ACCCODES && !err; j++)
err |= freadStrg(accCodes[j], fp);
}
// Return TRUE on a successful read, FALSE if an error occured
return ((i == MAXDENTRY) && !err);
}
// -----------------------------------------------------------------------
// Read any format directory file into memory.
int ReadDirectoryFile(char *fname)
{
FILE *fp;
int i, rVal = FALSE;
char buf[RDF_BUFSIZ];
if (fp = fopen(fname, "rb"))
{
// "dirFileSig", the signiture on a current version directory file is
// the longest signiture in any version. We'll read enough of the
// header to get the whole string; we may need to seek back in the
// file if it's an older version.
i = strlen(dirFileSig);
if (fread(buf, sizeof(char), i, fp) == i)
{
if (strncmp(buf, dirFileSig, i) == 0)
{
// Current style directory, second alpha, labeled α2
rVal = ReadCurrentDirectory(fp);
}
else if (strncmp(buf, dirFileSig_v100F, strlen(dirFileSig_v100F)) == 0)
{
// Version 1.00.c through 1.00.f style directory
fseek(fp, (long)(strlen(dirFileSig_v100F)), SEEK_SET);
rVal = ReadV100FDirectory(fp);
}
else if (strncmp(buf, dirFileSig_v0, strlen(dirFileSig_v0)) == 0)
{
// Earliest style, first alpha
fseek(fp, (long)(strlen(dirFileSig_v0)), SEEK_SET);
rVal = ReadV0Directory(fp);
}
}
fclose(fp);
}
return rVal;
}
// -----------------------------------------------------------------------
// Write a directory file of the current format.
int WriteDirectoryFile(char *fname)
{
FILE *fp;
int i, j, err, rVal = FALSE;
char c;
if (fp = fopen(fname, "wb"))
{
i = strlen(dirFileSig);
if (fwrite(dirFileSig, sizeof(char), i, fp) == i)
{
for (i = 0; i < MAXDENTRY; i++)
{
if (directory[i])
{
c = 1;
if (fwrite(&c, sizeof(char), 1, fp) == 1)
{
err = fwriteStrg(directory[i]->tag, fp);
err |= fwriteStrg(directory[i]->name, fp);
err |= fwriteStrg(directory[i]->number, fp);
err |= (fwrite(&(directory[i]->baud), sizeof(USHORT), 1, fp) != 1);
err |= (fwrite(&(directory[i]->parity), sizeof(USHORT), 1, fp) != 1);
err |= (fwrite(&(directory[i]->wordlen), sizeof(USHORT), 1, fp) != 1);
err |= (fwrite(&(directory[i]->stopbits), sizeof(USHORT), 1, fp) != 1);
err |= (fwrite(&(directory[i]->duplex), sizeof(USHORT), 1, fp) != 1);
err |= (fwrite(&(directory[i]->protocol), sizeof(USHORT), 1, fp) != 1);
err |= (fwrite(&(directory[i]->emulate), sizeof(USHORT), 1, fp) != 1);
err |= fwriteStrg(directory[i]->script, fp);
err |= (fwrite(&(directory[i]->connected), sizeof(USHORT), 1, fp) != 1);
err |= (fwrite(&(directory[i]->lastconnect), sizeof(DATETIME), 1, fp) != 1);
if (err) break;
}
else
break;
}
else
{
c = 0;
if (fwrite(&c, sizeof(char), 1, fp) != 1)
break;
}
}
rVal = (i == MAXDENTRY);
if (!err && !feof(fp))
{
for (j = 0; j < ACCCODES; j++)
err |= fwriteStrg(accCodes[j], fp);
}
}
fclose(fp);
}
return rVal;
}
// -----------------------------------------------------------------------
// Free all allocated memory associated with the directory
void EmptyDirectory()
{
int i;
for (i = 0; i < MAXDENTRY; i++)
{
if (directory[i])
{
free(directory[i]);
directory[i] = NULL;
}
}
}