xref: /titanic_44/usr/src/cmd/sgs/libld/common/exit.c (revision c28749e97052f09388969427adf7df641cdcdc22)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  *	Copyright (c) 1988 AT&T
24  *	  All Rights Reserved
25  *
26  *
27  *	Copyright 1999-2003 Sun Microsystems, Inc.  All rights reserved.
28  *	Use is subject to license terms.
29  */
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 /*
33  * Utility functions
34  */
35 #include	<unistd.h>
36 #include	<signal.h>
37 #include	<locale.h>
38 #include	<errno.h>
39 #include	<string.h>
40 #include	"msg.h"
41 #include	"_libld.h"
42 
43 /*
44  * Exit after cleaning up.
45  */
46 int
47 ldexit()
48 {
49 	/*
50 	 * If we have created an output file remove it.
51 	 */
52 	if ((Ofl.ofl_fd > 0) && ((Ofl.ofl_flags1 & FLG_OF1_NONREG) == 0))
53 		(void) unlink(Ofl.ofl_name);
54 
55 	/*
56 	 * Inform any support library that the link-edit has failed.
57 	 */
58 	lds_atexit(1);
59 
60 	return (1);
61 }
62 
63 /*
64  * Establish the signals we're interested in, and the handlers that need to be
65  * reinstalled should any of these signals occur.
66  */
67 typedef struct {
68 	int	signo;
69 	void (*	defhdl)();
70 } Signals;
71 
72 Signals signals[] = {	{ SIGHUP,	SIG_DFL },
73 			{ SIGINT,	SIG_IGN },
74 			{ SIGQUIT,	SIG_DFL },
75 			{ SIGBUS,	SIG_DFL },
76 			{ SIGTERM,	SIG_IGN },
77 			{ 0,		0 } };
78 
79 /*
80  * Define our signal handler.
81  */
82 static void
83 /* ARGSUSED2 */
84 handler(int sig, siginfo_t *sip, void *utp)
85 {
86 	struct sigaction	nact;
87 	Signals *		sigs;
88 
89 	/*
90 	 * Reset all ignore handlers regardless of how we got here.
91 	 */
92 	nact.sa_handler = SIG_IGN;
93 	nact.sa_flags = 0;
94 	(void) sigemptyset(&nact.sa_mask);
95 
96 	for (sigs = signals; sigs->signo; sigs++) {
97 		if (sigs->defhdl == SIG_IGN)
98 			(void) sigaction(sigs->signo, &nact, NULL);
99 	}
100 
101 	/*
102 	 * The model for creating an output file is to ftruncate() it to the
103 	 * required size and mmap() a mapping into which the new contents are
104 	 * written.  Neither of these operations guarantee that the required
105 	 * disk blocks exist, and should we run out of disk space a bus error
106 	 * is generated.
107 	 * Other situations have been reported to result in ld catching a bus
108 	 * error (one instance was a stale NFS handle from an unstable server).
109 	 * Thus we catch all bus errors and hope we can decode a better error.
110 	 */
111 	if ((sig == SIGBUS) && sip && Ofl.ofl_name) {
112 		eprintf(ERR_FATAL, MSG_INTL(MSG_FIL_INTERRUPT), Ofl.ofl_name,
113 		    strerror(sip->si_errno));
114 	}
115 	/*
116 	 * This assert(0) causes DEBUG enabled linkers to produce a core file.
117 	 */
118 	if ((sig != SIGHUP) && (sig != SIGINT))
119 		assert(0);
120 
121 	exit(ldexit());
122 }
123 
124 
125 /*
126  * Establish a signal handler for all signals we're interested in.
127  */
128 void
129 init()
130 {
131 	struct sigaction	nact, oact;
132 	Signals *		sigs;
133 
134 	/*
135 	 * For each signal we're interested in set up a signal handler that
136 	 * insures we clean up any output file we're in the middle of creating.
137 	 */
138 	nact.sa_sigaction = handler;
139 	(void) sigemptyset(&nact.sa_mask);
140 
141 	for (sigs = signals; sigs->signo; sigs++) {
142 		if ((sigaction(sigs->signo, NULL, &oact) == 0) &&
143 		    (oact.sa_handler != SIG_IGN)) {
144 			nact.sa_flags = SA_SIGINFO;
145 			if (sigs->defhdl == SIG_DFL)
146 				nact.sa_flags |= (SA_RESETHAND | SA_NODEFER);
147 			(void) sigaction(sigs->signo, &nact, NULL);
148 		}
149 	}
150 }
151