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