<div dir="ltr"><div class="gmail_default" style="font-family:monospace,monospace;font-size:small"><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">It's
 useful that it doesn't close unless you tell it to, because it's useful
 to set up a co-process that gets re-used many times rather than forking
 and closing every time.<br><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">user()is
 a very tricky feature to use *reliably* though. You must always be 
absolutely sure about the sequence of read vs writing to to the child 
process. It's stupid easy to get out of sync where you are trying to 
write to the processes stdin when it's not reading, or read from the 
processes stdout when it's not writing, and you sit there hung forever. 
All it takes if for the child program to issue one line of output that 
you didn't expect (like an error message, or a response that normally 
has x lines but under some odd condition that doesn't usually happen can
 be some other number of lines), or fail to issue a line of output you 
did expect. It's very useful, but it's also very fragile.<br><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">It's possible to set things up so that it's reliable, but you have to actually set things up and do things right yourself.<br><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">For myself, the way I do it is I follow these rules:<br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">For
 the child program, I make a shell script which loops until directed to 
exit, or until the parent exits, and the shell script absorbs all 
potential irregularities from any programs run inside the script. Then 
the script itself is the only thing that reads from stdin or writes to 
stdout, and I make sure the loop in the script always reads and writes 
in exctly the same pattern no matter what any of the programs in the 
script did.<br><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">For
 instance, if you issue say a command and it didn't return anything at 
all, that would hang fp, because in fp you'd have to try to read at 
least one line, but if the command didn't send at least one linefeed, 
then fp would sit and read forever.<br><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">But in a shell script you can x=`command`<br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">and
 then echo $x, and the echo command will append it's own linefeed 
regardless if $x is even unset (because, say that line in the shell 
script never even got run because of some bug), or is set but totally 
null, or contains a string with no linefeed, or contains a string with 
multiple linefeeds but doesn't end with a linefeed, or is a normal 
expected form of value.<br><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">Basically use the shell to normalize the input and output between filepro.<br><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">Then, in filepro, I stick to a certain boilerplate example of hour to ever user user(), in all cases.</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small"><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">After
 setting up the looping shell script, I write a simple gosub with no 
conditional spaghetti within the gosub itself, so the gosub always does 
exactly the same sequence of events with no risk of getting it wrong 
under some unexpected condition. And the gosub goes like, essentially:<br></div><div><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">user prog = prog</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">prog = x</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">x = prog</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">return</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small"><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">If the shell script has some other pattern like read one line of input then write 4 lines of output, then the gosub would be</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small"><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small"><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">user prog = prog</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">prog = x</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">xa = prog</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">xb = prog</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">xc = prog</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">xd = prog<br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">return</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small"><br></div></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">The key points are:</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">* No If: at all within the gosub if I can possibly avoid it.<br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">* Gosub always includes the user foo = foo line before the reading & writing within the gosub.</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">* All reads/writes to the user alias are done within the gosub. None at all outside of the gosub.</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">*
 No multiple exits from the gosub, or indeed any conditional/variable 
behavior within the gosub. It always does the same thing from beginning 
to end.</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">* The user() alias is never closed.</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small"><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">Then
 if I adhere to that template religiousy, I can just use the gosub as 
much or as little as I want, and I am never at risk of hanging trying to
 read when the child is not writing, hanging trying to write while the 
child is not reading, creating a zillion zombie children, spawning the 
child process for no reason if I never used it.<br><br>I arrived at this template procedure because of a few things:<br>*
 If the user() is not closed, then re-running the same user command 
(same alias) has no effect, so it's harmless to run 600 times. Placing 
it within the gosub at the beginning gurantees that the command has been
 run before any attempt to read or write to the alias.</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">*
 closing the alias isn't a reliable way to close the child process. When
 I used to close the alias each time, it frequently created a zillion 
zombie children. fp would sort of close the process but they didn't 
actually go away as long as the clerk or report process was still 
running, then the next time the user() command was run it would spawn a 
new child process, repeat, repeat, repeat... creating a zombie child 
process each time until the clerk or report process finally exits, which
 might be a long time because a user could just move from record to 
record inside the same clerk session all day long, or run a huge report 
that hits a lot of records etc... This is probably because of some 
glitch with waiting output on stdin, stdout, or stderr that needs to be 
consumed one way or the other, or, who knows what.<br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">*
 You can practically never really count on the output from almost any 
commands to really be guaranteed predictable at all times. There is 
always some odd situation where it outputs more lines or fewer lines 
than it usually does or than you expected, or outputs nothing at all, 
etc, and there is no way to test the output from user() for nothingness 
like you can in shell. You can read from a user alias and the result 
could be "", but that would only be if the program had actually output 
at least a single linefeed. It's just like the shell "read" command 
(it's default behaviour without using any options) It reads until it 
sees a linefeed. No linefeed, then it just waits forever.</div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small"><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">It
 is possible to do it other ways. Like you could have code in the script
 that says basically "when I read "EXIT" then, exit", and then have the 
filepro code say<br>foo = "EXIT" ; close foo<br><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">That
 can work too, but I just find it less bullet-proof, not to mention less
 efficient in cases where you might call the gosub multiple times within
 a clerk/report session.<br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small"><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">It
 is possible to have situations that require the gosub to be more 
complex than this example, or even really need your program to do all 
kinds of conditional jumping around while interacting with the user() 
throughout the whole program, with no gosub, it's just that this is the 
ideal I always try to stick to as religiously as possible, and only 
break this rule if I have to. I do have one thing I did one time where I
 made a sort of "driver" to interface with a network service, where the 
user command was just "netcat" talking to a tcp service, and I did all 
kinds of logic in processing where I send a command to the tcp service, 
read the first line of output, and decide what to do next based on that,
 and just hope to hell the docs for that service were complete and 
accurate! If I had to do that same project today, I'd probably do more 
of it in shell and stick to this rule like usual. I think that program 
in fact turned out to give that customer some problems once in a while 
probably exactly because I didn't. They had their own in-house developer
 after that so I never worked on it again but just explained how it was 
supposed to work to their guy.<br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small"><br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">Really,
 it's not so important exactly how you go about it, never close, always 
close, so long as one way or another you do ensure that you are always 
in sync with the child process, where you always only ever try to write 
when it is definitely waiting to read input, and always only ever try to
 read output from the child when it is going to write at least one line 
of output, including a terminating linefeed. That's the important part. 
And just generally realize that user() requires special care, and isn't 
really the best way to run a child process unless you really do wnat to 
interact with it to read and write stdin stdout with it. If you just 
want to run something and don't really need to collect it's output, use 
system(). And even in most cases where you do want to collect it's 
output, still use system() and a temp file.<br><br>-- <br></div><div class="gmail_default" style="font-family:monospace,monospace;font-size:small">bkw<br></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Aug 13, 2018 at 2:46 PM James Flanagan via Filepro-list <<a href="mailto:filepro-list@lists.celestial.com">filepro-list@lists.celestial.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Mark, <br>
<br>
Yeah, that was exactly it.  Thank you very much, <br>
<br>
<br>
James Flanagan<br>
Flantec.com <<a href="http://flantec.com/" rel="noreferrer" target="_blank">http://flantec.com/</a>><br>
<br>
email:  James@Flantec.com <mailto:<a href="mailto:James@Flantec.com" target="_blank">James@Flantec.com</a>><br>
mobile: 760-458-8498<br>
home:   219-221-6219<br>
text:           <a href="mailto:7604588498@txt.att.net" target="_blank">7604588498@txt.att.net</a> <mailto:<a href="mailto:7604588498@txt.att.net" target="_blank">7604588498@txt.att.net</a>><br>
<br>
Skype:  Flantec<br>
ichat:  James@Flantec.com <mailto:<a href="mailto:James@Flantec.com" target="_blank">James@Flantec.com</a>>    <br>
<br>
home:   1901 Cidermill Road<br>
                Michigan City, IN 46360<br>
<br>
> On Aug 13, 2018, at 2:38 PM, Fairlight via Filepro-list <<a href="mailto:filepro-list@lists.celestial.com" target="_blank">filepro-list@lists.celestial.com</a>> wrote:<br>
> <br>
> Your mistake is likely in not using CLOSE.<br>
> <br>
> After your "aa=xxx" line, use this line:<br>
> <br>
> ::close xxx:<br>
> <br>
> Should it -technically- close upon re-hitting the user command?  That's a<br>
> mattter one could debate either way.  I strongly suspect it is not closing,<br>
> however, leaving you with a dead file descriptor.<br>
> <br>
> mark-><br>
> <br>
> On Mon, Aug 13, 2018 at 02:02:04PM -0400, James Flanagan via Filepro-list thus spoke:<br>
>> Filepro 5.8.01.06D6<br>
>> Redhat Exnterprise 6.8<br>
>> <br>
>> /bin/test_script<br>
>> echo 23<br>
>> <br>
>> Input processing<br>
>> ::end:<br>
>> ::?:<br>
>> @keyx::?:<br>
>> ::aa(2,.0):<br>
>> ::user xxx = /bin/test_script<br>
>> ::aa=xxx:<br>
>> ::msgbox aa:<br>
>> ::end:<br>
>> <br>
>> The first iteration of this code, when hitting the ?X? key works and the msgbox contains ?23?.  Every subsequent time, however, the msgbox is blank.   <br>
>> <br>
>> I found the following in the manual, but I am not quite certain that this is the issue.  <br>
>> IMPORTANT: When reading from a user program, filePro Plus executes the program only once, not over and over. Therefore, make sure the user program itself loops until it reaches an end-of-file. <br>
>> <br>
>> Can input processing keep re-running a user command each time in @key processing, however many times the key is pressed for a given record.<br>
>> <br>
>> Thank you very much, in advance.  <br>
>> <br>
>> <br>
>> James Flanagan<br>
>> Flantec.com <<a href="http://flantec.com/" rel="noreferrer" target="_blank">http://flantec.com/</a>> <<a href="http://flantec.com/" rel="noreferrer" target="_blank">http://flantec.com/</a> <<a href="http://flantec.com/" rel="noreferrer" target="_blank">http://flantec.com/</a>>><br>
>> <br>
>> email:       James@Flantec.com <mailto:<a href="mailto:James@Flantec.com" target="_blank">James@Flantec.com</a>> <mailto:<a href="mailto:James@Flantec.com" target="_blank">James@Flantec.com</a> <mailto:<a href="mailto:James@Flantec.com" target="_blank">James@Flantec.com</a>>><br>
>> mobile:      760-458-8498<br>
>> home:        219-221-6219<br>
>> text:                <a href="mailto:7604588498@txt.att.net" target="_blank">7604588498@txt.att.net</a> <mailto:<a href="mailto:7604588498@txt.att.net" target="_blank">7604588498@txt.att.net</a>> <mailto:<a href="mailto:7604588498@txt.att.net" target="_blank">7604588498@txt.att.net</a> <mailto:<a href="mailto:7604588498@txt.att.net" target="_blank">7604588498@txt.att.net</a>>><br>
>> <br>
>> Skype:       Flantec<br>
>> ichat:       James@Flantec.com <mailto:<a href="mailto:James@Flantec.com" target="_blank">James@Flantec.com</a> <mailto:<a href="mailto:James@Flantec.com" target="_blank">James@Flantec.com</a>>> <br>
>> <br>
>> home:        1901 Cidermill Road<br>
>>              Michigan City, IN 46360<br>
>> <br>
>> -------------- next part --------------<br>
>> An HTML attachment was scrubbed...<br>
>> URL: <<a href="http://mailman.celestial.com/pipermail/filepro-list/attachments/20180813/98c7c5f6/attachment.html" rel="noreferrer" target="_blank">http://mailman.celestial.com/pipermail/filepro-list/attachments/20180813/98c7c5f6/attachment.html</a> <<a href="http://mailman.celestial.com/pipermail/filepro-list/attachments/20180813/98c7c5f6/attachment.html" rel="noreferrer" target="_blank">http://mailman.celestial.com/pipermail/filepro-list/attachments/20180813/98c7c5f6/attachment.html</a>>><br>
>> _______________________________________________<br>
>> Filepro-list mailing list<br>
>> <a href="mailto:Filepro-list@lists.celestial.com" target="_blank">Filepro-list@lists.celestial.com</a> <mailto:<a href="mailto:Filepro-list@lists.celestial.com" target="_blank">Filepro-list@lists.celestial.com</a>><br>
>> Subscribe/Unsubscribe/Subscription Changes<br>
>> <a href="http://mailman.celestial.com/mailman/listinfo/filepro-list" rel="noreferrer" target="_blank">http://mailman.celestial.com/mailman/listinfo/filepro-list</a> <<a href="http://mailman.celestial.com/mailman/listinfo/filepro-list" rel="noreferrer" target="_blank">http://mailman.celestial.com/mailman/listinfo/filepro-list</a>><br>
> <br>
> -- <br>
> Audio panton, cogito singularis.<br>
> _______________________________________________<br>
> Filepro-list mailing list<br>
> <a href="mailto:Filepro-list@lists.celestial.com" target="_blank">Filepro-list@lists.celestial.com</a> <mailto:<a href="mailto:Filepro-list@lists.celestial.com" target="_blank">Filepro-list@lists.celestial.com</a>><br>
> Subscribe/Unsubscribe/Subscription Changes<br>
> <a href="http://mailman.celestial.com/mailman/listinfo/filepro-list" rel="noreferrer" target="_blank">http://mailman.celestial.com/mailman/listinfo/filepro-list</a> <<a href="http://mailman.celestial.com/mailman/listinfo/filepro-list" rel="noreferrer" target="_blank">http://mailman.celestial.com/mailman/listinfo/filepro-list</a>><br>
-------------- next part --------------<br>
An HTML attachment was scrubbed...<br>
URL: <<a href="http://mailman.celestial.com/pipermail/filepro-list/attachments/20180813/8925ed56/attachment.html" rel="noreferrer" target="_blank">http://mailman.celestial.com/pipermail/filepro-list/attachments/20180813/8925ed56/attachment.html</a>><br>
_______________________________________________<br>
Filepro-list mailing list<br>
<a href="mailto:Filepro-list@lists.celestial.com" target="_blank">Filepro-list@lists.celestial.com</a><br>
Subscribe/Unsubscribe/Subscription Changes<br>
<a href="http://mailman.celestial.com/mailman/listinfo/filepro-list" rel="noreferrer" target="_blank">http://mailman.celestial.com/mailman/listinfo/filepro-list</a><br>
</blockquote></div><br clear="all"><br>-- <br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><font face="monospace,monospace">bkw<br></font></div></div>