rlb@rtpark.rtp.ge.COM.UUCP (04/09/87)
Re a recent posting concerning new mail message counter: I have in the past modified MAILUAF.COM to show that information and to reset it. Unfortunately I modified it in the SYS$EXAMPLES: directory and a later update of VMS wiped it out -- and I didn't discover it until it was much too late to recover it! (We keep our monthly image mode backups for about 12 months) I haven't tried to go back and do this since the READ/NEW command is adequate for resetting the counter. If on the other hand you're trying to figure out whether someone probably read their mail or not: There are 2 ways to figure out where the field is: 1. Read the fiche for the MAIL utility and look for the values of the symbols related to the field definitions. 2. Make sure that 2 or 3 different users have different mail counts (set up 2 or 3 dummy accounts to guarantee it) dump the records from the VMSMAIL file. Then look at the hex portion to find the counts that you can verify from getting in MAIL in those accounts -- with the SHOW NEW_MAIL command. I wish I could find what I did many months ago -- I had done a lot of neat things with it. Since then I've modified the newer version to do some inter- esting things. I have included the differences of mine with the original supplied in sys$examples: ------------------------------------ cut here -------------------------------- $!Use this command to reconstruct it: $ edit/sum/header/output=my_mailuaf.com - sys$examples:mailuaf.com/update=sys$input: $DECK - 1, 34 $ vfl = f$VERIFY(0+f$TRNLNM("debug$dcl")) $! documentation at the end of this mess $ on control_y then $ goto DONE $ on error then $ goto DONE $ if = "IF" $ null = "" $ at = "@" $ b = " " $ check_set = "#ADD#CANCEL#LIST#MODIFY#REMOVE#SHOW#HELP#EXIT" $ inquire = "INQUIRE" $ user_len = 31 $ user_len_bits = 8*user_len $ addr_max = 255 $ addr_ptr = 68 $ addr_len = 67 $ fnm_len_ptr = 66 $ dir_len_ptr = 65 $ addr_len_bits = addr_len*8 - 43, 95 $ mail_list = 0 $ ask = "inquire/nopunctuation" $ say = "write sys$output" $ prev_priv = f$SETPRV("SYSPRV") $ sysmai = f$PARSE("vmsmail","sys$system:vmsmail.dat") $ line = p1+b+p2+b+p3 $ line=f$EDIT(line,"trim,uncomment,compress") $ once_flag = line.nes.null $ open /share=write /read /write /error=NO_FILE f1 'sysmai' $ if once_flag then $ goto GOT_LINE $FILE_OPEN: $ on control_y then goto DONE - 99, 116 $DO_COMMAND: $ if .not.mail_list then $ goto NEXT_COMMAND $ gosub USER_READ $ if .$status then - $ goto USER_DO $NEXT_COMMAND: $ if once_flag then $ goto DONE $ ask line "MAILUAF> " $GOT_LINE: $ line=f$EDIT(line,"trim,uncomment,compress") $ if line .eqs. null then goto DONE $ t1 = f$LOCATE(b,line) $ command = f$EXTRACT(0,t1,line) $ user = f$EXTRACT(t1+1,user_len,line) $ mail_list = 0 $ check_val = command $ gosub in_set $ if .not.$status then $ goto COMMAND_ERROR $ if check_val.eqs."LIST" then $ goto LIST_USERS $ if check_val.eqs."EXIT" then $ goto DONE $ if check_val.eqs."HELP" then $ goto HELP_USER $ if user .eqs. null then goto SYNTAXERR $ fulluser[0,'user_len']:='user' $ if f$LOC(at,user).eq.0 then $ gosub USER_OPEN $USER_DO: $ goto 'check_val'_USER $COMMAND_ERROR: $ say "MAILUAF-E-INVCOMMND, invalid command: ",command $ goto HELP_USER $ADD_USER: $ read /index=0 /err=ADD_10 /key="''fulluser'" f1 record $ write sys$output "User ",user," record already exists" $ goto DO_COMMAND $ADD_10: $ s1 = f$EDIT(record,"trim,compress") $ if f$LENGTH(s1) .ne. 0 then $ delete/symbol record $ record[0,'user_len']:='user' $ record['user_len_bits',288]=0 $ ask address "Forwarding address? " $ t1 = f$LENGTH(address) $ record['addr_len_bits',8]='t1' $ record['addr_ptr','t1']:='address' $ write f1 record $ write sys$output "User ",user," added" $ goto DO_COMMAND $CANCEL_USER: $ read /index=0 /err=NOSUCHUSER/key="''fulluser'" f1 record $ address = f$EXTRACT(addr_ptr,addr_max,record) $ addr_length = f$CVUI(addr_len*8,8,record) $ address := 'address' $ naddress = f$EXTRACT(0,addr_length,address) $ t2 = f$LENGTH(address) $ t2 = 't2' - 'addr_length' $ if addr_length .eq. 0 then goto SHOW_10 $ write sys$output "User ",user,", forwarding address is ",naddress $ ask yn "Cancel mail forwarding? " $ if .not. yn then goto DO_COMMAND $ record['addr_len_bits',8]=0 $ record['addr_ptr','addr_max'] := "''f$EXTRACT(addr_ptr+addr_length,addr_max-addr_length,record)'" $ record = f$EXTRACT(0,addr_ptr+'t2',record) $ write /update f1 record $ goto DO_COMMAND $LIST_USERS: $ close f1 $ if f$VER() then $ sh sym line $ rem_flag = f$LOC(user,"REMOVE").eq.0 $ comp_flag = rem_flag .or. (f$LOC(user,"NOUSER").eq.0) $ list_fmt = "!''user_len'AS !AS" $ open /share=write /read /write f1 'sysmai' $ sysuaf = f$PARSE("sysuaf","sys$system:sysuaf.dat") $ if comp_flag then $ open/share=write/read f2 'sysuaf' $ write sys$output null $ write sys$output f$FAO(list_fmt,"Username","Forwarding address") $ write sys$output f$FAO(list_fmt,"--------","------------------") $LIST_10: $ read/nolock /end=DO_COMMAND f1 record $ user = f$EXTRACT(0,user_len,record) $ addr_length = f$CVUI(addr_len*8,8,record) $ address = f$EXTRACT(addr_ptr,addr_max,record) $ address = f$EDIT(address,"trim") $ address = f$EXTRACT(0,addr_length,address) $ if .not. comp_flag then $ goto LIST_20 ! see if it is in sysuaf $ trim_user = f$EDIT(user,"trim,compress,upcase") $ read/index=0/key="''trim_user'" f2/error=LIST_15 sysuaf_rec/nolock/time=5 $ goto LIST_10 ! it is so skip this one $LIST_15: $ if (.not.rem_flag) .or. (addr_length.gt.0) then $ goto LIST_20 $ if f$EDIT(address,"trim").nes.null then $ goto LIST_20 $ read /index=0 /err=LIST_10/DELETE /key="''user'" f1 record $ say "Removed ",user $LIST_20: $ write sys$output f$FAO(list_fmt,user,address) $ goto LIST_10 $! $MODIFY_USER: $ read /index=0 /err=NOSUCHUSER /key="''fulluser'" f1 record $ address = f$EXTRACT(addr_ptr,addr_max,record) $ addr_length = f$CVUI(addr_len*8,8,record) $ naddress = f$EXTRACT(0,addr_length,address) $ t2 = f$LENGTH(address) $ if addr_length .ne. 0 then goto XX1 $ write sys$output "User ",user," does not have forwarding enabled" $ goto XX2 $XX1: $ write sys$output "Current forwarding address is ",naddress $XX2: $ ask naddress "New forwarding address? " $ if naddress .eqs. null then goto DO_COMMAND $ address = f$EXTRACT(addr_length,t2-addr_length,address) $ t1 = f$LENGTH(naddress) $ record['addr_len_bits',8]='t1' $ record['addr_ptr','addr_max']:="''naddress'''address'" $ record = f$EXTRACT(0,addr_ptr+t1+t2,record) $ write /update f1 record $ write sys$output "User ",user," modified" $ goto DO_COMMAND $NOSUCHUSER: $ write sys$output "User ",user," record does not exist" $ goto DO_COMMAND $REMOVE_USER: $ read /index=0 /err=NOSUCHUSER/key="''fulluser'" f1 record $ address = f$EXTRACT(addr_ptr,addr_max,record) $ addr_length = f$CVUI(addr_len*8,8,record) $ address := 'address' $ if addr_length .eq. 0 then goto XX0 $ address = f$EXTRACT(0,addr_length,address) $ write sys$output "User ",user,", forwarding address is ",address $ goto XX9 $XX0: $ write sys$output "User ",user," does not have forwarding enabled" $XX9: $ if once_flag then $ goto XX91 $ ask yn "Remove? " $ if .not. yn then goto DO_COMMAND $XX91: $ read /index=0/key="''fulluser'" /delete f1 record $ goto DO_COMMAND $SHOW_USER: $ read /index=0 /err=NOSUCHUSER /key="''fulluser'" f1 record $ address = f$EXTRACT(addr_ptr,addr_max,record) $ addr_length = f$CVUI(addr_len*8,8,record) $ fnmlng=f$CVUI(fnm_len_ptr*8,8,record) $ dirlng=f$CVUI(dir_len_ptr*8,8,record) $ address := 'address' $ full_name := "''f$EXTRACT(addr_ptr+addr_length,fnmlng,record)'" $ dir_spec = f$EXTRACT(addr_length+fnmlng,dirlng,address) $ if dirlng .eq. 0 then goto NO_DIR $ write sys$output "User ",user,", MAIL subdirectory is ",dir_spec $ goto TEST_FULL_NAME $NO_DIR: $ write sys$output "User ",user," did not specify a MAIL subdirectory" $TEST_FULL_NAME: $ if fnmlng .eq. 0 then goto NO_PERS_NAME $ write sys$output "User ",user,", MAIL personal name is ",full_name $ goto CHECK_FORWARD $NO_PERS_NAME: $ write sys$output "User ",user," does not have a MAIL personal name." $CHECK_FORWARD: $ if addr_length .eq. 0 then goto SHOW_10 $ address = f$EXTRACT(0,addr_length,address) $ write sys$output "User ",user,", forwarding address is ",address $ goto DO_COMMAND $SHOW_10: $ write sys$output "User ",user," does not have forwarding enabled" $ goto DO_COMMAND $SYNTAXERR: $ write sys$output "Command syntax error" $ goto DO_COMMAND $DONE: $ if f$TRNLNM("f1","lnm$process").nes.null then $ close f1 $ if f$TRNLNM("f2","lnm$process").nes.null then $ close f2 $ prev_priv = f$SETPRV(prev_priv)+f$VER(vfl) $ exit $ ! $ ! Subroutine section $ ! $USER_OPEN: $ user_file = f$EXTRACT(1,999,user) $ if f$TRNLNM("user_file","lnm$process").eqs.null then - $ open/read/share=read/error=NO_USER_FILE user_file 'user_file' $ mail_list = 1 $USER_READ: $ read/end=USER_END/err=USER_END user_file user $ fulluser[0,'user_len']:= 'user' $ if fulluser.eqs.null then $ goto USER_READ $ return $USER_END: $ mail_list = 0 $ if f$TRNLNM("user_file","lnm$process").nes.null then $ close user_file $ return %X08000004 $IN_SET: ! see if check_val is in check_set $ n = 1 + f$LOCATE("#"+f$EDIT(check_val,"UPCASE,TRIM"), - f$EDIT(check_set,"UPCASE,TRIM") ) $ if n .gt. f$LENGTH(check_set) then $ return %X08040000 $ check_val = f$ELEMENT(0,"#",f$EXTRACT(n,999,check_set)) $ return $ ! $HELP_USER: - 128, 253 $ goto DO_COMMAND $! $NO_FILE: $ write sys$output sysmai," not found...creating new file" $ create /fdl=sys$input 'sysmai' !Create new VMSMAIL.DAT IDENT VMS MAIL Information data file FILE ALLOCATION 10 BEST_TRY_CONTIGUOUS yes BUCKET_SIZE 2 CONTIGUOUS no EXTENSION 10 GLOBAL_BUFFER_COUNT 0 ORGANIZATION indexed OWNER [001,004] PROTECTION (system:RWE, owner:RWE, group:, world:) RECORD BLOCK_SPAN yes CARRIAGE_CONTROL none FORMAT variable SIZE 0 AREA 0 ALLOCATION 10 BEST_TRY_CONTIGUOUS yes BUCKET_SIZE 2 CONTIGUOUS no EXTENSION 10 KEY 0 CHANGES no DATA_KEY_COMPRESSION yes DATA_RECORD_COMPRESSION yes DATA_AREA 0 DATA_FILL 100 DUPLICATES no INDEX_AREA 0 INDEX_COMPRESSION yes INDEX_FILL 100 LEVEL1_INDEX_AREA 0 NULL_KEY no PROLOGUE 3 SEG0_LENGTH 31 SEG0_POSITION 0 TYPE string $ open /share=read /read /write f1 'sysmai' $ goto FILE_OPEN $ !++ $ ! $ ! MAILUAF.COM - Modify SYS$SYSTEM:VMSMAIL.DAT $ ! $ ! $ ! ABSTRACT: Sample command procedure to modify $ ! SYS$SYSTEM:VMSMAIL.DAT $ ! $ ! This command procedure will prompt $ ! the user for a command. The valid $ ! commands are: $ ! $ ! ADD username - Add a new user to SYS$SYSTEM:VMSMAIL.DAT $ ! CANCEL username - Cancel mail forwarding for username $ ! EXIT - Exit from this procedure $ ! HELP - Type help message $ ! MODIFY username - Modify mail forwarding address for username $ ! REMOVE username - Remove username from SYS$SYSTEM:VMSMAIL.DAT $ ! SHOW username - Display mail information about username $ ! LIST - List forwarding addresses for all users $ ! $ ! $ ! REQUIRED PRIVILEGES: $ ! BYPASS $ ! $ ! $ ! IMPLICIT OUTPUT: $ ! SYS$SYSTEM:VMSMAIL.DAT will be created if it does $ ! not exsist. $ ! $ ! $ !-- $!Last Modified: 2-APR-1987 14:57:18.40, By: RLB / $EOD $! make a more interesting MAILCOMPRESS.COM -- allows .dis files for input $! also handles nested .dis files $ edit/sum/header/output=my_mailcompress.com - sys$examples:mailcompress.com/update=sys$input: $DECK - $ old_verify = f$VERIFY(f$TRNLNM("debug$dcl")+0) - 10, 11 - 15, 16 - 33, 33 - 37, 44 $ ! IMPLICIT OUTPUT: $ ! Old default MAIL ISAM file is deleted. $ !-- $ null = "" $ comma = "," $ say = "Write sys$output " - 58, 71 $ total_size = 0 $ total_reclaimed = 0 $ no_compression_needed_size = 40 $ time_stamp = f$CVTIME(null,"COMPARISON","DATETIME") $ set noon $ required_privileges = "BYPASS,EXQUOTA" $ prev_privs = f$SETPRV(required_privileges) $ if .not. f$PRIVILEGE(required_privileges) then goto NO_PRIVILEGES $ def_dev_dir = f$ENVIRONMENT("DEFAULT") $ uaf_file = f$PARSE("sysuaf:","sys$system:sysuaf.dat") $ vmai_file = f$PARSE("vmsmail:","sys$system:vmsmail.dat") $! open /read /share uaf 'uaf_file' $ open /read /share vmai 'vmai_file' $ cmd_file = 0 $ cmd_file_cnt = 0 $ param_flag = 0 $ if f$LENGTH(p1) .eq. 0 then goto GET_USERNAME $ username = p1 $ multi_user'cmd_file_cnt' = f$locate(comma,p1).lt.f$len(p1) - 77, 77 $GET_USERNAME: - 81, 94 $ if multi_user'cmd_file_cnt' then $ goto GET_UNWIND $ if cmd_file then goto 20$ $ if param_flag then goto EXIT_PROCEDURE $ read /end=EXIT_PROCEDURE /prompt="Username: " sys$command username $10$: $ username = f$EDIT(username,"COLLAPSE,UNCOMMENT,UPCASE") $ multi_user'cmd_file_cnt' = f$loc(comma,username).lt.f$len(username) $ if .not.multi_user'cmd_file_cnt' then $ goto NO_UNWIND $ multi_cnt'cmd_file_cnt' = 0 $ user_list'cmd_file_cnt' = username $GET_UNWIND: $ username = f$element(multi_cnt'cmd_file_cnt',comma,user_list'cmd_file_cnt') $ if username.eqs.comma then $ goto GET_UNWIND_FIN $ multi_cnt'cmd_file_cnt' = 1+multi_cnt'cmd_file_cnt' $ if username.eqs.null then $ goto GET_UNWIND $ goto NO_UNWIND $GET_UNWIND_FIN: $ multi_user'cmd_file_cnt' = 0 $ username = null $ goto GET_USERNAME $NO_UNWIND: $ if f$VERIFY().or.old_verify then - $ say cmd_file_cnt,": username = ",username $ if f$LENGTH(username) .eq. 0 then goto GET_USERNAME $ if f$LOC("%",username).lt.f$LENGTH(username) then - $ username = f$EXTRACT(1+f$LOC("%",username),32,username) $ if f$EXTRACT(0,1,username) .nes. "@" then goto 100$ $ cmd_file = 1 $ if f$TYPE(cmd_file_cnt).eqs.null then $ cmd_file_cnt = 0 $ cmd_file_cnt = cmd_file_cnt+1 $ username = f$EXTRACT(1,256,username) $ cmdfile'cmd_file_cnt' = f$PARSE(username,def_dev_dir) $ username = cmdfile'cmd_file_cnt' $ say "Opening file ",username," for list of users to compress" $ open /read /error=CANT_OPEN cmdf'cmd_file_cnt' 'username' $20$: $ read /end=CMD_FILE_EOF /prompt="USERNAME> " cmdf'cmd_file_cnt' username $ username = f$EDIT(username,"COLLAPSE,UNCOMMENT,UPCASE") $ if f$LENGTH(username) .eq. 0 then $ goto 20$ $ goto 10$ - 98, 130 $100$: $ GETUAF == "$util_root:[fermilab]getuaf/uaf=sysuaf:.dat" $ getuaf/device=dev_string/directory=dir_string 'username' $ if .not.$status then $ goto NO_USER $ temp_string = f$EDIT(dir_string,"COLLAPSE") $ dir_len = f$LENGTH(temp_string) $ if temp_string .eqs. null then goto BAD_SPEC $ if f$LOCATE("[",dir_string) .ne. dir_len then goto OKAY_DELIMIT $ dir_close_delimit = ">" $OKAY_DELIMIT: $ dir_string = dir_string - dir_close_delimit $ temp_string = f$EDIT(dev_string,"COLLAPSE") $ dev_len = f$LENGTH(temp_string) $ if temp_string .eqs. null then goto BAD_SPEC $ vmai_record = null $ mail = null $ read /nolock /error=110$ /key="''username'" vmai vmai_record $110$: $ if f$LENGTH(vmai_record) .eq. 0 then goto 120$ $ mail_len = f$CVUI(65*8,8,vmai_record) $ personal_len = f$CVUI(66*8,8,vmai_record) $ forward_len = f$CVUI(67*8,8,vmai_record) $ mail = f$EXTRACT(68+personal_len+forward_len,mail_len,vmai_record) $ if f$LOCATE("[",mail) .ne. mail_len then goto 120$ $ open_delimit = "<" $ close_delimit =">" $120$: $ temp = null $ if mail .nes. null then temp =mail- open_delimit - close_delimit $ mail_dir = dev_string + dir_string + temp + dir_close_delimit $ mail_dir = f$EDIT(mail_dir,"COLLAPSE") $ say null $ say "Processing directory ''mail_dir' for user ''username'" - 135, 138 $ if f$SEARCH("MAIL.MAI") .eqs. null then goto NO_MAIL_FILE $ create_time = f$FILE_ATTRIBUTES("MAIL.MAI","CDT") $ create_time = f$CVTIME(create_time,"COMPARISON","DATETIME") $ if create_time .gts. time_stamp then goto ALREADY_COMPRESSED - 143, 146 $ if (f$FILE_ATTRIBUTES("MAIL.MAI","ORG") .nes. "IDX") .or. - (f$FILE_ATTRIBUTES("MAIL.MAI","NOK") .ne. 2) - then goto NOT_MAIL_FILE $ old_size = f$FILE_ATTRIBUTES("MAIL.MAI", "ALQ") - 150, 152 $ if old_size .lt. no_compression_needed_size then $goto TOO_SMALL $ free_blks = f$GETDVI("SYS$DISK","FREEBLOCKS") $ if free_blks .lt. old_size * 3 then goto NO_SPACE - 157 $ say "Starting Convert for ",username $! if f$VERIFY() then $ goto END_LOOP - 228, 231 $ if $status .ne. 1 then goto CONVERT_ERROR $ new_size = f$FILE_ATTRIBUTES("MAIL.MAI;0", "ALQ") $ tmp = old_size - new_size $ total_size = total_size+new_size $ total_reclaimed = total_reclaimed+tmp $ say "Old size = ''old_size' New size = ''new_size'", - - 235, 236 $END_LOOP: $ goto GET_USERNAME - 240, 246 $EXIT_PROCEDURE: $ say "Mail file space: ",total_size,- " blocks after reclaiming ",total_reclaimed $ if f$TRNLNM("vmai","lnm$process").nes.null then $ close /nolog vmai $EXIT_CLOSE: $ if cmd_file_cnt.le.0 then $ goto EXIT_FINAL $ if f$TRNLNM("cmdf"+f$STRING(cmd_file_cnt),"lnm$process").nes.null then - $ close /nolog cmdf'cmd_file_cnt' $ cmd_file_cnt = cmd_file_cnt - 1 $ goto EXIT_CLOSE $EXIT_FINAL: $ set default 'def_dev_dir' $ prev_privs = f$SETPRV(prev_privs) $ old_verify = f$VERIFY(old_verify) - 251, 288 $NO_PRIVILEGES: $ say "Insufficient privileges" $ say "Requires ",REQUIRED_PRIVILEGES," privileges." $ goto EXIT_PROCEDURE $NO_MAIL_FILE: $ say "No mail file for user ''username'" $ goto GET_USERNAME $NOT_MAIL_FILE: $ say "File ''mail_dir'MAIL.MAI is not a mail file" $ goto GET_USERNAME $CONVERT_ERROR: $ say "Error compressing ''mail_dir'MAIL.MAI ", - "for user ''username'" $ goto GET_USERNAME $CMD_FILE_EOF: $ close cmdf'cmd_file_cnt' $ cmd_file_cnt = cmd_file_cnt -1 $ if cmd_file_cnt.lt.1 then $ cmd_file = 0 $ goto GET_USERNAME $NO_USER: $ say "User ''username' not found in UAF" $ goto GET_USERNAME $BAD_SPEC: $ say "Bad directory specification for user ''username'" $ goto GET_USERNAME $NO_SPACE: $ say "No space to compress file of ''old_size' blocks" $ goto GET_USERNAME $CANT_OPEN: $ say "Can not open file ''username'." $ cmd_file_cnt = cmd_file_cnt -1 $ if cmd_file_cnt.lt.1 then $ cmd_file = 0 $ goto GET_USERNAME $ALREADY_COMPRESSED: $ say "MAIL.MAI already compressed" $ goto GET_USERNAME $TOO_SMALL: $ say "MAIL.MAI too small to compress (''old_size' blocks)." $ goto GET_USERNAME $!Last Modified: 16-FEB-1987 12:18:37.92, By: RLB / $EOD ---------------------------------- cut here -------------------------------- Bob Boyd Usenet: rlb@rtp.ge.com GE Microelectronics Ctr. Voice: (919)549-3627 POB 13049, MS 7T2-04 GE DIALCOMM: 8*274-3627 RTP, NC 27709-3026 GE DECnet: RTPARK::RLB