1 /*
2  * $LynxId: LYexit.c,v 1.38 2020/02/25 10:14:48 tom Exp $
3  *
4  *	Copyright (c) 1994, University of Kansas, All Rights Reserved
5  *	(most of this file was rewritten in 1996 and 2004).
6  */
7 #include <HTUtils.h>
8 #include <LYexit.h>
9 #include <HTAlert.h>
10 #ifndef VMS
11 #include <LYGlobalDefs.h>
12 #include <LYUtils.h>
13 #include <LYSignal.h>
14 #include <LYMainLoop.h>
15 #endif /* !VMS */
16 #include <LYStrings.h>
17 #include <LYClean.h>
18 
19 /*
20  * Flag for outofmem macro.  - FM
21  */
22 BOOL LYOutOfMemory = FALSE;
23 
24 /*
25  * Stack of functions to call upon exit.
26  */
27 static void (*callstack[ATEXITSIZE]) (void);
28 static int topOfStack = 0;
29 
30 /*
31  * Capture "atexit()" calls for our own accounting.
32  */
LYatexit(void (* function)(void))33 int LYatexit(void (*function) (void))
34 {
35     int result = 0;
36 
37     if (topOfStack >= ATEXITSIZE) {
38 	CTRACE((tfp, "(LY)atexit: Too many functions, ignoring one!\n"));
39 	result = -1;
40     } else {
41 	int n;
42 	BOOLEAN found = FALSE;
43 
44 	for (n = 0; n < topOfStack; ++n) {
45 	    if (callstack[n] == function) {
46 		found = TRUE;
47 		break;
48 	    }
49 	}
50 	if (!found) {
51 	    callstack[topOfStack++] = function;
52 	}
53     }
54     return result;
55 }
56 
57 /*
58  * Purpose:		Call the functions registered with LYatexit
59  * Arguments:		void
60  * Return Value:	void
61  * Remarks/Portability/Dependencies/Restrictions:
62  * Revision History:
63  *	06-15-94	created Lynx 2-3-1 Garrett Arch Blythe
64  */
LYCompleteExit(void)65 static void LYCompleteExit(void)
66 {
67     /*
68      * Just loop through registered functions.  This is reentrant if more exits
69      * occur in the registered functions.
70      */
71     while (--topOfStack >= 0) {
72 	callstack[topOfStack] ();
73     }
74 }
75 
76 /*
77  * Purpose:		Terminates program, reports memory not freed.
78  * Arguments:		status	Exit code.
79  * Return Value:	void
80  * Remarks/Portability/Dependencies/Restrictions:
81  *	Function calls stdlib.h exit
82  * Revision History:
83  *	06-15-94	created Lynx 2-3-1 Garrett Arch Blythe
84  */
LYexit(int status)85 void LYexit(int status)
86 {
87 #ifndef VMS			/*  On VMS, the VMSexit() handler does these. - FM */
88 #ifdef _WINDOWS
89     DeleteCriticalSection(&critSec_READ);
90 
91     WSACleanup();
92 #endif
93     if (LYOutOfMemory == TRUE) {
94 	/*
95 	 * Ignore further interrupts.  - FM
96 	 */
97 #ifndef NOSIGHUP
98 	(void) signal(SIGHUP, SIG_IGN);
99 #endif /* NOSIGHUP */
100 	(void) signal(SIGTERM, SIG_IGN);
101 	(void) signal(SIGINT, SIG_IGN);
102 #ifndef __linux__
103 #ifdef SIGBUS
104 	(void) signal(SIGBUS, SIG_IGN);
105 #endif /* SIGBUS */
106 #endif /* !__linux__ */
107 	(void) signal(SIGSEGV, SIG_IGN);
108 	(void) signal(SIGILL, SIG_IGN);
109 
110 	/*
111 	 * Flush all messages.  - FM
112 	 */
113 	fflush(stderr);
114 	fflush(stdout);
115 
116 	/*
117 	 * Deal with curses, if on, and clean up.  - FM
118 	 */
119 	if (LYCursesON) {
120 	    LYSleepAlert();
121 	}
122 	cleanup_sig(0);
123 #ifndef __linux__
124 #ifdef SIGBUS
125 	signal(SIGBUS, SIG_DFL);
126 #endif /* SIGBUS */
127 #endif /* !__linux__ */
128 	signal(SIGSEGV, SIG_DFL);
129 	signal(SIGILL, SIG_DFL);
130     }
131 #endif /* !VMS */
132 
133     /*
134      * Close syslog before doing atexit-cleanup, since it may use a string
135      * that would be freed there.
136      */
137 #ifdef SYSLOG_REQUESTED_URLS
138     LYCloselog();
139 #endif
140 
141     /*
142      * Do functions registered with LYatexit.  - GAB
143      */
144     LYCompleteExit();
145 
146     LYCloseCmdLogfile();
147 
148 #ifdef exit
149 /*  Make sure we use stdlib exit and not LYexit. - GAB
150 */
151 #undef exit
152 #endif /* exit */
153 
154     cleanup_files();		/* if someone starts with LYNXfoo: page */
155 #ifndef VMS			/*  On VMS, the VMSexit() handler does these. - FM */
156     fflush(stderr);
157     if (LYOutOfMemory == TRUE) {
158 	LYOutOfMemory = FALSE;
159 	printf("\r\n%s\r\n\r\n", MEMORY_EXHAUSTED_ABORT);
160 	fflush(stdout);
161     }
162     LYCloseTracelog();
163 #endif /* !VMS */
164     show_alloc();
165 
166 #if defined(NCURSES_VERSION) && defined(LY_FIND_LEAKS)
167 #if defined(HAVE_CURSES_EXIT)
168     curses_exit(status);
169 #elif defined(HAVE__NC_FREE_AND_EXIT)
170     _nc_free_and_exit(status);
171 #elif defined(HAVE__NC_FREEALL)
172     _nc_freeall();
173 #endif
174 #endif /* NCURSES_VERSION */
175 
176     exit(status);
177 }
178 
outofmem(const char * fname,const char * func)179 void outofmem(const char *fname,
180 	      const char *func)
181 {
182     fprintf(stderr, "\n\n\n%s %s: %s\n", fname, func, MEMORY_EXHAUSTED_ABORTING);
183     LYOutOfMemory = TRUE;
184     LYexit(-1);
185 }
186