From: LAURI@DCD00.FNAL.GOV (Laurelin of Middle Earth, x2214)
Newsgroups: comp.os.vms
Subject: SETPQL  3/9
Date: 13 Nov 92 17:15:22 GMT
Distribution: world
Organization: The Internet

-+-+-+-+-+-+-+-+ START OF PART 3 -+-+-+-+-+-+-+-+
Xstruct LinkedListStruct *ExcludeUser_Prev = NULL;`09/* Previous excluded use
Vrname entry */
Xstruct LinkedListStruct *ExcludeUser_Cur  = NULL;`09/* Current excluded user
Vname entry */
X
Xstruct LinkedListStruct *IncludeUser_Root = NULL;`09/* Base address of inclu
Vded username list */
Xstruct LinkedListStruct *IncludeUser_Prev = NULL;`09/* Previous included use
Vrname entry */
Xstruct LinkedListStruct *IncludeUser_Cur  = NULL;`09/* Current included user
Vname entry */
X
X
X
X
X/*
X * external error messages, from the SETPQL_MSG.MSG module
X */
Xextern long pql_excfnf();`09`09/* exclude file wasn't found, continuing. */
Xextern long pql_raise();`09`09/* user's pql has been increased */
Xextern long pql_lowval();`09`09/* default account beats command line value*/
Xextern long pql_nochanges();`09`09/* no changes were made */
Xextern long pql_uafchanged();`09`09/* changes were made */
Xextern long pql_invuafstr();`09`09/* internal structure of the SYSUAF file h
Vas changed -- ABORT!!! */
Xextern long pql_nop();`09`09`09/* nooperation was performed. Bozo entered an
V essentially null cmd string. */
Xextern long pql_nodfltacct();`09`09/* no default account is on this system.
V */
Xextern long pql_insdynmem();`09`09/* insufficient dynamic memory. */
X
X/*
X * FAO parameter structures for any place where we need to pass`20
X * string values to an error message.
X */
Xchar fao_p1`5BNAM$C_MAXRSS + 1`5D;`09`09/* general storage for string parame
Vters. */
Xchar fao_p2`5BNAM$C_MAXRSS + 1`5D;
Xchar fao_p3`5BNAM$C_MAXRSS + 1`5D;
Xchar fao_p4`5BNAM$C_MAXRSS + 1`5D;
Xchar to_be`5BNAM$C_MAXRSS + 1`5D;`09`09/* stores the verb tense, either WAS
V or WOULD HAVE BEEN, for informational message */
X$DESCRIPTOR(fao_p1_d, fao_p1);`09`09/* must be in descriptor format. */
X$DESCRIPTOR(fao_p2_d, fao_p2);
X$DESCRIPTOR(fao_p3_d, fao_p3);
X$DESCRIPTOR(fao_p4_d, fao_p4);
X$DESCRIPTOR(to_be_d,  to_be);
X
X/*
X * internal function templates/declarations
X */
Xlong  parse_cmdline();`09`09`09`09`09`09/* obtain and parse the command line
V, set internal flags */
Xlong  init_data_structures();`09`09`09`09`09/* initialize all data structure
Vs and pointers that we can. */
Xshort we_are_lazy();`09`09`09`09`09`09/* check to make sure that there is so
Vmething for us to do! */
Xlong  open_sysuaf();`09`09`09`09`09`09/* open the SYSUAF file for indexed re
Vad */
Xlong  init_Addr(union Addr *, struct ValueStruct *);`09`09/* point the Addre
Vss structures to the addresses of the Values */
Xlong  init_ItemList(struct ItemListStruct *,union Addr *);`09/* initialize $
VGETUAI/$SETUAI item list pointers/buffers */
Xlong  get_nextuser(char *);`09`09`09`09`09/* get the next user in the sysuaf
V file */
Xshort include_this_user(char *, long);`09`09`09`09/* should this user be INC
VLUDED or EXCLUDED? */
Xlong  set_MasterValue(union Addr *);`09`09`09`09/* set the Master PQL minimu
Vm values which will be used */
Xlong  set_UserValue(union Addr *, union Addr *);`09`09/* make sure the User
V Values meet the minimum Master Values */
Xvoid  test_and_set(long *, long *, short);`09`09`09/* compare two longwords
V and set long1 to the maximum value */
Xshort zero_is_infinite(short);`09`09`09`09`09/* determine if the value 0 imp
Vlies infinite */
Xvoid  cast_to_long(union Addr *, short, long *);`09`09/* cast a WORD/LONG/BY
VTE -> long for the test_and_set comparison */
Xvoid  cast_from_long(union Addr *, short, long *);`09`09/* cast a long -> WO
VRD/LONG/BYTE after test_and_set comparison */
Xchar  *cvtim(unsigned long);`09`09`09`09`09/* cast a long -> dddd-hh:mm:ss.c
Vc form for error messages */
Xchar  *upcase(char *);`09`09`09`09`09`09/* convert a string to upper case */
Xchar  *strtrim(char *);`09`09`09`09`09`09/* strip trailing whitespace from a
V string */
Xchar  *uncomment(char *);`09`09`09`09`09/* strip trailing comments ("!" char
Vacter and beyond) */
Xchar  *comma_tize(char *);`09`09`09`09`09/* convert single blanks to commas
V to make a comma-delineated list*/
Xlong  link_into_list(struct LinkedListStruct **,`09`09/* add next element to
V a linked list */
X`09`09`09struct LinkedListStruct **,
X`09`09`09struct LinkedListStruct **,
X`09`09`09char *, short);
Xshort in_linked_list(char *, struct LinkedListStruct *);`09/* determine if a
V particular string is contained within one */
X`09`09`09`09`09`09`09`09/*  of the linked lists (does a WILDCARD match) */
Xlong  open_and_read_exclude_file();`09`09`09`09/* get list of excluded users
V from the exclude file */
Xvoid  DISPLAY_value(struct ValueStruct *);`09`09`09/* for debugging, display
V the Value structures */
Xvoid  DISPLAY_by_addr(union Addr *);`09`09`09`09/* for debugging, display th
Ve values via the Address structures */
Xvoid  DISPLAY_linked_list(char *,struct LinkedListStruct *);`09/* for debugg
Ving, display the values in a linked list */
X
X/*
X * and plain old global variable definitions
X */
Xshort modify;`09`09`09`09`09`09`09/* do or do not modify the UAF values ? */
Xshort log;`09`09`09`09`09`09`09/* do or do not log things? */
Xshort exclude;`09`09`09`09`09`09`09/* do or do not look at a list of exclude
Vd usernames? */
Xchar  exclude_file`5BNAM$C_MAXRSS + 1`5D;`09`09`09`09/* file whence exclusio
Vns */
Xlong  exit_status = SS$_NORMAL;`09`09`09`09`09/* assume the best until prove
Vn otherwise */
Xlong  shutup;`09`09`09`09`09`09`09/* for SILENT exit, turn on bit 28. */
Xlong  bit28 = 28;`09`09`09`09`09`09/* this is the bit, boys! */
Xshort UAF_wants_modification = FALSE;`09`09`09`09/* not unless proven otherw
Vise.  for exit status reporting. */
Xshort UAF_got_it = FALSE;`09`09`09`09`09/* ditto. */
Xlong  time_conversion = -100000;`09`09`09`09/* for converting quadword inter
Vnal time to longword $SETUAI time */
X
X
X`0C
X/***************************************
X * Main program for SETPQL begins here.*
X ***************************************/
Xmain()
X`7B
X /*
X  * variable declarations
X  */
X long status;
X short i;
X
X /*
X  * Parse the command line.  This routine will:
X  *`09- set global variables based upon the values on the command line, for
X  *`09  modify and log;
X  *`09- set up the value of the IncludeUser list, a linked list containing
X  *`09  all of the usernames entered on the command line to be INCLUDEd in t
Vhe
X  *`09  scan;
X  *`09- determine the name of the exclude_file containing usernames to be
X  *`09  EXCLUDEd from the scan;
X  *`09- set up the value of the ExcludeUser list, a linked list containing
X  *`09  all of the usernames entered on the command line to be EXCLUDEd from
V the
X  *`09  scan, as well as all of the usernames contained in the exclude_file;
X  *`09- determine which UAF parameters are to be examined and set the approp
Vriate
X  *`09  Info`5Bi`5D.shallwe to TRUE for each parameter we want to examine;
X  *`09- determine the value entered on the command line (if any) for each pa
Vrameter
X  *`09  we are supposed to examine and populate the appropriate Info`5Bi`5D.
Vcmdval
X  *`09  (if NOT_DEFINED, then we use the DEFAULT account value)
X  */
X
X status = parse_cmdline();
X SIGNAL(status);
X#ifdef DEBUG
X `7B
X   DISPLAY_linked_list("IncludeUser", IncludeUser_Root);
X   DISPLAY_linked_list("ExcludeUser", ExcludeUser_Root);
X `7D
X#endif
X
X /*
X  * Initialize all data structures and pointers.  This will
X  * set the shutup bits so we can exit silently, point the Address
X  * structures to the appropriate values within the Value structures,
X  * set the verb tense on the to_be variable, loads the MasterValue
X  * username with "DEFAULT".
X  */
X  status = init_data_structures();
X  SIGNAL(status);
X
X /*
X  * Set the ItemList pointers at the MasterAddress, so that
X  * we can store the DEFAULT account values as our preliminary
X  * best guess (we'll check with command line values later).
X  * Then call $GETUAI to read the DEFAULT account values.
X  * Be careful if there is no DEFAULT account!!
X  */
X
X status = init_ItemList( &ItemList, &MasterAddress );`09   `09/* Initialize
V the itemlist pointers so that they point to the */
X SIGNAL(status);`09`09`09`09`09   `09/*  MasterAddress locations.  We will s
Vtore the DEFAULT account */
X`09`09`09`09`09`09`09   `09/*  PQL values here first. */
X status = sys$getuai(0, 0, &Master_d, &ItemList, 0, 0, 0 );`09/* call $GETUA
VI to obtain the default uaf values */
X if ( status == RMS$_RNF )
X `7B`09`09`09`09`09`09`09`09/* no DEFAULT account record!!  We'd better be c
Vareful here. */
X    lib$signal(pql_nodfltacct);`09`09`09`09`09/* Signal this error. */
X    for( i = 0; i < MAX_PARAMS; i++ )`09`09`09`09/* Reset any command line e
Vntries that were planning on */
X    `7B`09`09`09`09`09`09`09`09/*  using DEFAULT account values -- we CAN'T
V USE THEM!! */
X`09if ( Info`5Bi`5D.cmdval == NOT_DEFINED )
X`09  Info`5Bi`5D.shallwe = FALSE;
X    `7D
X `7D
X else
X    SIGNAL(status);
X
X /*
X  * Now check: do we really have anything to do?
X  * There are certainly combinations of input parameters
X  * which would imply that we will not change anything nor
X  * display anything -- so why go through all the bother
X  * for nothing?!
X  */
X if ( we_are_lazy() )`09`09`09`09`09`09/* do we have anything to do? */
X `7B`09`09`09`09`09`09`09`09/* if not, why bother wasting all this CPU time?
V */
X     lib$signal(pql_nop);`09`09`09`09`09/* signal that this was a no-op */
X     exit_status = pql_nodfltacct;`09`09`09`09/* set this as the exit status
V */
X     exit(exit_status `7C shutup);
X `7D
X
X /*
X  * Set the Master values which will be used as minimum quotas.
X  * This will be either the value entered on the command line,
X  * e.g., /ASTLM=100, or the value from the DEFAULT account if
X  * no value was specified on the command line, e.g., /ASTLM.
X  */
X status = set_MasterValue( &MasterAddress );
X SIGNAL(status);
X
X
X /*
X  * Prepare the SYSUAF file for reading, record by record, to get
X  * the list of usernames on this system.
X  * This will also perform a sanity check to make sure that our record
X  * parameters still match the VMS SYSUAF format parameters (at least,
X  * as far as the USERNAME goes).  After all, the format of this file
X  * may change -- let's see if we can figure that out.
X  */
X  status = open_sysuaf();
X  SIGNAL(status);
X
X/*
X * And now we are ready to go.  Loop through each and every username,
X * and make sure that their pql values meet the minimums specified
X * in the MasterValues.
X * Point the ItemList at the UserAddress/UserValue array and then`20
X * we're off!
X */
X status = init_ItemList( &ItemList, &UserAddress );
X SIGNAL(status);
X
X/*
X * And set up the loop.
X */
X while (  (status = get_nextuser( &UserValue.username )) != RMS$_EOF )
X `7B
X#   ifdef DEBUG
X      printf("\n\nnext username = >%s<", UserValue.username );
X#   endif
X
X    SIGNAL(status);
X    User_d.dsc$w_length = strlen( UserValue.username );`09`09/* set up the s
Vtring descriptor for the $GETUAI call. */
X
X    status = sys$getuai(0, 0, &User_d, &ItemList, 0, 0, 0);`09/* get this us
Ver's pql values. */
X    SIGNAL(status);
X
X    if ( include_this_user(UserValue.username, UserValue.uic) )`09/* should
V this username be INCLUDED? or EXCLUDED? */
X    `7B
X
X  `20
X#      ifdef DEBUG`09`09`09`09`09`09/* if we're debugging, let's see the val
Vues in SYSUAF */
X       `7B
X         printf("\nBEFORE set_UserValue:");
X         DISPLAY_by_addr(&UserAddress);
X       `7D
X#      endif
X   `20
X
X       status = set_UserValue( &UserAddress, &MasterAddress );`09/* make sur
Ve this user meets the minimums! */
X       SIGNAL(status);
X
X  `20
X#      ifdef DEBUG`09`09`09`09`09`09/* and let's see what was modified. */
X       `7B
X`09   printf("\nAFTER set_UserValue:");
X`09   DISPLAY_by_addr(&UserAddress);
X       `7D
X#      endif
X
X      /*
X       * If we are NOT modifying, then we're done; the logging
X       * was already accomplished during the set_UserValue phase.
X       * If we ARE modifying, then make the $SETUAI call now:
X       */
X       if ( modify )
X       `7B
X`09   UAF_got_it = TRUE;
X`09   status = sys$setuai(0, 0, &User_d, &ItemList, 0, 0, 0);
X`09   SIGNAL(status);
X       `7D
X    `7D`09`09`09`09`09`09`09`09/* end of loop for DO-THIS-USER. */
X    else
X    `7B
X#      ifdef DEBUG
X`09 printf("\nEXCLUDING username >%s<",UserValue.username);
X#      endif
X    `7D
X
X `7D `09`09`09`09`09`09`09`09/* end of (while) loop */
X
X /*
X  * Close the SYSUAF file.
X  */
X status = sys$close( &uaffab );
X SIGNAL(status);
X
X /*
X  * If we didn't modify anything, remind everybody
X  * that we left our filthy paws off.  Otherwise,
X  * remind them that we were there!
X  */
X if ( UAF_wants_modification && UAF_got_it )
X `7B
X   lib$signal(pql_uafchanged);
X `7D
X else
X `7B `20
X   lib$signal(pql_nochanges);
X `7D
X
X /*
X  * Exit SILENTLY by turning on bit 28.  (We already issued the
X  * appropriate exit messages somewhere else).
X  */
X exit(exit_status `7C shutup);
X`7D
X`0C
X
X/****************************************************
X * Function to obtain the command line and parse for*
X * the parameters entered by the user.              *
X ****************************************************/
X
Xlong parse_cmdline()
X`7B
X extern int LIB$GET_FOREIGN();`09`09`09/* obtain command line */
X extern int CLI$DCL_PARSE();`09`09`09/* check to make sure it is legal */
X extern int CLI$PRESENT();`09`09`09/* check if qualifier/parameter is presen
Vt */
X extern int CLI$GET_VALUE();`09`09`09/* get value of qualifier= or paremeter
V */
X extern int LIB$GET_INPUT();`09`09`09/* prompt for missing parameters/qualif
Viers */
X extern int SETPQL_CLD();`09`09`09/* command definition module */
X
X long status;`09`09`09`09`09/* test status return values */
X char string`5BNAM$C_MAXRSS - 7 + 1`5D;`09`09/* put together the qualifiers/
Vparameters entered on the command line */
X char full_cmd`5BNAM$C_MAXRSS + 1`5D;`09`09/* and add the command verb itsel
Vf */
X $DESCRIPTOR(string_d, string);`09`09`09/* of course, VMS needs these in des
Vcriptor format */
X $DESCRIPTOR(full_cmd_d, full_cmd);
X char verb`5B`5D = "SETPQL ";`09`09`09/* defined in the SETPQL_CLD module */
X short len;`09`09`09`09`09/* cli routines return the number of characters wr
Vitten, we need to null-terminate*/
X short i;
X short do_all;`09`09`09`09`09/* is /ALL on the command line? */
X long dummy;
X
X char qualifier`5BNAM$C_MAXRSS + 1`5D = " ";`09/* set up for looping on the
+-+-+-+-+-+-+-+-  END  OF PART 3 +-+-+-+-+-+-+-+-