From:	CSBVAX::MRGATE!MRMANAGER@CRDMAIL  4-DEC-1987 16:21
To:	ARISIA::EVERHART
Subj:	retry on delivery



Date:  4-DEC-1987 16:09
From: Postmaster at GE-CRD.ARPA
Sender: MRMANAGER@CRDMAIL@CSBVAX
Subject: retry on delivery
To: everhart@arisia@mrgate
--------
M„POSTMASTERL„POSTMASTERL„Failed to deliver to: JMS%uamis@rvax.ccit.arizona.edu
Error - Internet address for node 'rvax.ccit.arizona.edu' could not be found in hosts file
------------------------------------------------------------
The  Original  Message  Follows
Delivery of this message at CSBVAX had the following result[s]:

Failed to deliver to: EVERHART

%SYSTEM-F-UNREACHABLE, remote node is not currently reachable

------------------------------------------------------------

The  Original  Message  Follows

Received: from rvax.ccit.arizona.edu by KL.SRI.COM with TCP; Mon 16 Nov 87 13:18:01-PST


Date: Mon, 16 Nov 87 13:01 MST


From: "Get thee behind me, O side order of Lucifer!"


 <JMS%uamis@rvax.ccit.arizona.edu>


Subject: RE: Disk Quotas


To: info-vax@kl.sri.com


X-VMS-To: IN::"info-vax@kl.sri.com"





Someone asked about disk quotas.  Assuming that they're talking


about something more than DISKQUOTA and the $ SHOW QUOTA programs,


I submit the following (now public-domain) software written here


by Chris Bontempi and myself.





+-------------------------------+


| Joel M Snyder                 |            BITNET: jms@arizmis.BITNET


| Univ of Arizona Dep't of MIS  |          Internet: jms@mrsvax.mis.arizona.edu


| Tucson, Arizona 85721         |   Pseudo-PhoneNET: (602) 621-2748


+-------------------------------+              ICBM: 32 13 N / 110 58 W


(I have gotten into trouble too many times to put any faith in disclaimers)


"There's nothing here that an overdose of Seconal won't cure." 





---makefile.


Dsqex : dsqex.obj , io$dsq.obj , dsqex_subcommands.obj , dsqex_msg.obj





 Link/notrace dsqex.obj,io$dsq.obj,dsqex_subcommands.obj,dsqex_msg.obj





dsqex.obj : dsqex.for


 for dsqex.for





io$dsq.obj : io$dsq.mar


 mac io$dsq.mar





dsqex_subcommands.obj : dsqex_subcommands.cld


 set command/object dsqex_subcommands.cld





dsqex_msg.obj : dsqex_msg.msg


 message dsqex_msg.msg


---dsqex.hlp


1 DSQEX





  DSQEX is a management facility used to query the user or users disk usage 


  on a particular disk and show the percentage of use compared to their 


  blocks allocated and to the maximum blocks available on the disk.  DSQEX


  is purely informational, that is, no modification of information in the


  QUOTA.SYS file is possible.





2 LIST





  This command returns the requested information to a file, instead of to


  the screen (as in the SHOW command).  The format for the LIST command is:





  LIST username or *





  Username may be any valid username on the current node.  Usernames which


  do not have a corresponding identifier in RIGHTSLIST.DAT will produce


  an error.  Note that no parameter list is allowed.  LIST * will return


  information for all users with allocated space on the currently selected


  device.





3 /OUTPUT=filename





  This qualifier directs the output of the LIST command to a particular


  output file.  If the /OUTPUT qualifier is omitted, the information is


  returned to DSQEX.LIS in the current default directory.





3 /SORT[=field]





  This qualifier sorts the output on any one of the fields in the output 


  stream.  When the /SORT qualifier is used without a value, the default 


  sort field is the USERNAME (note that if the /SORT qualifier is not 


  used, the information is returned in order of QUOTA.SYS, which is in 


  no particular order).  Other values for the /SORT qualifier are:





		ALLOCATED - Number of blocks allocated to the user(s).





		USAGE     - Number of blocks used by the user(s).





		PCT_ALLO  - Percentage of blocks used by the user(s).





		PCT_DISK  - Percentage of disk used by the user(s).





  Note that only one value may be specified for the /SORT qualifier.  Do


  not use /SORT with the /TOTAL qualifier.





3 /TOTAL





  This qualifier excludes the detailed information listing and prints 


  only the total for the users.  This qualifier is only effective with 


  the * parameter.  Do not use /TOTAL with the /SORT qualifier.





2 SHOW





  Returns information on a user or users to the terminal screen.  The format 


  for the SHOW command is:





  SHOW username or *





  Username may be any valid username on the current node.  Usernames which


  do not have a corresponding identifier in RIGHTSLIST.DAT will produce


  an error.  Note that no parameter list is allowed.  SHOW * will return


  information for all users with allocated space on the currently selected


  device.





3 /SORT[=field]





  This qualifier sorts the output on any one of the fields in the output 


  stream.  When the /SORT qualifier is used without a value, the default 


  sort field is the USERNAME (note that if the /SORT qualifier is not 


  used, the information is returned in order of QUOTA.SYS, which is in 


  no particular order).  Other values for the /SORT qualifier are:





		ALLOCATED - Number of blocks allocated to the user(s).





		USAGE     - Number of blocks used by the user(s).





		PCT_ALLO  - Percentage of blocks used by the user(s).





		PCT_DISK  - Percentage of disk used by the user(s).





  Note that only one value may be specified for the /SORT qualifier.  Do


  not use /SORT with the /TOTAL qualifier.





3 /TOTAL





  This qualifier excludes the detailed information listing and prints 


  only the total for the users.  This qualifier is only effective with 


  the * parameter.  Do not use /TOTAL with the /SORT qualifier.





2 USE





  The USE command specifies which disk in the present configuration 


  the manager wishes to draw information from.  The format of the USE 


  command is:





  USE disk_name





  Disk_name may be a physical device name or the logical name of a 


  valid device in the current configuration.  The default for gathering 


  information is the manager's current default device.  (Please note that 


  problems may occur when using this program from a nested root, that is 


  with a device logical name which represents a device and root directory.


  For example: Logical name USER: = DRA0:[USER.]).





2 HELP





  This command will produce the path to this Help Library.





2 EXIT





  This command is used to exit DSQEX and return to DCL.  Control-Z may


  be used in place of EXIT.


---dsqex$.inc


	Integer*4		dq$flags	! Flags from the diskquota file


	Integer*4		dq$uic		! UIC in the diskquota file


	Integer*4		dq$usage	! Quota used from diskquota file


	Integer*4		dq$permquota	! Allocated quota


	Integer*4		dq$overdraft	! Overdraft limit


	Character*12		dq$space	! empty space in quota file


*


* This is the structure for the diskquota QIO call.  The information from the


* QIO goes into this record structure.


*


	Structure /diskquota_structure/


	   Integer*4		dq$flags


	   Integer*4		dq$uic


	   Integer*4		dq$usage


	   Integer*4		dq$permquota


	   Integer*4		dq$overdraft


	   Character*12		dq$space


	End Structure


*


* Here is the record definition.


*


	Record /diskquota_structure/ dsqex_rec


*


* This is the definition of the sort record structure.


*


	Structure /sort_structure/


	  Character*12		username


	  Integer*4		uic


	  Integer*4		quota


	  Integer*4		usage


	  real*4		Qused


	  real*4		Dused


	End Structure


*


* This is the sort record.


*


	Record /sort_structure/ sort_rec


*


* This is the SORT_REC descriptor.  SOR$RELEASE_REC and SOR$RETURN_REC need to


* pass the sort record by descriptor.  SDESCR.BUF_LENGTH will be set up as the


* length of SORT_REC (32), and SDESCR.LOCATION will be the address of SORT_REC,


* (%loc(SORT_REC)).


*


	Structure /sort_descr/


	  Integer*2		buf_len


	  Integer*2		nada


	  Integer*4		location


	End Structure


*


* This is the record definition.


*


	Record /sort_descr/ sdescr


---dsqex.for


	Program DSQEX


	Implicit none			! Let no variable go undeclared





	Include 'DSQEX$.INC'		! More record definitions


	Include '($RMSDEF)'		! Record Management Services defs


	Include '($FIBDEF)'		! File Information Block defs


	Include '($DVIDEF)'		! Device Information defs


	Include '($DSCDEF)'		! Variable type defs for SOR$


	Include '($LBRDEF)'		! LBR services defs for help library





	Character*32	username	! Input parameter


	Character*8	logical   /'SYS$DISK'/	! Default disk name logical


	Character*20	disk		! Disk name used in QIO call


	Character*5	subcommand	! CLI subcommand


	Character*10	sort_val	! Value of /SORT qualifier


	Character*60	output_file	! output file for /OUTPUT qualifier


	integer*4	iostat_dsq(2)	! status block for QIO call


	Integer*4	CLI$DCL_PARSE	! DCL parse routine for CLI


	Integer*4	CLI$GET_VALUE	! Get value routine for CLI


	Integer*4	CLI$PRESENT	! Check presence of qual routine for CLI


	Integer*4	out_unit	! Output unit number (terminal/file)


	Integer*4	iostat_file	! status for file I/O


	Integer*4	istatus		! status variable for CLI calls


	Integer*4	ichan		! Device channel number for DISK


	Integer*4	dsflag		! Flag for finish of QIO call


	Integer*4	i,j		! counting integers


	Integer*4	Tot_blks	! max blocks on DISK


	Integer*4	iostat_asgn	! status for channel assign


	Integer*2	bfr_length	! record variables for DVI item block


	Integer*2	item_code	!


	Integer*4	bfr_addr	!


	Integer*4	rtn_length	!


	Integer*4	empty_long	!


	Real*4		usage_r		! Real for disk usage, for math


	Real*4		quota_r		! Real for Disk Quota, for math


	Real*4		Prct_quota	! Percentage of quota, calculated


	Real*4		Prct_disk	! Percentage of disk, calculated


	Real*4		Tot_r		! Real for Max Blocks, for math


	Integer*4	istat_id	! status for identifier routines


	Integer*4	Sys$assign	! Assign channel to disk routine


	Integer*4	sys$asctoid	! Translate ascii to identifier routine


	Real*4		Ent_sum		! Total records for wildcard SHOW-LIST


	Integer*4	Quota_sum	! Sum of quotas for wildcard SHOW-LIST


	Integer*4	Usage_sum	! Sum of Usage for wildcard SHOW-LIST


	Real*4		QUsed_avg	! Sum of Prct_Quota for wildcard


	Real*4		DUsed_sum	! Sum of Prct_Disk for wildcard


	Integer*2	Key_array(5)	! Word array for to specify sort key


	Integer*4	sorstat		! status for call to SOR$ routines


	Integer*4	sortpres	! status to check for presence of /SORT


	Integer*4	sor$pass_files	! Setup file defs routine for SOR$


	Integer*4	sor$begin_sort	! Define key routine for SOR$


	Integer*4	sor$sort_merge	! Sort routine for SOR$


	Integer*4	sor$end_sort	! Finish and release resources for SOR$


	Integer*4	sor$release_rec	! Send record to be sorted for SOR$


	Integer*4	sor$return_rec	! Return sorted record for SOR$


	Integer*2	lrl /32/	! longest record to be sorted for SOR$


	Integer*4	totpres		! status to check for presence of /TOTAL


	Integer*2	uic_part(2)	! 2 words to eqiv to UIC_WHOLE


	Integer*4	uic_whole	! Entire uic integer


	Character*34	help_lib /'MGR_HELP:DSQEX.HLB'/


	Character*10	help_line	! Parameter entered with HELP command


	Character*24	date_time	! date/time of command


	Integer*4	sys$asctim	! used to get current time in ascii format


	Character*80	command_line	! command line entered by user


	Integer*4	command_length	! length of command line entered by user





	Structure /dvi_structure/	! GETDVI item structure


	  Integer*2	bfr_length


	  Integer*2	item_code


	  Integer*4	bfr_addr


	  Integer*4	rtn_length


	  Integer*4	empty_long


	End Structure





	Record /dvi_structure/ dvi_rec	! GETDVI item record block





	Record /fibdef/ fib		! File Info Block record block





	Equivalence (uic_whole,uic_part(1))	! Equiv uic so it can be split





	External	Lib$Get_Input		! Generic system input routine


	External	Lib$Put_Output		! Generic system output routine


	External	Lib$signal		! Error signaling routine


	External	dsqex_subcommands	! CLD definitions


	External	sys$assign		! Assign dev channel routine


	External	sys$asctoid		! Translate to id routine


	External	CLI$_PRESENT		! Comparison Var for presence


	External	DSQEX_NOSUCHDEV		! No such device message


	External	DSQEX_NOSUCHUSER	! No such user message


	External	DSQEX_NOQUOTENTRY	! No quota for user message


	External	DSQEX_NOQUOTAS		! No quotas enabled message


	External	SS$_QFNOTACT		! Quota file not active message


	External	SS$_ENDOFFILE		! EOF def for sort routines





	parameter (out_unit=6)			! output unit number





*


* Setup item code for GETDVI.  GETDVI needs to get the Maximum number of


* blocks on DISK.


*


	dvi_rec.item_code = DVI$_MAXBLOCK





*


* Setup the descriptor for the sort block, since SOR$RELEASE_REC and


* SOR$RETURN_REC require the record to be passed by descriptor.  The


* record is SORT_REC.


*


	sdescr.buf_len = 32


	sdescr.location = %loc(sort_rec)





*


* Call CLI$DCL_PARSE to get the DSQEX subcommand.  Use DSQEX_SUBCOMMANDS


* definitions for parsing, use LIB$GET_INPUT as input routine and use


* 'Dsqex>' as them prompt


*





    1	istatus = Cli$Dcl_Parse (%val(0),dsqex_subcommands,


     c Lib$Get_Input,Lib$Get_input,'Dsqex> ')





*


* If information entered is ^Z (EOF) then exit DSQEX


*


	if (istatus .eq. RMS$_EOF) goto 999


*


* If nothing is entered at Dsqex> prompt then go back and get another


*


	if (.not. istatus) goto 1


*


* Put the verb from the command line into SUBCOMMAND


*


	istatus = Cli$Get_Value ('$VERB',subcommand)


*


* If the verb entered is SHOW


*


	if (subcommand(1:2) .eq. 'SH') then


*


* Open SYS$OUTPUT as the output device


*


	  Open (unit=out_unit,file='SYS$OUTPUT',status='UNKNOWN',


     c iostat=iostat_file,err=5000)


*


* Otherwise, if the verb entered is LIST


*


	Else if (subcommand(1:2) .eq. 'LI') then


*


* Attempt to get the value of the /OUTPUT qualifier, which may or may not


* be present.


*


	  istatus = Cli$Get_Value('OUTPUT',output_file)


*


* If there is no /OUTPUT on the command line, make DSQEX.LIS the output file


*


	  if (output_file(1:1) .eq. char(32)) output_file = 'DSQEX.LIS'


*


* Open the output file for the LIST command


*


	  Open (unit=out_unit,file=output_file,status='NEW',


     c iostat=iostat_file,err=5000)


*


* Otherwise, if the verb entered is USE


*


	Else if (subcommand(1:2) .eq. 'US') then


*


* Get the parameter from the command line


*


	  istatus = Cli$Get_Value('DISK',disk)


*


* If the disk name in DISK does not have a ":", find the end of the string


* and stick one on it.


*


	  if (index(disk,':') .eq. 0) then


	    do i=20,1,-1


	      if (disk(i:i) .ne. char(32) .and. disk(i:i) .ne.


     c char(0)) goto 5


	    end do


    5	    disk(i+1:i+1) = ':'


	  Endif


*


* Assign the disk a channel


*


	  iostat_asgn = Sys$Assign (disk,ichan,,)


*


* If the disk assign fails, assume no such disk, signal error, and


* go back and get another command line.


*


	  if (iostat_asgn .ne. 1) then


	    Call Lib$signal (DSQEX_NOSUCHDEV,%val(1),disk(1:i))


	    disk = ' '


	    goto 1


	  Endif


*


* Set up info for the GETDVI call:  Make destination point to TOT_BLKS


* and describe the length of TOT_BLOCKS as 4 bytes (integer*4)


*


	  dvi_rec.Bfr_addr = %loc(tot_blks)


	  dvi_rec.Bfr_length = 4


*


* Do the GETDVI call and put the information into TOT_BLKS


*


	  Call Sys$Getdvi (,%val(ichan),,dvi_rec,,,,)


*


* Go and get another command line


*


	  goto 1


*


* Otherwise, if the verb entered is HELP


*


	Else if (subcommand(1:2) .eq. 'HE') then


*


* Get the other info from the command line


*


	  istatus = Cli$Get_Value('HELP_LINE',help_line)


*


* Append DSQEX to the beginning of HELP_LINE to give the call that VMS


* appearence.


*


	  help_line = 'DSQEX '//help_line


*


* Call the LBR$OUTPUT_HELP routine to enter the help library


*


          Call Lbr$Output_Help(Lib$Put_output,,help_line,


     c help_lib,,Lib$Get_input)


*


* When help library is exited, go back and get another command


*


	  goto 1


*


* Otherwise, if the verb entered is EXIT go down to label 999


*


	Else if (subcommand(1:2) .eq. 'EX') then


	  goto 999


	Endif


*


* The only commands which allow the execution of the following code (with


* the exception of the code after label 999), are the SHOW and LIST commands.


*


*


* Get the parameter entered for the SHOW or LIST command.  This can be either


* a valid username for the current node, or an '*'.


*


	istatus = Cli$Get_Value('USERNAME',username)


*


* Zero the counters and summation variables


*


	ent_sum = 0


	quota_sum = 0


	usage_sum = 0


	Qused_avg = 0


	Dused_sum = 0


*


* If DISK has nothing in it, then translate LOGICAL (SYS$DISK) to find


* the current default device of the operator.  The follow code is performed


* only if the operator did not issue a USE command.


*


	If (disk(1:1) .eq. char(32) .or. disk(1:1) .eq. char(0)) then


*


* Translate the logical name


*


	  Call Lib$Sys_Trnlog (logical,,disk)


*


* Assign a channel to the disk


*


	  iostat_asgn = Sys$Assign (disk,ichan,,)


*


* Set up the pointer to TOT_BLKS for the DVI call


*


	  dvi_rec.Bfr_addr = %loc(tot_blks)


	  dvi_rec.Bfr_length = 4


*


* Call GETDVI to get the maximum number of blocks on the disk


*


	  Call Sys$Getdvi (,%val(ichan),,dvi_rec,,,,)


	Endif	  


*


* If this is a wildcard operation, that is, if the parameter from the


* SHOW or LIST command is an '*' then do the following


*


	if (username(1:1) .eq. '*') then


*


* If the verb is SHOW, set up the top 3 lines on the screen so they don't 


* scroll by displaying format line 2005 with <ESC> characters.


*


	  if (subcommand(1:2) .eq. 'SH') 


     c write (out_unit,2005) char(27),char(27),char(27)


*


* Now output a special line which shows the date/time, the command, and the 


* device being shown.


*


	Call Sys$Asctim (,date_time,,)


	istatus = Cli$Get_value ('$LINE',command_line,command_length)


	Write (out_unit,3000) date_time,command_line,disk


*


* Then, regardless of whether its a SHOW or LIST function, write out the


* HEADER LINES from format lines 2007 and 2008.


*


	  write (out_unit,2007)


	  write (out_unit,2008)


*


* Find out if either /SORT or /TOTAL is present on the command line and


* store the value in SORTPRES and TOTPRES respectively.


*


	  sortpres = Cli$PRESENT('SORT')


	  totpres = Cli$PRESENT('TOTAL')


*


* If /SORT is on the command line


*


	  if (sortpres .eq. %LOC(CLI$_PRESENT)) then


*


* Get the value associated with the /SORT, if there is one.  This value will


* be a string associated with the field to sort on.


*


	    istatus = Cli$Get_Value('SORT',sort_val)


*


* Set up the generic key information, key_array(1) is the number of


* keys defined in the key array.  Key_array(3) is for flags which


* are not used in this program.


*


	    key_array(1) = 1


	    key_array(3) = 0


*


* The following tests the value on the /SORT qualifier and sets up the


* datatype, offset and length of the key to sort on.  These offsets and


* lengths refer to SORT_REC.  The UIC portion of SORT_REC is ignored.


*


* If the value from the /SORT qualifier is USERNAME


*


	    if (sort_val(1:3) .eq. 'USE') then


*


* Set up the key type to be TEXT


*


	      key_array(2) = DSC$K_DTYPE_T


*


* Set up the starting position of the key to be byte 0


*


	      key_array(4) = 0


*


* Set up the length of the key to be 12 bytes


*


	      key_array(5) = 12


*


* Otherwise, if the value from the /SORT qualifier is ALLOCATED


*


	    else if (sort_val(1:3) .eq. 'ALL') then


*


* Set up key type as longword unsinged integer


*


	      key_array(2) = DSC$K_DTYPE_LU


*


* Set up key to start at byte 16


*


	      key_array(4) = 16


*


* Set up key length as 4 bytes


*


	      key_array(5) = 4


*


* Otherwise, if the value of the /SORT qualifier is USAGE


*


	    else if (sort_val(1:3) .eq. 'USA') then


*


* Set up key type as longword unsigned integer


*


	      key_array(2) = DSC$K_DTYPE_LU


*


* Set up key to start at byte 20


*


	      key_array(4) = 20


*


* Set up key length as 4 bytes


*


	      key_array(5) = 4


*


* Otherwise, if the value of the /SORT qualifier is PCT_ALLOCATED


*


	    else if (sort_val(1:5) .eq. 'PCT_A') then


*


* Set up the type of the key as d-type floating


*


	      key_array(2) = DSC$K_DTYPE_F


*


* Set up the starting position as byte 24


*


	      key_array(4) = 24


*


* Set up the length as 4 bytes


*


	      key_array(5) = 4


*


* Otherwise, if the value of the /SORT qualifier is PCT_DISK


*


	    else if (sort_val(1:5) .eq. 'PCT_D') then


*


* Set up the datatype as d-type floating


*


	      key_array(2) = DSC$K_DTYPE_F


*


* Set up the starting position as byte 28


*


	      key_array(4) = 28


*


* Set up the length as 4 bytes


*


	      key_array(5) = 4


	    Endif               


*


* Now that the key is defined, invoke the SOR$BEGIN_SORT routine to set


* up all necesary sort stuff.


*


	    sorstat = sor$begin_sort(key_array,%loc(lrl))


	  Endif


*


* Set dsflag to something other than zero.


*


	  dsflag = 1


*


* Set up the FIB for wildcard QIOs to QUOTA.SYS.


*


	  Fib.Fib$L_Exsz = Fib$M_All_Mem .or. Fib$M_All_Grp


	  Fib.Fib$L_Wcc = 0


	  Fib.Fib$W_Exctl = FIB$C_EXA_QUOTA


*


* Now, until dsflag is 0, do the following


*


	  Do While (dsflag .ne. 0)


*


* Initialize the fields in DSQEX_REC


*


	    dsqex_rec.dq$uic = 0


	    dsqex_rec.dq$permquota = 0


	    dsqex_rec.dq$usage = 0


	    sort_rec.username = ' '


	    sort_rec.uic = 0


*


* Make the call to user subroutine READ_DSQ, passing DSQEX_REC, the


* File Information Block, the device channel and a status block


*


	    Call Read_Dsq (dsqex_rec,fib,ichan,iostat_dsq)


*


* If quotas are not enabled for this device, signal and go back to


* get another command line.


*


	    if (iostat_dsq(1) .eq. %loc(SS$_QFNOTACT)) then


	      Call Lib$Signal (DSQEX_NOQUOTAS,%val(1),disk(1:20))


	      goto 1


	    Endif


*


* Translate the UIC identifier to its ascii equivalent (username)


*


	    Call Sys$Idtoasc


     c (%val(dsqex_rec.dq$uic),,sort_rec.username,,,)


*


* If UIC doesn't translate, put UNKNOWN in the username field.


*


	    if (sort_rec.username .eq. ' ') then


	      sort_rec.uic = dsqex_rec.dq$uic


              sort_rec.username = 'Unknown'


	    Endif


*


* Give real variables the integer values, for math with other real variables.


*


	    usage_r = float (dsqex_rec.dq$usage)


	    quota_r = float (dsqex_rec.dq$permquota)


	    tot_r = float (tot_blks)


*


* Set up the info in SORT_REC


*


	    sort_rec.quota = dsqex_rec.dq$permquota


	    sort_rec.usage = dsqex_rec.dq$usage


	    sort_rec.Qused = 0


	    sort_rec.dused = 0


	    If (sort_rec.quota .ne. 0) sort_rec.Qused = 


     c (usage_r/quota_r)*100


	    If (tot_r .ne. 0) sort_rec.Dused = 


     c (usage_r/tot_r)*100


*


* If /TOTAL is not on the command line, go ahead and sort the info


*


	    if (totpres .ne. %LOC(CLI$_PRESENT)) then


*


* That is, if /SORT IS on the command line


*


	      if (sortpres .eq. %LOC(CLI$_PRESENT)) then


*


* Send SORT_REC by way of SDESCR, the SORT_REC descriptor, to be sorted


*


	        sorstat = Sor$release_rec (sdescr)


	      Else


*


* Otherwise, that is, if there is no /TOTAL and no /SORT, just write out the 


* info in the order that its read from QUOTA.SYS.


*


	        Write (out_unit,2000) sort_rec.username,


     c sort_rec.quota,sort_rec.usage,sort_rec.Qused,


     c sort_rec.Dused


	      Endif	      


	    Endif


*


* Accumulate totals for the total line.


*


	    Ent_sum = ent_sum + 1


	    Quota_sum = Quota_sum + sort_rec.quota


	    Usage_sum = Usage_sum + sort_rec.usage


	    Qused_avg = Qused_avg + sort_rec.Qused


	    Dused_sum = Dused_sum + sort_rec.Dused


	    dsflag = fib.fib$l_wcc


	  End do


*


* After all of the information on each entry in QUOTA.SYS has been


* gathered and sent either to be sorted or to the screen...


*


* If /TOTAL qualifier is not used


*


	  if (totpres .ne. %LOC(CLI$_PRESENT)) then


*


* And if /SORT is used


*


	    if (sortpres .eq. %LOC(CLI$_PRESENT)) then


*


* Perform the sort on the information sent by SOR$RELEASE_REC.


*


	      sorstat = Sor$sort_merge ()


*


* Now, until there are no more records left in the temporary sort space,


*


	      Do while (sorstat .ne. %loc(SS$_ENDOFFILE))


*


* Return each record, one at a time.


*


	        sorstat = Sor$return_rec (sdescr,sdescr.buf_len)


*


* If this a real record, and not the end of the "file"


*


	        if (sorstat .ne. %loc(SS$_ENDOFFILE)) then


*


* Check to see if the uic is 0.  If it isn't...


*


	          if (sort_rec.uic .ne. 0) then


*


* Put the uic into UIC_WHOLE, which is equived to UIC_PART(1), and


* output the record to its destination with UIC in place of the


* username.  This uses format line 2001, instead of 2000, which is the


* standard output line for this program.


*


	            uic_whole = sort_rec.uic


	            Write (out_unit,2001) uic_part(2),uic_part(1),


     c sort_rec.quota,sort_rec.usage,sort_rec.Qused,sort_rec.Dused


	          Else


*


* Otherwise, if the UIC is 0, which it would be if the uic translated to


* a valid username, just write out the record with the username showing


* in the record.  If the username is Unknown, then the UIC is [0,0].


*


	            Write (out_unit,2000) sort_rec.username,


     c sort_rec.quota,sort_rec.usage,sort_rec.Qused,sort_rec.Dused


	          Endif


                Endif


	      End do


*


* When all of the records have been returned and written out, release all of


* the resources used for the sort.


*


	      sorstat = Sor$end_sort ()


	    Endif


*


* Write out a blank line for format.


*


	    Write (out_unit,7000)


	  Endif


*


* Make USERNAME in the record = to Totals.


*


	  Username = '    Totals'


*


* Write out the accumlated totals for all of the records.   QUOTA_SUM is the


* total of all user's quotas, USAGE_SUM is the total of all blocks used on the


* disk, QUSED_AVG/ENT_SUM is the average percentage of quota used, and 


* DUSED_SUM is the total of percentage of disk used.


*


	  Write (out_unit,2000) username,quota_sum,usage_sum,


     c Qused_avg/ent_sum,dused_sum


*


* If the command verb was SHOW, write out format line 2006 with escape


* characters to reset the entire screen as the scrolling region.


*


	  if (subcommand(1:2) .eq. 'SH') 


     c write (out_unit,2006) char(27),char(27)


*


* Otherwise, (this ELSE refers to whether username was an * or not)


*


	Else


*


* Find the last character in the USERNAME string


*


	  Do j=32,1,-1


	    if (username(j:j) .ne. char(0) .and. username(j:j)


     c .ne. char(32)) goto 30


	  End do


*


* Convert the username entered to its binary identifier.


*


   30	  istat_id = SYS$ASCTOID (username,dsqex_rec.dq$uic,)


*


* If this doesn't work, tell the user that this is not a valid username


* and go back to get another command.


*


	  if (istat_id .ne. 1) then


	    Call Lib$signal (DSQEX_NOSUCHUSER,%val(1),username(1:j))


	    goto 1


	  Endif


*


* Set up the File Information Block for a single QIO operation


*


	  Fib.Fib$L_Exsz = 0


	  Fib.Fib$W_Exctl = FIB$C_EXA_QUOTA


*


* Call user routine READ_DSQ to get the quota information for the


* user specified.


*


	  Call Read_dsq (dsqex_rec,fib,ichan,iostat_dsq)


*


* If quotas are not enabled on this volumn, signal as much, and


* go get another command.


*


	    if (iostat_dsq(1) .eq. %loc(SS$_QFNOTACT)) then


	      Call Lib$Signal (DSQEX_NOQUOTAS,%val(1),disk(1:20))


	      goto 1


	    Endif


*


* If there is another problem getting the quota entry for the username 


* specified, signal a "No entry found for this user" message and go 


* get another command.


*


	  if (iostat_dsq(1) .ne. 1) then


	    Call Lib$signal (DSQEX_NOQUOTENTRY,%val(2),username(1:j)


     c ,disk(1:20))


	    goto 1


	  endif


*


* If the info was found, convert it all to floating point numbers.


*


	  usage_r = float (dsqex_rec.dq$usage)


	  quota_r = float (dsqex_rec.dq$permquota)


	  tot_r = float (tot_blks)


*


* Initialize the percentage fields.


*


	  Prct_quota = 0


	  Prct_disk = 0


*


* If the divisors of the equation are not zero, calculate the percentages


* of allocated and disk.


*


	  If (quota_r .ne. 0) Prct_quota = (usage_r/quota_r)*100


	  If (tot_r .ne. 0) Prct_disk = (usage_r/tot_r)*100


*


* Write out the information for the reqested user.


*


	  Write (out_unit,2000) username,dsqex_rec.dq$permquota,


     c dsqex_rec.dq$usage,prct_quota,prct_disk


	Endif


*


* Go back and get another command.


*


	goto 1





*


* This is the standard output line for either the SHOW or the LIST


*


 2000	format(1x,a12,5x,i11,5x,i11,5x,f11.2,'%',5x,f11.2,'%')


*


* This is the output line for the SHOW or LIST with untranslatable UIC


*


 2001	format(1x,'[',o6,',',o6,']',5x,i8,5x,i11,5x,f11.2,'%',


     c 5x,f11.2,'%')


*


* This is the escape sequence line which sets the top 3 lines to noscroll.


*


 2005	format(1x,a,'[2J',a,'[1;1H',a,'[5;24r')


*


* This is the escape sequence line which sets the entire screen to scroll.


*


 2006	format(1x,a,'[1;24r',a,'[23;1H')


*


* These are the header lines


*


 2007	format(1x,'  Username  ',6x,' Allocated ',7x,'   Usage   ',


     c 5x,' % of Alloc',5x,' % of Disk ')


 2008	format(1x,'  ========  ',6x,' ========= ',7x,'   =====   ',


     c 5x,' ==========',5x,' ========= ')





 3000	format(1x,a24,1x,'"',a<command_length>,'" of ',a20)


*


* This is the error handler, in case the output file will not open or will


* not be written to.  This error is handled this way because it should not


* happen, and if it does, something is really wrong.


*


 5000	write (6,1000) out_unit,iostat_file


 1000	format (1x,'File error: Unit=',i,' iostat=',i)


	stop


*


* This is the blank line format.


*


 7000	format (1x)


*	


* This is the program exit routine which closes OUT_UNIT and exits.


*


  999	close (out_unit)


	end


---dsqex_msg.msg


..FACILITY           DSQEX,1/PREFIX=DSQEX_


NOSUCHDEV <!AS is not a valid device name>/FAO=1/ERROR


NOSUCHUSER <!AS does not exist on this node>/FAO=1/ERROR


NOQUOTENTRY <No quota information for !AS on !AS>/FAO=2/ERROR


NOQUOTAS <Quotas not enabled for volume !AS>/FAO=1/ERROR


---dsqex_subcommands.cld


MODULE DSQEX_SUBCOMMANDS


DEFINE TYPE SORT_TYPE


                KEYWORD USERNAME, DEFAULT


                KEYWORD ALLOCATED


                KEYWORD USAGE


                KEYWORD PCT_ALLOCATED


                KEYWORD PCT_DISK


DEFINE VERB SHOW


  PARAMETER P1, LABEL = USERNAME


                VALUE (REQUIRED)


                PROMPT = "Username"


  QUALIFIER SORT


                VALUE (TYPE=SORT_TYPE)


  QUALIFIER TOTAL


  DISALLOW (TOTAL AND SORT)


DEFINE VERB LIST


  PARAMETER P1, LABEL = USERNAME


                VALUE (REQUIRED)


                PROMPT = "Username"


  QUALIFIER OUTPUT


                VALUE (TYPE=$FILE)


  QUALIFIER SORT


                VALUE (TYPE=SORT_TYPE)


  QUALIFIER TOTAL


  DISALLOW (TOTAL AND SORT)


DEFINE VERB USE


  PARAMETER P1, LABEL = DISK


                VALUE (REQUIRED)


                PROMPT = "Device"


DEFINE VERB HELP


  PARAMETER P1, LABEL = HELP_LINE


  QUALIFIER SORT


  QUALIFIER OUTPUT


  QUALIFIER TOTAL


DEFINE VERB EXIT


---io$dsq.mar


;+++


; ACP CONTROL Defs


;


	.Library	/SYS$LIBRARY:LIB/


	


	$DQFDEF				; Diskquota File definitions


	$FIBDEF				; File Information Block Defs


	$IODEF				; I/O defs


	$SSDEF				; Message definitions





dqfdesc:				; diskquota file descriptor


	.word		DQF$C_LENGTH	; length


	.word		0		; not used


dqfdesc_a:


	.long		0		; address of dqf block


fibdesc:


	.word		FIB$C_LENGTH	; Fib Descriptor


	.word		0


fibaddr:


	.long		0		; Address of fib block


iosb:	.blkw		4		; I/O status block





dchan:		.word			; Device Channel number


ret_address:	.long			; return code address





	.PSECT io$dsq,EXE,NOWRT


	.entry Read_dsq ^m<>





	movl	4(AP),dqfdesc_a		; Get Uic to find


	movl	8(AP),fibaddr		; Get fib block


	movw	@12(AP),dchan		; Get channel number








SETUP_QUOTA_SEARCH:


	


	$Qiow_s -


                Chan = dchan, -			; Device channel number


                Func = #IO$_ACPCONTROL, -	; QIO operation


                Iosb =  iosb, -			; Status block


                P1 = fibdesc, -			; Fib block descriptor


                P2 = #dqfdesc, -		; Quota block descriptor


                P4 = #dqfdesc			; Quota block descriptor





	movl	iosb,@16(AP)			; Move status to last argument


	ret					; Return to calling routine


	.end





L
"CRDMAIL1
--------
