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

Conference noted::hackers_v1

Title:-={ H A C K E R S }=-
Notice:Write locked - see NOTED::HACKERS
Moderator:DIEHRD::MORRIS
Created:Thu Feb 20 1986
Last Modified:Mon Aug 03 1992
Last Successful Update:Fri Jun 06 1997
Number of topics:680
Total number of notes:5456

275.0. "How does TELL tell?" by KRYPTN::CROWELL () Tue Jul 29 1986 13:11

    How does the TELL.COM command file work to force monitor commands
    to another system.
    
    Why does it fail on some systems?
    
    What does -- NODE::"TASK=TELL" -- signify? Does the other system
    need a task TELL or just the command file TELL.COM
    
    Jon
    
T.RTitleUserPersonal
Name
DateLines
275.1TASK and TELLTUNDRA::HARRIMANTue Jul 29 1986 19:1057
    TELL is a really simple concept if you understand how the TASK network
    object does it's stuff. Anybody correct me if I'm wrong, but ere
    goes...
    
    
    TASK is a network object which is designed to allow remote execution
    of DCL commands (via a command procedure) from another system.
    basically how TASK works is when you issue a command like that
    NODE"access"::"TASK=COMFILE" then COMFILE.COM exists already on
    the other system. COMFILE.COM is then executed as a DCL procedure
    using a network (not interactive) process.
    
    What TELL, NEWTELL, NETDCL and others do are to first check for
    the existence of themselves on the remote node. You no doubt noticed
    that they have two sections of code (sender and receiver).
    
    If the procedure does not exist (usually inthe DECNET directory)
    then TELL copies itself there. Then the issuing procedure (the one
    you are running) then goes through the NODE::"TASK=TELL" stuff,
    which invokes the remote process.
    
    Now the fun part. the remote process starts up and figures out that
    it is a network process, so it goes to the network side of the code.
    The network side of the code simply opens SYS$NET for output (so
    all output from the process goes to the calling node) and goes into
    a loop which waits for the other process (you) to send it commands.
    
    Your process, by the way, is in the other loop (the one which is
    is sending commands). You can do this for all DCL and foreign commands.
    
    Some interesting side-effects. Everything you do is recorded in
    a NETSERVER.LOG somewhere. We all know what happens to those. If
    you ever try running something like an applications program or a
    compiler (or an interpreter) you will have many many problems since
    the process is not an interactive process. I once tried that attempting
    to run LISP through NETDCL and I filled up someone's system disk
    with a NETSERVER.LOG which simply repeated ad infinitum:
    
    no command input file
    no command input file
    .
    .
    .
    
    the last thing you asked about (why it fails on some systems) is
    that internal DEC policy towards the use of TASK is not very positive,
    considering the obvious security problems.
    
    The "accepted" solution is to remove the object TASK from the network
    object table. This gives you the "network object is unknown at remote
    node" error. If you get this error then the system you are attempting
    to probe is probably a manufacturing system or the system mangler
    is smarter than you think.
    
    sorry for the excess verbosity but this is the story as it goes.
    
    -pjh
275.2TELL.COMVAXUUM::DYERWage PeaceWed Jul 30 1986 16:37317
$ V := 'F$VERIFY( F$LOGI("DEBUG$COM") + F$LOGI("DEBUG$TELL") )
$ TELL_TYPE = "VMS"	!we are VMS
$ TELL_VERSION = 9	!use negative for debugging new version
$ !
$ !=========================================================================
$ !
$ ! Execute DCL command(s) in a remote network job - originally Tim Halvorsen
$ !
$ !	TELL :== @TELL  or, on V4: TELL :== @[wherever]TELL
$ !
$ !	P1 = Node name
$ !	P2-8 = (OPTIONAL) A DCL command to be executed
$ !	[ If you don't supply DCL command, you are prompted for commands.
$ !	  In this mode, you can type tilde (~) to enter local commands for
$ !	  your system without breaking the remote connection.  After typing
$ !	  ~ type ? for help on extra options (Sending text files and logging) ]
$ !
$ ! Modifications
$ !  DEC  8/15/84  Assign SYS$ERROR so we see error messages
$ !	   v 2	   and test for versions (auto update)
$ !		   Add local commands (with tilde ~) including:
$ !			? (help) and
$ !			@textfile, |logfile, local commands
$ !		   (still needs to be able to run interactive programs)
$ !
$ !  DEC  8/27/84  Recover & run if remote tell is old version, 
$ !	   v 3	   and update copy fails
$ !
$ !  DEC  9/6/84   COPY with protection W:RE.
$ !	   V 4	   Turn verify off on remote node.
$ !		   Leave a trail of nodes tell was copied from.
$ !		   Send file TELL$INIT: to remote, if it exists.
$ !		   As an example, TELL$INIT could point to a file containing:
$ !			write sys$output "Remote VMS ",f$getsyi("version")
$ !			dir :== dir/size/date/prot
$ !		   This would tell you the remote VMS version, and redefine 
$ !		   the DIR command to show more information
$ !	NOTE: write sys$output only works on V4 systems.  So, for a TELL$INIT 
$ !	command that works when you talk to V3.x or V4 systems, use:
$ !		write tell_link "Remote VMS ","''f$getsyi(""version"")'"
$ !
$ !  DEC  9/11/84  Fix LOG_FILE_NAME.DAT bug (wrong file name created)
$ !	   V 5	   Fix assign/user sys$input of local commands
$ !
$ !  DEC  9/13/84  Let ~local_cmd execute, but not prompt for more commands
$ !        V 6
$ !
$ !  RSD  10/9/84  Fix interactive command section
$ !	   V 7
$ !
$ !  JAS  5/13/85  Support different system types
$ !
$ !=========================================================================
$!
$! Some initial stuff
$!
$ v2 = v
$ tell_file := tell.com
$ no_log_sw = ""
$ if f$extract(0,2,f$getsyi("version")) .eqs. "V3" then goto skip_v4_features
$	tell_file = f$environment("procedure")  !VMS V4 feature
$	no_log_sw = "/nolog"			!VMS V4 feature
$!
$skip_v4_features:
$!
$ tell_file_name = f$parse(tell_file,,,"NAME")
$!
$! Network server or Local?
$!
$	if f$mode() .eqs. "NETWORK" then goto network
$!
$!==================================================
$!
$!	Local subroutines
$!
$!==================================================
$!
$	if p1 .eqs. "" then read/prompt="Node: " sys$command p1
$	nodespec = p1 - "::"
$	nodename = f$extract(0,f$locate("""",nodespec),nodespec)
$ !	if nodename .eqs. nodespec then nodespec = nodespec + """""" !no proxies
$	local_at = "F"
$	log_file = "F"
$	log_file_name = ""
$	remote_tell_exists = "F"
$	remote_tell_type = "VMS"
$	temp_zzz = "F"
$	tell_where := sys$login:telltemp.zzz;0
$	tell_init = "F"
$	new_remote = "F"
$	local = " " + f$sea(f$logi("TELL$INIT"))
$	if local .nes. " " then tell_init = "T"
$	on warning then continue
$	on error then goto exit2
$	on control_y then goto exit2
$	close/err=10$	tell_server
$10$:
$	open/read/write tell_server 'nodespec'::"TASK=''TELL_file_name'"/error=open_failure
$	remote_tell_exists = "T"
$	on error then goto exit
$	on control_y then goto exit
$	on warning then goto exit
$sync_start:
$	read tell_server record
$	if f$locate("REMOTE SYSTEM TYPE:",record) .lt. f$len(record) then goto save_server_type
$	if f$locate("REMOTE TELL VERSION:",record) .lt. f$len(record) then goto check_server_ver
$	if record .eqs. "ABOUT_TO_ISSUE_READ" then goto new_remote_server
$	goto sync_start
$
$flush_output:
$	read tell_server record
$	if record .eqs. "ABOUT_TO_ISSUE_READ" then goto send_command
$	if log_file then write to_log record
$!f$extract(0,255,record), f$extract(255,255,record)
$	write sys$output record
$!f$extract(0,255,record), f$extract(255,255,record)
$	goto flush_output
$
$send_command:
$	if p2 .nes. "" then goto single_command
$	if tell_init then goto local_at_file
$	if local_at then       read/error=no_at_file/end=done_at_file tmp_at record
$	if .not. local_at then read sys$command record /prompt="''nodename' ''f$environment("prompt")'" /end=exit
$	test_record	:= 'record
$	if test_record .eqs. "EXIT" then goto exit
$	if f$len(test_record) .gt. 0 .and. -
		f$locate("~", test_record) .eq. 0 then goto local_command_start
$	if log_file then write to_log "$ ",record
$	write tell_server record
$	goto flush_output
$
$local_command_start:
$	if f$len( record ) .le. 1 then goto local_command
$		local = f$extract( 1,999,record )  !typed ahead command
$		multi_local = "F"
$		goto local_1
$local_command:
$	local = ""
$	local_nodename = F$LOGICAL("SYS$NODE") - "_" - "::"
$	read sys$command local /prompt="~''local_nodename' ''f$environment("prompt")'" /end=local_1
$	multi_local = "T"
$local_1:
$	if f$len( local ) .eq. 0 then write sys$output ""
$	if f$len( local ) .eq. 0 then goto send_command
$	if f$locate("?", local) .eq. 0 then goto local_help
$	if f$locate("@", local) .eq. 0 then goto local_at_file
$	if f$locate("|", local) .eq. 0 then goto record_file
$	assign/user'no_log_sw' 'f$logi("sys$command") sys$input
$	set noon
$	V2 = F$VERIFY( V2 )	!restore verify to what user wants
$ 'local'
$	V2 := 'F$VERIFY( 0 )	!turn verify off for this com file
$	set on
$	if multi_local then goto local_command
$	goto send_command	!it's just one command
$
$local_at_file:
$	open/read/error=no_at_file tmp_at 'f$extract(1,999, local) 
$	local_at = "T"
$	tell_init = "F"
$	goto send_command
$
$done_at_file:
$	local_at = "F"
$	close tmp_at
$	goto send_command
$no_at_file:
$	write sys$output "Can't read file: ''local'"
$	local_at = "F"
$	tell_init = "F"
$	goto send_command
$
$record_file:
$	if local .eqs. "|" then goto done_log_file
$	if log_file then close to_log  !make sure it's closed first
$	log_file_name = f$extract(1,999, local) 
$	open/write/error=no_log_file to_log 'log_file_name
$	log_file = "T"
$	goto send_command
$
$done_log_file:
$	if log_file then close to_log  !only if it's already open
$	log_file = "F"
$	log_file_name = ""
$	goto send_command
$no_log_file:
$	write sys$output "Can't write file: ''local'"
$	log_file = "F"
$	log_file_name = ""
$	goto send_command
$
$local_help:
$	WRITE SYS$OUTPUT "      @FILE  sends text file to the remote system
$	WRITE SYS$OUTPUT "      |FILE  records screen output to file
$	WRITE SYS$OUTPUT "      |      turns recording off
$	WRITE SYS$OUTPUT "             anything else is executed locally
$	WRITE SYS$OUTPUT "             (to do @COMfile locally, type a space first)
$	WRITE SYS$OUTPUT "      ^Z     to exit
$	if .not. log_file then WRITE SYS$OUTPUT "      [no log file active]"
$	if log_file then WRITE SYS$OUTPUT "      [logging to file: ''log_file_name']"
$	goto local_command
$
$single_command:
$	command := "''p2' ''p3' ''p4' ''p5' ''p6' ''p7' ''p8'"
$	write tell_server command
$single_flush:
$	read tell_server record
$	if record .eqs. "ABOUT_TO_ISSUE_READ" then goto exit
$	write sys$output record
$	goto single_flush
$
$save_server_type:
$	remote_tell_type = f$extract(20,99,record)
$	goto sync_start
$
$check_server_ver:
$	remote_tell_version = f$extract(21,99,record)
$	if remote_tell_type .nes. tell_type then goto flush_output
$	if remote_tell_version .eq. tell_version then goto flush_output
$	if remote_tell_version .gt. tell_version then goto need_new_tell
$new_remote_server:
$!!!	close tell_server  !need a new version remotely
$!!!	wait 0:0:1	! Wait for remote FAL process to get ready
$	write sys$output "Remote TELL is old version: ''remote_tell_version'"
$	goto open_failure
$
$need_new_tell:
$	write sys$output "Remote TELL is newer version: ''remote_tell_version'"
$	goto flush_output
$
$open_failure:
$	inquire q "Want to copy this version of TELL.COM to target? "
$	if .not. q then goto flush_output	! try it
$	on warning then goto exit2
$	Write Sys$Output "Replicating TELL version ''Tell_version' to node ''nodename'"
$!
$!	Create tmp file to tell where we came from
$!
$ 	open/write where_is 'tell_where
$ 	temp_zzz = "T"
$ 	node_name = f$logi("sys$node")
$ 	if f$extra(0,1,node_name) .eqs. "_" then -
!		node_name = f$extra(1,999,node_name)
$ 	write where_is "$! Copied from ''node_name' on ''f$time()'"
$ 	close where_is
$ !
$	copy 'tell_file','tell_where' 'nodespec'::'tell_file_name'.COM;0 
$!/prot=w:RE	!highest version
$!
$	copy_stat = $status
$	delete 'tell_where'
$	temp_zzz = "F"
$!
$	if .not. copy_stat then goto Copy_fail_ok !copy failed, but old version is there
$	if remote_tell_exists then close tell_server !copy worked, close old version
$	wait 0:0:1	! Wait for remote FAL process to get ready
$	open/read/write tell_server 'nodespec'::"TASK=''TELL_file_name'"
$	new_remote = "T"
$	on error then goto exit
$	on control_y then goto exit
$	on warning then goto exit
$sync_start:
$	read tell_server record
$	if f$locate("REMOTE TELL VERSION:",record) .eq. f$len(record) then goto sync_start
$	on warning then goto exit
$	goto flush_output
$
$Copy_fail_ok:
$	Write Sys$Output "Can't update Remote TELL, continuing..."
$	on warning then goto exit
$	goto flush_output
$
$exit:
$	set noon
$	write tell_server "LOGOUT/BRIEF"
$	if log_file then close to_log
$	if local_at then close tmp_at
$exit2:
$	if temp_zzz then close where_is/error=e1
$e1:
$	if temp_zzz then delete 'tell_where'
$	close/error=e2 tell_server
$e2:
$	V = F$VERIFY( V )
$	exit
$!
$!===================================================
$!
$!	Network server piece
$!
$!===================================================
$
$network:
$	open/read/write tell_link sys$net
$	set noon
$	tell_verify = 'f$verify(0)'
$	V2 = 0	!initially turns off verify for command echo
$	define'no_log_sw' sys$error   tell_link:	!need to see errors
$	define'no_log_sw' sys$output  tell_link:
$	write tell_link "REMOTE SYSTEM TYPE: ''tell_type'"
$	write tell_link "REMOTE TELL VERSION: ''tell_version'"
$server_loop:
$	write tell_link "ABOUT_TO_ISSUE_READ"
$	read tell_link tell_string /end_of_file=server_exit /error=server_exit
$	V2 = F$VERIFY( V2 )	!restore verify to what user wants
$ 'tell_string'
$	V2 := 'F$VERIFY( 0 )	!turn verify off for this com file
$	goto server_loop
$server_exit:
$	if tell_verify then set verify
$	close tell_link
$	deassign sys$output
$!
$!=========================================================================
$!
$! Where did this copy of TELL come from?
$!
275.3NETDCL.COMVAXUUM::DYERWage PeaceWed Jul 30 1986 16:3890
$ 	IF f$mode() .EQS. "NETWORK" THEN GOTO network
$	! If we are a network object, respond properly
$!
$ 	IF p1 .EQS. "" THEN READ/PROMPT="Node: " sys$command p1
$	nodespec = p1 - "::"
$ 	nodename = f$extract(0,f$locate("""",nodespec),nodespec)
$!
$ 	ON WARNING THEN CONTINUE
$ 	CLOSE/ERR=open_server dcl_server
$	! Just in case it was open
$!
$open_server:
$	OPEN/READ/WRITE dcl_server 'nodespec'::"0=NETDCL"/ERROR=open_failure
$	ON WARNING THEN GOTO exit	
$!	Open the DECnet link to our DCL server
$!
$flush_output:
$	 READ dcl_server record
$ 	 IF record .EQS. "SEND_ME_A_COMMAND" -
	    THEN GOTO send_command
$!	    ELSE
$	 	 WRITE sys$output record
$ 		 GOTO flush_output		
$!
$! 	 Loop until we get rid of all output
$!	 the dcl server has passed back.
$!
$send_command:
$ 	IF p2 .NES. "" THEN GOTO single_command
$ 	READ sys$command record /PROMPT="DCL ''nodename'> " /END=exit
$ 	record	:= 'record
$ 	IF record .EQS. "EXIT" THEN GOTO exit
$!			       ELSE
$				    WRITE dcl_server record
$				    GOTO flush_output		
$! Send command to the node and get ready for the return onslaught
$
$single_command:
$ 	command := 'p2' 'p3' 'p4' 'p5' 'p6' 'p7' 'p8'
$	WRITE dcl_server command
$!	Once the command has been had, send it across to the server
$!
$single_flush:
$	READ dcl_server record
$ 	IF record .EQS. "SEND_ME_A_COMMAND"-
	   THEN GOTO exit
$!	   ELSE
$		WRITE sys$output record
$		GOTO single_flush
$!	On a single command, just exit as soon as all output has gone by
$!	and the server prompts us again..
$
$open_failure:
$ 	ON WARNING THEN EXIT
$ 	COPY/LOG rdf$com_library:netdcl.com 'nodespec'::
$ 	WAIT 0:0:1		
$	! Wait for remote FAL process to get ready
$!
$	OPEN/READ/WRITE dcl_server 'nodespec'::"0=NETDCL"
$	ON WARNING THEN GOTO exit
$	GOTO flush_output
$
$exit:
$	CLOSE dcl_server
$	EXIT
$
$network:
$!
$!	This section is what happens on the remote side of the DECnet
$!	link.
$!
$	OPEN/READ/WRITE dcl_link sys$net
$	SET NOON
$	dcl_verify = 'f$verify(0)'
$	DEFINE sys$output dcl_link:
$!	Open a channel to the sender, and redefine the default output device
$!
$server_loop:
$ 	WRITE dcl_link "SEND_ME_A_COMMAND"
$ 	READ dcl_link dcl_string /END_OF_FILE=server_exit /ERROR=server_exit
$ 	'dcl_string'
$ 	GOTO server_loop
$!	Issue a remote style prompt that they will know about, read in the 
$!	command, and execute it.
$!
$server_exit:
$ 	IF dcl_verify THEN set verify
$ 	CLOSE dcl_link
$ 	DEASSIGN sys$output
$	EXIT
275.4You sure this one works?PHENIX::SMITHWilliam P.N. (Wookie::) SmithWed Jul 30 1986 21:0316
    Umm, has anyone else tried this yet?  I keep getting 'network object
    is unknown at remote node' err I try to run this, even with a node
    that used to work on tell v7....  I suspect I've copied tell v9
    to MUSCAT (from whence I got v7), hope I didn't blow anyone away...
     Do you need special privs or anything to run this?
    
    P>S> (darn VT-100's with theirn-LK2 br! +) )
    P.S. Apogsoe aeetnes, the toklk tween NRO andT lgirs today, and
    I keep getting data overruns...
    
    Willie
    As I tried to say above, not only do VT-100s have non-LK-201 keyboards,
    but the network link between NRO and LTN can;t keep up with my flying
    fingers!  Need another couple of tin cans and some more sting guys!
      AAARRRGGGHHH!!!
    
275.5Try VMSJON::MORONEYMadmanThu Jul 31 1986 03:456
MUSCAT is running some form of UNIX (probably Ultrix) so all bets are off.
MUSCAT's TELL object is a program of some sort, not the .com file you
got.  Wonder who the UNIX hacker who wrote the UNIX tell is?  Anyway,
Try it on a VMS system.

-Mike
275.6I _did_ try VMS...PHENIX::SMITHWilliam P.N. (Wookie::) SmithThu Jul 31 1986 19:379
    I did try VMS system(s), PHENIX and NRLABS, neither of them would
    work, even tho I tried in both directions, and the copy was successful
    in each direction.  I kept getting 'network object unknown at remote
    node' errors.  Could you suggest a VMS node on which this is _known_
    to work?  I was just concerned about MUSCAT, as it looked like I
    had copied tell v9 _to_ it....
    
    Willie
    
275.7works for me...JON::MORONEYMadmanFri Aug 01 1986 01:397
re .6: NETDCL works fine on PHENIX, just tried it.  I ran the procedure
in note 3.  It has a logical name in it that points to the location of
the NETDCL procedure which has to be changed, otherwise it runs as is.

TELL also works on PHENIX.

-Mike
275.8MUSCAT; TELL V23THEBAY::MTHOMASThe Mad HackerFri Aug 01 1986 05:43622
    MUSCAT is 730 running Ultrix and the tell object is a program residing
    at /bin/tell (which is where you can't harm it.)  I have yet to
    see a version of VMS TELL V8 or later work properly with it.  But
    I am too busy to fix the version that I normally use.
    
    matt
    [Version 23 of TELL.COM follows]

$ V := 'F$VERIFY( F$LOGI("DEBUG$COM") + F$LOGI("DEBUG$TELL") )
$ TELL_VERSION = 23	!use negative for debugging new version
$!	-- documentation at end of file to speed processing --
$!
$! Some initial stuff
$!
$ v2 = v
$ tell_file := tell.com
$ no_log_sw = ""
$!
$ if f$extract(0,2,f$getsyi("version")) .eqs. "V3" then goto skip_v4_features
$	tell_file = f$environment("procedure")  !VMS V4 feature
$	no_log_sw = "/nolog"			!VMS V4 feature
$!
$skip_v4_features:
$!
$ tell_file_name = f$parse(tell_file,,,"NAME")
$	mail := $SYS$SYSTEM:MAIL
$	copy := copy/nolog
$	delete := delete/nolog
$!
$! Network server or Local?
$!
$	if f$mode() .nes. "NETWORK" then goto client_process
$!
$!===================================================
$!
$!	Network server piece
$!
$!===================================================
$
$network:
$	get_mail = "F"
$	open/read/write tell_link sys$net
$	set noon
$	V2 = 0	!initially turns off verify for command echo
$	define'no_log_sw' sys$error   tell_link:	!need to see errors
$	define'no_log_sw' sys$output  tell_link:
$	username = f$edit(f$getjpi("","USERNAME"),"COMPRESS,TRIM")
$	write tell_link "REMOTE TELL USER: ''username'"
$	write tell_link "REMOTE TELL VERSION: ''tell_version'"
$server_loop:
$	write tell_link "ABOUT_TO_ISSUE_READ"
$	read tell_link tell_string /end_of_file=server_exit /error=server_exit
$	tell_cmd = f$extract(0,f$locate(" ",tell_string),tell_string)
$	if tell_cmd .eqs."DO_GET_MAIL" then goto start_mail
$	if tell_Cmd .eqs."DO_FORWARD" then goto start_forwarding
$	if tell_cmd .eqs."DO_FILE" then goto start_fileing
$	if tell_cmd .eqs."DONE_MAIL" then goto done_with_mail
$	if get_mail then goto done_with_mail
$do_cmd:
$	V2 = F$VERIFY( V2 )	!restore verify to what user wants
$ 'tell_string'
$	V2 := 'F$VERIFY( 0 )	!turn verify off for this com file
$	goto server_loop
$start_mail:   
$	tell_string = f$edit(tell_string,"COMPRESS,TRIM")
$	to_address = f$extract(f$locate(" ",tell_string),999,tell_string)
$	get_mail = "T"
$	no_mail = "F"
$	doing_forward = "F"
$	doing_file = "F"
$	if f$search("MAIL_CMDS.TMP") .nes. "" then delete mail_cmds.tmp;*
$	if f$search("MAIL_LOG.TMP") .NES. "" THEN DELETE MAIL_LOG.TMP;*
$	open/write mail_cmds mail_cmds.tmp
$	write mail_cmds "$assign/user ''f$directory()'mail_log.tmp sys$output"
$	write mail_cmds "$!assign/user sys$command sys$input"
$	write mail_cmds "$!assign/user mail_log.tmp sys$error"
$	write mail_cmds "$   	mail"
$	write mail_cmds "dir newmail"
$	write mail_cmds "exit"
$	write mail_cmds "$! end"
$	close mail_cmds
$	submit/name="''username'_MAIL_GET" -
		/log='f$directory()''username'_mail_get.log -
		/noprint  mail_cmds.tmp
$!
$	sync 'username'_mail_get
$	last_mail_num = 0
$	open/read mail_log mail_log.tmp/error=error_mail_open
$read_mail_dir:     
$	if no_mail then goto eof_mail
$	read/error=eof_mail/end=eof_mail mail_log in_rec
$	write tell_link "''in_rec'"
$	in_rec = f$edit(in_rec,"COMPRESS,TRIM")
$	if f$locate("%E",in_rec) .Lt. f$length(in_rec) then no_mail = "T"
$	n = f$extract(0,f$locate(" ",in_rec),in_rec)
$	if (n .ge. 1) .and. (n .le. 99) then -
$		if (last_mail_num .lt. n) then -
$			last_mail_num = n
$	goto read_mail_dir
$error_mail_open:
$	write tell_link "No mail available"
$	no_mail = "T"
$	goto cont_eof_mail
$eof_mail:
$	close mail_log
$cont_eof_mail:
$	delete/nolog mail_*.tmp;*
$	open/write mail_cmds mail_cmds.tmp
$	write mail_cmds "$mail"
$	close mail_cmds
$	out_msg := "MAIL_DIR_DONE"
$	if no_mail then out_msg := "MAIL_EXIT"
$	if no_mail then get_mail = "F"
$	write tell_link "''out_msg'"
$	goto server_loop
$done_with_mail:     
$	open/append mail_cmds mail_cmds.tmp
$	write mail_cmds "EXIT"
$	write mail_cmds "$delete ''f$directory()'mail_*.tmp;*"
$	write mail_cmds "$delete ''f$directory()'*mail_get.*;*"
$	close mail_cmds
$	submit/name="''username'_MAIL_GET" -
		/log='f$directory()''username'_mail_get.log -
		/noprint  mail_cmds.tmp
$!
$	write tell_link "MAIL_EXIT"
$	get_mail = "F"
$	goto server_loop
$Start_forwarding:      
$	tell_string = f$edit(tell_string,"COMPRESS,TRIM")
$	CUR_LIST = f$extract(f$locate(" ",tell_string),999,tell_string)
$	open/append mail_cmds mail_cmds.tmp
$	write mail_cmds "dir newmail"
$	return = "write_forward"
$	type_list = "Forward"
$	ele_f_t = 1
$	goto get_list_ele
$Start_fileing:
$	tell_string = f$edit(tell_string,"COMPRESS,TRIM")
$	CUR_LIST = f$extract(f$locate(" ",tell_string),999,tell_string)
$	open/append mail_cmds mail_cmds.tmp
$	write mail_cmds "dir newmail"
$	return = "write_file"
$	type_list = "Fileing"
$	ele_f_t = 1
$	goto get_list_ele
$write_forward:
$	if ret_num .eq. -1 then goto done_forward
$	if (ret_num .gt. last_mail_num) -
	   .or. (ret_num .le. 0) then goto number_error
$	write mail_cmds "read ''ret_num'"
$	write mail_cmds "forward/noedit"
$	write mail_cmds "''to_address'"
$	write mail_cmds "Auto-forward via get_mail"
$!	write mail_cmds "delete"
$	goto get_list_ele
$Done_forward:          
$	close mail_cmds
$	goto server_loop
$write_file:
$	if ret_num .eq. -1 then goto done_file
$	if (ret_num .gt. last_mail_num) -
	   .or. (ret_num .le. 0) then goto number_error
$	write mail_cmds "read ''ret_num'"
$	goto get_list_ele
$done_file:
$	close mail_cmds
$	goto server_loop
$!
$number_error:
$	write tell_link "Message number ''ret_num' not found for ''type_list'"
$	goto get_list_ele
$!
$server_exit:
$	close tell_link
$	deassign sys$output
$	exit
$!
$Get_list_ele:
$	if (.not. ele_f_t) then goto ele_next_num
$	ele_next = 0
$	ret_num = 0
$	ele_f_t = 0
$ele_next_num:     
$	ret_num = F$ELEMENT(ele_NEXT,",",cur_list)
$	IF (ret_num .EqS. "") THEN goto ele_end_list
$	ele_NEXT = ele_NEXT + 1
$	goto 'return'
$ele_end_list:
$	ret_num = -1
$	ele_f_t = 1
$	goto 'return'
$!
$!==================================================
$!
$!	Local subroutines
$!
$!==================================================
$client_process:
$!
$	proxy_enabled = "F"
$	proxy_checked = "F"
$	one_command = "F"
$	if p1 .nes "PROXY" then goto get_node
$	proxy_enabled = "T"
$	n = 1
$	m = 2
$shift_params:
$	P'n' = P'm'
$	if m .ge. 8 then goto done_shift
$	n = m
$	m = m + 1
$	goto shift_params
$done_shift:
$	P8 = ""
$get_node:
$!	if proxy_enabled then write sys$output "[Tell will attempt proxy login]"
$!	if .not.proxy_enabled then write sys$output "[Tell will use default DECNET login]"
$	if p1 .eqs. "" then read/prompt="Node: " sys$command p1
$	nodespec = p1 - "::"
$	nodename = f$extract(0,f$locate("""",nodespec),nodespec)
$ 	if (nodename .eqs. nodespec) -
	   .AND. (.not. proxy_enabled) then nodespec = nodename + """""" !no proxies
$	rmread := read/time=120/error=timeout_exit
$	local_at = "F"
$	log_file = "F"
$	log_file_name = ""
$	remote_tell_exists = "F"
$	temp_zzz = "F"
$	tell_where := sys$login:telltemp.zzz;0
$	tell_init = "F"
$	new_remote = "F"
$	init_cmd_num = 1
$	tell_startup = "T"
$	mail_active = "F"
$	mail_dir_in_proc = "F"
$	cur_node = f$logical("SYS$NODE") - "_"
$	cur_user = f$getjpi("","USERNAME")
$	cur_user = f$edit(cur_user,"COMPRESS,TRIM")
$!
$! Set initial commands here (use numbers sequentially)
$!
$	init_cmd_1 = "if f$extr(0,1,f$logi(""sys$announce"")) .eqs. ""@"" then type 'f$extr(1,999,f$logi(""sys$announce""))"
$	init_cmd_2 = "if f$extr(0,1,f$logi(""sys$announce"")) .nes. ""@"" then write tell_link ""'" + -
									"'f$logi(""""sys$announce"""")'"""
									!V3.x needs tell_link, and quotes
$	init_cmd_3 = "write tell_link ""Remote VMS "",""'" + "'f$getsyi(""""version"""")'"""	!V3.x needs junk
$      	init_cmd_4 = "write tell_link ""[ ~ = Local cmd, ^ = Get Mail ]"" "
$!
$	local = " " + f$sea(f$logi("TELL$INIT"))
$	if local .nes. " " then tell_init = "T"
$	on warning then continue
$	on error then goto exit2
$	on control_y then goto exit2
$	close/err=10$	tell_server
$10$:
$	open/read/write tell_server 'nodespec'::"0=''TELL_file_name'"/error=open_failure
$	remote_tell_exists = "T"
$	on error then goto exit
$	on control_y then goto exit
$	on warning then goto exit
$sync_start:
$	rmread tell_server record
$	record := 'record'
$	if f$locate("REMOTE TELL USER:",record) .lt. f$len(record) then -
$		goto check_proxy_login
$	if f$locate("REMOTE TELL VERSION:",record) .lt. f$len(record) then -
$		goto check_server_ver
$	if record .eqs. "ABOUT_TO_ISSUE_READ" then goto new_remote_server
$	goto sync_start
$check_proxy_login:  
$	proxy_checked = "T"
$	if .not.proxy_enabled then goto sync_start
$	record = f$extract((f$loc(":",record)+1),f$len(record),record)
$	record = f$edit(record,"COMPRESS,TRIM")
$	if record .eqs. "DECNET" then proxy_enabled = "F"
$!	if proxy_enabled then goto sync_start
$!	write sys$output "[Tell access via ''record' caused proxy to be disabled]"
$	goto sync_start
$!
$flush_output:
$	if (.not.proxy_checked) then proxy_enabled = "F"
$	rmread tell_server record
$	if record .eqs. "ABOUT_TO_ISSUE_READ" then goto send_command
$!!?	if log_file then write/symbol to_log record
$!!?	write/symbol sys$output record		!"/symbol" means long records
$! the extracts below are to handle long writes from the remote system
$! such as you get when you say SHOW CLUSTER
$!
$	if f$loc("MAIL_DIR_DONE",record).lt. f$len(record) then -
$		mail_proc = "mail_dir_done"
$	if f$loc("MAIL_EXIT",record) .lt. f$len(record) then -
$		mail_proc = "mail_aborted"
$	if (mail_active).and. (mail_dir_in_proc) then -
$		goto 'mail_proc'
$	if log_file then write to_log f$extract(0,255,record), f$extract(255,255,record)
$	write sys$output f$extract(0,255,record), f$extract(255,255,record)
$	goto flush_output
$
$send_command:
$	if mail_active then goto 'mail_proc'
$	if p2 .nes. "" then goto single_command
$!
$! tell_startup is to send initial commands to remote:  init_cmd_1 ...
$!
$	if .not. tell_startup then goto do_send
$	record = init_cmd_'init_cmd_num
$	init_cmd_num = init_cmd_num + 1
$	tell_startup = (f$type(init_cmd_'init_cmd_num') .nes. "" )
$	goto process_input
$!
$! tell_init, local_at are sending commands from a command file (TELL$INIT)
$!
$do_send:
$	if tell_init then goto local_at_file
$	if local_at then read/error=no_at_file/end=done_at_file tmp_at record
$	if .not. local_at then read sys$command record /promt="(tell)''nodename'> " /end=exit
$!
$process_input:
$	test_record	:= 'record
$	if test_record .eqs. "EXIT" then goto exit
$	if f$len(test_record) .gt. 0 .and. -
		(f$locate("~", test_record) .eq. 0) then -
$			goto local_command_start
$	if f$len(test_record) .gt. 0 .and. -
		(F$LOCATE("^", TEST_RECORD) .EQ. 0) then -
$			goto get_mail
$	if log_file then write to_log "$ ",record
$	write tell_server record
$	goto flush_output
$
$local_command_start:
$	if f$len( record ) .le. 1 then goto local_command
$		local = f$extract( 1,999,record )  !typed ahead command
$		multi_local = "F"
$		goto local_1
$local_command:
$	local = ""
$	read sys$command local /prompt="Local command > " /end=local_1
$	multi_local = "T"
$local_1:
$	if f$len( local ) .eq. 0 then write sys$output ""
$	if f$len( local ) .eq. 0 then goto send_command
$	if f$locate("?", local) .eq. 0 then goto local_help
$	if f$locate("@", local) .eq. 0 then goto local_at_file
$	if f$locate("|", local) .eq. 0 then goto record_file
$	assign/user'no_log_sw' 'f$logi("sys$command") sys$input
$	set noon
$	V2 := 'F$VERIFY( V2 )	!restore verify to what user wants
$ 'local'
$	V2 := 'F$VERIFY( V )	!turn verify off for this com file
$	set on
$	if multi_local then goto local_command
$	goto send_command	!it's just one command
$
$!
$local_at_file:
$	open/read/error=no_at_file tmp_at 'f$extract(1,999, local) 
$	local_at = "T"
$	tell_init = "F"
$	goto send_command
$
$done_at_file:
$	local_at = "F"
$	close tmp_at
$	goto send_command
$no_at_file:
$	write sys$output "Can't read file: ''local'"
$	local_at = "F"
$	tell_init = "F"
$	goto send_command
$
$!++
$!	remote get mail request section
$!++
$get_mail:
$	if .NOT.proxy_enabled then goto sorry_no_mail
$	write tell_server "DO_GET_MAIL ''cur_node'''cur_user'"
$	disp_lns = 0
$	page_lns = f$getdvi("SYS$COMMAND","TT_PAGE")
$	mail_proc = "mail_dir"
$	multi_local = "F"
$	mail_active = "T"
$	mail_dir_in_proc = "T"
$	goto flush_output
$mail_dir:
$	disp_lns = disp_lns + 1
$	if disp_lns .lt. page_lns then goto mail_disp
$	read sys$command local /prompt="Hit return to continue.. " /end=mail_disp
$mail_disp:
$	write sys$output "''record'"
$	goto flush_output
$mail_aborted:
$	mail_proc = ""
$	if one_command then mail_proc = "EXIT"
$	if .not. one_command then mail_active = "F"
$	mail_dir_in_proc = "F"
$!	write sys$output "%I-GETMAIL Remote mail get finished"
$	goto send_command
$mail_dir_done:          
$	mail_dir_in_proc = "F"
$	mail_msg = ""
$	write sys$output "Enter the message numbers to be transfere here,"
$	write sys$output "  seperated with commas. <return for none>"
$	read/end=mail_fileing/error=mail_dir_done/prompt="Transfere which messages ?"  sys$command mail_msg 
$	mail_msg = f$edit(mail_msg,"COMPRESS,TRIM")
$	if mail_msg .eqs. "" then goto mail_fileing
$	mail_msg = mail_msg + "," - ",,"
$	write tell_server "DO_FORWARD ''MAIL_MSG'"
$	mail_proc = "mail_fileing"   
$	goto flush_output
$mail_fileing:
$	mail_msg = ""
$	write sys$output "Enter the message numbers to be filed there,"
$	write sys$output "  seperated with commas. <return for none>"
$	read sys$command mail_msg /prompt="File which messages?" /end=mail_fil1
$	mail_msg = f$edit(mail_msg,"COMPRESS,TRIM")
$	if mail_msg .eqs. "" then goto mail_fil1
$	mail_msg = mail_msg + "," - ",,"
$	write tell_server "DO_FILE ''MAIL_MSG'"
$mail_fil1:
$	mail_proc = "mail_done"
$	goto flush_output 
$mail_done:
$	mail_proc = ""
$	if one_command then mail_proc = "EXIT"
$	if .not. one_command then mail_active = "F"
$	write tell_server "DONE_MAIL"
$	goto flush_output
$sorry_no_mail:
$	write sys$output "  %E-NOPROXY Sorry proxy access not enabled, no GET MAIL allowed"
$	mail_active = "F"
$	goto local_command
$!
$record_file:
$	if local .eqs. "|" then goto done_log_file
$	if log_file then close to_log  !make sure it's closed first
$	log_file_name = f$extract(1,999, local) 
$	open/write/error=no_log_file to_log 'log_file_name
$	log_file = "T"
$	goto send_command
$
$done_log_file:
$	if log_file then close to_log  !only if it's already open
$	log_file = "F"
$	log_file_name = ""
$	goto send_command
$no_log_file:
$	write sys$output "Can't write file: ''local'"
$	log_file = "F"
$	log_file_name = ""
$	goto send_command
$
$local_help:
$	WRITE SYS$OUTPUT "      @FILE  sends text file to the remote system
$	WRITE SYS$OUTPUT "      |FILE  records screen output to file
$	WRITE SYS$OUTPUT "      |      turns recording off
$	WRITE SYS$OUTPUT "             anything else is executed locally
$	WRITE SYS$OUTPUT "             (to do @COMfile locally, type a space first)
$	WRITE SYS$OUTPUT "      ^Z     to exit
$	if .not. log_file then WRITE SYS$OUTPUT "      [no log file active]"
$	if log_file then WRITE SYS$OUTPUT "      [logging to file: ''log_file_name']"
$	goto local_command
$
$single_command:
$	command := 'p2' 'p3' 'p4' 'p5' 'p6' 'p7' 'p8'
$	m = 1
$	one_command = "T"
$clear_params:
$	P'm' = ""
$	if m .ge. 8 then goto done_clear
$	m = m + 1
$	goto clear_params
$done_clear:
$	if command .eqs. "^" then goto get_mail
$	write tell_server command
$single_flush:
$	rmread tell_server record
$	if record .eqs. "ABOUT_TO_ISSUE_READ" then goto exit
$	write sys$output record
$	goto single_flush
$
$check_server_ver:
$	remote_tell_version = f$extract(21,99,record)
$	if remote_tell_version .eq. tell_version then goto flush_output
$	if remote_tell_version .gt. tell_version then goto need_new_tell
$new_remote_server:
$!!!	close tell_server  !need a new version remotely
$!!!	wait 0:0:1	! Wait for remote FAL process to get ready
$	write sys$output "Remote TELL is old version: ''remote_tell_version'"
$	goto open_failure2
$
$need_new_tell:
$	write sys$output "Remote TELL is newer version: ''remote_tell_version'"
$	goto flush_output
$
$open_failure:
$	err_stat = $status
$	if f$logi("debug$tell2") .nes. "" then write sys$output "Error: ''err_stat' ''f$mess(err_stat)'"
$open_failure2:
$	on warning then goto exit2
$	Write Sys$Output "Replicating TELL version ''Tell_version' to node ''nodename'"
$!
$!	Create tmp file to tell where we came from
$!
$	open/write where_is 'tell_where
$	temp_zzz = "T"
$	write where_is "$! Copied from ''cur_node'''cur_user' on ''f$time()'"
$	close where_is
$!
$!!!	We should use the single COPY command, but COPY in Z2M9 can bomb
$!!!	copy 'tell_file','tell_where' 'nodespec'::'tell_file_name'.COM;0 /prot=w:RE	!highest version
$!
$	set noon
$	copy   'tell_file'  'nodespec'::'tell_file_name'.COM;0 /prot=w:RE	!highest version
$	copy_stat = $status
$	if copy_stat then -
		append 'tell_where' 'nodespec'::'tell_file_name'.COM   
$	set on
$!
$	delete 'tell_where'
$	temp_zzz = "F"
$!
$	if remote_tell_exists then -
	  if .not. copy_stat then goto Copy_fail_ok !copy failed, but old version is there
$	if remote_tell_exists then close tell_server !copy worked, close old version
$	wait 0:0:1	! Wait for remote FAL process to get ready
$	open/read/write tell_server 'nodespec'::"0=''TELL_file_name'"
$	new_remote = "T"
$	on error then goto exit
$	on control_y then goto exit
$	on warning then goto exit
$	goto sync_start
$
$Copy_fail_ok:
$	Write Sys$Output "Can't update Remote TELL, continuing..."
$	on warning then goto exit
$	goto send_command
$
$timeout_exit:
$	write sys$output "Remote Node timeout: Lost connection"
$!
$exit:
$	set noon
$	write tell_server "LOGOUT/BRIEF"
$	if log_file then close to_log
$	if local_at then close tmp_at
$exit2:
$	if temp_zzz then close where_is/error=e1
$e1:
$	if temp_zzz then delete 'tell_where'
$	close/error=e2 tell_server
$e2:
$	V = F$VERIFY( V )
$	exit
$!
$!
$ !
$ !=========================================================================
$ !
$ ! Execute DCL command(s) in a remote network job - Tim Halvorsen
$ !
$ !	This file is NOT intended to be any type of security breaching
$ ! mechanism, but just a tool to conveniently look at remote systems 
$ ! from my office terminal.  When I first found it in my DECNET account
$ ! I was very concerned, I hope that your concern will be short lived
$ ! also!   \s\Rick
$ !
$ !	TELL :== @TELL  or, on V4: TELL :== @[wherever]TELL
$ !
$ !	P1 = Node name or PROXY with node name in P2
$ !	P2-8 = (OPTIONAL) A DCL command to be executed
$ !	[ If you don't supply DCL command, you are prompted for commands.
$ !	  In this mode, you can type tilde (~) to enter local commands for
$ !	  your system without breaking the remote connection.  After typing
$ !	  ~ type ? for help on extra options (Sending text files and logging) ]
$ !
$ !	NOTE - in order for PROXY access and get_mail to work the local 
$ !	       node must have tell as a task in the known object list in 
$ !	       NCP with outgoing proxy access enabled. 
$ !		The system manager should do :
$ !		NCP> DEF OBJ TELL NUMBER 0 PROXY OUTGOING
$ !		NCP> SET OBJ TELL NUMBER 0 PROXY OUTGOING
$ !
$ ! Modifications
$ !		(condensed)
$ !  DEC  8/15/84  	   v 2	   
$ !		   (REGAL::CHESTNUTT)
$ !
$ !  DEC  8/27/84 	   v 3	   
$ !
$ !  DEC  9/6/84   	   V 4	   
$ !
$ !  DEC  9/11/84  	   V 5	   
$ !
$ !  DEC  9/13/84          V 6
$ !
$ !  RSD  10/9/84  	   V 7
$ !
$ !  DEC   2/6/85  	   V 8	   
$ !		
$ !  GJM  10/16/85 Add get_mail and proxy processing for access to 
$ !	   V22	   remote node mail processing via the ^ flag command.
$ !		   Bumped to version 20 due to other version floating 
$ !		   around. 
$ !		   requires that local node have TELL defined as an
$ !		   object with the NCP command :
$ !			NCP DEFINE OBJECT TELL NUMBER 0 PROXY OUTGOING
$ !		   and tell be initialed via the DCL
$ !			TELL :== @[mumble]TELL PROXY
$ !		   allows TELL PROXY DUMDUM ^ to do just get mail and exit
$ !		   could be defined as command in login via:
$ !		   GET_MAIL_DUMDUM :== @[mumble]TELL PROXY DUMDUM ^
$ !			(ZEPPO::MOODY)
$ !=========================================================================
$!=========================================================================
$!
$! Where did this copy of TELL come from?
$!
$! Copied from SONATA::CARCHIDE on 26-DEC-1985 13:19:50.79
$! Copied from ORC::MERSHON on 12-FEB-1986 10:22:29.39

275.9TELL.com;24LOGIC::PUDERKarl PuderMon Aug 04 1986 18:376
    version 24 is available on {BARTOK,BACH,BLAKE,LOGIC} and PERCVL.
    (I found different versions numbered 23, so I merged them).  It
    works (with a couple of ignorable warning messages) with the UNIX
    version.
    
    	:Karl.
275.10Yet another one - REMOTE.COMRANI::LEICHTERJJerry LeichterSun Sep 14 1986 19:47183
Yet another variation.  "tempfile" returns a unique name in COM_RESULT;
it's included below.

The other files already mentioned are probably better than this in most ways.
The nice thing about REMOTE is that it does command name substitution using
locally-defined symbols before sending the file over.  I haven't looked at
the others closely enough yet to determine if any of them do it.

The original version of REMOTE appeared in the default DECnet account on some
system or other a long, long time ago.  I have no idea who wrote it.

Oh, BTW, both REMOTE and TEMPFILE are RCL input fules.  RCL is available from
the Toolshed.
							-- Jerry
-------------------------REMOTE.RCL-------------------------
$!13-Nov-82  Allow multi-line stuff ("-").  CTRL/Z exits; "?" for help.
$!15-Nov-82  Use /OUTPUT= hack.  Send over def of command, not value.
$!15-Nov-82  @REMOTE HOST COMMAND exits immediately
$!16-Nov-82  Turn CONTROL=Y back on!
$! 3-Feb-83  @REMOTE FOO::BAR adds the double colon
$! need:  Do translation for "-" files.  Handle continuation at prompt.
$!	  "ambiguous symbol def's"
$ old_ver='f$verify(0)'
$ on control_y then goto fin
$ alnum = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
$ @tools:tempfile
$ tempname = COM_RESULT
$ host = p1
$ while (host .eqs. "")							-
{	$ inquire host "Host"		}
$ if f$extract(f$length(host)-2,2,host) .nes. "::"			-
then	host = host + "::"
$ write sys$output "Attempting connection, please wait..."
$ on error then goto badhost
$ open/write file 'host''tempname'.com
$ write file "$ set noverify"
$ write file "$ define sys$print _nl:"
$ write file "$ @''tempname'.cm/output=SYS$NET"
$ write file "$ delete ''tempname'.log;*,''tempname'.cm;*"
$ write file "$ logout/brief"
$ close file
$ write sys$output "Connection open"
$ on control_y then goto done
$ on error then goto done
$ prompt = f$extract(0,f$locate("""",host),host)
$ if f$locate("::",prompt) .eq. f$length(prompt)			-
then	prompt = prompt + "::"
$ command = "''p2' ''p3' ''p4' ''p5' ''p6' ''p7' ''p8'"
$ command := 'command'

$ once_only = (command .nes. "")
$ while (command .eqs. "")						-
{
$get_command:
	$ read/end=del/prompt="''prompt'$ " SYS$COMMAND command
}
$ if command .eqs. "-"							-
{	$ indirect = 1
	$ goto make_rem
}
$ indirect = 0
$ command := 'command'
$ if command .eqs. "?"							-
{	$ file SYS$OUTPUT
	"Type a command to be executed on node ",			-
		"''f$extract(0,f$length(host)-2,host)'",		-
		" or CTRL/Z or *EXIT to"
	"exit cleanly.  Type *PANIC to get out immediately.  Type just ""-"""
	"to be prompted for a command file."
$ eof
$ goto get_command
}
$ if command .eqs. "*EXIT" then goto del
$ if command .eqs. "*PANIC" then exit
$ offset = 0
$ while (offset .le. f$length(command)					-
	 .and. f$locate(f$extract(offset,1,command),alnum) .lt. 36)	-
{	offset = offset + 1	}
$ cname = f$extract(0,offset,command)
$ cvalue = "'" + "'" + "''cname'" + "'"
$ cvalue = "''cvalue'"
$make_rem:
$ open/write file 'host''tempname'.cm
$ if indirect								-
{	$ write SYS$COMMAND "Enter command file, type CTRL/Z when done."
	$ind:
	$ read/prompt=""/end=ind_done SYS$COMMAND line
	$ write file line
	$ goto ind
	$ind_done:
}
else
{	$ if cvalue .nes. ""						-
	then	$ write file "$",cname,":==",cvalue

	$ write file "$ ''command'"	}
$ close file
$ type 'host'"task=''tempname'"
$done:
$ close/error=noerr file
$noerr:
$ if .not. once_only then goto get_command
$!
$del:
$ set nocontrol=y
$ write SYS$OUTPUT "Closing connection, please wait..."
$ close/error=noerr2 file
$noerr2:
$ assign/user NL: SYS$OUTPUT:
$ assign/user NL: SYS$ERROR:
$ delete/nolog 'host''tempname'.*;*
$ set control=y
$ goto fin
$badhost:
$ write SYS$OUTPUT "Can't get access to host ",			-
	"''f$extract(0,f$length(host)-2,host)'"
$fin:
$ if old_ver then set verify

-----------------------TEMPFILE.RCL---------------------------
$ verify = 'f$verify(0)'
$!
$!		T M P F I L E . R C L
$!
$!)EDITLEVEL=13
$!
$!+
$! Returns, in COM_RESULT, a file name for a temporary file.  The name is
$! based on the current date and time.  It is guaranteed to be unique for
$! any two calls from a single process, or from two processes that call at
$! times separated by at least the resolution of the hundredths place of
$! f$time(), within a decade of each other.  Note that two processes executing
$! TMPFILE at the same time could conceivably end up with the same name,
$! although this is VERY unlikely.
$!
$! The value returned consists of letters and digits and is always exactly
$! 9 characters long.
$!-
$! Author:  Jerry Leichter
$!
$! Revision history
$! 0.0	 9-Jun-82 JSL	Invention
$!
$ on control_y then goto fin
$ on warning then goto fin			!Exit cleanly on errors
$ now := "''f$time()'"
$if p1 .nes. "" then now:="''p1'"
$ day = 'f$extract(0,2,now)'
$ month := 'f$extract(3,3,now)'
$ month = 'f$locate(month,"JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC")'/3
$ decade = 'f$extract(10,1,now)'
$ hour = 'f$extract(12,2,now)'
$ min = 'f$extract(15,2,now)'
$ sec = 'f$extract(18,2,now)'
$ hund = 'f$extract(21,2,now)'
$ arg = day*month				!1<=arg<=372<26**2=676
$ high = arg/26
$ low = arg - 26*high
$ COM_RESULT :== 'f$extract(high,1,"ABCDEFGHIJKLMNOPQRSTUVWXYZ")'
$ COM_RESULT :== 'COM_RESULT''f$extract(low,1,"ABCDEFGHIJKLMNOPQRSTUVWXYZ")'
$ COM_RESULT :== 'COM_RESULT''decade''f$extract(hour,1,		-
	"ABCDEFGHIJKLMNOPQRSTUVWXYZ")'
$! Pack the day and month into two characters, the decade as one (itself),
$! and the hour as one letter.  COM_RESULT is now 4 bytes long.
$!
$ arg = min*sec					!0<=arg<=3481<26**3=17576
$ high = arg/26
$ low = arg - 26*high
$ highest = high/26
$ high = high - 26*highest
$ COM_RESULT:=='COM_RESULT''f$extract(highest,1,"ABCDEFGHIJKLMNOPQRSTUVWXYZ")'
$ COM_RESULT:=='COM_RESULT''f$extract(high,1,"ABCDEFGHIJKLMNOPQRSTUVWXYZ")'
$ COM_RESULT:=='COM_RESULT''f$extract(low,1,"ABCDEFGHIJKLMNOPQRSTUVWXYZ")'
$! Pack in the minutes and seconds as three more bytes, total of 7 so far.
$!
$ if 'f$length(hund)' .eq. 1 then hund := 0'hund'
$ COM_RESULT :== 'COM_RESULT''hund'
$! Finally, add on the two bytes of the hundredths of seconds, total 9.
$!
$ if "''f$time()'" .eqs. now			-
then	wait 00:00:00.01			!Make sure the time changes
$fin:
$ if verify then set verify