[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference noted::hackers

Title:** Hackers **
Moderator:XDELTA::HOFFMAN
Created:Sun Jan 31 1988
Last Modified:Tue May 27 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:1838
Total number of notes:13578

1832.0. "ldr$unload_image" by CPEEDY::BRADLEY (Chuck Bradley) Tue Mar 25 1997 15:08

have any of you ever used ldr$unload_image?
do you know anyone or any project that might have tried it?

do any of you have any hints or warnings about replacing 
an execlet on the fly?

thanks.
T.RTitleUserPersonal
Name
DateLines
1832.1ZIMBRA::BERNARDODave Bernardo, VMS EngineeringTue Mar 25 1997 21:096
    
    ldr$unload_image can only unload an execlet which was previously
    loaded so that it _could_ be unloaded.... so, how are you planning
    to use it?
    
    d.
1832.2EEMELI::MOSEROrienteers do it in the bush...Wed Mar 26 1997 06:249
    I persoanlly have done this when writing an execlet and testing it,
    so I didn't have to reboot every time, but there are gotchas you need
    to know, otherwise you trigger an automatic reboot (== bugcheck).
    
    I do not recommend that for a production environment, and as Dave said
    you need to load it correctly so you can use the unload. I'll post my
    load/unload hack in the next reply (saince this is hackers...)
    
    /cmos
1832.3EEMELI::MOSEROrienteers do it in the bush...Wed Mar 26 1997 06:26235
	.title	CTRL_LOAD	- Dynamic loading of an exec image
	.sbttl	Copyright Notice
	.ident	'V2.0-001'

;
;*************************************************************************
;*                                                                       *
;*    �    Digital Equipment Corporation, 1993				 *
;*		All Rights Reserved. 					 *
;* Unpublished rights reserved under the copyright laws  of  the  United *
;* States.                                                               *
;*                                                                       *
;* The software contained on this media is proprietary to  and  embodies *
;* the   confidential   technology  of  Digital  Equipment  Corporation. *
;* Possession, use, duplication or dissemination  of  the  software  and *
;* media  is  authorized  only  pursuant to a valid written license from *
;* Digital Equipment Corporation.                                        *
;*                                                                       *
;* RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure by the  U.S. *
;* Government  is  subject  to restrictions as set forth in Subparagraph *
;* (c)(1)(ii) of DFARS 252.227-7013, or in FAR 52.227-19, as applicable. *
;*                                                                       *
;*************************************************************************
;

	.sbttl	Program Description
;
; ...	Title:		Ctrl_Load
;
; ...	Version:	V1.0-002
;
; ...	Facility:	Utilities
;
; ...	Abstract:	This utility will load the Ctrl_Stuff execlet into
;			nonpaged pool using the dynamic loader. The execlet
;			will be re-loaded if it already exists.
;
; ...	Environment:	Mostly kernel mode
;
; ...	Author:		Christian Moser / Digital Equipment Corporation (DEC)
;
; ...	Remarks:	
;
; ...	Date:		19-OCT-1993
;
; ...	Modified by:	
;
;	V1.0-002	Christian Moser		27-OCT-1993
;		Implement workaround for VMS versions prior to OpenVMS VAX V6.0
;		since there exists a bug in the system loader's initial
;		unload routine. A CMPC3 instruction is trashing some registers.
;
;	V2.0-001	Christian Moser		15-NOV-1994
;		Adapted for OpenVMS AXP.
;
;--------------------------------------------------------------------------
;
;

	.sbttl	Declarations
	.library	/sys$library:lib/

	$lnmdef
	$psldef
	$ldrimgdef
	.if DF	EVAX
	$ldrdef
	.endc

	.macro	onerror action,?l
	blbs	r0,l
	action
	l:
	.endm	onerror

	.macro	print	cnt,text,?l1
	.save	
	.psect	macro_literals,nowrt,noexe,quad
	.align	quad
l1:	.ascid	\text\
	.restore 
	movl	#255,buf_desc
	pushaq	buf_desc
	pushal	buf_desc
	pushaq	l1
	calls	#<cnt+3>,g^sys$fao
	pushaq	buf_desc
	calls	#1,g^lib$put_output
	.endm	print


	.page
	.sbttl	Data Definitions
	.psect	load$data	pic,rd,wrt,noexe,quad

handle:		.blkl	3			; execlet handle information
lnm:		.word	4			; $trnlnm itemlist
		.word	lnm$_string
		.address rtn_table
		.long	0
		.long	0
rtn_table:	.blkl	1			; addr to hold ptr to rtn table
acmode:		.long	psl$c_exec		; executive mode
buf_desc:	.blkl	1			; output buffer descr
		.address buf			; addr of output buffer
buf:		.blkb	255			; output buffer
imgdsc:		.ascid	/SYS$COMMON:[SYS$LDR]CTRL_STUFF.EXE/
						; image name to be loaded
tabnam:		.ascid	/LNM$SYSTEM_TABLE/	; system-wide log table
lognam:		.ascid	/CTRL$RTN_TABLE/	; logical name for rtn table


	.page
	.sbttl	Ctrl_Load	- Dynamic loading of an exec image
	.psect	load$code	pic,rd,nowrt,exe,long

	.enable	lsb
	.entry	Ctrl_Load,^m<r2>

	pushal	handle				; addr to hold handle
	pushaq	imgdsc				; identifies the execlet
	pushl	#2				; argument count
	$cmkrnl_s -				; must be done from kernel mode
		routin=g^ldr$ref_info, -	; retrieve handle information
		arglst=(sp)
	onerror	<brw 100$>			; branch on errors
	moval	handle,r2			; point to execlet handle
	pushl	8(r2)				; sequence number
	pushl	4(r2)				; ldrimg data block
	pushl	(r2)				; execlet addr
	print	3,<%CTRL-I-HANDLE, execlet handle information...!/!_Address: !XL,  Ldrimg Data Block: !XL,  Seq Number: !XL>

	print	0,<%CTRL-I-UNLOAD, unloading Ctrl_Stuff execlet...>
	$cmkrnl_s -				; unload the image
		routin=g^ldr$unload_image, -
		arglst=(sp)
	onerror	<brw 200$>			; branch on error

100$:	print	0,<%CTRL-I-LOAD, loading Ctrl_Stuff execlet...>
	pushal	handle				; push handle addr
	.if DF	EVAX
	pushl	#<ldr$m_unl>			; push flag for possible unload
	.iff
	pushl	#<ldr_dyn$m_unl>		; push flag for possible unload
	.endc
	pushaq	imgdsc				; push image descr
	pushl	#3				; push arg count
	$cmexec_s -				; must do it from exec mode
		routin=g^ldr$load_image, -	; dynamic loader routine
		arglst=(sp)			; arg list on stack
	onerror	<brw 150$>			; branch on error
	moval	handle,r2			; point to execlet handle
	pushl	8(r2)				; sequence number
	pushl	4(r2)				; ldrimg data block
	pushl	(r2)				; execlet addr
	print	3,<%CTRL-I-HANDLE, execlet handle information...!/!_Address: !XL,  Ldrimg Data Block: !XL,  Seq Number: !XL>

	$trnlnm_s -				; trying to translate the
		tabnam=tabnam,-			; logical name to find the
		lognam=lognam,-			; rtn table information
		acmode=acmode,-
		itmlst=lnm
	onerror	<brw 250$>			; branch on errors
	pushl	rtn_table			; rtn table address
	print	1,<%CTRL-I-RTNTAB, control routine table...!/!_Address: !XL>

120$:	movzwl	#ss$_normal,r0			; setup happy status
	ret					; get the hell out

150$:	movl	r0,r2				; save error status
	pushl	r0				; push error status
	print	1,<%CTRL-E-NOLOAD, could not load Ctrl_Stuff execlet (status=%X!XL)>
	pushl	r2				; push error status
	pushl	#1				; only one argument
	movl	sp,r2				; save stack pointer
	$putmsg_s -				; signal message to user
		msgvec=(r2)			; message vector on stack
	addl2	#8,sp				; restore stack
	print	0,<%CTRL-I-DELLNM, deleting CTRL$RTN_TABLE logical name...>
	$dellnm_s -				; delete a system-wide logical
		tabnam=tabnam,-			; containing the routine table
		lognam=lognam,-			; address pointer
		acmode=acmode
	brw	120$				; branch to common exit

	.if NDF	EVAX
190$:	brw	300$				; branch helper
	.endc
200$:	movl	r0,r2				; save error status
	cmpl	#ss$_badparam,r0		; is it bad parameter ?
	bneq	215$				; continue if not
	.if NDF	EVAX
	movl	g^sys$gq_version,r0		; grab VMS version
	cmpl	#^a/V5.5/,r0			; check for V5.5
	beql	190$				; out of line if true
	cmpl	#^a/A5.5/,r0			; check for A5.5
	beql	190$				; out of line if true
	.endc

215$:	pushl	r2				; push error status
	print	1,<%CTRL-E-NOUNLOAD, could not unload Ctrl_Stuff execlet (status=!XL)>
220$:	pushl	r2				; push error status
	pushl	#1				; only one argument
	movl	sp,r2				; save stack pointer
	$putmsg_s -				; signal message to user
		msgvec=(r2)			; message vector on stack
	addl2	#8,sp				; restore stack
	brw	120$				; branch to common exit

250$:	movl	r0,r2				; save error status
	pushl	r0				; push error status
	print	1,<%CTRL-E-TRNLNM, could not translate CTRL$RTN_TABLE logical name (status=!XL)>
	brw	220$				; branch to common exit

	.if NDF	EVAX
300$:	$cmkrnl_s -				; must do it from kernel mode
		routin=unload_055		; workaround for bug in sysldr
	brw	100$				; join common code for load
	.endc
	.disable lsb


	.if NDF	EVAX
	.entry	unload_055,^m<r5>
	moval	handle,r5			; grab handle
	pushl	4(r5)				; push LDRIMG data block addr
	calls	#1,g^ldr$final_unload		; use alternate entry point
						; bypassing checks (pre V6.0)
	movzwl	#ss$_normal,r0			; setup happy status
	ret					; get the hell out
	.endc


	.end	ctrl_load
    
1832.4considering trying itCPEEDY::BRADLEYChuck BradleyWed Mar 26 1997 11:1526
re .1, what am i trying to do?

similar to .2, we could save a lot of time testing if we could unload
an execlet.  in pathworks, we have an execlet to implement streams
and we use it for various communications protocols.  we build several
times per week and each new installation requires a reboot. it would
be nice to avoid the reboot.  

some customers report problems, and sometimes we have to collect more
information to solve the problem. sometimes it takes an instrumented
version of the software to gather the information.  the customer does
not want to reboot just to gather information, so he waits until the
next scheduled or accidental downtime to install the instrumented
software.  as a result it takes a longer time to solve the problem.
CLD turnaround time is a major concern this year.

someone worked on this for a while, but did not have a full solution
when they left the company.  i wanted to be sure it was possible
before looking further.  ldr$unload_image does not seem to be documented
for the outside world, so it was easy to imagine that it was only
half implemented.  the existence proof in .3 is reassuring.

re .3, sample of use:
thank you.  after i study it, and review what has been done here,
i may have some more questions.

1832.5Suggestions, Pointers...XDELTA::HOFFMANSteve, OpenVMS EngineeringWed Mar 26 1997 12:0613
   There are some ldr$* and *image* keywords here...

   Have you considered an execlet that contains vector(s) to the real
   execlet(s)?  This would let you "update" the code on the fly.  (You
   might not be able to unload the code, but generating pool large
   enough to support some no-longer-needed code might be easier than
   the reboot appears to be.)

   My preference is usually to use a pseudo device driver as a "shell"
   for loadable code, as one can easily add more of these, and one has
   a nice user-mode-accessable "control interface" available.

1832.6thanks. lots of pool usedCPEEDY::BRADLEYChuck BradleyWed Mar 26 1997 13:5624
re .5:
thanks for the suggested keywords.  i'll check them out.
so few conferences have useful and up to date keywords, that i didn't 
even try.  i made about a half dozen tries with dir/title=foo and found 
very little -- unloading a device driver, repeated initialization.
so i scanned the entire directory looking for related titles.
when i didn't see anything useful, i entered .0.

we might be able to afford losing the space occupied by the image to
be replaced, but i think there is many times that much in data buffers.
this is just a hunch, not an estimate or even an educated guess,
but i suspect doing it as bad as i can get away with is at least
3/4 of the effort to do it right.

i'll also look at the pseudo device driver.  i've only looked at
a tiny fraction of the code, but that part is well organized.
all of the allocated pool is on multiple lists and it looks
like i can give it all back exactly once.

thanks, again for the suggestions and the pointers.

BTW, silence here does not necessarily mean success. this might not
even make it to the top of the list of things to work on.
1832.7ZIMBRA::BERNARDODave Bernardo, VMS EngineeringWed Mar 26 1997 18:2517
    If you decide to go the unload route, you'll need to initially load
    your execlets with the LDR$V_UNL bit set. And, you will also have to
    make sure that nothing is using the execlet while you are trying to
    unload it... or you'll get to see the reboot feature of the ldr
    routines in action.

    One of the features execlets were intended to have were unload
    routines. Similar to initialization routines but at the other end of
    the rainbow. So, you _could_ try to use this feature to deallocate your
    memory.  But, you will probably be the first. I own the exec loader on
    Alpha VMS and I know that everything else works. But, no one uses the
    unload routine stuff, so I can't say if it does.

    And lastly, the ldr$ routines got documented in V7.1... in the
    Programming Concepts book.

    d.
1832.8It can be done....UTRTSC::VDBURGChange mode to PANICThu Mar 27 1997 01:3921
    Well, you can load as well as unload. Some time ago i created some
    stuff to load and unload a module on the fly. The main routine to do
    the processing is called from macro and written in C, it was some
    process state monitor. The problem i ran into was that real dynamic
    unloading support is not compiled in the VMS kernel. I don't have the
    right details in my head, but you should be able to specify an unload
    routine in a seprarate psect, and by specifying a flag it should be
    called. But this code is currently not included in the kernel.
    
    The next replies contain example code.
    
    .+1 = BUILD.COM, the build procedure
    .+2 = ARCH.MAR, used for conditional compilation for Vax or Alpha
    .+3 = SMON.MAR, the main routine
    .+4 = SMONLOAD.C, the dynamic loader
    .+5 = SMONUNLOAD.C, the dynamic unloader
    .+6 = PROCPROC.C, the C routine called by the main routine to do
    some processing.
    
    Jur.
    
1832.9BUILD.COMUTRTSC::VDBURGChange mode to PANICThu Mar 27 1997 01:3993
$ if f$getsyi("hw_model") .gt. 1023
$ then
$   alpha = 1
$ else
$   alpha = 0
$ endif
$ if alpha
$ then
$   if p1 .nes. "" then goto linka
$   macro/obj=smon arch+smon+sys$library:lib/lib
$   cc/define="ALPHA"/instruct=nofloat/extern=strict-
/warning=disable=globalext procproc+sys$library:sys$lib_c/lib
$   cc/define="ALPHA" smonload+sys$library:sys$lib_c/lib
$   cc/define="ALPHA" smonunload+sys$library:sys$lib_c/lib
$linka:
$   link/notrace/sysexe smonload
$   link/notrace/sysexe smonunload
$   link/native_only/bpages=14/section/replace/notraceback/nosysshr/vms_exec-
	/nodemand_zero/contiguous/share=smon.exe/map=smon/cross/full sys$input:/opt
cluster=smon,,,smon,procproc,sys$library:starlet/include=(sys$doinit)
sys$loadable_images:sys$base_image.exe/share/sele
psect_attr = $linkage                   ,  PIC,GBL,NOSHR,NOEXE,  RD,  WRT
psect_attr = exec$init_linkage          ,  PIC,USR,CON,REL,GBL,NOSHR,EXE,RD,WRT,NOVEC
psect_attr = exec$init_code             ,  PIC,GBL,NOSHR,  EXE,  RD,  WRT
psect_attr = exec$init_000              ,  PIC,GBL,NOSHR,  EXE,  RD,  WRT
psect_attr = exec$init_001              ,  PIC,GBL,NOSHR,  EXE,  RD,  WRT
psect_attr = exec$init_002              ,  PIC,GBL,NOSHR,  EXE,  RD,  WRT
psect_attr = exec$init_sstbl_000        ,  PIC,GBL,NOSHR,  EXE,  RD,  WRT
psect_attr = exec$init_sstbl_001        ,  PIC,GBL,NOSHR,  EXE,  RD,  WRT
psect_attr = exec$init_sstbl_002        ,  PIC,GBL,NOSHR,  EXE,  RD,  WRT
psect_attr = $link$			,  PIC,WRT
psect_attr = $initial$			,  PIC,WRT
psect_attr = $literal$			,  PIC,NOSHR,WRT
psect_attr = $readonly$			,  PIC,NOSHR,WRT
psect_attr = $code$			,  PIC,GBL,NOSHR,  EXE,  RD,  NOWRT
psect_attr = $data$			,  PIC,GBL,NOSHR,  NOEXE,  RD,  WRT
psect_attr = $bss$			,  PIC,GBL,NOSHR,  NOEXE,  RD,  WRT
collect = nonpaged_readonly_psects/attributes=resident,-
	exec$nonpaged_code,$code$
collect = nonpaged_readwrite_psects/attributes=resident,-
	exec$nonpaged_data,$data$,$link$,$literal$,$bss$,-
	$readonly$,$linkage,exec$nonpaged_linkage
collect = initialization_psects/attributes=initialization_code -
        , exec$init_code -
        , exec$init_000 -
        , exec$init_001 -
        , exec$init_002 -
        , exec$init_linkage -
        , exec$init_sstbl_000 -
        , exec$init_sstbl_001 -
        , exec$init_sstbl_002
$ else
$   if p1 .nes. "" then goto linkv
$   macro smon+sys$library:lib/lib
$   cc procproc
$   cc smonload
$   cc smonunload
$linkv:
$   link/notrace smonload,sys$input/opt
sys$share:vaxcrtl.exe/share
sys$system:sys.stb/selective
$   link/notrace smonunload,sys$input/opt
sys$share:vaxcrtl.exe/share
sys$system:sys.stb/selective
$   link/nosysshr/notraceback/share=smon/contiguous-
/symbol=smon/map=smon/full/cross sys$input/opt
sys$library:starlet/include:(sys$doinit),-
sys$disk:[]smon,procproc,-
sys$system:sys.stb/selective
vector_table=sys$system:sys.stb
psect_attr=$code,noshr
psect_attr=$char_string_constants,noshr
collect=nonpaged_readonly_psects/attributes=resident,-
	exec$nonpaged_code,$code
collect=nonpaged_readwrite_psects/attributes=resident,-
	exec$nonpaged_data,$data,$char_string_constants
collect=paged_readonly_psects,-
	exec$paged_code
collect=paged_readwrite_psects,-
	exec$paged_data
collect=initialization_psects/attributes=initialization_code,-
	exec$init_code,-
	exec$init_000,-
	exec$init_001,-
	exec$init_002,-
	exec$init_pfntbl_001,-
	exec$init_pfntbl_002,-
	exec$init_pfntbl_003,-
	exec$init_sstbl_000,-
	exec$init_sstbl_001,-
	exec$init_sstbl_002
$ endif
$ copy/log smon.exe sys$common:[sys$ldr]
1832.10ARCH.MARUTRTSC::VDBURGChange mode to PANICThu Mar 27 1997 01:401
alpha==1
1832.11SMON.MARUTRTSC::VDBURGChange mode to PANICThu Mar 27 1997 01:40116
	.title		Smon - Process state monitor
	.ident		/V1.0/
	.library	'sys$library:lib'

	$ipldef
      	$tqedef
	$ldrimgdef
	$inirtndef      
	.if df alpha
	$ldrdef
	.endc

	.macro	return
	.if df alpha
	ret
	.iff
	rsb
	.endc
	.endm

	DECLARE_PSECT	EXEC$INIT_CODE

	.if df alpha
	INITIALIZATION_ROUTINE	NAME=SMON$INIT
	.iff
	INITIALIZATION_ROUTINE	NAME=SMON$INIT,-
				SYSTEM_RTN=1
	.endc
;
; Input: R4 = LDRIMG block
;        R5 = Address of flags longword
;	 R0,R1,R2,R3 = scratch
;
smon$init:
	.if df alpha
	.call_entry	input=<r4,r5>,-
			output=<r0>
	.endc
	movzwl	#ss$_normal,r0
	bbs	#inirtn$v_called,(r5),20$
	setipl	#ipl$_astdel,-                                  
		environ=uniprocessor			; Avoid scheduling
;
; Now allocate the TQE and queue it to the system.
;                                                 
	pushr	#^m<r2,r3,r4,r5>
	jsb	g^exe$alloctqe		  		; Allocate a timer entry
	blbc	r0,10$					; Any errors ?
	movl	r2,tqeadr
;
; Now setup the TQE to contain the correct parameters.
;                
	movab	action,tqe$l_fpc(r2)			; Setup the rtn address
	movb	#tqe$c_ssrept,tqe$b_rqtype(r2)		; Make it repeatable
	movl	r2,r5	       				; Copy the TQE address
	movq	g^exe$gq_systime,r0			; Get current time
	.iif df alpha, .disable flagging
	movq	#^D1000000,tqe$q_delta(r5)		; 10 Ms delta time
	.iif df alpha, .enable flagging
	jsb	g^exe$instimq				; Insert it in the queue
	movab	smon$unload,unlvec			; Setup address of unload routine
	.if ndf alpha
	bisl2	#inirtn$m_sysrtn,unlvec+4
	.endc
	moval	unlvec,ldrimg$l_unlvec(r4)		; Setup address of unload vector
	movzwl	#ss$_normal,r0

10$:	setipl	#0,-          
	       	environ=uniprocessor			; Restore IPL
	popr	#^m<r2,r3,r4,r5>

20$:	blbc	r0,30$					; Stop in case of error
	calls	#0,procinit				; Init of main code

30$:	return						; Return to the caller

	DECLARE_PSECT	EXEC$NONPAGED_CODE

action:
	.if df alpha
	.call_entry
	.endc

	lock	sched
	calls	#0,procproc
	unlock	sched
	return
;
smon$unload:
	.if df alpha
	.call_entry	output=<r0>
	.endc

	movl	tqeadr,r4
	jsb	g^exe$rmvtimq
	blbc	r0,10$
	movl	r4,r0
	jsb	g^exe$deanonpaged
	movzwl	#ss$_normal,r0

10$:	return

	DECLARE_PSECT	EXEC$NONPAGED_DATA

tqeadr:		.long	0				; Our TQE address

unlvec:		.long	0				; Unload routine address
		.long	0				; Flags
		.long	0				; Termination of chain

;	DECLARE_PSECT	EXEC$UNL_001
;
;	.address	smon$unload
;	.long		0

	.end
1832.12SMONLOAD.CUTRTSC::VDBURGChange mode to PANICThu Mar 27 1997 01:4073
#include <stdio.h>
#include <descrip.h>
#include <psldef.h>
#include <lnmdef.h>
#include <starlet.h>
#include <lib$routines.h>

#define IMAGE "SMON.EXE"
#define TABLE "LNM$SYSTEM_TABLE"
#define LOGNAM "SMON$HANDLE"

#ifdef ALPHA
#include <ldrdef.h>
#else
#ifndef LDR_DYN$M_UNL
#define LDR_DYN$M_UNL 2
#endif
#endif

typedef struct itmlst {
	short size;
	short item;
	char *buffer;
	char *retlen;
} ITEMS;

int ldr$load_image();

int main()
{
	int stat;
	unsigned int handle[3];
	unsigned int arglist[4];
	$DESCRIPTOR(imgdsc,IMAGE);
	$DESCRIPTOR(tblname,TABLE);
	$DESCRIPTOR(logname,LOGNAM);
	ITEMS lnmlst[4];
	char h1[9], h2[9], h3[9];

	arglist[0] = 3;
	arglist[1] = (int) &imgdsc;
#ifdef ALPHA
	arglist[2] = LDR$M_UNL;
#else
	arglist[2] = LDR_DYN$M_UNL;
#endif
	arglist[3] = (int) handle;
	stat = sys$cmkrnl(&ldr$load_image,arglist);
	if (!(stat & 1))
		lib$stop(stat);
	printf("Image %s loaded successfully.\nAddress:\t%08.8X\nLDRIMG block:\t%08.8X\nSeq. number:\t%08.8X\n",
		IMAGE, handle[0], handle[1], handle[2]);
	sprintf(h1,"%08.8X",handle[0]);
	sprintf(h2,"%08.8X",handle[1]);
	sprintf(h3,"%08.8X",handle[2]);
	lnmlst[0].size = 8;
	lnmlst[0].item = LNM$_STRING;
	lnmlst[0].buffer = h1;
	lnmlst[0].retlen = 0;
	lnmlst[1].size = 8;
	lnmlst[1].item = LNM$_STRING;
	lnmlst[1].buffer = h2;
	lnmlst[1].retlen = 0;
	lnmlst[2].size = 8;
	lnmlst[2].item = LNM$_STRING;
	lnmlst[2].buffer = h3;
	lnmlst[2].retlen = 0;
	lnmlst[3].size = 0;
	lnmlst[3].item = 0;
	stat = sys$crelnm(0,&tblname,&logname,&PSL$C_EXEC,&lnmlst);
	if (!(stat & 1))
		lib$stop(stat);
}
1832.13SMONUNLOAD.CUTRTSC::VDBURGChange mode to PANICThu Mar 27 1997 01:4081
#include <stdio.h>
#include <descrip.h>
#include <psldef.h>
#include <lnmdef.h>
#include <starlet.h>
#include <lib$routines.h>

#define IMAGE "SMON.EXE"
#define TABLE "LNM$SYSTEM_TABLE"
#define LOGNAM "SMON$HANDLE"

typedef struct itmlst {
	short size;
	short item;
	char *buffer;
	short *retlen;
} ITEMS;

int ldr$unload_image();

int main()
{
	int stat;
	unsigned int handle[3];
	unsigned int arglist[3];
	$DESCRIPTOR(imgdsc,IMAGE);
	$DESCRIPTOR(tblname,TABLE);
	$DESCRIPTOR(logname,LOGNAM);
	ITEMS lnmlst[7];
	char h1[9], h2[9], h3[9];
	short l1, l2, l3;
	int idx1, idx2, idx3;

	idx1 = 0;
	idx2 = 1;
	idx3 = 2;
	lnmlst[0].size = 4;
	lnmlst[0].item = LNM$_INDEX;
	lnmlst[0].buffer = (char *) &idx1;
	lnmlst[0].retlen = 0;
	lnmlst[1].size = 8;
	lnmlst[1].item = LNM$_STRING;
	lnmlst[1].buffer = h1;
	lnmlst[1].retlen = &l1;
	lnmlst[2].size = 4;
	lnmlst[2].item = LNM$_INDEX;
	lnmlst[2].buffer = (char *) &idx2;
	lnmlst[2].retlen = 0;
	lnmlst[3].size = 8;
	lnmlst[3].item = LNM$_STRING;
	lnmlst[3].buffer = h2;
	lnmlst[3].retlen = &l2;
	lnmlst[4].size = 4;
	lnmlst[4].item = LNM$_INDEX;
	lnmlst[4].buffer = (char *) &idx3;
	lnmlst[4].retlen = 0;
	lnmlst[5].size = 8;
	lnmlst[5].item = LNM$_STRING;
	lnmlst[5].buffer = h3;
	lnmlst[5].retlen = &l3;
	lnmlst[6].size = 0;
	lnmlst[6].item = 0;
	stat = sys$trnlnm(0,&tblname,&logname,&PSL$C_EXEC,&lnmlst);
	if (!(stat & 1))
		lib$stop(stat);
	h1[l1] = '\0';
	h2[l2] = '\0';
	h3[l3] = '\0';
	sscanf(h1,"%x",&handle[0]);
	sscanf(h2,"%x",&handle[1]);
	sscanf(h3,"%x",&handle[2]);
	arglist[0] = 2;
	arglist[1] = (int) &imgdsc;
	arglist[2] = (int) handle;
	stat = sys$cmkrnl(&ldr$unload_image,arglist);
	if (!(stat & 1))
		lib$stop(stat);
	stat = sys$dellnm(&tblname,&logname,&PSL$C_EXEC);
	if (!(stat & 1))
		lib$stop(stat);
}
1832.14PROCPROC.CUTRTSC::VDBURGChange mode to PANICThu Mar 27 1997 01:40137
#ifdef ALPHA
#include <pcbdef.h>
#else
typedef struct _pcb {
	char dummy1[26];
	unsigned short pcb$w_state;
	char dummy2[284];
	unsigned char pcb$t_lname[16];
} PCB;
#endif
#include <starlet.h>
#include <ssdef.h>

int p_strlen();
int p_strncmp();
char *p_strcpy();
void p_bzero();

globalref unsigned long int sch$gl_pcbvec;
globalref unsigned long int sch$gl_maxpix;

struct proctbl {
	char proclen;
	char procname[15];
	int statarray[15];
	int starttime[2];
};

static struct proctbl procs[1000];

static char *namtbl[] = {
	"PWRK$MASTER",
	"PWRK$LMSRV",
	"PWRK$LMMCP",
	"PWRK$LMDMN",
	"PWRK$ADMIN_0",
	"PWRK$LICENSE_R",
	"PWRK$KNBDAEMON",
	"PWRK$NBDAEMON",
	"PWRK$MONITOR",
	"NETBIOS",
	""
};

int procinit()
{
   struct proctbl *p;
   char **namp;
   int stat, starttime[2];

   if (sch$gl_maxpix > 1000)
      return (SS$_INSFMEM);
   stat = sys$gettim(starttime);
   if (stat & 1) {
      namp = namtbl;
      p = procs;
      for (; *namp[0]; p++, namp++) {
         p_strcpy(p->procname,*namp);
         p->proclen = p_strlen(p->procname);
         p_bzero(p->statarray,sizeof(p->statarray));
         p->starttime[0] = starttime[0];
         p->starttime[1] = starttime[1];
      }
      p->proclen = 0;
   }
   return stat;
}

int procproc()
{
   unsigned int maxindex, *tblpnt;
   PCB *pcbpnt, *nullpcb;
   struct proctbl *p;
   int j, namesize;

   maxindex = sch$gl_maxpix - 2;
   tblpnt = (unsigned int *) sch$gl_pcbvec;
   nullpcb = (PCB *) *tblpnt++;		/* pcb of null process */
   tblpnt++;				/* skip swapper */

   for (j = 0; j <= maxindex; j++) {
      pcbpnt = (PCB *) *tblpnt++;
      if (pcbpnt != nullpcb) {
         namesize = *pcbpnt->pcb$t_lname & 0xff;
         for (p = procs; p->proclen > 0; p++) {
            if ((p->proclen == namesize) &&
               (p_strncmp(pcbpnt->pcb$t_lname+1,p->procname,namesize) == 0)) {
#ifdef ALPHA
               p->statarray[pcbpnt->pcb$l_state]++;
#else
               p->statarray[pcbpnt->pcb$w_state]++;
#endif
            }
         }
      }
   }
   return 1;
}

int p_strncmp(s1, s2, n)
register unsigned char *s1, *s2;
register n;
{
   while (--n >= 0 && *s1 == *s2++)
      if (*s1++ == '\0')
         return(0);
   return(n<0 ? 0 : *s1 - *--s2);
}

char *p_strcpy(s1, s2)
register char *s1, *s2;
{
   register char *os1;

   os1 = s1;
   while (*s1++ = *s2++);
   return(os1);
}

int p_strlen(s)
register char *s;
{
   register n;

   n = 0;
   while (*s++)
      n++;
   return(n);
}

void p_bzero(p, n)
register char *p;
register n;
{
   while (--n >= 0)
      *p++ = 0;
}
1832.15More infoUTRTSC::VDBURGChange mode to PANICThu Mar 27 1997 01:506
    I found some reference to the unload problem:
    
    I link in the module SYS$DOINIT from STARLET.OLB, but for real dynamic
    unloading SYS$DOINIT_UNL is needed which is not provided.
    
    Jur.