mirror of
https://github.com/open-simh/simtools.git
synced 2026-01-21 10:13:04 +00:00
Include large file support in SHOW VERSION, work on memory leaks, bufs
Show version includes the other configuration info, including READLINE and ASPI. Fix a memory leak in Unix show devices. Start using valgrind. Add VLD support for Windows. Fix memory leaks in main command processing. add command line arguments to history if USEing_READLINE Add atexit() and rundown support to dismount volumes at exit. Update makefiles for READLINE - some versions require you to link with termcap or ncurses as well. Fix memory leak in set default (including implicit set default on mount) Free WCCFILE on search NAM$M_SYNCHK as VMS does. Also release when returning RMS$_NMF. Add nam$l_rlf field to NAM Implement show devices for VMS. When reusing a WCB for large file, ensure that the file header pointer is valid. Add show cwd so it's easy to find out default for local files. Add set cwd Add spawn cmd so it's easy to inspect copied files. Handle condition codes properly. Finish sysmsg. Add standard macros to stsdef.h Deal with strerror on windows.
This commit is contained in:
parent
57049f51b3
commit
5f00f5b509
3
extracters/ods2/.valgrindrc
Normal file
3
extracters/ods2/.valgrindrc
Normal file
@ -0,0 +1,3 @@
|
||||
--memcheck:leak-check=yes
|
||||
--suppressions=valgrind_suppressions_readline
|
||||
--suppressions=valgrind_suppressions_ods2
|
||||
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
@ -12,15 +12,18 @@
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{BCCEAED2-1732-D796-1F70-040DE5DA42AD}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
@ -43,10 +46,10 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>DEBUG_BUILD;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions> HOME_SKIP=1 ;HOME_LOG;USE_VLD;DEBUG_BUILD;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<Optimization>Disabled</Optimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@ -98,6 +101,7 @@
|
||||
<Command>copy $(OutDir)$(TargetName)$(TargetExt) $(SolutionDir)$(TargetName)$(TargetExt) </Command>
|
||||
<Outputs>$(SolutionDir)$(TargetName)$(TargetExt)</Outputs>
|
||||
<Message>Copying $(TargetName)$(TargetExt)</Message>
|
||||
<Inputs>$(OutDir)$(TargetName)$(TargetExt) </Inputs>
|
||||
</CustomBuildStep>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@ -51,6 +51,15 @@ struct WCBKEY {
|
||||
struct WCB *prevwcb;
|
||||
};
|
||||
|
||||
#if 0
|
||||
static unsigned int delta_from_name( const char *diskname );
|
||||
#endif
|
||||
static unsigned int delta_from_index( size_t index );
|
||||
static unsigned int compute_delta( unsigned long sectorsize,
|
||||
unsigned long sectors,
|
||||
unsigned long tracks,
|
||||
unsigned long cylinders );
|
||||
|
||||
unsigned deallocfile(struct FCB *fcb); /* Update.c */
|
||||
#define DEBUGx
|
||||
|
||||
@ -287,6 +296,7 @@ static void *wcb_create( unsigned hashval, void *keyval, unsigned *retsts ) {
|
||||
curvbn = wcbkey->prevwcb->hd_basevbn;
|
||||
wcb->hd_seg_num = wcbkey->prevwcb->hd_seg_num;
|
||||
memcpy(&wcb->hd_fid,&wcbkey->prevwcb->hd_fid,sizeof(struct fiddef));
|
||||
head = wcbkey->fcb->head;
|
||||
}
|
||||
while (TRUE) {
|
||||
register unsigned short *mp;
|
||||
@ -825,15 +835,28 @@ unsigned dismount(struct VCB * vcb)
|
||||
/******************************************************************** mount() */
|
||||
|
||||
#ifdef DEBUG
|
||||
#define HOME_LIMIT 5
|
||||
#ifndef HOME_SKIP
|
||||
#define HOME_SKIP 1
|
||||
#endif
|
||||
#ifndef HOME_LIMIT
|
||||
#define HOME_LIMIT 3
|
||||
#endif
|
||||
#else
|
||||
#define HOME_LIMIT 100
|
||||
#ifndef HOME_SKIP
|
||||
#define HOME_SKIP 0
|
||||
#endif
|
||||
#ifndef HOME_LIMIT
|
||||
#define HOME_LIMIT 1000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* mount() make disk volume available for processing... */
|
||||
|
||||
unsigned mount(unsigned flags,unsigned devices,char *devnam[],char *label[],
|
||||
struct VCB **retvcb) {
|
||||
unsigned mount( unsigned flags,
|
||||
unsigned devices,
|
||||
char *devnam[],
|
||||
char *label[],
|
||||
struct VCB **retvcb ) {
|
||||
register unsigned device,sts = 0;
|
||||
struct VCB *vcb;
|
||||
struct VCBDEV *vcbdev;
|
||||
@ -842,13 +865,21 @@ unsigned mount(unsigned flags,unsigned devices,char *devnam[],char *label[],
|
||||
#ifdef DEBUG
|
||||
if (sizeof(struct HOME) != 512 || sizeof(struct HEAD) != 512) return SS$_NOTINSTALL;
|
||||
#endif
|
||||
vcb = (struct VCB *) calloc(1, sizeof(struct VCB) + (devices - 1) * sizeof(struct VCBDEV));
|
||||
if (vcb == NULL) return SS$_INSFMEM;
|
||||
if( retvcb )
|
||||
*retvcb = NULL;
|
||||
|
||||
vcb = (struct VCB *) calloc( 1, sizeof(struct VCB) +
|
||||
((devices - 1) * sizeof(struct VCBDEV)) );
|
||||
if( vcb == NULL )
|
||||
return SS$_INSFMEM;
|
||||
|
||||
vcb->status = 0;
|
||||
if (flags & MOU_WRITE) vcb->status |= VCB_WRITE;
|
||||
if( flags & MOU_WRITE )
|
||||
vcb->status |= VCB_WRITE;
|
||||
vcb->fcb = NULL;
|
||||
vcb->dircache = NULL;
|
||||
vcb->devices = 0;
|
||||
|
||||
vcbdev = vcb->vcbdev;
|
||||
for( device = 0; device < devices; device++, vcbdev++ ) {
|
||||
char *dname;
|
||||
@ -857,9 +888,12 @@ unsigned mount(unsigned flags,unsigned devices,char *devnam[],char *label[],
|
||||
sts = SS$_NOSUCHVOL;
|
||||
vcbdev->dev = NULL;
|
||||
if (strlen(dname)) { /* Really want to allow skipping volumes? */
|
||||
unsigned int hba;
|
||||
unsigned int hba, delta, homtry;
|
||||
|
||||
if( label[device] != NULL && strlen(label[device]) > sizeof( volsetSYS[0].vsr$t_label ) ) {
|
||||
if( label[device] != NULL && strlen(label[device]) >
|
||||
sizeof( volsetSYS[0].vsr$t_label ) ) {
|
||||
printf( "%%ODS2-E-BADPARAM, Label %s is too long\n",
|
||||
label[device] );
|
||||
sts = SS$_BADPARAM;
|
||||
break;
|
||||
}
|
||||
@ -876,35 +910,44 @@ unsigned mount(unsigned flags,unsigned devices,char *devnam[],char *label[],
|
||||
break;
|
||||
}
|
||||
}
|
||||
vcb->devices++;
|
||||
sts = device_lookup( strlen( dname ), dname, TRUE,
|
||||
&vcbdev->dev );
|
||||
if ( !( sts & STS$M_SUCCESS ) ) break;
|
||||
if( !(sts & STS$M_SUCCESS) )
|
||||
break;
|
||||
vcbdev->dev->access = flags; /* Requested mount options */
|
||||
/* (e.g., /Write) */
|
||||
sts = phyio_init( vcbdev->dev );
|
||||
if ( !( sts & STS$M_SUCCESS ) ) break;
|
||||
vcb->devices++;
|
||||
if( !(sts & STS$M_SUCCESS) )
|
||||
break;
|
||||
if (vcbdev->dev->vcb != NULL) {
|
||||
sts = SS$_DEVMOUNT;
|
||||
break;
|
||||
}
|
||||
for (hba = 1; hba <= HOME_LIMIT; hba++) {
|
||||
delta = delta_from_index( (vcbdev->dev->access & MOU_DEVTYPE) >> MOU_V_DEVTYPE );
|
||||
|
||||
for( hba = 1, homtry = 0; homtry < HOME_LIMIT; homtry++, hba += delta ) {
|
||||
struct HOME *hom;
|
||||
|
||||
#if HOME_SKIP > 100
|
||||
if( homtry < HOME_SKIP )
|
||||
continue;
|
||||
#endif
|
||||
sts = phyio_read( vcbdev->dev, hba, sizeof( struct HOME ),
|
||||
(char *) &vcbdev->home );
|
||||
if (!(sts & STS$M_SUCCESS)) break;
|
||||
hom = &vcbdev->home;
|
||||
#ifdef DEBUG
|
||||
printf( "--->mount(): LBA=%u, HM2$L_HOMELBN=%u, "
|
||||
#if defined( DEBUG ) || defined( HOME_LOG )
|
||||
printf( "--->mount(%u): LBA=%u, HM2$L_HOMELBN=%u, "
|
||||
"HM2$L_ALHOMELBN=%u, "
|
||||
"HM2$T_FORMAT=\"%12.12s\", memcmp()=%u\n",
|
||||
hba, VMSLONG( hom->hm2$l_homelbn ),
|
||||
homtry+1,hba, VMSLONG( hom->hm2$l_homelbn ),
|
||||
VMSLONG( hom->hm2$l_alhomelbn ),
|
||||
hom->hm2$t_format,
|
||||
memcmp( hom->hm2$t_format, "DECFILE11B ", 12 )
|
||||
);
|
||||
#endif
|
||||
if( (hba == VMSLONG(hom->hm2$l_homelbn) ||
|
||||
hba == VMSLONG(hom->hm2$l_alhomelbn)) &&
|
||||
if( (hba == VMSLONG(hom->hm2$l_homelbn)) &&
|
||||
(VMSLONG(hom->hm2$l_alhomelbn) != 0) &&
|
||||
(VMSLONG(hom->hm2$l_altidxlbn) != 0) &&
|
||||
(VMSWORD(hom->hm2$w_homevbn) != 0) &&
|
||||
@ -919,7 +962,7 @@ unsigned mount(unsigned flags,unsigned devices,char *devnam[],char *label[],
|
||||
(memcmp(hom->hm2$t_format,"DECFILE11B ",12) == 0) ) {
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
#if defined( DEBUG ) || defined( HOME_LOG )
|
||||
printf( "--->mount(): Home block validation failure\n" );
|
||||
printf( "(VMSLONG(hom->hm2$l_alhomelbn) != 0) %u\n", (VMSLONG(hom->hm2$l_alhomelbn) != 0) );
|
||||
printf( "(VMSLONG(hom->hm2$l_altidxlbn) != 0) %u\n", (VMSLONG(hom->hm2$l_altidxlbn) != 0) );
|
||||
@ -1102,7 +1145,11 @@ unsigned mount(unsigned flags,unsigned devices,char *devnam[],char *label[],
|
||||
if( !(sts & 1) ) {
|
||||
vcbdev = vcb->vcbdev;
|
||||
for( device = 0; device < devices; device++, vcbdev++ ) {
|
||||
if (vcbdev->dev == NULL) continue;
|
||||
if (vcbdev->dev == NULL) {
|
||||
if( flags & MOU_VIRTUAL )
|
||||
virt_device( devnam[device], NULL );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( vcb->status & VCB_WRITE && vcbdev->mapfcb != NULL ) {
|
||||
/* sts = */
|
||||
@ -1127,6 +1174,11 @@ unsigned mount(unsigned flags,unsigned devices,char *devnam[],char *label[],
|
||||
} else { /* *** DECREF *** */
|
||||
vcbdev = vcb->vcbdev;
|
||||
for( device = 0; device < vcb->devices; device++, vcbdev++ ) {
|
||||
if (vcbdev->dev == NULL) {
|
||||
if( flags & MOU_VIRTUAL )
|
||||
virt_device( devnam[device], NULL );
|
||||
continue;
|
||||
}
|
||||
phyio_done( vcbdev->dev );
|
||||
}
|
||||
free(vcb);
|
||||
@ -1314,3 +1366,198 @@ void show_volumes( void ) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************** acccess_rundown() */
|
||||
void access_rundown( void ) {
|
||||
struct VCB *vcb, *next;
|
||||
unsigned sts;
|
||||
|
||||
for( vcb = vcb_list; vcb != NULL; vcb = next ) {
|
||||
next = vcb->next;
|
||||
|
||||
sts = dismount( vcb );
|
||||
if( !(sts & STS$M_SUCCESS) ) {
|
||||
printf( "Dismount failed in rundown: %s", getmsg(sts, MSG_TEXT) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************** compute_delta() */
|
||||
/*
|
||||
* The search delta is computed from the
|
||||
* volume geometry, expressed in sectors, tracks (surfaces), and
|
||||
* cylinders, according to the following rules, to handle the cases where
|
||||
* one or two dimensions of the volume have a size of 1.
|
||||
*
|
||||
* Geometry: Delta
|
||||
*
|
||||
* s x 1 x 1: 1 Rule 1
|
||||
* 1 x t x 1: 1 Rule 2
|
||||
* 1 x 1 x c: 1 Rule 3
|
||||
*
|
||||
* s x t x 1: s+1 Rule 4
|
||||
* s x 1 x c: s+1 Rule 5
|
||||
* 1 x t x c: t+1 Rule 6
|
||||
*
|
||||
* s x t x c: (t+1)*s+1 Rule 7
|
||||
*/
|
||||
|
||||
|
||||
#define DISK( name, sectors, tracks, cylinders ) \
|
||||
{#name, 512 ## ul, sectors ## ul, tracks ## ul, cylinders ## ul},
|
||||
#define DISKS( name, sectorsize, sectors, tracks, cylinders ) \
|
||||
{#name, sectorsize ## ul, sectors ## ul, tracks ## ul, cylinders ## ul},
|
||||
struct disktype disktype[] = {
|
||||
DISK(UNKNOWN, 1, 1, 1) /* First = short sequence delta = 1 */
|
||||
DISK(RK05, 12, 2, 203)
|
||||
DISK(RK06, 22, 3, 411)
|
||||
DISK(RK07, 22, 3, 815)
|
||||
DISK(RK11, 12, 2, 203)
|
||||
|
||||
DISK(RL01, 40, 2, 256)
|
||||
DISK(RL02, 40, 2, 512)
|
||||
|
||||
DISK(RM02, 32, 5, 823)
|
||||
DISK(RM03, 32, 5, 823)
|
||||
DISK(RP04, 22, 19, 411)
|
||||
DISK(RP05, 22, 19, 411)
|
||||
DISK(RM80, 31, 14, 559)
|
||||
DISK(RP06, 22, 19, 815)
|
||||
DISK(RM05, 32, 19, 823)
|
||||
DISK(RP07, 50, 32, 630)
|
||||
|
||||
#if 0 /* Not useful now as RSX20-F used ODS-1 */
|
||||
DISKS(RM02-T, 576, 30, 5, 823)
|
||||
DISKS(RM03-T, 576, 30, 5, 823)
|
||||
DISKS(RP04-T, 576, 20, 19, 411)
|
||||
DISKS(RP05-T, 576, 20, 19, 411)
|
||||
DISKS(RM80-T, 576, 30, 14, 559)
|
||||
DISKS(RP06-T, 576, 20, 19, 815)
|
||||
DISKS(RM05-T, 576, 30, 19, 823)
|
||||
DISKS(RP07-T, 576, 43, 32, 630)
|
||||
#endif
|
||||
|
||||
DISK(RX50, 10, 1, 80)
|
||||
DISK(RX33, 15, 2, 80)
|
||||
|
||||
#if 0
|
||||
DISK(RD50, 99, 99, 9999)
|
||||
#endif
|
||||
DISK(RD51, 18, 4, 306)
|
||||
DISK(RD31, 17, 4, 615)
|
||||
DISK(RD52, 17, 8, 512)
|
||||
DISK(RD53, 17, 7, 1024)
|
||||
DISK(RD54, 17, 15, 1225)
|
||||
|
||||
DISK(RA72, 51, 20, 1921)
|
||||
|
||||
#if 0
|
||||
DISK(RA80, 99, 99, 9999)
|
||||
|
||||
#endif
|
||||
DISK(RA81, 51, 14, 1258)
|
||||
DISK(RA82, 57, 15, 1435)
|
||||
|
||||
DISK(RA90, 69, 13, 2649)
|
||||
DISK(RA92, 73, 13, 3099)
|
||||
|
||||
DISK(RRD40,128, 1, 10400)
|
||||
DISK(RRD50,128, 1, 10400)
|
||||
DISKS(RX01, 128, 26, 1, 77)
|
||||
DISKS(RX02, 256, 26, 1, 77)
|
||||
|
||||
#if 0
|
||||
DISK(RX23-SD, 99, 99, 9999)
|
||||
DISK(RX23-DD, 99, 99, 9999)
|
||||
|
||||
DISK(RX33-SD, 10, 1, 80)
|
||||
DISK(RX33-DD, 99, 99, 9999)
|
||||
#endif
|
||||
|
||||
DISK(RX50, 10, 1, 80)
|
||||
#if 0
|
||||
DISK(RC25, 99, 99, 9999 )
|
||||
|
||||
DISK(RF30, 99, 99, 9999 )
|
||||
DISK(RF31, 99, 99, 9999 )
|
||||
DISK(RF35, 99, 99, 9999 )
|
||||
DISK(RF36, 99, 99, 9999 )
|
||||
DISK(RF71, 99, 99, 9999 )
|
||||
DISK(RF72, 99, 99, 9999 )
|
||||
DISK(RF73, 99, 99, 9999 )
|
||||
DISK(RF74, 99, 99, 9999 )
|
||||
|
||||
DISK(RZ22, 99, 99, 9999 )
|
||||
DISK(RZ23, 99, 99, 9999 )
|
||||
DISK(RZ24, 99, 99, 9999 )
|
||||
DISK(RZ25, 99, 99, 9999 )
|
||||
DISK(RZ26, 99, 99, 9999 )
|
||||
DISK(RZ27, 99, 99, 9999 )
|
||||
DISK(RZ28, 99, 99, 9999 )
|
||||
DISK(RZ29, 99, 99, 9999 )
|
||||
DISK(RZ31, 99, 99, 9999 )
|
||||
DISK(RZ33, 99, 99, 9999 )
|
||||
DISK(RZ35, 99, 99, 9999 )
|
||||
DISK(RZ55, 99, 99, 9999 )
|
||||
DISK(RZ56, 99, 99, 9999 )
|
||||
DISK(RZ57, 99, 99, 9999 )
|
||||
DISK(RZ58, 99, 99, 9999 )
|
||||
DISK(RZ59, 99, 99, 9999 )
|
||||
|
||||
DISK(RZ72, 99, 99, 9999 )
|
||||
DISK(RZ73, 99, 99, 9999 )
|
||||
DISK(RZ74, 99, 99, 9999 )
|
||||
#endif
|
||||
|
||||
{ NULL, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
static unsigned int compute_delta( unsigned long sectorsize,
|
||||
unsigned long sectors,
|
||||
unsigned long tracks,
|
||||
unsigned long cylinders ) {
|
||||
|
||||
if( sectorsize < 512 )
|
||||
sectors = (sectorsize * sectors) / 512;
|
||||
|
||||
if( sectors > 1 && tracks > 1 && cylinders > 1 ) /* Rule 7 */
|
||||
return (tracks + 1) * sectors +1;
|
||||
|
||||
if( (sectors > 1 && tracks > 1 && cylinders == 1 ) || /* Rule 4 */
|
||||
(sectors > 1 && tracks == 1 && cylinders > 1 ) ) /* Rule 5 */
|
||||
return sectors + 1;
|
||||
|
||||
if( sectors == 1 && tracks > 1 && cylinders > 1 ) /* Rule 6 */
|
||||
return tracks + 1;
|
||||
|
||||
return 1; /* Rules 1-3 */
|
||||
}
|
||||
|
||||
#if 0
|
||||
static unsigned int delta_from_name( const char *diskname ) {
|
||||
struct disktype *dp;
|
||||
|
||||
for( dp = disktype; dp->name != NULL; dp++ ) {
|
||||
if( !strcmp( dp->name, diskname ) )
|
||||
return compute_delta( dp->sectorsize, dp->sectors, dp->tracks, dp->cylinders );
|
||||
}
|
||||
|
||||
return ~0u;
|
||||
}
|
||||
#endif
|
||||
static unsigned int delta_from_index( size_t index ) {
|
||||
struct disktype *dp;
|
||||
unsigned int delta;
|
||||
|
||||
if( index >= sizeof(disktype)/sizeof(disktype[0]) )
|
||||
abort();
|
||||
dp = disktype + index;
|
||||
delta = compute_delta( dp->sectorsize, dp->sectors, dp->tracks, dp->cylinders );
|
||||
|
||||
#if defined( DEBUG ) || HOME_SKIP > 0
|
||||
printf( "HOM search index for %s is %u\n", dp->name, delta );
|
||||
#endif
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
@ -256,6 +256,13 @@ struct VCB {
|
||||
extern struct VCB *vcb_list;
|
||||
void show_volumes( void );
|
||||
|
||||
struct disktype {
|
||||
const char *name;
|
||||
unsigned long sectorsize, sectors, tracks, cylinders;
|
||||
};
|
||||
|
||||
extern struct disktype disktype[];
|
||||
|
||||
/* RVN_TO_DEV( vcb, rvn ) - returns device from relative volume number */
|
||||
|
||||
/* returns NULL if RVN illegal or device not mounted */
|
||||
@ -289,4 +296,6 @@ unsigned update_create(struct VCB *vcb,struct fiddef *did,char *filename,
|
||||
unsigned update_extend(struct FCB *fcb,unsigned blocks,unsigned contig);
|
||||
vmsword checksum( vmsword *block );
|
||||
|
||||
void access_rundown( void );
|
||||
|
||||
#endif /* # ifndef _ACCESS_H */
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
*
|
||||
* Microsoft deprecates sprintf, but doesn't supply standard
|
||||
* replacement until very recent IDEs.
|
||||
* Microsoft doesn't like fopen.
|
||||
* Microsoft doesn't like fopen, or strerror, or getcwd.
|
||||
* One needs to use a M$ call to translate system errors.
|
||||
*
|
||||
* Finding out about drive letter assignments is unique to windows.
|
||||
@ -18,12 +18,14 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
|
||||
int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
|
||||
{
|
||||
/******************************************************************* c99_vsnprintf() */
|
||||
|
||||
int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) {
|
||||
int count = -1;
|
||||
|
||||
if (size != 0)
|
||||
@ -34,8 +36,9 @@ int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
|
||||
return count;
|
||||
}
|
||||
|
||||
int c99_snprintf(char *outBuf, size_t size, const char *format, ...)
|
||||
{
|
||||
/******************************************************************* c99_snprintf() */
|
||||
|
||||
int c99_snprintf(char *outBuf, size_t size, const char *format, ...) {
|
||||
int count;
|
||||
va_list ap;
|
||||
|
||||
@ -49,6 +52,8 @@ int c99_snprintf(char *outBuf, size_t size, const char *format, ...)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
/******************************************************************* openf() */
|
||||
|
||||
FILE *openf( const char *filename, const char *mode ) {
|
||||
errno_t err;
|
||||
FILE *fd = NULL;
|
||||
@ -63,11 +68,24 @@ FILE *openf( const char *filename, const char *mode ) {
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/******************************************************************* ods2_strerror() */
|
||||
|
||||
const char *ods2_strerror( int errn ) {
|
||||
static char buf[256];
|
||||
|
||||
if( strerror_s( buf, sizeof( buf ), errn ) != 0 )
|
||||
snprintf( buf, sizeof( buf ), "Untranslatable error %u", errn );
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/******************************************************************* w32_errstr() */
|
||||
|
||||
TCHAR *w32_errstr( DWORD eno, ... ) {
|
||||
va_list ap;
|
||||
TCHAR *msg;
|
||||
|
||||
if( eno == 0 )
|
||||
if( eno == NO_ERROR )
|
||||
eno = GetLastError();
|
||||
va_start(ap,eno);
|
||||
|
||||
@ -81,6 +99,8 @@ TCHAR *w32_errstr( DWORD eno, ... ) {
|
||||
return msg;
|
||||
}
|
||||
|
||||
/******************************************************************* driveFromLetter() */
|
||||
|
||||
char *driveFromLetter( const char *letter ) {
|
||||
DWORD rv = ERROR_INSUFFICIENT_BUFFER;
|
||||
size_t cs = 16;
|
||||
|
||||
@ -20,11 +20,24 @@ FILE *openf( const char *filename, const char *mode );
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#undef getcwd
|
||||
#define getcwd _getcwd
|
||||
#undef chdir
|
||||
#define chdir _chdir
|
||||
|
||||
#undef strerror
|
||||
#define strerror(n) ods2_strerror(n)
|
||||
const char *ods2_strerror( errno_t errn );
|
||||
|
||||
TCHAR *w32_errstr( DWORD eno, ... );
|
||||
char *driveFromLetter( const char *letter );
|
||||
|
||||
#else /* Not WIN32 */
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
@ -7,7 +7,7 @@ CC=gcc
|
||||
CCFLAGS = -O4 -g
|
||||
|
||||
DEFS = -DUSE_READLINE
|
||||
LDFLAGS = -lreadline
|
||||
LDFLAGS = -lreadline -ltermcap
|
||||
|
||||
# Object file extension
|
||||
OBJ = .o
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
CCFLAGS = -O4 -g
|
||||
|
||||
# DEFS = -DUSE_READLINE
|
||||
# LDFLAGS = -lreadline
|
||||
# LDFLAGS = -lreadline -ltermcap
|
||||
|
||||
# Object file extension
|
||||
OBJ = .o
|
||||
|
||||
@ -9,7 +9,7 @@ CCFLAGS = -O4 -g
|
||||
# Include readline support
|
||||
|
||||
DEFS = -DUSE_READLINE
|
||||
LDFLAGS = -lreadline
|
||||
LDFLAGS = -lreadline -ltermcap
|
||||
|
||||
# Object file extension
|
||||
OBJ = .o
|
||||
|
||||
@ -104,32 +104,38 @@
|
||||
#define _BSD_SOURCE
|
||||
#include <ctype.h> /* isalpha(), isspace(), tolower() */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "version.h"
|
||||
#include "compat.h"
|
||||
#include "sysmsg.h"
|
||||
#include "phyio.h"
|
||||
#include "phyvirt.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
#include "version.h"
|
||||
|
||||
#include "access.h"
|
||||
#include "compat.h"
|
||||
#include "descrip.h"
|
||||
#include "device.h"
|
||||
#include "direct.h"
|
||||
#include "ods2.h"
|
||||
#include "phyio.h"
|
||||
#include "phyvirt.h"
|
||||
#include "rms.h"
|
||||
#include "ssdef.h"
|
||||
#include "stsdef.h"
|
||||
#include "sysmsg.h"
|
||||
|
||||
#if !defined( _WIN32 ) && !defined( VMS )
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#else
|
||||
# ifdef _WIN32
|
||||
# include <process.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef VMS
|
||||
#include <starlet.h>
|
||||
|
||||
#else
|
||||
#include "vmstime.h"
|
||||
#endif
|
||||
@ -148,6 +154,14 @@
|
||||
#define FALSE ( 0 != 0 )
|
||||
#endif
|
||||
|
||||
#if defined( _WIN32 ) && defined(_MSC_VER) && defined( DEBUG_BUILD ) && defined( USE_VLD )
|
||||
/* Normally done in the project file, but VLD is optional and I'd rather not provide
|
||||
* instructions as they vary by IDE version. See http://vld.codeplex.com/ if interested.
|
||||
*/
|
||||
#include "C:\\Program Files (x86)\\Visual Leak Detector\\include\\vld.h"
|
||||
#pragma comment (lib,"C:\\Program Files (x86)\\Visual Leak Detector\\lib\\Win32\\vld.lib")
|
||||
#endif
|
||||
|
||||
#define MAXREC 32767
|
||||
#define PRINT_ATTR ( FAB$M_CR | FAB$M_PRN | FAB$M_FTN )
|
||||
|
||||
@ -158,6 +172,7 @@
|
||||
#include <readline/history.h>
|
||||
#endif
|
||||
|
||||
/******************************************************************* fgetline() */
|
||||
/* Read a line of input - unlimited length
|
||||
* Removes \n, returns NULL at EOF
|
||||
* Caller responsible for free()
|
||||
@ -170,7 +185,7 @@ static char *fgetline( FILE *stream, int keepnl ) {
|
||||
int c;
|
||||
|
||||
while( (c = fgetc(stream)) != EOF && c != '\n' ) {
|
||||
if( idx + (keepnl != 0) +1 > bufsize ) { /* Allow space for char + (optional \n) + \0 */
|
||||
if( idx + (keepnl != 0) +2 > bufsize ) { /* In buf + char + (optional \n) + \0 */
|
||||
char *nbuf;
|
||||
bufsize += xpnsize;
|
||||
nbuf = (char *) realloc( buf, bufsize );
|
||||
@ -202,11 +217,12 @@ static char *fgetline( FILE *stream, int keepnl ) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
/******************************************************************* keycomp() */
|
||||
/* keycomp: routine to compare parameter to a keyword - case insensitive! */
|
||||
|
||||
static int keycomp(const char *param, const char *keywrd) {
|
||||
while (*param != '\0') {
|
||||
if (tolower(*param++) != *keywrd++) return 0;
|
||||
if( tolower(*param++) != tolower(*keywrd++) ) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -217,11 +233,12 @@ static int keycomp(const char *param, const char *keywrd) {
|
||||
*/
|
||||
#define NV NOVAL, NULL
|
||||
#define KV(list) KEYVAL, list
|
||||
#define CV(list) KEYCOL, list
|
||||
struct qual {
|
||||
const char *name;
|
||||
int set;
|
||||
int clear;
|
||||
enum qualtype { NOVAL, KEYVAL } qtype;
|
||||
enum qualtype { NOVAL, KEYVAL, KEYCOL } qtype;
|
||||
void *arg;
|
||||
const char *helpstr;
|
||||
};
|
||||
@ -261,6 +278,7 @@ static void qualhelp( int par, struct qual *qtable );
|
||||
static int vms_qual = 1;
|
||||
static int verify_cmd = 1;
|
||||
|
||||
/******************************************************************* checkquals() */
|
||||
/* checkquals: Given valid qualifier definitions, process qualifer
|
||||
* list from a command left to right. Also handles parameters and
|
||||
* qualifier values (/Qual=value).
|
||||
@ -322,6 +340,7 @@ static int checkquals(int result, struct qual qualset[],int qualc,char *qualv[])
|
||||
*nvp++ = '\0';
|
||||
switch( qp->qtype ) {
|
||||
case KEYVAL:
|
||||
case KEYCOL:
|
||||
result = checkquals( result, (struct qual *)qp->arg, -1, &qv );
|
||||
if( result == -1 )
|
||||
return result;
|
||||
@ -336,6 +355,9 @@ static int checkquals(int result, struct qual qualset[],int qualc,char *qualv[])
|
||||
return result;
|
||||
}
|
||||
|
||||
/******************************************************************* dodir() */
|
||||
/*********************************************************** prvmstime() */
|
||||
|
||||
static int prvmstime(VMSTIME vtime, const char *sfx) {
|
||||
int sts = 0;
|
||||
char tim[24];
|
||||
@ -358,6 +380,8 @@ static int prvmstime(VMSTIME vtime, const char *sfx) {
|
||||
return sts;
|
||||
}
|
||||
|
||||
/*********************************************************** pwrap() */
|
||||
|
||||
static void pwrap( int *pos, const char *fmt, ... ) {
|
||||
char pbuf[200], *p, *q;
|
||||
va_list ap;
|
||||
@ -392,6 +416,7 @@ static void pwrap( int *pos, const char *fmt, ... ) {
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************** dirtotal() */
|
||||
|
||||
#define dir_extra (dir_date | dir_fileid | dir_owner | dir_prot | dir_size)
|
||||
#define dir_date (1 << 0)
|
||||
@ -486,6 +511,8 @@ static void dirtotal( int options, int size, int alloc ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/************************************************************ dodir() */
|
||||
|
||||
static unsigned dodir(int argc,char *argv[],int qualc,char *qualv[]) {
|
||||
char res[NAM$C_MAXRSS + 1],rsa[NAM$C_MAXRSS + 1];
|
||||
int options;
|
||||
@ -1412,7 +1439,7 @@ static unsigned dostats( void ) {
|
||||
|
||||
/******************************************************************* doshow() */
|
||||
|
||||
/* show: version */
|
||||
/*********************************************************** show_version() */
|
||||
|
||||
#define MNAMEX(n) #n
|
||||
#define MNAME(n) MNAMEX(n)
|
||||
@ -1431,23 +1458,26 @@ static void show_version( void ) {
|
||||
# endif
|
||||
printf( " direct SCSI access support");
|
||||
#endif
|
||||
printf( "\n\n" );
|
||||
printf( "\n " );
|
||||
phyio_show( SHOW_FILE64 );
|
||||
putchar( '\n' );
|
||||
return;
|
||||
}
|
||||
|
||||
/* show: the show command */
|
||||
/*********************************************************** doshow() */
|
||||
|
||||
static struct qual showkwds[] = { {"default", 0, 0, NV, "Default directory"},
|
||||
{"devices", 1, 0, NV, "Devices"},
|
||||
{"qualifier_style", 2, 0, NV, "Qualifier style (Unix, VMS)" },
|
||||
{"statistics", 3, 0, NV, "Debugging statistics", },
|
||||
{"time", 4, 0, NV, "Time"},
|
||||
{"verify", 5, 0, NV, "Command file echo" },
|
||||
{"version", 6, 0, NV, "Version"},
|
||||
{"volumes", 7, 0, NV, "Mounted volume information" },
|
||||
static struct qual showkwds[] = { {"cwd", 0, 0, NV, "Working directory on local system"},
|
||||
{"default", 1, 0, NV, "Default directory on VMS volume"},
|
||||
{"devices", 2, 0, NV, "Devices"},
|
||||
{"qualifier_style", 3, 0, NV, "Qualifier style (Unix, VMS)" },
|
||||
{"statistics", 4, 0, NV, "Debugging statistics"},
|
||||
{"time", 5, 0, NV, "Time"},
|
||||
{"verify", 6, 0, NV, "Command file echo" },
|
||||
{"version", 7, 0, NV, "Version"},
|
||||
{"volumes", 8, 0, NV, "Mounted volume information" },
|
||||
{NULL, 0, 0, NV, NULL }
|
||||
};
|
||||
static struct param showpars[] = { {"item_name", REQ, KEYWD, PA(showkwds), NULL },
|
||||
static struct param showpars[] = { {"item_name", REQ, KEYWD, PA(showkwds), "" },
|
||||
{NULL, 0, 0, NOPA, NULL }
|
||||
};
|
||||
|
||||
@ -1463,6 +1493,29 @@ unsigned doshow(int argc,char *argv[],int qualc,char *qualv[]) {
|
||||
default:
|
||||
return SS$_BADPARAM;
|
||||
case 0: {
|
||||
size_t size = 32;
|
||||
char *buf = NULL;
|
||||
while( 1 ) {
|
||||
char *nbuf;
|
||||
nbuf = (char *)realloc( buf, size );
|
||||
if( nbuf == NULL ) {
|
||||
free( buf );
|
||||
return SS$_INSFMEM;
|
||||
}
|
||||
buf = nbuf;
|
||||
if( getcwd( buf, size ) != NULL )
|
||||
break;
|
||||
if( errno != ERANGE ) {
|
||||
perror( "getcwd" );
|
||||
return SS$_BADPARAM;
|
||||
}
|
||||
size *= 2;
|
||||
}
|
||||
printf( " Current working directory is %s\n", buf );
|
||||
free( buf );
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
case 1: {
|
||||
int sts;
|
||||
unsigned short curlen;
|
||||
char curdir[NAM$C_MAXRSS + 1];
|
||||
@ -1478,16 +1531,16 @@ unsigned doshow(int argc,char *argv[],int qualc,char *qualv[]) {
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
case 1:
|
||||
case 2:
|
||||
phyio_show( SHOW_DEVICES );
|
||||
virt_show( NULL );
|
||||
return SS$_NORMAL;
|
||||
case 2:
|
||||
case 3:
|
||||
printf ( " Qualifier style: %s\n", vms_qual? "/VMS": "-unix" );
|
||||
return SS$_NORMAL;
|
||||
case 3:
|
||||
case 4:
|
||||
return dostats();
|
||||
case 4: {
|
||||
case 5: {
|
||||
unsigned sts;
|
||||
char timstr[24];
|
||||
unsigned short timlen;
|
||||
@ -1504,56 +1557,66 @@ unsigned doshow(int argc,char *argv[],int qualc,char *qualv[]) {
|
||||
}
|
||||
}
|
||||
return SS$_NORMAL;
|
||||
case 5:
|
||||
case 6:
|
||||
printf( "Command file verification is %s\n", (verify_cmd? "on": "off") );
|
||||
return SS$_NORMAL;
|
||||
case 6:
|
||||
case 7:
|
||||
show_version();
|
||||
return SS$_NORMAL;
|
||||
case 7:
|
||||
case 8:
|
||||
show_volumes();
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
|
||||
/******************************************************************* setdef() */
|
||||
/******************************************************************* doset() */
|
||||
/*********************************************************** setdef() */
|
||||
|
||||
static unsigned setdef_count = 0;
|
||||
static int default_set = FALSE;
|
||||
|
||||
static unsigned setdef( char *newdef )
|
||||
{
|
||||
static unsigned setdef( char *newdef ) {
|
||||
register unsigned sts;
|
||||
struct dsc_descriptor defdsc;
|
||||
|
||||
defdsc.dsc_a_pointer = (char *) newdef;
|
||||
defdsc.dsc_w_length = strlen( defdsc.dsc_a_pointer );
|
||||
defdsc.dsc_w_length = (unsigned short)strlen( defdsc.dsc_a_pointer );
|
||||
sts = sys_setddir( &defdsc, NULL, NULL );
|
||||
if ( sts & STS$M_SUCCESS ) {
|
||||
setdef_count++;
|
||||
default_set = TRUE;
|
||||
} else {
|
||||
printf( "%%ODS2-E-SETDEF, Error %s setting default to %s\n", getmsg(sts, MSG_TEXT), newdef );
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
/******************************************************************** doset() */
|
||||
static unsigned setcwd( char *newdef ) {
|
||||
if( chdir( newdef ) != 0 ) {
|
||||
printf( "%%ODS2-W-SETDEF, Error %s setting cwd to %s\n",
|
||||
strerror( errno ), newdef );
|
||||
return SS$_BADPARAM;
|
||||
}
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
|
||||
/************************************************************ sethelp() */
|
||||
|
||||
static hlpfunc_t sethelp;
|
||||
|
||||
static struct qual setkwds[] = { {"default", 0, 0, NV, "Default directory"},
|
||||
static struct qual setkwds[] = { {"cwd", 0, 0, NV, "Working directory on local system"},
|
||||
{"directory_qualifiers", 1, 0, NV, "Default qualifiers for DIRECTORY command" },
|
||||
{"qualifier_style", 2, 0, NV, "Qualifier style (Unix, VMS)" },
|
||||
{"verify", 3, 0, NV, "-Display commands in indirect files" },
|
||||
{"noverify", 4, 0, NV, NULL },
|
||||
{"default", 2, 0, NV, "Default directory on VMS volume"},
|
||||
{"qualifier_style", 3, 0, NV, "Qualifier style (Unix, VMS)"},
|
||||
{"verify", 4, 0, NV, "-Display commands in indirect files"},
|
||||
{"noverify", 5, 0, NV, NULL },
|
||||
{NULL, 0, 0, NV, NULL }
|
||||
};
|
||||
static struct qual setqskwds[] = {{"unix", 1, 0, NV, "Unix style options, '-option'"},
|
||||
{"vms", 2, 0, NV, "VMS style qualifiers, '/qualifier'"},
|
||||
{NULL, 0, 0, NV, NULL }
|
||||
};
|
||||
static struct param setpars[] = { {"item_name", REQ, KEYWD, PA(setkwds), NULL },
|
||||
{"value" , CND, KEYWD, sethelp, setqskwds, NULL },
|
||||
static struct param setpars[] = { {"item_name", REQ, KEYWD, PA(setkwds), "" },
|
||||
{"value" , CND, KEYWD, sethelp, setqskwds, "" },
|
||||
{NULL, 0, 0, NOPA, NULL },
|
||||
};
|
||||
|
||||
@ -1575,21 +1638,25 @@ static const char * sethelp( struct CMDSET *cmd, struct param *p, int argc, char
|
||||
return NULL;
|
||||
switch( par ) {
|
||||
case 0:
|
||||
p->helpstr = "default directory on volume - ";
|
||||
p->ptype = VMSFS;
|
||||
p->helpstr = "working directory for local files";
|
||||
p->ptype = STRING;
|
||||
break;
|
||||
case 1:
|
||||
p->helpstr = "default directory on volume";
|
||||
p->ptype = VMSFS;
|
||||
break;
|
||||
case 2:
|
||||
p->helpstr = "directory qualifier name ";
|
||||
p->ptype = KEYWD;
|
||||
p->arg = dirquals;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
p->helpstr = "style ";
|
||||
p->ptype = KEYWD;
|
||||
p->arg = setqskwds;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
p->ptype = NONE;
|
||||
break;
|
||||
|
||||
@ -1599,6 +1666,8 @@ static const char * sethelp( struct CMDSET *cmd, struct param *p, int argc, char
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*********************************************************** doset() */
|
||||
|
||||
static unsigned doset(int argc,char *argv[],int qualc,char *qualv[]) {
|
||||
int parnum;
|
||||
|
||||
@ -1611,11 +1680,12 @@ static unsigned doset(int argc,char *argv[],int qualc,char *qualv[]) {
|
||||
default:
|
||||
return SS$_BADPARAM;
|
||||
case 0: /* default */
|
||||
case 2: /* current working directory */
|
||||
if( qualc ) {
|
||||
printf( "%%ODS2-E-NOQUAL, No qualifiers are permitted\n" );
|
||||
return 0;
|
||||
}
|
||||
return setdef( argv[2] );
|
||||
return (parnum == 0)? setdef( argv[2] ) : setcwd( argv[2] );
|
||||
case 1:{ /* directory_qualifiers */
|
||||
int options = checkquals(dir_default,dirquals,qualc,qualv);
|
||||
if( options == -1 )
|
||||
@ -1623,7 +1693,7 @@ static unsigned doset(int argc,char *argv[],int qualc,char *qualv[]) {
|
||||
dir_defopt = options;
|
||||
return 1;
|
||||
}
|
||||
case 2: { /* qualifier_style */
|
||||
case 3: { /* qualifier_style */
|
||||
int par = checkquals (0,setqskwds,1,argv+2);
|
||||
if( par == -1 )
|
||||
return SS$_BADPARAM;
|
||||
@ -1639,16 +1709,16 @@ static unsigned doset(int argc,char *argv[],int qualc,char *qualv[]) {
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
case 3:
|
||||
case 4:
|
||||
verify_cmd = 1;
|
||||
return 1;
|
||||
case 4:
|
||||
case 5:
|
||||
verify_cmd = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* The bits we need when we don't have real VMS routines underneath... */
|
||||
/******************************************************************* dodismount() */
|
||||
|
||||
static struct param dmopars[] = { {"drive_letter", REQ, STRING, NOPA, "Drive containing volume to dismount", },
|
||||
{NULL, 0, 0, NOPA, NULL }
|
||||
@ -1678,7 +1748,10 @@ unsigned dodismount(int argc,char *argv[],int qualc,char *qualv[]) {
|
||||
#error MOU_WRITE != 1
|
||||
#endif
|
||||
|
||||
static struct qual mouquals[] = { {"image", MOU_VIRTUAL, 0, NV, "Mount a disk image file", },
|
||||
#define DT_NAME "drive_type"
|
||||
|
||||
static struct qual mouquals[] = { {DT_NAME, 0, MOU_DEVTYPE, CV(NULL), "Drive type (DEC model name) "},
|
||||
{"image", MOU_VIRTUAL, 0, NV, "Mount a disk image file", },
|
||||
{"readonly", 0, MOU_WRITE, NV, "Only allow reading from volume"},
|
||||
{"virtual", MOU_VIRTUAL, 0, NV, NULL, },
|
||||
{"write", MOU_WRITE, 0, NV, "Allow writing to volume", },
|
||||
@ -1691,6 +1764,10 @@ static struct param moupars[] = { {"volumes", REQ, LIST, NOPA,
|
||||
{ NULL, 0, 0, NOPA, NULL }
|
||||
};
|
||||
|
||||
/******************************************************************* domount() */
|
||||
|
||||
/*********************************************************** parselist() */
|
||||
|
||||
static int parselist( char ***items, size_t min, char *arg, const char *label ) {
|
||||
size_t n = 0, i;
|
||||
char **list = NULL;
|
||||
@ -1737,7 +1814,9 @@ static int parselist( char ***items, size_t min, char *arg, const char *label )
|
||||
return (int)n;
|
||||
}
|
||||
|
||||
static unsigned domount(int argc,char *argv[],int qualc,char *qualv[]) {
|
||||
/*********************************************************** domount() */
|
||||
|
||||
static unsigned domount( int argc,char *argv[],int qualc,char *qualv[] ) {
|
||||
int sts = 1,devices = 0;
|
||||
char **devs = NULL, **labs = NULL;
|
||||
|
||||
@ -1760,7 +1839,7 @@ static unsigned domount(int argc,char *argv[],int qualc,char *qualv[]) {
|
||||
struct VCB *vcb;
|
||||
sts = mount( options | MOU_LOG, devices, devs, labs, &vcb );
|
||||
if (sts & STS$M_SUCCESS) {
|
||||
if (setdef_count == 0) {
|
||||
if( !default_set ) {
|
||||
char *colon, *buf;
|
||||
size_t len;
|
||||
|
||||
@ -1770,7 +1849,8 @@ static unsigned domount(int argc,char *argv[],int qualc,char *qualv[]) {
|
||||
perror( "malloc" );
|
||||
} else {
|
||||
colon = strchr( vcb->vcbdev[0].dev->devnam, ':' );
|
||||
if( colon != NULL ) len = (size_t)(colon - vcb->vcbdev[0].dev->devnam);
|
||||
if( colon != NULL )
|
||||
len = (size_t)(colon - vcb->vcbdev[0].dev->devnam);
|
||||
memcpy( buf, vcb->vcbdev[0].dev->devnam, len );
|
||||
memcpy( buf+len, ":[000000]", sizeof( ":[000000]" ) );
|
||||
setdef(buf);
|
||||
@ -1788,8 +1868,68 @@ static unsigned domount(int argc,char *argv[],int qualc,char *qualv[]) {
|
||||
return sts;
|
||||
}
|
||||
|
||||
/******************************************************************* dospawn() */
|
||||
|
||||
static unsigned dospawn( int argc,char *argv[],int qualc,char *qualv[] ) {
|
||||
#ifdef VMS
|
||||
unsigned sts;
|
||||
|
||||
UNUSED( argc );
|
||||
UNUSED( argv );
|
||||
UNUSED( qualc );
|
||||
UNUSED( qualv );
|
||||
|
||||
sts = lib$spawn( 0,0,0,0,0,0,0,0,0,0,0,0,0 );
|
||||
return sts;
|
||||
#else
|
||||
# ifdef _WIN32
|
||||
UNUSED( argc );
|
||||
UNUSED( argv );
|
||||
UNUSED( qualc );
|
||||
UNUSED( qualv );
|
||||
|
||||
if( system( "cmd" ) == -1 ) {
|
||||
perror( "cmd" );
|
||||
return SS$_NOSUCHFILE;
|
||||
}
|
||||
return SS$_NORMAL;
|
||||
# else
|
||||
char *shell, *p;
|
||||
pid_t pid;
|
||||
|
||||
UNUSED( argc );
|
||||
UNUSED( argv );
|
||||
UNUSED( qualc );
|
||||
UNUSED( qualv );
|
||||
|
||||
if( (shell = getenv( "SHELL" )) == NULL )
|
||||
shell = "/bin/sh";
|
||||
if( (p = strrchr( shell, '/')) == NULL )
|
||||
p = shell;
|
||||
else
|
||||
p++;
|
||||
|
||||
if( (pid = fork()) == 0 ) {
|
||||
execlp( shell, p, (char *)NULL );
|
||||
perror( "%s" );
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if( pid == -1 ) {
|
||||
perror( shell );
|
||||
return SS$_NOSUCHFILE;
|
||||
}
|
||||
waitpid( pid, NULL, 0 );
|
||||
|
||||
return SS$_NORMAL;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************* dohelp() */
|
||||
|
||||
/*********************************************************** cmdhelp() */
|
||||
|
||||
static void cmdhelp( struct CMDSET *cmdset ) {
|
||||
struct CMDSET *cmd;
|
||||
int n = 0;
|
||||
@ -1809,10 +1949,12 @@ static void cmdhelp( struct CMDSET *cmdset ) {
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
/*********************************************************** cmdhelp() */
|
||||
|
||||
static void qualhelp( int par, struct qual *qtable ) {
|
||||
struct qual *q;
|
||||
int n = 0;
|
||||
size_t max = 0;
|
||||
size_t max = 0, col = 4;
|
||||
|
||||
if( par < 0 )
|
||||
max = -par;
|
||||
@ -1838,14 +1980,28 @@ static void qualhelp( int par, struct qual *qtable ) {
|
||||
if( *q->helpstr == '-' )
|
||||
switch( q->qtype ) {
|
||||
case NOVAL:
|
||||
printf( NOSTR "%-*s - %s\n",
|
||||
(int) (max-NOSTR_LEN), q->name, q->helpstr+1 );
|
||||
if( *q->helpstr ) {
|
||||
printf( NOSTR "%-*s - %s\n",
|
||||
(int) (max-NOSTR_LEN), q->name, q->helpstr+1 );
|
||||
break;
|
||||
}
|
||||
if( col + max > 50 ) {
|
||||
printf( "\n " );
|
||||
col = 8;
|
||||
} else {
|
||||
while( col < 8 ) {
|
||||
putchar( ' ' ); col++;
|
||||
}
|
||||
}
|
||||
printf( "%-*s", (int) max, q->name );
|
||||
col += max;
|
||||
break;
|
||||
case KEYVAL:
|
||||
case KEYCOL:
|
||||
printf( NOSTR "%s=%-*s - %s\n",
|
||||
q->name, (int) (max-(NOSTR_LEN+strlen(q->name)+1)), "",
|
||||
q->helpstr+1 );
|
||||
qualhelp( -(int)max, (struct qual *)q->arg );
|
||||
qualhelp( q->qtype == KEYCOL? 1 : -(int)max, (struct qual *)q->arg );
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
@ -1853,12 +2009,26 @@ static void qualhelp( int par, struct qual *qtable ) {
|
||||
else
|
||||
switch( q->qtype ) {
|
||||
case NOVAL:
|
||||
printf("%-*s - %s\n", (int) max, q->name, q->helpstr );
|
||||
if( *q->helpstr ) {
|
||||
printf("%-*s - %s\n", (int) max, q->name, q->helpstr );
|
||||
break;
|
||||
}
|
||||
if( col + max > 50 ) {
|
||||
printf( "\n " );
|
||||
col = 8;
|
||||
} else {
|
||||
while( col < 8 ) {
|
||||
putchar( ' ' ); col++;
|
||||
}
|
||||
}
|
||||
printf( "%-*s", (int) max, q->name );
|
||||
col += max;
|
||||
break;
|
||||
case KEYVAL:
|
||||
case KEYCOL:
|
||||
printf( "%s=%-*s - %s\n", q->name, (int)(max-strlen(q->name)+1), "",
|
||||
q->helpstr );
|
||||
qualhelp( -(int)max, (struct qual *)q->arg );
|
||||
qualhelp( q->qtype == KEYCOL? 1 : -(int)max, (struct qual *)q->arg );
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
@ -1871,6 +2041,8 @@ static void qualhelp( int par, struct qual *qtable ) {
|
||||
#undef NOSTR
|
||||
#undef NOSTR_LEN
|
||||
|
||||
/*********************************************************** parhelp() */
|
||||
|
||||
static void parhelp( struct CMDSET *cmd, int argc, char **argv) {
|
||||
struct param *p;
|
||||
struct param *ptable;
|
||||
@ -1888,14 +2060,14 @@ static void parhelp( struct CMDSET *cmd, int argc, char **argv) {
|
||||
size_t max = 0;
|
||||
|
||||
for( p = ptable; p->name != NULL; p++ ) {
|
||||
if( 1||p->helpstr ) {
|
||||
if( p->helpstr ) {
|
||||
size_t len = strlen(p->name);
|
||||
if( len > max )
|
||||
max = len;
|
||||
}
|
||||
}
|
||||
for( p = ptable; p->name != NULL; p++ ) {
|
||||
if(1|| p->helpstr ) {
|
||||
if( p->helpstr ) {
|
||||
size_t len = strlen(p->name);
|
||||
if( !col ) {
|
||||
printf( " Parameters:\n " );
|
||||
@ -1913,7 +2085,8 @@ static void parhelp( struct CMDSET *cmd, int argc, char **argv) {
|
||||
col += len;
|
||||
}
|
||||
}
|
||||
printf( "\n\n Type help PARAMETER for more about each parameter.\n" );
|
||||
printf( "\n\n Type help %s PARAMETER for more about each parameter.\n",
|
||||
cmd->name );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1968,13 +2141,15 @@ static void parhelp( struct CMDSET *cmd, int argc, char **argv) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*********************************************************** dohelp() */
|
||||
/* help: Display help guided by command table. */
|
||||
#define NCMD 16
|
||||
|
||||
#define NCMD 17
|
||||
static struct CMDSET cmdset[NCMD+1];
|
||||
|
||||
static struct param helppars[] = { {"command", OPT, CMDNAM, PA(cmdset), NULL },
|
||||
{"parameter", OPT, STRING, NOPA, NULL },
|
||||
{"value", OPT, STRING, NOPA, NULL },
|
||||
static struct param helppars[] = { {"command", OPT, CMDNAM, PA(cmdset), "" },
|
||||
{"parameter", OPT, STRING, NOPA, "" },
|
||||
{"value", OPT, STRING, NOPA, "" },
|
||||
{NULL, 0, 0, NOPA, NULL },
|
||||
};
|
||||
|
||||
@ -1983,19 +2158,20 @@ static unsigned dohelp(int argc,char *argv[],int qualc,char *qualv[]);
|
||||
|
||||
static struct CMDSET cmdset[NCMD+1] = {
|
||||
{ "copy", docopy, 0,copyquals,copypars, "Copy a file from VMS to host file", },
|
||||
{ "import", doimport, 0,NULL, importpars, "Copy a file from host to VMS", },
|
||||
{ "delete", dodelete, 0,delquals, delpars, "Delete a VMS file", },
|
||||
{ "difference",dodiff, 0,NULL, diffpars, "Compare VMS file to host file", },
|
||||
{ "directory", dodir, 0,dirquals,dirpars, "List directory of VMS files", },
|
||||
{ "dismount", dodismount,0,NULL, dmopars, "Dismount a VMS volume", },
|
||||
{ "exit", NULL, 2,NULL, NULL, "Exit ODS2", },
|
||||
{ "extend", doextend, 0,NULL, extendpars, NULL },
|
||||
{ "help", dohelp, 0,NULL, helppars, "Obtain help on a command", },
|
||||
{ "quit", NULL, 2,NULL, NULL, "Exit ODS-2", },
|
||||
{ "show", doshow, 0,NULL, showpars, "Display state", },
|
||||
{ "search", dosearch, 0,NULL, searchpars, "Search VMS file for a string", },
|
||||
{ "set", doset, 0,NULL, setpars, "Set PARAMETER - set HELP for list", },
|
||||
{ "dismount", dodismount,0,NULL, dmopars, "Dismount a VMS volume", },
|
||||
{ "import", doimport, 0,NULL, importpars, "Copy a file from host to VMS", },
|
||||
{ "mount", domount, 0,mouquals, moupars, "Mount a VMS volume", },
|
||||
{ "quit", NULL, 2,NULL, NULL, "Exit ODS-2", },
|
||||
{ "search", dosearch, 0,NULL, searchpars, "Search VMS file for a string", },
|
||||
{ "set", doset, 0,NULL, setpars, "Set PARAMETER - set HELP for list", },
|
||||
{ "show", doshow, 0,NULL, showpars, "Display state", },
|
||||
{ "spawn", dospawn, 0,NULL, NULL, "Open a command subprocess", },
|
||||
{ "test", dotest, 0,NULL, testpars, NULL },
|
||||
{ "type", dotype, 0,NULL, typepars, "Display a VMS file on the terminal", },
|
||||
{ NULL, NULL, 0,NULL, NULL, NULL } /* ** END MARKER ** */
|
||||
@ -2064,15 +2240,6 @@ static unsigned dohelp(int argc,char *argv[],int qualc,char *qualv[]) {
|
||||
}
|
||||
printf( "%s: command not found\n", argv[1] );
|
||||
return 0;
|
||||
|
||||
printf(" set_default type\n");
|
||||
printf(" Example:-\n $ mount e:\n");
|
||||
printf(" $ search e:[vms_common.decc*...]*.h rms$_wld\n");
|
||||
printf(" $ set default e:[sys0.sysmgr]\n");
|
||||
printf(" $ copy *.com;-1 c:\\*.*\n");
|
||||
printf(" $ directory/file/size/date [-.sys*...].%%\n");
|
||||
printf(" $ exit\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*************************************************************** cmdexecute() */
|
||||
@ -2142,7 +2309,7 @@ static int cmdexecute( int argc, char *argv[], int qualc, char *qualv[] ) {
|
||||
/* cmdsplit: break a command line into its components */
|
||||
|
||||
/*
|
||||
* New feature for Unix: '//' or '--' stops qualifier parsing.
|
||||
* Feature for Unix: '//' or '--' stops qualifier parsing.
|
||||
* This enables us to copy to Unix directories with VMS style /qualifiers.
|
||||
* copy /bin // *.com /tmp/ *
|
||||
* is split into argv[0] -> "*.com" argv[1] -> "/tmp/ *" qualv[0]-> "/bin"
|
||||
@ -2156,60 +2323,71 @@ static int cmdsplit(char *str) {
|
||||
char *sp = str;
|
||||
int i;
|
||||
char q = vms_qual? '/': '-';
|
||||
for (i = 0; i < MAXITEMS; i++) argv[i] = qualv[i] = "";
|
||||
while (*sp != '\0') {
|
||||
while (*sp == ' ') sp++;
|
||||
if (*sp != '\0') {
|
||||
if (*sp == q) {
|
||||
*sp++ = '\0';
|
||||
if (*sp == q) {
|
||||
sp++;
|
||||
q = '\0';
|
||||
continue;
|
||||
}
|
||||
if( qualc >= MAXITEMS ) {
|
||||
printf( "%%ODS2-E-CMDERR, Too many qualifiers specified\n" );
|
||||
return 0;
|
||||
|
||||
for( i = 0; i < MAXITEMS; i++ ) argv[i] = qualv[i] = "";
|
||||
|
||||
while( *sp != '\0' ) {
|
||||
while( *sp == ' ' ) sp++;
|
||||
if( *sp == '\0' )
|
||||
break;
|
||||
|
||||
if( *sp == q ) { /* Start of qualifier */
|
||||
*sp++ = '\0'; /* Terminate previous word */
|
||||
if (*sp == q) { /* qq = end of qualifiers */
|
||||
sp++;
|
||||
q = '\0';
|
||||
continue;
|
||||
}
|
||||
if( qualc >= MAXITEMS ) {
|
||||
printf( "%%ODS2-E-CMDERR, Too many qualifiers specified\n" );
|
||||
return 0;
|
||||
}
|
||||
qualv[qualc++] = sp;
|
||||
} else { /* New argument */
|
||||
if( argc >= MAXITEMS ) {
|
||||
printf( "%%ODS2-E-CMDERR, Too many arguments specified\n" );
|
||||
return 0;
|
||||
}
|
||||
argv[argc++] = sp;
|
||||
if( *sp == '"' ) {
|
||||
++argv[argc-1];
|
||||
for( ++sp; *sp && (*sp != '"' || sp[1] == '"'); sp++ ) {
|
||||
if( *sp == '"' ) /* Interior "" => " */
|
||||
memmove( sp, sp+1, strlen(sp+1)+1 );
|
||||
}
|
||||
qualv[qualc++] = sp;
|
||||
} else {
|
||||
if( argc >= MAXITEMS ) {
|
||||
printf( "%%ODS2-E-CMDERR, Too many arguments specified\n" );
|
||||
return 0;
|
||||
}
|
||||
argv[argc++] = sp;
|
||||
if( *sp == '"' ) {
|
||||
++argv[argc-1];
|
||||
for( ++sp; *sp && (*sp != '"' || sp[1] == '"'); sp++ ) {
|
||||
if( *sp == '"' )
|
||||
memmove( sp, sp+1, strlen(sp+1)+1 );
|
||||
}
|
||||
if( *sp == '"' ) {
|
||||
*sp++ = '\0';
|
||||
if( *sp && *sp != ' ' ) {
|
||||
printf( "%%ODS2-E-CMDERR, Unterminated string\n" );
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if( *sp == '"' ) { /* Ending " of string */
|
||||
*sp++ = '\0';
|
||||
if( *sp && *sp != ' ' ) { /* Something following */
|
||||
printf( "%%ODS2-E-CMDERR, Unterminated string\n" );
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
printf( "%%ODS2-E-CMDERR, Unterminated string\n" );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
while (*sp != ' ' && *sp != q && *sp != '\0') sp++;
|
||||
if (*sp == '\0') {
|
||||
break;
|
||||
} else {
|
||||
if (*sp != q) *sp++ = '\0';
|
||||
}
|
||||
continue;
|
||||
} /* Quoted string */
|
||||
}
|
||||
|
||||
/* Find end of atom */
|
||||
|
||||
while( !(*sp == '\0' || *sp == ' ' || *sp == q) ) sp++;
|
||||
if (*sp == '\0')
|
||||
break;
|
||||
if( *sp == ' ' )
|
||||
*sp++ = '\0';
|
||||
}
|
||||
|
||||
if (argc > 0) return cmdexecute(argc,argv,qualc,qualv);
|
||||
if( argc > 0 )
|
||||
return cmdexecute( argc, argv, qualc, qualv );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/******************************************************************* main() */
|
||||
|
||||
/*********************************************************** getcmd() */
|
||||
|
||||
#ifdef VMS
|
||||
static char *getcmd( char *inp, size_t max, char *prompt ) {
|
||||
struct dsc_descriptor prompt_d = { strlen(prompt),DSC$K_DTYPE_T,
|
||||
@ -2242,6 +2420,7 @@ static char *getcmd( char *inp, size_t max, char *prompt ) {
|
||||
}
|
||||
#endif /* VMS */
|
||||
|
||||
/*********************************************************** main() */
|
||||
/* main: the simple mainline of this puppy... */
|
||||
|
||||
/*
|
||||
@ -2285,10 +2464,43 @@ int main( int argc,char *argv[] ) {
|
||||
history_truncate_file( hfname, 200 );
|
||||
stifle_history( 200 );
|
||||
read_history( hfname );
|
||||
} else {
|
||||
hfname = NULL;
|
||||
}
|
||||
#endif
|
||||
sts = sys_initialize();
|
||||
if( !(sts & STS$M_SUCCESS) ) {
|
||||
printf( "Unable to initialize library: %s\n", getmsg( sts, MSG_TEXT ) );
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
{ /* Build parser keyword list from disk table entries */
|
||||
struct qual *qp, *kp = NULL;
|
||||
struct disktype * dp;
|
||||
size_t n = 0;
|
||||
|
||||
for( dp = disktype; dp->name != NULL; dp++ )
|
||||
;
|
||||
n = (size_t) (dp - disktype);
|
||||
kp = (struct qual *)calloc( n+1, sizeof( struct qual ) );
|
||||
if( kp == NULL ) {
|
||||
perror( "malloc" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
for( qp = mouquals; qp->name != NULL; qp++ )
|
||||
if( !strcmp( qp->name, DT_NAME ) )
|
||||
break;
|
||||
qp->arg = kp;
|
||||
|
||||
for( dp = disktype; dp->name != NULL; dp++ ) {
|
||||
kp->name = dp->name;
|
||||
kp->set = (int)((dp-disktype) << MOU_V_DEVTYPE);
|
||||
kp->clear = MOU_DEVTYPE;
|
||||
kp->qtype = NOVAL;
|
||||
if( dp != disktype )
|
||||
kp->helpstr = "";
|
||||
kp++;
|
||||
}
|
||||
if( (((unsigned)(dp-disktype)) << MOU_V_DEVTYPE) & ~MOU_DEVTYPE )
|
||||
abort(); /* MOU_DEVTYPE isn't wide enough for the max index */
|
||||
}
|
||||
|
||||
if( argc > 1 ) {
|
||||
int i, l = 0;
|
||||
@ -2327,6 +2539,10 @@ int main( int argc,char *argv[] ) {
|
||||
*p = '\0';
|
||||
i += strlen( ptr ) +1;
|
||||
}
|
||||
#ifdef USE_READLINE
|
||||
if( ptr != NULL && *ptr )
|
||||
add_history( ptr );
|
||||
#endif
|
||||
}
|
||||
if( ptr == NULL ) {
|
||||
if (atfile != NULL) {
|
||||
@ -2404,18 +2620,30 @@ int main( int argc,char *argv[] ) {
|
||||
}
|
||||
} /* while 1 */
|
||||
|
||||
free( command_line );
|
||||
|
||||
if( rl != NULL ) {
|
||||
free( rl );
|
||||
}
|
||||
#ifdef USE_READLINE
|
||||
if( hfname != NULL ) {
|
||||
write_history( hfname );
|
||||
clear_history();
|
||||
}
|
||||
wordfree( &wex ); /* hfname points into wex and should not be free()d */
|
||||
#endif
|
||||
if (atfile != NULL) fclose(atfile);
|
||||
#ifdef VMS
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
if (atfile != NULL)
|
||||
fclose(atfile);
|
||||
|
||||
{
|
||||
struct qual *qp;
|
||||
|
||||
for( qp = mouquals; qp->name != NULL; qp++ )
|
||||
if( !strcmp( qp->name, DT_NAME ) ) {
|
||||
free( qp-> arg );
|
||||
qp->arg = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
exit( EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
@ -5,10 +5,11 @@
|
||||
#ifndef _ODS2_H
|
||||
#define _ODS2_H
|
||||
|
||||
#define MOU_WRITE 1
|
||||
#define MOU_VIRTUAL 2
|
||||
#define MOU_LOG 4
|
||||
#define MOU_WRITE 1
|
||||
#define MOU_VIRTUAL 2
|
||||
#define MOU_LOG 4
|
||||
|
||||
#define SUB_DELETE 1
|
||||
#define MOU_V_DEVTYPE 8
|
||||
#define MOU_DEVTYPE (0xffff << MOU_V_DEVTYPE)
|
||||
|
||||
#endif /* #ifndef _ODS2_H */
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
#include "stsdef.h"
|
||||
#include "compat.h"
|
||||
#include "phyvirt.h"
|
||||
#include "sysmsg.h"
|
||||
|
||||
#ifdef USE_ASPI
|
||||
#include "scsidefs.h"
|
||||
@ -558,9 +559,11 @@ static void getsysversion( void ) {
|
||||
OSVERSIONINFO sysver;
|
||||
|
||||
memset( &sysver, 0, sizeof( sysver ) );
|
||||
#pragma warning (disable : 4996)
|
||||
sysver.dwOSVersionInfoSize = sizeof( sysver );
|
||||
GetVersionEx( &sysver /* lpVersionInfo */
|
||||
);
|
||||
#pragma warning (default : 4996)
|
||||
is_NT = ( sysver.dwPlatformId == VER_PLATFORM_WIN32_NT ) ? 1 : 0 ;
|
||||
}
|
||||
|
||||
@ -580,21 +583,21 @@ static unsigned phy_getsect( struct DEV *dev, unsigned sector ) {
|
||||
sector, dev->bytespersector, dev->IoBuffer );
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
{
|
||||
if ( dev->access & MOU_VIRTUAL || is_NT ) {
|
||||
DWORD DistanceLow, DistanceHigh, BytesRead;
|
||||
DistanceLow = ( sector * dev->blockspersector ) << 9;
|
||||
DistanceHigh = ( sector * dev->blockspersector ) >> 23;
|
||||
SetLastError( 0 );
|
||||
SetFilePointer( dev->API.Win32.handle,/* hFile */
|
||||
DistanceLow, /* lDistanceToMove */
|
||||
&DistanceHigh, /* lpDistanceToMoveHigh */
|
||||
FILE_BEGIN /* dwMoveMethod */
|
||||
);
|
||||
if ( GetLastError() != NO_ERROR ) {
|
||||
TCHAR *msg = w32_errstr(0);
|
||||
printf( "PHYIO_READ: SetFilePointer() failed: %s\n",
|
||||
msg );
|
||||
DWORD BytesRead;
|
||||
__int64 distance;
|
||||
LARGE_INTEGER li;
|
||||
distance = (((__int64)sector) * dev->blockspersector) << 9;
|
||||
li.QuadPart = distance;
|
||||
if( SetFilePointer( dev->API.Win32.handle,/* hFile */
|
||||
li.LowPart, /* lDistanceToMove */
|
||||
&li.HighPart, /* lpDistanceToMoveHigh */
|
||||
FILE_BEGIN /* dwMoveMethod */
|
||||
) == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR ) {
|
||||
TCHAR *msg = w32_errstr(NO_ERROR);
|
||||
printf( "PHYIO_READ: SetFilePointer() failed at sector %lu: %s\n",
|
||||
sector, msg );
|
||||
LocalFree(msg);
|
||||
sts = SS$_PARITY;
|
||||
}
|
||||
@ -607,9 +610,14 @@ static unsigned phy_getsect( struct DEV *dev, unsigned sector ) {
|
||||
&BytesRead, /* lpNumberOfBytesRead */
|
||||
NULL /* lpOverlapped */
|
||||
) || BytesRead != dev->bytespersector ) {
|
||||
TCHAR *msg = w32_errstr(0);
|
||||
printf( "PHYIO_READ: ReadFile() failed: %s\n",
|
||||
msg );
|
||||
TCHAR *msg;
|
||||
|
||||
if( BytesRead == 0 )
|
||||
return SS$_ENDOFFILE;
|
||||
|
||||
msg = w32_errstr(NO_ERROR);
|
||||
printf( "PHYIO_READ: ReadFile() failed at sector %lu: %s\n",
|
||||
sector, msg );
|
||||
LocalFree(msg);
|
||||
sts = SS$_PARITY;
|
||||
}
|
||||
@ -641,7 +649,7 @@ static unsigned phy_getsect( struct DEV *dev, unsigned sector ) {
|
||||
NULL /* lpOverlapped */
|
||||
) && !( reg.reg_Flags & 0x0001 );
|
||||
if ( !result ) {
|
||||
TCHAR *msg = w32_errstr(0);
|
||||
TCHAR *msg = w32_errstr(NO_ERROR);
|
||||
printf( "PHYIO_READ: Read sector %d failed: %s\n",
|
||||
sector, msg );
|
||||
LocalFree(msg);
|
||||
@ -672,34 +680,33 @@ static unsigned phy_putsect( struct DEV *dev, unsigned sector ) {
|
||||
#endif
|
||||
{
|
||||
if ( dev->access & MOU_VIRTUAL || is_NT ) {
|
||||
DWORD DistanceLow, DistanceHigh, BytesWritten;
|
||||
DistanceLow = ( sector * dev->blockspersector ) << 9;
|
||||
DistanceHigh = ( sector * dev->blockspersector ) >> 23;
|
||||
SetLastError( 0 );
|
||||
SetFilePointer( dev->API.Win32.handle, /* hFile */
|
||||
DistanceLow, /* lDistanceToMove */
|
||||
&DistanceHigh, /* lpDistanceToMoveHigh */
|
||||
FILE_BEGIN /* dwMoveMethod */
|
||||
);
|
||||
if ( GetLastError() != NO_ERROR ) {
|
||||
TCHAR *msg = w32_errstr(0);
|
||||
printf( "PHYIO_WRITE: SetFilePointer() failed: %s\n",
|
||||
msg );
|
||||
DWORD BytesWritten;
|
||||
__int64 distance;
|
||||
LARGE_INTEGER li;
|
||||
distance = (((__int64)sector) * dev->blockspersector) << 9;
|
||||
li.QuadPart = distance;
|
||||
if( SetFilePointer( dev->API.Win32.handle,/* hFile */
|
||||
li.LowPart, /* lDistanceToMove */
|
||||
&li.HighPart, /* lpDistanceToMoveHigh */
|
||||
FILE_BEGIN /* dwMoveMethod */
|
||||
) == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR ) {
|
||||
TCHAR *msg = w32_errstr(NO_ERROR);
|
||||
printf( "PHYIO_WRITE: SetFilePointer() failed at sector %lu: %s\n",
|
||||
sector, msg );
|
||||
LocalFree(msg);
|
||||
sts = SS$_PARITY;
|
||||
}
|
||||
if ( sts & STS$M_SUCCESS ) {
|
||||
/* hFile */
|
||||
if ( !WriteFile( dev->API.Win32.handle,
|
||||
dev->IoBuffer, /* lpBuffer */
|
||||
/* nNumberOfBytesToWrite */
|
||||
if ( !WriteFile( dev->API.Win32.handle, /* hFile */
|
||||
dev->IoBuffer, /* lpBuffer */
|
||||
/* nNumberOfBytesToWrite */
|
||||
dev->bytespersector,
|
||||
&BytesWritten, /* lpNumberOfBytesWritten */
|
||||
NULL /* lpOverlapped */
|
||||
&BytesWritten, /* lpNumberOfBytesWritten */
|
||||
NULL /* lpOverlapped */
|
||||
) || BytesWritten != dev->bytespersector ) {
|
||||
TCHAR *msg = w32_errstr(0);
|
||||
printf( "PHYIO_WRITE: WriteFile() failed: %s\n",
|
||||
msg );
|
||||
TCHAR *msg = w32_errstr(NO_ERROR);
|
||||
printf( "PHYIO_WRITE: WriteFile() failed at sector %lu: %s\n",
|
||||
sector, msg );
|
||||
LocalFree(msg);
|
||||
sts = SS$_PARITY;
|
||||
}
|
||||
@ -730,7 +737,7 @@ static unsigned phy_putsect( struct DEV *dev, unsigned sector ) {
|
||||
NULL /* lpOverlapped */
|
||||
) && !( reg.reg_Flags & 0x0001 );
|
||||
if ( !result ) {
|
||||
TCHAR *msg = w32_errstr(0);
|
||||
TCHAR *msg = w32_errstr(NO_ERROR);
|
||||
printf( "PHYIO_WRITE: Write sector %d failed: %s\n",
|
||||
sector, msg );
|
||||
LocalFree(msg);
|
||||
@ -751,7 +758,7 @@ void phyio_show( showtype_t type ) {
|
||||
init_count, read_count, write_count );
|
||||
return;
|
||||
case SHOW_FILE64:
|
||||
printf( "\nLarge ODS-2 image files (>2GB) are supported.\n" );
|
||||
printf( "Large ODS-2 image files (>2GB) are %ssupported.\n", "" );
|
||||
return;
|
||||
case SHOW_DEVICES: {
|
||||
TCHAR *namep = NULL, *dname = NULL;
|
||||
@ -793,8 +800,8 @@ void phyio_show( showtype_t type ) {
|
||||
free(namep);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
@ -934,15 +941,15 @@ unsigned phyio_init( struct DEV *dev ) {
|
||||
);
|
||||
}
|
||||
if ( dev->API.Win32.handle == INVALID_HANDLE_VALUE ) {
|
||||
TCHAR *msg = w32_errstr(0);
|
||||
TCHAR *msg = w32_errstr(NO_ERROR);
|
||||
printf( "PHYIO_INIT: Open( \"%s\" ) failed: %s\n",
|
||||
dev->devnam, msg );
|
||||
LocalFree(msg);
|
||||
return SS$_NOSUCHDEV;
|
||||
}
|
||||
if ( !LockVolume( dev ) ) {
|
||||
TCHAR *msg = w32_errstr(0);
|
||||
printf( "PHYIO_INIT: LockVolume( \"%s\" ) failed: %a\n",
|
||||
TCHAR *msg = w32_errstr(NO_ERROR);
|
||||
printf( "PHYIO_INIT: LockVolume( \"%s\" ) failed: %s\n",
|
||||
dev->devnam, msg );
|
||||
LocalFree(msg);
|
||||
phyio_done( dev );
|
||||
@ -950,7 +957,7 @@ unsigned phyio_init( struct DEV *dev ) {
|
||||
}
|
||||
}
|
||||
if ( !GetDiskGeometry( dev, &dev->sectors, &dev->bytespersector ) ) {
|
||||
TCHAR *msg = w32_errstr(0);
|
||||
TCHAR *msg = w32_errstr(NO_ERROR);
|
||||
printf( "PHYIO_INIT: GetDiskGeometry( \"%s\" ) failed: %s\n",
|
||||
dev->devnam, msg );
|
||||
LocalFree(msg);
|
||||
@ -989,6 +996,10 @@ unsigned phyio_init( struct DEV *dev ) {
|
||||
);
|
||||
}
|
||||
if ( dev->API.Win32.handle == INVALID_HANDLE_VALUE ) {
|
||||
TCHAR *msg = w32_errstr(NO_ERROR);
|
||||
printf( "PHYIO_INIT: CreateFile() failed for %s: %s\n",
|
||||
virtual, msg );
|
||||
LocalFree(msg);
|
||||
return SS$_NOSUCHFILE;
|
||||
}
|
||||
SetLastError( 0 );
|
||||
@ -1078,8 +1089,8 @@ unsigned phyio_read( struct DEV *dev, unsigned block, unsigned length,
|
||||
offset = 0;
|
||||
}
|
||||
if ( !( sts & STS$M_SUCCESS ) ) {
|
||||
printf( "PHYIO_READ Error %d Block %d Length %d",
|
||||
sts, block, length );
|
||||
printf( "PHYIO_READ Error %s Block %d Length %d",
|
||||
getmsg(sts, MSG_TEXT), block, length );
|
||||
#ifdef USE_ASPI
|
||||
printf( " (ASPI: %x %x %x)",
|
||||
ASPI_status, ASPI_HaStat, ASPI_TargStat );
|
||||
|
||||
@ -111,8 +111,10 @@ static void showdevs( void ) {
|
||||
free( fs );
|
||||
continue;
|
||||
}
|
||||
if( !S_ISBLK( stb.st_mode ) )
|
||||
if( !S_ISBLK( stb.st_mode ) ) {
|
||||
free( fs );
|
||||
continue;
|
||||
}
|
||||
|
||||
memmove( fs, fs + sizeof( DEV_PREFIX ) -1, len +1 );
|
||||
unit = ~0;
|
||||
@ -126,14 +128,17 @@ static void showdevs( void ) {
|
||||
if( unit < (*list)[i].low )
|
||||
(*list)[i].low = unit;
|
||||
}
|
||||
free( fs );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( i >= n ) {
|
||||
nl = (struct devdat (*)[1])
|
||||
realloc( list, (n+1) * sizeof( struct devdat ) );
|
||||
if( nl == NULL )
|
||||
if( nl == NULL ) {
|
||||
free( fs );
|
||||
break;
|
||||
}
|
||||
list = nl;
|
||||
(*list)[n].name = fs;
|
||||
(*list)[n].low = unit;
|
||||
@ -206,7 +211,8 @@ void phyio_show( showtype_t type ) {
|
||||
init_count, read_count, write_count );
|
||||
return;
|
||||
case SHOW_FILE64:
|
||||
printf( "\nLarge ODS-2 image files (>2GB) are supported.\n" );
|
||||
printf( "Large ODS-2 image files (>2GB) are %ssupported.\n",
|
||||
(sizeof( off_t ) < 8)? "NOT ": "" );
|
||||
return;
|
||||
case SHOW_DEVICES:
|
||||
printf( " Physical devices\n" );
|
||||
@ -338,6 +344,9 @@ unsigned phyio_read( struct DEV *dev, unsigned block, unsigned length,
|
||||
return SS$_PARITY;
|
||||
}
|
||||
if ( ( res = read( dev->handle, buffer, length ) ) != length ) {
|
||||
if( res == 0 ) {
|
||||
return SS$_ENDOFFILE;
|
||||
}
|
||||
perror( "read " );
|
||||
printf("read failed %" PRIuMAX "u\n", (uintmax_t)res);
|
||||
return SS$_PARITY;
|
||||
|
||||
@ -52,7 +52,7 @@ void virt_show( const char *devnam ) {
|
||||
unsigned devlen, devsiz;
|
||||
struct VDEV *vp;
|
||||
|
||||
if ( devnam == NULL ) {
|
||||
if( devnam == NULL ) {
|
||||
size_t maxd = sizeof( "Device" ) -1,
|
||||
maxp = sizeof( "File" ) -1,
|
||||
n;
|
||||
@ -61,7 +61,7 @@ void virt_show( const char *devnam ) {
|
||||
printf( " No virtual devices are assigned\n" );
|
||||
return;
|
||||
}
|
||||
for ( vp = virt_device_list; vp != NULL; vp = vp->next ) {
|
||||
for( vp = virt_device_list; vp != NULL; vp = vp->next ) {
|
||||
n = strlen( vp->devnam );
|
||||
if( n > maxd )
|
||||
maxd = n;
|
||||
@ -79,23 +79,23 @@ void virt_show( const char *devnam ) {
|
||||
for( n = 0; n < maxp; n++ ) putchar( '-' );
|
||||
putchar( '\n' );
|
||||
|
||||
for ( vp = virt_device_list; vp != NULL; vp = vp->next ) {
|
||||
for( vp = virt_device_list; vp != NULL; vp = vp->next ) {
|
||||
n = strlen( vp->path );
|
||||
printf( " %-*s %.*s\n", (int)maxd, vp->devnam, (int)maxp,
|
||||
(n > maxp)? vp->path+(n-maxp): vp->path );
|
||||
}
|
||||
} else {
|
||||
devlen = strlen( devnam );
|
||||
for ( devsiz = 0; devsiz < devlen; devsiz++ ) {
|
||||
if ( devnam[devsiz] == ':' ) {
|
||||
for( devsiz = 0; devsiz < devlen; devsiz++ ) {
|
||||
if( devnam[devsiz] == ':' ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( devsiz == 0 ) {
|
||||
if( devsiz == 0 ) {
|
||||
return;
|
||||
}
|
||||
for ( vp = virt_device_list; vp != NULL; vp = vp->next ) {
|
||||
if ( virt_compare( devsiz, (char *) devnam, vp->devnam ) == 0 ) {
|
||||
for( vp = virt_device_list; vp != NULL; vp = vp->next ) {
|
||||
if( virt_compare( devsiz, (char *) devnam, vp->devnam ) == 0 ) {
|
||||
printf( " %s => %s\n", vp->devnam, vp->path );
|
||||
return;
|
||||
}
|
||||
@ -111,13 +111,13 @@ static int virt_compare( unsigned keylen, const char *keynam,
|
||||
register int cmp;
|
||||
|
||||
cmp = 0;
|
||||
while ( keylen-- > 0 ) {
|
||||
while( keylen-- > 0 ) {
|
||||
cmp = toupper( *keynam++ ) - toupper( *devnam++ );
|
||||
if ( cmp != 0 ) {
|
||||
if( cmp != 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( cmp == 0 && *devnam != '\0' && *devnam != ':' ) {
|
||||
if( cmp == 0 && *devnam != '\0' && *devnam != ':' ) {
|
||||
cmp = -1;
|
||||
}
|
||||
return cmp;
|
||||
@ -133,16 +133,16 @@ char *virt_lookup( const char *devnam ) {
|
||||
struct VDEV *vp;
|
||||
|
||||
devlen = strlen( devnam );
|
||||
for ( devsiz = 0; devsiz < devlen; devsiz++ ) {
|
||||
if ( devnam[devsiz] == ':' ) {
|
||||
for( devsiz = 0; devsiz < devlen; devsiz++ ) {
|
||||
if( devnam[devsiz] == ':' ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( devsiz == 0 ) {
|
||||
if( devsiz == 0 ) {
|
||||
return NULL;
|
||||
}
|
||||
for ( vp = virt_device_list; vp != NULL; vp = vp->next ) {
|
||||
if ( virt_compare( devsiz, (char *) devnam, vp->devnam ) == 0 ) {
|
||||
for( vp = virt_device_list; vp != NULL; vp = vp->next ) {
|
||||
if( virt_compare( devsiz, (char *) devnam, vp->devnam ) == 0 ) {
|
||||
return vp->path;
|
||||
}
|
||||
}
|
||||
@ -176,21 +176,22 @@ unsigned virt_device( char *devnam, char **vname ) {
|
||||
}
|
||||
path = p;
|
||||
|
||||
for ( vpp = &virt_device_list; *vpp != NULL; vpp = &(*vpp)->next ) {
|
||||
for( vpp = &virt_device_list; *vpp != NULL; vpp = &(*vpp)->next ) {
|
||||
if( strcmp( (*vpp)->path, path ) == 0 ) {
|
||||
printf( "%%ODS2-E-MAPPED, %s is in use on virtual drive %s\n", path, (*vpp)->devnam );
|
||||
free( path );
|
||||
return SS$_DEVMOUNT;
|
||||
}
|
||||
}
|
||||
}
|
||||
devlen = strlen( devnam );
|
||||
|
||||
for ( devsiz = 0; devsiz < devlen; devsiz++ ) {
|
||||
if ( devnam[devsiz] == ':' ) {
|
||||
for( devsiz = 0; devsiz < devlen; devsiz++ ) {
|
||||
if( devnam[devsiz] == ':' ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( devsiz == 0 ) {
|
||||
if( devsiz == 0 ) {
|
||||
free( path );
|
||||
return SS$_BADPARAM;
|
||||
}
|
||||
@ -216,21 +217,21 @@ static struct VDEV *virt_insert( const char *devnam, unsigned devsiz,
|
||||
struct VDEV *vp, **vpp, **here;
|
||||
|
||||
here = NULL;
|
||||
for ( vpp = &virt_device_list; *vpp != NULL; vpp = &(*vpp)->next ) {
|
||||
if ( virt_compare( devsiz, (char *) devnam, (*vpp)->devnam ) < 0 ) {
|
||||
for( vpp = &virt_device_list; *vpp != NULL; vpp = &(*vpp)->next ) {
|
||||
if( virt_compare( devsiz, (char *) devnam, (*vpp)->devnam ) < 0 ) {
|
||||
here = vpp;
|
||||
}
|
||||
}
|
||||
if ( here == NULL ) {
|
||||
if( here == NULL ) {
|
||||
here = vpp;
|
||||
}
|
||||
vp = (struct VDEV *) malloc( sizeof( struct VDEV ) );
|
||||
if ( vp == NULL ) {
|
||||
if( vp == NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
vp->devnam = (char *) malloc( devsiz + 1 );
|
||||
vp->path = (char *) malloc( (pathsiz = strlen( path )) + 1 );
|
||||
if ( vp->devnam == NULL || vp->path == NULL ) {
|
||||
if( vp->devnam == NULL || vp->path == NULL ) {
|
||||
free( vp->devnam );
|
||||
free( vp->path );
|
||||
free( vp );
|
||||
@ -251,8 +252,8 @@ static void virt_remove( const char *devnam, unsigned devsiz ) {
|
||||
|
||||
struct VDEV *vp, **vpp;
|
||||
|
||||
for ( vpp = &virt_device_list; *vpp != NULL; vpp = &(*vpp)->next ) {
|
||||
if ( virt_compare( devsiz, (char *) devnam, (*vpp)->devnam ) == 0 ) {
|
||||
for( vpp = &virt_device_list; *vpp != NULL; vpp = &(*vpp)->next ) {
|
||||
if( virt_compare( devsiz, (char *) devnam, (*vpp)->devnam ) == 0 ) {
|
||||
vp = *vpp;
|
||||
*vpp = (*vpp)->next;
|
||||
free( vp->devnam );
|
||||
|
||||
@ -39,6 +39,7 @@
|
||||
#include <mntdef.h>
|
||||
#include <rms.h> /* struct FAB */
|
||||
#include <ssdef.h>
|
||||
#include <stsdef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -67,15 +68,23 @@ unsigned sys$dassgn();
|
||||
#include <starlet.h>
|
||||
#endif
|
||||
|
||||
#ifndef SS$_NOMOREDEV
|
||||
#define SS$_NOMOREDEV 2648
|
||||
#endif
|
||||
|
||||
#ifndef EFN$C_ENF
|
||||
#define EFN$C_ENF 0 /* 128 in recent VMS */
|
||||
#endif
|
||||
|
||||
#include "ods2.h"
|
||||
#include "phyio.h"
|
||||
#include "virtual.h"
|
||||
|
||||
struct ITMLST {
|
||||
unsigned short length;
|
||||
unsigned short itmcod;
|
||||
void *buffer;
|
||||
unsigned long *retlen;
|
||||
unsigned short length;
|
||||
unsigned short itmcod;
|
||||
void *buffer;
|
||||
unsigned short *retlen;
|
||||
};
|
||||
|
||||
#define chk( sts ) { register chksts; \
|
||||
@ -83,10 +92,86 @@ struct ITMLST {
|
||||
lib$stop( chksts ); \
|
||||
}
|
||||
|
||||
#define MSGID(sts) ((sts) & (STS$M_COND_ID|STS$M_SEVERITY))
|
||||
|
||||
static unsigned init_count = 0;
|
||||
static unsigned read_count = 0;
|
||||
static unsigned write_count = 0;
|
||||
|
||||
/*************************************************************** showdevs() */
|
||||
static void showdevs( void ) {
|
||||
unsigned long status;
|
||||
size_t max = 0;
|
||||
int pass;
|
||||
|
||||
max = 0
|
||||
for( pass = 0; pass < 2; pass++ ) {
|
||||
unsigned long ctx[2] = { 0, 0 };
|
||||
size_t col = 0;
|
||||
unsigned short retlen, iosb[4];
|
||||
char devnam[64+1],
|
||||
dspnam[64+1];
|
||||
struct dsc$descriptor_s retdsc = { sizeof( devnam ) -1,
|
||||
DSC$K_DTYPE_T,
|
||||
DSC$K_CLASS_S, devnam };
|
||||
$DESCRIPTOR( searchdsc, "*" );
|
||||
unsigned long devclass = DC$_DISK;
|
||||
struct ITMLST scanlist[] = {
|
||||
{ sizeof( devclass ), DC$_DISK, &devclass, NULL },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
struct ITMLST dvilist[] = {
|
||||
{ sizeof( dspnam ) -1, DVI$_DISPLAY_DEVNAM, dspnam, &retlen },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
while( 1 ) {
|
||||
char *name;
|
||||
size_t len;
|
||||
|
||||
status = sys$device_scan( &retdsc, &retlen,
|
||||
&searchdsc, scanlist, &ctx );
|
||||
if( MSGID(status) != SS$_NORMAL )
|
||||
break;
|
||||
name = devnam;
|
||||
name[retlen] = '\0';
|
||||
len = retlen;
|
||||
status = sys$getdviw( EFN$C_ENF, 0, &retdsc, dvilist, iosb,
|
||||
NULL, 0, NULL );
|
||||
if( MSGID(status) == SS$_NORMAL ) {
|
||||
name = dspnam;
|
||||
dspnam[retlen] = '\0';
|
||||
len = retlen;
|
||||
}
|
||||
if( pass == 0 ) {
|
||||
if( len > max )
|
||||
max = len;
|
||||
continue;
|
||||
}
|
||||
if( col + max > 75 ) {
|
||||
putchar( '\n' );
|
||||
col = 0;
|
||||
}
|
||||
col += 1+ max;
|
||||
|
||||
printf( " %-*s", (int)max, name );
|
||||
}
|
||||
}
|
||||
switch( MSGID(status) ) {
|
||||
case SS$_NOMOREDEV:
|
||||
break;
|
||||
case SS$_NOSUCHDEV:
|
||||
printf( "No devices found\n" );
|
||||
case SS$_NORMAL:
|
||||
break;
|
||||
default:
|
||||
printf( "%%ODS2-W-ERRDEV, Error scanning devices: %s\n",
|
||||
getmsg( status, MSG_TEXT ) );
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************** phyio_show() */
|
||||
|
||||
void phyio_show( showtype_t type ) {
|
||||
@ -96,13 +181,12 @@ void phyio_show( showtype_t type ) {
|
||||
init_count, read_count, write_count );
|
||||
return;
|
||||
case SHOW_FILE64:
|
||||
printf( "\nLarge ODS-2 image files (>2GB) are supported.\n" );
|
||||
printf( "Large ODS-2 image files (>2GB) are %ssupported.\n",
|
||||
(sizeof( off_t ) < 8)? "NOT ": "" );
|
||||
return;
|
||||
case SHOW_DEVICES:
|
||||
#if 0 /* VMS doesn't make listing devices easy */
|
||||
printf( " Physical devices\n" );
|
||||
showdevs();
|
||||
#endif
|
||||
return;
|
||||
default:
|
||||
abort();
|
||||
@ -178,6 +262,7 @@ unsigned phyio_init( struct DEV *dev ) {
|
||||
unsigned long devclass, cylinders, tracks, sectors;
|
||||
char devname[65];
|
||||
unsigned long devchar;
|
||||
unsigned short iosb[4];
|
||||
struct ITMLST dvi_itmlst[7] = {
|
||||
{ sizeof( devclass ), DVI$_DEVCLASS, &devclass, NULL },
|
||||
{ sizeof( devname ), DVI$_ALLDEVNAM, &devname, NULL },
|
||||
@ -191,7 +276,7 @@ unsigned phyio_init( struct DEV *dev ) {
|
||||
/* Get some device information: device name, class, and mount status */
|
||||
devdsc.dsc$w_length = strlen( dev->devnam );
|
||||
devdsc.dsc$a_pointer = dev->devnam;
|
||||
sts = sys$getdviw( 0, 0, &devdsc, &dvi_itmlst, 0, 0, 0, 0 );
|
||||
sts = sys$getdviw( EFN$C_ENF, 0, &devdsc, &dvi_itmlst, iosb, 0, 0, 0 );
|
||||
if ( !( sts & STS$M_SUCCESS ) ) {
|
||||
return sts;
|
||||
}
|
||||
@ -295,6 +380,9 @@ unsigned phyio_read( struct DEV *dev, unsigned block, unsigned length,
|
||||
return SS$_PARITY;
|
||||
}
|
||||
if ( ( res = read( dev->handle, buffer, length ) ) != length ) {
|
||||
if( res == 0 ) {
|
||||
return SS$_ENDOFFILE;
|
||||
}
|
||||
perror( "read " );
|
||||
printf( "read failed %d\n", res );
|
||||
return SS$_PARITY;
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
#include "ssdef.h"
|
||||
#include "stsdef.h"
|
||||
#include "compat.h"
|
||||
#include "sysmsg.h"
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE ( 0 == 0 )
|
||||
@ -455,6 +456,7 @@ unsigned do_search(struct FAB *fab,struct WCCFILE *wccfile)
|
||||
wcc->wcd_reslen - 6,".DIR;1",6);
|
||||
} else {
|
||||
sts = RMS$_NMF;
|
||||
cleanup_wcf(&wccfile);
|
||||
break; /* giveup */
|
||||
}
|
||||
}
|
||||
@ -753,7 +755,13 @@ unsigned do_parse(struct FAB *fab,struct WCCFILE **wccret)
|
||||
}
|
||||
if (wccret != NULL) *wccret = wccfile;
|
||||
if (nam != NULL) {
|
||||
nam->nam$l_wcc = wccfile;
|
||||
if( (nam->nam$b_nop & NAM$M_SYNCHK) &&
|
||||
!fab->fab$b_dns && !nam->nam$l_rlf ) {
|
||||
cleanup_wcf(&wccfile);
|
||||
if( wccret ) *wccret = NULL;
|
||||
} else {
|
||||
nam->nam$l_wcc = wccfile;
|
||||
}
|
||||
}
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
@ -795,14 +803,21 @@ unsigned sys_setddir(struct dsc_descriptor *newdir,unsigned short *oldlen,
|
||||
sts = sys_parse(&fab);
|
||||
if (sts & STS$M_SUCCESS) {
|
||||
if (nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver > 2) {
|
||||
return RMS$_DIR;
|
||||
sts = RMS$_DIR;
|
||||
} else {
|
||||
if (nam.nam$l_fnb & NAM$M_WILDCARD)
|
||||
sts = RMS$_WLD;
|
||||
else {
|
||||
default_name = default_buffer;
|
||||
default_size[0] = nam.nam$b_dev;
|
||||
default_size[1] = nam.nam$b_dir;
|
||||
memcpy(default_name + nam.nam$b_dev + nam.nam$b_dir,".;",3);
|
||||
}
|
||||
}
|
||||
if (nam.nam$l_fnb & NAM$M_WILDCARD) return RMS$_WLD;
|
||||
default_name = default_buffer;
|
||||
default_size[0] = nam.nam$b_dev;
|
||||
default_size[1] = nam.nam$b_dir;
|
||||
memcpy(default_name + nam.nam$b_dev + nam.nam$b_dir,".;",3);
|
||||
}
|
||||
fab.fab$b_dns = 0;
|
||||
nam.nam$l_rlf = 0;
|
||||
sys$parse( &fab );
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
@ -1473,3 +1488,18 @@ unsigned sys_extend(struct FAB *fab)
|
||||
fab->fab$l_alq - ifi_table[ifi_no]->wcf_fcb->hiblock,0);
|
||||
return sts;
|
||||
}
|
||||
|
||||
/*************************************************************** sys_initialize() */
|
||||
static void sys_rundown( void ) {
|
||||
access_rundown();
|
||||
|
||||
sysmsg_rundown();
|
||||
}
|
||||
|
||||
/*************************************************************** sys_initialize() */
|
||||
unsigned sys_initialize( void ) {
|
||||
if( atexit( sys_rundown ) != 0 )
|
||||
return SS$_INSFMEM;
|
||||
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
|
||||
#include "vmstime.h"
|
||||
|
||||
#define RMS$_FACILITY 1
|
||||
|
||||
#define RMS$_RTB 98728
|
||||
#define RMS$_EOF 98938
|
||||
#define RMS$_FNF 98962
|
||||
@ -170,10 +172,11 @@ struct NAM {
|
||||
void *nam$l_wcc;
|
||||
int nam$b_nop;
|
||||
int nam$l_fnb;
|
||||
struct NAM *nam$l_rlf;
|
||||
};
|
||||
|
||||
#ifdef RMS$INITIALIZE
|
||||
struct NAM cc$rms_nam = {0,0,0,0,0,0,0,0,0,0,0,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0,0,0};
|
||||
struct NAM cc$rms_nam = {0,0,0,0,0,0,0,0,0,0,0,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0,0,0,NULL};
|
||||
#else
|
||||
extern struct NAM cc$rms_nam;
|
||||
#endif
|
||||
@ -317,4 +320,6 @@ unsigned sys_extend(struct FAB *fab);
|
||||
unsigned sys_setddir(struct dsc_descriptor *newdir,unsigned short *oldlen,
|
||||
struct dsc_descriptor *olddir);
|
||||
|
||||
unsigned sys_initialize(void);
|
||||
|
||||
#endif /* #ifndef _RMS_H */
|
||||
|
||||
@ -13,6 +13,8 @@
|
||||
#ifndef _SSDEF_H
|
||||
#define _SSDEF_H
|
||||
|
||||
#define SYSTEM$_FACILITY 0
|
||||
|
||||
#define SS$_NORMAL 1
|
||||
#define SS$_WASCLR 1
|
||||
#define SS$_WASSET 9
|
||||
@ -45,6 +47,7 @@
|
||||
#define SS$_NOSUCHFILE 2320
|
||||
#define SS$_NOMOREFILES 2352
|
||||
#define SS$_ITEMNOTFOUND 2640
|
||||
#define SS$_NOMOREDEV 2648
|
||||
#define SS$_NOSUCHVOL 3882
|
||||
#define SS$_NOTINSTALL 8212
|
||||
#define SS$_DEVNOTDISM 8628
|
||||
|
||||
@ -5,6 +5,52 @@
|
||||
#ifndef _STSDEF_H
|
||||
#define _STSDEF_H
|
||||
|
||||
#define STS$M_SUCCESS 1
|
||||
#define STS$V_SEVERITY 0
|
||||
#define STS$M_SEVERITY 0x00000007
|
||||
#define STS$S_SEVERITY 3
|
||||
#define STS$V_COND_ID 3
|
||||
#define STS$M_COND_ID 0x0FFFFFF8
|
||||
#define STS$S_COND_ID 25
|
||||
#define STS$V_CONTROL 28
|
||||
#define STS$M_CONTROL 0xF0000000
|
||||
#define STS$S_CONTROL 4
|
||||
#define STS$V_SUCCESS 0
|
||||
#define STS$M_SUCCESS 0x01
|
||||
#define STS$S_SUCCESS 1
|
||||
#define STS$V_MSG_NO 3
|
||||
#define STS$M_MSG_NO 0x0000FFF8
|
||||
#define STS$S_MSG_NO 13
|
||||
#define STS$V_CODE 3
|
||||
#define STS$M_CODE 0x00007FF8
|
||||
#define STS$S_CODE 12
|
||||
#define STS$V_FAC_SP 15
|
||||
#define STS$M_FAC_SP 0x00008000
|
||||
#define STS$S_FAC_SP 1
|
||||
#define STS$V_CUST_DEF 27
|
||||
#define STS$M_CUST_DEF 0x08000000
|
||||
#define STS$S_CUST_DEF 1
|
||||
#define STS$V_INHIB_MSG 28
|
||||
#define STS$M_INHIB_MSG 0x10000000
|
||||
#define STS$S_INHIB_MSG 1
|
||||
#define STS$V_FAC_NO 16
|
||||
#define STS$M_FAC_NO 0x0FFF0000
|
||||
#define STS$S_FAC_NO 12
|
||||
|
||||
#define STS$K_WARNING 0
|
||||
#define STS$K_SUCCESS 1
|
||||
#define STS$K_ERROR 2
|
||||
#define STS$K_INFO 3
|
||||
#define STS$K_SEVERE 4
|
||||
|
||||
#define $VMS_STATUS_CODE(code) ( ( (code) & STS$M_CODE ) >> STS$V_CODE )
|
||||
#define $VMS_STATUS_COND_ID(code) ( ( (code) & STS$M_COND_ID ) >> STS$V_COND_ID )
|
||||
#define $VMS_STATUS_CONTROL(code) ( ( (code) & STS$M_CONTROL ) >> STS$V_CONTROL )
|
||||
#define $VMS_STATUS_CUST_DEF(code) ( ( (code) & STS$M_CUST_DEF ) >> STS$V_CUST_DEF )
|
||||
#define $VMS_STATUS_FAC_NO(code) ( ( (code) & STS$M_FAC_NO ) >> STS$V_FAC_NO )
|
||||
#define $VMS_STATUS_FAC_SP(code) ( ( (code) & STS$M_FAC_SP ) >> STS$V_FAC_SP )
|
||||
#define $VMS_STATUS_INHIB_MSG(code) ( ( (code) & STS$M_INHIB_MSG ) >> STS$V_INHIB_MSG )
|
||||
#define $VMS_STATUS_MSG_NO(code) ( ( (code) & STS$M_MSG_NO ) >> STS$V_MSG_NO )
|
||||
#define $VMS_STATUS_SEVERITY(code) ( ( (code) & STS$M_SEVERITY ) >> STS$V_SEVERITY )
|
||||
#define $VMS_STATUS_SUCCESS(code) ( ( (code) & STS$M_SUCCESS ) >> STS$V_SUCCESS )
|
||||
|
||||
#endif /* #ifndef _STSDEF_H */
|
||||
|
||||
@ -1,7 +1,18 @@
|
||||
/* Timothe Litt litt _at_ acm _ddot_ org */
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
email address: Paulnank@au1.ibm.com
|
||||
|
||||
ODS2 is distributed freely for all members of the
|
||||
VMS community to use. However all derived works
|
||||
must maintain comments in their source to acknowledge
|
||||
the contibution of the original author.
|
||||
*/
|
||||
|
||||
/* Message code translations for non-VMS systems */
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -16,83 +27,226 @@
|
||||
#include "compat.h"
|
||||
#include "sysmsg.h"
|
||||
|
||||
#define MSG(code,text) { $VMS_STATUS_COND_ID(code), #code, text },
|
||||
|
||||
static
|
||||
const struct VMSFAC {
|
||||
unsigned int code;
|
||||
const char *const text;
|
||||
} fac2text[] = {
|
||||
{ SYSTEM$_FACILITY, "SYSTEM" },
|
||||
{ RMS$_FACILITY, "RMS" },
|
||||
{ 0, NULL },
|
||||
{ 0, "NONAME" }
|
||||
};
|
||||
|
||||
static const char sev2text[(STS$M_SEVERITY>>STS$V_SEVERITY)+1] =
|
||||
{ 'W', 'S', 'E', 'I', 'F', '?', '?', '?', };
|
||||
|
||||
/* Unknown facility or message code */
|
||||
|
||||
#ifndef SS$_NOMSG
|
||||
#define SS$_NOMSG 0xFFFFFFFF
|
||||
#endif
|
||||
|
||||
static const char nofmt[] = "Message number %08X";
|
||||
static char notext[sizeof(nofmt)+8];
|
||||
|
||||
static
|
||||
const struct VMSMSG {
|
||||
unsigned int code;
|
||||
const char *const text;
|
||||
} *mp, vms2text[] = {
|
||||
{RMS$_BUG, "%RMS-F-BUG, fatal RMS condition detected, process deleted"},
|
||||
{RMS$_DIR, "%RMS-F-DIR, error in directory name"},
|
||||
{RMS$_DNF, "%RMS-E-DNF, directory not found"},
|
||||
{RMS$_EOF, "%RMS-E-EOF, end of file detected"},
|
||||
{RMS$_ESS, "%RMS-F-ESS, expanded string area too small"},
|
||||
{RMS$_FNF, "%RMS-E-FNF, file not found"},
|
||||
{RMS$_FNM, "%RMS-F-FNM, error in file name"},
|
||||
{RMS$_IFI, "%RMS-F-IFI, invalid internal file identifier (IFI) value"},
|
||||
{RMS$_NAM, "%RMS-F-NAM, invalid NAM block or NAM block not accessible"},
|
||||
{RMS$_NMF, "%RMS-E-NMF, no more files found"},
|
||||
{RMS$_RSS, "%RMS-F-RSS, invalid resultant string size"},
|
||||
{RMS$_RSZ, "%RMS-F-RSZ, invalid record size"},
|
||||
{RMS$_RTB, "%RMS-W-RTB, !UL byte record too large for user's buffer"},
|
||||
{RMS$_WCC, "%RMS-E-WCC, invalid wild card context (WCC) value"},
|
||||
{RMS$_WLD, "%RMS-F-WLD, invalid wildcard operation"},
|
||||
{SS$_ABORT, "%SYSTEM-F-ABORT, abort"},
|
||||
{SS$_BADFILENAME, "%SYSTEM-W-BADFILENAME, bad file name syntax"},
|
||||
{SS$_BADIRECTORY, "%SYSTEM-W-BADIRECTORY, bad directory file format"},
|
||||
{SS$_BADPARAM, "%SYSTEM-F-BADPARAM, bad parameter value"},
|
||||
{SS$_BUGCHECK, "%SYSTEM-F-BUGCHECK, internal consistency failure"},
|
||||
{SS$_DATACHECK, "%SYSTEM-F-DATACHECK, write check error"},
|
||||
{SS$_DEVICEFULL, "%SYSTEM-W-DEVICEFULL, device full - allocation failure"},
|
||||
{SS$_DEVMOUNT, "%SYSTEM-F-DEVMOUNT, device is already mounted"},
|
||||
{SS$_DEVNOTALLOC, "%SYSTEM-W-DEVNOTALLOC, device not allocated"},
|
||||
{SS$_DEVNOTDISM, "%SYSTEM-F-DEVNOTDISM, device not dismounted"},
|
||||
{SS$_DEVNOTMOUNT, "%SYSTEM-F-DEVNOTMOUNT, device is not mounted"},
|
||||
{SS$_DUPFILENAME, "%SYSTEM-W-DUPFILENAME, duplicate file name"},
|
||||
{SS$_DUPLICATE, "%SYSTEM-F-DUPLNAM, duplicate name"},
|
||||
{SS$_ENDOFFILE, "%SYSTEM-W-ENDOFFILE, end of file"},
|
||||
{SS$_FILELOCKED, "%SYSTEM-W-FILELOCKED, file is deaccess locked"},
|
||||
{SS$_FILESEQCHK, "%SYSTEM-W-FILESEQCHK, file identification sequence number check"},
|
||||
{SS$_ILLEFC, "%SYSTEM-F-ILLEFC, illegal event flag cluster"},
|
||||
{SS$_INSFMEM, "%SYSTEM-F-INSFMEM, insufficient dynamic memory"},
|
||||
{SS$_ITEMNOTFOUND, "%SYSTEM-W-ITEMNOTFOUND, requested item cannot be returned"},
|
||||
{SS$_IVCHAN, "%SYSTEM-F-IVCHAN, invalid I/O channel"},
|
||||
{SS$_IVDEVNAM, "%SYSTEM-F-IVDEVNAM, invalid device name"},
|
||||
{SS$_NOIOCHAN, "%SYSTEM-F-NOIOCHAN, no I/O channel available"},
|
||||
{SS$_NOMOREFILES, "%SYSTEM-W-NOMOREFILES, no more files"},
|
||||
{SS$_NORMAL, "%SYSTEM-S-NORMAL, normal successful completion"},
|
||||
{SS$_NOSUCHDEV, "%SYSTEM-W-NOSUCHDEV, no such device available"},
|
||||
{SS$_NOSUCHFILE, "%SYSTEM-W-NOSUCHFILE, no such file"},
|
||||
{SS$_NOSUCHVOL, "%SYSTEM-E-NOSUCHVOL, No such volume"},
|
||||
{SS$_NOTINSTALL, "%SYSTEM-F-NOTINSTALL, writable shareable images must be installed"},
|
||||
{SS$_PARITY, "%SYSTEM-F-PARITY, parity error"},
|
||||
{SS$_UNSUPVOLSET, "%SYSTEM-E-UNSUPVOLSET, Volume set not supported"},
|
||||
{SS$_WASCLR, "%SYSTEM-S-NORMAL, normal successful completion"},
|
||||
{SS$_WASSET, "%SYSTEM-S-WASSET, Event flag was set"},
|
||||
{SS$_WRITLCK, "%SYSTEM-F-WRITLCK, write lock error"},
|
||||
{SS$_OFFSET_TOO_BIG, "SYSTEM-F-OFFSET_TOO_BIG, Volume is too large for local file system: needs 64-bit I/O" },
|
||||
{0, NULL},
|
||||
};
|
||||
unsigned int code;
|
||||
const char *const txtcode;
|
||||
char *text;
|
||||
} vms2text[] = {
|
||||
MSG(RMS$_BUG, "fatal RMS condition detected, process deleted")
|
||||
MSG(RMS$_DIR, "error in directory name")
|
||||
MSG(RMS$_DNF, "directory not found")
|
||||
MSG(RMS$_EOF, "end of file detected")
|
||||
MSG(RMS$_ESS, "expanded string area too small")
|
||||
MSG(RMS$_FNF, "file not found")
|
||||
MSG(RMS$_FNM, "error in file name")
|
||||
MSG(RMS$_IFI, "invalid internal file identifier (IFI) value")
|
||||
MSG(RMS$_NAM, "invalid NAM block or NAM block not accessible")
|
||||
MSG(RMS$_NMF, "no more files found")
|
||||
MSG(RMS$_RSS, "invalid resultant string size")
|
||||
MSG(RMS$_RSZ, "invalid record size")
|
||||
MSG(RMS$_RTB, "%u byte record too large for user's buffer") /* !UL byte */
|
||||
MSG(RMS$_WCC, "invalid wild card context (WCC) value")
|
||||
MSG(RMS$_WLD, "invalid wildcard operation")
|
||||
MSG(SS$_ABORT, "abort")
|
||||
MSG(SS$_BADFILENAME, "bad file name syntax")
|
||||
MSG(SS$_BADIRECTORY, "bad directory file format")
|
||||
MSG(SS$_BADPARAM, "bad parameter value")
|
||||
MSG(SS$_BUGCHECK, "internal consistency failure")
|
||||
MSG(SS$_DATACHECK, "write check error")
|
||||
MSG(SS$_DEVICEFULL, "device full - allocation failure")
|
||||
MSG(SS$_DEVMOUNT, "device is already mounted")
|
||||
MSG(SS$_DEVNOTALLOC, "device not allocated")
|
||||
MSG(SS$_DEVNOTDISM, "device not dismounted")
|
||||
MSG(SS$_DEVNOTMOUNT, "device is not mounted")
|
||||
MSG(SS$_DUPFILENAME, "duplicate file name")
|
||||
MSG(SS$_DUPLICATE, "duplicate name")
|
||||
MSG(SS$_ENDOFFILE, "end of file")
|
||||
MSG(SS$_FILELOCKED, "file is deaccess locked")
|
||||
MSG(SS$_FILESEQCHK, "file identification sequence number check")
|
||||
MSG(SS$_ILLEFC, "illegal event flag cluster")
|
||||
MSG(SS$_INSFMEM, "insufficient dynamic memory")
|
||||
MSG(SS$_ITEMNOTFOUND, "requested item cannot be returned")
|
||||
MSG(SS$_NOMOREDEV, "no more devices")
|
||||
MSG(SS$_IVCHAN, "invalid I/O channel")
|
||||
MSG(SS$_IVDEVNAM, "invalid device name")
|
||||
MSG(SS$_NOIOCHAN, "no I/O channel available")
|
||||
MSG(SS$_NOMOREFILES, "no more files")
|
||||
MSG(SS$_NORMAL, "normal successful completion")
|
||||
MSG(SS$_NOSUCHDEV, "no such device available")
|
||||
MSG(SS$_NOSUCHFILE, "no such file")
|
||||
MSG(SS$_NOSUCHVOL, "No such volume")
|
||||
MSG(SS$_NOTINSTALL, "writable shareable images must be installed")
|
||||
MSG(SS$_PARITY, "parity error")
|
||||
MSG(SS$_UNSUPVOLSET, "Volume set not supported")
|
||||
MSG(SS$_WASCLR, "normal successful completion")
|
||||
MSG(SS$_WASSET, "Event flag was set")
|
||||
MSG(SS$_WRITLCK, "write lock error")
|
||||
MSG(SS$_OFFSET_TOO_BIG, "Volume is too large for local file system: needs 64-bit I/O" )
|
||||
{0, NULL, NULL},
|
||||
{ SS$_NOMSG, "SS$_NOMSG", notext }
|
||||
};
|
||||
|
||||
const char *getmsg( unsigned int vmscode, unsigned int flags ) {
|
||||
const char fmt[] = "%%SYSTEM-E-NOSUCHMSG, Unknown message code %08X";
|
||||
static char buf[sizeof(fmt)+8+1];
|
||||
const char *txtp = NULL;
|
||||
static char *buf = NULL;
|
||||
static size_t bufsize = 0;
|
||||
|
||||
for( mp = vms2text; mp->text; mp++ ) {
|
||||
if( vmscode == mp-> code ) {
|
||||
txtp = mp->text;
|
||||
break;
|
||||
}
|
||||
/******************************************************************* xpand() */
|
||||
|
||||
static int xpand( size_t used, size_t add ) {
|
||||
char *nbuf;
|
||||
size_t need;
|
||||
|
||||
need = used + add + 1; /* Always allow for \0 */
|
||||
if( need < bufsize ) {
|
||||
return 1;
|
||||
}
|
||||
if( txtp == NULL ) {
|
||||
txtp = buf;
|
||||
nbuf = realloc( buf, need + 16 + 1); /* 16 minimizes reallocs */
|
||||
if( nbuf == NULL ) {
|
||||
return 0;
|
||||
}
|
||||
if( flags == MSG_TEXT ) {
|
||||
txtp = strchr( txtp, ',' );
|
||||
if( txtp == NULL ) abort();
|
||||
return txtp+2;
|
||||
buf = nbuf;
|
||||
bufsize = need + 16 + 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/******************************************************************* getmsg() */
|
||||
|
||||
const char *getmsg( unsigned int vmscode, unsigned int flags, ... ) {
|
||||
const struct VMSMSG *mp = NULL;
|
||||
const struct VMSFAC *fp = NULL;
|
||||
|
||||
if( !(flags & MSG_FULL) )
|
||||
flags = (flags & ~MSG_FULL) | MSG_FULL;
|
||||
|
||||
while( 1 ) {
|
||||
size_t i = 0, len;
|
||||
|
||||
do {
|
||||
if( flags & (MSG_FACILITY|MSG_SEVERITY|MSG_NAME) ) {
|
||||
if( !xpand( i, 1 ) )
|
||||
return strerror( errno );
|
||||
buf[i++] = '%';
|
||||
|
||||
if( fp == NULL ) {
|
||||
for( fp = fac2text; fp->text != NULL; fp++ ) {
|
||||
if( fp->code == $VMS_STATUS_FAC_NO(vmscode) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( fp->text == NULL )
|
||||
break;
|
||||
if( flags & MSG_FACILITY ) {
|
||||
len = strlen( fp->text );
|
||||
if( !xpand( i, len +1 ) )
|
||||
return strerror( errno );
|
||||
|
||||
memcpy( buf+i, fp->text, len );
|
||||
i += len;
|
||||
if( flags & (MSG_SEVERITY|MSG_NAME) )
|
||||
buf[i++] = '-';
|
||||
}
|
||||
if( flags & MSG_SEVERITY ) {
|
||||
if( !xpand( i, 2 ) )
|
||||
return strerror( errno );
|
||||
buf[i++] = sev2text[$VMS_STATUS_SEVERITY(vmscode)];
|
||||
if( flags & MSG_NAME )
|
||||
buf[i++] = '-';
|
||||
}
|
||||
if( flags & MSG_NAME ) {
|
||||
char *p;
|
||||
|
||||
if( mp == NULL ) {
|
||||
for( mp = vms2text; mp->text != NULL; mp++ ) {
|
||||
if( $VMS_STATUS_COND_ID(vmscode) == mp-> code )
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( mp->text == NULL )
|
||||
break;
|
||||
p = strchr( mp->txtcode, '_' );
|
||||
if( p == NULL )
|
||||
abort();
|
||||
len = strlen( ++p );
|
||||
if( !xpand( i, len ) )
|
||||
return strerror( errno );
|
||||
memcpy( buf+i, p, len );
|
||||
i += len;
|
||||
}
|
||||
if( flags & MSG_TEXT ) {
|
||||
if( !xpand( i, 2 ) )
|
||||
return strerror( errno );
|
||||
buf[i++] = ',';
|
||||
buf[i++] = ' ';
|
||||
}
|
||||
}
|
||||
if( flags & MSG_TEXT ) {
|
||||
va_list ap;
|
||||
if( mp == NULL ) {
|
||||
for( mp = vms2text; mp->text; mp++ ) {
|
||||
if( $VMS_STATUS_COND_ID(vmscode) == mp-> code )
|
||||
break;
|
||||
}
|
||||
if( mp->text == NULL )
|
||||
break;
|
||||
}
|
||||
if( flags & MSG_WITHARGS ) {
|
||||
va_start( ap, flags );
|
||||
len = vsnprintf( buf+i, 1, mp->text, ap );
|
||||
va_end( ap );
|
||||
} else
|
||||
len = strlen( mp->text );
|
||||
if( !xpand( i, len ) )
|
||||
return strerror( errno );
|
||||
if( flags & MSG_WITHARGS ) {
|
||||
va_start( ap, flags );
|
||||
(void) vsnprintf( buf+i, len+1, mp->text, ap );
|
||||
va_end( ap );
|
||||
} else
|
||||
memcpy( buf+i, mp->text, len );
|
||||
i += len;
|
||||
}
|
||||
buf[i] = '\0';
|
||||
return buf;
|
||||
} while( 0 );
|
||||
|
||||
if( fp == NULL || fp->text == NULL )
|
||||
fp = fac2text + (sizeof(fac2text)/sizeof(fac2text[0])) -1;
|
||||
|
||||
mp = vms2text + (sizeof(vms2text)/sizeof(vms2text[0])) -1;
|
||||
snprintf( notext, sizeof(notext), nofmt, vmscode );
|
||||
}
|
||||
return txtp;
|
||||
}
|
||||
|
||||
/******************************************************************* sysmsg_rundown() */
|
||||
|
||||
void sysmsg_rundown( void ) {
|
||||
free( buf );
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -1,8 +1,18 @@
|
||||
#ifndef SYSMSG_H
|
||||
#define SYSMSG_H
|
||||
|
||||
#define MSG_TEXT 0
|
||||
#define MSG_FULL 1
|
||||
const char *getmsg( unsigned int vmscode, unsigned int flags );
|
||||
#include <stdarg.h>
|
||||
|
||||
#define MSG_FACILITY (1 << 0)
|
||||
#define MSG_SEVERITY (1 << 1)
|
||||
#define MSG_NAME (1 << 2)
|
||||
#define MSG_TEXT (1 << 3)
|
||||
#define MSG_WITHARGS (1 << 4)
|
||||
|
||||
#define MSG_FULL (MSG_FACILITY|MSG_SEVERITY|MSG_NAME|MSG_TEXT)
|
||||
|
||||
const char *getmsg( unsigned int vmscode, unsigned int flags, ... );
|
||||
|
||||
void sysmsg_rundown( void );
|
||||
|
||||
#endif
|
||||
|
||||
2
extracters/ods2/valgrind_suppressions_ods2
Normal file
2
extracters/ods2/valgrind_suppressions_ods2
Normal file
@ -0,0 +1,2 @@
|
||||
# suppression rules for ods2
|
||||
# The goal is that there aren't any.
|
||||
46
extracters/ods2/valgrind_suppressions_readline
Normal file
46
extracters/ods2/valgrind_suppressions_readline
Normal file
@ -0,0 +1,46 @@
|
||||
# Suppression rules for users of readline
|
||||
# This attempts to suppress the stuff that
|
||||
# readline creates from termcap, etc, while
|
||||
# still tracking the data returned to the caller.
|
||||
#
|
||||
# Most history memory can be released with the
|
||||
# clear_history() call - after write_history
|
||||
# if desired. However, the master history
|
||||
# structure remains. Don't know how to
|
||||
# distinguish the two, so the history calls
|
||||
# that add lines are suppressed. Note
|
||||
# that read_history calls add_history internally.
|
||||
|
||||
{
|
||||
history
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
...
|
||||
fun:add_history
|
||||
}
|
||||
{
|
||||
readline
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
...
|
||||
fun:rl_initialize
|
||||
...
|
||||
fun:readline
|
||||
}
|
||||
{
|
||||
readline
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
...
|
||||
fun:init_line_structures
|
||||
...
|
||||
fun:readline
|
||||
}
|
||||
{
|
||||
readline
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: reachable
|
||||
...
|
||||
fun:rl_set_prompt
|
||||
fun:readline
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user