From:	CSBVAX::CSBVAX::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX"  3-DEC-1988 05:01
To:	MRGATE::"ARISIA::EVERHART"
Subj:	re:  Writes without linefeed or carriage return


Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Fri,  2 DEC 88 12:32:49 PDT
Received: from CUSPIF.TN.CORNELL.EDU by KL.SRI.COM with TCP; Fri, 2 Dec 88 12:27:57 PST
Date: 2 Dec 1988 15:30:49 EST
From: Brian.T.Carcich@CUSPIF.TN.CORNELL.EDU
To: info-vax@kl.sri.com
Subject: re:  Writes without linefeed or carriage return
X-VMS-Original-To: INET%"info-vax@kl.sri.com"


Pete Klammer writes:
     
>I want to write escape sequences from DCL without gratuitous CR/LF...
>     
>[read/time_out responses] ...
>     
>Good!  Great, in fact!  READ/PROMPT=/TIME_OUT=0 does as you claim (note the
>spelling: with under_score).  ...Unless SPAWN is involved!!! (sigh)
>     
>What I really wanted to do is keep the terminal busy by posting a clock
>in the corner of the screen: {pushcursor}-{position}-{DATE/TIME}-{popcursor}.
>Output with READ/PROMPT/TIME=0, put in a loop with WAIT, hide in a child
>process with SPAWN/NOWAIT, add salt and pepper to taste, and VOILA?  No.
>...
>If your system is like mine, the time is not displayed every 10 seconds,
>until you type some terminal activity.  ...
>

The problem is that the two processes have to queue their read requests,
and only one read request is "active" at a time, so the
***read/time/prompt="<esc>..." process*** is waiting for you to complete
the i/o (i.e. hit cr) for ***your*** (i.e. "$ ") process.  Like you say, so 
close...

Anyway, what you want to do can be done with the following .com and .for.
It makes use of a foreign command via lib$get_foreign.  Also, I assume we
are talking about VT100's here. 

I've made the .com a little fancier than your test circuit to keep it from
sending the time while the user process is running an image.  Basically 
it's the same as your test circuit except it defines and uses the foreign 
command "aaa" instead of "write sys$output".

BTW, I did get DCL write to work for all but the last line of the display 
by putting a ^R in the terminal answerback sequence and adding an <ESC>[A
(move cursor up) and a ^E (send answerback) after the pop-cursor string:

                                 up arrow -----v    v----control-E
                                            /-----\/\  
$ outstr="<esc>7<esc>3;50f"+f$time()+"<esc>8<esc>[A^E"
$ write sys$output outstr
$ goto again

The ^E gets the terminal to send the ^R from its answerback storage which
gets DCL to refresh the command line, prompt and all.  That's why I added 
in the f$getjpi(,"imagname") stuff:  When I edited in the subprocess, the 
^E/^R combination kept refreshing the screen (yes, I'm an EDT dinosaur:-).


Here's the .com and .for that does what you want, I think:


$ ! run a subproc, send f$time() update to its screen every 10 seconds
$ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$ ! I. initialization
$ pos1="3;50f"			!VTxxx screen positioning:  <line>;<column>f
$ wtim="00:00:10"		!time between updates
$ oldmsg=f$environment("message")		!save old message setup
$ write sys$output "type LOGOUT to quit"	!informative message
$ usrnam:='f$getjpi(0,"username")		!username to build subproc name
$ cou=0						!counter for subproc name suffix
$ mypid=f$getjpi(0,"pid")			!get my pid
$ tmpf=mypid+".tmp"				!unique temporary file
$ stat1=1					!again:  loop goodexit status
$ aaa="$disk:[carcich.junk]aaa"			!again:  loop foreign command
$ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$ ! II. generate subprocess name
$loop0:	coustr="_''cou'"		!"_" & integer to string:  "_n..."
$ lencoustr=f$length(coustr)+1		!length of _n...
$ lenusrnam=15-lencoustr		!max process name less length of suffix
$ prcnam=f$extract(0,lenusrnam,usrnam)+coustr	!hopefully unique process name
$ cou=cou+1					!incr counter for next loop0
$ on error then $ goto loop0			!loop on (assumed) dupl name
$ spawn/nowait/process="''prcnam'"/promp="SUB$ "!here's some beef
$ on error then $ exit				!spawn success; reset "on error"
$ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$ ! III. find just-created subprocess' pid
$ if f$search(tmpf) .nes. "" then $ deletes/nolog 'tmpf;*	!ensure cleanup
$ sho system/out='tmpf					!get all processes
$ prcnam17=" "+f$extract(0,16,prcnam+"                ")!build 17-char prcnam
$ searchs 'tmpf;1 /out='tmpf;2 "''prcnam17'"	!find it in sh sys o/p
$ !
$ close/nolog aaa				!pre-cleanup belt & suspenders
$ on error then $ goto errex1			!ensure file gets closed
$ open/read aaa 'tmpf;2				!open file
$loop1: read/err=errex1 aaa aaaline		!read subproc line from "sh sys"
$ subpid="%x"+f$extract(0,8,aaaline)		!get subproc's pid
$ parpid=f$getjpi(subpid,"master_pid")		!get subproc's parent's pid
$ if mypid .nes. parpid then $ goto loop1	!compare with mine, loop if dif
$ !					! n.b. fails if I am subproc already!!!
$ close/nolog aaa
$ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$ ! IV. loop until subprocess goes away
$ set message/nof/noi/nos/not		!to avoid "non-existent process" message
$again:	wait 'wtim			!here's the wait
$ ! - send clock if subprocess is in dcl; quotes foreign cmd to keep lowercase
$ if "''f$getjpi(subpid,"imagname")'" .eqs. "" then $ aaa "''pos1'''f$time()'"
$ stat2=$status
$ if stat2 .eq. %x8e8 then $ goto goodexit	!check if subprocess logged out
$ if stat2 then $ goto again			!no prob, do it again
$ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$ ! V. Unknown error exit handling
$ stat1=stat2
$ write sys$output "Unknown problem - exiting; status = ",stat1
$badexit: set noon
$ set message'oldmsg
$ writ sys$output "Parent:  ''f$process()' stopping subproc:  ''prcnam'"
$ stop 'prcnam
$ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$ ! VI. non-error exit handling
$goodexit: set noon
$ set message'oldmsg
$ close/nolog aaa
$ deletes /nolog 'tmpf;*
$ exit stat1
$ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$ ! VII. can't-verify-subprocess error exit handling 
$errex1: stat1=$status		!save status
$ set noon
$ set message'oldmsg		!reset messages
$ writ sys$output "Parent:  ''f$process()' can't verify subproc:  ''prcnam'"
$ goto badexit			!send message and stop subprocess
 
DISK:[CARCICH.JUNK]AAA.FOR;10
 
	program writewolf		!write without linefeed
	implicit none			!pretend I'm a pro
	character esc1*5, esc2*2	!escape prefix and suffix
	parameter ( esc1 = char(0)// char(27)// '7'// char(27)// '[')
	parameter ( esc2 = char(27) // '8' )
	integer status*4, lib$get_foreign*4, il*2/0/	!il = foreign input len
	character*1000 inp				!foreign input buffer
c********** start execution ********************************************
	status = lib$get_foreign(inp,,il,)			!get foreign i/p
	if ( il .gt. 0) then					!ensure non-null
	  if ( '"' .ne. inp(:1) .or. '"' .ne. inp(il:il)) then	!check 4 quotes
	    write(*,fmt='(a)') esc1 // inp(:il) // esc2		!full input
	  elseif (il.gt.2) then					!1 & il are "'s
	    write(*,fmt='(a)') esc1 // inp(2:il-1) // esc2	!strip quotes
	  endif
	endif
	call sys$exit( %val( status))
	end


