/* Copyright 2003-2023 James F. Duff */
/* License and disclaimer: http://www.eight-cubed.com/disclaimer.html */

#define __NEW_STARLET 1

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <ssdef.h>
#include <stsdef.h>
#include <jpidef.h>
#include <efndef.h>
#include <iosbdef.h>
#include <iledef.h>
#include <lib$routines.h>
#include <starlet.h>

#include "errchk.h"


/******************************************************************************/
static void ast_routine (unsigned int efn) {

static int r0_status;

    r0_status = sys$setef (efn);
    errchk_sig (r0_status);
}


/******************************************************************************/
int main (void) {

static IOSB iosb;

static int r0_status;
static unsigned int pid;
static unsigned int group;
static unsigned int member;

static char username[12];
static unsigned short int username_len;
static unsigned int efn;

static ILE3 jpiitms[] = {  4, JPI$_PID, &pid, NULL,
                           4, JPI$_GRP, &group, NULL,
                           4, JPI$_MEM, &member, NULL,
                          12, JPI$_USERNAME, username, &username_len,
                           0, 0, NULL, NULL };

    /*
    ** There are quite a few important system services have both a
    ** synchronous and asynchronous version.  Both versions can set
    ** an event flag and call an AST routine on completion.  Here we
    ** will get an event flag to wait on, and rather than letting
    ** getjpi set it, we will set it in an AST routine.  Just for
    ** fun :-)
    */
    r0_status = lib$get_ef (&efn);
    errchk_sig (r0_status);

    /*
    ** Normally, we would pass the event flag to the system service
    ** which would take care of ensuring it was clear.  As we are
    ** not doing that, we need to clear it outselves.
    */
    r0_status = sys$clref (efn);
    errchk_sig (r0_status);

    /*
    ** Note the first parameter is EFN$C_ENF.  This tells the system
    ** service that we don't care about event flags.  It's a _very_
    ** good idea to specify this value if you don't care, because if
    ** you don't specify it, the value defaults to zero, which is a
    ** valid event flag that _will_ be set when the routine completes.
    ** If you have multiple threads of execution that default this to
    ** zero, you could easily get in trouble really quickly.
    **
    ** The last parameter is the user parameter passed to the AST
    ** routine.  In this case we are passing the value of the event
    ** flag.  We could just as easily have stuck it in a structure
    ** and passed the address of the structure.
    */
    r0_status = sys$getjpi (EFN$C_ENF,
                            0,
                            0,
                            jpiitms,
                            &iosb,
                            ast_routine,
                            efn);
    errchk_sig (r0_status);

    /*
    ** Wait for the event flag to be set by the AST.
    */
    r0_status = sys$waitfr (efn);
    errchk_sig (r0_status);

    /*
    ** Note that the I/O status block status is not set until after
    ** the asynch operation completes.
    */
    errchk_sig (iosb.iosb$l_getxxi_status);

    /*
    ** The username is returned as a space filled 12 byte string.
    */
    for (; username_len - 1 >= 1; username_len--) {
        if (!isspace (username[username_len - 1])) {
            break;
        }
    }

    (void)printf ("Hello %-.*s, your process ID is %08x "
                  "and your UIC is [%o,%o]\n",
                  username_len,
                  username,
                  pid,
                  group,
                  member);

    r0_status = lib$free_ef (&efn);
    errchk_sig (r0_status);
}

Back to the master examples list.