Page 1 of 1

exec function not returning string list

Posted: Sat Dec 05, 2015 12:13 pm
by TedWalther
Since I've had problems with (process), I tried to use (exec) instead. When I read the documentation I was very happy; it does exactly what I need.

Code: Select all

(exec "command") => string-list
With (exec), I would run the command, and it would return the output of the command as a list of strings. Ok, that is almost what I need, but I need to send the command some specific input. Great! (exec) allows that, with usage:

Code: Select all

(exec "command" "input to command") => ?
The documentation doesn't say that (exec cmd input) has different output than (exec cmd). But, it doesn't return a list of strings. Instead it returns a number. Whether it is a process id or the exit value of the program, I don't know.

Lutz, could exec with user supplied input be updated to return the same string list I've come to expect from the simpler form?

Again, this is with newLisp 10.6.2.

Re: exec function not returning string list

Posted: Sun Dec 06, 2015 4:54 pm
by Lutz
The exec function uses the C function popen() to open a process and return a pipe handle. This pipe is only unidirectional, you can call popen() either con “r” for reading in the first syntax of exec or “w” for writing for the second syntax of exec.

There is only FreeBSD and some FreeBDS derivates, where you can specify “r+” in popen() for a bidirectional pipe. On Linux and OpenBSD this would not work.

One could fake a bidirectional popen() using fork() and duplicating/creating pipe handles, but this would not work on Windows, which does not have fork.

Here is a work-around which will work on all OSs:

Code: Select all

> (exec "wc > result" "this is a sentence") ; wc counts letters and words
> (exec "cat result")
("       0       4      18")
So this will give you output as if a bidirectional exec and still lets you specify the input coming from newLISP.

Re: exec function not returning string list

Posted: Tue Mar 22, 2016 10:08 am
by hds1
If you want to avoid the interim file creation you could use the environment as a placeholder

(env "willi" "<html><head></head><body>Killroy</body></html>")

(exec "echo $willi" | tidy -q 2>/dev/null)
=> ("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 3.2//EN\">" "<html>" "<head>" "<meta name=\"generator\" content="
"\"HTML Tidy for Linux (vers 25 March 2009), see\">" "<title></title>"
"</head>" "<body>" "Killroy" "</body>" "</html>")

;; cleanup a bit if you like
(env "willi" "")

I used this method with success on thousands of html files upto 2MB of size (Linux 64bit system).
Limited of course to the env you are working with.