+++ /dev/null
-/* Generic atexit()
- Copyright (C) 1996 Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file. (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Rather than come up with some ugly hack to make mcrt1 work, it is
- better to just go ahead and provide atexit(). */
-
-
-#include <stdlib.h>
-
-
-void exit(int) __attribute__((noreturn));
-void _exit(int) __attribute__((noreturn));
-void _cleanup(void);
-
-
-#define FNS_PER_BLOCK 32
-
-struct atexit_fn_block
-{
- struct atexit_fn_block *next;
- void (*fns[FNS_PER_BLOCK])(void);
- short used;
-};
-
-
-/* statically allocate the first block */
-static struct atexit_fn_block atexit_fns;
-static struct atexit_fn_block *current_block = &atexit_fns;
-
-
-int atexit(void (*fn)(void))
-{
- if (current_block->used >= FNS_PER_BLOCK)
- {
- struct atexit_fn_block *new_block =
- (struct atexit_fn_block *)malloc(sizeof(struct atexit_fn_block));
- if (new_block == NULL)
- return -1;
-
- new_block->used = 0;
- new_block->next = current_block;
- current_block = new_block;
- }
-
- current_block->fns[current_block->used++] = fn;
-
- return 0;
-}
-
-
-void exit(int status)
-{
- struct atexit_fn_block *block = current_block, *old_block;
- short i;
-
- while (1)
- {
- for (i = block->used; --i >= 0 ;)
- (*block->fns[i])();
- if (block == &atexit_fns)
- break;
- /* I know what you are thinking -- we are about to exit, why free?
- Because it is friendly to memory leak detectors, that's why. */
- old_block = block;
- block = block->next;
- free(old_block);
- }
-
- _exit(status);
-}