[comp.os.minix] atexit

frank@Morgan.COM (Frank Wortner) (11/15/88)

I've written an atexit() function for use with the Minix 1.3 library.
It's occasionally useful, and no one (that I can recall) has posted
anything like it yet, so here it is.  Enjoy!

					Frank
------------------------------------------------------------------------------
echo x - atexit.doc
sed '/^X/s///' > atexit.doc << '/'
Xint atexit(func)
Xvoid (*func)();
X
Xatexit() arranges for the subroutine whose address is func to be
Xcalled upon normal program termination.  atexit() returns zero
Xif the registration cannot be made, non-zero otherwise.
/
echo x - atexit.c
sed '/^X/s///' > atexit.c << '/'
X/* Copyright 1988 Frank Wortner
X**	You may reproduce and use this software as long as you
X**	do not delete this notice from the source code.
X*/
X
X#define MAXFN 33	/* Maximum number of functions registerable
X			   (includes 1 for __cleanup)			*/
X
Xtypedef void (*PFN)();	/* Pointer to FuNction */
X
Xextern PFN __cleanup;	/* imported from exit.c */
X
Xstatic PFN fn[MAXFN];	/* addresses of functions stored here */
Xstatic int nfn = -1;	/* number of functions registered less one */
X
Xvoid checkcleanup(), run_atexit();
X
Xint atexit(fun)
XPFN fun;
X{
X	if (nfn == -1)			/* Do we need to check for stdio? */
X		checkcleanup();
X	if (nfn >= MAXFN)		/* Run out of room yet? */
X		return (-1);
X	fn[++nfn] = fun;		/* Save the address of the subr. */
X	return (0);
X}
X
X/* Check to see if stdio is used.  If yes register stdio's cleanup routine
X** with the atexit() system and then force stdio to call run_atexit().
X*/
Xstatic void checkcleanup()
X{
X	if (__cleanup)			/* stdio used ? */
X		fn[++nfn] = __cleanup;
X	__cleanup = run_atexit;
X}
X
X/* Run the requested subroutines */
Xstatic void run_atexit()
X{
X	while (nfn >= 0) {
X		(*fn)[nfn--]();
X	}
X}
/


-- 
						Frank

"Computers are mistake amplifiers."

frank@Morgan.COM (Frank Wortner) (11/28/88)

Here, for hopefully the *final* time is atexit().  Credit goes to Mark
Becker and Bruce Evans for spotting inconsistancies in the previous
(now cancelled) postings.

To use this function, unshar the attached archive, and apply the patch
putc.dif to putc.c.  (It's in libsrc.a.)  Compile the resulting putc.c
like so:

	cc -c -O -LIB putc.c
	
and replace putc.s in libc.a.  If you do not, atexit() won't work.  atexit()
also will not work if you do not have the 1.3 C library.  You can make it
work with earlier libaries by modifying exit.c.  Simply add a line that
checks to see if __cleanup contains a non-NULL pointer and calls the function
addressed.

One final warning:  I've only tried this function on PC-Minix.  While
chances are the ST library works in the same manner, I have no way of
confirming this.

Good luck.

						Frank

"Computers are mistake amplifiers."

-------------------------------cut here----------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	atexit.c
#	atexit.fmt
#	putc.dif
# This archive created: Mon Nov 28 08:53:10 1988
export PATH; PATH=/bin:$PATH
echo shar: extracting "'atexit.c'" '(1126 characters)'
if test -f 'atexit.c'
then
	echo shar: will not over-write existing file "'atexit.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'atexit.c'
	X/* Copyright 1988 Frank Wortner
	X**	You may reproduce and use this software as long as you
	X**	do not delete this notice from the source code.
	X*/
	X
	X#define MAXFN 33	/* Maximum number of functions registerable
	X			   (includes 1 for __cleanup)			*/
	X
	Xtypedef void (*PFN)();	/* Pointer to FuNction */
	X
	Xextern PFN __cleanup;	/* imported from exit.c */
	X
	Xstatic PFN fn[MAXFN];	/* addresses of functions stored here */
	Xstatic int nfn = -1;	/* number of functions registered less one */
	X
	Xstatic void checkcleanup(), run_atexit();
	X
	Xint atexit(fun)
	XPFN fun;
	X{
	X	if (nfn == -1)			/* Do we need to check for stdio? */
	X		checkcleanup();
	X	if (nfn >= MAXFN)		/* Run out of room yet? */
	X		return (-1);
	X	fn[++nfn] = fun;		/* Save the address of the subr. */
	X	return (0);
	X}
	X
	X/* Check to see if stdio is used.  If yes register stdio's cleanup routine
	X** with the atexit() system and then force stdio to call run_atexit().
	X*/
	Xstatic void checkcleanup()
	X{
	X	if (__cleanup)			/* stdio used ? */
	X		fn[++nfn] = __cleanup;
	X	__cleanup = run_atexit;
	X}
	X
	X/* Run the requested subroutines */
	Xstatic void run_atexit()
	X{
	X	while (nfn >= 0) {
	X		(*fn[nfn--])();
	X	}
	X}
SHAR_EOF
if test 1126 -ne "`wc -c < 'atexit.c'`"
then
	echo shar: error transmitting "'atexit.c'" '(should have been 1126 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'atexit.fmt'" '(422 characters)'
if test -f 'atexit.fmt'
then
	echo shar: will not over-write existing file "'atexit.fmt'"
else
sed 's/^	X//' << \SHAR_EOF > 'atexit.fmt'
	X
	X
	X
	Xatexit(3)              C LIBRARY FUNCTIONS              atexit(3)
	X
	X
	X
	XNAME
	X     atexit() - call a function just before program termination
	X
	XSYNOPSIS
	X     int atexit(func)
	X     void (*func)();
	X
	XDESCRIPTION
	X     atexit() arranges for the subroutine whose address  is  func
	X     to  be  called  upon  normal  program termination.  atexit()
	X     returns zero if the registration cannot  be  made,  non-zero
	X     otherwise.
	X
SHAR_EOF
if test 422 -ne "`wc -c < 'atexit.fmt'`"
then
	echo shar: error transmitting "'atexit.fmt'" '(should have been 422 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'putc.dif'" '(528 characters)'
if test -f 'putc.dif'
then
	echo shar: will not over-write existing file "'putc.dif'"
else
sed 's/^	X//' << \SHAR_EOF > 'putc.dif'
	X*** putc.c.orig	Tue Nov 23 05:14:07 1988
	X--- putc.c	Tue Nov 23 05:08:07 1988
	X***************
	X*** 22,28 ****
	X  		didwrite++;
	X  	}
	X  	else{
	X! 		__cleanup = _cleanup;
	X  		*iop->_ptr++ = ch;
	X  		if ((++iop->_count) >= BUFSIZ && !testflag(iop,STRINGS) ){
	X  			n = write(iop->_fd,iop->_buf,iop->_count);
	X--- 22,29 ----
	X  		didwrite++;
	X  	}
	X  	else{
	X! 		if (__cleanup == 0)
	X! 			__cleanup = _cleanup;
	X  		*iop->_ptr++ = ch;
	X  		if ((++iop->_count) >= BUFSIZ && !testflag(iop,STRINGS) ){
	X  			n = write(iop->_fd,iop->_buf,iop->_count);
SHAR_EOF
if test 528 -ne "`wc -c < 'putc.dif'`"
then
	echo shar: error transmitting "'putc.dif'" '(should have been 528 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
-- 
						Frank

"Computers are mistake amplifiers."