OSDN Git Service

Doh! Miles Bader noticed a couple of spots where I forgot
[uclinux-h8/uClibc.git] / libc / stdlib / atexit.c
1 /* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
2  * This file is part of the Linux-8086 C library and is distributed
3  * under the GNU Library General Public License.
4  */
5
6 /*
7  * Dec 2000          Manuel Novoa III
8  *
9  *   Made atexit handling conform to standards... i.e. no args.
10  *   Removed on_exit since it did not match gnu libc definition.
11  *   Combined atexit and __do_exit into one object file.
12  *
13  * Feb 2001          Manuel Novoa III
14  *
15  *   Reworked file after addition of __uClibc_main.
16  *   Changed name of __do_exit to atexit_handler.
17  *   Changed name of __cleanup to __uClibc_cleanup.
18  *   Moved declaration of __uClibc_cleanup to __uClibc_main
19  *      where it is initialized with (possibly weak alias)
20  *      __stdio_flush_buffers.
21  *
22  * Jul 2001          Steve Thayer
23  * 
24  *   Added an on_exit implementation (that now matches gnu libc definition.)
25  *   Pulled atexit_handler out of the atexit object since it is now required by
26  *   on_exit as well.  Renamed it to __exit_handler.
27  *   Fixed a problem where exit functions stop getting called if one of
28  *   them calls exit().
29  *   As a side effect of these changes, abort() no longer calls the exit
30  *   functions (it now matches the gnu libc definition).
31  *
32  */
33
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <errno.h>
37
38 #define __MAX_EXIT __UCLIBC_MAX_ATEXIT
39
40 typedef void (*aefuncp) (void);         /* atexit function pointer */
41 typedef void (*oefuncp) (int, void *);  /* on_exit function pointer */
42 typedef enum {
43         ef_atexit,
44         ef_on_exit
45 } ef_type; /* exit function types */
46
47 /* this is in the L_exit object */
48 extern void (*__exit_cleanup) (int);
49
50 /* these are in the L___do_exit object */
51 extern int __exit_count;
52 extern void __exit_handler(int);
53 extern struct exit_function {
54         ef_type type;   /* ef_atexit or ef_on_exit */
55         union {
56                 aefuncp atexit;
57                 struct {
58                         oefuncp func;
59                         void *arg;
60                 } on_exit;
61         } funcs;
62 } __exit_function_table[__MAX_EXIT];
63
64 #ifdef L_atexit
65         /*
66  * register a function to be called at normal program termination
67  * (the registered function takes no arguments)
68          */
69 int atexit(aefuncp func)
70 {
71         struct exit_function *efp;
72
73         if (__exit_count >= __MAX_EXIT) {
74                 __set_errno(ENOMEM);
75                 return -1;
76         }
77         if (func) {
78                 __exit_cleanup = __exit_handler; /* enable cleanup */
79                 efp = &__exit_function_table[__exit_count++];
80                 efp->type = ef_atexit;
81                 efp->funcs.atexit = func;
82         }
83         return 0;
84 }
85 #endif
86
87 #ifdef L_on_exit
88 /*
89  * register a function to be called at normal program termination
90  * the registered function takes two arguments:
91  *     status - the exit status that was passed to the exit() function
92  *     arg - generic argument
93  */
94 int on_exit(oefuncp func, void *arg)
95 {
96         struct exit_function *efp;
97
98         if (__exit_count >= __MAX_EXIT) {
99                 __set_errno(ENOMEM);
100                 return -1;
101         }
102         if (func) {
103                 __exit_cleanup = __exit_handler; /* enable cleanup */
104                 efp = &__exit_function_table[__exit_count++];
105                 efp->type = ef_on_exit;
106                 efp->funcs.on_exit.func = func;
107                 efp->funcs.on_exit.arg = arg;
108         }
109         return 0;
110 }
111 #endif
112
113 #ifdef L___exit_handler
114 struct exit_function __exit_function_table[__MAX_EXIT];
115 int __exit_count = 0; /* Number of registered exit functions */
116
117 /*
118  * Handle the work of executing the registered exit functions
119  */
120 void __exit_handler(int status)
121 {
122         struct exit_function *efp;
123
124         /* In reverse order */
125         for ( ; __exit_count-- ; ) {
126                 efp = &__exit_function_table[__exit_count];
127                 switch (efp->type) {
128                 case ef_on_exit:
129                         if (efp->funcs.on_exit.func) {
130                                 (efp->funcs.on_exit.func) (status, efp->funcs.on_exit.arg);
131                         }
132                         break;
133                 case ef_atexit:
134                         if (efp->funcs.atexit) {
135                                 (efp->funcs.atexit) ();
136                         }
137                         break;
138                 }
139         }
140 }
141 #endif
142
143 #ifdef L_exit
144 extern void weak_function __stdio_flush_buffers(void);
145 void (*__exit_cleanup) (int) = 0;
146
147 /*
148  * Normal program termination
149  */
150 void exit(int rv)
151 {
152         /* Perform exit-specific cleanup (atexit and on_exit) */
153         if (__exit_cleanup) {
154                 __exit_cleanup(rv);
155         }
156
157         /* Clean up everything else */
158         if (__stdio_flush_buffers) 
159             __stdio_flush_buffers();
160
161         _exit(rv);
162 }
163 #endif