OSDN Git Service

Miles Bader writes:
[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_close_all.
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 extern void __stdio_close_all(void);
48
49 /* this is in the L_exit object */
50 extern void (*__exit_cleanup) (int);
51
52 /* these are in the L___do_exit object */
53 extern int __exit_count;
54 extern void __exit_handler(int);
55 extern struct exit_function {
56         ef_type type;   /* ef_atexit or ef_on_exit */
57         union {
58                 aefuncp atexit;
59                 struct {
60                         oefuncp func;
61                         void *arg;
62                 } on_exit;
63         } funcs;
64 } __exit_function_table[__MAX_EXIT];
65
66 #ifdef L_atexit
67         /*
68  * register a function to be called at normal program termination
69  * (the registered function takes no arguments)
70          */
71 int atexit(aefuncp func)
72 {
73         struct exit_function *efp;
74
75         if (__exit_count >= __MAX_EXIT) {
76                 __set_errno(ENOMEM);
77                 return -1;
78         }
79         if (func) {
80                 __exit_cleanup = __exit_handler; /* enable cleanup */
81                 efp = &__exit_function_table[__exit_count++];
82                 efp->type = ef_atexit;
83                 efp->funcs.atexit = func;
84         }
85         return 0;
86 }
87 #endif
88
89 #ifdef L_on_exit
90 /*
91  * register a function to be called at normal program termination
92  * the registered function takes two arguments:
93  *     status - the exit status that was passed to the exit() function
94  *     arg - generic argument
95  */
96 int on_exit(oefuncp func, void *arg)
97 {
98         struct exit_function *efp;
99
100         if (__exit_count >= __MAX_EXIT) {
101                 __set_errno(ENOMEM);
102                 return -1;
103         }
104         if (func) {
105                 __exit_cleanup = __exit_handler; /* enable cleanup */
106                 efp = &__exit_function_table[__exit_count++];
107                 efp->type = ef_on_exit;
108                 efp->funcs.on_exit.func = func;
109                 efp->funcs.on_exit.arg = arg;
110         }
111         return 0;
112 }
113 #endif
114
115 #ifdef L___exit_handler
116 struct exit_function __exit_function_table[__MAX_EXIT];
117 int __exit_count = 0; /* Number of registered exit functions */
118
119 /*
120  * Handle the work of executing the registered exit functions
121  */
122 void __exit_handler(int status)
123 {
124         struct exit_function *efp;
125
126         /* In reverse order */
127         for ( ; __exit_count-- ; ) {
128                 efp = &__exit_function_table[__exit_count];
129                 switch (efp->type) {
130                 case ef_on_exit:
131                         if (efp->funcs.on_exit.func) {
132                                 (efp->funcs.on_exit.func) (status, efp->funcs.on_exit.arg);
133                         }
134                         break;
135                 case ef_atexit:
136                         if (efp->funcs.atexit) {
137                                 (efp->funcs.atexit) ();
138                         }
139                         break;
140                 }
141         }
142         if (__stdio_close_all)
143           __stdio_close_all();
144 }
145 #endif
146
147 #ifdef L_exit
148 extern void (*__uClibc_cleanup) (void);
149 void (*__exit_cleanup) (int) = 0;
150
151 /*
152  * Normal program termination
153  */
154 void exit(int rv)
155 {
156         /* Perform exit-specific cleanup (atexit and on_exit) */
157         if (__exit_cleanup) {
158                 __exit_cleanup(rv);
159         }
160
161         /* Clean up everything else */
162         if (__uClibc_cleanup) {
163             __uClibc_cleanup();
164
165         _exit(rv);
166 }
167 #endif