#module  GETQUOTA  "V1.1"

/*++GETQUOTA.C

 Facility: 
	Fermilab Accelerator Control System - VAX/VMS ACNET
	General utility program.

 Abstract:
	This program (along with GETQUOTA.CLD) implements a DCL command to
	return the current disk usage, permanent quota and overdraft quota
	from the quota file in DCL local symbols.  Optionally, the command
	parameter may specify either the disk (SYS$DISK: is used as the
	default) and/or the UIC to be accessed.

 Environment:
	User mode via a user-defined DCL command.
--*/

/*
 Modification History:
 Author: F. Nagy

 V1.0	13-Jan-84  FJN	Created to replace all those little command procedures
 V1.1	16-Jan-84  FJN	Debugging... allow P1 to be list parameter to handle
			"," in the UIC correctly
*/

/******************
 * Include Files: *
 ******************/
#include  vaxtypes			/* VAX-11 C Type extensions */
#include  descrip			/* VAX-11 Descriptors */
#include  descrip2			/* Additional descriptor defs. */
#include  $shrdef			/* Shared messages */
#include  stsdef			/* Fields of status code */

/********************************
 * Local definitions and types: *
 ********************************/
typedef unsigned long status;		/* Condition code status type */

typedef struct UIC {			/* User Identification Code */
    uword mem;				/* Member number */
    uword grp;				/* Group number */
    } UIC;

globalvalue  SS$_NORMAL;
globalvalue  CLI$_FACILITY;		/* CLI message facility code */
#define  CLI$_SYNTAX  $SHR_MSGDEF( CLI$_FACILITY, SHR$_SYNTAX, STS$K_SEVERE)
globalvalue  CLI$_CONCAT;		/* List elements connected by "+" */

#define  PARAMETER_LEN	32		/* Parameter string buffer length */
#define  SYMBOL_LEN	255		/* Symbol name buffer length */
#define  NUMBER_LEN	13		/* Number string buffer length */

#define  _RO_DESCR(d,s)	static readonly $DESCRIPTOR(d,s)


/*+0Main Program

 Functional Description:
	Provide pseudo-lexical function to access disk quota entry from DCL.

 Calling Sequence:
	$ SET COMMAND FERMI$EXE:GETQUOTA
	$ GETQUOTA[qualifiers]  [[dev:]uic]

 Side Effects:
	Read access to the quota file is required to examine quotas for
	other UIC's.
-*/

main()
{
_RO_DESCR( d_used_qual, "USED");
int used_return = FALSE;		/* Return used space value */
char used_name[SYMBOL_LEN];		/* Buffer for /USED symbol name */
$DESCRIPTORM( d_used_name, used_name);

_RO_DESCR( d_perm_qual, "PERMANENT");
int perm_return = FALSE;		/* Return permanent quota value */
char perm_name[SYMBOL_LEN];		/* Buffer for /PERMANENT symbol name */
$DESCRIPTORM( d_perm_name, perm_name);

_RO_DESCR( d_over_qual, "OVERDRAFT");
int over_return = FALSE;		/* Return overdraft quota value */
char over_name[SYMBOL_LEN];		/* Buffer for /OVERDRAFT symbol name */
$DESCRIPTORM( d_over_name, over_name);

int got_uic = FALSE;			/* Flags user specified UIC */
ulong uicmem, uicgrp;			/* Temp. group/member numbers */
UIC uic;				/* Specified UIC value */
UIC *up;				/* Pointer to UIC value */

$DESCRIPTOR( d_param_1, "P1");
char p1[PARAMETER_LEN];			/* Parameter buffer */
$DESCRIPTORM( d_p1, p1);		/* Parameter buffer descriptor */
char *p;				/* Temporary character pointer */

int got_device = FALSE;			/* Flags user specifies device */
$DESCRIPTOR0( d_device);		/* Descriptor for device name */
_RO_DESCR( d_sysdisk, "SYS$DISK:");	/* Default device text/descr. */
struct dsc$descriptor_s *dp;		/* Pointer to device descriptor */

char number[NUMBER_LEN];		/* Buffer for numeric text */
$DESCRIPTOR( d_number, number);		/* Descriptor for same */
int used;				/* No. of disk blocks in use */
int perm;				/* Permanent disk quota */
int over;				/* Overdraft disk quota */

status sts;				/* Completion status */
status CLI$PRESENT();			/* Check for qualifier/parameter */
status CLI$GET_VALUE();			/* Return parameter/qualifier value */
status LIB_GET_DISK_QUOTA();		/* Get disk quota entry */
status LIB$SET_SYMBOL();		/* Define DCL symbol */

int sprintf();				/* Binary to text via format */
int strlen();				/* Length of NUL-term string */
int sscanf();				/* Scan string using format */
char *strchr();				/* Point to character in string */

/*
  Check for the /USED qualifier and if found, get the symbol name to set.
*/
if ($VMS_SUCCESS( CLI$PRESENT( &d_used_qual)))
    {
    used_return = TRUE;
    CLI$GET_VALUE( &d_used_qual, &d_used_name);
    }

/*
  Check for the /PERMANENT qualifier and if found, get the symbol name to set.
*/
if ($VMS_SUCCESS( CLI$PRESENT( &d_perm_qual)))
    {
    perm_return = TRUE;
    CLI$GET_VALUE( &d_perm_qual, &d_perm_name);
    }

/*
  Check for the /OVERDRAFT qualifier and if found, get the symbol name to set.
*/
if ($VMS_SUCCESS( CLI$PRESENT( &d_over_qual)))
    {
    over_return = TRUE;
    CLI$GET_VALUE( &d_over_qual, &d_over_name);
    }

/*
  Check for the parameter and if found, decode into device and UIC pieces as
  present.
*/
if ($VMS_SUCCESS( CLI$PRESENT( &d_param_1)))
    {
    sts = CLI$GET_VALUE( &d_param_1, &d_p1);
    STR$TRIM( &d_p1, &d_p1, &$LENGTH(d_p1));
    p = &p1[$LENGTH(d_p1)];		/* Point to last non-blank */
    *p = '\0';				/* Provide NUL terminator for string */
    if ($VMS_SUCCESS( CLI$GET_VALUE( &d_param_1, &d_number)))
	{
	STR$TRIM( &d_number, &d_number, &$LENGTH(d_number));
	/*
	  Got second part of UIC string, restore "," (or "+") and the second
	  part to the parameter string.
	*/
	*p++ = (sts == CLI$_CONCAT) ? '+' : ',';
	strncpy( p, number, $LENGTH(d_number));
	$LENGTH(d_p1) += $LENGTH(d_number) + 1;
	p1[$LENGTH(d_p1)] = '\0';
	}
    if (sts == CLI$_CONCAT)
	LIB$SIGNAL( CLI$_SYNTAX, 1, &d_p1);

    /*
	Check for ":", if found assume text up to ":" is the device name.
    */
    if ((p = strchr( p1, ':')) != NULL)
	{
	$POINTER(d_device) = p1;	/* Found ":", setup device name */
	$LENGTH(d_device) = (p++) - p1;	/* NOTE: p points to UIC text now */
	got_device = TRUE;
	}
    else
	p = p1;				/* Assume only UIC parameter */

    /*
	Now check for UIC text (provided pointer is not to NUL character).
    */
    if (*p != '\0')
	if (sscanf( p, "[%o,%o]", &uicgrp, &uicmem) < 2)
	    {
	    $POINTER(d_p1) = p;		/* Setup UIC text descriptor */
	    $LENGTH(d_p1) = strlen(p);
	    LIB$SIGNAL( CLI$_SYNTAX, 1, &d_p1);
	    }
	else
	    {
	    got_uic = TRUE;		/* Decoded UIC successfully */
	    uic.grp = uicgrp;
	    uic.mem = uicmem;
	    }
    }

/*
  Now setup pointer to descriptor for either default or specified device
  text.  Similary setup pointer to UIC (or NULL pointer).
*/
dp = got_device ? &d_device : &d_sysdisk;
up = got_uic ? &uic : NULL;

/*
  Now access the quota entry.
*/
sts = LIB_GET_DISK_QUOTA( &used, &perm, dp, up, 0, &over);
ABORT_ON_FAILURE( sts);

/*
  Define used disk space symbol if the /USED qualifier was seen.
*/
if (used_return)
    {
    $LENGTH(d_number) = sprintf( number, "%d", used);
    sts = LIB$SET_SYMBOL( &d_used_name, &d_number);
    ABORT_ON_FAILURE( sts);
    }

/*
  Define permanent disk quota symbol if the /PERMANENT qualifier was seen.
*/
if (perm_return)
    {
    $LENGTH(d_number) = sprintf( number, "%d", perm);
    sts = LIB$SET_SYMBOL( &d_perm_name, &d_number);
    ABORT_ON_FAILURE( sts);
    }

/*
  Define overdraft quota symbol if the /OVERDRAFT qualifier was seen.
*/
if (over_return)
    {
    $LENGTH(d_number) = sprintf( number, "%d", over);
    sts = LIB$SET_SYMBOL( &d_over_name, &d_number);
    ABORT_ON_FAILURE( sts);
    }

return SS$_NORMAL;
}
