[comp.lang.c] exit

ADLER1%BRANDEIS.BITNET@CUNYVM.CUNY.EDU (12/16/87)

I was looking through the file crt0.c in the GNU emacs source code and
found the command

exit(main(argc,argv,env));

which I find puzzling. I thought that one was supposed to give exit a
number for an argument. What does the above command do and why would
anyone want to do it that way ?

ADLER1@BRANDEIS.BITNET

pardo@uw-june.UUCP (David Keppel) (12/17/87)

>why:
> exit(main(argc,argv,env))

Guesses:

The C compiler (or the loader, or whatever) guarantees that there is some
function called "main" that is the thing you want to execute first.
Main is defined as returning an int, so exit() gets an int.

Therefore this code can set up whatever it needs, call main, and then
exit with whatever status code main exited with.  This would be like

	status = main(argc,argv,envp);
	exit(status);

but doesn't use an extra variable.

	;-D on  (Well it _sounded_ like a good idea at the time!)  Pardo

gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/17/87)

In article <10875@brl-adm.ARPA> ADLER1%BRANDEIS.BITNET@CUNYVM.CUNY.EDU writes:
>exit(main(argc,argv,env));
>which I find puzzling. I thought that one was supposed to give exit a
>number for an argument.

exit() takes an int argument; main() returns an int value.
What don't you understand?

By the way, the "env" parameter is nonstandard, although it
doesn't matter on some architectures.

ljz@fxgrp.UUCP (Lloyd Zusman, Master Byte Software) (12/17/87)

In article <10875@brl-adm.ARPA> ADLER1%BRANDEIS.BITNET@CUNYVM.CUNY.EDU writes:
>I was looking through the file crt0.c in the GNU emacs source code and
>found the command
>
>exit(main(argc,argv,env));
>
>which I find puzzling. I thought that one was supposed to give exit a
>number for an argument. What does the above command do and why would
>anyone want to do it that way ?


This command invokes your main() routine with the proper arguments.  Just
like any other C function, main() returns a value.  Consider the following
code fragment ...

    int retcode;
          .
    	  .
    	  .
    retcode = main(argc, argv, env);
    exit(retcode);

In this case, exit() is getting a number as its argument.  This is equivalent
to the "exit(main(argc, argv, env))" command that was mentioned above.

Perhaps your confusion is due to the fact that you didn't think that main()
is the same as other functions.  It is.  You can give it a return()
statement ...

    main()
    {
    	    .
    	    .
    	    .
    	return(99);
    }

This is supposed to be equivalent to

    main()
    {
    	    .
    	    .
    	    .
    	exit(99);
    }

I say "supposed to" because I've used C compilers on the IBM PC where
this doesn't work.

The "exit(main(...))" construct in the crt0.c will ensure that this
construct works like it should.





-------------------------------------------------------------------------
 Lloyd Zusman
 Master Byte Software
 Los Gatos, California	    	    	Internet:   fxgrp!ljz@ames.arpa
 "We take things well in hand."	    	UUCP:	    ...!ames!fxgrp!ljz

ncbauers@ndsuvax.UUCP (Michael Bauers) (12/17/87)

In article <10875@brl-adm.ARPA> ADLER1%BRANDEIS.BITNET@CUNYVM.CUNY.EDU writes:
>I was looking through the file crt0.c in the GNU emacs source code and
>found the command
>exit(main(argc,argv,env));
>which I find puzzling. I thought that one was supposed to give exit a
>number for an argument. What does the above command do and why would
>anyone want to do it that way ?

	Well I have never seen syntax like this...but it should just recur-
sively call main.  I assume you know what argc, argv, and env are.  Main
would be in big trouble if it did not have a normal exit statement which
presumably is of the form exit(n).

mr@homxb.UUCP (mark) (12/18/87)

In article <10875@brl-adm.ARPA>, ADLER1%BRANDEIS.BITNET@CUNYVM.CUNY.EDU writes:
> I was looking through the file crt0.c in the GNU emacs source code and
> found the command
> 
> exit(main(argc,argv,env));
> 
> which I find puzzling. I thought that one was supposed to give exit a
> number for an argument. What does the above command do and why would
> anyone want to do it that way ?
> 
> ADLER1@BRANDEIS.BITNET

main() returns an int which is then the argument to exit() and is then
returned to the shell or whatever exec'ed the program.

This brings up an interesting problem :

	What if you declare main to return something other than an int ?
	Is that allowed ?

mark
homxb!mr

marty1@houdi.UUCP (M.BRILLIANT) (12/18/87)

> 
> I was looking through the file crt0.c in the GNU emacs source code and
> found the command
> 
> exit(main(argc,argv,env));
> 
> which I find puzzling. I thought that one was supposed to give exit a
> number for an argument. What does the above command do and why would
> anyone want to do it that way ?
> 
> ADLER1@BRANDEIS.BITNET

Yeah, I second the question.  What this does is execute main(...)  and
then give exit() the number that main returns.  So main(...) must have
in it some statements of the form return(3); or return(status); so that
exit() will get a useful number.  But the same effect would be achieved
if main() had statements of the form exit(3); or exit(status);.

The key question is where the exit(main(..)) was found.  Since main()
is the first function called, no statement is needed to invoke main(). 
Put it another way, since main() is invoked anyway, any statement that
calls main() must call it recursively.  Why would anybody do that?

M. B. Brilliant					Marty
AT&T-BL HO 3D-520	(201)-949-1858
Holmdel, NJ 07733	ihnp4!houdi!marty1

daveb@laidbak.UUCP (Dave Burton) (12/18/87)

In article <10875@brl-adm.ARPA> ADLER1%BRANDEIS.BITNET@CUNYVM.CUNY.EDU writes:
>I was looking through the file crt0.c in the GNU emacs source code and
>found the command
>
>exit(main(argc,argv,env));
>
>which I find puzzling. I thought that one was supposed to give exit a
>number for an argument. What does the above command do and why would
>anyone want to do it that way ?
>
>ADLER1@BRANDEIS.BITNET

Actually, "main(...)" DOES give exit() an integer argument.
Remember, any function without a type declaration in C is implicitly
a function returning int.

This line of code simply starts the C program at the symbol "main",
passing the usual arguments to it. When main returns, an integer value
is pushed on the stack for the exit().

I don't have the emacs source, so I don't know exactly what main()
returns to exit(). If no explicit return is given, the value returned
is undefined. If main() quits with an exit() call, I believe the
exit(main()) will get the argument from the main(){ ... exit(x); }.
-- 
--------------------"Well, it looked good when I wrote it"---------------------
 Verbal: Dave Burton                        Net: ...!ihnp4!laidbak!daveb
 V-MAIL: (312) 505-9100 x325            USSnail: 1901 N. Naper Blvd.
#include <disclaimer.h>                          Naperville, IL  60540

daveb@laidbak.UUCP (Dave Burton) (12/18/87)

In article <176@fxgrp.UUCP> fxgrp!ljz@ames.arpa (Lloyd Zusman, Master Byte Software) writes:
>In article <10875@brl-adm.ARPA> ADLER1%BRANDEIS.BITNET@CUNYVM.CUNY.EDU writes:
>>...
>>found the command
>>exit(main(argc,argv,env));
>>which I find puzzling. ...
> ...
>    	return(99);
> ...
>This is supposed to be equivalent to
> ...
>    	exit(99);
> ...
>I say "supposed to" because I've used C compilers on the IBM PC where
>this doesn't work.



They are NOT equivalent!
At least in the UNIX environment, exit() is a function that flushes all
buffers (and closes all file descriptors?), as well as handling functions
registered via onexit(), finally calling _exit(), a system call that
never returns.

Using return instead of exit() bypasses this cleanup operation.




-- 
--------------------"Well, it looked good when I wrote it"---------------------
 Verbal: Dave Burton                        Net: ...!ihnp4!laidbak!daveb
 V-MAIL: (312) 505-9100 x325            USSnail: 1901 N. Naper Blvd.
#include <disclaimer.h>                          Naperville, IL  60540

gp@picuxa.UUCP (Greg Pasquariello X1190) (12/18/87)

In article <1451@houdi.UUCP>, marty1@houdi.UUCP (M.BRILLIANT) writes:
> 
> The key question is where the exit(main(..)) was found.  Since main()
> is the first function called, no statement is needed to invoke main(). 
> Put it another way, since main() is invoked anyway, any statement that
> calls main() must call it recursively.  Why would anybody do that?


On the compilers that I have seen, main() isn't the first routine called.
Rather, some startup code is included (typically called _main()) that in
turn invokes main().  Therefor exit(main(argc,argv,envp)) is an efficient
way (it saves a variable) to call main and return an exit status.

sbw@naucse.UUCP (Steve Wampler) (12/19/87)

In article <1451@houdi.UUCP>, marty1@houdi.UUCP (M.BRILLIANT) writes:
> > 
> > I was looking through the file crt0.c in the GNU emacs source code and
> > found the command
> > 
> > exit(main(argc,argv,env));
> 
> The key question is where the exit(main(..)) was found.  Since main()
> is the first function called, no statement is needed to invoke main(). 
> Put it another way, since main() is invoked anyway, any statement that
> calls main() must call it recursively.  Why would anybody do that?

The key is probably that the statement was found in crt0.c.  On all the
systems I'm familiar with, the 'main' function is not called directly
by the system - instead the system invokes a 'startup' routine that
opens standard files, munges the environment a bit, and then calls 'main'.
I'll bet the above code was in a routine 'start' or 'Start'.

Most of the languages I'm familiar with do this - I can remember rewriting
the FORTRAN startup routine on a CDC 6400 to process ratfor more cleanly,
patterned after an approach some friends used on a DEC-10.

wesommer@athena.mit.edu (William Sommerfeld) (12/19/87)

This really isn't a C question; it is a UNIX question.

> 
> I was looking through the file crt0.c in the GNU emacs source code and
> found the command
> 
> exit(main(argc,argv,env));
> 

First misconception: exit() is a _function_ in the C library.  It
happens to be different from other functions in that it never returns
control to its caller, but that's just a property of the
implementation; there isn't anything in the C compiler which
special-cases exit(), or abort(), or any of the other special
functions.  You don't have to pass it a constant integer.

On UNIX, crt0.c happens to be the module which sets up argv, argc, and
the environment and then calls main() with the appropriate arguments;
it is silently included into the load image by 'cc' when you use it to
link a program.  Needless to say, it is highly architecture- and OS-
dependant.

GNU emacs has its own version of crt0.c (with probably hundreds of
#ifdefs to account for all sorts of machine dependancies) because it
has to be able to dump out a core image of itself containing
pre-loaded emacs lisp, and then restart this core image later.

				- Bill

pardo@uw-june.UUCP (David Keppel) (12/19/87)

[Why does crt0.c have "exit(main(argc,argv,argp));"?  Isn't main called first?]

I think that crt0.c is responsible for implementing the convention that main()
is called first.  crt0.c shags some environment pointers off of the stack
and in some implementations may do other stuff.  crt0.c is called directly
by the kernel.  This also means that it is the *last* thing executed before
a user program terminates.

(Sorry if I got this wrong, but I think that's how it goes).

	;-D on  (Conventions?  NAHHHH... )  Pardo

jph@houxa.UUCP (J.HARKINS) (12/19/87)

In article <10875@brl-adm.ARPA>, ADLER1%BRANDEIS.BITNET@CUNYVM.CUNY.EDU writes:
> 
> exit(main(argc,argv,env));
> 
> which I find puzzling. I thought that one was supposed to give exit a
> number for an argument. What does the above command do and why would
> anyone want to do it that way ?

As the other posters have noted, main() returns an int which is what exit()
needs.  However, doing this also ensures that exit() will be called, even if it
is never explicitely called from main().  exit() may flush buffers, close files,
and perform other chores required for nice, systematic completion of a C program.
How many times have you seen buffered output not get printed because a program
died between the output statement and the physical flushing of its output buffer?
The exit(main()) ensures that things like this should not happen.

-------
Disclaimer: I hereby disclaim all my debts.
------

Jack Harkins @ AT&T Bell Labs
Princeton Information
(201) 949-3618
(201) 356-7573
ihnp4!houxa!jph

ljz@fxgrp.UUCP (Lloyd Zusman, Master Byte Software) (12/19/87)

In article <1451@houdi.UUCP> marty1@houdi.UUCP (M.BRILLIANT) writes:
>> I was looking through the file crt0.c in the GNU emacs source code and
>> found the command
>> 
>> exit(main(argc,argv,env));
> ...
>The key question is where the exit(main(..)) was found.  Since main()
>is the first function called, no statement is needed to invoke main(). 
>Put it another way, since main() is invoked anyway, any statement that
>calls main() must call it recursively.  Why would anybody do that?

It is a de facto and possibly also de jure standard in unix for the
run-time support code for a C program exist in a file called crt0.o,
whose source code would, presumably, be in a file called crt0.c.

By "run time support" I mean the following: the code in crt0.o is what
gets executed *before* the main() routine gets called.  This code will
do things such as intialize certain C-library variables, open stdin,
stdout, and stderr, parse command-line arguments, and possibly many
other things.  One of the final things it does is to invoke a function
called "main" with the argc, argv, and possibly also envp arguments.
This is how the system knows to start executing your program at the
main() entry point.

The linker knows about this crt0.o file and automatically links it
in without you having to specify it.

Hence, it is entirely appropriate for an the above-mentioned exit
statement to appear in crt0.c.

With regard to the issue of main() having a return statement, if you
use the crt0.c startup module (i.e., runtime support module) described
above, you can have your main() routine issue a return(N) statement
and it will be treated just as if you issued an exit(N) statement (for
integer values of N, of course).  I'm not sure if this is standard
behavior.  In several C compilers on the IBM PC, there is a varied
interpretation of this.  I've seen the following two ways of doing this
in the runtime support modules of IBM PC C compilers.

(1)  As above.  In other words,

    exit(main(argc, argv, envp));

(2)  Ignore main's return code

    main(argc, argv, envp);
    exit(0);

The first option will behave as described above with regard to return
and exit in main().  The second one requires the programmer to put an
exit(N) statement into the main() routine if an non-zero exit code is
desired.  Any return statements in the main() routine would have their
arguments ignored in the second option.  A disadvantage of the first
approach is that you will get an indeterminate exit code if you leave
the main() routine without a return or an exit, which is a quite
common occurrence.

I'm sure that we could have a nice long discussion about this issue.




-------------------------------------------------------------------------
 Lloyd Zusman
 Master Byte Software
 Los Gatos, California	    	    	Internet:   fxgrp!ljz@ames.arpa
 "We take things well in hand."	    	UUCP:	    ...!ames!fxgrp!ljz

chris@mimsy.UUCP (Chris Torek) (12/19/87)

In article <1286@laidbak.UUCP> daveb@laidbak.UUCP (Dave Burton) writes:
-They are NOT equivalent!
-At least in the UNIX environment, exit() is a function that flushes all
-buffers (and closes all file descriptors?), as well as handling functions
-registered via onexit(), finally calling _exit(), a system call that
-never returns.
-
-Using return instead of exit() bypasses this cleanup operation.

If it does, the system is broken.

exit(n) and return(n)-from-main are supposed to be equivalent.  Among
those systems that get it wrong are various releases of SunOS (where
the difference was intentional, yet still wrong).
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/19/87)

In article <1451@houdi.UUCP> marty1@houdi.UUCP (M.BRILLIANT) writes:
>The key question is where the exit(main(..)) was found.

He told you; it was in crt0.c, the C run-time startup module.
That is the fellow who runs your main() function.  I doubt that
in the Gnu package it was called recursively.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/19/87)

In article <1286@laidbak.UUCP> daveb@laidbak.UUCP (Dave Burton) writes:
>Using return instead of exit() bypasses this cleanup operation.

False.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/19/87)

In article <182@fxgrp.UUCP> fxgrp!ljz@ames.arpa (Lloyd Zusman, Master Byte Software) writes:
>    main(argc, argv, envp);
>    exit(0);

Such implementations do not conform to the proposed ANSI C standard.

dave@westmark.UUCP (Dave Levenson) (12/19/87)

In article <1451@houdi.UUCP>, marty1@houdi.UUCP (M.BRILLIANT) writes:
> > 
> > I was looking through the file crt0.c in the GNU emacs source code and
> > found the command
> > 
> > exit(main(argc,argv,env));
> > 
...
> The key question is where the exit(main(..)) was found.  Since main()
> is the first function called, no statement is needed to invoke main(). 
> Put it another way, since main() is invoked anyway, any statement that
> calls main() must call it recursively.  Why would anybody do that?

Why call main() ?  Well, you, yourself, said that main is the first
function _called_.  This implies that someone calls main.  The code
that actually receives control from the operating system is a
runtime initialization function called crt0.  It establishes the
runtime stack, the local copy of the environment, and the arguments,
and then calls main().  

In other words, main() is not the first function to be called, it is
the first user-written function to be called.  It is called by crt0,
which is not application-specific, and generally supplied by the
compiler-writer.   Main may call exit() explicitly, or it may return
to its caller.  In the latter case, its caller calls exit,
apparently, and passes the return value of main() when it does so!

-- 
Dave Levenson
Westmark, Inc.		A node for news.
Warren, NJ USA
{rutgers | clyde | mtune | ihnp4}!westmark!dave

ljz@fxgrp.UUCP (Lloyd Zusman, Master Byte Software) (12/19/87)

In article <1286@laidbak.UUCP> daveb@laidbak.UUCP (Dave Burton) writes:
>In article <176@fxgrp.UUCP> fxgrp!ljz@ames.arpa (Lloyd Zusman, Master Byte Software) writes:
>>In article <10875@brl-adm.ARPA> ADLER1%BRANDEIS.BITNET@CUNYVM.CUNY.EDU writes:
> ...
>At least in the UNIX environment, exit() is a function that flushes all
>buffers (and closes all file descriptors?), as well as handling functions
>registered via onexit(), finally calling _exit(), a system call that
>never returns.
>
>Using return instead of exit() bypasses this cleanup operation.

In the GNU version of crt0.o, this is obviously not the case due to
the

    exit(main(argc, argv, envp));

statement in the GNU crt0.c file.  In this case, using the return
statement to leave main() will indeed cause all the cleanup functions
to take place because this results in an immediate exit() call from
the crt0 module [ i.e., *not* an _exit() call ].

I have been told here that our SunOS version 3.4 system works the same
way as the GNU crt0 module is written, and hence at least on our unix,
return(N) and exit(N) will be the same if issued from main() [ assuming,
of course that my source of information about SunOS is correct ].

But upon reflection, I have to agree that it is better to always
use an exit() statement in main() instead of relying on return [ or
even worse, using neither return nor exit(), as is often done ].
If even one C compiler doesn't use exit() with main() the way it
is done in the GNU crt0 module, then you have unpredictable results
if exit() is left out of main().

So, to be safe, always leave main() via exit().

-------------------------------------------------------------------------
 Lloyd Zusman
 Master Byte Software
 Los Gatos, California	    	    	Internet:   fxgrp!ljz@ames.arpa
 "We take things well in hand."	    	UUCP:	    ...!ames!fxgrp!ljz

gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/19/87)

In article <1253@homxb.UUCP> mr@homxb.UUCP (mark) writes:
>This brings up an interesting problem :

"Interesting" must be in the mind of the beholder!

>	What if you declare main to return something other than an int ?

Simple: if you do that, you're wrong.

>	Is that allowed ?

How could it be?  However, few compilers will warn you about this
mistake.

andrew@teletron.UUCP (Andrew Scott) (12/22/87)

In article <184@fxgrp.UUCP>, ljz@fxgrp.UUCP (Lloyd Zusman, Master Byte Software) writes:
	But upon reflection, I have to agree that it is better to always
	use an exit() statement in main() instead of relying on return [ or
	even worse, using neither return nor exit(), as is often done ].
	If even one C compiler doesn't use exit() with main() the way it
	is done in the GNU crt0 module, then you have unpredictable results
	if exit() is left out of main().

	So, to be safe, always leave main() via exit().


Is it *really* better to use exit() instead of return from main()?  Are there
many compilers that don't do the same thing?  The reason I ask is that it's
always annoyed me that our lint doesn't understand exit() (and similar
functions) and complains that "main() returns random value to invocation
environment" if I don't use return.

	Andrew

lvc@tut.cis.ohio-state.edu (Lawrence V. Cipriani) (12/23/87)

In article <164@teletron.UUCP>, andrew@teletron.UUCP (Andrew Scott) writes:
	previous quotation and first two questions deleted
>					    The reason I ask is that it's
> always annoyed me that our lint doesn't understand exit() (and similar
> functions) and complains that "main() returns random value to invocation
> environment" if I don't use return.
> 
> 	Andrew

This has bothered me about lint too.  I don't think it will ever
be changed by AT&T (but don't quote me on that).  To get lint to shut up
about this use the /*NOTREACHED*/ comment after the call to exit(n); e.g.

	main(argc, argv)
		int argc; char *argv[];
	{
		code for main
		exit(n); 
		/*NOTREACHED*/
	}

This will work for similar functions too.  I wish I didn't HAVE to do
this, but thats how to get around the complaint.
-- 
	Larry Cipriani AT&T Network Systems at
	cbosgd!osu-cis!tut!lvc Ohio State University

djones@megatest.UUCP (Dave Jones) (12/23/87)

in article <1451@houdi.UUCP>, marty1@houdi.UUCP (M.BRILLIANT) says:
> 
>> 
>> I was looking through the file crt0.c in the GNU emacs source code and
>> found the command
>> 
>> exit(main(argc,argv,env));
>> 
>> which I find puzzling. I thought that one was supposed to give exit a
>> number for an argument. What does the above command do and why would
>> anyone want to do it that way ?
>> 
>> ADLER1@BRANDEIS.BITNET
> 
> Yeah, I second the question.  What this does is execute main(...)  and
> then give exit() the number that main returns.  So main(...) must have
> in it some statements of the form return(3); or return(status); so that
> exit() will get a useful number.  But the same effect would be achieved
> if main() had statements of the form exit(3); or exit(status);.
> 
> The key question is where the exit(main(..)) was found.  Since main()
> is the first function called, no statement is needed to invoke main(). 
> Put it another way, since main() is invoked anyway, any statement that
> calls main() must call it recursively.  Why would anybody do that?
> 
> M. B. Brilliant					Marty
> AT&T-BL HO 3D-520	(201)-949-1858
> Holmdel, NJ 07733	ihnp4!houdi!marty1

Don't count on anything in GNU emacs being what it appears to be.  Our
GNU emacs guru ("gnuru?") was gone for a couple of weeks, and I found
myself with the job of fixing a bug.  I chased it down, and it 
seemed to indicate a new static variable.  So I added one.  When
the new version of emacs came up, it crashed, on entry... long before
it could have gotten to any reference to the new variable.  I tried
running it under dbx.  dbx crashed.  Much head-scratching later, I discovered
that when you add a new static variable, you have to do some extra magic...
I forget just what.  Seems there is a step in the making of a new emacs
that edits the a.out file.  Probably for purposes of runtime garbage
collection.  

So it is quite possible that some step in the "make" is
changing the name of "main" to "foo", or "bar" to "main" or something.
There is also a concept of a "recursive edit" in emacs.  Maybe that's it.

The bad news is that our gnuru has now gone on to different pastures of
an indeterminate shade of green.  I hope that was the last bug in gnuemacs.

New subject: As to why main() should return something rather than just call
exit().  I suspect that before stdio, there was no "exit()".  Old-timers,
is that true?  Anyway, all that the Berkeley 4.2 exit() does is to flush
all the stdio buffers, then call _exit().  Problem is, stdio is not unique
in requiring some clean-up upon any exit from the program.  I confess that
I have on occasion used my own a.out editor to change the name of the
C-library's exit() "Cexit" or whatever, then written my own exit() which
does some cleanup then calls the (now) Cexit routine.  Simpler than trying
to police the use of exit() by a dozen or so fellow programmers.

Moral: Start a company policy of not using exit().  Call Lexit() instead.
Have a way of registering cleanup routines with Lexit. A possible solution:


/* No, I have not tested this, so if it's buggy, it's buggy. */
static int (*cleanup)();

int (*)();
set_Lexit(new_cleanup)
  int (*new_cleanup)();
{
  int (*old_cleanup)() = cleanup;
  cleanup = new_cleanup;
  return old_cleanup;
}

Lexit(code)
{
  if(cleanup) (*cleanup)(code);
  exit(code);
}


/* use.... */

static int (*next_cleanup)();

foo_cleanup(code)
{
  /* do my cleanup then... */
  (*next_cleanup)();
}

bar()
{
  next_cleanup = set_Lexit(foo_cleanup);

  /* do stuff ... */
}

djones@megatest.UUCP (Dave Jones) (12/23/87)

[...]

> At least in the UNIX environment, exit() is a function that flushes all
> buffers (and closes all file descriptors?), as well as handling functions
> registered via onexit(), finally calling _exit(), a system call that
> never returns.
> 
> Using return instead of exit() bypasses this cleanup operation.
> 
> 
> 
> 
> -- 
> --------------------"Well, it looked good when I wrote it"---------------------
>  Verbal: Dave Burton                        Net: ...!ihnp4!laidbak!daveb


Hum.  "onexit"... Just what's needed.  (See my previous note, where I 
rambled on about "Lexit()".

But on my Sun-3, I find no manual-page for onexit, and 

nm /lib/libc.a | grep onexit

returns silently.  So it looks as though not ALL unixes have onexit().

By the way, I've figured out what those long canned signatures with
disclaimers are for.  It's to keep vn from rejecting your reply because
"quoted text is longer than new text"!  So...


		Dave Jones
		Megatest Corp.
		880 Fox Lane
		San Jose, CA.
		95131

		(408) 437-9700 Ext 3227
		UUCP: ucbvax!sun!megatest!djones
		ARPA: megatest!djones@riacs.ARPA

ok@quintus.UUCP (Richard A. O'Keefe) (12/24/87)

In article <174@goofy.megatest.UUCP>, djones@megatest.UUCP (Dave Jones) writes:
> Hum.  "onexit"... Just what's needed.  (See my previous note, where I 
> rambled on about "Lexit()".
> 
> But on my Sun-3, I find no manual-page for onexit, and 
> 
> nm /lib/libc.a | grep onexit
> 
> returns silently.  So it looks as though not ALL unixes have onexit().

	% man exit
	<oh dear, it's raving on about Csh commands>
	% man 2 exit
	<tells me about _exit(), with a cross-reference to exit(3)>
	% man 3 exit
	<tells me about exit(), with a cross-reference to on_exit(3)>
	% man 3 on_exit
	SYNOPSIS
	     int on_exit(procp, arg)
	     void (*procp)();
	     caddr_t arg;
	NOTES
	     This call is specific to Sun Unix and should not be used  if
	     portability is a concern.

Basically, there is a stack of up to 20 termination functions,
and on_exit() pushes the pair procp,arg on the stack.  On exit,
these pairs are popped and procp(arg) called in reverse order.

The problem with this feature (and with the version in dpANS) is that it
is too global.  What I would like to be able to do is

	{
	    FILE *f;
	    EXIT_HANDLER *e;

	    FCHECK(f = fopen(...));
	    e = push_exit_handler(fclose, f);
	    ....
	    pop_run_one_handler(e);
	    ...
	}

so that I can put cleanup actions onto a stack and REMOVE them when they
have been done, but if an exit() happens in between the actions will be
done.  Common Lisp's "unwind-protect" is the kind of thing we're after.

Some other C implementations have a similar thing called "atexit()" or
"at_exit()".  While onexit() or whatever doesn't quite do what I want,
I can at least register my own handler manager with it, so it's ok as a
primitive.

msb@sq.uucp (Mark Brader) (12/26/87)

Lloyd Zusman (ljz@fxgrp.UUCP) writes:
> But upon reflection, I have to agree that it is better to always
> use an exit() statement in main() instead of relying on return [ or
> even worse, using neither return nor exit(), as is often done ].
> If even one C compiler doesn't use exit() with main() the way it
> is done in the GNU crt0 module, then you have unpredictable results
> if exit() is left out of main().

I once met a C compiler that didn't implement ++ correctly for pointers
to structures.  Does this mean that we should all stop using ++?

I suggest that return is the better thing to use in main().  If you use
exit(), you're making the assumption that this function will always be
the mainline of its program; if you use return, you can wrap another
mainline around it by just changing the name of the original one.

Also, if this practice is followed, a call to exit() really stands out
as an abnormal return path, like longjmp().

Of course, if main() is recursive, the two forms are not equivalent;
but not many people write recursive mainlines, and those that do are
old enough to look after themselves.


Mark Brader				"C takes the point of view
SoftQuad Inc., Toronto			 that the programmer is always right"
utzoo!sq!msb, msb@sq.com				-- Michael DeCorte

ftw@datacube.UUCP (12/28/87)

djones@megatest.UUCP writes:

> Hum.  "onexit"... Just what's needed.  (See my previous note, where I 
> rambled on about "Lexit()".

> But on my Sun-3, I find no manual-page for onexit, and 

> nm /lib/libc.a | grep onexit

> returns silently.  So it looks as though not ALL unixes have onexit().

The person who mentioned onexit() could have been using a Whitesmiths
compiler.  Their library provides onexit().


<edited>

> 		Dave Jones
> 		Megatest Corp.
> 		880 Fox Lane
> 		San Jose, CA.
> 		95131

> 		(408) 437-9700 Ext 3227
> 		UUCP: ucbvax!sun!megatest!djones
> 		ARPA: megatest!djones@riacs.ARPA

#include <disclaimer.h>





				Farrell T. Woods 

Datacube Inc. Systems / Software Group	4 Dearborn Rd. Peabody, Ma 01960
VOICE:	617-535-6644;	FAX: (617) 535-5643;  TWX: (710) 347-0125
INTERNET: ftw@datacube.COM
UUCP: {rutgers, ihnp4, mirror}!datacube!ftw

"OS/2 -- Half an operating system"

ok@quintus.UUCP (Richard A. O'Keefe) (12/31/87)

I just installed a program which came over one of the *sources*
newsgroups.   The accompanying README was extremely funny:  it said
    The program should be owned by root and suid.
But that's not a C joke.  What is of interest here is its use of exit().

It used exit() in two ways:
	exit(1)		/* can't find datum in file */
	exit(-1)	/* can't fopen file, either "r" or "w" */
Oddly enough, it did not use exit(0) at the end of main().

Given all the hoo-haa we've been having about exit() recently, I
thought it might not be out of place to warn people that the value
given to exit() is often truncated to 8 bits on the way out.  For
example, in UNIX, for which this program was intended, saying
	this-program some-argument
	if [ #? -eq -1 ] ; then
	    ...
	fi
will NEVER succeed, because the return value is going to be 255.
The VAX-11 C manual explicitly says that the argument of exit()
should be 0 or a value errno might have.

The Oct86 dpANS said only that 0 arguments indicate success and
non-0 arguments indicate failure in some system-dependent way.

Except where you are writing code for a specific system (say you
have #if cases for MVS, VMS, and UNIX) it seems like a good idea
to pass only 0 or 1 to exit().

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/06/88)

In article <171@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>Moral: Start a company policy of not using exit().  Call Lexit() instead.
>Have a way of registering cleanup routines with Lexit. A possible solution:

ANSI C provides an atexit() function that helps immensely with this.
However, in the interim you need to take care of this yourself.
One possibility is to use my public-domain implementation of atexit()
and atexit-supporting exit(), which requires that your current "exit"
library entry be renamed, to "__exit" for example, but otherwise slips
right into your current C library.  Contact me if you need a copy.
	- Gwyn@BRL.MIL

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/06/88)

In article <502@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>Except where you are writing code for a specific system (say you
>have #if cases for MVS, VMS, and UNIX) it seems like a good idea
>to pass only 0 or 1 to exit().

VMS C would like for exit(1); to also mean "success", we were told,
so the current proposed standard requires <stdlib.h> to define macros
EXIT_FAILURE and EXIT_SUCCESS.  Special dispensation was granted to
the value 0, which also indicates success (the VMS C implementor
agreed that he could make that work on his system).  All other values
of the exit status have implementation-defined meaning; they might
contain system error codes, errno values, or some other stuff with
non-portable meaning.

peter@sugar.UUCP (Peter da Silva) (01/06/88)

In article ... ok@quintus.UUCP (Richard A. O'Keefe) writes:
> [exit()]
>
> The VAX-11 C manual explicitly says that the argument of exit()
> should be 0 or a value errno might have.
> 
> The Oct86 dpANS said only that 0 arguments indicate success and
> non-0 arguments indicate failure in some system-dependent way.
> 
> Except where you are writing code for a specific system (say you
> have #if cases for MVS, VMS, and UNIX) it seems like a good idea
> to pass only 0 or 1 to exit().

I like passing -1 because:

	It's negative (some systems use the sign bit to specify true/false).
	It's odd (some systems use the low bit for the same purpose).
	All bits are set (some systems do ANDS and ORS using & and |).
	If it's truncated, it's large (some systems use small values for
		warnings, and large ones for fatal errors).

I've never had a system treat "-1" as a successful result. I have had one
ignore a return code of 1.
-- 
-- Peter da Silva  `-_-'  ...!hoptoad!academ!uhnix1!sugar!peter
-- Disclaimer: These U aren't mere opinions... these are *values*.

brett@wjvax.UUCP (Brett Galloway) (01/07/88)

In article <6935@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>In article <502@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>>Except where you are writing code for a specific system (say you
>>have #if cases for MVS, VMS, and UNIX) it seems like a good idea
>>to pass only 0 or 1 to exit().
>
>VMS C would like for exit(1); to also mean "success", we were told,
>so the current proposed standard requires <stdlib.h> to define macros
>EXIT_FAILURE and EXIT_SUCCESS.  Special dispensation was granted to
>the value 0, which also indicates success (the VMS C implementor
>agreed that he could make that work on his system).  All other values
>of the exit status have implementation-defined meaning; they might
>contain system error codes, errno values, or some other stuff with
>non-portable meaning.

It appears to me that requiring EXIT_FAILURE and EXIT_SUCCESS is a
sop to VMS's non-traditional usage.  Now I grant that it is a nice idea to
define EXIT_FAILURE and EXIT_SUCCESS.  I also grant that other exit values
are implementation-defined.  However, it is hard to conceive an implementation
which has multiple exit-success values.  In this context, 0 is by far the
most intuitive choice for EXIT_SUCCESS.

Instead of accommodating VMS's stupid choice of exit values, why not require
an ANSI-conforming VMS C compiler to swap 0 and 1 in the exit() in its C
library?  That way, even if VMS wants to see 1 for success, it will, with
C programs able to return the natural value of 0 for success.  I seem to
recall that VMS already defines macros for error return values.  It could
swap those (make 0 success).  This way, currently-compiled VMS C binaries
would continue to run, and newly-compiled C binaries would also work (they
would get the swapped exit() *and *the new EXIT_FAILURE and EXIT_SUCCESS
macros at the same time.  The only time that there would be a problem would
be a re-link without a re-compile.  Frankly, anybody that would not
re-compile across a transition to an ANSI-conformant compiler deserves what
they get.

This solves the problem for everybody, while leaving conformant the vast body of
programs which use the natural exit(0) => success and exit(!0) => !success.
It puts the burden of conformance upon VMS instead of upon the rest of the
world.  This is apt, since VMS caused the problem in the first place.

-- 
-------------
Brett D. Galloway
{ac6,calma,cerebus,isi,isieng,pyramid,tymix}!wjvax!brett

chris@mimsy.UUCP (Chris Torek) (01/08/88)

>>VMS C would like for exit(1); to also mean "success", we were told,

In article <1179@wjvax.UUCP> brett@wjvax.UUCP (Brett Galloway) writes:
>Instead of accommodating VMS's stupid choice of exit values, why not require
>an ANSI-conforming VMS C compiler to swap 0 and 1 in the exit() in its C
>library?

This is not the right approach.  The right approach is this:

	exit(int status) { _vms_exit(!status); }
		/* more complex encodings can be devised */
		/* note that _vms_exit shuts down stdio in this example */
	_exit(int status) { _vms_stopcold(!status); }
		/* just another example */

The `problem' is that VMS programmers need access to the full range
of VMS status values.  There are many sub-fields to a VMS status.
The low bit means `success'; the next few bits define what sort of
error; a few more define a sub-error or previous error or something
similar; and so forth.  (Incidentally, exit status 0 in VMS means
`failed, no errors occurred'.  It is also possible to exit with
`succeeded, but fatal errors occurred'.)

But VMS status values mean nothing on other operating systems!
Writing

	exit(0x1074);	/* some fancy error or another */

means nothing outside of VMS---so why not use a VMS-specific function
such as _vms_exit()?
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/08/88)

In article <1179@wjvax.UUCP> brett@wjvax.UUCP (Brett Galloway) writes:
>It appears to me that requiring EXIT_FAILURE and EXIT_SUCCESS is a
>sop to VMS's non-traditional usage.

Yes, it was, but the argument was made that the exit status is intended
to pass system-specific useful information back to the environment, and
I have a hard time arguing against that because UNIX does that all the
time.  Clearly, X3J11 is in no position to dictate what various system
information must consist of, other than "generic success" and "generic
failure" which are the only useful statuses for portable applications.

>However, it is hard to conceive an implementation
>which has multiple exit-success values.

VMS does!

I agree that probably all implementations, including VMS, will
	#define	EXIT_SUCCESS	0

>Instead of accommodating VMS's stupid choice of exit values, why not require
>an ANSI-conforming VMS C compiler to swap 0 and 1 in the exit() in its C
>library?

We tried that, but many existing VMS applications have been passing
the value of 1 (disguised as SYS$SUCCESS or something like that) to
exit() to indicate success.

>This is apt, since VMS caused the problem in the first place.

Actually, I agree with this, but since we found a solution that the
VMS folk could live with, why not stick with it.

egisin@orchid.waterloo.edu (Eric Gisin) (01/09/88)

> The `problem' is that VMS programmers need access to the full range
> of VMS status values.  There are many sub-fields to a VMS status.

VMS C programmers have always had sys$exit() to return VMS status values.
There is no excuse for making exit() synonymous with sys$exit --
something like the following would have been better and Unix compatible.

exit(i) {
	sys$exit((i==0) ? SS$_NORMAL : SS$_CFAILURE);
}

john@chinet.UUCP (John Mundt) (01/10/88)

In article <1179@wjvax.UUCP> brett@wjvax.UUCP (Brett Galloway) writes:

>It appears to me that requiring EXIT_FAILURE and EXIT_SUCCESS is a
>sop to VMS's non-traditional usage.  Now I grant that it is a nice idea to
>define EXIT_FAILURE and EXIT_SUCCESS.  I also grant that other exit values
>are implementation-defined.  However, it is hard to conceive an implementation
>which has multiple exit-success values.  In this context, 0 is by far the
>most intuitive choice for EXIT_SUCCESS.

Using a non-zero exit value for a programs that exec()s a series of
sub-programs allows the sub-program to return the user's intentions
back to the execing program.  We use it in a menu-driven bbs program
where 0 is the plain-vanilla exit value with no special action
intended while other values call up various menus or denote a
particular program error.


John Mundt,				....ihnp4!chinet!teachad!fred
Teachers' Aide, Inc.
----------------------------

My opinions reflect the thinking of the company.  I *own* it!

brett@wjvax.UUCP (Brett Galloway) (01/11/88)

In article <6983@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>In article <1179@wjvax.UUCP> brett@wjvax.UUCP I wrote:
>>However, it is hard to conceive an implementation
>>which has multiple exit-success values.
>VMS does!
>I agree that probably all implementations, including VMS, will
>	#define	EXIT_SUCCESS	0

I overstated.  I even have applications which have multiple exit-success
values.  However, there was always one fundamental exit-success value.  I
feel that 0 is the best choice for this.

>>Instead of accommodating VMS's stupid choice of exit values, why not require
>>an ANSI-conforming VMS C compiler to swap 0 and 1 in the exit() in its C
>>library?
>We tried that, but many existing VMS applications have been passing
>the value of 1 (disguised as SYS$SUCCESS or something like that) to
>exit() to indicate success.

Not to beat a dead horse, but that's why I suggested swapping 0 and 1 in
exit() *and* simultaneously re-defining SYS$SUCCESS et al in the relevant
header file(s).  As I noted, this would break only unlinked binaries that
were not re-compiled.  I had said:

- The only time that there would be a problem would be a re-link without a
- re-compile.  Frankly, anybody that would not re-compile across a transition
- to an ANSI-conformant compiler deserves what they get.

One E-mail respondent took exception to my tone (deservedly, I believe).
However, I stand by my point.  It is unlikely that unlinked binaries will
survive across the transition to an ANSI C library.

>>This is apt, since VMS caused the problem in the first place.
>Actually, I agree with this, but since we found a solution that the
>VMS folk could live with, why not stick with it.

Of course the VMS folk could live with the ANSI C solution; it *is*
effectively the VMS solution.  It is a trivial matter for VMS to adapt to
this solution.

-- 
-------------
Brett D. Galloway
{ac6,calma,cerebus,isi,isieng,pyramid,tymix}!wjvax!brett

tanner@ki4pv.uucp (Dr. T. Andrews) (01/11/88)

In article <6983@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
) [ elaborates on VMS and EXIT_SUCCESS, EXIT_FAILURE reasoning ]
) Actually, I agree with this, but since we found a solution that the
) VMS folk could live with, why not stick with it.

Great!  You've found a solution that the VMS folks could live with.
Unfortunately, those few unlucky enough to not be using VMS have been
spending their lives coding progs which finish with exit(0) when they
worked.  How about a slap in the face with a wet towel to them?
-- 
{allegra clyde!codas decvax!ucf-cs ihnp4!codas killer}!ki4pv!tanner

gwyn@brl-smoke.UUCP (01/12/88)

In article <1185@wjvax.UUCP> brett@wjvax.UUCP (Brett Galloway) writes:
>... simultaneously re-defining SYS$SUCCESS et al in the relevant header file(s).

I may be mistaken, but I was under the impression that the SYS$... symbols
were not #defined constants, but rather were system-wide logical names,
or something of the sort.

gwyn@brl-smoke.UUCP (01/12/88)

In article <7208@ki4pv.uucp> tanner@ki4pv.uucp (Dr. T. Andrews) writes:
-Great!  You've found a solution that the VMS folks could live with.
-Unfortunately, those few unlucky enough to not be using VMS have been
-spending their lives coding progs which finish with exit(0) when they
-worked.  How about a slap in the face with a wet towel to them?

Please pay more careful attention.  exit(0); is still a valid way of
reporting success under the proposed ANSI C.  I'm sure I said that.
However, exit(1); is not guaranteed to report failure on all systems.
The real need was for EXIT_FAILURE; EXIT_SUCCESS was introduced just
for symmetry and completeness.

g-rh@cca.CCA.COM (Richard Harter) (01/12/88)

In article <7208@ki4pv.uucp> tanner@ki4pv.uucp (Dr. T. Andrews) writes:
>
>Great!  You've found a solution that the VMS folks could live with.
>Unfortunately, those few unlucky enough to not be using VMS have been
>spending their lives coding progs which finish with exit(0) when they
>worked.  How about a slap in the face with a wet towel to them?

People who write exit(0) are violating the well known canons of good
programming practice -- "Thou shalt not embed magic numbers in your code".
In this case, 0 is a magic number -- it is a coded value and the wise
(read those who learned by being burnt) use symbolic names which are
defined in one place only.  [I am guilty of this also, so if I am 
pointing fingers, I share the guilt.]

Does it matter?  That depends.  If your only environment is one where
the magic number is always 0 then there is no harm in using 0.  If you
are writing code which will be ported across operating systems then it
matters a great deal.

I do not understand the wet towel bit.  If you are a Unix programmer in
the habit of using exit(0) you are not impacted by the standard.  Your
code will work the way it always did.  If you are writing portable code
you will be grateful for a standard mechanism for handling returns that
is not operating system dependent.

-- 

In the fields of Hell where the grass grows high
Are the graves of dreams allowed to die.
	Richard Harter, SMDS  Inc.

hydrovax@nmtsun.nmt.edu (M. Warner Losh) (01/13/88)

In article <1185@wjvax.UUCP>, brett@wjvax.UUCP (Brett Galloway) writes:
> In article <6983@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
> >In article <1179@wjvax.UUCP> brett@wjvax.UUCP I wrote:
> >>However, it is hard to conceive an implementation
> >>which has multiple exit-success values.
> >VMS does!
> >I agree that probably all implementations, including VMS, will
> >	#define	EXIT_SUCCESS	0
> 
> Of course the VMS folk could live with the ANSI C solution; it *is*
> effectively the VMS solution.  It is a trivial matter for VMS to adapt to
> this solution.
Am I missing something here, or are you saying that because VMS cause
this so-called mess, that they should have to live with a UNIX like
kludge, just to make you happy?  When you exit(0) on VMS you get the error

%NONAME-W-NOMESSAGE, No message text for message 0000000

or something similar.  Remember that VMS is not really 'C' based, and
much of the code is written in a whole slew of languages.  Would you
propose that all of that be rewritten?  I think not.  The more proper
VMS implementation of EXIT_STATUS should be SS$_NORMAL, which is
(at least in 4x) defined to be 1.  Why would you expect an operating
system dependent scheme such as exit(0) to work on all OS's?  The whole
world isn't using UNIX.


-- 
bitnet:	lush@nmt.csnet			M. Warner Losh
csnet:	warner%hydrovax@nmtsun
uucp:	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!warner%hydrovax
	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!hydrovax
Warning:  Hydrovax is both a machine, and an account, so be careful.

dhesi@bsu-cs.UUCP (Rahul Dhesi) (01/14/88)

In article <23160@cca.CCA.COM> g-rh@CCA.CCA.COM.UUCP (Richard Harter) writes:
>In this case, 0 is a magic number -- it is a coded value and the wise
>(read those who learned by being burnt) use symbolic names which are
>defined in one place only.

But zero is not a magic number, else we'd all have to stop assuming
that the range of unsigned values begins at 0 (have to use UNSIGNED_MIN
instead), or assume that array indices start at 0 (have to begin arrays
at ARAY_MIN), or assume that NULL is zero (could be 17 on some
machines), or assume that all static variables are initialized to zero
(ought to be INIT_DEFAULT, an implementation-defined constant), or
assume that division by zero is illegal (division by ILL_DIVISOR, an
implementation-defined constant, is illegal instead), etc.
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/15/88)

In article <1843@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
>In article <23160@cca.CCA.COM> g-rh@CCA.CCA.COM.UUCP (Richard Harter) writes:
>>In this case, 0 is a magic number -- it is a coded value ...
>But zero is not a magic number, ...

What g-rh was trying to say was that the SUCCESSFUL TERMINATION STATUS
INDICATOR (which traditionally has been 0 on UNIX systems) is a "magic
number", and he's right.

eichin@athena.mit.edu (Mark W. Eichin) (01/16/88)

Regarding Rahul Dhesi's comments on 0 not being a magic number:
	1) Assuming NULL is zero (meaning it is a zero bitstring
internally) is not correct, however casting 0 to a pointer, as in:
	if(*p){ do_something() }
where (*p) is (*p != 0) which becomes (*p != NULL) is valid. The
trick is the conversion of 0 to NULL; on Multics, NULL is a pointer
into segment -1 with arbitrary offset; on Primes, it is something
other non-zero bitmap. This gets hashed about here every 6 months, it
seems.
	2) Assuming that arrays start at 0 is straight out of K&R.
However, you are then stuck with using C arrays. I had a large
(50Klines) application where we started out with a custom
implementation of arrays, with bounds checking and operator packages
and other ``neat stuff'', and we ORIGINALLY had ARRAY_MIN == 1. It
kept us honest... since after the 3d rewrite (aren't educational
projects fun :-) we decided to change the Array package implementation
and ARRAY_MIN was suddenly 0 again. I am glad we didn't start out with
0 and convert to 1 later, that would have been BAD... but with all of
the fenceposts to keep track of, we had alot of references to BASE
that were explicit, so the conversion went fairly smoothly. (With a
real package layer, like C++ has, we would have had NO problems, but
this was vanilla C...)
	3) Assuming that Division by Zero is illegal is not
implementation defined, since the implementation is specified as
standard mathematics. Mathematicians use a special symbol for `that
which division is not defined upon': 0. Why should C programmers do
otherwise? :-) 

In any case, the original point (that zero is not a magic number) was
correct (we are *almost* in violent agreement here) but some of the
excuses were not correct; point 2 above bothered me enough to
respond... the point being that some things that are specified, but
are changeable anyway.  Zero is *specified* in some places as the
correct thing, so extracting it out as a symbol can clutter and
confuse. The change in meaning of 0 as a value to exit(int status)
under un*x and vms$exit() is from the original spec being o/s
specific. Oh well...


				Mark Eichin
			<eichin@athena.mit.edu>
		SIPB Member & Project Athena ``Watchmaker'' 

eichin@athena.mit.edu (Mark W. Eichin) (01/16/88)

Under 4.3BSD, there is a <sysexits.h> which does include a bunch of
standard return values like EX_USAGE, EX_NOPERM, and others, for use
as arguments to exit(); it is not complete, in fact it isn't terribly
large. In any case, there is one return value EX_OK commented as /*
successful termination */ with the value of 0... it is NOT documented
in the comments at the top. It doesn't seem that many people use
these, are they a really recent development? If it were in common use,
the problem under discussion wouldn't be so severe...
				Mark Eichin
			<eichin@athena.mit.edu>
		SIPB Member & Project Athena ``Watchmaker'' 

dhesi@bsu-cs.UUCP (01/16/88)

I gave a number of example attempting to show that zero is inherently
a unique integer and therefore not a "magic number" in the usual
sense of the term.

In article <2305@bloom-beacon.MIT.EDU> eichin@athena.mit.edu (Mark W.
Eichin) gives a number of counter arguments.

I respond thus.

Zero symmetrically divides the number line.  If one had to choose ONE
of the values on the number line as being unique, it would have to be
zero.  It is the only value that isn't arbitrary, the only one that
doesn't have a mirror-image counterpart (of opposite sign), the only
one that can't be a legal divisor, the only one that, in short,
stands out as "different" from all the other values.

It seems to make perfect sense to me that in the non-VMS world in which
a single successful termination value, and multiple failure termination
values, are needed, zero should be the successful termination value.

Therefore the use of exit(0) for successful termination is not
arbitrary.  It is intuitively correct.
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi

jay@splut.UUCP (Jay Maynard) (01/16/88)

In article <7208@ki4pv.uucp>, tanner@ki4pv.uucp (Dr. T. Andrews) writes:
> In article <6983@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
> ) [ elaborates on VMS and EXIT_SUCCESS, EXIT_FAILURE reasoning ]
> ) Actually, I agree with this, but since we found a solution that the
> ) VMS folk could live with, why not stick with it.
> 
> Unfortunately, those few unlucky enough to not be using VMS have been
> spending their lives coding progs which finish with exit(0) when they
> worked.  How about a slap in the face with a wet towel to them?

for(i = 0; i < 100; i++) {
	repeat_after_me('All the world does not run on Unix, either.');
	}

I think it's only fair that those of us who complain about 'all the world is
a VAX' should complain about 'all the world is Unix' as well...

This is probably the best, portable solution.

-- 
Jay Maynard, K5ZC (@WB5BBW)...>splut!< | GEnie: JAYMAYNARD  CI$: 71036,1603
uucp: {uunet!nuchat,academ!uhnix1,{ihnp4,bellcore,killer}!tness1}!splut!jay
Never ascribe to malice that which can adequately be explained by stupidity.
The opinions herein are shared by none of my cats, much less anyone else.

mike@arizona.UUCP (01/17/88)

In article <1868@bsu-cs.UUCP>, dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
> [...]
> Zero symmetrically divides the number line.  If one had to choose ONE
> of the values on the number line as being unique, it would have to be
> zero.  It is the only value that isn't arbitrary, the only one that
> doesn't have a mirror-image counterpart (of opposite sign), the only
> one that can't be a legal divisor, the only one that, in short,
> stands out as "different" from all the other values.
One (1) symmetrically divides the number line.  If one had to choose ONE
of the values on the number line as being unique, it would have to be
one.  It is the only value that isn't arbitrary, it only one that 
is a multiplicative identity, the only number of noses on my face, the
only one, in short, that stands out as "different" from all the other
values. :->



-- 

Mike Coffin				mike@arizona.edu
Univ. of Ariz. Dept. of Comp. Sci.	{allegra,cmcl2,ihnp4}!arizona!mike
Tucson, AZ  85721			(602)621-4252

hydrovax@nmtsun.nmt.edu (M. Warner Losh) (01/17/88)

In article <1843@bsu-cs.UUCP>, dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
> In article <23160@cca.CCA.COM> g-rh@CCA.CCA.COM.UUCP (Richard Harter) writes:
> >In this case, 0 is a magic number -- it is a coded value and the wise
> >(read those who learned by being burnt) use symbolic names which are
> >defined in one place only.
> 
> But zero is not a magic number,
> Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi
Rahul,  any number is magic.  We associate Zero with a correct
exit, ONLY BECAUSE WE HAVE BE TAUGH THIS BY UNIX.  If you had ever worked
wit (a real operating system :-)) VMS, then you know that an ODD number
is sucess, while an even one is an error.  Both systems are equally
valid, since they are arbitrary abstractions.

FLAME ON
Your statements about valid uses of zero THAT ARE DEFINED TO BE VALID IN
C (K&R version), are so amazinly BOGUS, that I'm not even going to
include them in this article.  THE WHOLE WORLD IS NOT UNIX, VMS, MVS,
or any other operating system.  Please try to remeber that there are some
things in a "standard" 'C' that are part of C (like the zero indexing)
and somethings that are part of the environment that 'C' lives in (the
exit() stuff for one).
FLAME OFF


-- 
bitnet:	lush@nmt.csnet			M. Warner Losh
csnet:	warner%hydrovax@nmtsun
uucp:	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!warner%hydrovax
	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!hydrovax
Warning:  Hydrovax is both a machine, and an account, so be careful.

mike@arizona.edu (Mike Coffin) (01/17/88)

In article <1868@bsu-cs.UUCP>, dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
> [...]
> Zero symmetrically divides the number line.  If one had to choose ONE
> of the values on the number line as being unique, it would have to be
> zero.  It is the only value that isn't arbitrary, the only one that
> doesn't have a mirror-image counterpart (of opposite sign), the only
> one that can't be a legal divisor, the only one that, in short,
> stands out as "different" from all the other values.
One (1) symmetrically divides the number line.  If one had to choose ONE
of the values on the number line as being unique, it would have to be
one.  It is the only value that isn't arbitrary, it only one that 
is a multiplicative identity, the only number of noses on my face, the
only one, in short, that stands out as "different" from all the other
values. :->



-- 

Mike Coffin				mike@arizona.edu
Univ. of Ariz. Dept. of Comp. Sci.	{allegra,cmcl2,ihnp4}!arizona!mike
Tucson, AZ  85721			(602)621-42

g-rh@cca.CCA.COM (Richard Harter) (01/17/88)

In article <1868@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
>I gave a number of example attempting to show that zero is inherently
>a unique integer and therefore not a "magic number" in the usual
>sense of the term.
>
	... Discussion of the properties of zero deleted ...
>
>It seems to make perfect sense to me that in the non-VMS world in which
>a single successful termination value, and multiple failure termination
>values, are needed, zero should be the successful termination value.
>
>Therefore the use of exit(0) for successful termination is not
>arbitrary.  It is intuitively correct.

	This is perhaps my fault for assuming that everyone knows
what is meant by a magic number, as in "don't use magic numbers".
Let me give an example.  Look at the following code:

	char foo[57];
	....
	for(i=0;i<57;i++) {...}
        foo[55]='\n';
	foo[56]='\0';

As we all know, this kind of code is likely to create maintenance
problems.  If, for some reason, we want to change the size of foo,
we must identify and change every occurence of 57, including the
indirect ones.  Experienced programmers will prefer something like
this

	#define size 57
	....
	char foo[size];
	....
	for (i=0;i<size;i++) {...}
	foo[size-2]='\n';
	foo[size-1]='\0';

This has two advantages.  The number, 57, is explicitly referenced only
once, which makes it much easier to alter.  The name, size, has a specific
meaning that is relevant to, and limited to, its actual usage.  A magic
number is a number embedded in code that has a special meaning in the
context of the code.  In this context 57 is a magic number.  0,1, and
2, as used, are not, because they are implied by the conventions of the
language.  Note that it is the usage and meaning that determines whether
a number is a magic number or not.  It is considered good programming
practice to avoid using magic numbers.

Numbers which represent encoded values are magic numbers.  For example,
if I write a function which returns a number returning a color, with
0=red, 1=blue, and 2=green, I will do better if my code says

	return red;

(with read appropriately defined) than if I say

	return 0;

In addition to the two advantages I cited above, there is a third
advantage in this case.  If I hard code the encoded values, the encodings
have to be known in two places -- in my function and in the program(s)
calling my function.  Life will clearly be simpler if the encodings
are in a common place shared by my function and the program(s) that
call my function.  This will be particularly true if my function is
going to be used by several different programs which may use different
encodings.

My apologies for going on at length about basic principles, but it would
appear that these thoughts are novel for some people.

Rahul argues above that zero has various special properties, and that
it is therefore the "best" choice for representing successful termination.
This is irrelevant.  It doesn't matter whether zero is the "best"
choice or not.  It would still be bad practice to return zero, even
if all operating systems accepted it as meaning successful termination.
As we know, some do, and some do not.

I will concede that 'exit(0)' is standard practice in UNIX environments,
and that there has been, heretofore, for standard for sharing encodings
of the returned value with the host operating system.  I also recognize
that if you are only concerned with C programs running under UNIX, then
it won't matter if you write exit(0).  If it doesn't matter in your
case, and you are not a purist about good programming practice, then
the issue is moot.

If, however, you are dealing with software that will have to run on
a variety of machines and operating systems then it matters very much.
-- 

In the fields of Hell where the grass grows high
Are the graves of dreams allowed to die.
	Richard Harter, SMDS  Inc.

sns@genghis.UUCP (Sam Southard) (01/18/88)

In article <1868@bsu-cs.UUCP>, dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
> Zero symmetrically divides the number line.  If one had to choose ONE

Let me choose one.  There are the same number of numbers greater than one as
there are less than one, so one must symmetrically divide the number line.

> of the values on the number line as being unique, it would have to be
> zero.  It is the only value that isn't arbitrary, the only one that
> doesn't have a mirror-image counterpart (of opposite sign), the only
> one that can't be a legal divisor, the only one that, in short,
> stands out as "different" from all the other values.

If we had to choose ONE of the values on the number line as being uniqe, it
would have to be one.  It is the only value that isn't arbitrary, the only
one which when multiplying or dividing another number yields the same number,
the only one whose mirror image is the square of 'i', the only one that, in
short, stands out as "different" from all the other values.

> Therefore the use of exit(0) for successful termination is not
> arbitrary.  It is intuitively correct.

Therefore the use of exit(0) for successful termination is completely
arbitrary.  Obviosly, the intuitive value is exit(1).

Rahul, *every* number has unique properties.  Those of one and zero simply
stand out more and are more significant.
-- 

Sam Southard, Jr.
{sns@genghis.caltech.edu|sns@genghis.uucp|{backbone}!cit-vax!genghis!sns}

rsalz@bbn.com (Rich Salz) (01/18/88)

>Under 4.3BSD, there is a <sysexits.h> which does include a bunch of
>standard return values like EX_USAGE, EX_NOPERM, and others ...
>				Mark Eichin

The sysexits.h file was originally written by Eric Allman as part of
the original sendmail distribution (shortly after 4.1c, I think).
When 4.2 was released the file made its way into /usr/include.
Apparently /usr/include was already filled up, so the Berkeley
folks decided to move <time.h> into <sys/time.h> as a tradeoff, thereby
forcing thousands of Makefile writers to add -I/usr/include/sys to
their DEFS macro.

Getting back to reality, I have word from ATT that they have absolutely no
claim on sendmail, and a Berkeley spokesman says that (quoting from
personal e-mail) "it is redistributable as long as due credit is given to
the University."  With such credit given, then...

HEY, YOU:  Further discussion on error codes -- especially this file --
probably isn't relative to this "C" newsgroup or mailing list.
	/r$

/*
**  SYSEXITS.H -- Exit status codes for system programs.
**
**	This include file attempts to categorize possible error
**	exit statuses for system programs, notably delivermail
**	and the Berkeley network.
**
**	Error numbers begin at EX__BASE to reduce the possibility of
**	clashing with other exit statuses that random programs may
**	already return.  The meaning of the codes is approximately
**	as follows:
**
**	EX_USAGE -- The command was used incorrectly, e.g., with
**		the wrong number of arguments, a bad flag, a bad
**		syntax in a parameter, or whatever.
**	EX_DATAERR -- The input data was incorrect in some way.
**		This should only be used for user's data & not
**		system files.
**	EX_NOINPUT -- An input file (not a system file) did not
**		exist or was not readable.  This could also include
**		errors like "No message" to a mailer (if it cared
**		to catch it).
**	EX_NOUSER -- The user specified did not exist.  This might
**		be used for mail addresses or remote logins.
**	EX_NOHOST -- The host specified did not exist.  This is used
**		in mail addresses or network requests.
**	EX_UNAVAILABLE -- A service is unavailable.  This can occur
**		if a support program or file does not exist.  This
**		can also be used as a catchall message when something
**		you wanted to do doesn't work, but you don't know
**		why.
**	EX_SOFTWARE -- An internal software error has been detected.
**		This should be limited to non-operating system related
**		errors as possible.
**	EX_OSERR -- An operating system error has been detected.
**		This is intended to be used for such things as "cannot
**		fork", "cannot create pipe", or the like.  It includes
**		things like getuid returning a user that does not
**		exist in the passwd file.
**	EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp,
**		etc.) does not exist, cannot be opened, or has some
**		sort of error (e.g., syntax error).
**	EX_CANTCREAT -- A (user specified) output file cannot be
**		created.
**	EX_IOERR -- An error occurred while doing I/O on some file.
**	EX_TEMPFAIL -- temporary failure, indicating something that
**		is not really an error.  In sendmail, this means
**		that a mailer (e.g.) could not create a connection,
**		and the request should be reattempted later.
**	EX_PROTOCOL -- the remote system returned something that
**		was "not possible" during a protocol exchange.
**	EX_NOPERM -- You did not have sufficient permission to
**		perform the operation.  This is not intended for
**		file system problems, which should use NOINPUT or
**		CANTCREAT, but rather for higher level permissions.
**		For example, kre uses this to restrict who students
**		can send mail to.
**
**	Maintained by Eric Allman (eric@berkeley, ucbvax!eric) --
**		please mail changes to me.
**
**                      @(#)sysexits.h  4.2             7/31/83
*/

# define EX_OK		0	/* successful termination */

# define EX__BASE	64	/* base value for error messages */

# define EX_USAGE	64	/* command line usage error */
# define EX_DATAERR	65	/* data format error */
# define EX_NOINPUT	66	/* cannot open input */
# define EX_NOUSER	67	/* addressee unknown */
# define EX_NOHOST	68	/* host name unknown */
# define EX_UNAVAILABLE	69	/* service unavailable */
# define EX_SOFTWARE	70	/* internal software error */
# define EX_OSERR	71	/* system error (e.g., can't fork) */
# define EX_OSFILE	72	/* critical OS file missing */
# define EX_CANTCREAT	73	/* can't create (user) output file */
# define EX_IOERR	74	/* input/output error */
# define EX_TEMPFAIL	75	/* temp failure; user is invited to retry */
# define EX_PROTOCOL	76	/* remote error in protocol */
# define EX_NOPERM	77	/* permission denied */
-- 
For comp.sources.unix stuff, mail to sources@uunet.uu.net.

hydrovax@nmtsun.nmt.edu (M. Warner Losh) (01/18/88)

Mark Eichin write that using exit(0) is OS sepcific, when in fact
it is ENVIRONMENT specific.  True enough that all of the SHELLS
that UN*X uses use an exit status of zero to mean success (at least
all of the one's that I know of).  It is the SHELL, NOT THE OPERATING
SYSTEM, that is the factor here.  If you were programming on VMS, where
you could have the dcl shell (or more correctly (from a VMS point of view :-),
command interpreter [sic on spelling]) that treats an exit status of
on ODD number as success, and an EVEN (for error, I quess) number as
an error.  On the same machine, running the same OS, you can also have
DEC/Shell, which assumes a more "unix" oriented posture.  That is, it
expects the "exit(0)" convention.

As a side note.  exit(0) in UNIX isn't quit correct.  The UNIX shell,
as far as I know, doesn't give a hill of beans wheather you say exit(0),
exit(1000), exit (magic_number)....  It is the SHELL SCRIPTS that people
write that impose this "standard" upon UNIX.  I could be wrong about
this, but I seem to remeber reading in one of the books/manuals/mag
articles about unix that this was the case.  I know it's common practice,
but is it required?  Plesae resond only if YOU KNOW FOR SURE.
-- 
bitnet:	lush@nmt.csnet			M. Warner Losh
csnet:	warner%hydrovax@nmtsun
uucp:	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!warner%hydrovax
	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!hydrovax
Warning:  Hydrovax is both a machine, and an account, so be careful.

hydrovax@nmtsun.nmt.edu (M. Warner Losh) (01/18/88)

In article <1868@bsu-cs.UUCP>, dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
> Zero symmetrically divides the number line.  If one had to choose ONE
> of the values on the number line as being unique, it would have to be
> zero.  It is the only value that isn't arbitrary, the only one that
> doesn't have a mirror-image counterpart (of opposite sign), the only
> one that can't be a legal divisor, the only one that, in short,
> stands out as "different" from all the other values.
> 
Because it is, as you say, different, it is magic.  That is one of the
definitions of a magic number.  It is different, yet arbitrary.

btw, your arguement that it isn't arbitrary is BOGUS.  I could easily
come up with simialar arguements that one (SS$_NORMAL, the normal
exit status in VMS) isn't arbitrary :
  If you have something, then the least whole number of it you can have
is one.  Therefore one isn't arbitrary.  :-) * 16

The point is, that in this case, ZERO, or ANY OTHER NUMBER THAT YOU
CHOSSE TO REPESENT SUCCESS IS arbitrary.

Come on Rahul, you will have to do better than that if you want to convince
anybody that zero isn't arbitrary.
-- 
bitnet:	lush@nmt.csnet			M. Warner Losh
csnet:	warner%hydrovax@nmtsun
uucp:	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!warner%hydrovax
	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!hydrovax
Warning:  Hydrovax is both a machine, and an account, so be careful.

goudreau@xyzzy.UUCP (Bob Goudreau) (01/18/88)

In article <1868@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
>I gave a number of example attempting to show that zero is inherently
>a unique integer and therefore not a "magic number" in the usual
>sense of the term.
>....
>It seems to make perfect sense to me that in the non-VMS world in which
>a single successful termination value, and multiple failure termination
>values, are needed, zero should be the successful termination value.
>
>Therefore the use of exit(0) for successful termination is not
>arbitrary.  It is intuitively correct.

Gee that's swell, but it still doesn't address the issue of the
magic number.  You can stamp your feet and pout all you want at
"non-intuitive" operating systems, but your code still won't port
to them easily.  Doug Gwyn is still correct:  zero is definitely
a magic number when used as the successful termination value.
Your point about zero as the first index to an array is irrelevant:
such behavior is part of the specification of the C language.
Return statuses are OS-dependent, and are explicitly beyond the scope
of X3J11.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/18/88)

In article <304@fig.bbn.com> rsalz@bbn.com (Rich Salz) writes:
>**  SYSEXITS.H -- Exit status codes for system programs.

Use this on UNIX systems if you wish; it is NOT suitable for use on some
other operating systems.

leichter@yale.UUCP (Jerry Leichter) (01/19/88)

In article <7121@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>In article <304@fig.bbn.com> rsalz@bbn.com (Rich Salz) writes:
>>**  SYSEXITS.H -- Exit status codes for system programs.
>
>Use this on UNIX systems if you wish; it is NOT suitable for use on some
>other operating systems.


On the other hand, the NAMES and their respective meanings would make sense
on any operating system.  If you are willing to (a) use only macros from
SYSEXITS.H in calls to exit() or as values returned by main(); and (b) go
through the fairly simple exercise of creating a SYSEXITS.H with values
appropriate to a particular operating system you want to port to; then
your code will be very portable (at least in this one respect).

Of course, if SYSEXITS.H were to become standard - either part of an ANSI C
standard, or a defacto standard - then (b) becomes unnecessary, since some-
one will already have done the work.

...and THAT, of course, was the whole point.  (I'm sure Doug understands this,
but it might have gotten missed in his very brief response.)

(It should be noted, though, that the list of errors was clearly chosen
with a particular kind of program - a mailer - in mind.  While some of them
are more generally useful ("No permission"), others are rather specialized
("Protocol error"), and there are probably other, more generally-useful
errors that would have to be included to create a truely useful, general-
purpose "SYSEXITS" file.)

							-- Jerry

malloy@crash.cts.com (Sean Malloy) (01/19/88)

In article <3475@megaron.arizona.edu> mike@arizona.edu (Mike Coffin) writes:
>In article <1868@bsu-cs.UUCP>, dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
>> [...]
>> Zero symmetrically divides the number line.  If one had to choose ONE
>> [...]
>> one that can't be a legal divisor, the only one that, in short,
>> stands out as "different" from all the other values.
>One (1) symmetrically divides the number line.  If one had to choose ONE
> [...]
>only one, in short, that stands out as "different" from all the other
>values. :->

No, zero has to be more 'different'. Zero is the number of subjects
concerning the internals of C which can be discussed without accreting
huge quantities of flames, stupid comments, and "I would do it this
way" followups.

-- 
	Sean Malloy {hplabs!hp-sdd, akgua, sdcsvax, nosc}!crash!malloy
		ARPA: crash!malloy@nosc
	Naval Personnel Research and Development Center
	San Diego, CA 92152-6800
		UUCP: {hplabs!hp-sdd, akgua, sdcsvax}!nprdc!malloy
		ARPA: malloy@nprdc

chris@mimsy.UUCP (Chris Torek) (01/19/88)

In article <1225@nmtsun.nmt.edu> hydrovax@nmtsun.nmt.edu (M. Warner
Losh) writes:
>... The more proper VMS implementation of EXIT_STATUS should be
>SS$_NORMAL, which is (at least in 4x) defined to be 1.

(I think it was inherited from RT-11.  It was 1 in VMS 2.8.)

>Why would you expect an operating system dependent scheme such
>as exit(0) to work on all OS's?

Simple.  Let me phrase it this way:  `Why would you expect a standard
library scheme to be dependent on the O/S?'  Or, `whoever said exit
was a system call?'

Unix, by virtue of being the first system to implement the language,
is privileged: it gets to take the argument to exit() and pass it
back to the calling program.  Other systems might have to convert
the argument to 0 => success, anything else => unspecified failure.
(Actually, other systems might attempt to map the exits in
<sysexits.h>.)  This---a boolean success/failure indication---is
as much as, or perhaps even more than, a portable standard could
guarantee.  Specific systems would also provide system specific
versions of exit().  Indeed, Unix systems might define either

	_unix_exit(int status) { exit(status); }

or

	exit(int status) { _unix_exit(status); }

(symmetry means never having to say `oops' :-) )

VMS would provide

	exit(int status) { _vms_exit(_vms_map(status)); }

while AOS/VS would provide

	exit(int stauts) { _aos_exit(_aos_map(status)); }

Of course, this is not what the dpANS says, so the argument is
rather pointless.  But this is what should have been done.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

wesommer@athena.mit.edu (William E. Sommerfeld) (01/19/88)

In article <1225@nmtsun.nmt.edu> hydrovax@nmtsun.nmt.edu (M. Warner Losh) writes:
>Am I missing something here, or are you saying that because VMS cause
>this so-called mess, that they should have to live with a UNIX like
>kludge, just to make you happy?  When you exit(0) on VMS you get the error
>
>%NONAME-W-NOMESSAGE, No message text for message 0000000
>
>or something similar.  Remember that VMS is not really 'C' based, and
>much of the code is written in a whole slew of languages.  

So what.  You can use exit(), fork(), etc. from BSD UNIX FORTRAN and
Pascal.  

> Would you propose that all of that be rewritten? 

If ANSI doesn't support this, it effectively means that someone will
have to rewrite all the UNIX code which does this to use EXIT_SUCCESS
and EXIT_FAILURE.  VMS is just one machine-dependant, non-portable OS,
whereas UNIX can runs on any hardware that VMS can, and then some.

>The more proper
>VMS implementation of EXIT_STATUS should be SS$_NORMAL, which is
>(at least in 4x) defined to be 1.  Why would you expect an operating
>system dependent scheme such as exit(0) to work on all OS's?  The whole
>world isn't using UNIX.

UNIX is not the only system where zero is success, and non-zero is
failure; for example, Multics `system calls' and library routines
return a status codes which are zero on success, and non-zero on
failure.  Multics is by no means C based, either...  I would say that,
of the systems I have seen, it is far more common to use 0->success,
nonzero->failure.  Besides, on most architectures (except for the
VAX), it's easier to test a whole word against zero than it is to test
the lower bit.  Since you want multiple error values to distinguish
between different cases, and also want to make testing for success as
cheap as possible, this implies that 0 must be success.

It would make a _lot_ of sense if VMS C were to ``go with the flow''
and change exit() so that it actually returned (code ? (code << 1) :
1), assuming that even return codes mark failure, and odd ones mark
success?), or, if that wasn't feasible, (code ? SS$_FAILURE :
SS$_SUCCESS)

An emulation of wait() could perform the reverse transformation for
the benefit of things which wanted to call out to other processes,
assuming that you can emulate the UNIX fork() and wait() calls under
VMS.  

If you wanted to write VMS-specific code, you could use the system
calls directly to talk to other system functions, but then you would
_NOT_ have portable code.  The implementation can define additional
routines (vms_exit(), or whatever) if they wanted to return "success,
sort of" (is that what the other success codes mean?) instead of just
a straight success or failure indication.

				- Bill

mwm@eris (Mike (My watch has windows) Meyer) (01/19/88)

In article <1868@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
<I gave a number of example attempting to show that zero is inherently
<a unique integer and therefore not a "magic number" in the usual
<sense of the term.

# mount /dev/mathematicians_hat /head

Rahul, *all* numbers are unique and interesting. Even 1729. You can
even proof it, if you like. I dislike zero because there's no
primitive operate that generates a common set when applied to zero.
One and either of + or - generates a common set.

# umount /dev/mathematicians_hat
# mount /dev/programmers_hat /head

<Therefore the use of exit(0) for successful termination is not
<arbitrary.  It is intuitively correct.

I don't see anything intuitive about exiting with a false value for
success. Exiting with a true value seems a lot more intuitive to me.

	<mike
--
How many times do you have to fall			Mike Meyer
While people stand there gawking?			mwm@berkeley.edu
How many times do you have to fall			ucbvax!mwm
Before you end up walking?				mwm@ucbjade.BITNET

eichin@athena.mit.edu (Mark W. Eichin) (01/19/88)

This looks much too simple to me:

In C:
  
exit(ansi_status)
     int ansi_status;
{
  int vms_status;
  
  switch(ansi_status)
    {	
    case 0:
      vms_status = SS$EXIT;	/* == 1 */
      break;
    case 1:
      /* .... fill in other ANSI codes and there VMS equivalents .... */
    default:	
      vms_status = SS$WEIRD;	/* you know what I mean... */
    }

  vms_$exit(vms_status);	/* getting out for real */
}

In English:

The ANSI values for arguments to exit() do NOT specify what the
program must return to the operating system! They map status meanings
to the >>>argument of exit()<<< which will then get shuffled off into
the operating system as anything it wants... The question that should
follow is "what about system() or exec()/wait(), what should they
return?" Well, ANSI could probably specify that too, and any operating
system that needed to do a mapping for exit() could just reverse the
mapping... 

Thus, the arguments seem to result from the neglect of the idea that
simple units specified by ANSI could have deeper implementations.

Am I missing something dreadful here? [The details are fuzzy, my
knowledge of the VMS problem derives solely from these postings... but
this idea SEEMS sound.]


				Mark Eichin
				<eichin@athena.mit.edu>


				Mark Eichin
			<eichin@athena.mit.edu>
		SIPB Member & Project Athena ``Watchmaker'' 

dhesi@bsu-cs.UUCP (Rahul Dhesi) (01/19/88)

In article <10237@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>Unix, by virtue of being the first system to implement the language,
>is privileged: it gets to take the argument to exit() and pass it
>back to the calling program.  Other systems might have to convert
>the argument to 0 => success, anything else => unspecified failure.

A Daniel come to judgement!
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/19/88)

In article <21531@yale-celray.yale.UUCP> leichter@yale-celray.UUCP (Jerry Leichter) writes:
>On the other hand, the NAMES and their respective meanings would make sense
>on any operating system.

No!  Many operating systems cannot return such a variety of termination
statuses.  And it would do little good to have several of them mapped
into the same value.  Plus, there are zillions of possible reasons for
program failure, and any pre-established list cannot cover enough of them.

I think we're doing quite well to get just the two, generic failure and
generic success, standardized.

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/19/88)

In article <1225@nmtsun.nmt.edu> hydrovax@nmtsun.nmt.edu (M. Warner Losh) writes:
>Why would you expect an operating system dependent scheme such as exit(0)
>to work on all OS's?  The whole world isn't using UNIX.

You guys have gotten confused.

X3J11, including the VMS C implementor, agreed to the following:

	#include <stdlib.h>	/* defines EXIT_SUCCESS & EXIT_FAILURE */

	exit(0);		/* indicates success on all OSes */
	exit(EXIT_SUCCESS);	/* indicates success on all OSes */
	exit(EXIT_FAILURE);	/* indicates failure on all OSes */

If, as you report, VMS C does not currently map exit(0) to something
sensible, that will have to be fixed before VMS C is ANSI-conforming.

>%NONAME-W-NOMESSAGE, No message text for message 0000000

Certainly this is not something that is essential to preserve on VMS!

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/19/88)

In article <6597@agate.BERKELEY.EDU> mwm@eris.UUCP (Mike (My watch has windows) Meyer) writes:
>Rahul, *all* numbers are unique and interesting. Even 1729.

1729 is especially interesting, or "not dull" as Ramanujan would say. However,
those who haven't already heard about it wouldn't get the joke anyway.

>You can even [prove] it, if you like.

Let U = { n : n positive integer AND n is uninteresting }.
Assume (*) that U is a non-empty set.  It must have a least
member, call it m.  But, since m is the smallest uninteresting
integer, it is quite interesting.  This means it could not
have been in U.  But that is a contradiction.  Therefore the
assumption (*) must be false.  Therefore there are no
uninteresting positive integers.  QED :-)

tanner@ki4pv.uucp (Dr. T. Andrews) (01/19/88)

In article <334@splut.UUCP>, jay@splut.UUCP writes:
) In article <7208@ki4pv.uucp>, tanner@ki4pv.uucp (Dr. T. Andrews) writes:
)>  [ remarks supporting exit(0) deleted ]
) for(i = 0; i < 100; i++) {
) 	repeat_after_me('All the world does not run on Unix, either.');
) 	}
He's right.  Much of the world doesn't run unix.  Much of the world
does run C, however, and that means that somewhere out there we have
people implementing C compilers in diverse environments.

In fact, I had the pleasure of supporting just such a beast.  In
one environment where exit status didn't have the same system-defined
meaning, I went and did the right thing: I implemented an exit() with
the standard (in the old sense, not in the X3J11 sense) meaning.
My exit(0) did the right thing; my exit(non_zero) also did the right
thing.

It seems reasonable that the vax implementor should also take the
trouble to do the right thing.  If the vax folks wish to do something
strange with vms_exit status, then they and the compiler vendor are
free to implemnt a VMS-specific exit routine (vms_exit(), perhaps)
which supports the funny meanings like "failed, no errors" and
"worked, but fatal errors".  However, since this code will be VMS
specific, the implementation should only affect VMS sites.  The rest
of the world's code, which uses things like exit(0), exit(1), and
of course the ever-popular exit(n_err), should continue to be supported.

Perhaps it's time for something like this:
	for  ( i=101 ; --i ; )
		repeat_after_me("standards codify existing practice\n");
-- 
{allegra clyde!codas decvax!ucf-cs ihnp4!codas killer}!ki4pv!tanner

ok@quintus.UUCP (Richard A. O'Keefe) (01/20/88)

In article <7133@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
> In article <1225@nmtsun.nmt.edu> hydrovax@nmtsun.nmt.edu (M. Warner Losh) writes:
> >Why would you expect an operating system dependent scheme such as exit(0)
> >to work on all OS's?  The whole world isn't using UNIX.
> If, as you report, VMS C does not currently map exit(0) to something
> sensible, that will have to be fixed before VMS C is ANSI-conforming.

Everything that has been said about VMS and exit(0) so far is false.
I decide that it was time to check the manual.
	Programming in VAX C
	Order Number AA-L370B-TE
	For VAX/VMS version 4.0 or later
	Compiler version VAX C version 2.0
	April 1985.
Section 22.1.2 exit, _exit
	exit([status])
	_exit([status])
	The optional argument status corresponds with [sic!] an errno
	value.  ... The functions return the specified status to the
	parent process.  ... The two functions are identical.

[I do not understand how an argument can exchange letters with
(correspond with) a number.  No doubt they meant "correspond to".
Aren't eddicayshun wunnerful?]

Checking SYS$LIBRARY:ERRNO.H, I found that not only were the errno
symbols (such as EPERM) the same as in UNIX, they had been given the
same numbers as well.  It is clear, therefore, that in the VMS
implementation of C, the argument of exit() is a ***UNIX*** error
number (including 0 as specifying NO error), *NOT* a VMS error code.

Trying several values of N in
	main() { exit(N); }
and	main() { return N; }
I found that *none* of them resulted in any message from DCL;
*all* of them produced a quiet exit.  {But the return code was
available to DCL for inspection, and perror() does plausible things.}

VAX-11 C does more optimisation than most C compilers do.
For compatibility with other compilers, the preprocessor accepts
but IGNORES #pragma.  I wonder about the other compilers that "need"
it, I really do.

dhesi@bsu-cs.UUCP (Rahul Dhesi) (01/21/88)

In article <551@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) 
writes:
>Everything that has been said about VMS and exit(0) so far is false.
...
>I found that *none* of them resulted in any message from DCL;
>*all* of them produced a quiet exit.

The time frame of discussion is important.  DEC has recently revised
its C compiler for VMS.  Some things formerly missing are now present,
and the old exit(0) problem ("No text for message 0000" etc.) has been
fixed.
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi

ok@quintus.UUCP (Richard A. O'Keefe) (01/21/88)

In article <7292@ki4pv.uucp>, tanner@ki4pv.uucp (Dr. T. Andrews) writes:
> ) for(i = 0; i < 100; i++) {
> ) 	repeat_after_me('All the world does not run on Unix, either.');
> ) 	}
> specific, the implementation should only affect VMS sites.  The rest
> of the world's code, which uses things like exit(0), exit(1), and
> of course the ever-popular exit(n_err), should continue to be supported.
> 
If you are using UNIX, ***DON'T*** use exit(n_err)!  Why?  Because the
error code is truncated to EIGHT BITS.  So 256, 512, 768 errors and so
on look exactly like ZERO errors.  There are a couple of UNIX utilities
which do things like returning the number of files they couldn't read.
Which of course makes them useless in scripts unless you first check
that they are given fewer than 256 files...

exit(n_err) has never worked in UNIX, which is the original home of C.
How can you "continue to support" something which has always been broken?

Just to repeat an earlier point: exit(0) and exit(1) ***DO*** work in VMS.
I think I was the one to start this exchange about exit() in C, and my
original point was that exit(-1) *does not work in UNIX*.  I suggested
sticking to 0 and 1 because they *do* work in UNIX *and* in VMS.  We're
also interested in IBM MVS and VM/CMS, so here's another data point:

	IBM Systems Application Architecture
	Common Programming Interface
	C Reference [SC266-4353-0]
	For MVS, VM, and OS/2
says, on page 202,
	void exit(int status)
	set status to 0 to indicate a normal exit
	or to some other value to indicate an error.
	Control, and the value of status,
	is returned to the operating system.

This also works in SAS Lattice C.  (Apparently under OS, exit(x) where
x > 4095 is truncated to exit(4095).)  The bottom line is that
	0 for success,
	1 for failure
*is* portable between UNIX, VAX/VMS, IBM-MVS, IBM-VM/CMS, and IBM-OS/2,
and that exit(n) for n < 0 or n > 255 never "worked" in UNIX either.

TLIMONCE%DREW.BITNET@CUNYVM.CUNY.EDU (01/21/88)

Can someone post how ANSI proposes to handle this situation?  I think I
remember someone mentioning the method and it sounded very good.  Can we
hear the whole story?

                             Tom Limoncelli
  Drew U/Box 1060/Madison NJ 07940     Bitnet: tlimonce@drew.BITNET
  Disclaimer: These are my views, not my employer or Drew Univesity.
--------------------------------------------------------------------------

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/21/88)

In article <7292@ki4pv.uucp> tanner@ki4pv.uucp (Dr. T. Andrews) writes:
>Perhaps it's time for something like this:
>	for  ( i=101 ; --i ; )
>		repeat_after_me("standards codify existing practice\n");

	for ( ; ; )
		repeat_after_me( "there is no single \"existing practice\""
				 "in this case\n"
			       );

wen-king@cit-vlsi.Caltech.Edu (Wen-King Su) (01/22/88)

In article <555@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>In article <7292@ki4pv.uucp>, tanner@ki4pv.uucp (Dr. T. Andrews) writes:
<Just to repeat an earlier point: exit(0) and exit(1) ***DO*** work in VMS.
>I think I was the one to start this exchange about exit() in C, and my
<original point was that exit(-1) *does not work in UNIX*.  I suggested
>sticking to 0 and 1 because they *do* work in UNIX *and* in VMS.

This seems a little strange to me so I decided to check it out.
Following is a script showing that exit(-1) DOES work in UNIX.
I am running it on a SUN and I am using csh.

    Script started on Thu Jan 21 10:19:36 1988
    % cat t.c
    main() { exit(-1); }
    % t
    % echo $status
    -1
    % t &
    [1] 5825
    % 
    [1]    Exit -1              t
    % ^D
    script done on Thu Jan 21 10:20:03 1988

I agree that it is a good idea to have 0 as the universal indicator of
success, but I believe application programmers should be free to use
other numbers to their own advantage and OS should provide them with
the maximum flexibility.  The issue of portability is something each
programmer has to decide for <arrg!!>self, but it is always useful for
those who had the experience to point out trouble spots and recommend
solutions.
/*------------------------------------------------------------------------*\
| Wen-King Su  wen-king@vlsi.caltech.edu  Caltech Corp of Cosmic Engineers |
\*------------------------------------------------------------------------*/

hydrovax@nmtsun.nmt.edu (M. Warner Losh) (01/22/88)

In article <10237@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
> In article <1225@nmtsun.nmt.edu> I write
> >... The more proper VMS implementation of EXIT_STATUS should be
> >SS$_NORMAL, which is (at least in 4x) defined to be 1.
> 
> (I think it was inherited from RT-11.  It was 1 in VMS 2.8.)
> 
> >Why would you expect an operating system dependent scheme such
> >as exit(0) to work on all OS's?
> 
> Simple.  Let me phrase it this way:  `Why would you expect a standard
> library scheme to be dependent on the O/S?'  Or, `whoever said exit
> was a system call?'

  If I remember correctly, fopen() is system dependent (you can't
say fopen ("/tmp/foo", "r"), for example, and expect it to work on
all operating systems.  The same sort of thing is true about exit().
 
> Unix, by virtue of being the first system to implement the language,
> is privileged: it gets to take the argument to exit() and pass it
> back to the calling program.  Other systems might have to convert
> the argument to 0 => success, anything else => unspecified failure.

    The UNIX operating system does not work this way.  The shells that
surround it DO.  What I mean is this : UNIX doesn't give a furry rat's
whatever what you use for an exit status, it mearly passes it to the
shell (or to make, or whatever) who then desides what to do with that
number.  Even the shell doesn't care what value you give it, as long
as you give it something.  Most people choose to use zero, cause
that's what K&R say to use.  Not that I'm slamming UNIX, or anything,
that's just what's goin' on behind the scenes.

    In VMS, the exit status is more than just any arbitrary number.
Each of the numbers has a perscribed meaning.  The numbers are
interpeted, again by the shell (to use the UNIX terminology; command
interpreter to use DEC's), as meaning success or failure.  Again,
these exit values are useful to the shell, or shell scripts that are
running (DCL command files) IN ADDITION TO THE SHELL ITSELF.  There
are mechanisms to allow you to say "When a warning, or anything more
sever occures, then branch to this part of my DCL program".

The basic argument is this:  Since UNIX had it first, should all other
OS's be forced to use that convention?  I think not.  THIS IS AN OPERATING
SYSTEM DEPENDENT ISSUE, just like file names.  It should be delt
with in a reasonably intelligent mannor, so that ALL PARTIES involved
CAN WRITE PORTABLE CODE.  Isn't that what ANSI is all about?????


-- 
bitnet:	lush@nmt.csnet			M. Warner Losh
csnet:	warner%hydrovax@nmtsun
uucp:	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!warner%hydrovax
	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!hydrovax
Warning:  Hydrovax is both a machine, and an account, so be careful.

sarge@scheme.Berkeley.EDU (Steven Sargent) (01/22/88)

The UNIX shells absolutely enforce the 0 vs. nonzero exit status
distinction.

1. The usages
	(Shell)		if cmdlist; then stuff; else stuff; fi
	(csh)		if ({cmd}) then stuff; else stuff; endif
along with their loop analogues, make the decision based on exit status
of cmd (or of the last command in cmdlist).

2. The Shell's operators && and || also work this way, i.e., in
	foo && bar
bar is executed only if foo exits happily.

3. The Shell has a command-line option (-e) that causes a script to
exit whenever a command exits nonzeroly.

All this (and more, I'm sure; but csh is of less interest to me in
this context) is available in the relevant manual pages.

S.

ok@quintus.UUCP (Richard A. O'Keefe) (01/22/88)

In article <5262@cit-vax.Caltech.Edu>, wen-king@cit-vlsi.Caltech.Edu (Wen-King Su) writes:
> In article <555@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
> <original point was that exit(-1) *does not work in UNIX*.  I suggested
> >sticking to 0 and 1 because they *do* work in UNIX *and* in VMS.
> 
> This seems a little strange to me so I decided to check it out.
> Following is a script showing that exit(-1) DOES work in UNIX.
To summarise,
	cat <<EOF >t.c
	main(argc, argv)
	    int argc;
	    char **argv;
	    {
		exit(argc >= 2 ? atoi(argv[1]) : -1);
	    }
	EOF
	cc -o t t.c
He ran this program on a SUN, and claimed that it works.
I too shall run this on a SUN.  Behold!
	Script started on Thu Jan 21 20:09:54 1988
	% csh
	% t ; echo $status
	-1
	% t 254 ; echo $status
	-2
	% exit
	% sh
	$ t ; echo $?
	255
	$ t -2 ; echo $?
	254
	$ exit
	% exit
	script done on Thu Jan 21 20:10:42 1988
To repeat my point, UNIX truncates the argument to 8 bits.  The Bourne
shell treats this as an unsigned char.  The C shell treats this as a
signed char.  Note that on a SUN, according to /usr/include/sys/wait.h
(the include file which describes the termination status result that
is returned to a process's parent) the Bourne shell is right (the
field is described as unsigned short w_Retcode:8;) and the C shell is
wrong.  I don't want to argue for one or the other, only to point
out that they are different, so exit(-1) isn't even portable between
two shells on the same machine!

Wen-King Su also says:
> success, but I believe application programmers should be free to use
> other numbers to their own advantage and OS should provide them with
> the maximum flexibility.  The issue of portability is something each
> programmer has to decide for <arrg!!>self, but it is always useful for
> those who had the experience to point out trouble spots and recommend
> solutions.
Well, yes, but before using other numbers to their own advantage,
application programmers should at least take the trouble to read the
manuals (on a SUN, man 2 exit says explicitly that the low order 8
bits of the status are made available through wait(2), and man 2 wait
points you to <sys/wait.h> where those 8 bits are explicitly declared
to be UNsigned).  I am grateful to Wen-King Su, because I didn't know
about this design bug in the C shell before.  (The manual doesn't say
that status can take negative values, though there is a comment about
adding 0200 which may have some faint connexion.)

Are there any implementations of C in which exit(0) and exit(1) do
NOT work?  Presumably there are, or the ANSI committee wouldn't have
added the new macros (:-), but which are they?

sns@genghis.UUCP (Sam Southard) (01/23/88)

In article <1234@nmtsun.nmt.edu>, hydrovax@nmtsun.nmt.edu (M. Warner Losh) writes:
> you could have the dcl shell (or more correctly (from a VMS point of view :-),
> command interpreter [sic on spelling]) that treats an exit status of
> on ODD number as success, and an EVEN (for error, I quess) number as

Yet another reason not to use VMS - on VMS success is odd.
-- 

Sam Southard, Jr.
{sns@genghis.caltech.edu|sns@genghis.uucp|{backbone}!cit-vax!genghis!sns}

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/23/88)

In article <1234@nmtsun.nmt.edu> hydrovax@nmtsun.nmt.edu (M. Warner Losh) writes:
>As a side note.  exit(0) in UNIX isn't quit correct.  The UNIX shell,
>as far as I know, doesn't give a hill of beans wheather you say exit(0),
>exit(1000), exit (magic_number)....

No, there are shell built-ins such as "test" that "know" that only a 0
termination status indicates success.

Note that only the low-order 8 bits of the exit status are significant
on UNIX.  Therefore, adding any multiple of 256 would have no effect
(but don't do this, please!).

The point that the exit status is interpreted by the execution environment,
which is not necessarily synonymous with the "operating system", is correct.
Saying that this is a "shell" is being too specific, however.  In fact,
even on UNIX it's not necessarily a shell, just the parent process.

ok@quintus.UUCP (Richard A. O'Keefe) (01/23/88)

In article <1234@nmtsun.nmt.edu>, hydrovax@nmtsun.nmt.edu
(M. Warner Losh) writes (with spelling unchanged):

> As a side note.  exit(0) in UNIX isn't quit correct.  The UNIX shell,
> as far as I know, doesn't give a hill of beans wheather you say exit(0),
> exit(1000), exit (magic_number)....  It is the SHELL SCRIPTS that people
> write that impose this "standard" upon UNIX.  I could be wrong about this

He is.

    sh(1):
	Option: set -e is "exit immediately if a command exits with
	a non-zero exit status".
	Control structures:  Cmd1 && Cmd2 executes Cmd2 iff Cmd1 returns
	a zero exit status,  Cmd1 || Cmd2 executes Cmd2 iff Cmd1 returns
	a non-zero exit status. if Cmds then ... treats zero exit status
	as true, non-zero as false.  while Cmds do ... is the same.

    csh(1):
	Option:	set -e
	means exit if a command terminates abnormally OR exits with NONZERO.
	"Builtin commands that fail return exit status `1', all other
	builtin command set status to `0'."  && and || are as in sh(1);
	if and while take expressions, not commands, as arguments.

    make(1):
	"make normally terminates when a command returns non-zero
	status, unless the -i or -k option is in effect."

It is quite definitely the shells which impose the convention
0 == success == true, non-zero ==failure == false, not the scripts.
Try the following in a recent Bourne shell:
	# "foo N" prints true or false 
	foo() { ( exit $1 ) && ( echo true ) || ( echo false ) }
	# try it
	foo 0	# true
	foo 1	# false

This is relevant to some C programmers because the 0/non-0 convention
is the direct opposite of the C convention.  This confused me for a
couple of days.  It is possible to program around the non-zero-exit-
status-means-failure convention, but it definitely is a convention
that is supported by UNIX shells (not scripts) and by DEC/Shell in VMS.

Note that this convention is reflected back into C by the system(3)
command:  system "returns the exit status of the shell".   This means
that the 0==success, non-zero==failure rule is visible to C.  (You
*do* check the result of calls to system(), don't you?)  Alas, all
that the Oct86 dpANS says about the result of system() is that
	system(NULL) returns non-zero to indicate that there
		     is a command interpreter
	system(non-NULL) is completely implementation-defined.
Beware, by the way.  Due to byte sex problems, even in UNIX, the
result of system() may be shifted left by 8 (it is on a SUN).

We still have the question:
	exit(0) and exit(1) make sense in UNIX, VAX/VMS,
	IBM-MVS, and IBM-VM.
Which implementations of C do they *not* work in?
Which implementations of C do *not* use 0==success for system()?

hydrovax@nmtsun.nmt.edu (M. Warner Losh) (01/23/88)

In article <551@cresswell.quintus.UUCP>, ok@quintus.UUCP (Richard A. O'Keefe) writes:
> 
> Trying several values of N in
> 	main() { exit(N); }
> and	main() { return N; }
> I found that *none* of them resulted in any message from DCL;
> *all* of them produced a quiet exit.  {But the return code was
> available to DCL for inspection, and perror() does plausible things.}
I have VMS version 4.4, running C version 2.2.  When I do an exit(0);,
I get the message that I posted. (The No message for this message
message).  In the 2.2 manual, section 22.1.2, it says that the
value is returned to DCL "and a message is displayed".  I guess that
Version 2.3 fixes this problem.



-- 
bitnet:	lush@nmt.csnet			M. Warner Losh
csnet:	warner%hydrovax@nmtsun
uucp:	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!warner%hydrovax
	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!hydrovax
Warning:  Hydrovax is both a machine, and an account, so be careful.

guy@gorodish.Sun.COM (Guy Harris) (01/23/88)

> Beware, by the way.  Due to byte sex problems, even in UNIX, the
> result of system() may be shifted left by 8 (it is on a SUN).

Nope.  This has nothing to do with byte sex problems, and is true on all
non-broken UNIX implementations (even those with a byte size other than 8
bits).

On UNIX systems, "system()" calls "wait()" to wait for the shell that runs the
command to terminate; the value that "wait()" stuffs into the "int" pointed to
by its first argument is what "system()" returns.  The exit status of the shell
is always shifted left by 8 in the value returned by "wait()"; the low order 8
bits are used if the shell stops or is terminated by a signal.

(Ignore the fact that in BSD systems "wait" is nominally declared as returning
a "union wait".  The BSD *kernel* code still returns an "int", in the same way
that all other UNIX implementations do.  The "union wait" was, I presume, an
attempt to make it easier to pull the exit status apart.  Unfortunately, since
the order of bit fields in a structure is implementation-dependent, that
structure is not portable!  Note that the Sun version of that structure has
"#ifdef"s giving one definition for little-endian VAXes and another for
big-endian Sun-3s and Sun-4s.)
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

chris@mimsy.UUCP (Chris Torek) (01/23/88)

>In article <10237@mimsy.UUCP> I claimed that (in a better world)
>>Unix, by virtue of being the first system to implement the language,
>>is privileged: it gets to take the argument to exit() and pass it
>>back to the calling program.  Other systems might have to convert
>>the argument to 0 => success, anything else => unspecified failure.

In article <1240@nmtsun.nmt.edu> hydrovax@nmtsun.nmt.edu (M. Warner
Losh) writes:
>    The UNIX operating system does not work this way.  The shells that
>surround it DO.

This is true, and entirely irrelevant.  Since the shells that
surround it assume that 0 => success, anything else => unspecified
failure, `Unix' (whatever that is) assumes 0 => success, anything
else => unspecified failure.  While there are programs that do not
follow this convention, they are in the minority (and, incidentally,
they are being weeded out, at least in 4BSD: /etc/dump recently
changed to exit(0) instead of exit(1) on success).

In other words, all we have to do is take this convention and
establish it as a standard across all systems (including Unix!---where
it is implemented entirely outside of the kernel, but it *is*
implemented), and *everything* *works*.  We have gained portability
and lost nothing.

>The basic argument is this:  Since UNIX had it first, should all other
>OS's be forced to use that convention?

Since portability is gained, and nothing is lost, *YES*.  This is
then a *language* convention, *not* an operating system convention.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

ok@quintus.UUCP (Richard A. O'Keefe) (01/23/88)

In article <39799@sun.uucp>, guy@gorodish.Sun.COM (Guy Harris) writes:
> > Beware, by the way.  Due to byte sex problems, even in UNIX, the
> > result of system() may be shifted left by 8 (it is on a SUN).
> 
> Nope.  This has nothing to do with byte sex problems, and is true on all
> non-broken UNIX implementations (even those with a byte size other than 8
> bits).
> 
OOPS!  I was misled by the SUN manual page for system(2), which suggests
that the value IS e.g. 127 but 'may be displayed as "32512"'.
The manual page for wait(2) is still misleading.  I checked a System Vr2
manual, and it says "the <<high order 8 bits>> of status contain the low
order 8 bits of the argument that the child process passed to exit()";
you have to read carefully to realise that this means the high order 8
bits of the low order 16 bits...

I've been using

#define	WAIT_EXIT(x) (((x) >> 8) & 0377)
#define WAIT_DUMP(x) ( (x) & 0200)
#define WAIT_SGNO(x) ( (x) & 0177)

	int child;
	int status;
	...
	if ((child = wait(&status)) < 0) ...
for years, and just put up with 4.2BSD lint complaining about the way
I use wait().  I'd forgotten what the macros do.  (That's portability...)

hydrovax@nmtsun.nmt.edu (M. Warner Losh) (01/24/88)

In article <7162@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
> In article <1234@nmtsun.nmt.edu> hydrovax@nmtsun.nmt.edu (I) write:
> >As a side note.  exit(0) in UNIX isn't quit correct.  The UNIX shell,
> >as far as I know, doesn't give a hill of beans wheather you say exit(0),
> >exit(1000), exit (magic_number)....
> 
> No, there are shell built-ins such as "test" that "know" that only a 0
> termination status indicates success.
> 

A knee jerk reaction at best.  Had I stopped to read the manuals.....

> The point that the exit status is interpreted by the execution environment,
> which is not necessarily synonymous with the "operating system", is correct.
> Saying that this is a "shell" is being too specific, however.  In fact,
> even on UNIX it's not necessarily a shell, just the parent process.

I know that picking nits like this can be irritating, but they should be
pointed out from time to time.  I just got a little carried away with
the generalism.  Programmers that complain about how this or that system
does X should realize what part of the system is resonsible for the X
behaviour.  Otherwise, we might say that UNIX (or VMS) has lots of bugs
in it, because some obscure utility core dumps (or produces a typical
VMS error SCREEN :-).  That utility is buggy, not the operating system
in which it lives.

-- 
bitnet:	lush@nmt.csnet			M. Warner Losh
csnet:	warner%hydrovax@nmtsun
uucp:	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!warner%hydrovax
	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!hydrovax
Warning:  Hydrovax is both a machine, and an account, so be careful.

rsalz@bbn.com (Rich Salz) (01/24/88)

>>I might be wrong.
>You are.
So are you. :-)

>    sh(1):
...
>	Control structures:  Cmd1 && Cmd2 executes Cmd2 iff Cmd1 returns
>	a zero exit status,  Cmd1 || Cmd2 executes Cmd2 iff Cmd1 returns
...
>    csh(1):
>	...  && and || are as in sh(1);
...

Nope.  The use of && and || in csh is the opposite of that in /bin/sh.
	/bin/sh -c "/bin/test -d foo || mkdir foo"
Means if the foo directory doesn't exist, make it.  That is, /bin/sh does
the "conceptually right thing" in that it takes a||b to mean, do b if a
failed.

The Cshell takes a||b in the mathematical sense; do b if a does an exit(0):
	/bin/csh -c "/bin/test -d foo || mkdir foo"
will never make the directory, or mkdir will spit if it already exists.

This has stopped being an comp.lang.c.ansii-bash issue, so I'm directing
followups to comp.unix.questions
	/r$
-- 
For comp.sources.unix stuff, mail to sources@uunet.uu.net.

peter@sugar.UUCP (Peter da Silva) (02/03/88)

I don't understand the problem.

On VMS, neither 1 nor 0 are valid exit codes.

So have the exit function map 0 into SUCCESS, and 1 into FAIL.
Let anything else through unchanged...

Or go with VMS$EXIT(VMS_CODE);.
-- 
-- Peter da Silva  `-_-'  ...!hoptoad!academ!uhnix1!sugar!peter
-- Disclaimer: These U aren't mere opinions... these are *values*.

jkchan@lynx.cat.syr.edu (J. K. Chan) (03/31/91)

I must be missing learning some simple idea about the use of exit();.
Given the following program (I chopped it out from my program),
"lint" always issues a warning message as shown in the comment part
of the program.  My program can run but I'm bothered by the lint
warning message.  I tried to use lint in different Unix accounts but
still got the same message.  The K&R book didn't say anything more than just
using exit(); directly.  Please help and send email to the above address.
Thanks in advance.
Jim

/*
    exit value declared inconsistently	llib-lc(232)  ::  t.c(8)
*/
#include <stdio.h>
#include <stdlib.h>
main()
{
  exit(0);
}

jim@segue.segue.com (Jim Balter) (04/01/91)

In article <1991Mar30.155011.767@rodan.acs.syr.edu> jkchan@lynx.cat.syr.edu (J. K. Chan) writes:
>    exit value declared inconsistently	llib-lc(232)  ::  t.c(8)

How is exit declared in stdlib.h and in llib-lc on your system?  They should
both be declared as returning void.  I suspect that your stdlib.h doesn't
declare exit at all, which would explain why the message refers to t.c(8),
which would be an implicit declaration of  int exit();  in the absense of
a declaration in stdlib.h.

When posting a question like this to the net, you really ought to provide the
obvious information (what system and compiler you are using, what line 232 of
llib-lc is) rather than assuming people have E.S.P. or that all systems are
identical.

It is also useful to treat such a specific informative message from lint as
just that, rather than as a magic incantation.

In any case, your usage of exit is fine.  Some compilers and versions of lint
will also complain that main returns no value even though it is expected to.
Some will honor a comment on the declaration of exit indicating that it never
returns, or (inferior) some will honor a /*NOTREACHED*/ following the call
to exit, but since this is far from universal, just learn to ignore the
warnings when issued in conjunction with exit.  Or use return instead of exit
in main; thats will avoid the warnings in this case.

jjr@rushpc (John J. Rushford Jr) (04/02/91)

In article <1991Mar30.155011.767@rodan.acs.syr.edu> jkchan@lynx.cat.syr.edu (J. K. Chan) writes:
>    exit value declared inconsistently	llib-lc(232)  ::  t.c(8)

In article <1991Mar31.6943@segue.segue.com> jim@segue.segue.com (Jim Balter) writes:

> How is exit declared in stdlib.h and in llib-lc on your system?  They should
> both be declared as returning void.  I suspect that your stdlib.h doesn't
> declare exit at all, which would explain why the message refers to t.c(8),
> which would be an implicit declaration of  int exit();  in the absense of
> a declaration in stdlib.h.

I've always used the following and avoid the lint complaint:

#include	<stdio.h>

void exit();  /* exit returns type void */

main()
{
	program_stuff();
	exit(1);
	exit(2);
	exit(3);
	exit(etc);
}
-- 

J. Rushford
-----------
Westminster, Colorado.