[comp.sys.ibm.pc] system

det@hawkmoon.MN.ORG (Derek E. Terveer) (01/21/89)

Has anyone encountered a problem with the Microsoft C 5.0 compiler always
returning a 0 from the system() call, no matter what the actual command
executed by system() returns?

Is there a fix for this or am i misunderstanding something fundamental about
the way the system() call works in msc5.0?  (Like the command.com always
returning the 0, which system(), in turn, returns to my program?)

I'm trying to determine whether or not the executed command succeeded or not by
looking at the completion code from system, ala:

	char buf[BUFSIZ];

	sprintf(buf,"rnews < D_elricf.3aa");
	if (!system(buf)) perror(buf);

and i'm having a hard time of it since system() always (seems) to return 0!

derek
-- 
Derek Terveer 	    det@hawkmoon.MN.ORG || ..!uunet!rosevax!elric!hawkmoon!det
		    w(612)681-6986   h(612)688-0667

"A proper king is crowned" -- Thomas B. Costain

jeenglis@nunki.usc.edu (Joe English) (01/24/89)

In article <782@hawkmoon.MN.ORG> det@hawkmoon.MN.ORG (Derek E. Terveer) writes:
>Has anyone encountered a problem with the Microsoft C 5.0 compiler always
>returning a 0 from the system() call, no matter what the actual command
>executed by system() returns?

That, unfortunately, is right.  system() returns the exit status of
command.com (in Turbo C, anyway, and I suspect that MSC works the same
way), and command.com doesn't return an error code if the called
program fails. (!)  (system() also returns non-zero if command.com could
not be loaded for lack of memory.)

The way to get the return status of the program you're interested in
is to use one of the exec or spawn functions, which call the DOS
load/exec syscall and bypass command.com.  It's possible, though a bit
more work, to do redirection with these as well (check out dup() and
dup2()); the only thing you can't do is call command.com-resident
functions like copy and type.


Joe English
jeenglis@nunki.usc.edu

maa@nbires.nbi.com (Mark Armbrust) (01/24/89)

In article <2439@nunki.usc.edu> jeenglis@nunki.usc.edu (Joe English) writes:
>
>That, unfortunately, is right.  system() returns the exit status of
>command.com (in Turbo C, anyway, and I suspect that MSC works the same
>way), and command.com doesn't return an error code if the called
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>program fails. (!)  
 ^^^^^^^^^^^^^

No waranties expressed or implied, use at own risk, etc.

I've been using these patches for years with no problems.  Source (sort of)
is included for those worried about virus problems.

(This is from a make package some friends and I wrote a while ago--ignore any
references to make that didn't get edited out.)


              -------------------------------------------------
              COMMAND.COM patch to return ERRORLEVEL from child
              _________________________________________________



There is a feature (bug) in COMMAND.COM that causes MAKE not to be able to 
detect when commands that involve redirection fail.  This is because MAKE
executes these commands using a sub-shell and the sub-shell does not return
the exit code of the command it executed.

What follow are patches for COMMAND.COM version 2.11 (MS only) and versions
3.20 and 3.30 (MS and IBM versions).

______________________________________________________________________________

Patch to return ERRORLEVEL as exit code when COMMAND.COM terminates.
Note that in 3.20 and 3.30, ERRORLEVEL is already returned correctly when a
sub-shell is terminated with the EXIT command.  This patch does not cause
built-in commands (DEL, etc.) to return failure exit codes.

This patch is valid for MSDOS version 2.11.  THIS IS NOT VALID FOR PCDOS!

0220:                            B8 00 4C CD  21             MS-DOS 2.11
0AC0:                            00 00 00 00  00 00 00 00    COMMAND.COM
19C0:        06 8E  06 BA 2C 26  A1 35 08 26  A3 16 00 07
19D0:  8E 06 BC 2C  B4 49 CD 21  B8 00 4C CD  21

0220:                            E9 9D 08 90  90             2.11 Patch
0AC0:                            B4 4C 2E A0  75 08 CD 21
19C0:        8E 06  BA 2C 06 B8  C8 0A 50 26  A1 35 08 26
19D0:  A3 16 00 8E  06 BC 2C B4  49 CD 21 CB  90
_________________________________________________________

This patch is valid for MSDOS and PCDOS version 3.20.

0210:  A1 9C 0A 2E  A3 16 00 A1  9E 0A 2E A3  0A 00 A1 A0    3.20 COMMAND.COM
0220:  0A 2E A3 0C  00 B8 00 4C 

0210:  0E 07 FC BE  9C 0A AD 26  A3 16 00 BF  0A 00 A5 A5    3.20 Patch
0220:  A0 FA 0A B4  4C 90 90 90
_________________________________________________________

This patch is valid for MSDOS and PCDOS version 3.30.

023A:                                  A1 8C  0B 2E A3 16    3.30 COMMAND.COM
0240:  00 A1 8E 0B  2E A3 0A 00  A1 90 0B 2E  A3 0C 00 B8
0250:  00 4C

023A:                                  0E 07  FC BE 8C 0B    3.30 Patch
0240:  AD 26 A3 16  00 BF 0A 00  A5 A5 B4 4C  A0 EA 0B 90
0250:  90 90
______________________________________________________________________________

MS-DOS 2.11 COMMAND.COM

0228 B8004C         MOV     AX,4C00         ; "/C" termination
022B CD21           INT     21

19C2 06             PUSH    ES              ; "EXIT" command processor
19C3 8E06BA2C       MOV     ES,[2CBA]       ; in transient section
19C7 26A13508       MOV     AX,ES:[0835]
19CB 26A31600       MOV     ES:[0016],AX
19CF 07             POP     ES
19D0 8E06BC2C       MOV     ES,[2CBC]
19D4 B449           MOV     AH,49
19D6 CD21           INT     21
19D8 B8004C         MOV     AX,4C00
19DB CD21           INT     21
____________________________________________

MS-DOS 2.11 Patch

0228 E99D08         JMP     0AC8            ; "/C" termination -- jump to
022B 90             NOP                     ; exit patch
022C 90             NOP

0AC8 B44C           MOV     AH,4C           ; terminate process with exit
0ACA 2EA07508       MOV     AL,CS:[0875]    ; code set to ERRORLEVEL
0ACE CD21           INT     21

19C2 8E06BA2C       MOV     ES,[2CBA]       ; "EXIT" command in overlay
19C6 06             PUSH    ES
19C7 B8C80A         MOV     AX,0AC8         ; put address of exit patch in
19CA 50             PUSH    AX              ; root on stack
19CB 26A13508       MOV     AX,ES:[0835]
19CF 26A31600       MOV     ES:[0016],AX
19D3 8E06BC2C       MOV     ES,[2CBC]
19D7 B449           MOV     AH,49
19D9 CD21           INT     21
19DB CB             RETF                    ; jump to exit patch
19DC 90             NOP
______________________________________________________________________________

0210 A19C0A         MOV     AX,[0A9C]               ; MSDOS COMMAND.COM 3.20
0213 2EA31600       MOV     CS:[0016],AX
0217 A19E0A         MOV     AX,[0A9E]       ; "/C" termination
021A 2EA30A00       MOV     CS:[000A],AX
021E A1A00A         MOV     AX,[0AA0]
0221 2EA30C00       MOV     CS:[000C],AX
0225 B8004C         MOV     AX,4C00
0228 CD21           INT     21

2728 B44C           MOV     AH,4C           ; "EXIT" command termination
272A 26A0FA0A       MOV     AL,ES:[0AFA]
272E CD21           INT     21
____________________________________________

0210 0E             PUSH    CS                      ; 3.20 Patch
0211 07             POP     ES
0212 FC             CLD
0213 BE9C0A         MOV     SI,0A9C
0216 AD             LODSW
0217 26A31600       MOV     ES:[0016],AX
021B BF0A00         MOV     DI,000A
021E A5             MOVSW
021F A5             MOVSW
0220 A0FA0A         MOV     AL,[0AFA]
0223 B44C           MOV     AH,4C
0225 90             NOP
0226 90             NOP
0227 90             NOP
0228 CD21           INT     21
______________________________________________________________________________

023A A18C0B         MOV     AX,[0B8C]               ; MS-DOS COMMAND.COM 3.30
023D 2EA31600       MOV     CS:[0016],AX
0241 A18E0B         MOV     AX,[0B8E]       ; "/C" termination
0244 2EA30A00       MOV     CS:[000A],AX
0248 A1900B         MOV     AX,[0B90]
024B 2EA30C00       MOV     CS:[000C],AX
024F B8004C         MOV     AX,4C00
0252 CD21           INT     21

2CE8 B44C           MOV     AH,4C           ; "EXIT" command termination
2CEA 26A0EA0B       MOV     AL,ES:[0BEA]
2CEE CD21           INT     21
__________________________________________

023A 0E             PUSH    CS                    ; 3.30 Patch
023B 07             POP     ES
023C FC             CLD
023D BE8C0B         MOV     SI,0B8C
0240 AD             LODSW
0241 26A31600       MOV     ES:[0016],AX
0245 BF0A00         MOV     DI,000A
0248 A5             MOVSW
0249 A5             MOVSW
024A B44C           MOV     AH,4C
024C A0EA0B         MOV     AL,[0BEA]
024F 90             NOP
0250 90             NOP
0251 90             NOP
0252 CD21           INT     21

------------------------------------------

alexande@drivax.DRI (Mark Alexander) (01/25/89)

One possible solution to the problem of COMMAND.COM always returning
zero is that used by NDMAKE.  The basic idea is to construct on the
fly a little batch file that gets passed to COMMAND.COM.  Before you
call system(), though, you create a little zero-length temporary file.
The batch file runs the subprogram, then checks the errorlevel.  If
the errorlevel is 0, it deletes the temporary file.  Then the main
program gets control again and checks the existence of the temporary
file: if it still exists, an error occurred.

The batch file would look something like this:
	prog [parms...] [<infile] [>outfile]
	if errorlevel 1 goto done
	del tempfile
	:done
-- 
Mark Alexander	(amdahl!drivax!alexande)

bkbarret@sactoh0.UUCP (Brent K. Barrett) (01/25/89)

In article <2439@nunki.usc.edu>, jeenglis@nunki.usc.edu (Joe English) writes:
> 
> In article <782@hawkmoon.MN.ORG> det@hawkmoon.MN.ORG (Derek E. Terveer) writes:
> >Has anyone encountered a problem with the Microsoft C 5.0 compiler always
> >returning a 0 from the system() call, no matter what the actual command
> >executed by system() returns?
> 
> That, unfortunately, is right.  system() returns the exit status of
> command.com (in Turbo C, anyway, and I suspect that MSC works the same
> way), and command.com doesn't return an error code if the called
> program fails. (!)  (system() also returns non-zero if command.com could
> not be loaded for lack of memory.)
> 
 That may not be entirely correct, at least as far as TC goes. In
Turbo C 2.0 (and, I believe, 1.5, even though it was not
documented), system() will return 0 if command.com was successfully
loaded, and -1 if command.com was not found. I do not know the ANSI
standard on this beast (if indeed there is one), but since MSC and
TC both have it functioning this way, I'm going to assume it's
ANSI. 
 
 You are correct that spawn()/exec() should be used to return the
proper errorlevels. I ran into this exact same problem a few days
ago when I wanted to run a small utility program externally from a
larger program without removing the larger program from memory. An
errorlevel had to be returned and system() didn't seem to want to
do it. I was confused by the TC 1.0 manual and the 2.0 THELP. The
manual stated that the errorlevel was returned, while the THELP
indicated the true condition. Since I only ordered the upgrade to
2.0, I did not receive a full 2.0 manual, and only have the 1.0
description of system(). Fortunately for me, a Borland beta tester
is easily accessable.
                                  
-- 
 "Somebody help me! I'm trapped in this computer!"
  
 Brent Barrett ..pacbell!sactoh0!bkbarret GEMAIL: B.K.BARRETT

wietse@wzv.UUCP (Wietse Z. Venema) (01/25/89)

In article <782@hawkmoon.MN.ORG> det@hawkmoon.MN.ORG (Derek E. Terveer) writes:
>Has anyone encountered a problem with the Microsoft C 5.0 compiler always
>returning a 0 from the system() call, no matter what the actual command
>executed by system() returns?

Command.com always returns a zero status. There are two alternatives:

(a) Do not use a shell, but use the spawnlp() functions. These are
    similar to the unix execlp() functions, but instead of over-
    laying the calling process they just suspend it.

(b) Use a different shell. This may not be practical if your program
    is to be used on other machines.

In case of alternative (a) you will have to do your own i/o redirection
handling.  Caveat:  in some cases I had to save the positions of all
stdio streams open for reading from files, and restore them after the
system() routine terminated.
-- 
work:	wswietse@eutrc3.uucp	| Eindhoven University of Technology
work:	wswietse@heitue5.bitnet	| Mathematics and Computing Science
home:	wietse@wzv.uucp		| 5600 MB Eindhoven, The Netherlands

bobmon@iuvax.cs.indiana.edu (RAMontante) (01/25/89)

[ The "system()" returns 0 after invoking COMMAND.COM,
  in MSC and TC on MSDOS machines ]

<646@sactoh0.UUCP> bkbarret@sactoh0.UUCP (Brent K. Barrett):
>
> That may not be entirely correct, at least as far as TC goes. In
>Turbo C 2.0 (and, I believe, 1.5, even though it was not
>documented), system() will return 0 if command.com was successfully
>loaded, and -1 if command.com was not found. I do not know the ANSI
>standard on this beast (if indeed there is one), but since MSC and
>TC both have it functioning this way, I'm going to assume it's
>ANSI. 

"System()" in Turbo C is specifically defined to "...invoke COMMAND.COM
to execute a command...".  In TCv1.5 the return value is described as
the exit status of COMMAND.COM.  Unfortunately (but not surprisingly)
COMMAND.COM exits with a 0 if it successfully loads and runs, whether
the executable file that it was supposed to execute was successful or
not.  So the only information that you can get back from COMMAND.COM is
whether it (loaded and) ran, or crashed the whole dam' machine; nothing
about what it did while it was running.  This has nothing to do with
ANSI, which doesn't specify the behavior of MSDOS.  The C "system()"
call is doing what it should, but what it receives from the operating
system isn't any use to anyone (except in the case of a missing
COMMAND.COM file).

> You are correct that spawn()/exec() should be used to return the
>proper errorlevels.

No problem here, as COMMAND.COM isn't involved.  The executed file is
responsible for returning a meaningful value to spawn() / exec().

ray@ole.UUCP (Ray Berry) (01/26/89)

value from the last program it executed.  There are times when it would be
handy to be able to interrogate that number from the command line.  Does
anyone know a way to do this?   The location of the variable?

       Obviously a short shell could be written in c to execute it and
print the value, but it seems as though it the ERRORLEVEL variable must
be present somewhere in memory. 
	


-- 
Ray Berry  KB7HT uucp: ...{uw-beaver|uiucuxc}tikal!ole!ray CS: 73407,3152 
Seattle Silicon Corp. 3075 112th Ave NE. Bellevue WA 98004 (206) 828 4422

bright@Data-IO.COM (Walter Bright) (01/26/89)

In article <782@hawkmoon.MN.ORG> det@hawkmoon.MN.ORG (Derek E. Terveer) writes:
>Has anyone encountered a problem with the Microsoft C 5.0 compiler always
>returning a 0 from the system() call, no matter what the actual command
>executed by system() returns?

system("command") on MS-DOS is usually implemented by running COMMAND.COM
with the argument "/c command". The system() call returns the value that
COMMAND.COM returns. COMMAND.COM does not return the exit status of the
command that it executed, so it's a DOS bug, not a compiler library bug.

The correct solution is to use the spawn() function. spawn() also uses
less memory and executes faster than system(). The only caveats are that
spawn() cannot execute COMMAND.COM's built-in commands like TYPE and DIR,
and spawn() does not do the < | > redirection.

ked@garnet.berkeley.edu (Earl H. Kinmonth) (01/26/89)

In article <782@hawkmoon.MN.ORG> det@hawkmoon.MN.ORG (Derek E. Terveer) writes:
>Has anyone encountered a problem with the Microsoft C 5.0 compiler always
>returning a 0 from the system() call, no matter what the actual command
>executed by system() returns?

The same brain dead result occurs with the Turbo C system call.  Presumably
the problem is in command.com.  I wrote my own system() using spawn to get
around this.

Remember, you don't get to be a multi-billion dollar company by doing this
for the conveience of users.

scm@datlog.co.uk ( Steve Mawer ) (01/26/89)

In article <782@hawkmoon.MN.ORG> det@hawkmoon.MN.ORG (Derek E. Terveer) writes:
>Has anyone encountered a problem with the Microsoft C 5.0 compiler always
>returning a 0 from the system() call, no matter what the actual command
>executed by system() returns?
>
>and i'm having a hard time of it since system() always (seems) to return 0!
>

According to my Microsoft manual "The system function returns the value
0 if string is successfully executed.  A return value of -1 indicates an
error ..." and cites the error reasons as being

    E2BIG   - arg list > 128 bytes or env info >32K
    ENOENT  - can't find COMMAND.COM
    ENOEXEC - COMMAND.COM file can't be executed
    ENOMEM  - insufficient memory to execute the command, etc.

What it returns is whether its exec succeeded, not the exec'd command's
status.  I have been burned by this problem, too, and haven't got a
solution. (Anyone?)

-- 
Steve C. Mawer        <scm@datlog.co.uk> or < {backbone}!ukc!datlog!scm >
                       Voice:  +44 1 863 0383 (x2153)

sme@computing-maths.cardiff.ac.uk (Simon Elliott) (02/01/89)

In article <782@hawkmoon.MN.ORG>, det@hawkmoon.MN.ORG (Derek E. Terveer) writes:
> Has anyone encountered a problem with the Microsoft C 5.0 compiler always
> returning a 0 from the system() call, no matter what the actual command
> executed by system() returns?
  
> -- 
> Derek Terveer  det@hawkmoon.MN.ORG || ..!uunet!rosevax!elric!hawkmoon!det

The problem is that system works by constructing a "command /c yourcommand",
thus letting commnad.com do the work of looking down the path, etc.
command.com _always_ succeeds, so system returns 0, always.  You have to do
the work yourself, and use one of the spawn/exec functions if you want
meaningful status information.

I have used this behaviour of command.com in makefiles when i want to
clean up files which may not be there.  Some versions of make will croak
if the file is not there, since the 'del' is a builtin, but command /c del
will always succeed, and the make continues.




-- 
--------------------------------------------------------------------------
Simon Elliott            Internet: sme%v1.cm.cf.ac.uk@cunyvm.cuny.edu
UWCC Computer Centre     JANET:    sme@uk.ac.cf.cm.v1
40/41 Park Place         UUCP:     {backbones}!mcvax!ukc!reading!cf-cm!sme
Cardiff, Wales           PHONE:    +44 222 874300