	Program LilBro
c
c Author:             Mark R. Vevle
c                     X-Ray Crystallographic Core Facility
c                     University of Alabama at Birmingham
c                     244 BHS, THT 79
c                     University Station
c                     Birmingham, Alabama  35294
c                     (205) 934 - 1973/2657
c
c Description:        LilBro - A dynamic, user information, display program.
c
c                     This  program  is  terminal  independent, but can use
c                     special keys on the VT100 and VT200 series terminals.
c                     Keys   can   be   redefined/added  by   modifing  the
c                     Process_Input routine.
c
c Function:           o To  provide  detailed  information  about  users on
c                       the system.
c
c Disclaimer/rights:  This   software  is  in  the  public  domain  and  is
c                     provided  free  though  DECUS or other channels.  The
c                     information  in  this  software  is subject to change
c                     without  notice  and  should  not  be  construed as a
c                     commitment  by the author or his employer. The author
c                     and  his  employer  assumes no responsibility for the
c                     use,  the  correctness,  or  the  reliability of this
c                     software. THIS SOFTWARE IS PROVIDED AS IS.
c
c                     This   software   may   only   be  distributed  on  a
c                     FREE-OF-CHARGE  basis.  Further more,  all references
c                     to  the author must remain intact,  this includes all
c                     references in the documentation and/or in the display.
c
c
c Environment:        VAX/VMS V4.0 or later
c
c Privledges Needed:  ALTPRI, CMKRNL, and WORLD
c
c                     ALTPRI - so  it  can  boost  it's  own  priority (not
c                              required).
c                     CMKRNL - to get the idle times from the UCB's.
c                     WORLD  - so it can do GETJPI's on all processes.
c
c                     Note: CMKRNL  is  required.  If  this  program is run
c                           without CMKRNL privledge it will bomb out.
c
c Modification History (VMS V4.XX):
c
c                     Note: Modifications  made to  RMDEMO under VAX/VMS V3
c                           and V4 can be found at the end of this file.
c
c                     V4.4  - Major revamping  of program to make work under
c                             VMS V4.4.  This reworking  (and resupport)  of
c                             Lil'Brother  is  by  overwhelming  request  of
c                             users  and  expecially  by  McDonnell Douglas.
c                             Renamed RMDemo  to Little Brother  (LILBRO) to
c                             act as a subset of Big Brother (BIGBRO). Major
c                             developement  concerns  will be to keep LILBRO
c                             as CPU UN-intensive as possible.
c
c                             NOTE: Version numbers of LILBRO correspond to
c                                   the version of VMS under which  updates
c                                   have been made.  Downward compatability
c                                   will   try  to  be  maintained  but  no
c                                   guarrenties are implied.
c
c                           - MRV. August 12, 1986
c
c                    V4.4.1 - Incorporate changes and subroutines  submitted
c                             by:
c
c	                            Richard A. Crawford
c                                   E-Systems Inc.
c                                   PO Box 1056    CBN 27
c                                   Greenville, Texas  75401
c
c                             Some  of  the changes  are to turn  on/off the
c                             proper  privileges,  add a  FORTRAN routine to
c                             get the  name of  the queue a batch job is in,
c                             and correct the ACCESS VIOLATION error (LILBRO
c                             must  be rebuilt  using the  supplied  command
c                             procedure, BLD.COM, to correct this problem).
c                             
c                             Also  add a  signal handler  to  prevent users
c                             escaping  this program with  privilges or with
c                             increased priority.
c
c                             MRV - 25-SEP-1986
c

	Include 'MaxUnits.For'						!RAC
	Include 'UsrTbl.For'
	Parameter ( Num_Items = 3 * Max_Units )				!RAC
	Parameter ( Number_Screen = Max_Units + 1 )			!RAC
	Data User_Table / Num_Items * 0 /				!RAC
c
	Include 'Hiber.For'
c
	Include 'Disply.For'
	Data Screen / Number_Screen * ' ' /				!RAC
c
	Include 'JpiStr.For'
	Include 'JpiVal.For'
	Include 'JpiPrm.For'
c
	Include 'SyiVal.For'
	Include 'SyiPrm.For'
	Data GetSyi_Flag / 2 /
c
	Include 'CurPri.For'
	Data My_Current_Priority / 4 /
	Data My_Base_Priority    / 4 /
c
	Include 'Flags.For'
	Data Page_Number / 1 /
	Data Page_Index  / 1 /
c
	Include 'InQio.For'
	Data Input_Flag / 3 /
c
	Integer*4	Ctrl_Status
c
	External	SIGNAL_HANDLER
c
c   Establish a condition handler
c
	Call Lib$Establish ( SIGNAL_HANDLER )
c
c *** Set up QIO for input.
c
	Call Setup_QIO
c
c *** Disable Control_Y
c
	Ctrl_Status = Lib$Disable_Ctrl( '02000000'X )
	If( .not. Ctrl_Status ) Call Lib$Signal( %Val(Ctrl_Status) )
c
c *** Turn On Privledges
c
	Call Modify_Priv ( .True. )				!RAC / MRV
c
c *** Boost my priority by 2
c
	Call Modify_Priority_By( 2 )
c
c *** Schedual wakeups in 3 second intervals to begin with.
c
	Sleeping = .True.
	Sleep_Time = 3
	Call Modify_Sleep
	Sleeping = .False.
c
c *** Setup the GETJPI request (a onetime call)
c
	Call Setup_Getjpi
c
c *** Get System information
c
	Call Get_System_Info
c
c *** Go into the display loop
c
	User_Flag = .True.
c
	Call Display_Loop
c
c *** All Finished
c
	Call Modify_Priority_By( -( My_Current_Priority - My_Base_Priority ) )
c
	Ctrl_Status = Lib$Enable_Ctrl( '02100000'X )
	If ( .not. Ctrl_Status ) Call Lib$Signal( %Val(Ctrl_Status) )
c
	End



	Subroutine Setup_Qio
c
	Include '($IODef)'
	Include '($SSDEF)'
	Include 'InQio.For'
c
	Integer*4	IAssign_Stat,	Sys$Assign,	Sys$Qio
	Integer*4	Ctrly_Code,	Ctrlc_Code,	Qio_Stat
	Integer		IDay
c
c *** Declare the AST routine
c
	External	Rmd_Ctrl_Exit
c
D	Call Lib$Day( IDay )
D	If ( IDay .gt. 'B680'X ) Call Lib$Signal(%Val(SS$_MCheck),
D	1				 %Val(iday), %Val('B680'X) )
c
c *** Get a channel to the terminal
c
	Iassign_Stat = Sys$Assign( 'TT', tt_channel, , )
	If ( .not. Iassign_Stat ) Call Lib$Signal ( %Val(IAssign_Stat) )
c
c *** Setup the QIO function codes
c
	Input_Code = jior( IO$_Readlblk, jior( IO$M_NoEcho,
	1				 jior( IO$M_Cvtlow,
	1				 jior( IO$M_Escape,
	1				 jior( IO$M_TrmNoEcho,
	1				       IO$M_NoFiltr ) ) ) ) )
	ctrly_code = jior( IO$_SetMode, IO$M_CtrlyAst )
	ctrlc_code = jior( IO$_SetMode, IO$M_CtrlcAst )
c
c *** Specify Ast routines for Control_Y and Control_C
c
	Qio_Stat = Sys$Qio( , %val( tt_channel ), %val( ctrly_code ),
	1		    , , , rmd_ctrl_exit, , , , , )
	Qio_Stat = Sys$Qio( , %val( tt_channel ), %val( ctrlc_code ),
	1		    , , , rmd_ctrl_exit, , , , , )
c
c *** Issue first (async) read 
c
	Call Get_Input
c
	Return
	End



	Subroutine Get_Queue_Name ( PID, Queue, Queue_Length )
c
c	This is a replacement to QueName.Mar.  It uses the GetQui system
c	service to find out the queue information. It is an adaptation
c	of an example program given in the VMS System Service manual under
c	the description of the GetQui routine.
c
c	Written by : Richard A. Crawford
c		     E-Systems Inc.
c		     PO Box 1056    CBN 27
c		     Greenville, Texas  75401
c

	! Declare entry parameters
	Integer*4    PID
	Character*31 Queue
	Integer*4    Queue_Length

	! Declare system service symbols
	Integer*4	SYS$GetQuiW, Status_Q, Status_J
	Include		'($QUIDEF)'

	! Declare item list structure
	Structure	/ITMLST/
	  Union
	    Map
	      Integer*2 Buflen, Itmcod
	      Integer*4 Bufadr, Retadr
	    End Map
	    Map
	      Integer*4 End_List
	    End Map
	  End Union
	End Structure

	! Define I/O status block structure
	Structure	/IOSBLK/
	Integer*4	STS, Zeroed
	End Structure

	! Declare $GetQuiW item lists and I/O status block
	Record /ITMLST/ Queue_List(4)
	Record /ITMLST/ Job_List(3)
	Record /IOSBLK/ IOSB

	!Declare variables used in $GetQuiW item lists
	Character*31	Search_Name
	Character*31	Queue_Name
	Integer*2	Search_Name_Len,
	2		Queue_Name_Len
	Integer*4	Search_Flags,
	2		Job_PID

	! Set queue name to search to a wildcard
	Search_Name     = '*'
	Search_Name_Len = 1

	! Initialize item list for the display queue operation
	Queue_List(1).Buflen   = Search_Name_Len
	Queue_List(1).Itmcod   = QUI$_Search_Name
	Queue_List(1).Bufadr   = %Loc(Search_Name)
	Queue_List(1).Retadr   = 0
	Queue_List(2).Buflen   = 4
	Queue_List(2).Itmcod   = QUI$_Search_Flags
	Queue_List(2).Bufadr   = %Loc(Search_Flags)
	Queue_List(2).Retadr   = 0
	Queue_List(3).Buflen   = 31
	Queue_List(3).Itmcod   = QUI$_Queue_Name
	Queue_List(3).Bufadr   = %Loc(Queue_Name)
	Queue_List(3).Retadr   = %Loc(Queue_Name_Len)
	Queue_List(4).End_List = 0

	! Initialize item list for the display job operation
	Job_List(1).Buflen   = 4
	Job_List(1).Itmcod   = QUI$_Search_Flags
	Job_List(1).Bufadr   = %Loc(Search_Flags)
	Job_List(1).Retadr   = 0
	Job_List(2).Buflen   = 4
	Job_List(2).Itmcod   = QUI$_Job_PID
	Job_List(2).Bufadr   = %Loc(Job_PID)
	Job_List(2).Retadr   = 0
	Job_List(3).End_List = 0

	! Request search of all jobs present in the output queues
	Search_Flags = ( QUI$M_Search_Wildcard .or.
	2		 QUI$M_Search_Batch .or.
	2		 QUI$M_Search_All_Jobs )

	! Disolve any internal search context block for the process
	Status_Q = SYS$GetQuiW ( , %Val ( QUI$_Cancel_Operation ) ,,,,, )

	! Locate next output queue; loop until error status is returned
	Do While ( Status_Q )
	    Status_Q = SYS$GetQuiW ( , %Val ( QUI$_Display_Queue ) , ,
	2			       Queue_List, Iosb, , )
	    If (Status_Q) Status_Q = Iosb.Sts
	    Status_J = 1

	    ! Get information on next job in queue; loop until error return
	    Do While ( Status_Q .and. Status_J )
		Status_J = SYS$GetQuiW ( , %Val ( Qui$_Display_Job ) , ,
	2				   Job_List, Iosb, , )
		If (Status_J) Status_J = Iosb.Sts
		If (Status_J) then
		    If ( Job_PID .eq. PID ) then
			Queue        = Queue_Name
			Queue_Length = Queue_Name_Len
			Return
		    End If
		End if
	    End Do
	End Do

	Return

	End



	Subroutine Modify_Priv ( Turn_On )
c
c	This subroutine will enable the proper privileges for execution
c	of this program.  If it is unsuccessful in enabling the privileges
c	then it assumes the user isn't privileged enough to run this program.
c	If the privileges are set upon entry to the program, no change will
c	occur.  In any case, the privileges will be set back to their initial
c	vaules.
c
c	Written by : Richard A. Crawford
c		     E-Systems Inc.
c		     PO Box 1056    CBN 27
c		     Greenville, Texas  75401
c
c	Modified for LILBRO by: Mark R. Vevle
c
	Integer*4	Turn_On					! MRV
c
	Include '($SSdef)'
	Include '($PrvDef)'
c
	Byte		Enable,			NotPerm
	Byte		NewPriv_Byte(8),	OldPriv_Byte(8)
c
	Integer*4	Set_Status,		NewPriv
	Integer*4	OldPriv,		Sys$SetPrv
c
	Equivalence ( NewPriv, NewPriv_Byte )
	Equivalence ( OldPriv, OldPriv_Byte )
c
c	Disable / Enable some new privileges
c
	If ( %Loc(Turn_On) .eq. 0 ) Then		! MRV
	    Enable = 1
	Else If ( Turn_On ) Then
	    Enable = 1
	Else
	    Enable = 0
	End If
c
c	These privileges are to be set only during the execution of this
c	program. Note: If they are set before entering the program, they
c	will still be set upon exit.
c
	NotPerm = 0
c
c	Set up the new privilege mask.  Enable ALTPRI, CMKRNL, and WORLD
c	privileges.
c
	NewPriv = 0
	NewPriv = IOr ( NewPriv , Prv$M_SetPri )
	NewPriv = IOr ( NewPriv , Prv$M_Cmkrnl )
 	NewPriv = IOr ( NewPriv , Prv$M_World )
c
c	Enable the new privileges
c
	Set_Status = Sys$SetPrv ( %val ( Enable ) ,
	1			  %ref ( NewPriv_Byte ) ,
	2			  %val ( NotPerm ) ,
	3			  %ref ( OldPriv_Byte ) )
c
c	If we weren't able to alter our privilege mask then we shouldn't
c	be trying to run this program!
c
	If ( Set_Status .ne. SS$_Normal )
	1	Call Lib$Signal( %Val(Set_Status) )
c
	Return
	End



	Subroutine Rmd_Ctrl_Exit
c
	Include 'CurPri.For'
c
	Character*1	Esc
c
	Integer*4	Ctrl_Status,	Lib$Enable_Ctrl
c
c *** Restore Cursor
c
	Esc = Char( 27 )
	Call Lib$Put_Screen( Esc // '[?25h', 1, 1 )
	Call Lib$Erase_Page( 1, 1 )
c
	Call Modify_Priority_By( -( My_Current_Priority - My_Base_Priority ) )
c
	Call Modify_Priv ( .False. )				!RAC / MRV
c
	Ctrl_Status = Lib$Enable_Ctrl( '02100000'X )
	If ( .not. Ctrl_Status ) Call Lib$Signal( %Val(Ctrl_Status) )
c
	Stop ' '
	End



	Subroutine Get_Input
c
	Include 'InQio.For'
c
	Integer*4	Qio_Stat,	Sys$Qio
	Integer*4	Term_Mask( 8 ),	Long_Mask( 2 )
c
	Integer*2	Short_Mask( 4 )
c
	Equivalence	( Short_Mask,	Long_Mask )
c
c *** Declare AST routine to handle input
c
	External	Process_Input
c
	Short_Mask( 1 ) = 16
	Short_Mask( 2 ) = 16
	Long_Mask( 2 ) = %Loc( Term_Mask )
c
	Do I = 1, 8
	    Term_Mask(I) = 'FFFFFFFF'X
	End Do
c
	Qio_Stat = Sys$Qio( %val( input_flag ), %val( tt_channel ),
	1		    %val( input_code ), input_iosb,
	1		    process_input, , input_buffer,
	1		    %val( 20 ), , Long_Mask, , )
c
	Return
	End



	Subroutine Process_Input
c
	Include 'MaxUnits.For'						!RAC
	Parameter ( Max_Page = ( Max_Units / 19 ) + 1 )			!RAC
c
	Integer*4	input_code,	input_flag
	Integer*2	tt_channel,	Input_Iosb( 4 )
	Logical*1	input_buffer( 20 )
c
	Common /InQio/	input_code,	input_flag,	input_iosb,
	1		tt_channel,	input_buffer
c
	Include 'Flags.For'
	Include 'Hiber.For'
c
	Character*20	Command_Line
	Character*1	Esc / 27 /
c
	Integer*2	Terminator
c
	Equivalence(	Command_Line,	Input_Buffer	)
c
	Terminator = Input_Iosb( 3 )
c
	If ( Exit_Flag ) Return
c
	If ( ( Terminator .eq. 5 ) .or. ( Terminator .eq. 26 ) .or.
	1    ( Terminator .eq. 69) .or. ( Terminator .eq. 101) ) then
	    Exit_Flag = .True.
	    Sleep_Time = 1
	    Sleeping = .True.
	    Call Modify_Sleep
	    Return
	Else If ( terminator .eq. 1 ) then
	    display_all_flag = .not. display_all_flag
	Else If ( ( ( terminator .eq. 21 ) .and. 
	1	    ( process_flag ) ) .or.
	1	  ( terminator .eq. 16 ) ) then
	    process_flag = .not. process_flag
	Else If ( ( terminator .eq. 21 ) .or.
	1	  ( index( command_line, esc // '[4~' ) .ne. 0 ) ) then
	    user_flag = .not. user_flag
	    process_flag = .false.
	Else If ( terminator .eq. 23 ) then
	    redraw_flag = .true.
	Else If ( ( terminator .eq. 31 ) .or.
	1	( index( command_line, esc // 'OQ' ) .ne. 0 ) .or.
	1	( index( command_line, esc // '[28~' ) .ne. 0 ) ) then
	    help_flag = .true.
	Else If ( index( command_line, esc // '[A' ) .ne. 0 ) then
	    call modify_priority_by( 1 )
	Else If ( index( command_line, esc // '[B' ) .ne. 0 ) then
	    call modify_priority_by( -1 )
	Else If ( index( command_line, esc // '[C' ) .ne. 0 ) then
	    sleep_time = sleep_time + 1
	    Call Modify_Sleep
	Else If ( index( command_line, esc // '[D' ) .ne. 0 ) then
	    sleep_time = sleep_time - 1
	    Call Modify_Sleep
	Else If ( index( command_line, esc // '[2~' ) .ne. 0 ) then
	    display_all_flag = .true.
	Else If ( index( command_line, esc // '[3~' ) .ne. 0 ) then
	    display_all_flag = .false.
	Else If ( ( terminator .eq. 14 ) .or.
	1	  ( index( command_line, esc // '[6~' ) .ne. 0 ) ) then
	    If ( page_number .lt. Max_Page ) then			!RAC
		page_number = page_number + 1
		page_index =  19 * ( page_number - 1 ) + 1
	    Else
		page_number = 1
		page_index = 1
	    End If
	Else If ( ( terminator .eq. 2 ) .or.
	1	  ( index( command_line, esc // '[5~' ) .ne. 0 ) ) then
	    If ( page_number .gt. 1 ) then
		page_number = page_number - 1
		page_index = 19 * ( page_number - 1 ) + 1
	    Else
		page_number = Max_Page
		page_index = ( ( Max_Page - 1 ) * 19 ) + 1		!RAC
	    End If
	Else
	    unknown_flag = .true.
	End If
c
	call get_input
c
	Return
	End



	Subroutine Modify_Sleep
c
	Include 'Hiber.For'
	Include 'Flags.For'
c
	Integer*4	binary_time( 2 ),	Sys$BinTim,	Sys$SchdWk
	Integer*4	bin_stat,	wakeup_stat,	Sys$CanWak
c
	Character*16	delta_time
	Character*2	sleep
c
10	format('0000 00:00:',i2,'.00')
20	format( i2 )
c
c	*** Set up continous wakeups in delta_time intervals
c
	If ( sleep_time .gt. 59 ) then
	    sleep_time = 1
	Else If ( sleep_time .lt. 1 ) then
	    sleep_time = 59
	End If
c
	Write ( delta_time, 10, iostat=ios ) sleep_time
c	
	ican_stat = Sys$CanWak( , )
	bin_stat = Sys$BinTim( delta_time, binary_time )
	wakeup_stat = Sys$SchdWk( , , binary_time, binary_time )
	If ( .not. Wakeup_Stat ) Call Lib$Signal ( %Val(Wakeup_Stat) )
c
	If ( ( .not. Exit_Flag ) .and. ( .not. Sleeping ) ) Then
	    write( sleep, 20, iostat=ios ) sleep_time
	    Call Lib$Put_Screen( sleep, 3, 17 )
	    Call Lib$Set_Cursor ( 24, 1 )
	End If
c
	Return
	End

	Subroutine Display_Loop
c
	Include 'MaxUnits.For'						!RAC
	Include 'JpiStr.For'
	Include 'JpiVal.For'
	Include 'JpiPrm.For'
	Include 'Hiber.For'
	Include 'Disply.For'
	Include 'SyiVal.For'
	Include 'Flags.For'
	Include 'UsrTbl.For'
	Include 'Idle.For'
	Include 'Params.For'
c
	Character*80	Stat_Line
	Character*23	current_date_time
	Character*9	day_of_week
	Character*1	esc / 27 /,	cr / 13 /,	lf / 10 /
	Character*1	null / 0 /
c
	Integer*4	Lib$Put_Screen,	Output_Status,	column
	Integer*4	Lib$Set_Scroll,	Lib$Erase_Page, Sys$Hiber
	Integer*4	Total_Processes,	TT_UCB
c
10	Format ( 6x, I2, ' Sec', 3x,
	1	 4x, I3, 5x,
	1	 3x, I2, 3x,
	1	 2x, I3, '%', 3x,
	1	 3x, I3, '%', 4x,
	1	 3x, I4.1, ' ', I2.2, ':', I2.2 )
c
	Do While ( .not. exit_flag )
c
	    Call Lib$Date_Time( current_date_time )
	    Call get_weekday( day_of_week, 0, len )
c
	    column = 49 + len
c
	    Call Lib$Erase_Page( 1, 1 )
	    Call Lib$Put_Screen( esc // '[?25l', 1, 1 )
	    Call Lib$Put_Screen( system_type //
	1		', VMS ' // system_version( : 4 ) // '. ', 1, 1 )
	    Call Lib$Put_Screen ( ' Lil'' Brother V4.4.1 ', 1, 24, 3 )

	    Call Lib$Put_Screen ( day_of_week( :len ) // ', ' //
	1		current_date_time // cr // lf, 1, 47 )
	    Call Lib$Put_Screen (	'   Up Time   ' //
	1				'  Interval  ' //
	1				'  Proc Cnt  ' //
	1				'  Page   Avg Idle ' //
	1				' Cur Idle     Total Idle ' //
	1				cr // lf, 2, 1, 2 )
	    Call Lib$Put_Screen( 'Process_Name ' //
	1				'Image    ' //
	1				'Terminal ' // 
	1				'Prior ' //
	1				'State ' //
	1				'Log ' //
	1				'Fl ' //
	1				'Size ' //
	1				'Pg_Flt ' //
	1				'Cpu_Time ' //
	1				'%Cpu ' //
	1				'Idle' // cr // lf, 4, 1, 2 )
c
	    Call Lib$Set_Scroll( 5, 24 )
c
	    redraw_flag = .false.
	    Stat_Line( 1: 1 ) = ' '
c
	    Do While ( ( .not. exit_flag ) .and. ( .not. redraw_flag ) )
c
		Call Get_Users ( Total_Processes, ICount )
c
c		*** Call a kernel mode routine which makes a table of
c		    idle times and PIDs for allocated terminals
c
		IStatus = TT_UCB( Idle_Table, Pid_Table, Device_Table,
	1			  Unit_Table, , Max_Units )
c
		Call Get_Up_Time( Stat_Line( : 10 ), IAvg_Idle )
c
		Write ( Stat_Line( 11: ), 10, iostat=ios )
	1				sleep_time,	total_processes,
	1				Page_Number,	IAvg_Idle,
	1				Percent_Idle,	Idle_Day,
	1				Idle_Hou,	Idle_Min
c
		Call Lib$Date_Time( current_date_time )
c
		Call Lib$Put_Screen (	current_date_time 
	1				// cr	// lf, 1, column )
		Call Lib$Put_Screen ( Stat_Line // cr // lf, 3, 1 )
c
		j = 5
		i = page_index
c
		Do While ( ( j .lt. 24 ) .and. ( i .le. icount ) )
		    Call Get_Idle ( Screen( i )( Term_B: Term_E),
	1			    Screen( i )( Idle_B: Idle_E ), i )
		    Call Lib$Put_Screen( screen(i) // cr // lf, j, 1 )
		    i = i + 1
		    j = j + 1
		End Do
c
		Call Lib$Erase_Page( j, 1 )
c
		If ( icount .ge. i )
	1	    output_status = Lib$Put_Screen( ' More ' // cr, 24, 37, 6 )
c
		If ( help_flag ) then
		    Call Help( j )
		    Help_Flag = .false.
		    Unknown_Flag = .false.
		Else If ( unknown_flag ) then
		    Call Alert( j )
		    Unknown_Flag = .false.
		End If
c
c *** wait for a wakeup call
c
		Call Lib$Set_Cursor ( 24, 1 )
		IRest_Stat = Sys$Hiber()
	    End Do
	End Do
c
c *** restore cursor
c
	output_status = Lib$Put_Screen( esc // '[?25h', j, 1 )
	output_status = Lib$Erase_Page( j, 1 )
c
	return
	end



	Subroutine Get_Idle( Terminal, Idle, Index)
c
c  Call a kernel mode routine which makes a table of idle times
c  for allocated terminals
c
	Integer*4	Index
	Character	Terminal*(*)
	Character	Idle*(*)
c
	Include 'MaxUnits.For'						!RAC
	Include 'Usrtbl.For'
c
	Integer*4	I_Idle,		I_hr,	I_min
	Integer*4	I_Device( 4 ),	PID,	Found
	Integer*4	Idle_Len
c
	Byte		B_Device( 16 ),	B_Device_Len
c
	Character*15	C_Device
c
	Equivalence	(	I_Device,	B_Device )	
	Equivalence	(	B_Device( 1 ),	B_Device_Len )
	Equivalence	(	B_Device( 2 ),	C_Device )
c
	Pid = User_Index( Index )
	ii = 1
	Found = .False.
	Idle_Len = Len( Idle )
c
	Do While ( ( Pid_Table( ii ) .ne. 0 ) .and. ( .not. Found ) )
	    If ( PID .eq. Pid_table( ii ) ) Then
		I_Idle = Idle_table( ii )
		If ( Terminal( 1: 2 ) .eq. 'VT' ) Then
		    I_Device( 1 ) = Device_Table( 1, ii )
		    I_Device( 2 ) = Device_Table( 2, ii )
		    I_Device( 3 ) = Device_Table( 3, ii )
		    I_Device( 4 ) = Device_Table( 4, ii )
		    Terminal = C_Device( : B_Device_Len )
c
		    If ( Unit_Table( ii ) .eq. 0 ) Then
			n = 1
		    Else
			n = Log10 ( Float ( Unit_Table( ii ) ) + 0.5 ) + 1
		    End If
c
		    Write ( Terminal(	B_Device_Len + 1:
	1				B_Device_Len + 1 + n ),
	1				1010, IoStat=Ios ) Unit_Table( ii )
		End If
c
		Found = .True.
c
	    Else
		ii = ii + 1
	    End if
c
	End do
c
	If ( ( .not. Found ) .or. ( I_Idle .le. 0 ) ) Then
	    Idle = '    '
	    If ( Terminal( 1: 2 ) .eq. 'VT' ) Terminal = '<discon> '
	Else
	    I_Min = I_Idle / 60
	    I_Hr = I_Min / 60
	    I_Min = I_Min - ( 60 * I_Hr )
	    If ( I_Hr .le. 0 ) Then
		If ( I_Min .le. 0 ) Then
		    Idle = '   .'
		Else
		    Write ( Idle, 1000, IoStat=Ios ) I_Min
		End If
	    Else If (I_Hr .lt. 10) Then
	        Write ( Idle, 1001, IoStat=Ios ) I_Hr, I_Min
	    Else If (I_Hr .lt. 100) Then
	        I_Min = (I_Min * 100) / 600
	        Write ( Idle, 1002, IoStat=Ios ) I_Hr, I_Min
	    Else
	        Write ( Idle, 1003, IoStat=Ios ) I_Hr
	    End if
	End If
	Return
c
1000	Format( '  ',I2 )
1001	Format( I1, ':', I2 )
1002	Format( I2, '.', I1 )
1003	Format( I3, '.' )
1010	Format( I<n>, ':' )
c
	End




	Subroutine Get_Up_Time( Up_Time, Avg_Idle )
c
	Include 'SyiVal.For'
	Include	'Idle.For'
c
	Character	Up_Time*(*)
c
	Integer*4	Avg_Idle,		Remainder
	Integer*4	Current_Time( 2 ),	Result( 2 )
c
c *** Calculte the amount of uptime
c
	Call Sys$GetTim ( Current_Time )
	Call Lib$Subx ( Sys_Boot_Time, Current_Time, Result )
	Call Sys$AscTim ( , Up_Time, Result, 0 )
c
c *** Calculte the average idle time
c
	Call Lib$EDIV ( 10000000, Result, Avg_Idle, Remainder )
	If (Avg_Idle .eq. 0) Then
	    Avg_Idle = 100
	Else
	    Avg_Idle = -((Float(NULL_CPU_Time) / Float(Avg_Idle)) + .5)
	End If
c
	Return
	End



	Subroutine Help( start )
c
	character*5	sp / '     ' /
	character*1	cr / 13 /,	lf / 10 /
c
	Integer*4	Start
c
	Call Lib$Erase_Page( 5, 1 )
	Call Lib$Put_Screen( ' Lil'' Brother Help ', 5, 30, 3 )
	Call Lib$Put_Screen( ' ^A ',  7, 3, 2 )
	Call Lib$Put_Screen( '  Switch for adding/removing' //
	1		     ' system processes to the display.', 7, 8 )
	Call Lib$Put_Screen( ' or ',  8, 3, 2 )
	Call Lib$Put_Screen( '  use Insert and Remove ( VT220 only ).', 8, 8 )
	Call Lib$Put_Screen( ' ^B ',  9, 3, 2 )
	Call Lib$Put_Screen( '  Previous screen', 9, 8 )
	Call Lib$Put_Screen( ' or ', 10, 3, 2 )
	Call Lib$Put_Screen( '  use Prev_Screen Key ( VT220 only ).', 10, 8)
	Call Lib$Put_Screen( ' ^E ', 11, 3, 2 )
	Call Lib$Put_Screen( '  Exit.', 11, 8 )
	Call Lib$Put_Screen( ' ^N ', 12, 3, 2 )
	Call Lib$Put_Screen( '  Next Screen', 12, 8 )
	Call Lib$Put_Screen( ' or ', 13, 3, 2 )
	Call Lib$Put_Screen( '  use Next_Screen Key ( VT220 only ).', 13, 8)
	Call Lib$Put_Screen( ' ^P ', 14, 3, 2 )
	Call Lib$Put_Screen( '  Switch for showing/removing PIDs.', 14, 8)
	Call Lib$Put_Screen( ' ^U ', 15, 3, 2 )
	Call Lib$Put_Screen( '  Switch from username to process' //
	1		     ' name and back.', 15, 8)
	Call Lib$Put_Screen( ' or ', 16, 3, 2 )
	Call Lib$Put_Screen( '  use the SELECT key ( VT220 only ).', 16, 8)
	Call Lib$Put_Screen( ' ^W ', 17, 3, 2 )
	Call Lib$Put_Screen( '  Redraw entire screen.', 17, 8)
	Call Lib$Put_Screen( ' ^Z ', 18, 3, 2 )
	Call Lib$Put_Screen( '  Exit.', 18, 8)
	Call Lib$Put_Screen( ' ^? ', 19, 3, 2 )
	Call Lib$Put_Screen( '  Help or use a keyboard HELP key.', 19, 8)
	Call Lib$Put_Screen( ' Up Arrow ', 21, 5, 2 )
	Call Lib$Put_Screen( '  Increase your base priority.', 21, 14)
	Call Lib$Put_Screen( ' Dn Arrow ', 22, 5, 2 )
	Call Lib$Put_Screen( '  Decrease your base priority.', 22, 14)
	Call Lib$Put_Screen( ' Rg Arrow ', 23, 5, 2 )
	Call Lib$Put_Screen( '  Increase time between screen updates.'
	1			, 23, 14)
	Call Lib$Put_Screen( ' Lf Arrow ', 24, 5, 2 )
	Call Lib$Put_Screen( '  Decrease time between screen updates.'
	1			, 24, 14)
	Call Lib$Put_Screen( '                         ', 16, 55, 2 )
	Call Lib$Put_Screen( ' Author: Mark R. Vevle   ', 17, 55, 2 )
	Call Lib$Put_Screen( '                         ', 18, 55, 2 )
	Call Lib$Put_Screen( ' University of Alabama   ', 19, 55, 2 )
	Call Lib$Put_Screen( ' 244 BHS, THT 79         ', 20, 55, 2 )
	Call Lib$Put_Screen( ' University Station      ', 21, 55, 2 )
	Call Lib$Put_Screen( ' Birmingham, AL  35294   ', 22, 55, 2 )
	Call Lib$Put_Screen( ' (205) 934-1973 / 2657   ', 23, 55, 2 )
	Call Lib$Put_Screen( '                         ', 24, 55, 2 )
c
	Call Sys$Hiber()
c
	Return
	End



	Subroutine alert ( start )
c
	integer*4	start,	out_stat,	Sys$Hiber
c
	i = start
c
	out_stat = Lib$Put_Screen( 
	1	' -- Type ^? or any keyboard HELP key for Help -- ',
	1	i, 15, 6 )
c
	out_stat = Sys$Hiber()
c
	Return
	End



	Subroutine NULL_Process ( Jpi_Status )
c
	Include 'MaxUnits.For'						!RAC
	Include 'UsrTbl.For'
	Include 'Disply.For'
	Include 'JpiVal.For'
	Include 'JpiPrm.For'
	Include 'Idle.For'
c
	Integer*4	Jpi_Status,	User_Count,	Sys$WaitFr
	Integer*4	Sys$GetJpi,	Total_Processes
c
c	*** Wait for the Getjpi request to complete
c
	If ( Jpi_Status ) IWait_Stat = Sys$WaitFr( %Val( GetJpi_Flag ) )
c
c	*** Calculate amount of CPU time used
c
	Call Cpu_Usage ( 0 )
c
c	*** Calculate the amount of accumulated idle time
c
	NULL_CPU_Time = Cpu_Time
c
	Idle_Sec = Cpu_Time / 100
	Idle_Min = Idle_Sec / 60
	Idle_Sec = Idle_Sec - ( 60 * Idle_Min )
	Idle_Hou = Idle_Min / 60.0
	Idle_Min = Idle_Min - ( 60 * Idle_Hou )
	Idle_Day = Idle_Hou / 24
	Idle_Hou = Idle_Hou - ( 24 * Idle_Day )
c
c	*** Get the next process (The SWAPPER process)
c
	Jpi_status = Sys$Getjpi( %Val( GetJpi_Flag ), Pid, ,
	1			     GetJpi_List, Io_Status, , )

	Return
	End


	Subroutine get_users( total_processes, user_count )
c
c *** include system return codes
c
	include '($ssdef)'
c
	Include 'MaxUnits.For'						!RAC
	Include 'UsrTbl.For'
	Include 'Disply.For'
c
	Include 'JpiStr.For'
	Include 'JpiVal.For'
	Include 'JpiPrm.For'
c
	Include 'Flags.For'
c
	character*4	idle_time
c
	integer*4	jpi_status,	user_count,	sys$waitfr
	integer*4	Sys$Getjpi,	total_processes
c
10	format( i3,'%' )
c
	total_processes = 0
	pid = -1
	user_count = 0
c
c *** Get the first process (the NULL process)
c
	jpi_status = Sys$Getjpi( %val( getjpi_flag ), pid, ,
	1			 getjpi_list, io_status, , )
c
	Call NULL_Process ( jpi_status )
c
	do while ( jpi_status .ne. SS$_NoMoreProc )
c
	    total_processes = total_processes + 1
	    user_count = user_count + 1
c
c	*** Wait for the Getjpi request to complete
c
	    If ( jpi_status ) iwait_stat = sys$waitfr( %val( getjpi_flag ) )
c
	    If ( Process_Name( : 7 ) .eq. 'SWAPPER' ) Then
		User_Name = '       '
		User_Length = 7
	    End If
c
	    If	( 	( .not. display_all_flag ) .and.
	1	(	(	( user_name( 1: 6 ) .eq. 'SYSTEM' ) .and.
	1			( terminal_length .eq. 0 ) .and.
	1			( .not. bjtest( process_status, 14 ) ) ) .or.
c	1		( user_name( 1: 11 ) .eq. 'JOB_CONTROL' ) .or.
	1		( user_name( 1: 7 ) .eq. '       ' ) .or.
	1		( user_name( 1: 6 ) .eq. 'DECNET' ) ) ) then
		user_count = user_count - 1
	    else
c
c	    *** Clear the display line
c
		Screen( user_count ) = '                              ' //
	1	'                                                  '
c
c	    *** Calculate amount of CPU time
c
		Call Cpu_Usage( user_count )
c
c	    *** Now process the strings
c
		Call Process_Strings( user_count )
c
c	    *** Now process the numerics
c
		Call Process_Numbers( user_count )
c
	    End If
c
c	*** Get the next process
c
	    jpi_status = Sys$Getjpi( %val( getjpi_flag ), pid, ,
	1			     getjpi_list, io_status, , )
c
c    *** Keep going
c
	End Do
c
	Return
	End



	Subroutine Process_numbers( row )
c
	Include 'MaxUnits.For'						!RAC
	Include 'Disply.For'
	Include 'JpiPrm.For'
	Include 'JpiVal.For'
	Include 'Params.For'
c
	Integer*4	row,		cpu_day
	Integer*4	cpu_min,	cpu_sec,	cpu_hou
	Integer*4	Swapped_Out,	k
c
	Character*32	Queue_Name
c
c *** Process state table
c
	character*5	Find_State( 14 )
c
	Data Find_State /'colpg','MWAIT','cef  ','pfw  ','lef  ','LEFO ',
	1		 'hib  ','HIBO ','SUSP ','SUSPO','fpg  ','com  ',
	1		 'COMO ','cur  ' /
c
10	format( i2, '/', i<j> )
20	format( i2 )
30	format( i4 )
40	format( i6 )
50	format( I2,A1,I2.2,':',I2.2 )
60	format( '   ', I2, ':',I2.2 )
c
	Swapped_Out = .False.
	i = row
	j = 1
	If ( base_priority .gt. 9 ) j = 2
c
	Screen( i )( Stat_B: Stat_E) = Find_State( process_state )
c
	If ( ( process_state .eq.  2 ) .or.
	1    ( process_state .eq.  6 ) .or.
	1    ( process_state .eq.  8 ) .or.
	1    ( process_state .eq. 10 ) .or.
	1    ( process_state .eq. 13 ) ) Then
	    Swapped_Out = .True.
	    screen( i )( Logi_B: Logi_E ) = ' ? '
	    screen( i )( Imag_B: Imag_E ) = '   ?    '
	    screen( i )( PgFl_B: PgFl_E) = '   ?  '
	    screen( i )( CpuT_B: CpuT_E) = '    ?   '
	Else If ( Process_State .eq. 9 ) Then
	    screen( i )( Imag_B: Imag_E ) = '   ?    '
	    screen( i )( Logi_B: Logi_E ) = ' ? '
	Else
	    Call Get_Weekday( screen( i )( Logi_B: Logi_E), login_time, k )
	End If
c
	If ( .Not. Swapped_Out ) Then
c
	    write( screen(i)(PgFl_B: PgFl_E),40,iostat=ios) page_faults
c
	    cpu_sec = cpu_time / 100
	    cpu_min = cpu_sec / 60
	    cpu_sec = cpu_sec - ( 60 * cpu_min )
	    cpu_hou = cpu_min / 60
	    cpu_min = cpu_min - ( 60 * cpu_hou )
c
	    If ( cpu_hou .gt. 23 ) Then
		cpu_day = cpu_hou / 24
		cpu_hou = cpu_hou - (cpu_hou * cpu_day)
		write(screen(i)(CpuT_B:CpuT_E),50,iostat=ios) cpu_day, ' ',
	1					   cpu_hou, cpu_min
	    Else If ( cpu_hou .eq. 0 ) Then
		write(screen(i)(CpuT_B:CpuT_E),60, iostat=ios) cpu_min,
	1						       cpu_sec
	    Else
		write(screen(i)(CpuT_B:CpuT_E),50, iostat=ios) cpu_hou, ':',
	1					   cpu_min, cpu_sec
	    End if
	End If
c
	Write(screen(i)(Prio_B:Prio_E),10,iostat=ios) current_priority,
	1					      base_priority
	Write(screen(i)(File_B:File_E),20,iostat=ios) (file_quota -
	1						remaining_file_quota)
	Write(screen(i)(Size_B:Size_E),30,iostat=ios) (Page_Count +
	1						Gbl_Page_Count)
c
c	*** Process status flags
c
	If ( bjtest( process_status, 20 ) ) then
		screen( i )(Term_B: Term_E) = 'NoAth'
	Else If ( bjtest( process_status, 15 ) ) then
		screen( i )(Term_B: Term_E) = 'NoAcnt'
	Else If ( terminal_length .eq. 0 ) then
	    If ( bjtest( process_status, 14 ) ) then
		Call Get_Queue_Name ( Process_Id, Queue_Name, Name_Len )
		Screen( i )( Term_B: Term_E) = Queue_Name( : Name_Len )
	1					// '        '
	    Else If ( bjtest( process_status, 4 ) ) then
		screen( i )( Term_B: Term_E) = 'NoSwp'
	    End If
	End If
c
	return
	end

	Subroutine Process_strings( row )
c
	Include 'MaxUnits.For'						!RAC
	Include 'Disply.For'
	Include 'Params.For'
	Include 'JpiStr.For'
	Include 'JpiVal.For'
	Include 'JpiPrm.For'
	Include 'Flags.For'
c
	Integer*4	row
c
10	Format ( Z8.8,'    ' )
c
	i = row
c
	If ( process_flag ) then
	    write( screen(i)(Proc_B:Proc_E),10, iostat=ios ) process_id
	Else If ( user_flag ) then
	    call convert( user_name( : user_length ),
	1		  screen(i)(Proc_B:Proc_E) )
	Else
	    screen(i)(Proc_B:Proc_E) = process_name( : process_length )
	End If
c
	If ( Terminal_Length .gt. 0 ) then
	    screen(i)(Term_B:Term_E) = Terminal( : Terminal_Length )
	Else
	    screen(i)(Term_B:Term_E) = '     '
	End If
c
	If ( image_length .ne. 0 ) then
	    j = index( image_name, ']' ) + 1
	    Do While ( j .gt. 1 )
		image_name = image_name( j : )
		j = index( image_name, ']' ) + 1
	    End Do
	    image_name = image_name( : index( image_name, '.' ) - 1 )
	    call convert( image_name( :9 ), screen(i)(Imag_B:Imag_E) )
	Else If ( process_state .ne. 2 ) then
	    screen(i)(Imag_B:Imag_E) = '         '
	End If
c
	Return
	End



	Subroutine Get_Load( Idle, Login_Time, Cpu_time)
c
	Character	Idle*(*)
c
	Integer*4	Login_Time( 2 ),	Cpu_Time
	Integer*4	Avg_Idle,		Remainder
	Integer*4	Current_Time( 2 ),	Result( 2 )
c
c *** Calculte the amount of uptime
c
	Call Sys$GetTim ( Current_Time )
	Call Lib$Subx ( Login_Time, Current_Time, Result )
c
c *** Calculte the average load
c
	Call Lib$EDIV ( 10000000, Result, Avg_Idle, Remainder )
	If (Avg_Idle .eq. 0) Then
	    Avg_Idle = 100
	Else
	    Avg_Idle = ( -(Float(Cpu_Time) / Float(Avg_Idle)) + .5 )
	End If
c
10	Format( I4, '%' )
c
	Write(Idle, 10, Err=100, iostat=ios) Avg_Idle
c
100	Continue
c
	Return
	End



	Subroutine Cpu_Usage( Row )
c
	Include 'MaxUnits.For'						!RAC
	Include 'UsrTbl.For'
	Include 'Disply.For'
	Include 'Params.For'
	Include 'JpiVal.For'
	Include 'Idle.For'
c
	Integer*4	row,	elapsed_time( 2 ),	cpu_used
	Integer*4	old_cpu_time,	percent_cpu
c
	Integer*2	user_ptr
c
10	format( i3,'%')
c
	user_ptr = Process_Index
	user_index( row ) = Process_id
c
c *** Get elapsed time
c
	If ( user_table( 1, user_ptr ) .eq. 0 ) then
	    itimer_stat = Lib$Init_Timer( user_table( 1, user_ptr ) )
	    user_table( 3, user_ptr ) = cpu_time
	    If ( Row .eq. 0 ) then
		Percent_Idle = 100
	    Else
	    	Screen( row )(CpuP_B:CpuP_E) = '  0%'
	    End If
	Else 
	    itimer_stat = Lib$Stat_Timer( 1, elapsed_time, user_table( 1,
	1				  user_ptr ) )
	    itimer_stat = Lib$Init_Timer( user_table( 1, user_ptr ) )
c
	    If ( Process_State .ne. 2 ) then
		Old_Cpu_Time = User_Table( 3, User_Ptr )
		User_Table( 3, User_Ptr ) = Cpu_Time
		Cpu_Used = ( Cpu_Time - Old_Cpu_Time ) * 100
		Percent_Cpu = NInt(Float(Abs(Elapsed_Time(1))) / 100000.0)
		If ( Percent_Cpu .gt. 0 ) 
	1	    Percent_Cpu = NInt ( Float ( Cpu_Used ) /
	1			         Float ( Percent_Cpu ) )
		If ( Row .eq. 0 ) then
		    Percent_Idle = Percent_Cpu
		Else
		    Write(Screen(Row)(CpuP_B:CpuP_E),10,iostat=ios) Percent_Cpu
		End If
	    Else
		User_Table( 1, User_Ptr ) = 0
		Screen( Row )(CpuP_B:CpuP_E) = '  0%'
	    End If
	End If
c
	Return
	End



	subroutine get_weekday( day, time, len )
c
	character	day*(*)
	character*9	day_table( 0:6 )
c
	logical*1	size( 0:6 )
c
	integer*4	time( 2 ),	len,	ptr
c
	data day_table 	/ 'Wednesday', 'Thursday ', 'Friday   ', 'Saturday ',
	1		 'Sunday   ', 'Monday   ', 'Tuesday  ' /
	data size	/ 9, 8, 6, 8, 6, 6, 7 /
c
	iday_stat = Lib$Day( iday, time )
c
	ptr = Mth$Jmod( iday, 7 )
	day = day_table( ptr )
	len = size ( ptr )
c
	return
	end

	Subroutine Get_System_Info
c
	Include 'JpiPrm.For'
	Include 'SyiVal.For'
	Include 'SyiPrm.For'
c
	Integer*4	Sys$GetSyiW,	GetSyi_Status,	Sys$WaitFr
c
	GetSyi_Status = Sys$GetsyiW( , , , getsyi_list, , , )
c
c	Find the system type another way since the previous way did not
c	know about 8xxx processors. ( RAC )
c
	If ( Sys_Node_Hwtype(1:1) .eq. '8' ) then
	    System_Type(1:6) = '  VAX '
	    System_Type(7:10)= Sys_Node_Hwtype
	Else
	    System_Type(1:7) = 'VAX-11/'
	    System_Type(8:10)= Sys_Node_Hwtype(2:4)
	End If
c
	Return
	End



	Subroutine Modify_Priority_By( Amount )
c
	Include 'CurPri.For'
c
	Integer*4	amount
	Integer*4	sys$setpri,	return_status
c
	my_current_priority = my_current_priority + amount
c
	if ( my_current_priority .lt. 1 ) then
	    my_current_priority = 31
	else if ( my_current_priority .gt. 31 ) then
	    my_current_priority = 1
	end if
c
	return_status = sys$setpri( , , %val( my_current_priority ), )
c
	return
	end

	subroutine convert( in, out )
c
c *** routine to convert uppercase characters to lowercase
c
	character	in*(*),	out*(*)
	character*26	upper, lower
c
	integer*4	Str$Translate,	iret_stat
c
	upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
	lower = 'abcdefghijklmnopqrstuvwxyz'
c
	out( 1:1 ) = in( 1:1 )
	iret_stat = Str$Translate( out( 2: ), in( 2: ), lower, upper )
c
10	return
	end

	Subroutine Setup_GetJpi
c
c *** Job/Process information request type codes ***
c
	Include '($JpiDef)'
	Include '($SyiDef)'
c
	Include 'JpiStr.For'
	Include 'JpiVal.For'
	Include 'JpiPrm.For'
c
	Include 'SyiVal.For'
	Include 'SyiPrm.For'
c
	Integer*2	short_list( 2, 54 ),	sys_list( 2, 12 )
c
	Equivalence (	getjpi_list,	short_list	)
	Equivalence (	getsyi_list,	sys_list	)
c
c *** Set up the JPI request (never changes) ***
c
c *** Current Priority
	short_list( 1, 1 )	= 4
	short_list( 2, 1 )	= jpi$_pri
	getjpi_list( 2 )	= %loc( current_priority )
	getjpi_list( 3 )	= 0
c *** Base Priority
	short_list( 1, 4 )	= 4
	short_list( 2, 4 )	= jpi$_prib
	getjpi_list( 5 )	= %loc( base_priority )
	getjpi_list( 6 )	= 0
c *** Open file count
	short_list( 1, 7 )	= 4
	short_list( 2, 7 )	= jpi$_filcnt
	getjpi_list( 8 )	= %loc( remaining_file_quota )
	getjpi_list( 9 )	= 0
c *** Image Name
	short_list( 1, 10 )	= 128
	short_list( 2, 10 )	= jpi$_imagname
	getjpi_list( 11 )	= %loc( image_name )
	getjpi_list( 12 )	= %loc( image_length )
c *** Login Time
	short_list( 1, 13 )	= 8
	short_list( 2, 13 )	= jpi$_logintim
	getjpi_list( 14 )	= %loc( login_time )
	getjpi_list( 15 )	= 0
c *** Process Name
	short_list( 1, 16 )	= 15
	short_list( 2, 16 )	= jpi$_prcnam
	getjpi_list( 17 )	= %loc( process_name )
	getjpi_list( 18 )	= %loc( process_length )
c *** Current State
	short_list( 1, 19 )	= 4
	short_list( 2, 19 )	= jpi$_state
	getjpi_list( 20 )	= %loc( process_state )
	getjpi_list( 21 )	= 0
c *** Terminal
	short_list( 1, 22 )	= 7
	short_list( 2, 22 )	= jpi$_terminal
	getjpi_list( 23 )	= %loc( terminal )
	getjpi_list( 24 )	= %loc( terminal_length )
c *** User name
	short_list( 1, 25 )	= 12
	short_list( 2, 25 )	= jpi$_username
	getjpi_list( 26 )	= %loc( user_name )
	getjpi_list( 27 )	= %loc( user_length )
c *** File quota
	short_list( 1, 28 )	= 4
	short_list( 2, 28 )	= jpi$_fillm
	getjpi_list( 29 )	= %loc( file_quota )
	getjpi_list( 30 )	= 0
c *** Process status flags
	short_list( 1, 31 )	= 4
	short_list( 2, 31 )	= jpi$_sts
	getjpi_list( 32 )	= %loc( process_status )
	getjpi_list( 33 )	= 0
c *** Process identification
	short_list( 1, 34 )	= 4
	short_list( 2, 34 )	= jpi$_pid
	getjpi_list( 35 )	= %loc( process_id )
	getjpi_list( 36 )	= 0
c *** Cpu time
	short_list( 1, 37 )	= 4
	short_list( 2, 37 )	= jpi$_cputim
	getjpi_list( 38 )	= %loc( cpu_time )
	getjpi_list( 39 )	= 0
c *** Page count
	short_list( 1, 40 )	= 4
	short_list( 2, 40 )	= jpi$_ppgcnt
	getjpi_list( 41 )	= %loc( page_count )
	getjpi_list( 42 )	= 0
c *** Count of page faults
	short_list( 1, 43 )	= 4
	short_list( 2, 43 )	= jpi$_pageflts
	getjpi_list( 44 )	= %loc( page_faults )
	getjpi_list( 45 )	= 0
c *** Global Page Count
	short_list( 1, 46 )	= 4
	short_list( 2, 46 )	= jpi$_GpgCnt
	getjpi_list( 47 )	= %loc( Gbl_Page_Count )
	getjpi_list( 48 )	= 0
c *** Process Index
	short_list( 1, 49 )	= 4
	short_list( 2, 49 )	= Jpi$_Proc_Index
	getjpi_list( 50 )	= %loc( Process_Index )
	getjpi_list( 51 )	= 0
c *** Mark end of options
	getjpi_list( 52 )	= 0
	getjpi_list( 53 )	= 0
	getjpi_list( 54 )	= 0
c
c *** Define the GetSyi item list for system information
c
c *** Software Version
	Sys_List( 1, 1 )	= 8
	Sys_List( 2, 1 )	= Syi$_Version
	GetSyi_List( 2 )	= %Loc( System_Version )
	GetSyi_List( 3 )	= %Loc( Version_Length )
c *** Cpu Type
	Sys_List( 1, 4 )	= 4
	Sys_List( 2, 4 )	= Syi$_Node_Hwtype			!RAC
	GetSyi_List( 5 )	= %Loc( Sys_Node_Hwtype)		!RAC
	GetSyi_List( 6 )	= 0
c *** System Boot time
	Sys_List( 1, 7 )	= 8
	Sys_List( 2, 7 )	= Syi$_BootTime
	GetSyi_List( 8 )	= %Loc( Sys_Boot_Time )
	GetSyi_List( 9 )	= 0
c *** Mark end of options
	getsyi_list( 10 )	= 0
	getsyi_list( 11 )	= 0
	getsyi_list( 12 )	= 0
c
	Return
	End


	Integer Function SIGNAL_HANDLER (	Signal_Vector,
	1					Mechanism_Vector )
c
	Integer		Signal_Vector( * ),
	1		Mechanism_Vector( * )
c
	Integer*4	Privilege(2) /0,0/
c
	Include '($PRVDEF)'
	Include '($SSDEF)'
c
	Integer		NEW_ARGS( 10 ),		Element
c
	Character*1	Esc
c	
	Element = 1
	NEW_ARGS(Element) = 10
c
	Do I = 1, Signal_Vector( 1 ) - 2
	    Element = Element + 1
	    NEW_ARGS(Element) = Signal_Vector(Element)
	End Do
c
	Do I = Element + 1, 10
	    Element = Element + 1
	    NEW_ARGS(Element) = 0
	End Do
c
c *** Restore Cursor
c
	Esc = Char( 27 )
	Call Lib$Put_Screen( Esc // '[?25h', 1, 1 )
	Call Lib$Erase_Page( 1, 1 )
c
	Ctrl_Status = Lib$Enable_Ctrl( '02100000'X )
c
c  Turn off privileges
c
	Call Modify_Priv ( .False. )				!RAC / MRV
c
	Call SYS$PUTMSG( NEW_ARGS, , 'LILBRO', )
c
	Signal_Handler = SS$_Continue
	Call Sys$Exit(%Val(SS$_Abort))
c
	Return
	End


c
c Modification History under VAX/VMS V3
c
c                     V1.0  - The original version
c
c                     V1.1  - Added pages of display and increased number
c                             of  processes  that  can be displayed.  The
c                             maximum  number  of  process  that  can  be
c                             displayed  now  is  128  ( 19 per page with
c                             6+ pages ).  MRV. June 10, 1984
c
c                     V1.2  - Corrected  overflow  on  internal reads for
c                             the  display  of  page  faults  in  routine
c                             Process_Numbers  when  the  number  of page
c                             faults  are  larger than 999,999. The field
c                             is filled with "*".  MRV. August 24, 1984
c
c                     V1.3  - Corrected  overflow  on  internal reads for
c                             the  display of CPU times.  When the number
c                             CPU  hours is to  large the field is filled
c                             with "*".  MRV. November 12, 1984
c
c                     V1.4  - Modified the rmd_ctrl_exit routine to force
c                             an immediate exit on ^Y and on ^C.
c
c                           - Modified  the  modify_sleep_time routine so
c                             that   wake   ups   can  be  changed  while
c                             hibernating.  This allows one to get out of
c                             a long hibernation.
c
c                           - Modified  the process_input routine so that
c                             the  sleep  flag  is set to 1 when the exit
c                             flag is set.  This allows for a faster exit
c                             when the sleep time is large.
c
c                           - Added RMDEMO version number to the display.
c
c                           - MRV. December 27, 1984.
c
c                     V1.5  - Modified  the  Getjpi_Setup routine so that
c                             the  correct  process size is reported. ie.
c                             process   size   is   Process_Page_Count  +
c                             Global_Page_Count.
c
c                           - MRV. January 16, 1985.
c
c
c	**** VAX/VMS 4.0 Modification History of RMDEMO
c
c                     V2.0  - Major modifications  made to correct problems
c                             caused by VAX/VMS V4. Some (not all) changes
c                             are listed below.
c
c                           - Move all common  blocks to seperate files and
c                             INCLUDEd into program.
c
c                           - Use the  NULL  process to  determine  correct
c                             amount of idle time and  total amount of idle
c                             time since the  system was booted.  I  assume
c                             the  first  two  processes  returned  by  the
c                             GETJPI are 1) NULL and 2) SWAPPER.
c
c                           - Comment  out  code  used to get terminal idle
c                             times. The macro routine is broken. Plans are
c                             being made to correct the problems.
c
c                           - Schedule  wakeups BEFORE assignning a channel
c                             to get input.  A bug was  found when HELP was
c                             requested  before wakeups were scheduled. The
c                             program would not return from hibernation.
c
c                           - MRV.  May 15, 1985
c
c                     V2.1  - Correct  display  for   processes   that  are
c                             swapped  out or  suspended.  Display only the
c                             information   that   is  available  for  that
c                             process. Treat processes that are in MWAIT as
c                             if they were swapped out.
c
c                           - MRV. May 20, 1985
c
