Are there standard numbers for various errors?

  • Thread starter Walter Dnes (delete the 'z' to get my real address
  • Start date
W

Walter Dnes (delete the 'z' to get my real address

A long time ago, in a place far away, there was an OS called DOS that
had standard numeric return codes. Regardless of the programming
language used, the same error return codes were supposed to be used. See
http://www.felgall.com/doserr.htm for a larger list. It starts like so...

# 1 Invalid Function Code
# 2 File Not Found
# 3 Path Not Found
# 4 No Handles Available, Too Many Open Files
# 5 Access Denied
# 6 Invalid File Handle

As per the subject of my post, are there any standards for error
return codes in C? Right now, I'm using 1 for lack of anything better,
unless there's some over-riding reason. Here's the start of a typical
program...

#include <stdio.h>
int main(int argc, char *argv[])
{
unsigned long int accumulator, b1[256];
float percent;
int i, pixel;
FILE *input_file, *output_file;

if(argc != 3){
printf(" Correct usage:\n %s input_filename output_filename\n", argv[0]);
return 1;
}
if((input_file = fopen(argv[1], "rb")) == NULL){
printf("Error opening %s for input\n", argv[1]);
return 1;
}
if((output_file = fopen(argv[2], "w")) == NULL){
printf("Error opening %s for output\n", argv[2]);
return 1;
 
E

Erik Trulsson

Walter Dnes (delete the 'z' to get my real address) said:
A long time ago, in a place far away, there was an OS called DOS that

There have actually been several OS called DOS; I guess you are
thinking of the one named MS-DOS.
had standard numeric return codes. Regardless of the programming
language used, the same error return codes were supposed to be used. See
http://www.felgall.com/doserr.htm for a larger list. It starts like so...

# 1 Invalid Function Code
# 2 File Not Found
# 3 Path Not Found
# 4 No Handles Available, Too Many Open Files
# 5 Access Denied
# 6 Invalid File Handle

As per the subject of my post, are there any standards for error
return codes in C? Right now, I'm using 1 for lack of anything better,
unless there's some over-riding reason. Here's the start of a typical
program...

The only program return codes that are defined by the standard are that
if a program exits successfully it should return 0 or EXIT_SUCCESS, and
if it fails it should return EXIT_FAILURE.
The macros EXIT_SUCCESS and EXIT_FAILURE are defined in <stdlib.h>
 
G

Gordon Burditt

A long time ago, in a place far away, there was an OS called DOS that

There were a lot of OSs called DOS. Many of them had nothing to do
with Microsoft or with Intel hardware.
had standard numeric return codes. Regardless of the programming
language used, the same error return codes were supposed to be used. See
http://www.felgall.com/doserr.htm for a larger list. It starts like so...

# 1 Invalid Function Code
# 2 File Not Found
# 3 Path Not Found
# 4 No Handles Available, Too Many Open Files
# 5 Access Denied
# 6 Invalid File Handle

I know of a lot of uses of program exit codes (used in COMMAND.COM
batch scripts) that did not conform to this usage. Many scripts
would run a program which would throw up a menu and get an answer
from the user, then return the user's choice. The exit code then
told the batch script the user's choice, which often used small
numbers like the above, and the script did what was asked.
Choices might be something like: (1) install, (2) uninstall,
(3) display help file, (4) quit
As per the subject of my post, are there any standards for error
return codes in C?

C has a few error codes that are typically deposited in errno after
an error, such as ERANGE and EDOM. Many implementations, such as
UNIX, add a lot more of them. These codes do not have standard
integer values; ERANGE has a value of ERANGE everywhere, but it's
not guaranteed that ERANGE == 0xdeadbeef anywhere. Sometimes
the codes in errno or extensions of these local to the program
are used as function return values (where 0 indicates success).

Exit values from a program are not "error codes" per se. The
standard values for use as an argument of exit() or return from
main() are EXIT_SUCCESS, 0, and EXIT_FAILURE.

Note that a program might terminate abnormally for a number of
reasons, including the negative of what the OS might consider to
be an error: "Access Granted", or "File Found" might be a fatal
error (for example, some programs refuse to overwrite existing files
and specially test for this). There are also plenty of reasons for
terminating a program that don't deal with an OS error at all:
missing or conflicting options or command-line arguments, syntax
error in the input, bad database password, etc.

Note that it's often much more important to tell the user *WHAT*
failed then *WHY*. A user usually has a better chance of figuring
the problem out if the program says that "foobar.txt cannot be
opened for writing" than if it says "permission denied" without
saying *WHAT* permission was denied.

Gordon L. Burditt
 
A

August Derleth

There have actually been several OS called DOS; I guess you are
thinking of the one named MS-DOS.

Or FreeDOS or OpenDOS or DR-DOS or PC-DOS or QDOS ...
The only program return codes that are defined by the standard are that
if a program exits successfully it should return 0
[snip]

This has always kind of confused me: Given that in VMS, a return code of 0
indicates an unsuccessful execution, what does the compiler do with a
main() that ends with return 0;? (This is only confusing because the
compiler would have to contradict what the programmer said to do what the
programmer meant, something distinctly un-C-like to my mind.)
 
J

Joe Wright

August said:
There have actually been several OS called DOS; I guess you are
thinking of the one named MS-DOS.


Or FreeDOS or OpenDOS or DR-DOS or PC-DOS or QDOS ...

The only program return codes that are defined by the standard are that
if a program exits successfully it should return 0

[snip]

This has always kind of confused me: Given that in VMS, a return code of 0
indicates an unsuccessful execution, what does the compiler do with a
main() that ends with return 0;? (This is only confusing because the
compiler would have to contradict what the programmer said to do what the
programmer meant, something distinctly un-C-like to my mind.)

If you insist on relating various OS behaviours to various
programming languages, it may be that you will remain confused. C
does have a familial (incestuous) relationship with Unix because Ken
Thompson and Dennis Ritchie did C and Unix together.

While C may be 'Unix friendly' in some ways, the Implementor of C on
a VMS system will make allowances such that 'return 0;' will do the
right thing for VMS.
 
D

Darrell Grainger

A long time ago, in a place far away, there was an OS called DOS that
had standard numeric return codes. Regardless of the programming
language used, the same error return codes were supposed to be used. See
http://www.felgall.com/doserr.htm for a larger list.

I'm not sure if felgall is referring to PC-DOS or MS-DOS. Regardless, I do
not believe this was a widely adapted standard. I wrote and used many
application on PC-DOS and MS-DOS that did not comform to this standard.
It starts like so...

# 1 Invalid Function Code
# 2 File Not Found
# 3 Path Not Found
# 4 No Handles Available, Too Many Open Files
# 5 Access Denied
# 6 Invalid File Handle

As per the subject of my post, are there any standards for error
return codes in C? Right now, I'm using 1 for lack of anything better,
unless there's some over-riding reason. Here's the start of a typical
program...

If a program is successful, return EXIT_SUCCESS or 0. If a program fails,
return EXIT_FAILURE. Beyond that there is no standard.

When I wrote programs for batch scripting and the error code would be
important, I would pick values and document them; note that these sort of
programs tend to be operating system specific. That way if someone wanted
to use my application they knew what the different error codes, coming
from my application, would mean. I always return 0 for success.
#include <stdio.h>
int main(int argc, char *argv[])
{
unsigned long int accumulator, b1[256];
float percent;
int i, pixel;
FILE *input_file, *output_file;

if(argc != 3){
printf(" Correct usage:\n %s input_filename output_filename\n", argv[0]);
return 1;
}
if((input_file = fopen(argv[1], "rb")) == NULL){
printf("Error opening %s for input\n", argv[1]);
return 1;
}
if((output_file = fopen(argv[2], "w")) == NULL){
printf("Error opening %s for output\n", argv[2]);
return 1;

I'd return 1 for incorrect number of arguments, 2 for failure to open read
file and 3 for failure to open write file.

Different operating systems might have other standards but C language does
not.
 
R

red floyd

August Derleth said:
This has always kind of confused me: Given that in VMS, a return code of 0
indicates an unsuccessful execution, what does the compiler do with a
main() that ends with return 0;? (This is only confusing because the
compiler would have to contradict what the programmer said to do what the
programmer meant, something distinctly un-C-like to my mind.)

I would assume that either

a) in VAX-C (or any other VMS C compiler) EXIT_SUCCESS and
EXIT_FAILURE are defined appropriately for that platform, or
b) in VAX-C (or any other VMS C compiler) the CRT catches the return
from main(), and deals with it appropriately before dropping dead. I
have no idea what it would do with exit().
 
S

Stephen Sprunk

"Walter Dnes (delete the 'z' to get my real address)"
A long time ago, in a place far away, there was an OS called DOS that
had standard numeric return codes. Regardless of the programming
language used, the same error return codes were supposed to be used. See
http://www.felgall.com/doserr.htm for a larger list. It starts like so... ....
As per the subject of my post, are there any standards for error
return codes in C? Right now, I'm using 1 for lack of anything better,
unless there's some over-riding reason. Here's the start of a typical
program...

Most standard C functions return NULL or -1 to indicate an error, and set
errno to the exact reason. Other functions can return the error (negated)
because they return only non-negative signed values on success. Either
convention will be understood by others reading your code.

POSIX.1 specifies a number of symbolic names for error codes, but
implementations can give them any value they want; of course, this means you
need to find the right header to include so you get the macros defined
correctly for your platform. On Linux the man page for errno(3) gives a
list of the standard error codes, and the numeric values can be found in
<asm/errno.h>. FreeBSD is probably somewhat similar, but you'll need to dig
around to find out.

S
 
C

Chris Torek

This has always kind of confused me: Given that in VMS, a return code of 0
indicates an unsuccessful execution, what does the compiler do with a
main() that ends with return 0;? (This is only confusing because the
compiler would have to contradict what the programmer said to do what the
programmer meant, something distinctly un-C-like to my mind.)

In "very old VMS" (pre-1989-C-standard) C, the startup code did the
equivalent of:

exit(main(argc, argv));

Now, however, it does the equivalent of this:

result = main(argc, argv);
if (result == 0)
result = 1;
sys$exit(result);

Hence, 0 converts to 1, 1 (EXIT_SUCCESS) stays 1, and other
values including EXIT_FAILURE stay themselves.
 
A

August Derleth

August said:
The only program return codes that are defined by the standard are that
if a program exits successfully it should return 0

[snip]

This has always kind of confused me: Given that in VMS, a return code of 0
indicates an unsuccessful execution, what does the compiler do with a
main() that ends with return 0;? (This is only confusing because the
compiler would have to contradict what the programmer said to do what the
programmer meant, something distinctly un-C-like to my mind.)

If you insist on relating various OS behaviours to various
programming languages, it may be that you will remain confused. C
does have a familial (incestuous) relationship with Unix because Ken
Thompson and Dennis Ritchie did C and Unix together.

I know that. Unix was implemented in C very early on (though not the first
couple times) and C very likely mirrors the kind of machine T&R wanted for
their Unix systems.

(Also, C is a modified and stripped-down BCPL, Unix is a modified and
stripped-down Multics. Bastard children, both of them. ;) )

None of that is relevant here.
While C may be 'Unix friendly' in some ways, the Implementor of C on
a VMS system will make allowances such that 'return 0;' will do the
right thing for VMS.

I was wondering what the Standard itself said. Maybe I could have made
that clearer. If so, I'm sorry.
 
C

CBFalconer

Chris said:
In "very old VMS" (pre-1989-C-standard) C, the startup code did
the equivalent of:

exit(main(argc, argv));

Now, however, it does the equivalent of this:

result = main(argc, argv);
if (result == 0)
result = 1;
sys$exit(result);

I would expect that to need to be:

if (0 == (_result = main(argc, argv))) _result = 1;
else if (EXIT_FAILURE == _result) _result = 0;
else if (EXIT_SUCCESS == _result) _result = 1;

and EXIT_SUCCESS could never be defined as 0.

(and this is just the sort of thing that illustrates why C
programs should not return arbitrary integers at exit)
 
E

Eric Sosman

red said:
I would assume that either

a) in VAX-C (or any other VMS C compiler) EXIT_SUCCESS and
EXIT_FAILURE are defined appropriately for that platform, or
b) in VAX-C (or any other VMS C compiler) the CRT catches the return
from main(), and deals with it appropriately before dropping dead. I
have no idea what it would do with exit().

VAXC was a pre-Standard implementation. The value passed to
exit() or returned from main() was a standard VMS status code, so
even values meant "failure" and odd values meant "success" (there
were several flavors of each). VAXC never became fully Standard-
conforming (DEC presumably figured that it would break too much
existing code to attempt such a thing), but in the later releases
a hack was added to the library: An exit status of 0 or 1 was
translated to the other so that programs naively ported from Unix
would work as expected. Other exit statuses were passed along
unchanged, so VMS-aware programs could still return an "amplified"
exit status.

DECC was an entirely new implementation, intended to be Standard-
conforming. As such, it provided EXIT_SUCCESS and EXIT_FAILURE, but
hackery was still required for an exit status of zero. I worked with
DECC only a little, on the early Alpha systems, and I don't recall
the numeric values of the EXIT_xxx macros.
 
D

Dan Pop

In said:
In "very old VMS" (pre-1989-C-standard) C, the startup code did the
equivalent of:

exit(main(argc, argv));

Now, however, it does the equivalent of this:

result = main(argc, argv);
if (result == 0)
result = 1;
sys$exit(result);

Hence, 0 converts to 1, 1 (EXIT_SUCCESS) stays 1, and other
values including EXIT_FAILURE stay themselves.

I don't get it: since exit(0) must perform the very same conversion,
what's the point of changing the C startup code?

Dan
 
C

Chris Torek

I don't get it: since exit(0) must perform the very same conversion,
what's the point of changing the C startup code?

I am not sure they did. Perhaps the tests are indeed in exit(). I
have not used the Alpha implementation of VMS; I have only heard
that it translates 0 to 1.

This is why I said "does the equivalent of this", rather than "does
this". :) It would probably have been better to show it as a change
to exit() though:

/* old */
void exit(int status) { sys$exit(status); }

/* new */
void exit(int status) { sys$exit(status ? status : 1); }

Of course, exit() does more than just call sys$exit (which might
actually be spelled SYS$exit, etc.), which is why I did not want
to show it as a change to exit() in the first place.... (The
library exit() function has to flush stdio buffers, call any
atexit() routines, and only then invoke the VMS "exit" system
call.)
 
D

Dan Pop

In said:
I am not sure they did. Perhaps the tests are indeed in exit(). I
have not used the Alpha implementation of VMS; I have only heard
that it translates 0 to 1.

This is why I said "does the equivalent of this", rather than "does
this". :) It would probably have been better to show it as a change
to exit() though:

/* old */
void exit(int status) { sys$exit(status); }

/* new */
void exit(int status) { sys$exit(status ? status : 1); }

Yup, now it makes sense.
Of course, exit() does more than just call sys$exit (which might
actually be spelled SYS$exit, etc.), which is why I did not want
to show it as a change to exit() in the first place.... (The
library exit() function has to flush stdio buffers, call any
atexit() routines, and only then invoke the VMS "exit" system
call.)

But all these things *also* happen when returning from main(), so your
original approach bought you NOTHING in terms of completeness. The
right way of showing it is a change to exit():

/* old */
void exit(int status) { ...; sys$exit(status); }

/* new */
void exit(int status) { ...; sys$exit(status ? status : 1); }

where the odd ... statement obviously stands for all the other actions
performed by exit() before actually passing the control back to the
execution environment.

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top