Return value

Started by Dave, October 07, 2005, 07:55:17 PM

Previous topic - Next topic

Dave

How does one get the return value for exec?



(set 'x (exec "command")) seems to return a nil x, regardless if the command is successful or not.

HPW

#1
Works for me in windows.

But I have to kill the DOS-window.



> (set 'x (exec "command"))
("Microsoft(R) Windows DOS" "(C)Copyright Microsoft Corp 1990-2001."
 "" "C:\PROGRA~1\NEWLISP>")


This works:

> (set 'x (exec "dir un*.exe"))
(" Datentr?ger in Laufwerk C: ist Festplatte" " Volumeseriennummer: 4875-9A91"
 "" " Verzeichnis von C:\Programme\newlisp" "" "26.09.2005  19:38            35.923 uninstall.exe"
 "               1 Datei(en)         35.923 Bytes" "               0 Verzeichnis(se), 91.052.036.096 Bytes frei")


Added later:

The above test was with newLISP-TK!

In native newLISP-shell the first hang up and the second work.
Hans-Peter

Lutz

#2
I don't have access to a Windows machine at the moment, but I think you can seperate commands with a semicolon in a DOS window and could put an 'exit' as a second statement:



(exec "dir *.exe; exit")



if exec returns 'nil' then it did not find the command shell try this instead:



(exec "cmd /c dir *.exe")



this would be 'cmd' for the NT cmd command shell and 'command' for older versions of Windows



Lutz

Dave

#3
I'm using newLISP as a scripting language under FreeBSD.



I am unclear about the term "return value", whether it is the data returned from the system process (say, a directory), or if it is the exit status of the process (success/fail). The reference says "The return value  true is the process was successfully launched, else nil" (I think is s/b "if" btw). I am looking for the status of the process in this instance. I tried to query "$?", with the same results; nil on both pass and fail.

Lutz

#4
There are two forms of the syntax, with and without the second argument:



(1) 'exec' returns 'nil' if it could not launch the command given, else it returns a list of strings, each string beeing one of the output lines of std-out of the process launched.



(2) with the second argument given (stdin to the process), the return value is 'true' on success and 'nil' if the process could not be launched.



Lutz

Dave

#5
(set 'x (exec "ls /a_directory")) --- x will be the contents of the directory.

(set 'x (exec "ls /empty_directory")) --- x will be empty.



But this is where I have trouble understanding:



(set 'x (exec "ls /not_a_directory"))  --- x will be empty NOT null, and the OS will output an error message.

(set 'x (exec "not_an_instruction"))  --- x will be empty NOT null, and the OS will output an error message.



I am trying to test for failed calls to the system, and deal with them before they are sent to the output. Should I be using some form of catch/throw? How is it used in this way?

Lutz

#6
'exec' launches a shell process and returns whatever was standard-out via a pipe mechanism. There is no way to check stdout from the launched process before it gets returned. 'exec' fails if the command in exec couldn't be launched returning a 'nil'.



If you want a more direct control over OS system calls you could import system calls from the libraries of your OS. I.e.:



(import "libc.so" "kill")



could be used to import the kill system call and then you could do a:



(kill pid 9)



To send SIGKILL to a process ID and the function would return 0 for sucess -1 for error etc.



The purpose of 'exec' is to execute OS utilities/programs in a shell like fashion and capture stdout. But there is a way to capture std error using the following method:



> (exec "ls *.abc 2>&1")
("ls: *.abc: No such file or directory")
>


The 2>&1 spec tell ls to redirect error output to stdout. This way it gets captured in the list returned by exec.



Lutz

Dave

#7
Very informative answer, Lutz! It shows me some things I will have to study.



Thanks. I'm a fan!

statik

#8
The 2>&1 is a format for stderr redirection that is only valid with the bourne-again shell. Keep that in mind when developing; all shells use different syntax when using stdio/out/err redirection.
-statik

Dmi

#9
Just checked 2>&1 on Tru64 with ksh and pure sh - it works like bash.

Even command.com (AFAI remember) works this way, despite in it it's only "idiom", I think.
WBR, Dmi

Dmi

#10
Btw, there is a nice way in unix shell:
$ mknod pipe p
$ ls pipe
prw-r--r--  1 dmi users 0 Oct 15 00:44 pipe
$ cat pipe >error&
[1] 22755
$ ls nonexistent 2>pipe
$ cat error
ls: nonexistent: No such file or directory

...but there is some special things about locking and end of file on the named pipe's ends
WBR, Dmi

nigelbrown

#11
Quote from: "Lutz"
...

If you want a more direct control over OS system calls you could import system calls from the libraries of your OS. I.e.:



(import "libc.so" "kill")

...

Lutz

Trying on Suse 10 I get (using newlisp compiled on system from source):

nigel@linux:~/newlisp-8.7.1> ./newlisp

newLISP v.8.7.1 on linux, execute 'newlisp -h' for more info.



> (import "libc.so" "kill")

/usr/lib/libc.so: invalid ELF header

problem loading library in function import : "libc.so"



>            



Looking at libc.so shows:

linux:/home/nigel # ls -l /usr/lib/libc.so

-rw-r--r--  1 root root 204 2005-09-10 03:20 /usr/lib/libc.so



I really want to call getuid (to find if newlisp is running as root).

Any tips on calling from libc ?



Nigel

newdep

#12
What happens when you provide the whole path?

>(import "/lib/libc.so.6" "fopen")



what does "ldd" give on libc.so ?

(Looks like the libc you revering to is not a shared lib...)
-- (define? (Cornflakes))

nigelbrown

#13
Thanks for pointing out the correct path - works as required viz:



nigel@linux:~/newlisp-8.7.1> ./newlisp

newLISP v.8.7.1 on linux, execute 'newlisp -h' for more info.



> (import "/lib/libc.so.6" "fopen")

fopen <401CF720>

> (import "/lib/libc.so.6" "getuid")

getuid <402075E0>

> (getuid)

1000

> (exit)

nigel@linux:~/newlisp-8.7.1> su

Password:

linux:/home/nigel/newlisp-8.7.1 # ./newlisp

newLISP v.8.7.1 on linux, execute 'newlisp -h' for more info.



> (import "/lib/libc.so.6" "getuid")

getuid <402075E0>

> (getuid)

0

>  



as you expected:

linux:/home/nigel/newlisp-8.7.1 # ldd /usr/lib/libc.so

ldd: warning: you do not have execution permission for `/usr/lib/libc.so'

        not a dynamic executable

linux:/home/nigel/newlisp-8.7.1 # ldd /lib/libc.so.6

        /lib/ld-linux.so.2 (0x40000000)

        linux-gate.so.1 =>  (0xffffe000)



Regards

Nigel