js@UW-JUNE.ARPA (Joe Meadows) (09/07/86)
It's been a while since I've posted any sample code, so, heres
a short program I threw together that gets disk quota information, performs
a lookup in the authorization file, and prints out a line showing all the
usefull info. UAF.REC contains a fortran record definition of the authorization
file, DQF.REC contains a record definition of QUOTA.SYS, although I don't
directly read the QUOTA file in this example (I use a QIO function).
I hope this answers a few peoples questions about how to access these
things.. I haven't updated to 4.4 yet, so I don't use the SYS$GETUAI service
in this code, but I plan on upgrading to it so I can provide an example of
it in the future.
Anyway, move to a nice fresh directory and execute the following
procedure if you want to. I call it QUOTA.
Cheers,
Joe Meadows Jr js@uw-june.arpa
$ say := write sys$output
$ say "Creating diskquota.mar"
$ create diskquota.mar
$ deck
.title diskquota
.library 'sys$share:lib'
$iodef
$fibdef
$dqfdef
fib_desc:
.long fib$k_length
.long fib
fib: .blkb fib$k_length
iosb: .quad
chan: .blkw 1
.entry next_quota,^m<r2,r3,r4,r5,r6>
tstw chan
bneq 10$
$assign_s-
devnam=@4(ap),-
chan=chan
blbc r0,20$
10$: movw #fib$c_exa_quota,fib+fib$w_cntrlfunc
movl #fib$m_all_mem!fib$m_all_grp,fib+fib$l_cntrlval
movl @8(ap),fib+fib$l_wcc
$qiow_s func=#io$_acpcontrol,-
iosb=iosb,-
chan=chan,-
p1=fib_desc,-
p2=12(ap),-
p3=16(ap),-
p4=12(ap)
blbc r0,20$
movl iosb,r0
blbc r0,20$
movl fib+fib$l_wcc,@8(ap)
20$: ret
.end
$ eod
$ say "Creating DQF.REC"
$ create dqf.rec
parameter DQF$M_ACTIVE = 1
parameter DQF$K_LENGTH = 32
parameter DQF$C_LENGTH = 32
parameter DQF$S_DQFDEF = 32
structure /dqfdef/
union
map
integer*4 DQF$L_FLAGS
parameter DQF$V_ACTIVE = 0
integer*4 DQF$L_UIC
integer*4 DQF$L_USAGE
integer*4 DQF$L_PERMQUOTA
integer*4 DQF$L_OVERDRAFT
end map
map
character*32 t_full
end map
end union
end structure
$ eod
$ say "Creating UAF.REC
$ create uaf.rec
$ deck
!*** MODULE $UAFDEF ***
! ++
! User authorization file format
! Note: With the exception of the username and account name,
! all strings are blank padded counted strings. Username and
! account name are uncounted, blank padded.
! --
STRUCTURE /UAF/
union
map
character*1412 t_full
end map
map
BYTE B_RTYPE ! UAF record type
BYTE B_VERSION ! UAF format version
INTEGER*2 W_USRDATOFF ! offset of counted string of user data
! username
UNION
MAP
CHARACTER*32 T_USERNAME ! username
END MAP
MAP
CHARACTER*31 %FILL
CHARACTER*1 T_USERNAME_TAG ! tag to differentiate records
END MAP
END UNION
! uic
UNION
MAP
INTEGER*4 L_UIC
END MAP
MAP
INTEGER*2 W_MEM ! member subfield
INTEGER*2 W_GRP ! group subfield
END MAP
END UNION
INTEGER*4 L_SUB_ID ! user sub-identifier
INTEGER*4 Q_PARENT_ID(2) ! identifier of owner of this account
CHARACTER*32 T_ACCOUNT ! account name
CHARACTER*32 T_OWNER ! owner's name
CHARACTER*32 T_DEFDEV ! default device
CHARACTER*64 T_DEFDIR ! default directory
CHARACTER*64 T_LGICMD ! login command file
CHARACTER*32 T_DEFCLI ! default command interpreter
CHARACTER*32 T_CLITABLES ! user CLI tables
! Password
UNION
MAP
INTEGER*4 Q_PWD(2)
END MAP
MAP
INTEGER*4 L_PWD ! 32 bit subfield
END MAP
END UNION
INTEGER*4 Q_PWD2(2) ! second password
INTEGER*2 W_LOGFAILS ! count of login failures
INTEGER*2 W_SALT ! random password salt
BYTE B_ENCRYPT ! encryption algorithm
BYTE B_ENCRYPT2 ! encryption algorithm for 2nd pwd
BYTE B_PWD_LENGTH ! minimum password length
BYTE %FILL
INTEGER*4 Q_EXPIRATION(2) ! expiration date for account
INTEGER*4 Q_PWD_LIFETIME(2) ! password lifetime
INTEGER*4 Q_PWD_DATE(2) ! date of password change
INTEGER*4 Q_PWD2_DATE(2) ! date of 2nd password change
INTEGER*4 Q_LASTLOGIN_I(2) ! date of last interactive login
INTEGER*4 Q_LASTLOGIN_N(2) ! date of last non-interactive login
INTEGER*4 Q_PRIV(2) ! process privilege vector
INTEGER*4 Q_DEF_PRIV(2) ! default process privileges
CHARACTER*20 R_MIN_CLASS ! minimum security class
CHARACTER*20 R_MAX_CLASS ! maximum security class
INTEGER*4 L_FLAGS
c PARAMETER UAF$V_DISCTLY = 0 ! no user control-y
c PARAMETER UAF$V_DEFCLI = 1 ! only allow user default CLI
c PARAMETER UAF$V_LOCKPWD = 2 ! disable SET PASSWORD command
c PARAMETER UAF$V_CAPTIVE = 3 ! captive account (no overrides)
c PARAMETER UAF$V_DISACNT = 4 ! no interactive login
c PARAMETER UAF$V_DISWELCOM = 5 ! skip welcome message
c PARAMETER UAF$V_DISMAIL = 6 ! skip new mail message
c PARAMETER UAF$V_NOMAIL = 7 ! disable mail delivery
c PARAMETER UAF$V_GENPWD = 8 ! passwords must be generated
c PARAMETER UAF$V_PWD_EXPIRED = 9 ! password has expired
c PARAMETER UAF$V_PWD2_EXPIRED = 10 ! 2nd password has expired
c PARAMETER UAF$V_AUDIT = 11 ! audit all actions
c PARAMETER UAF$V_DISREPORT = 12 ! skip last login messages
c PARAMETER UAF$V_DISRECONNECT = 13 ! inhibit reconnections
c PARAMETER UAF$V_AUTOLOGIN = 14 ! auto-login only
BYTE B_NETWORK_ACCESS_P(3) ! hourly network access, primary
BYTE B_NETWORK_ACCESS_S(3) ! hourly network access, secondary
BYTE B_BATCH_ACCESS_P(3) ! hourly batch access, primary
BYTE B_BATCH_ACCESS_S(3) ! hourly batch access, secondary
BYTE B_LOCAL_ACCESS_P(3) ! hourly local access, primary
BYTE B_LOCAL_ACCESS_S(3) ! hourly local access, secondary
BYTE B_DIALUP_ACCESS_P(3) ! hourly dialup access, primary
BYTE B_DIALUP_ACCESS_S(3) ! hourly dialup access, secondary
BYTE B_REMOTE_ACCESS_P(3) ! hourly remote access, primary
BYTE B_REMOTE_ACCESS_S(3) ! hourly remote access, secondary
CHARACTER*12 %FILL
BYTE B_PRIMEDAYS
c PARAMETER UAF$V_MONDAY = 0 ! bit clear means this is a primary day
c PARAMETER UAF$V_TUESDAY = 1 ! bit set means this is an off day
c PARAMETER UAF$V_WEDNESDAY = 2
c PARAMETER UAF$V_THURSDAY = 3
c PARAMETER UAF$V_FRIDAY = 4
c PARAMETER UAF$V_SATURDAY = 5
c PARAMETER UAF$V_SUNDAY = 6
BYTE %FILL
BYTE B_PRI ! base process priority
BYTE B_QUEPRI ! maximum job queuing priority
INTEGER*2 W_MAXJOBS ! maximum jobs for UIC allowed
! 0 means no limit
INTEGER*2 W_MAXACCTJOBS ! maximum jobs for account allowed
! 0 means no limit
INTEGER*2 W_MAXDETACH ! maximum detached processes for UIC
! 0 means no limit
INTEGER*2 W_PRCCNT ! subprocess creation limit
INTEGER*2 W_BIOLM ! buffered I/O limit
INTEGER*2 W_DIOLM ! direct I/O limit
INTEGER*2 W_TQCNT ! timer queue entry limit
INTEGER*2 W_ASTLM ! AST queue limit
INTEGER*2 W_ENQLM ! enqueue limit
INTEGER*2 W_FILLM ! open file limit
INTEGER*2 W_SHRFILLM ! shared file limit
INTEGER*4 L_WSQUOTA ! working set size quota
INTEGER*4 L_DFWSCNT ! default working set size
INTEGER*4 L_WSEXTENT ! working set size limit
INTEGER*4 L_PGFLQUOTA ! page file quota
INTEGER*4 L_CPUTIM ! CPU time quota
INTEGER*4 L_BYTLM ! buffered I/O byte count limit
INTEGER*4 L_PBYTLM ! paged buffer I/O byte count limit
INTEGER*4 L_JTQUOTA ! job-wide logical name table creation quota
INTEGER*2 W_PROXY_LIM ! number of proxies user can grant
INTEGER*2 W_PROXIES ! number of proxies granted
INTEGER*2 W_ACCOUNT_LIM ! number of sub-accounts allowed
INTEGER*2 W_ACCOUNTS ! number of sub-accounts in use
end map
end union
END STRUCTURE
$ eod
$ say "Creating QUOTA.FOR"
$ create quota.for
$ deck
program diskquotas
implicit integer (a-z)
include 'dqf.rec'
include 'uaf.rec'
external ss$_nodiskquota
record /UAF/ uafrec
record /dqfdef/ dqf
character*80 buff,output
integer p1(2)/'020e0000'x,0/
call cli$get_value('p1',p1)
call cli$get_value('output',output)
status = lib$get_lun(uaf_lun)
if (.not.status) call lib$signal(%val(status))
open(unit=uaf_lun,file='sys$system:sysuaf.dat',status='old'
1 ,readonly,shared,access='keyed',form='formatted')
binary=cli$present('binary')
status = lib$get_lun(out_lun)
if (.not.status) call lib$signal(%val(status))
if (binary) then
open(unit=out_lun,file=output,status='new'
1 ,form='unformatted',recordtype='variable')
else
open(unit=out_lun,file=output,status='new')
end if
10 status = next_quota(p1,context,dqf.t_full,buflen)
if (status.eq.%loc(ss$_nodiskquota)) goto 20
if (.not.status) call lib$signal(%val(status))
read(unit=uaf_lun,keyeq=dqf.dqf$l_uic,keyid=1
1 ,fmt='(q,a)',err=15,iostat=ios) length,uafrec.t_full
call str$trim(uafrec.t_username,uafrec.t_username,userlen)
if (dqf.dqf$l_flags) then
call sys$fao('!AS !SL!_!%I!_!AS',length,buff
1 ,uafrec.t_account
2 ,%val(dqf.dqf$l_usage)
3 ,%val(dqf.dqf$l_uic)
4 ,uafrec.t_username(:userlen))
else
15 if (ios.ne.0) then
uafrec.t_account='error'
uafrec.t_username='error'
userlen=5
end if
call sys$fao('!AS !SL!_!%I!_!AS',length,buff
1 ,uafrec.t_account
2 ,%val(dqf.dqf$l_usage)
3 ,%val(dqf.dqf$l_uic)
4 ,uafrec.t_username(:userlen))
end if
if (binary) then
call str$trim(uafrec.t_account,uafrec.t_account,accntlen)
write(out_lun) dqf.dqf$l_uic
1 ,dqf.dqf$l_usage
2 ,uafrec.t_account(:accntlen)
else
write(out_lun,*) buff(:length)
end if
goto 10
20 end
$ eod
$ say "Creating QUOTA.CLD"
$ create quota.cld
$ deck
!*************************************QUOTA*************************************
define verb QUOTA
parameter P1
default
value (default="SYS$DISK",type=$device)
qualifier BINARY
qualifier OUTPUT
default
value (default="SYS$OUTPUT",type=$outfile)
$ eod
$ say "Compiling DISKQUOTA.MAR"
$ macro diskquota
$ say "Compiling QUOTA.FOR
$ fortran quota
$ say "Linking QUOTA,DISKQUOTA"
$ link/notrace quota,diskquota
$ say "Defining QUOTA command"
$ set command quota
$ type sys$input
In the future you will either need to modify QUOTA.CLD
or add a DEFINE QUOTA device:[directory]QUOTA to your
login command procedure.. For now I'll define it for you..
$ define quota 'f$envir("default")'QUOTA
$ say "All done, give it a try by saying QUOTA"