From:	CSBVAX::MRGATE!nagy%warner.hepnet@LBL.Gov@SMTP 16-APR-1988 21:10
To:	ARISIA::EVERHART
Subj:	REMOTEDCL - execute DCL commands on DECnet nodes and ...


Received: from LBL.Gov by KL.SRI.COM with TCP; Thu 14 Apr 88 07:13:46-PDT
Received: from warner.hepnet by LBL.Gov with VMSmail ;
	Thu, 14 Apr 88 07:06:02 PDT
Date:    Thu, 14 Apr 88 07:06:02 PDT
From:     nagy%warner.hepnet@LBL.Gov (Frank J. Nagy, VAX Wizard & Guru)
Message-Id: <880414070602.20a05302@LBL.Gov>
Subject: REMOTEDCL - execute DCL commands on DECnet nodes and ...
To:       Info-VAX@kl.sri.com
X-ST-Vmsmail-To: INFO_VAX

I have the REMOTEDCL.COM procedure stored in my login area on all the VAXes
I deal with on our network.  We normally setup proxy logins between these
systems.  This allows me to define a RDCL command to invoke this
procedure to execute DCL on a remote system without having to do a
SET HOST to that system (see the help information at the end of the
command procedure).  The CLUSTERNODES program (sources are included,
the REMOTEDCL.COM procedure RUNs this program from RDCS$EXE - this should
be changed for your site) is used to generate a list of all the current
VAXCluster nodes into a DCL symbol.  REMOTEDCL allows a single DCL
command to be executed on any of:

	- a list of one or more DECnet nodes
	- all the nodes currently in the local VAXCluster
	- all the nodes currently in the local VAXCluster - except the
	  local node from which REMOTEDCL is being invoked
	- all the nodes in a remote VAXCluster (assumes CLUSTERNODES
	  must be present on the remote cluster)

SECURITY NOTE: This procedure uses DECnet task-to-task communications.
For security reasons, we disable use of the DECnet TASK object by the
default DECNET account and enable incoming and outgoing proxy access
for the TASK object.  (DECNET access was disabled by providing the
default DECNET account with a password and expliciting setting the
user to DECNET and password to its password on all objects for which
we wished to allow default DECnet access AND also enabling proxy
access as appropriate.  Doing this on FAL allows non-proxied users
access to our file base with permitting them to dump a procedure in
the default DECNET area and execute it with task-to-task communications.
In addition, the MAIL and PHONE objects use only the DECNET account
and do not use proxy logins).

Since I use proxy logins, all I have to do is have this procedure in
my login area on the destination nodes.  This can be made available
as a general DECnet object for all users by putting the procedure into
SYS$SYSTEM or by defining REMOTEDCL in the DECnet object database and
providing a file specification for a place other than SYS$SYSTEM.
I DO NOT SUGGEST YOU DO THIS UNLESS YOU ARE AWARE OF THE POSSIBLE
CONSEQUENCES AS NEITHER FERMILAB NOR I, ONLY YOU WILL BE RESPONSIBLE
IF SOMEONE DAMAGES YOUR SYSTEM USING THIS PROCEDURE.


= Frank J. Nagy   "VAX Guru & Wizard"
= Fermilab Research Division EED/Controls
= HEPNET: WARNER::NAGY (43198::NAGY) or FNAL::NAGY (43009::NAGY)
= BitNet: NAGY@FNAL
= USnail: Fermilab POB 500 MS/220 Batavia, IL 60510

........................ Cut between dotted lines and save ......................
$!..............................................................................
$! VAX/VMS archive file created by VMS_SHAR V-5.01 01-Oct-1987
$! which was written by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au)
$! To unpack, simply save and execute (@) this file.
$!
$! This archive was created by NAGY
$! on Thursday 14-APR-1988 08:15:19.81
$!
$! It contains the following 2 files:
$! REMOTEDCL.COM CLUSTERNODES.C
$!==============================================================================
$ Set Symbol/Scope=(NoLocal,NoGlobal)
$ Version=F$GetSYI("VERSION") ! See what VMS version we have here:
$ If Version.ges."V4.4" then goto Version_OK
$ Write SYS$Output "Sorry, you are running VMS ",Version, -
                ", but this procedure requires V4.4 or higher."
$ Exit 44
$Version_OK: CR[0,8]=13
$ Pass_or_Failed="failed!,passed."
$ Goto Start
$Convert_File:
$ Read/Time_Out=0/Error=No_Error1/Prompt="creating ''File_is'" SYS$Command ddd
$No_Error1: Define/User_Mode SYS$Output NL:
$ Edit/TPU/NoSection/NoDisplay/Command=SYS$Input/Output='File_is' -
        VMS_SHAR_DUMMY.DUMMY
f:=Get_Info(Command_Line,"File_Name");b:=Create_Buffer("",f);
o:=Get_Info(Command_Line,"Output_File");Set(Output_File,b,o);
Position(Beginning_of(b));Loop x:=Erase_Character(1);Loop ExitIf x<>"V";
Move_Vertical(1);x:=Erase_Character(1);Append_Line;
Move_Horizontal(-Current_Offset);EndLoop;Move_Vertical(1);
ExitIf Mark(None)=End_of(b) EndLoop;Position(Beginning_of(b));Loop
x:=Search("`",Forward,Exact);ExitIf x=0;Position(x);Erase_Character(1);
If Current_Character='`' then Move_Horizontal(1);else
Copy_Text(ASCII(INT(Erase_Character(3))));EndIf;EndLoop;Exit;
$ Delete VMS_SHAR_DUMMY.DUMMY;*
$ Checksum 'File_is
$ Success=F$Element(Check_Sum_is.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)+CR
$ Read/Time_Out=0/Error=No_Error2/Prompt=" CHECKSUM ''Success'" SYS$Command ddd
$No_Error2: Return
$Start:
$ File_is="REMOTEDCL.COM"
$ Check_Sum_is=187571372
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X$ verify = 'F$VERIFY(0)'
X$!.. REMOTEDCL.COM`009`009!Execute DCL command on remote node(s)
X$!.. Description/history at end of file.
X$ exit_status = 1`009`009! SS$_NORMAL
X$ finishflag = "#@#@COMMAND_IS_FINISHED$%$%"`009`009!Finish flag
X$ _Write := Write /Error=Write_Error
X$!
X$! Determine what mode we are in: if network job, we have been called
X$! from a remote system.  Other cases, check first parameter for
X$! special forms (lists, etc.).
X$!
X$ Goto 'F$Mode()'
X$Interactive:
X$ On Control_Y Then Goto Exit_Com
X$Batch:
X$ If p1 .eqs. "*" then $ GoTo VCNodes`009`009`009!VAXCluster nodes
X$ If p1 .eqs. "-*" then $ GoTo VCNodes`009`009`009!Remote Cluster nodes
X$ If F$Trnlnm(p1) .nes. "" then $ GoTo LogicalName`009!Node is logical name
X$ If F$Locate(",",p1) .lt. F$Length(p1) then $ GoTo NodeList
X$ If F$Extract( F$Length(p1)-3,3,p1) .eqs. "::*" then $ GoTo RemoteVC
X$ Read_Error_Text = "results"
X$ Write_Error_Text = "command"
X$!
X$! We are the master, call ourselves on the other side to do the work,
X$! feed the output back here where its captured and displayed.
X$!
X$ rmt_node = p1 - ":" - ":"
X$ Open /Read /Write /Error=Connect_Error  NetOut  'rmt_node'::"TASK=REMOTEDCL"
X$ _Write`009NetOut`009"0"
X$ _Write`009NetOut`009p2," ",p3," ",p4," ",p5," ",p6," ",p7," ",p8
X$Read_Loop:`009`009`009`009! Now read any results, Exit at Eof
X$ `009Read /End=Exit_Com /Error=Read_Error`009NetOut`009line
X$`009If line .eqs. finishflag then $ GoTo Exit_Com
X$`009_Write`009Sys$Output`009Line
X$ `009Goto Read_Loop
X$!
X$! Input selects a set of nodes: all or all remote (non-local) nodes
X$! in the VAXCluster which the local node is a member of (the VAXCluster).
X$!
X$VCNodes:`009`009`009!List is that of nodes in a VAXCluster
X$ If .not. f$getsyi( "CLUSTER_MEMBER") then $ GoTo VAXCluster
X$ Run Rdcs$Exe:ClusterNodes`009`009!Gets list of nodes in cluster
X$ localnode = f$getsyi("NODENAME")
X$ If p1 .eqs. "*" then p1 = cluster_nodes
X$ If p1 .eqs. "-*" then -
X`009p1 = cluster_nodes - (localnode + ",") - ("," + localnode)
X$!
X$! General processing for a list of nodes where P1 is the list of
X$! nodes separated by commas.  This procedure is recursively called
X$! for each separate node.
X$!
X$NodeList:`009`009`009`009!P1 is list of logical nodes
X$ thisproc = F$Environment( "PROCEDURE")
X$Nodes_Loop:`009`009`009`009!List of nodes in p1
X$`009IF p1 .eqs. "" THEN $ GoTo Exit_Com
X$`009node = F$Element( 0, ",", p1)`009!Get a node name
X$`009p1 = p1 - node - ","`009`009!Remove it from list
X$ `009_Write`009Sys$Output`009"!!!!! Node ",node
X$`009@'thisproc'`009'node'`009'p2' 'p3' 'p4' 'p5' 'p6' 'p7' 'p8'
X$`009GoTo Nodes_Loop
X$!
X$! Here is node name is a logical name...$
X$!
X$LogicalName:
X$ names = F$Trnlnm(p1,,,,,"MAX_INDEX")
X$ If names .gt. 1 Then $ GoTo NameList
X$ p1 = F$Trnlnm(p1)
X$ GoTo NodeList
X$!
X$! Here the node name is a logical name which is a search list (as
X$! opposed to a comma list) of nodes.
X$!
X$NameList:`009`009`009`009!P1 is logical name search list of nodes
X$ thisproc = F$Environment( "PROCEDURE")
X$ name = 0
X$NamesLoop:
X$`009If name .gt. names then $ GoTo Exit_Com
X$`009node = F$Trnlnm( p1,,name)`009!Get a node name
X$`009name = name + 1`009`009`009!Advance to next equivalence name
X$`009If node .eqs. "" then $ GoTo NamesLoop
X$ `009_Write`009Sys$Output`009"!!!!! Node ",node
X$`009@'thisproc'`009'node'`009'p2' 'p3' 'p4' 'p5' 'p6' 'p7' 'p8'
X$`009GoTo NamesLoop
X$!
X$! Nearly the biggest kluge of all: specifies all the nodes of a remote
X$! VAXCluster (i.e. a cluster the local node is *not* a member of).
X$!
X$RemoteVC:`009`009`009!Do all nodes in a remote VAXCluster
X$ rmt_node = p1 - "::*"
X$ Open /Read /Write /Error=Connect_Error  NetOut  'rmt_node'::"TASK=REMOTEDCL"
X$ _Write`009NetOut`009"*"
X$ _Write`009NetOut`009p2," ",p3," ",p4," ",p5," ",p6," ",p7," ",p8
X$ GoTo Read_Loop
X$! 
X$! Network process called by a remote system to do something.
X$! This is the slave to accept the command, execute it, capture
X$! the output from the command and sent same back to the master.
X$!
X$Network:
X$ Read_Error_Text = "command"
X$ Write_Error_Text = "results"
X$ rmt_node = f$extract(0,f$locate("::",f$trnlnm("SYS$NET")),-
X`009`009`009f$trnlnm("SYS$NET"))
X$ Open /Read /Write /Error=Connect_Error`009NetIn`009Sys$Net:
X$ _Read := Read /Error=Read_Error /End=Exit_Com
X$ _Read`009`009NetIn`009XType
X$ If XType .eqs. "+" then $ GoTo SkipComFile
X$ _Read`009`009NetIn`009Command
X$ If XType .eqs. "*" then $ _Write  NetIn  "!!!!! Node ",f$getsyi("NODENAME")
X$ Open /Write`009Com_File`009Sys$Scratch:RemoteDCL.Tmp
X$ file_spec = f$search("Sys$Scratch:RemoteDCL.Tmp")
X$ Write Com_File "$ ",command`009`009!Write command to a file for executing
X$ Close Com_File
X$SkipComFile:
X$ Set NoOn
X$@Sys$Scratch:RemoteDCL.Tmp/Output=Sys$Scratch:RemoteDCL.Log
X$ If XType .eqs. "0" then $ delete/log 'file_spec'
X$ file_spec = f$search("Sys$Scratch:RemoteDCL.Log")
X$ Set On
X$ Open /Read /Error=Log_Error`009Tell_Log`009'file_spec'
X$Write_Loop:
X$ `009Read /End=Write_Done`009Tell_Log Line
X$ `009_Write`009`009`009NetIn`009 Line
X$ `009Goto Write_Loop
X$Write_Done:
X$ Close Tell_Log
X$ Delete/Log 'file_spec'
X$ IF XType .eqs. "*" then $ GoTo NextNodes
X$ _Write`009NetIn`009 finshflag
X$ Goto Exit_Com
X$!
X$! Special format of slave for the additional nodes in a remote VAXCluster.
X$! The command procedure already exists, so just invoke this procedure
X$! (again) as a slave on each of the other (each for this one) nodes in
X$! this VAXCluster.  Now we act as a master to those slaves, but we just
X$! pass the output back to the original master (ain't it a kluge?).
X$!
X$NextNodes:
X$ Run Rdcs$Exe:ClusterNodes`009`009!Gets list of nodes in cluster
X$ localnode = f$getsyi("NODENAME")
X$ cluster_nodes = cluster_nodes - (localnode + ",") - ("," + localnode)
X$ thisproc = F$Environment( "PROCEDURE")
X$RmtVC_Loop:`009`009`009`009!List of nodes in p1
X$`009IF cluster_nodes .eqs. "" THEN $ GoTo RmtVC_Exit
X$`009node = F$Element( 0, ",", cluster_nodes)`009!Get a node name
X$`009cluster_nodes = cluster_nodes - node - ","`009!Remove it from list
X$ `009_Write`009NetIn`009"!!!!! Node ",node
X$`009Open /Read /Write /Error=Connect_Error  NetOut  'node'::"TASK=REMOTEDCL"
X$`009_Write`009NetOut`009"+"
X$RmtVC_Read_Loop:`009`009`009! Now read any results, Exit at Eof
X$`009 `009Read /End=RmtVC_Read_Exit /Error=Read_Error`009NetOut`009line
X$`009`009If line .eqs. finishflag then $ GoTo RmtVC_Read_Exit
X$`009`009_Write`009NetIn`009Line
X$`009 `009Goto RmtVC_Read_Loop
X$RmtVC_Read_Exit:
X$`009Close`009NetOut
X$`009GoTo RmtVC_Loop
X$RmtVC_Exit:
X$ Delete/Log 'file_spec'
X$ _Write`009NetIn`009 finshflag
X$ Goto Exit_Com
X$!
X$! **** Error Handlers
X$!
X$Read_Error:
X$  Exit_Status = $Status
X$  Write Sys$Error "%RemoteDCL-F-Read, Error reading ",Read_Error_Text,-
X`009`009" from remote system ",rmt_node
X$  Goto Exit_Com
X$Write_Error:
X$  Exit_Status = $Status
X$  Write Sys$Error "%RemoteDCL-F-Write, Error writing ",Write_Error_Text,-
X`009`009" to remote system ",rmt_node
X$  Goto Exit_Com
X$Connect_Error:
X$  Exit_Status = $Status
V$  Write Sys$Error "%RemoteDCL-F-Connect, Failed to connect to remote system ",
X-
X`009`009rmt_node
X$  Goto Exit_Com
X$VAXCluster:
X$  Write Sys$Error "%RemoteDCL-F-NotCLuster, not a VAXCluster member"
X$EXIT_COM:`009`009`009`009!** All done
X$ Set NoOn
X$ Close /NoLog`009NetIn
X$ Close /NoLog`009NetOut
X$ Close /NoLog`009Tell_Log
X$ EXIT`009F$VERIFY(verify).OR.exit_status
X$!=============================================================================
X$!+ RMTDCL
X$! Execute a single DCL command on one or more remote nodes using DECnet.
X$! The REMOTEDCL.COM procedure must be located in the SYS$LOGIN area on
X$! both the local and remote nodes.  The RMTDCL command can then be defined:
X$!`009$ RMT*DCL :== @SYS$LOGIN:REMOTEDCL
X$!
X$! To execute command on a single node:
X$!`009$ RMT  node  command...
X$! where node can be just a node name or node name and access control
X$! string (as in ANODE"USER PASS", this must be entered on the command
X$! line as "ANODE""USER PASS"""; the extra "'s are needed by DCL).  See
X$! below for a special form for handling remote VAXClusters.
X$!
X$! To execute the command sequentially on several remote nodes:
X$!`009$ RMT  node,node,...   command...
X$!
X$! The list of node names can be specified in a logical name:
X$!`009$ RMT  log-name  command...
X$! where log-name translates to node,node,... (the logical name can
X$! have the node defined as "node,node,node" - a single equivalence
X$! string or as a search list (the "" are not used around the list of
X$! nodes on the DEFINE or ASSIGN command).
X$!
X$! And, on a VAXCluster, all the nodes of the VAXCluster can be specified
X$! by:
X$!`009$ RMT  *  command...
X$! or just the remote VAXCluster nodes (all except the local node) by:
X$!`009$ RMT  -*  command...
X$! Also, all the nodes of a remote VAXCluster (the local node is NOT part
X$! of the target VAXCluster) can be specified by:
X$!`009$ RMT  node::*  command...
X$! The "::*" are required part of the syntax.  If any of these VAXCluster
X$! forms are used and the selected node is not a VAXCluster member, an
X$! error message will result.
X$!-
X$!=============================================================================
X$! Modifications:
X$!  03-Mar-88`009FJN`009Created
X$!  08-Mar-88`009FJN`009Gotten working
$ GoSub Convert_File
$ File_is="CLUSTERNODES.C"
$ Check_Sum_is=2121550507
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X#module  ClusterNodes  "V1.0"
X
X/*
X **********************************************************************
X **********************************************************************
X ****`009`009`009`009`009`009`009`009   **** 
X ****`009`009`009`009`009`009`009`009   **** 
X ****`009      `009EPICURE Beamline Control System`009`009`009   **** 
X ****`009`009Copyright (c) Fermilab, 1987`009`009`009   **** 
X ****`009`009`009`009`009`009`009`009   **** 
X ****        `009Get list of VAXCluster nodes for DCL`009           **** 
X ****`009`009`009`009`009`009`009`009   **** 
X ****`009`009`009`009`009`009`009`009   **** 
X **********************************************************************
X **********************************************************************
X
X Functional Description:
X    This program supplements the DCL lexical function F$GETSYI by
X    returning a list of the node names in the VAXCluster in a DCL
X    local symbol.  
X
X Environment:
X    General purpose VMS utility.
X
X Published Information:
X    None
X
X Change Requests:
X =============================================================================
X Author: Frank J. Nagy`009`009Fermilab Research Division EED/Controls
X Modification History:
X
X V1.0`00901-May-87  FJN`009Created for MULTISUBMIT.COM to allow removal of the
X`009`009`009built-in VAXCluster node name list.
X*/
X
X/******************
X * Include Files: *
X ******************/
X#include  vaxtypes`009`009`009/* VAX C Type extensions */
X#include  descrip`009`009`009/* VAX Descriptors */
X#include  descrip2`009`009`009/* Additional descriptor defs. */
X#include  ssdef`009`009`009`009/* System status codes */
X#include  syidef`009`009`009/* System information codes */
X#include  libclidef`009`009`009/* CLI callback definitions */
X
X/*********************************
X * Global definitions and types: *
X *********************************/
Xglobalvalue LIB$_INSVIRMEM;`009`009/* Insufficient virtual memory */
X
X/********************************
X * Local definitions and types: *
X ********************************/
Xtypedef unsigned long status;`009`009/* Condition code status type */
X
X#define`009NODENAME_LEN`00916`009`009/* Length of node name string */
X#define`009MAX_NODES`009256`009`009/* Maximum # of nodes in VAXCluster */
X
X/***********************
X * Global Own Storage: *
X ***********************/
X
X/*****************************
X * Module Local Own Storage: *
X *****************************/
Xstatic char nodes[MAX_NODES][NODENAME_LEN]; /* Storage for node names */
Xstatic int number_of_nodes;`009`009/* Number of nodes in VAXCluster */
X
Xstatic long csid = -1;`009`009`009/* Cluster system id, wildcard */
Xstatic unsigned short returned;`009`009/* Length of returned string */
Xstatic $DESCRIPTOR0( d_proto);`009`009/* Descriptor for node string */
X
Xstatic readonly $DESCRIPTOR( d_symbol, "CLUSTER_NODES");
Xstatic readonly $DESCRIPTOR( d_null, "");
X
Xstatic struct {`009`009`009`009/* Item list for $GETSYI */
X    unsigned short buflen;`009`009/* Buffer length */
X    unsigned short itemcode;`009`009/* Item code */
X    char *buffer;`009`009`009/* Pointer to return buffer */
X    unsigned short *retlen;`009`009/* Pointer to return length */
X    int listterm;`009`009`009/* List terminator */
X    } items = { NODENAME_LEN, SYI$_NODENAME, NULL, &returned, 0 };
Xstatic status iosb[2];`009`009`009/* $GETSYI I/O status block */
X
X/**********************************************
X * Global Procedure and Function definitions: *
X **********************************************/
Xextern status lib$getsyi();`009`009/* Get system information */
Xextern status sys$getsyiw();`009`009/* .. ditto .. */
Xextern void lib$signal();`009`009/* Signal error */
X
Xextern void exit();`009`009`009/* Program exit */
Xextern int strlen();`009`009`009/* Length of NUL-terminated string */
Xextern void strcat();`009`009`009/* String concatenation routine */
Xextern char *malloc();`009`009`009/* Memory allocator */
X
X`012
X/* Main Program
X This program is executed by a RUN command.  It uses a wildcard $GETSYI
X to gather the node names of the current members of the VAXCluster.  These
X are then returned in the local DCL symbol CLUSTER_NODES as a list of
X names separated by commas.
X
X If the current system is not a VAXCluster member, CLUSTER_NODES is set
X to the null string.
X*/
X
Xmain( )
X{
Xregister status sts;
Xregister int nnn;`009`009`009/* Node name number */
X
X/*
X First, a quick check that we are part of a VAXCluster.
X*/
Xsts = lib$getsyi( &SYI$_CLUSTER_MEMBER, &csid);
XSIGNAL_FAILURE( sts);
X
Xif ($VMS_FAILURE( csid))
X    {
X    /*
X     Not part of a VAXCluster, set symbol CLUSTER_NODES to null string and
X     exit prematurely.
X    */
X    sts = lib$set_symbol( &d_symbol, &d_null, &LIB$K_CLI_LOCAL_SYM);
X    SIGNAL_FAILURE( sts);
X
X    exit();
X    }
X
X/*
X Now get the number of nodes in the VAXCluster (used later).
X*/
Xsts = lib$getsyi( &SYI$_CLUSTER_NODES, &number_of_nodes);
XSIGNAL_FAILURE( sts);
X
X/*
X Now do wildcard node name look up with $GETSYI and build table of node
X names.
X*/
X
Xitems.buffer = nodes[0];`009`009    /* Initialize buffer pointer */
X
Xfor (csid = -1, nnn = 0;;)`009`009    /* Wildcard node scan */
X    {
X    sts = sys$getsyiw( 1, &csid, 0, &items, &iosb, 0, 0);
X    if ($VMS_SUCCESS( sts))
X`009sts = iosb[0];`009`009`009    /* Use IOSB status */
X    if ($VMS_SUCCESS( sts))
X`009{
X`009nodes[nnn][returned] = '\0';`009    /* Add NUL terminator */
X`009items.buffer = nodes[++nnn];
X`009}
X    else if (sts == SS$_NOMORENODE)
X`009break;
X    else
X`009lib$signal( sts);
X    }
X
X/*
X Get some memory to build the list of node names (separated by commas)
X for the DCL symbol value.
X*/
Xif ((d_proto.dsc$a_pointer = malloc( number_of_nodes*NODENAME_LEN)) == NULL)
X    lib$signal( LIB$_INSVIRMEM);
X*d_proto.dsc$a_pointer = '\0';`009`009/* Init to empty string */
X
Xfor (nnn = 0; nnn < number_of_nodes; nnn++)
X    {
X    if (nnn > 0)
X`009strcat( d_proto.dsc$a_pointer, ",");`009/* Add "," to previous... */
X
X    strcat( d_proto.dsc$a_pointer, nodes[nnn]);
X    }
X
Xd_proto.dsc$w_length = strlen( d_proto.dsc$a_pointer);
X
X/*
X Set the DCL symbol and exit out end...
X*/
Xsts = lib$set_symbol( &d_symbol, &d_proto, &LIB$K_CLI_LOCAL_SYM);
XSIGNAL_FAILURE( sts);
X
X}
$ GoSub Convert_File
$ Exit
