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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1988 AT&T 24 * All Rights Reserved 25 * 26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 /* 32 * Utility functions 33 */ 34 #include <unistd.h> 35 #include <signal.h> 36 #include <locale.h> 37 #include <string.h> 38 #include "msg.h" 39 #include "_libld.h" 40 41 /* 42 * Exit after cleaning up. 43 */ 44 int 45 ld_exit(Ofl_desc *ofl) 46 { 47 /* 48 * If we have created an output file remove it. 49 */ 50 if ((ofl->ofl_fd > 0) && ((ofl->ofl_flags1 & FLG_OF1_NONREG) == 0)) 51 (void) unlink(ofl->ofl_name); 52 53 /* 54 * Inform any support library that the link-edit has failed. 55 */ 56 ld_sup_atexit(ofl, 1); 57 return (1); 58 } 59 60 /* 61 * Establish the signals we're interested in, and the handlers that need to be 62 * reinstalled should any of these signals occur. 63 */ 64 typedef struct { 65 int signo; 66 void (* defhdl)(); 67 } Signals; 68 69 static Signals signals[] = { 70 { SIGHUP, SIG_DFL }, 71 { SIGINT, SIG_IGN }, 72 { SIGQUIT, SIG_DFL }, 73 { SIGBUS, SIG_DFL }, 74 { SIGTERM, SIG_IGN }, 75 { 0, 0 } }; 76 77 static Ofl_desc *Ofl = 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(Ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_FIL_INTERRUPT), 113 Ofl->ofl_name, 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(ld_exit(Ofl)); 122 } 123 124 /* 125 * Establish a signal handler for all signals we're interested in. 126 */ 127 void 128 ld_init(Ofl_desc *ofl) 129 { 130 struct sigaction nact, oact; 131 Signals * sigs; 132 133 Ofl = ofl; 134 135 /* 136 * For each signal we're interested in set up a signal handler that 137 * insures we clean up any output file we're in the middle of creating. 138 */ 139 nact.sa_sigaction = handler; 140 (void) sigemptyset(&nact.sa_mask); 141 142 for (sigs = signals; sigs->signo; sigs++) { 143 if ((sigaction(sigs->signo, NULL, &oact) == 0) && 144 (oact.sa_handler != SIG_IGN)) { 145 nact.sa_flags = SA_SIGINFO; 146 if (sigs->defhdl == SIG_DFL) 147 nact.sa_flags |= (SA_RESETHAND | SA_NODEFER); 148 (void) sigaction(sigs->signo, &nact, NULL); 149 } 150 } 151 } 152