[Info-vax] RMS and SSIO (again)

Arne Vajhøj arne at vajhoej.dk
Mon Jan 10 14:17:25 EST 2022


On 1/9/2022 9:57 PM, Greg Tinkler wrote:
> frankly I am not surprised that the offshore VMS group could fix it,
> I am surprised the the back in the 80/90's the CRTL folk did not talk
> with the RMS group and have a good solution in place to start with.
> But then C IO was a very low priority, you either did RMS or your own
> $QIO.  Now with open source it is a very different ball game.
> 
> SSIO is not and was never a well designed solution.  It looks more
> like a *nix persons view of how VMS should work.

> The SYS$MODIFY's function is what you just described, after an open,
> get RMS to pretend that the file is of a different format.  And no it
> is not just 20 lines, that was the few line to help those that don't
> understand VMS/RMS what is possible.  Careful code design would allow
> the initial open to use UDF so you don't need to do it each IO.
> 
> "There is no need for all of that. It can be done other ways." Well
> if that is the case then please put your code up... and clearly you
> don't think SSIO is a good solution either. 8-))

I think SSIO is the only solution.

I don't believe the UDF hack is the solution.

But the UDF hack is not difficult to write.

Little bit more than 20 lines. With single reset call
for multiple files I ended up with a whooping 62 lines
of code.

$ type hack.c
#include <stdio.h>

#include <starlet.h>
#include <lib$routines.h>
#include <rms.h>
#include <rmedef.h>

static void set_rfm(struct FAB *fab, long int rfm)
{
     long int stat;
     fab->fab$l_fop |= FAB$M_ESC;
     fab->fab$l_ctx |= RME$C_SETRFM;
     fab->fab$b_rfm = rfm;
     stat = sys$modify(fab,0,0);
     if(stat & 1 == 0) lib$signal(stat);
}

static long int set_rfm_ext(struct FAB *fab, long int rfm)
{
     long int stat;
     long int oldrfm;
     stat = sys$open(fab,0,0);
     if(stat & 1 == 0) lib$signal(stat);
     oldrfm = fab->fab$b_rfm;
     set_rfm(fab, rfm);
     stat = sys$close(fab,0,0);
     if(stat & 1 == 0) lib$signal(stat);
     return oldrfm;
}

#define MAX_FAB 100
static long int savrfm[MAX_FAB];
static struct FAB *savfab[MAX_FAB] = { NULL };

int hack_udfify_callback(int *first_arg, struct FAB *fab, struct RAB *rab)
{
     int i;
     long int oldrfm;
     oldrfm = set_rfm_ext(fab, FAB$C_UDF);
     for(i = 0; i < MAX_FAB; i++)
     {
         if(savfab[i] == NULL)
         {
             savrfm[i] = oldrfm;
             savfab[i] = fab;
             break;
         }
     }
     return 0;
}

void hack_reset()
{
     int i;
     for(i = 0; i < MAX_FAB; i++)
     {
         if(savfab[i] != NULL)
         {
             set_rfm(savfab[i], savrfm[i]);
         }
     }
}

It works as expected.

$ type demo.c
#include <stdio.h>
#include <stdlib.h>

#include "hack.h"

void test1(char *fnm)
{
    char cmd[1024];
    sprintf(cmd, "write sys$output f$file_attributes(\"%s\",\"RFM\")", fnm);
    system(cmd);
}

void test()
{
     test1("z.1");
     test1("z.2");
     test1("z.3");
}

int main()
{
     FILE *fp1, *fp2, *fp3;
     test();
     printf("Open files (2 with udfify callback and 1 without)\n");
     fp1 = fopen("z.1", "r+", "shr=get", "acc", hack_udfify_callback, NULL);
     fp2 = fopen("z.2", "r+", "shr=get", "acc", hack_udfify_callback, NULL);
     fp3 = fopen("z.3", "r+", "shr=get");
     test();
     printf("Reset and close files\n");
     hack_reset();
     fclose(fp1);
     fclose(fp2);
     fclose(fp3);
     test();
     return 0;
}

$ cc demo
$ cc hack
$ link demo+hack
$ run demo
VAR
VAR
VAR
Open files (2 with udfify callback and 1 without)
UDF
UDF
VAR
Reset and close files
VAR
VAR
VAR

I just don't think it is useful for anything.

Arne




More information about the Info-vax mailing list