From:	MERC::"uunet!WKUVX1.BITNET!MacroMan" 18-MAR-1993 00:29:14.09
To:	MACRO32@WKUVX1.BITNET
CC:	
Subj:	Re: Direct modification of SYSUAF

In article <00969A67.CE215B80@buckie.HSC.Colorado.EDU>, dwing@uh01.colorado.edu
 (Dan Wing) writes:
> In article <Stafford-170393154036@stafford.winona.msus.edu>,
> Stafford@Vax2.Winona.MSUS.EDU (John Stafford) writes:
>
>>In article <C41Hs3.IqE@news.iastate.edu>, gvrod@isuvax.iastate.edu (R
>>Eldridge, VMS FOREVER) wrote:
>>>
>>> IMHO, i wouldn't access the sysuaf file directly. we create command
>>> procedures from the program to execute the commands to delete, add, and
>>> modify usernames in the sysuaf. then we spawn the 'submit' command to
>>> execute the command procedure.
>>
>>      but how does one use the unused are of sysuaf?  Isn't there a
>>      large 'user area' which we can use if we can write to the file?
>
> One doesn't!
>
> While you *can* write to SYSUAF.DAT directly, doing so could cause
> corruption of your SYSUAF.DAT.

True.  It is not supported.  I've noticed that DEC has been emphasizing this
a *lot* more lately.  It may be that changes are in the works.  Forewarned is
forearmed.

> If you want to store "extra" information for a user, user the OWNER field
> in SYSUAF.DAT, or have separate, site-maintained file, which contains
> all the extra information.

There is a supported way to access the "user data" area.  Explanation and
sample C code follows.

There is a special "user data" field in the UAF record where you can store
up to 255 bytes of data.  The SUPPORTED way of modifying this field is
through the use of the $SETUAI system service.  The $GETUAI system service
can be used to read the field.  Unprivileged users can read the field but
cannot set it (see the $GETUAI and $SETUAI system service descriptions for
more information on privs required).

An example in VAXC in VMS_SHARE format is attached below after my .sig.

Caveats:

Please note that I have only run this successfully under OpenVMS V5.5-2.
I originally wrote it the last time I was writing something where I wanted
to use this field, and I know for certain that it didn't work then even
though as I recall the version of VMS we were running at the time obstensibly
supported the UAI$_USER_DATA item.  I reported the problem at that time, and
VMS Engineering (bless their little hearts!) has seemed to have fixed it!
So, if it doesn't work on your system, well, upgrade or something.
Please note that this program sets and clears the user data field in the
UAF record for the user you specify, so if you are already using this
field for something, you may not want to run it.
--
James Harvey    IUPUI OIT Technical Support -- VMS/Unix/Networks
harvey@iupui.edu  uucp:iugate!harvey  bitnet:harvey@indyvax

===============================================================================
$! ------------------ CUT HERE -----------------------
$ v='f$verify(f$trnlnm("SHARE_VERIFY"))'
$!
$! This archive created by VMS_SHARE Version 7.2-007  22-FEB-1990
$!   On 17-MAR-1993 22:41:31.05   By user SYSTEM
$!
$! This VMS_SHARE Written by:
$!    Andy Harper, Kings College London UK
$!
$! Acknowledgements to:
$!    James Gray       - Original VMS_SHARE
$!    Michael Bednarek - Original Concept and implementation
$!
$! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER
$! AND EXECUTE AS A COMMAND PROCEDURE  (  @name  )
$!
$! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING:
$!       1. USERDATA.C;15
$!
$set="set"
$set symbol/scope=(nolocal,noglobal)
$f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID"))
$e="write sys$error  ""%UNPACK"", "
$w="write sys$output ""%UNPACK"", "
$ if f$trnlnm("SHARE_LOG") then $ w = "!"
$ ve=f$getsyi("version")
$ if ve-f$extract(0,1,ve) .ges. "4.4" then $ goto START
$ e "-E-OLDVER, Must run at least VMS 4.4"
$ v=f$verify(v)
$ exit 44
$UNPACK: SUBROUTINE ! P1=filename, P2=checksum
$ if f$search(P1) .eqs. "" then $ goto file_absent
$ e "-W-EXISTS, File ''P1' exists. Skipped."
$ delete 'f'*
$ exit
$file_absent:
$ if f$parse(P1) .nes. "" then $ goto dirok
$ dn=f$parse(P1,,,"DIRECTORY")
$ w "-I-CREDIR, Creating directory ''dn'."
$ create/dir 'dn'
$ if $status then $ goto dirok
$ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped."
$ delete 'f'*
$ exit
$dirok:
$ w "-I-PROCESS, Processing file ''P1'."
$ if .not. f$verify() then $ define/user sys$output nl:
$ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1'
PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET(
SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name");b:=
CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(b));
LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION(
BEGINNING_OF(b));g:=0;LOOP EXITIF MARK(NONE)=END_OF(b);x:=ERASE_CHARACTER(1);
IF g=0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x="V" THEN APPEND_LINE;
MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF;IF x="+" THEN g:=1;
ERASE_LINE;ENDIF;ELSE IF x="-" THEN IF INDEX(CURRENT_LINE,"+-+-+-+-+-+-+-+")=
1 THEN g:=0;ENDIF;ENDIF;ERASE_LINE;ENDIF;ENDLOOP;t:="0123456789ABCDEF";
POSITION(BEGINNING_OF(b));LOOP r:=SEARCH("`",FORWARD);EXITIF r=0;POSITION(r);
ERASE(r);x1:=INDEX(t,ERASE_CHARACTER(1))-1;x2:=INDEX(t,ERASE_CHARACTER(1))-1;
COPY_TEXT(ASCII(16*x1+x2));ENDLOOP;WRITE_FILE(b,GET_INFO(COMMAND_LINE,
"output_file"));ENDPROCEDURE;Unpacker;QUIT;
$ delete/nolog 'f'*
$ CHECKSUM 'P1'
$ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT
$ e "-E-CHKSMFAIL, Checksum of ''P1' failed."
$ ENDSUBROUTINE
$START:
$ create 'f'
X/*
X**  USERDATA.C -- Example: Manipulate UAI$_USER_DATA field.
X**
X**  Author: James A. Harvey, IUPUI
X**
X**  Compile and link, run with:
X**
X**`09MCR SYS$DISK:`5B`5DUSERDATA username
X**
X**  Requires privs according to $SETUAI.
X**
X**  This program sets and clears the "user data" field of the UAF record
X**  you specify.  So if you are already using this field, you may not want
X**  to run this.
X*/
X
X#include stdio
X#include descrip
X#include uaidef
X#ifndef UAI$_USER_DATA`09`09/* For elderly uaidef header files */
X#define UAI$_USER_DATA 72
X#endif
X
Xstruct il3$_item `7B
X    unsigned short il3_buflen;  /* Buffer length */
X    unsigned short il3_code;    /* Item code */
X    char           *il3_bufadr; /* Address of first byte of buffer */
X    char           *il3_retadr; /* Address of returned length word */
X`7D;
X
Xmain(
X    int argc,
X    char *argv`5B`5D
X)
X`7B
X    extern int sys$getuai(), sys$setuai();
X    static int status, i, userdata_size;
X    static unsigned char userdata`5B255`5D;
X    static struct dsc$descriptor_s username;
X    static struct il3$_item item_list`5B`5D = `7B
X        `7B sizeof(userdata), UAI$_USER_DATA, userdata, &userdata_size `7D,
X        `7B 0, 0, 0, 0 `7D
X    `7D;
X
X    if (argc != 2 `7C`7C strlen(argv`5B1`5D) == 0) `7B
X`09fprintf(stderr,"userdata: usage: userdata username\n");
X`09exit(1);
X    `7D
X    username.dsc$w_length = strlen(argv`5B1`5D);
X    username.dsc$b_dtype = DSC$K_DTYPE_T;
X    username.dsc$b_class = DSC$K_CLASS_S;
X    username.dsc$a_pointer = argv`5B1`5D;
X
X    printf("reading user data for user %.*s...\n",
X`09`09username.dsc$w_length,username.dsc$a_pointer);
X    status = sys$getuai(0,0,&username,item_list,0,0,0);
X    if (`7Estatus & 1) `7B
X`09fprintf(stderr,"userdata: getuai failed\n");
X`09exit(status);
X    `7D
X
X    printf("userdata_size returned was %d\n", userdata_size);
X    printf("user data in hex:");
X    for (i = 0;  i < userdata_size;  i++)
X`09printf(" %02X",userdata`5Bi`5D);
X    printf("\n");
X
X    strcpy(userdata,"0123456789");
X    item_list`5B0`5D.il3_buflen = strlen(userdata);
X    printf("setting userdata to %s\n",userdata);
X    status = sys$setuai(0,0,&username,item_list,0,0,0);
X    if (`7Estatus & 1) `7B
X`09fprintf(stderr,"userdata: setuai failed\n");
X`09exit(status);
X    `7D
X    printf("OK...  reading it back...\n");
X
X    item_list`5B0`5D.il3_buflen = sizeof(userdata);
X    status = sys$getuai(0,0,&username,item_list,0,0,0);
X    if (`7Estatus & 1) `7B
X`09fprintf(stderr,"userdata: getuai failed\n");
X`09exit(status);
X    `7D
X
X    printf("userdata_size returned was %d\n", userdata_size);
X    printf("user data in hex:");
X    for (i = 0;  i < userdata_size;  i++)
X`09printf(" %02X",userdata`5Bi`5D);
X    printf("\n");
X
X    item_list`5B0`5D.il3_buflen = 0;
X    printf("clearing userdata field...\n",userdata);
X    status = sys$setuai(0,0,&username,item_list,0,0,0);
X    if (`7Estatus & 1) `7B
X`09fprintf(stderr,"userdata: setuai failed\n");
X`09exit(status);
X    `7D
X
X    return;
X`7D
$ CALL UNPACK USERDATA.C;15 341718139
$ v=f$verify(v)
$ EXIT

