[comp.os.minix] Making exit

rmtodd@uokmax.UUCP (Richard Michael Todd) (12/11/87)

Here's the info on how to get exit() and _exit() to work on MINIX like 
they work on UNIX (exit() always flushes all stdio buffers, _exit() exits
immediately, but exit() won't cause stdio to be linked in if your program
never references it.)  You'll probably need this to get PD Tar to work
correctly on MINIX (although you probably could get away with sticking in
a call to _cleanup() at the end of main(), still, why not go ahead and make
libc.a more UNIX-compatible while you're at it?)  Long-time readers of this
newsgroup may have already seen this once before; if you've already put this
in your libc.a, you're in good shape.  

Here's how I altered the library:
	1. Cd to the library source dir (in my system /u/src/lib).
	2. Edit printdat.c and include in it at the end the contents of
cleanup.c , deleting the redundant #include.  This way whenever the printdat
module is loaded (which is whenever _io_table is referenced, i.e. any stdio
file is referred to), the version of cleanup that flushes all stdio buffers
is also linked in.  You no longer need cleanup.c, so delete it.
	3. Edit exit.c.  Change the given exit() function so that it is now
called _exit() (the new name for the direct system exit call).  Add a new
function exit() at the end that looks like this:
-------------------------------------------------------------------------
	PUBLIC int exit(status)
	int status;
	{
		_cleanup();
		_exit(status);
	}
-------------------------------------------------------------------------
	4.  Create a new file 'fakecleanup.c' with this in it:
	int _cleanup() {}
	5. Compile the changed and added files and rebuild the library.
Note that the 'ar' commands 'r' (replace file) option is known to screw up
the library's order (deleting the file from the old position and replacing it
at the end.  Yuk.)  It's safest to recreate the library from scratch.  What I
do is cd to a subdirectory of /u/src/lib, unpack libc.a ("ar xv libc.a"),
delete libc.a, move the *.s files I've just made from /u/src/lib to the
subdirectory, and use a shell script to rebuild libc.a, which I then copy
to /usr/lib.  There also was a script posted some time back for automatically
rebuilding libc.a, taking the ordering of the previous version as a starting
base (I believe it was picked up in the V1.2 update).  I don't use that script,
so I don't know whether it'll work or not.
--------------------------------------------------------------------------
Richard Todd
USSnail:820 Annie Court,Norman OK 73069
UUCP: {allegra!cbosgd|ihnp4}!occrsh!uokmax!rmtodd

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

In article <960@uokmax.UUCP> rmtodd@uokmax.UUCP (Richard Michael Todd) writes:
>... exit() always flushes all stdio buffers, _exit() exits
>immediately, but exit() won't cause stdio to be linked in if
>your program never references it. ...
...
>	4.  Create a new file 'fakecleanup.c' with this in it:
>	int _cleanup() {}
>	5. Compile the changed and added files and rebuild the library.
[being very careful about the order of files in the library]

This method can work, depending on the implmentation of your archiver
and loader, but is rather painful.  A simpler (to me) system is
the one I implemented recently; it goes about like this:

	exit.c:
	int (*__cleanup)();

	exit(status)
		int status;
	{

		if (__cleanup)
			(*__cleanup)();
		_exit(status);
	}

	<In one or more stdio files that are used by IO operations,
	such that any use of stdio will run the code below.  In
	4.3BSD this can be put in exactly one place, in findiop.c.
	If it must go in several files, this should probably be
	placed in a header file.>:
		...
		extern int (*__cleanup)();
		int _cleanup();

		/* arrange for exit to call _cleanup */
		__cleanup = _cleanup;
		...

This way exit has no reference to any stdio functions; it merely
uses a sizeof(int (*)()) global variable.  If stdio has been used,
this variable points to _cleanup, so that exit can find it.  Note
that if stdio is referenced but never used, _cleanup is never
called.  This particular implementation assumes that exit will
always be referenced if stdio is referenced; since the typical C
startup is `...; exit(main(argc, argv, envp));' this will be true
unless you write assembly coded startups.

This would be better done with a reserved slot in an `atexit'
table, but that requires a bit more ambition than I had when I
implemented it.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris