Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!uunet!seismo!mcnc!gatech!hao!oddjob!gargoyle!ihnp4!homxb!mhuxt!mhuxm!mhuxo!ulysses!sfmag!sfsup!mpl
From: mpl@sfsup.UUCP (M.P.Lindner)
Newsgroups: comp.os.minix
Subject: Re: Keeping exit(3) small but making it work for stdio -- atexit()
Message-ID: <1607@sfsup.UUCP>
Date: Thu, 9-Jul-87 20:47:14 EDT
Article-I.D.: sfsup.1607
Posted: Thu Jul  9 20:47:14 1987
Date-Received: Sun, 12-Jul-87 09:23:47 EDT
References: <3118@felix.UUCP> <2352@hoptoad.uucp> <3169@felix.UUCP> <333@mcdsun.UUCP>
Organization: AT&T-IS, Summit N.J. USA
Lines: 66
Summary: data.c

In article <333@mcdsun.UUCP>, fnf@mcdsun.UUCP writes:
< In article <2368@hoptoad.uucp> gnu@hoptoad.uucp (John Gilmore) writes:
< >While Art's solution works, there is a cleaner solution than
	[text deleted]
< function, just set a global pointer (_stdio_cleanup) in exit and insure
< that it got dereferenced *after* all the functions registered by atexit().
< 
< P.S.  I put my pointer initialization as the first statement in flsbuf()
< in flsbuf.c:
< 
< 	     unsigned char c1;
< 	+    extern VOID (*_stdio_cleanup)();	/* Found in exit() module */
< 	
< 	+    _stdio_cleanup = _cleanup;
	[more text deleted]
< This may or may not be the theoretically correct place to put it, so if
< someone more knowledgeable about stdio wants to speak up...
	[still MORE text deleted]
< = Fred Fish  Motorola Computer Division, 3013 S 52nd St, Tempe, Az 85282  USA
> = seismo!noao!mcdsun!fnf    (602) 438-5976

The correct thing to do theoretically is declare _stdio_cleanup to be a global
in exit, and declare *and initialize* it in data.c (the file which declares
_iob).  That way, if there's no reference to stdio, data.c doesn't get loaded
becasue there's no unresolved reference to _stdio_cleanup.  However, if any
stdio is used, data.c will get loaded (since _iob is referenced), and the
loader will merge the two declarations (technically non-kosher, but laoders
do these things) producing the desired result.  As an exampl (and also a test)
try the following:

main.c:
main() { foo(); }

foo.c:
int	foobar;
foo() { printf("%d\n", foobar); }

bar.c:
int	xyzzy;
int	foobar = 3;

cc -c foo.c bar.c
ar rv libbar foo.o bar.o
cc main.c libbar
a.out

should print "0" for the value of foobar as printed by foo().
now edit main.c:
extern int	xyzzy;
main() { xyzzy = 0; foo(); }

cc main.c libbar
a.out

should print "3" for the value of foobar, since the reference to xyzzy
pulled in bar.o which initialized foobar to 3.  Simple, no?

The method of putting the statement in flsbuf has the disadvantage that if
flsbuf is never called (ie no output buffer is filled by the program), the
output doesn't get flushed.  Thus, a program like printf("hello world") fails
to produce output, while printf("hello world\n") works, because of line
buffering.  I hope I was able to explain this satisfactorily to the net
audience.

Mike Lindner
....!ihnp4!attunix!mpl