[comp.emacs] process exit status

Buehring@Intellection.COM (06/04/91)

Greetings,

I'm writing an elisp function that calls a subprocess and waits for
completion.  The obvious way to do this is to use 'call-process', but
I need the process exit status before the elisp can continue with
confidence.  In all the tests I've run, 'call-process' returns 'nil'
regardless of the exit status.

Is there a way to obtain the exit status besides resorting to
'start-process' and using a process-sentinal?  The function I'm
writing shouldn't require such hair, but I *must* have the exit
status.


Thanks in advance,
\/\/

Walt Buehring
  Internet:  Buehring@Intellection.COM		Intellection, Inc.
  UUCP:      uupsi!intell!buehring		1603 LBJ Freeway, Suite 780
  Phone:     (214) 620-2100 			Dallas, TX  75234

Church of the SubGenius -- Eternal salvation or triple your money back!

darrylo@HPNMXX.SR.HP.COM (Darryl Okahata) (06/05/91)

In message <WALT.91Jun4105619@arrisun3.utarl.edu> you write:

> Is there a way to obtain the exit status besides resorting to
> 'start-process' and using a process-sentinal?  The function I'm
> writing shouldn't require such hair, but I *must* have the exit
> status.

     I wrote the following function eons ago.  It will execute a unix
command, wait for it to finish, and return the exit status.  Note,
however, that this is not the world's best written function; if I had to
re-write it, I'd do it slightly differently.  Also note that the
function documentation says that a SIGINT will be sent if ^G is pressed.
This will only work on those machines that do NOT support SIGIO.  I wrote
this function when HP-UX did not support SIGIO; it does now, and
pressing ^G to interrupt the subprocess no longer works.  Pressing ^G
will interrupt Emacs, but the subprocess will continue to grind away in
the background (this can be easily fixed using `unwind-protect', but I
don't have the time to modify and test it).

     -- Darryl Okahata
	Internet: darrylo@sr.hp.com

DISCLAIMER: this message is the author's personal opinion and does not
constitute the support, opinion or policy of Hewlett-Packard or of the
little green men that have been following him all day.

===============================================================================
(defun execute-unix-command (buffer program &rest args)
  "Execute a unix command, wait for it for finish, and return the exit status.
This function creates a process, using BUFFER for output, and waits
for the process to exit.  The name of the program to run is given by
PROGRAM, and any remaining arguments, ARGS, are passed as command line
arguments to the program.  All arguments are strings.

Note that there are no provisions for giving input to the program.  If
you must give input to the program, create a file containing the input
for the process and pass the name of this file to a shell script that
starts up the program with standard input redirected to the given
file.

If BUFFER is nil, any output from the program will be throw away.

If a ^G is pressed while the program is running, the program will be
killed via a SIGINT, and this function will return nil.  All other
keypresses will be flushed.

Upon normal completion of the program, the numeric exit status of the
program will be returned.  Note that this function returns either nil
or a numeric value.
"
  (let (prg (process nil) status (return-status nil))
    (catch 'exit-process
      (progn
	(setq prg (list 'start-process "unix-process" buffer program))
	(if args
	  (if (listp args)
	    (setq prg (append prg args))
	    (setq prg (append prg (list args)))
	  )
	)
	(setq process (eval prg))
	(if (processp process)
	  (progn
	    (process-send-eof process)
	    (while (or (equal (setq status (process-status process))
			      'run)
		       (equal status 'stop))
	      (sit-for 1)
	      (if (input-pending-p)
		(if (equal (read-char) ?\^G)
		  (progn
		    (interrupt-process process t)
		    (throw 'exit-process nil)
		  )
		)
	      )
	    )
	    (setq return-status (process-exit-status process))
	  )
	)
      )
    )
    return-status
  )
)

manderso@mpr.ca (Mark Anderson) (06/05/91)

Buehring@Intellection.COM writes:
>I need the process exit status before the elisp can continue with

How about...

process-exit-status:
Return the exit status of PROCESS or the signal number that killed it.
If PROCESS has not yet exited or died, return 0.

Buehring@Intellection.COM (Walt Buehring) (06/05/91)

) Buehring@Intellection.COM writes:
) >I need the process exit status before the elisp can continue with
) 
) How about...
) 
) process-exit-status:
) Return the exit status of PROCESS or the signal number that killed it.
) If PROCESS has not yet exited or died, return 0.

I'm aware of the function -- using it requires an argument which is a process
object, which you never get access to (to my knowledge) when using
'call-process'.  I wanted to use 'call-process' because it's many times
simpler than futzing with 'start-process' and all that jazz.  

Oh well, there appears to be no alternative to using 'start-process' when you
want the exit status -- so much for keeping my little elisp function nice and
simple.  :-(


\/\/
Walt Buehring
  Internet:  Buehring@Intellection.COM		Intellection, Inc.
  UUCP:      uupsi!intell!buehring		1603 LBJ Freeway, Suite 780
  Phone:     (214) 620-2100 			Dallas, TX  75234

Church of the SubGenius -- Eternal salvation or triple your money back!

levin@eos.ncsu.edu (Dr. Hal Levin) (06/06/91)

>I'm writing an elisp function that calls a subprocess and waits for
>completion.  The obvious way to do this is to use 'call-process', but
>I need the process exit status before the elisp can continue with
>confidence.  In all the tests I've run, 'call-process' returns 'nil'
>regardless of the exit status.
>
>Is there a way to obtain the exit status besides resorting to
>'start-process' and using a process-sentinal?  The function I'm
>writing shouldn't require such hair, but I *must* have the exit
>status.



This is most assuredly a hack.  Nonetheless I offer it because it has a certain
beauty to it - similar to that of well-done "objet-trouvee" art.

(let ((buf (get-buffer-create "*Turnin Error*")))
      (set-buffer buf)
      (erase-buffer)
      (call-process "csh" nil buf nil
                    "-fc" (concat "compress" " -f" "< " source-file ">!
" target
-file ";if ($status) then\necho ERROR MESSAGE from TURNIN\nelse\necho
OK\nendif"
 ))
      (if (equal (buffer-string) "OK\n")
          (progn (kill-buffer buf)
                 (message "Your File Was Turned In Successfully."))
        (progn
          (goto-char (point-max))
          (princ "

                         **** E R R O R ****

Your File Was NOT Turned In.

Try Again.  But if that doesn't work, check with a TA.


**** BE SURE TO WRITE DOWN THE ERROR MESSAGE AT THE TOP OF THE BUFFER!!! ****"
                 buf)
          (pop-to-buffer buf)
          (other-window 1)
          (beep)
          (message "C-x 1 to remove *Turnin Error* buffer")
          ))

The idea is simply to force the shell to test the error status and to write to 
standard output the result of the test.  call-process will place the standard
output in a buffer where the full power of emacs is available to test the
error status.