#module GETUAI "V2.2" /* GETUAI.C Facility: Fermilab Accelerator Control System - VAX/VMS ACNET Get User Authorization Information for use in DCL Abstract: This program provides an interim solution until (if?) an F$GETUAI lexical function is added to DCL. Since this program uses the $GETUAI system service; it should continue to function across VMS upgrades (unlike GETUAF which reads the UAF records directly). One use of GETUAI is in the system startup to define logical names for packages which reside on the user disks under various "manager" accounts (FPS164, MASS11MGR, etc). Environment: Foreign DCL command. Author: Frank J. Nagy Fermilab Accelerator Controls Modification History: V0.0 21-Jul-86 FJN Created V0.1 22-Jul-86 FJN Initial implementation nearly complete; start testing V0.2 23-Jul-86 FJN Complete implementation and finish testing V1.0 24-Jul-86 FJN Change qualifier names to avoid ambiguities; final tests V1.1 27-Jul-86 FJN Handle privilege lists in up to 2 output symbols V1.2 28-Jul-86 FJN Add support for /DEFAULT qualifier V2.0 12-Sep-89 FJN Add support for /EXISTS qualifier to provide easy way to test if an account exists V2.1 03-Oct-89 FJN Added support for /RESTRICTED and /DISIMAGE qualifiers (flags added with VMS V5.2) V2.2 28-Nov-90 FJN Added /PWDDIC and /PWDHIS qualifiers to support the DISPWDDIC and DISPWDHIS flags introduced with VMS V5.4 */ /****************** * Include Files: * ******************/ #include stddef /* VAX C standard definitions */ #include stdlib /* Standard C library definitions */ #include "vaxtypes.h" /* VAX C Type extensions */ #include descrip /* VAX Descriptors */ #include "descrip2.h" /* Additional descriptor defs. */ #include jpidef /* Definitions for $GETJPI */ #include prvdef /* Privilege bit numbers */ #include rmsdef /* RMS status codes */ #include ssdef /* System status codes */ #include "uaidef.h" /* Definitions for $GETUAI */ #include "privbits.h" /* Privilege bit number constants */ /********************************* * Global definitions and types: * *********************************/ globalref char GETUAI_TABLES; /* DCL tables for GETUAI "command" */ /******************************** * Local definitions and types: * ********************************/ typedef unsigned long status; /* Condition code status type */ typedef struct dsc$descriptor *Descrp; /* Pointer to text descriptor */ typedef struct { /* Item in $GETUAI/$GETJPI list */ unsigned short buflen; /* Buffer length */ unsigned short itmcod; /* Item code */ address bufptr; /* Address of buffer for data */ unsigned long *rtlptr; /* Address of return length */ } Item; #define N_ITEMS 128 /* Number of items in list */ #define SYMBOL_LEN 256 /* Length of DCL symbol name */ #define SYMBOL_MAX 255 /* Maximum length of DCL symbol value */ /***************************** * Module Local Own Storage: * *****************************/ readonly static $DESCRIPTOR( d_yes, "YES"); readonly static $DESCRIPTOR( d_no, "NO"); readonly static $DESCRIPTOR( d_infinite, "INFINITE"); readonly static $DESCRIPTOR( d_none, "NONE"); readonly static $DESCRIPTOR( d_full, "FULL"); readonly static $DESCRIPTOR( d_exists, "EXISTS"); /* Table for driving this program... */ typedef struct { /* Table entry definition */ struct dsc$descriptor d_qual; /* Descriptor for qualifier name text */ unsigned long itemcode; /* Primary $GETUAI item code */ void (*build_routine)(); /* Pointer to BUILD routine */ unsigned long build_param; void (*action_routine)(); /* Pointer to ACTION routine */ unsigned long action_param; Item *itemptr; /* Pointer to $GETUAI item block */ struct dsc$descriptor d_symbol; /* Descriptor for symbol name */ } TEntry; /* General entry definition */ #define TEDef( qual, icode, builder, bparam, actor, aparam) \ { { sizeof qual - 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, qual }, \ icode, builder, bparam, actor, aparam, NULL, \ { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 } } /* FLAGS entry definition */ #define TEFlag( qual, actor, foffset) \ { { sizeof qual - 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, qual }, \ UAI$_FLAGS, build_int, 0, actor, foffset, NULL, \ { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 } } /* Access data entry definition */ #define TEAccess( qual, icode1, icode2) \ { { sizeof qual - 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, qual }, \ icode1, build_access, icode2, action_access, 0, NULL, \ { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 } } /* Date entry definition */ #define TEDate( qual, icode, dflag) \ { { sizeof qual - 1, DSC$K_DTYPE_T, DSC$K_CLASS_S, qual }, \ icode, build_quad, 0, action_date, dflag, NULL, \ { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 } } #define DATE_NONE 1 /* Date of 0 returns "NONE" */ #define DATE_INFINITE 2 /* Date of 0 returns "INFINITE" */ #define ASCIC 1 /* Flag for counted text string */ /* Forward function definitions... */ void build_text(), build_int(), build_quad(), build_access(); void build_privs(); void action_ascii(), action_int(), action_flag0(), action_flag1(); void action_access(), action_cputime(), action_privs(), action_date(); void action_uic(), action_primedays(), action_default(); static TEntry table[] = { /* Controller table ... */ TEDef( "ACCOUNT", UAI$_ACCOUNT, build_text, 9, action_ascii, 0), TEDef( "ASTLM", UAI$_ASTLM, build_int, 0, action_int, 0), TEFlag( "AUDIT", action_flag1, UAI$M_AUDIT), TEFlag( "AUTOLOGIN", action_flag1, UAI$M_AUTOLOGIN), TEAccess( "BATCH", UAI$_BATCH_ACCESS_P, UAI$_BATCH_ACCESS_S), TEDef( "BIOLM", UAI$_BIOLM, build_int, 0, action_int, 0), TEDef( "BYTLM", UAI$_BYTLM, build_int, 0, action_int, 0), TEFlag( "CAPTIVE", action_flag1, UAI$M_CAPTIVE), TEDef( "CLI", UAI$_DEFCLI, build_text, 40, action_ascii, ASCIC), TEDef( "CLITABLES", UAI$_CLITABLES, build_text, 32, action_ascii, ASCIC), TEDef( "CPUTIME", UAI$_CPUTIM, build_int, 0, action_cputime, 0), TEFlag( "CTRLY", action_flag0, UAI$M_DISCTLY), TEDef( "DEFAULT", UAI$_DEFDEV, build_text, 16, action_default, 0), TEDef( "DEFAULT", UAI$_DEFDIR, build_text, 64, action_default, 0), TEFlag( "DEFCLI", action_flag1, UAI$M_DEFCLI), TEDef( "DEFPRIVILEGES", UAI$_DEF_PRIV, build_privs, 0, action_privs, 0), TEDef( "DEVICE", UAI$_DEFDEV, build_text, 16, action_ascii, ASCIC), TEAccess( "DIALUP", UAI$_DIALUP_ACCESS_P, UAI$_DIALUP_ACCESS_S), TEDef( "DIOLM", UAI$_DIOLM, build_int, 0, action_int, 0), TEDef( "DIRECTORY", UAI$_DEFDIR, build_text, 64, action_ascii, ASCIC), TEFlag( "DISUSER", action_flag1, UAI$M_DISACNT), TEFlag( "DISIMAGE", action_flag1, UAI$M_DISIMAGE), TEDef( "ENQLM", UAI$_ENQLM, build_int, 0, action_int, 0), TEDate( "EXPIRATION", UAI$_EXPIRATION, DATE_NONE), TEDef( "FILLM", UAI$_FILLM, build_int, 0, action_int, 0), TEFlag( "GENPWD", action_flag1, UAI$M_GENPWD), TEDef( "JTQUOTA", UAI$_JTQUOTA, build_int, 0, action_int, 0), TEDate( "LAST_LOGIN", UAI$_LASTLOGIN_I, DATE_NONE), TEDate( "INTERACTIVE_LOGIN", UAI$_LASTLOGIN_I, DATE_NONE), TEDate( "NONINTERACTIVE_LOGIN", UAI$_LASTLOGIN_N, DATE_NONE), TEDef( "LGICMD", UAI$_LGICMD, build_text, 256, action_ascii, ASCIC), TEAccess( "LOCAL", UAI$_LOCAL_ACCESS_P, UAI$_LOCAL_ACCESS_S), TEFlag( "LOCKPWD", action_flag1, UAI$M_LOCKPWD), TEDef( "LOGIN_FAILURES", UAI$_LOGFAILS, build_int, 0, action_int, 0), TEFlag( "MAIL", action_flag0, UAI$M_NOMAIL), TEDef( "MAXACCTJOBS", UAI$_MAXACCTJOBS, build_int, 0, action_int, 0), TEDef( "MAXDETACH", UAI$_MAXDETACH, build_int, 0, action_int, 0), TEDef( "MAXJOBS", UAI$_MAXJOBS, build_int, 0, action_int, 0), TEAccess( "NETWORK", UAI$_NETWORK_ACCESS_P, UAI$_NETWORK_ACCESS_S), TEFlag( "NEWMAIL", action_flag0, UAI$M_DISMAIL), TEDef( "OWNER", UAI$_OWNER, build_text, 32, action_ascii, ASCIC), TEDef( "USER_DATA", UAI$_USER_DATA, build_text, 255, action_ascii, ASCIC), TEDef( "PBYTLM", UAI$_PBYTLM, build_int, 0, action_int, 0), TEDef( "PGFLQUOTA", UAI$_PGFLQUOTA, build_int, 0, action_int, 0), TEDef( "PRCLM", UAI$_PRCCNT, build_int, 0, action_int, 0), TEDef( "PRIMEDAYS", UAI$_PRIMEDAYS, build_int, 0, action_primedays, 0), TEDef( "PRIORITY", UAI$_PRI, build_int, 0, action_int, 0), TEDef( "PRIVILEGES", UAI$_PRIV, build_privs, 0, action_privs, 0), TEDate( "PWDATE", UAI$_PWD_DATE, DATE_NONE), TEFlag( "PWDDIC", action_flag1, UAI$M_DISPWDDIC), TEFlag( "PWDHIS", action_flag1, UAI$M_DISPWDHIS), TEFlag( "PWEXPIRED", action_flag1, UAI$M_PWD_EXPIRED), TEDate( "PWLIFETIME", UAI$_PWD_LIFETIME, DATE_INFINITE), TEDef( "PWMINIMUM", UAI$_PWD_LENGTH, build_int, 0, action_int, 0), TEDef( "PWLENGTH", UAI$_PWD_LENGTH, build_int, 0, action_int, 0), TEDate( "P2DATE", UAI$_PWD2_DATE, DATE_NONE), TEFlag( "P2EXPIRED", action_flag1, UAI$M_PWD2_EXPIRED), TEDef( "QUEUE_PRIORITY", UAI$_QUEPRI, build_int, 0, action_int, 0), TEFlag( "RECONNECT", action_flag0, UAI$M_DISRECONNECT), TEAccess( "REMOTE", UAI$_REMOTE_ACCESS_P, UAI$_REMOTE_ACCESS_S), TEFlag( "REPORT", action_flag0, UAI$M_DISREPORT), TEFlag( "RESTRICTED", action_flag1, UAI$M_RESTRICTED), TEDef( "SHRFILLM", UAI$_SHRFILLM, build_int, 0, action_int, 0), TEDef( "TQELM", UAI$_TQCNT, build_int, 0, action_int, 0), TEDef( "UIC", UAI$_UIC, build_int, 0, action_uic, 0), TEDef( "USERNAME", UAI$_USERNAME, build_text, 12, action_ascii, 0), TEFlag( "WELCOME", action_flag0, UAI$M_DISWELCOM), TEDef( "WSDEFAULT", UAI$_DFWSCNT, build_int, 0, action_int, 0), TEDef( "WSEXTENT", UAI$_WSEXTENT, build_int, 0, action_int, 0), TEDef( "WSQUOTA", UAI$_WSQUOTA, build_int, 0, action_int, 0), }; #define TABLE_END ((address) table + sizeof table) static char *privnames[64]; /* Privilege names by bit number */ readonly static long privbits[] = { /* Privilege bit numbers */ PRV$V_NOACNT, PRV$V_ALLSPOOL, PRV$V_SETPRI, PRV$V_BUGCHK, PRV$V_BYPASS, PRV$V_CMEXEC, PRV$V_CMKRNL, PRV$V_DETACH, PRV$V_DIAGNOSE, PRV$V_DOWNGRADE, PRV$V_EXQUOTA, PRV$V_GROUP, PRV$V_GRPNAM, PRV$V_GRPPRV, PRV$V_LOG_IO, PRV$V_MOUNT, PRV$V_NETMBX, PRV$V_OPER, PRV$V_PFNMAP, PRV$V_PHY_IO, PRV$V_PRMCEB, PRV$V_PRMGBL, PRV$V_PRMMBX, PRV$V_PSWAPM, PRV$V_READALL, PRV$V_SECURITY, PRV$V_SETPRV, PRV$V_SHARE, PRV$V_SHMEM, PRV$V_SYSGBL, PRV$V_SYSLCK, PRV$V_SYSNAM, PRV$V_SYSPRV, PRV$V_TMPMBX, PRV$V_UPGRADE, PRV$V_VOLPRO, PRV$V_WORLD }; #define BITS_END ((address) privbits + sizeof privbits) /********************************************** * Global Procedure and Function definitions: * **********************************************/ address malloc(); /* Memory allocation routine */ int sprintf(); /* Formatted output to string routine */ int strlen(); /* Length of NUL-terminated string */ status LIB$SET_SYMBOL(); /* Define DCL symbol */ status SYS$ASCTIM(); /* Binary-to-ASCII time service */ /*+ Main Program Functional Description: Interprets table to build item list for $GETUAI and then set the DCL symbols from the results of the $GETUAI call. Calling Sequence: $ GETUAI :== $disk:[directory]GETUAI $ GETUAI user /qualifer=symbol ... Side Effects: None -*/ main( ) { register status sts; status LIB$GET_FOREIGN(); /* Get foreign command line */ status LIB$GET_INPUT(); /* Get input from SYS$INPUT */ status CLI$DCL_PARSE(); /* Invoke DCL command parser */ status CLI$PRESENT(); /* Test for command component present */ status CLI$GET_VALUE(); /* Get command component value */ status SYS$GETUAI(); /* Get User Authorization Information */ TEntry *jte; /* Table entry pointer */ Item *jlp, *ilp; /* Item list pointers */ Descrp lqdp = NULL; /* Pointer to last qualifier */ address calloc(); /* Memory allocate and clear */ address malloc(); /* Memory allocate only */ readonly static $DESCRIPTOR( d_p1, "P1"); readonly static $DESCRIPTOR( d_dot, "."); static char ftext[1024] = "GETUAI "; /* Buffer for foreign command line */ static $DESCRIPTOR( d_ftext, ftext); #define VERB_LEN (sizeof "GETUAI " - 1) static char user[32]; /* Buffer for username parameter */ static $DESCRIPTOR( d_user, user); int STR$COMPARE_EQL(); /* Test 2 strings for equal */ status LIB$GETJPI(); /* Get process information */ void init_privnames(); /* Initialize privilege names */ void fixup_table(); /* Make run-time fixups to table */ status uaists; /* Status from $GETUAI operation */ /* Adjust foreign command line buffer descriptor for verb text. */ d_ftext.dsc$w_length -= VERB_LEN; d_ftext.dsc$a_pointer += VERB_LEN; sts = LIB$GET_FOREIGN( &d_ftext, 0, &d_ftext.dsc$w_length); ABORT_ON_FAILURE( sts); /* Readjust descriptor for GETUAI command line. */ d_ftext.dsc$w_length += VERB_LEN; d_ftext.dsc$a_pointer = ftext; /* Decode the "DCL" command line for the GETUAI command. */ sts = CLI$DCL_PARSE( &d_ftext, &GETUAI_TABLES, LIB$GET_INPUT); ABORT_ON_FAILURE( sts); fixup_table(); /* Enter run-time fixups in drive table */ /* Build item list for $GETUAI from the qualifiers present... */ jlp = ilp = (Item *) calloc( N_ITEMS, sizeof (Item)); for (jte = table, lqdp = NULL; jte < TABLE_END; jte++) if ($VMS_SUCCESS( CLI$PRESENT( &jte->d_qual))) { if ((lqdp == NULL) || (STR$COMPARE_EQL( lqdp, &jte->d_qual) != 0)) { jte->d_symbol.dsc$w_length = SYMBOL_LEN; jte->d_symbol.dsc$a_pointer = malloc( SYMBOL_LEN); sts = CLI$GET_VALUE( &jte->d_qual, &jte->d_symbol, &jte->d_symbol.dsc$w_length); ABORT_ON_FAILURE( sts); } else { jte->d_symbol.dsc$w_length = (jte-1)->d_symbol.dsc$w_length; jte->d_symbol.dsc$a_pointer = (jte-1)->d_symbol.dsc$a_pointer; } jte->itemptr = jlp; /* Pointer to entry's $GETUAI item */ (*jte->build_routine)( jte->itemcode, jte->build_param, &jlp); jlp++; lqdp = &jte->d_qual; /* Save pointer to qualifier name */ } /* Get GETUAI command parameter, the user's name. If the parameter is ".", then use $GETJPI to get username associated with current process. */ sts = CLI$GET_VALUE( &d_p1, &d_user, &d_user.dsc$w_length); ABORT_ON_FAILURE( sts); if (STR$COMPARE_EQL( &d_user, &d_dot) == 0) { d_user.dsc$w_length = sizeof user; sts = LIB$GETJPI( &JPI$_USERNAME, 0, 0, 0, &d_user, &d_user.dsc$w_length); ABORT_ON_FAILURE( sts); } /* Use $GETUAI to get all the items on the list built above. If the /EXISTS qualifier is present, then get the symbol name and set it to YES or NO. We detect the NO case by looking for RMS RNF (Record Not Found) error code. If the /EXISTS qualifier exists, then a success status will always be returned; otherwise GETUAI will exit with RMS error status. */ uaists = SYS$GETUAI( 0, 0, &d_user, ilp, 0, 0, 0); if ($VMS_SUCCESS( CLI$PRESENT( &d_exists))) { $DESCRIPTOR0( d_symbol); d_symbol.dsc$w_length = SYMBOL_LEN; d_symbol.dsc$a_pointer = malloc( SYMBOL_LEN); sts = CLI$GET_VALUE( &d_exists, &d_symbol, &d_symbol.dsc$w_length); ABORT_ON_FAILURE( sts); if ($VMS_SUCCESS( uaists)) { sts = LIB$SET_SYMBOL( &d_symbol, &d_yes); /* Account EXISTS */ ABORT_ON_FAILURE( sts); } else if (uaists == RMS$_RNF) { sts = LIB$SET_SYMBOL( &d_symbol, &d_no); /* NO such account */ ABORT_ON_FAILURE( sts); exit( SS$_NORMAL); } else exit( uaists); } else ABORT_ON_FAILURE( uaists); init_privnames(); /* Initialize privilege names now */ /* Now scan table again. For those entries which had qualifiers present (now have a non-null $GETUAI item pointer), invoke the action routine to set the specified DCL symbol. */ for (jte = table; jte < TABLE_END; jte++) if (jte->itemptr != NULL) (*jte->action_routine)( &jte->d_symbol, &jte->itemptr, jte->action_param); } /* ACTION routine for access information. */ void action_access( symbol, ilpp, actionparam) Descrp symbol; /* Pointer to symbol name descriptor */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ unsigned long actionparam; /* Unused action parameter */ { status sts; unsigned long prihrs; /* Temp. for primary day hours */ unsigned long sechrs; /* Temp. for secondary day hours */ char text[96]; /* Temp. text buffer and descriptor */ $DESCRIPTOR( d_text, text); #define NOACCESS 0XFFFFFF /* No access for 24 hour day */ readonly static $DESCRIPTOR( d_prionly, "PRIMARY=ALL,SECONDARY=NONE"); readonly static $DESCRIPTOR( d_seconly, "PRIMARY=NONE,SECONDARY=ALL"); prihrs = (unsigned long) ((*ilpp)++)->rtlptr; /* Also advances item list ptr */ sechrs = (unsigned long) (*ilpp)->rtlptr; /* and gets secondary day hours */ if ((prihrs == 0) && (sechrs == 0)) sts = LIB$SET_SYMBOL( symbol, &d_full); /* Full access */ else if ((prihrs == NOACCESS) && (sechrs == NOACCESS)) sts = LIB$SET_SYMBOL( symbol, &d_none); /* No access */ else if ((prihrs == 0) && (sechrs == NOACCESS)) sts = LIB$SET_SYMBOL( symbol, &d_prionly); /* Primary days access only */ else if ((prihrs == NOACCESS) && (sechrs == 0)) sts = LIB$SET_SYMBOL( symbol, &d_seconly); /* Secondary days access only */ else { d_text.dsc$w_length = sprintf( text, "PRIMARY=%X,SECONDARY=%X", prihrs, sechrs); sts = LIB$SET_SYMBOL( symbol, &d_text); } ABORT_ON_FAILURE( sts); } /* ACTION routine for all forms of ASCII text. If atype=ASCIC then the text in the buffer is preceeded by a count byte otherwise the return length provides the length of the text. */ void action_ascii( symbol, ilpp, atype) Descrp symbol; /* Pointer to symbol name descriptor */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ unsigned long atype; /* 0=straight text, ASCIC=counted text */ { status sts; $DESCRIPTOR0( d_text); d_text.dsc$a_pointer = (*ilpp)->bufptr; /* Pointer to text (and count?) */ if (atype == ASCIC) d_text.dsc$w_length = *d_text.dsc$a_pointer++; /* Move count and bump ptr */ else d_text.dsc$w_length = (unsigned short) (*ilpp)->rtlptr; /* Store length */ sts = LIB$SET_SYMBOL( symbol, &d_text); ABORT_ON_FAILURE( sts); } /* Special ACTION routine for CPU time limit. */ void action_cputime( symbol, ilpp, actionparam) Descrp symbol; /* Pointer to symbol name descriptor */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ unsigned long actionparam; /* Unused action parameter */ { status sts; int cputime[2]; /* Quadword CPU time */ char text[16]; /* Temp. text buffer and descriptor */ $DESCRIPTOR( d_text, text); status LIB$EMUL(); /* 32-bit to 64-bit multiplication */ if (((unsigned long) (*ilpp)->rtlptr) == 0) sts = LIB$SET_SYMBOL( symbol, &d_infinite); /* No CPU time limit */ else { sts = LIB$EMUL( &(*ilpp)->rtlptr, &(-100000), &0, cputime); ABORT_ON_FAILURE( sts); sts = SYS$ASCTIM( &d_text.dsc$w_length, &d_text, cputime, 0); ABORT_ON_FAILURE( sts); sts = LIB$SET_SYMBOL( symbol, &d_text); } ABORT_ON_FAILURE( sts); } /* ACTION routine for handling dates/time. */ void action_date( symbol, ilpp, dformat) Descrp symbol; /* Pointer to symbol name descriptor */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ unsigned long dformat; /* Code for handling date of 0 */ { status sts; char text[24]; /* Temp. text buffer and descriptor */ $DESCRIPTOR( d_text, text); int *vdp; /* Pointer to VMS date/time */ vdp = (int *) (*ilpp)->bufptr; /* Pointer to date/time */ if ((vdp[0] == 0) && (vdp[1] == 0) && (dformat != 0)) switch (dformat) { case DATE_NONE: sts = LIB$SET_SYMBOL( symbol, &d_none); break; case DATE_INFINITE: sts = LIB$SET_SYMBOL( symbol, &d_infinite); break; } else { sts = SYS$ASCTIM( &d_text.dsc$w_length, &d_text, vdp, 0); ABORT_ON_FAILURE( sts); sts = LIB$SET_SYMBOL( symbol, &d_text); } ABORT_ON_FAILURE( sts); } /* ACTION routine for /DEFAULT to combine two ASCIC text strings. */ void action_default( symbol, ilpp, unused) Descrp symbol; /* Pointer to symbol name descriptor */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ unsigned long unused; /* Unused action routine parameter */ { status sts; $DESCRIPTOR0( d_text); static char *s1p = NULL; /* Pointer to first string */ address malloc(); /* Memory allocation routine */ char *sp; char *strchr(); /* Search for character */ void strcat(); /* String concatenation */ if (s1p == NULL) { s1p = (*ilpp)->bufptr; /* First part, save string pointer */ *(s1p + *s1p + 1) = '\0'; /* Make sure of NUL terminator */ return; } /* Get combined string length into descriptor, also bump string pointers past the byte counts. Check that device name (first string) ends with a ":". */ d_text.dsc$w_length = (unsigned short) *s1p++ + (unsigned short) *(*ilpp)->bufptr++; if ((sp = strchr( s1p, ':')) == NULL) d_text.dsc$w_length++; /* Room to add ":" */ /* Allocate buffer to hold complete string and fill it up. */ d_text.dsc$a_pointer = malloc( d_text.dsc$w_length + 1); *d_text.dsc$a_pointer = '\0'; /* Empty string to start with */ strcat( d_text.dsc$a_pointer, s1p); /* Device name */ if (sp == NULL) strcat( d_text.dsc$a_pointer, ":"); /* Terminator for device name */ strcat( d_text.dsc$a_pointer, (*ilpp)->bufptr); sts = LIB$SET_SYMBOL( symbol, &d_text); ABORT_ON_FAILURE( sts); } /* ACTION routine for FLAGS bit where OFF (bit=0) returns a "YES". */ void action_flag0( symbol, ilpp, bitmask) Descrp symbol; /* Pointer to symbol name descriptor */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ unsigned long bitmask; /* Bit mask for FLAGS longword */ { status sts; if ((((unsigned long) (*ilpp)->rtlptr) & bitmask) == 0) sts = LIB$SET_SYMBOL( symbol, &d_yes); /* 0 => YES */ else sts = LIB$SET_SYMBOL( symbol, &d_no); /* 1 => NO */ ABORT_ON_FAILURE( sts); } /* ACTION routine for FLAGS bit where ON (bit=1) returns a "YES". */ void action_flag1( symbol, ilpp, bitmask) Descrp symbol; /* Pointer to symbol name descriptor */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ unsigned long bitmask; /* Bit mask for FLAGS longword */ { status sts; if ((((unsigned long) (*ilpp)->rtlptr) & bitmask) == 0) sts = LIB$SET_SYMBOL( symbol, &d_no); /* 0 => NO */ else sts = LIB$SET_SYMBOL( symbol, &d_yes); /* 1 => YES */ ABORT_ON_FAILURE( sts); } /* ACTION routine for integer values. */ void action_int( symbol, ilpp, actionparam) Descrp symbol; /* Pointer to symbol name descriptor */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ unsigned long actionparam; /* Unused action parameter */ { status sts; char text[16]; /* Temp. text buffer and descriptor */ $DESCRIPTOR( d_text, text); d_text.dsc$w_length = sprintf( text, "%d", (*ilpp)->rtlptr); sts = LIB$SET_SYMBOL( symbol, &d_text); ABORT_ON_FAILURE( sts); } /* Special ACTION routine for PRIMEDAYS. */ void action_primedays( symbol, ilpp, actionparam) Descrp symbol; /* Pointer to symbol name descriptor */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ unsigned long actionparam; /* Unused action parameter */ { status sts; char text[64]; /* Temp. text buffer and descriptor */ $DESCRIPTOR( d_text, text); int i; readonly static char *daynames[7] = { /* Names of the days of the week */ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; readonly static unsigned long daymasks[7] = { 1<rtlptr) & daymasks[i]) == 0) { if (text[0] != '\0') strcat( text, ","); /* Add separator */ strcat( text, daynames[i]); } d_text.dsc$w_length = strlen( text); /* Set length of string */ sts = LIB$SET_SYMBOL( symbol, &d_text); ABORT_ON_FAILURE( sts); } /* Special ACTION routine for list of privileges. */ void action_privs( symbol, ilpp, symbol2) Descrp symbol; /* Pointer to symbol name descriptor */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ Descrp symbol2; /* Pointer to 2nd symbol descriptor */ { status sts; char text[512]; /* Temp. text buffer and descriptor */ $DESCRIPTOR( d_text, text); $DESCRIPTOR( d_text2, text); /* For second symbol text */ int *bp; /* Pointer into list of bit offsets */ int LIB$EXTV(); /* Extract bit field instruction */ char *lc; /* Pointer to last comma */ void strcat(); /* String concatenation */ text[0] = '\0'; /* Init to empty string */ for (bp = privbits; bp < BITS_END; bp++) if (LIB$EXTV( bp, &1, (*ilpp)->bufptr)) { if (text[0] != '\0') strcat( text, ","); /* Separate names with comma */ strcat( text, privnames[*bp]); } if ((d_text.dsc$w_length = strlen( text)) > SYMBOL_MAX) { lc = text + SYMBOL_MAX; do lc--; while (*lc != ','); d_text2.dsc$a_pointer = ++lc; /* Break text after a comma */ d_text2.dsc$w_length = strlen( lc); /* Length of 2nd portion of text */ d_text.dsc$w_length = lc - text; /* Length of 1st portion */ } else d_text2.dsc$w_length = 0; /* 2nd symbol has null string */ sts = LIB$SET_SYMBOL( symbol, &d_text); ABORT_ON_FAILURE( sts); if (symbol2 != NULL) /* See if 2nd symbol to define */ { sts = LIB$SET_SYMBOL( symbol2, &d_text2); ABORT_ON_FAILURE( sts); } } /* Special ACTION routine for UIC. */ void action_uic( symbol, ilpp, actionparam) Descrp symbol; /* Pointer to symbol name descriptor */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ unsigned long actionparam; /* Unused action parameter */ { status sts; char text[16]; /* Temp. text buffer and descriptor */ $DESCRIPTOR( d_text, text); struct UIC { /* Member and group numbers of UIC */ unsigned short uic$w_mem; unsigned short uic$w_grp; }; d_text.dsc$w_length = sprintf( text, "[%o,%o]", ((struct UIC *) &(*ilpp)->rtlptr)->uic$w_grp, ((struct UIC *) &(*ilpp)->rtlptr)->uic$w_mem); sts = LIB$SET_SYMBOL( symbol, &d_text); ABORT_ON_FAILURE( sts); } /* BUILD routine for access information where the build parameter is a second item code. */ void build_access( itemcode, itemcode2, ilpp ) unsigned short itemcode; /* $GETUAI item code */ unsigned long itemcode2; /* Second $GETUAI item code */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ { void build_int(); build_int( itemcode, 0, ilpp); (*ilpp)++; /* Advance to next item in list */ build_int( itemcode2, 0, ilpp); } /* BUILD routine for 32-bit longword/integer return. */ void build_int( itemcode, buildparam, ilpp ) unsigned short itemcode; /* $GETUAI item code */ unsigned long buildparam; /* Unused build parameter */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ { (*ilpp)->buflen = 4; (*ilpp)->itmcod = itemcode; (*ilpp)->bufptr = (address) &(*ilpp)->rtlptr; (*ilpp)->rtlptr = 0; /* Used for return data */ } /* BUILD routine for privileges vector (64-bit integer). */ void build_privs( itemcode, te, ilpp ) unsigned short itemcode; /* $GETUAI item code */ TEntry *te; /* Pointer to current table entry */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ { address malloc(); /* Memory allocator */ Descrp s2d; /* Pointer to descriptor for symbol2 */ status sts; status CLI$GET_VALUE(); (*ilpp)->buflen = 8; (*ilpp)->itmcod = itemcode; (*ilpp)->bufptr = malloc( 8); /* Allocates a quadword for data */ (*ilpp)->rtlptr = (address) &(*ilpp)->rtlptr; /* Get memory for descriptor and buffer for symbol2 name. */ s2d = (Descrp) malloc( sizeof (struct dsc$descriptor)); s2d->dsc$w_length = SYMBOL_LEN; s2d->dsc$b_dtype = DSC$K_DTYPE_T; /* Text descriptor */ s2d->dsc$b_class = DSC$K_CLASS_S; /* Static descriptor */ s2d->dsc$a_pointer = malloc( SYMBOL_LEN); /* Get name of 2nd symbol. If there is one, then store pointer to its descriptor in the action routine parameter. */ sts = CLI$GET_VALUE( &te->d_qual, s2d, &s2d->dsc$w_length); if ($VMS_SUCCESS(sts)) te->action_param = (unsigned long) s2d; } /* BUILD routine for 64-bit integer (date) return. */ void build_quad( itemcode, buildparam, ilpp ) unsigned short itemcode; /* $GETUAI item code */ unsigned long buildparam; /* Unused build parameter */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ { address malloc(); (*ilpp)->buflen = 8; (*ilpp)->itmcod = itemcode; (*ilpp)->bufptr = malloc( 8); /* Allocates a quadword for data */ (*ilpp)->rtlptr = (address) &(*ilpp)->rtlptr; } /* BUILD routine for text return. */ void build_text( itemcode, maxlength, ilpp ) unsigned short itemcode; /* $GETUAI item code */ unsigned long maxlength; /* Maximum length of text item */ Item **ilpp; /* Ptr-to-ptr to item entry in list */ { address malloc(); (*ilpp)->buflen = maxlength; (*ilpp)->itmcod = itemcode; (*ilpp)->bufptr = malloc( maxlength); /* Allocates text buffer */ (*ilpp)->rtlptr = (address) &(*ilpp)->rtlptr; } /* Perform run-time fixups to the driver tables: - If build routine is "build_privs" then store pointer to the table entry as the build routine parameter to allow build_privs to store pointer to 2nd symbol descriptor into action routine parameter. */ void fixup_table() { TEntry *jte; /* Pointer to table entries */ for (jte = table; jte < TABLE_END; jte++) if (jte->build_routine == build_privs) jte->build_param = (unsigned long) jte; } /* Initialize the vector of privilege names. The array index is the bit offset into the privilege vector. */ void init_privnames() { privnames[PRV$V_NOACNT] = "ACNT"; privnames[PRV$V_ALLSPOOL] = "ALLSPOOL"; privnames[PRV$V_SETPRI] = "ALTPRI"; privnames[PRV$V_BUGCHK] = "BUGCHK"; privnames[PRV$V_BYPASS] = "BYPASS"; privnames[PRV$V_CMEXEC] = "CMEXEC"; privnames[PRV$V_CMKRNL] = "CMKRNL"; privnames[PRV$V_DETACH] = "DETACH"; privnames[PRV$V_DIAGNOSE] = "DIAGNOSE"; privnames[PRV$V_DOWNGRADE] = "DOWNGRADE"; privnames[PRV$V_EXQUOTA] = "EXQUOTA"; privnames[PRV$V_GROUP] = "GROUP"; privnames[PRV$V_GRPNAM] = "GRPNAM"; privnames[PRV$V_GRPPRV] = "GRPPRV"; privnames[PRV$V_LOG_IO] = "LOG_IO"; privnames[PRV$V_MOUNT] = "MOUNT"; privnames[PRV$V_NETMBX] = "NETMBX"; privnames[PRV$V_OPER] = "OPER"; privnames[PRV$V_PFNMAP] = "PFNMAP"; privnames[PRV$V_PHY_IO] = "PHY_IO"; privnames[PRV$V_PRMCEB] = "PRMCEB"; privnames[PRV$V_PRMGBL] = "PRMGBL"; privnames[PRV$V_PRMMBX] = "PRMMBX"; privnames[PRV$V_PSWAPM] = "PSWAPM"; privnames[PRV$V_READALL] = "READALL"; privnames[PRV$V_SECURITY] = "SECURITY"; privnames[PRV$V_SETPRV] = "SETPRV"; privnames[PRV$V_SHARE] = "SHARE"; privnames[PRV$V_SHMEM] = "SHMEM"; privnames[PRV$V_SYSGBL] = "SYSGBL"; privnames[PRV$V_SYSLCK] = "SYSLCK"; privnames[PRV$V_SYSNAM] = "SYSNAM"; privnames[PRV$V_SYSPRV] = "SYSPRV"; privnames[PRV$V_TMPMBX] = "TMPMBX"; privnames[PRV$V_UPGRADE] = "UPGRADE"; privnames[PRV$V_VOLPRO] = "VOLPRO"; privnames[PRV$V_WORLD] = "WORLD"; }