Files
org-hyperion-cules/dmap2hrc.c
Rhialto The M 8175ad07bc Fix UB when calling ctype functions. (#570)
Compiling Hercules with gcc 10 produces many warnings like this one:
```
  CC       hao.lo
In file included from /usr/include/ctype.h:97,
                 from hstdinc.h:117,
                 from hao.c:17:
hao.c: In function 'hao_message':
hao.c:812:37: warning: array subscript has type 'char' [-Wchar-subscripts]
  812 |                         if (isdigit(p[2]))
      |                             ^
```
Gcc should really present these as compile time errors, since each and every
one represents a potential case of Undefined Behaviour.
I changed (almost) all of these calls, except a few where the parameter was an
int that just came from a getc()-type function.
2023-06-12 11:43:50 -07:00

211 lines
8.0 KiB
C

/* DMAP2HRC.C (C) Copyright Jay Maynard, 2001-2012 */
/* Convert P/390 DEVMAP to Hercules config file */
/* */
/* Released under "The Q Public License Version 1" */
/* (http://www.hercules-390.org/herclic.html) as modifications to */
/* Hercules. */
/*-------------------------------------------------------------------*/
/* This program reads a P/390 DEVMAP file and extracts the device */
/* definitions from it, then writes them to the standard output in */
/* the format Hercules uses for its .cnf file. */
/*-------------------------------------------------------------------*/
#include "hstdinc.h"
#include "hercules.h"
#define UTILITY_NAME "dmap2hrc"
#define UTILITY_DESC "Convert P/390 DEVMAP to Hercules"
/*-------------------------------------------------------------------*/
/* Structure definition for DEVMAP controller record */
/*-------------------------------------------------------------------*/
typedef struct _DEVMAP_CTLR {
BYTE channel; /* High order dev addr byte */
BYTE name[8]; /* Name of controller program*/
BYTE lowdev; /* Low addr byte first dev */
BYTE highdev; /* Low addr byte last dev */
BYTE filler1; /* Fill byte */
BYTE type[4]; /* Type of controller */
BYTE flags; /* Flag byte */
BYTE filler2[47]; /* More filler bytes */
} DEVMAP_CTLR;
/*-------------------------------------------------------------------*/
/* Structure definition for DEVMAP device record */
/*-------------------------------------------------------------------*/
typedef struct _DEVMAP_DEV {
BYTE highaddr; /* High order dev addr byte */
BYTE lowaddr; /* Low order dev addr byte */
char type[4]; /* Type of device */
union {
struct { /* Disk devices: */
BYTE filler1[4]; /* filler */
BYTE volser[6]; /* Volume serial */
BYTE filler2[2]; /* more filler */
char filename[45]; /* name of file on disk */
BYTE flags; /* flag byte */
} disk;
struct { /* Other devices: */
BYTE filler1[7]; /* fill bytes */
char filename[50]; /* device filename */
BYTE flags; /* flag byte */
} other;
} parms;
} DEVMAP_DEV;
/*-------------------------------------------------------------------*/
/* DEVMAP2CNF main entry point */
/*-------------------------------------------------------------------*/
int main (int argc, char *argv[])
{
char *pgm; /* less any extension (.ext) */
int i; /* Array subscript */
int len; /* Length of actual read */
char *filename; /* -> Input file name */
int infd = -1; /* Input file descriptor */
DEVMAP_CTLR controller; /* Controller record */
DEVMAP_DEV device; /* Device record */
char output_type[5]; /* Device type to print */
char *output_filename; /* -> filename to print */
int more_devices; /* More devices this ctlr? */
char pathname[MAX_PATH]; /* file path in host format */
INITIALIZE_UTILITY( UTILITY_NAME, UTILITY_DESC, &pgm );
/* The only argument is the DEVMAP file name */
if (argc == 2 && argv[1] != NULL)
{
filename = argv[1];
}
else
{
// "Usage: ..."
WRMSG( HHC02645, "I", pgm );
exit (1);
}
/* Open the devmap file */
hostpath(pathname, filename, sizeof(pathname));
infd = HOPEN (pathname, O_RDONLY | O_BINARY);
if (infd < 0)
{
// "Error opening %s: %s"
FWRMSG( stderr, HHC02646, "E", filename, strerror( errno ));
exit (2);
}
/* Skip the file header */
for (i = 0; i < 9; i++)
{
len = read (infd, (void *)&controller, sizeof(DEVMAP_CTLR));
if (len < 0)
{
// "Error reading %s record%s from %s: %s"
FWRMSG( stderr, HHC02647, "E", "header", "s", filename, strerror( errno ));
exit (3);
}
}
/* Read records from the input file and convert them */
while (1)
{
/* Read a controller record. */
len = read (infd, (void *)&controller, sizeof(DEVMAP_CTLR));
if (len < 0)
{
// "Error reading %s record%s from %s: %s"
FWRMSG( stderr, HHC02647, "E", "controller", "", filename, strerror( errno ));
exit (4);
}
/* Did we finish too soon? */
if ((len > 0) && (len < (int)sizeof(DEVMAP_CTLR)))
{
// "Incomplete %s record on %s"
FWRMSG( stderr, HHC02648, "E", "controller", filename );
exit(5);
}
/* Check for end of file. */
if (len == 0)
{
// "End of input file."
FWRMSG( stderr, HHC02649, "E" );
break;
}
/* Read devices on this controller. */
more_devices = 1;
while (more_devices)
{
/* Read a device record. */
len = read (infd, (void *)&device, sizeof(DEVMAP_DEV));
if (len < 0)
{
// "Error reading %s record%s from %s: %s"
FWRMSG( stderr, HHC02647, "E", "device", "", filename, strerror( errno ));
exit (6);
}
/* Did we finish too soon? */
if ((len > 0) && (len < (int)sizeof(DEVMAP_DEV)))
{
// "Incomplete %s record on %s"
FWRMSG( stderr, HHC02648, "E", "device", filename );
exit(7);
}
/* Check for end of file. */
if (len == 0)
{
// Premature end of input file"
FWRMSG( stderr, HHC02650, "E" );
exit(8);
}
/* Is this the dummy device record at the end of the controller's
set of devices? */
if (strncmp(device.type," ",4) == 0)
{
more_devices = 0;
break;
}
/* It's a real device. Fix the type so Hercules can use it and
locate the output filename. */
STRLCPY( output_type, device.type );
if (isprint((unsigned char)device.parms.disk.volser[0]))
output_filename = device.parms.disk.filename;
else output_filename = device.parms.other.filename;
if (strncmp(device.type, "3278", 4) == 0)
{
STRLCPY( output_type, "3270" );
output_filename = "";
}
if (strncmp(device.type, "2540", 4) == 0)
STRLCPY( output_type, "3505" );
/* Emit the Hercules config file entry. */
len = (int) strlen( output_filename );
printf("%02X%02X %s%s%s\n",
device.highaddr,
device.lowaddr,
output_type,
len ? " " : "",
len ? output_filename : ""
);
} /* end while more_devices) */
} /* end while (1) */
/* Close files and exit */
close (infd);
return 0;
} /* end function main */