I don't have "type /tail=[n]" or "type /continuous" what do I do - VMS

This is a discussion on I don't have "type /tail=[n]" or "type /continuous" what do I do - VMS ; Hello, I am looking for a way to implement Unix's tail command on the Vax. Thank you, Chris...

+ Reply to Thread
Results 1 to 17 of 17

Thread: I don't have "type /tail=[n]" or "type /continuous" what do I do

  1. I don't have "type /tail=[n]" or "type /continuous" what do I do

    Hello,

    I am looking for a way to implement Unix's tail command on the Vax.

    Thank you,
    Chris

  2. Re: I don't have "type /tail=[n]" or "type /continuous" what do I do


    "Christopher Lusardi" wrote in message
    news:6d4177f2-c55d-4438-866c-80237df088d2@s1g2000pra.googlegroups.com...

    > I am looking for a way to implement Unix's tail command on the Vax.


    There is a tail implementation on the VMS Freeware CDs.
    Google will find you a copy.



  3. Re: I don't have "type /tail=[n]" or "type /continuous" what do I do

    On Sep 11, 8:01*am, "Richard Brodie" wrote:
    > There is a tail implementation on the VMS Freeware CDs.


    Ha, I am not allowed to do that!

    Chris



  4. Re: I don't have "type /tail=[n]" or "type /continuous" what do I do


    "Christopher Lusardi" wrote in message
    news:e4994777-f99e-44f8-a260-6e0e1083194e@i24g2000prf.googlegroups.com...
    On Sep 11, 8:01 am, "Richard Brodie" wrote:
    > There is a tail implementation on the VMS Freeware CDs.


    Ha, I am not allowed to do that!

    Chris

    Why not? You just take this code and rewrite it yourself. There is a C
    based version. So you just pull the source listing up and type it into a
    DECterm window yurself. What are we missing here?


  5. Re: I don't have "type /tail=[n]" or "type /continuous" what do Ido

    Christopher Lusardi wrote:
    > Hello,
    >
    > I am looking for a way to implement Unix's tail command on the Vax.
    >
    > Thank you,
    > Chris


    type/tail= works for me on a vax running vms 7.2

  6. Re: I don't have "type /tail=[n]" or "type /continuous" what do I do

    On Sep 11, 8:47*am, sol gongola wrote:
    > Christopher Lusardi wrote:
    > > Hello,

    >
    > > * I am looking for a way to implement Unix's tail command on the Vax.

    >
    > > Thank you,
    > > Chris

    >
    > type/tail= works for me on a vax running vms 7.2


    This is not implemented on my system, neither is type /continuous/
    interval...

    Chris

  7. Re: I don't have "type /tail=[n]" or "type /continuous" what do I do

    On Sep 11, 9:02*am, Christopher Lusardi wrote:
    > On Sep 11, 8:47*am, sol gongola wrote:
    >
    > > Christopher Lusardi wrote:
    > > > Hello,

    >
    > > > * I am looking for a way to implement Unix's tail command on the Vax.

    >
    > > > Thank you,
    > > > Chris

    >
    > > type/tail= works for me on a vax running vms 7.2

    >
    > This is not implemented on my system, neither is type /continuous/
    > interval...


    Then perhaps you'd help us out here by telling us what
    *is* implemented on your system? I.e., what version
    of VMS are you running ($ Show System/NoProcess, or
    if *that* is also not available to you, how about you just
    cut-n-paste the first line of output from $ Show System
    which you *do* have...for sure!).

    Guessing on usenet gets old, fast. ;-(

    -Ken

  8. Re: I don't have "type /tail=[n]" or "type /continuous" what do I do

    In article <6d4177f2-c55d-4438-866c-80237df088d2@s1g2000pra.googlegroups.com>, Christopher Lusardi writes:
    > Hello,
    >
    > I am looking for a way to implement Unix's tail command on the Vax.


    1) use type/tail

    2) download tail from gnu


  9. Re: I don't have "type /tail=[n]" or "type /continuous" what do Ido

    Christopher Lusardi wrote:
    > Hello,
    >
    > I am looking for a way to implement Unix's tail command on the Vax.
    >
    > Thank you,
    > Chris


    I have a tail program in C. Do you have some place I can FTP it to?

    Or, if your version of VMS is reasonably up-to-date, you could simply
    use TYPE /TAIL.

  10. Re: I don't have "type /tail=[n]" or "type /continuous" what do Ido

    Christopher Lusardi wrote:
    > On Sep 11, 8:47 am, sol gongola wrote:
    >> Christopher Lusardi wrote:
    >>> Hello,
    >>> I am looking for a way to implement Unix's tail command on the Vax.
    >>> Thank you,
    >>> Chris

    >> type/tail= works for me on a vax running vms 7.2

    >
    > This is not implemented on my system, neither is type /continuous/
    > interval...
    >
    > Chris



    Then you need to describe your system in far greater detail. I forget
    just when TYPE /TAIL was implemented but it has been around for a LONG
    time. Maybe as far back as V5.5-2 and certainly by 6.2.

  11. Re: I don't have "type /tail=[n]" or "type /continuous" what do I do

    > On Sep 11, 9:21*am, Ken.Fairfi...@gmail.com wrote:
    > what version
    > of VMS are you running ($ Show System/NoProcess


    5.5

    Chris

  12. Re: I don't have "type /tail=[n]" or "type /continuous" what do I do

    On Sep 11, 11:49 am, "Richard B. Gilbert"
    wrote:
    > Christopher Lusardi wrote:
    > > On Sep 11, 8:47 am, sol gongola wrote:
    > >> Christopher Lusardi wrote:
    > >>> Hello,
    > >>> I am looking for a way to implement Unix's tail command on the Vax.
    > >>> Thank you,
    > >>> Chris
    > >> type/tail= works for me on a vax running vms 7.2

    >
    > > This is not implemented on my system, neither is type /continuous/
    > > interval...

    >
    > > Chris

    >
    > Then you need to describe your system in far greater detail. I forget
    > just when TYPE /TAIL was implemented but it has been around for a LONG
    > time. Maybe as far back as V5.5-2 and certainly by 6.2.



    Richard,

    6.2 has it (just checked).However, the freeware tail (which I got as
    part of the UUCP implementation) is/was more forgiving of different
    file structures, etc.

    - Bob Gezelter, http://www.rlgsc.com

  13. Re: I don't have "type /tail=[n]" or "type /continuous" what do I do

    On Sep 11, 9:49*am, "Richard B. Gilbert"
    wrote:
    > Then you need to describe your system in far greater detail..


    V5.5-2H4

    Chris


  14. Re: I don't have "type /tail=[n]" or "type /continuous" what do I do

    On Thu, 11 Sep 2008 11:09:34 -0700, Christopher Lusardi
    wrote:

    > On Sep 11, 9:49*am, "Richard B. Gilbert"
    > wrote:
    >> Then you need to describe your system in far greater detail..

    >
    > V5.5-2H4


    Curious what prevented you from upgrading to a later version?

    >
    > Chris
    >




    --
    PL/I for OpenVMS
    www.kednos.com

  15. Re: I don't have "type /tail=[n]" or "type /continuous" what do I do

    In article
    <6d4177f2-c55d-4438-866c-80237df088d2@s1g2000pra.googlegroups.com>,
    Christopher Lusardi writes:

    > I am looking for a way to implement Unix's tail command on the Vax.


    #include descrip /* descriptor details */
    #include stdio /* for printf and stuff */
    #include rms /* for the "real" I/O stuff */
    #include dvidef /* stuff for the GETDVI ss */
    #include dcdef /* device classes */
    #include iodef /* QIO stuff */
    #include msgdef /* mailbox stuff */
    #include ssdef /* completion codes */

    struct FAB inp_fab; /* Input fab/rab/xab */
    struct RAB inp_rab;
    struct XABFHC inp_xab;

    struct FAB out_fab; /* Output fab/rab */
    struct RAB out_rab;

    typedef struct { /* define an item list struct */
    short length; /* length of buffer */
    short code; /* item code */
    void *ptr; /* ptr to buffer */
    void *retlen; /* ptr to return length */
    } Item;

    typedef struct { /* Genernic IOSB struct */
    short status;
    short length;
    long devdepend;
    } Iosb;

    typedef struct {
    unsigned long block; /* block # */
    unsigned short offset; /* offset within block */
    unsigned short length; /* record length */
    } Rfa;

    typedef struct { /* VMS 64 bit quadword time */
    long lsb;
    long msb;
    } VMSTime;

    unsigned char inp_buf[65536-512]; /* 127 blocks of buffer space */
    int the_safe_way=0; /* If != then read var files front to back */
    int monitor; /* if != then loop on display of tail */
    int sec=5; /* delay time in seconds */
    int tti_chan; /* channel to use to look for stop code */
    char tti_text[8]; /* room for terminal input */
    Iosb tti_iosb; /* IOSB for terminal input */
    int tti_class; /* SYS$INPUT device class */
    int tto_class; /* SYS$OUTPUT device class */
    int tto_page; /* SYS$OUTPUT page size (if tto_class == DC$_TERM) */
    int were_done; /* if !=, signals monitor complete */
    int last_rfa_blk; /* saved rfa of last record read */
    int last_rfa_off;

    char default_string[] = "SYS$DISK:[].LOG"; /* default input filename */

    Item tt_dvi[] = { /* An item list used to get SYS$xxx class */
    {4,DVI$_DEVCLASS,&tto_class,0},
    {4,DVI$_TT_PAGE,&tto_page,0},
    {0,0,0,0}
    };

    $DESCRIPTOR(sysin,"SYS$INPUT");
    $DESCRIPTOR(sysout,"SYS$OUTPUT");

    /* rfa stands for "record file address" */

    Rfa *rfas; /* ptr to array of rfa structs */
    int record_count=23; /* number of records to output */
    int maxargs; /* records size of next_file array */
    char **next_file; /* pts to array of char ptrs to filenames */
    VMSTime delay = {-5*10*1000*1000, /* 64 bit VMS delta time format for monitor timer... */
    -1}; /* ...initialized to 5 seconds */

    char *mini_help_msg[] = {
    "TAIL version 2.4, 09/10/91. D. Shepperd, shepperd@dms.UUCP\n",
    "Usage: TAIL [/record_count] [/S] [/F] [/T secs] input_file [output_file]\n",
    0
    };

    char *help_msg[] = {
    "where: \"[]\" indicates optional data\n",
    " \"/record_count\" is decimal number of records desired\n",
    " \"/S\" indicates to use the \"safer\" mode\n",
    " \"/F\" monitor tail end of file (5 second sample rate)\n",
    " \"/T secs\" monitor tail end of file with sample rate of \"secs\"\n",
    " \"input_file\" is the input filename (can have wildcards)\n",
    " \"output_file\" is output filename (bogus if wildcards on input)\n",
    "Note that a \"-\" can be used in place of the \"/\" to delimit options.\n",
    "White space is required between all arguments (including the /T and secs).\n",
    "Options may appear in any order, but all must preceed filename(s).\n",
    0
    };


    void mini_help()
    {
    char **s;
    for (s=mini_help_msg;*s;++s) fputs(*s,stderr); /* show mini help */
    return;
    }

    void show_help()
    {
    char **s;
    mini_help();
    for (s = help_msg;*s;++s) fputs(*s,stderr); /* display help message */
    return;
    }

    int main(int argc,char *argv[])
    {
    int param; /* Parameter counter */
    int err; /* place to hold rms errors */
    int rfm; /* loaded with record format code */
    int i, files;

    err = sys$getdviw(0,0,&sysin,&tt_dvi,0,0,0,0);
    if ((err&1) == 0) return err;
    tti_class = tto_class;

    err = sys$getdviw(0,0,&sysout,&tt_dvi,0,0,0,0);
    if ((err&1) == 0) return err;
    if (tto_class == DC$_TERM) record_count = tto_page > 2 ? tto_page-1 : 2;

    inp_fab = cc$rms_fab; /* init the input fab/rab/xab */
    inp_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPI;
    inp_fab.fab$b_fac = FAB$M_GET|FAB$M_BRO;
    inp_rab = cc$rms_rab;
    inp_rab.rab$l_ubf = inp_buf;
    inp_rab.rab$w_usz = sizeof(inp_buf); /* assume to read the max */
    inp_xab = cc$rms_xabfhc;
    inp_rab.rab$l_fab = &inp_fab; /* tell rab where fab is */
    inp_fab.fab$l_xab = &inp_xab; /* tell fab where xab is */
    inp_fab.fab$l_dna = default_string; /* say input file defaults */
    inp_fab.fab$b_dns = sizeof(default_string)-1;

    param = 1; /* start looking at argv[1] */
    --argc; /* skip the image name */
    while(1) { /* get all the command options */
    char c,*s;
    if (argc < 1) break;
    s = argv[param];
    c = *s++;
    if (c == '/' || c == '-') {
    c = *s++;
    c = toupper(c);
    switch (c) {
    int secs;
    case '?':
    case 'H':
    show_help();
    return 0x10000003;
    case 'S': /* safer mode */
    the_safe_way = 1;
    break;
    case 'T': /* set monitor rate in seconds */
    if (*s == 0) {
    if (--argc < 1) {
    fputs("Missing delay time parameter\n",stderr);
    mini_help();
    return 0x10000002;
    }
    s = argv[++param];
    }
    if (sscanf(s,"%d",&secs) != 1 || secs <= 0 || secs > 2000) {
    fprintf(stderr,"Invalid delay time parameter: %s\n",s);
    fputs("Time value must be between 1 and 2000 secs\n",stderr);
    mini_help();
    return 0x10000002;
    }
    delay.lsb = -secs*10*1000*1000;
    /* fall through to /F to default to monitor mode if /T specified */
    case 'F': /* set monitor mode */
    monitor = 1;
    break;
    default: /* assume the param is a record count */
    --s; /* backup to the first char of the record count */
    if (sscanf(s,"%d",&record_count) != 1 || record_count <= 0) {
    fprintf(stderr,"Invalid record count parameter: %s\n",s);
    mini_help();
    return 0x10000002;
    }
    }
    ++param;
    --argc;
    } else {
    break;
    }
    }
    record_count++; /* Fix of wrong record_count. KAR - 6-mar-1990 */
    if (argc < 1) {
    show_help();
    exit(0x10000003);
    }
    files = fgen(argv[param], &next_file, &maxargs); /* deal with wildcards */
    if (files < 1) {
    fputs("No input file(s) found\n",stderr);
    return 0x10000002;
    }
    if (monitor) {
    if (tti_class != DC$_TERM) {
    fputs("Cannot monitor files if SYS$INPUT is not a terminal\n",stderr);
    monitor = 0;
    } else {
    err = sys$assign(&sysin,&tti_chan,0,0);
    if ((err&1) == 0) {
    fputs("Error assigning channel to SYS$INPUT, monitor mode disabled\n",stderr);
    monitor = 0;
    }
    que_ttiread(); /* que up a read to the terminal */
    }
    }
    for (i = 0; i < files; i++) {
    if (files > 1) {
    if (tto_class == DC$_TERM) {
    printf("\r\n \033[7m**************** %s ****************\033[0m",
    next_file[i]);
    } else {
    printf("\r\n **************** %s ****************",
    next_file[i]);
    }
    }
    inp_fab.fab$l_fna = next_file[i]; /* input filename is next param */
    inp_fab.fab$b_fns = strlen(next_file[i]);
    if (((err=sys$open(&inp_fab))&1) == 0) {
    fputs("Error opening input file\n",stderr);
    exit(err);
    }
    if (((err=sys$connect(&inp_rab))&1) == 0) {
    fputs("Error connecting input rab\n",stderr);
    exit(err);
    }
    if (inp_fab.fab$b_org != FAB$C_SEQ) {
    char *oldtype="UNKNOWN";
    if (inp_fab.fab$b_org == FAB$C_REL) oldtype = "RELATIVE";
    if (inp_fab.fab$b_org == FAB$C_IDX) oldtype = "INDEXED";
    if (inp_fab.fab$b_org == FAB$C_HSH) oldtype = "HASHED";
    fprintf(stderr,"Input file organization is %s. This program only supports SEQUENTIAL.\n",
    oldtype);
    exit(0x10000002);
    }
    if (inp_fab.fab$b_rfm == FAB$C_UDF || inp_fab.fab$b_rfm > FAB$C_STMCR) {
    fputs("Input file has undefined or unsupported record format.\n",stderr);
    exit(0x10000002);
    }
    out_fab = cc$rms_fab; /* init the output fab */
    out_fab.fab$b_bks = inp_fab.fab$b_bks; /* make rest same as input */
    out_fab.fab$w_bls = inp_fab.fab$w_bls;
    out_fab.fab$w_deq = inp_fab.fab$w_deq;
    out_fab.fab$b_fac = FAB$M_PUT;
    out_fab.fab$b_fsz = inp_fab.fab$b_fsz;
    out_fab.fab$w_mrs = inp_fab.fab$w_mrs;
    out_fab.fab$b_rat = inp_fab.fab$b_rat;
    out_fab.fab$b_rfm = inp_fab.fab$b_rfm;
    out_rab = cc$rms_rab;
    out_rab.rab$l_fab = &out_fab; /* tell rab where fab is */
    if (--argc >= 1) {
    out_fab.fab$l_fna = argv[++param]; /* output filename is next param */
    } else {
    out_fab.fab$l_fna = "SYS$OUTPUT:"; /* else default */
    }
    out_fab.fab$b_fns = strlen(out_fab.fab$l_fna);
    if (((err=sys$create(&out_fab))&1) == 0) {
    fputs("Error opening output file\n",stderr);
    exit(err);
    }
    if (((err=sys$connect(&out_rab))&1) == 0) {
    fputs("Error connecting output rab\n",stderr);
    exit(err);
    }
    rfm = inp_fab.fab$b_rfm; /* pickup rfm code */
    last_rfa_blk = last_rfa_off = 0; /* start at top of file */
    were_done = 0;
    while (1) {
    long oldebk;
    int oldffb;
    oldebk = inp_xab.xab$l_ebk; /* remember the old end of file mark */
    oldffb = inp_xab.xab$w_ffb;
    if (last_rfa_blk != 0) { /* if we've already been through the file */
    err = skip_through(); /* then just start where we left off */
    } else {
    switch (inp_fab.fab$b_rfm) {
    case FAB$C_FIX:
    err = do_fixed();
    break;
    case FAB$C_VAR:
    err = do_var();
    break;
    case FAB$C_VFC:
    err = do_var();
    break;
    case FAB$C_STM:
    err = do_stream(2);
    break;
    case FAB$C_STMCR:
    err = do_stream(1);
    break;
    case FAB$C_STMLF:
    err = do_stream(0);
    break;
    default:
    err = 0x10000004;
    fputs("Unknown record format\n",stderr);
    exit(err);
    }
    }
    if ((err&1) == 0) {
    if (err != RMS$_EOF) {
    fputs("Error reading input\n",stderr);
    exit(err);
    }
    }
    if (!monitor || were_done == 1) break;
    while (!were_done) {
    sys$schdwk(0,0,&delay,0);
    sys$hiber();
    err = sys$display(&inp_fab); /* see if stuff has been added to file */
    if ((err&1) == 0) {
    fputs("Error doing $DISPLAY on input, monitor mode cancelled\n",stderr);
    were_done = 1;
    break;
    }
    if (inp_xab.xab$l_ebk == oldebk && inp_xab.xab$w_ffb == oldffb) {
    continue; /* eof hasn't moved, continue waiting */
    }
    /* This part is goofy. One would think that a simple sys$display would be all that */
    /* should be required, but nooooooo.... DEC has set some internal flags that will */
    /* not let me read past the old end of file regardless of the fact the the eof has */
    /* moved. What's really goofy is that sys$display notices that the eof has moved */
    /* but it won't change those internal flags. Closing/reopening the file every few */
    /* seconds seems like an expensive proposition to me. Grrrr. */
    err = sys$close(&inp_fab); /* close the file */
    if ((err&1) == 0) {
    fputs("Error closing the input file\n",stderr);
    exit(err);
    }
    err = sys$open(&inp_fab); /* reopen the file */
    if ((err&1) == 0) {
    fputs("Error reopening the input file\n",stderr);
    exit(err);
    }
    err = sys$connect(&inp_rab); /* reconnect the rab */
    if ((err&1) == 0) {
    fputs("Error reconnecting the input rab\n",stderr);
    exit(err);
    }
    break;
    }
    }
    sys$close(&inp_fab);
    sys$close(&out_fab);
    }
    if ((err&1) != 0) return err;
    if (err != RMS$_EOF) return err;
    return SS$_NORMAL;
    }

    /************************************************** ************************
    * do_seqout - sequentially output the data from the input file
    *
    * At entry:
    * rfa_blk - starting block number
    * rfa_off - offset within block to start of record
    * At exit:
    * last_rfa_blk and last_rfa_off are set to the rfa of the last record read
    * input file has been dumped to output
    ************************************************** ************************/

    do_seqout(long rfa_blk,int rfa_off) /* seek to desired record and output */
    {
    int err,skip=0;
    if (rfa_blk == 0) rfa_blk = 1; /* start at the beginning */
    if (rfa_blk < last_rfa_blk || (rfa_blk == last_rfa_blk && rfa_off <= last_rfa_off)) {
    rfa_blk = last_rfa_blk; /* seek to record last displayed */
    rfa_off = last_rfa_off;
    skip = 1; /* and skip it */
    }
    inp_rab.rab$l_rfa0 = rfa_blk; /* starting block # */
    inp_rab.rab$w_rfa4 = rfa_off; /* byte offset within block */
    inp_rab.rab$b_rac = RAB$C_RFA; /* change to RFA access mode */
    inp_rab.rab$l_bkt = 0; /* make sure bkt field is clear */
    inp_rab.rab$l_rhb = inp_buf; /* init the ptrs */
    inp_rab.rab$l_ubf = inp_buf + inp_fab.fab$b_fsz; /* in case making VFC file */
    out_rab.rab$l_rhb = inp_buf;
    out_rab.rab$l_rbf = inp_buf + inp_fab.fab$b_fsz;
    while(1) {
    last_rfa_blk = inp_rab.rab$l_rfa0; /* save rfa of last record read */
    last_rfa_off = inp_rab.rab$w_rfa4;
    err=sys$get(&inp_rab); /* read the record */
    if ((err&1) == 0) {
    if (err != RMS$_EOF) {
    fputs("Error reading input\n",stderr);
    exit(err);
    }
    break;
    }
    inp_rab.rab$b_rac = RAB$C_SEQ; /* switch back to sequential reads */
    out_rab.rab$w_rsz = inp_rab.rab$w_rsz;
    if (skip == 0) { /* if not to skip the record */
    if (((err=sys$put(&out_rab))&1) == 0) { /* write it */
    fputs("Error writing output\n",stderr);
    exit(err);
    }
    }
    skip = 0; /* at most, we skip 1 record */
    }
    return err;
    }

    char end_mark[] = "\n\r\n";

    /************************************************** ************************
    * do_stream - figure out the record structure for one of the 3 types of
    * stream files there are.
    * At entry:
    * type - record type. 0=stmlf, 1=stmcr, 2=stmcrlf
    * At exit:
    * has called do_seqout with the computed block and offset of the
    * desired starting record.
    ************************************************** ************************/

    do_stream(type)
    int type; /* 0=stmlf, 1=stmcr, 2=stmcrlf */
    {
    unsigned long block,rfa_blk=0;
    int rcd_num= 0,err,rfa_off,part1=0,end_char;
    unsigned char *s;

    inp_rab.rab$l_bkt = inp_xab.xab$l_ebk+1;
    end_char = end_mark[type];

    while(1) { /* as long as there's data in the file */
    if (inp_rab.rab$l_bkt <= 1) { /* quit if we already read blk 1 */
    rfa_blk = 1; /* give 'em the whole file */
    rfa_off = 0;
    break;
    }
    block = inp_rab.rab$l_bkt-(inp_rab.rab$w_usz>>9);
    if (block == 0 || block > inp_rab.rab$l_bkt) block = 1; /* but can't start before 1 */
    inp_rab.rab$l_bkt = block; /* rememebr starting block number */
    err = sys$read(&inp_rab);
    if ((err&1) == 0) {
    if (err == RMS$_EOF) break;
    fprintf(stderr,"Error (%08X) trying to read %d bytes at block %d\n",
    err,inp_rab.rab$w_usz,block);
    continue;
    }
    s = inp_rab.rab$l_ubf+inp_rab.rab$w_rsz;

    if (part1) {
    if (*--s == '\r') {
    rfa_blk = block+((s+2)-inp_rab.rab$l_ubf>>9);
    rfa_off = ((s+2)-inp_rab.rab$l_ubf)&511;
    if (++rcd_num >= record_count) break;
    }
    ++s;
    }
    part1 = 0;
    while (s >= inp_rab.rab$l_ubf) {
    if (*--s == end_char) {
    char *nrp;
    nrp = s+1; /* next record starts here */
    if (type == 2) { /* if strmcrlf */
    if (s <= inp_rab.rab$l_ubf) { /* if on the cusp */
    part1 = 1; /* defer */
    break; /* get somemore data */
    }
    if (*--s != '\r') { /* else if next char is not cr */
    ++s; /* then this is not a record */
    continue;
    }
    }
    rfa_blk = block+(nrp-inp_rab.rab$l_ubf>>9);
    rfa_off = (nrp-inp_rab.rab$l_ubf)&511;
    if (++rcd_num >= record_count) break;
    }
    }
    if (rcd_num >= record_count) break; /* we got everything */
    }
    if (rfa_blk == 0) return RMS$_EOF;
    return do_seqout(rfa_blk,rfa_off); /* write out records */
    }

    /************************************************** **********************
    * do_varfast. This procedure trys to figure out the record structure
    * of a variable length file while reading from the end of the file.
    *
    * At entry:
    * (called by do_var)
    * At exit:
    * returns a 0 if it couldn't determine a valid record structure.
    * called do_seqout with a computed block and offset if it did
    * successfuly find an appropriate record boundary.
    * returns with RMS status in all cases.
    ************************************************** ***********************/

    do_varfast()
    {
    unsigned long block,rfa_blk=0;
    int rcd_num= 0,err,rec_len,rfa_off,min_recsiz;
    union {
    unsigned char *s;
    unsigned short *len;
    unsigned int align;
    } rp;

    inp_rab.rab$l_bkt = inp_xab.xab$l_ebk+1;
    rec_len = 0;
    min_recsiz = inp_fab.fab$b_fsz;
    inp_rab.rab$w_usz = ((inp_xab.xab$w_lrl+3)*record_count+511)&~511;

    while(1) {
    if (inp_rab.rab$l_bkt <= 1) break; /* quit if we already read blk 1 */
    block = inp_rab.rab$l_bkt-(inp_rab.rab$w_usz>>9);
    if (block == 0 || block > inp_rab.rab$l_bkt) block = 1; /* but can't start before 1 */
    inp_rab.rab$l_bkt = block; /* remember starting block number */
    err = sys$read(&inp_rab);
    if ((err&1) == 0) {
    if (err == RMS$_EOF) break;
    fprintf(stderr,"Error (%08X) trying to read %d bytes at block %d, record %d\n",
    err,inp_rab.rab$w_usz,block,rcd_num);
    continue;
    }
    rp.s = inp_rab.rab$l_ubf+inp_rab.rab$w_rsz;
    if ((rp.align&1) == 1) ++rp.align; /* ffb must be even */

    /************************************************** ***********************
    * The following procedure loops through the buffer picking up pairs of bytes (a
    * short) on even byte boundaries from the end. If this pair of bytes forms a
    * integer whose value points within 1 of the the next record or the current eof,
    * then the pair is assumed to be the count field of a valid record and is so
    * recorded. It can easily get screwed up if there is binary data in the records,
    * but for ascii files such as log files, it ought to work well enough most of
    * the time. The integer value represents the length of the record. If this value
    * is greater than the maxium record length recorded for the file (in the
    * XAB$W_LRL field of the XABFHC), then this routine assumes to have gotten lost,
    * so it rolls over and dies.
    ************************************************** ***********************/

    while (1) {
    int len,t;
    char *tp;
    rp.s -= 2; /* backup 2 bytes */
    if (rp.s < inp_rab.rab$l_ubf) break; /* too far, get more data */
    len = *rp.len;
    if (rec_len >= min_recsiz && /* if currently at or greater than min */
    (len == rec_len || /* and lengths match exactly */
    (rec_len > 0 && /* or less by 1 */
    len == rec_len-1))) {
    rfa_blk = block+(rp.s-inp_rab.rab$l_ubf>>9); /* remember this point */
    rfa_off = (rp.s-inp_rab.rab$l_ubf)&511;
    rec_len = 0;
    if (++rcd_num >= record_count) break;
    continue;
    }
    rec_len += 2; /* increase size of record */
    if (rec_len > inp_xab.xab$w_lrl) return 0; /* we're lost, give up */
    }
    if (rcd_num >= record_count) break; /* we got everything */
    }
    if (rfa_blk == 0) return RMS$_EOF;
    return do_seqout(rfa_blk,rfa_off); /* write out records */
    }

    /************************************************** **********************
    * skip_through - this routine positions to the desired record begining
    * with a known starting position. It is used in monitor mode to skip
    * records that may have been added to the input file since the last
    * time it was looked at it.
    *
    * At entry:
    * last_rfa_blk and last_rfa_off point to the last record read.
    * At exit:
    * called do_seqout with a computed block and offset
    * last_rfa_blk and last_rfa_off point to a new last record read.
    *
    ************************************************** **********************/

    int skip_through()
    {
    int err;
    int first_rfa=0; /* index to first rfa */
    int next_rfa=0; /* index to next available rfa */

    if (rfas == (Rfa *)0) rfas = (Rfa *)calloc(record_count,sizeof(Rfa));
    inp_rab.rab$l_rfa0 = last_rfa_blk; /* where we left off */
    inp_rab.rab$w_rfa4 = last_rfa_off;
    inp_rab.rab$b_rac = RAB$C_RFA; /* change to RFA access mode */
    inp_rab.rab$l_bkt = 0; /* make sure bkt field is off */
    inp_rab.rab$l_rhb = inp_buf; /* init the ptrs */
    inp_rab.rab$l_ubf = inp_buf + inp_fab.fab$b_fsz; /* in case making VFC file */
    while (1) {
    (rfas+next_rfa)->block = inp_rab.rab$l_rfa0;
    (rfas+next_rfa)->offset = inp_rab.rab$w_rfa4;
    next_rfa += 1;
    next_rfa %= record_count;
    if (next_rfa == first_rfa) {
    first_rfa += 1;
    first_rfa %= record_count;
    }
    err=sys$get(&inp_rab);
    if ((err&1) == 0) {
    if (err != RMS$_EOF) {
    fputs("Error reading input\n",stderr);
    exit(err);
    }
    break;
    }
    inp_rab.rab$b_rac = RAB$C_SEQ; /* switch back to sequential */
    }
    return do_seqout((rfas+first_rfa)->block,(rfas+first_rfa)->offset);
    }

    /************************************************** **********************
    * do_var. This procedure positions to the nth record from the end of
    * a file by reading the whole file into memory 127 blocks at a time
    * and skipping through the records recording the block and offset of
    * each as it goes.
    *
    * At entry:
    *
    * At exit:
    * called do_seqout with the computed block and offset
    * last_rfa_blk and last_rfa_off updated to point to the last record read.
    * returns with RMS status.
    ************************************************** ***********************/

    do_var()
    {
    long block,rcd_num= 0;
    int err;
    int first_rfa=0; /* index to first rfa */
    int next_rfa=0; /* index to next available rfa */
    unsigned char *ebp;
    union {
    char *s;
    unsigned short *len;
    unsigned int align;
    } rp;

    /* Unless otherwise indicated, trys to do the fast way first. If that fails,
    * it'll do the hard way. */

    if (the_safe_way == 0 && inp_xab.xab$l_ebk > (inp_rab.rab$w_usz>>9)) {
    if ((err=do_varfast()) != 0) return err;
    fputs("Unable to determine record structure from backend of file.\n",stderr);
    fputs("Doing it the 'safer' way instead.\n",stderr);
    inp_rab.rab$w_usz = sizeof(inp_buf); /* assume to read the max */
    }
    rp.s = inp_rab.rab$l_ubf;
    inp_rab.rab$l_bkt = 1;
    if (rfas == (Rfa *)0) rfas = (Rfa *)calloc(record_count,sizeof(Rfa));
    while(1) {
    block = inp_rab.rab$l_bkt;
    err = sys$read(&inp_rab);
    inp_rab.rab$l_bkt += (inp_rab.rab$w_rsz+511) >> 9;
    if ((err&1) == 0) {
    if (err == RMS$_EOF) break;
    fprintf(stderr,"Error (%08X) trying to read %d bytes at block %d, record %d\n",
    err,inp_rab.rab$w_usz,block,rcd_num);
    continue;
    }
    ebp = inp_rab.rab$l_ubf+inp_rab.rab$w_rsz;
    while (1) {
    int len,t;
    char *tp;
    if ((rp.align&1) == 1) ++rp.align;
    if (rp.s >= ebp) {
    t = rp.s - ebp;
    inp_rab.rab$l_bkt += t>>9;
    rp.s = inp_rab.rab$l_ubf+(t&511);
    break;
    }
    ++rcd_num;
    len = *rp.len;
    if (len > 32767) {
    if (len == 0xFFFF) {
    rp.s = inp_rab.rab$l_ubf;
    break; /* eof */
    }
    fprintf(stderr,"Warning: Record %d (blk=0x%08X,off=0x%04X): cnt %04X greater than 0x7FFF\n",
    rcd_num,(rp.s-inp_rab.rab$l_ubf>>9)+block,(rp.s-inp_rab.rab$l_ubf)&511,len);
    }
    t = rp.s-inp_rab.rab$l_ubf;
    (rfas+next_rfa)->block = block + (t >> 9);
    (rfas+next_rfa)->offset = t & 511;
    (rfas+next_rfa)->length = len;
    next_rfa += 1;
    next_rfa %= record_count;
    if (next_rfa == first_rfa) {
    first_rfa += 1;
    first_rfa %= record_count;
    }
    rp.s += len+2;
    }
    }
    if ((rfas+first_rfa)->block == 0) return RMS$_EOF;
    return do_seqout((rfas+first_rfa)->block,(rfas+first_rfa)->offset);
    }

    /************************************************** **********************
    * do_fixed. This procedure positions to the nth record from the end of
    * a fixed length record file by computing the desired rfa from the
    * required record number, the size of the file and the size of each
    * record. This is by far the simplest of the three decoding routines.
    *
    * At entry:
    *
    * At exit:
    * called do_seqout with the computed block and offset
    * last_rfa_blk and last_rfa_off updated to point to the last record read.
    * returns with RMS status.
    ************************************************** ***********************/

    do_fixed()
    {
    int reccnt;
    unsigned long size,sbn;
    long start,rfa_blk,rfa_off;

    size = inp_xab.xab$l_ebk*512+inp_xab.xab$w_ffb; /* file size in bytes */
    reccnt = size/inp_xab.xab$w_mrz; /* total record count */
    start = reccnt - record_count; /* starting record # */
    if (start < 0) start = 0; /* can't go past beginning */
    sbn = start*inp_xab.xab$w_mrz; /* starting byte # */
    rfa_blk = (sbn >> 9) + 1; /* starting block number */
    rfa_off = sbn & 511; /* offset in block */
    if (rfa_blk < last_rfa_blk || (rfa_blk == last_rfa_blk && rfa_off < last_rfa_off)) {
    rfa_blk = last_rfa_blk; /* don't display records already displayed */
    rfa_off = last_rfa_off+inp_xab.xab$w_mrz; /* advance 1 record */
    if (rfa_off >= 512) { /* and adjust pointers if appropriate */
    rfa_off -= 512;
    rfa_blk += 1;
    }
    }
    return do_seqout(rfa_blk,rfa_off); /* write the end of the file */
    }

    int tti_ast()
    {
    int sts;
    if (tti_iosb.status == SS$_ABORT) {
    return SS$_NORMAL; /* aborts are ok, since they'll happen at exit */
    }
    if (tti_iosb.status == SS$_NORMAL || tti_iosb.status == SS$_ENDOFFILE) {
    were_done = 1; /* signal that we're done */
    sys$canwak(0,0); /* cancel our schwk */
    sys$wake(0,0); /* wake up from our hiber */
    } else {
    if ((tti_iosb.status&1) == 0) {
    fputs("Error reading from maillbox\n",stderr);
    exit(tti_iosb.status);
    }
    }
    return que_ttiread();
    }

    int que_ttiread()
    {
    int sts;
    sts = sys$qio( 0, /* efn */
    tti_chan, /* channel */
    IO$_READVBLK, /* function */
    &tti_iosb, /* iosb addr */
    tti_ast, /* astadr */
    0, /* astparam */
    tti_text, /* p1 (buffer ptr) */
    sizeof(tti_text), /* p2 (buffer size) */
    0,0,0,0); /* p3-p6 not used */

    if ((sts&1) == 0) {
    fputs("unable to do QIO to SYS$INPUT, monitor mode disabled\n",stderr);
    monitor = 0;
    }
    return sts;
    }

    /* ==============================fgen.c============== ================ */

    #include
    /* #include ...defined in the program top... */

    /*
    * fgen(pattern, result_array, array_length)
    * fgen generates filenames of files, matching a VMS pattern,
    * the results are stored in an array, space for the strings is allocated
    * by using malloc.
    * Return values:
    * -1 : error in pattern
    * 0 : no files found
    * n(>0) : number of matching filenames. (Stored in result_array [0] - [n-1])
    *
    * Wildcard expansion for VMS is easy; we just use a run-time library call.
    */

    fgen(pat,resarry,len)
    char *pat,**resarry[];
    int *len;
    {
    struct dsc$descriptor_s file_spec, result, deflt;
    long context;
    int count, slen, status, plen;
    char *pp, *rp, result_string[256], *strchr();
    char *fnp,**fnpp;

    file_spec.dsc$w_length = strlen(pat);
    file_spec.dsc$b_dtype = DSC$K_DTYPE_T;
    file_spec.dsc$b_class = DSC$K_CLASS_S;
    file_spec.dsc$a_pointer = pat;

    result.dsc$w_length = sizeof result_string;
    result.dsc$b_dtype = DSC$K_DTYPE_T;
    result.dsc$b_class = DSC$K_CLASS_S;
    result.dsc$a_pointer = result_string;

    deflt.dsc$w_length = sizeof(default_string)-1;
    deflt.dsc$b_dtype = DSC$K_DTYPE_T;
    deflt.dsc$b_class = DSC$K_CLASS_S;
    deflt.dsc$a_pointer = default_string;

    count = 0;
    context = 0;
    pp = strrchr(pat, ']');
    if ( !pp ) pp = strrchr(pat, ':');
    if ( !pp ) plen = 0;
    else plen = pp - pat + 1;
    fnpp = *resarry;
    while ((status = LIB$FIND_FILE(&file_spec, &result, &context, &deflt))
    == RMS$_NORMAL) {
    if (count >= *len) {
    if (*len == 0) *len = 256;
    if (*resarry == (char **)0) {
    *resarry = (char **)malloc(*len*sizeof(char *));
    } else {
    *len += *len/2; /* increase length by 1/2 again */
    *resarry = (char **)realloc(*resarry,*len*sizeof(char *));
    }
    if (*resarry == (char **)0) {
    perror("Unable to malloc/realloc memory");
    exit(0x10000004);
    }
    fnpp = *resarry + count;
    }
    rp = strrchr(result_string, ']') + 1;
    if( !rp )
    rp = result_string;
    slen = strchr(rp, ' ') - rp;
    fnp = *fnpp++ = malloc(slen + plen + 1);
    if (plen != 0)
    strncpy(fnp, pat, plen);
    strncpy(fnp + plen, rp, slen);
    fnp[slen + plen] = '\0';
    ++count;
    }
    #ifdef DVI$_ALT_HOST_TYPE
    lib$find_file_end(&context); /* Only on V4 and later */
    #endif
    if (status == RMS$_FNF) return(0);
    if (status == RMS$_NMF) return(count);
    return(-1);
    }


  16. Re: I don't have "type /tail=[n]" or "type /continuous" what do I do

    In article
    ,
    Christopher Lusardi wrote:

    > On Sep 11, 8:01*am, "Richard Brodie" wrote:
    > > There is a tail implementation on the VMS Freeware CDs.

    >
    > Ha, I am not allowed to do that!
    >


    OK. This is what I used to do going way back before V5:

    $ type file.log /output=x.tmp
    $ edit x.tmp

    and in the editor go to the end of file to see what's there.

    This worked fine for the logfiles output from a batch job, though you
    might have to wait a while for the output to be flushed to disk. The
    flush time can be set within a batch job via the command

    $ set output_rate=delta-time !(default 1 minute)

    See HELP SET OUTPUT_RATE for more details.

    If it's not a batch logfile you are looking at, but an application
    output file instead, you might find that TYPE cannot open the file due
    to sharing constraints. I.E. the application has opened the file for
    exclusive write and no access to other readers.

    In that case I doubt if the freeware TAIL would solve your problem
    either (though someone else may chip in and say otherwise).

    --
    Paul Sture

  17. Re: I don't have "type /tail=[n]" or "type /continuous" what do I

    In article , "Richard B. Gilbert" writes:
    >
    > Then you need to describe your system in far greater detail. I forget
    > just when TYPE /TAIL was implemented but it has been around for a LONG
    > time. Maybe as far back as V5.5-2 and certainly by 6.2.


    I think it was 6.0. My 5.5-2 systems certinaly don't have it.


+ Reply to Thread