|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char *sccsid = "@(#)sigretro.c 5.2 (Berkeley) 6/21/85";
9: #endif not lint
10:
11: #include <signal.h>
12: #include <errno.h>
13: #include <setjmp.h>
14: #include "sigretro.h"
15:
16: /*
17: * Retrofit new signal interface to old signal primitives.
18: * Supported routines:
19: * sigsys(sig, func)
20: * sigset(sig, func)
21: * sighold(sig)
22: * sigrelse(sig)
23: * sigignore(sig)
24: * sigpause(sig)
25: * Also,
26: * sigchild()
27: * to set all held signals to ignored signals in the
28: * child process after fork(2)
29: */
30:
31: typedef int (*sigtype)();
32:
33: sigtype sigdisp(), sighold(), sigignore();
34:
35: /*
36: * The following helps us keep the extended signal semantics together.
37: * We remember for each signal the address of the function we're
38: * supposed to call. s_func is SIG_DFL / SIG_IGN if appropriate.
39: */
40: struct sigtable {
41: sigtype s_func; /* What to call */
42: int s_flag; /* Signal flags; see below */
43: } sigtable[NSIG + 1];
44:
45: /*
46: * Signal flag values.
47: */
48: #define SHELD 1 /* Signal is being held */
49: #define SDEFER 2 /* Signal occured while held */
50: #define SSET 4 /* s_func is believable */
51: #define SPAUSE 8 /* are pausing, waiting for sig */
52:
53: jmp_buf _pause; /* For doing sigpause() */
54:
55: /*
56: * Approximate sigsys() system call
57: * This is almost useless since one only calls sigsys()
58: * in the child of a vfork(). If you have vfork(), you have new signals
59: * anyway. The real sigsys() does all the stuff needed to support
60: * the real sigset() library. We don't bother here, assuming that
61: * you are either ignoring or defaulting a signal in the child.
62: */
63: sigtype
64: sigsys(sig, func)
65: sigtype func;
66: {
67: sigtype old;
68:
69: old = sigdisp(sig);
70: signal(sig, func);
71: return(old);
72: }
73:
74: /*
75: * Set the (permanent) disposition of a signal.
76: * If the signal is subsequently (or even now) held,
77: * the action you set here can be enabled using sigrelse().
78: */
79: sigtype
80: sigset(sig, func)
81: sigtype func;
82: {
83: sigtype old;
84: int _sigtramp();
85: extern int errno;
86:
87: if (sig < 1 || sig > NSIG) {
88: errno = EINVAL;
89: return(BADSIG);
90: }
91: old = sigdisp(sig);
92: /*
93: * Does anyone actually call sigset with SIG_HOLD!?
94: */
95: if (func == SIG_HOLD) {
96: sighold(sig);
97: return(old);
98: }
99: sigtable[sig].s_flag |= SSET;
100: sigtable[sig].s_func = func;
101: if (func == SIG_DFL) {
102: /*
103: * If signal has been held, must retain
104: * the catch so that we can note occurrance
105: * of signal.
106: */
107: if ((sigtable[sig].s_flag & SHELD) == 0)
108: signal(sig, SIG_DFL);
109: else
110: signal(sig, _sigtramp);
111: return(old);
112: }
113: if (func == SIG_IGN) {
114: /*
115: * Clear pending signal
116: */
117: signal(sig, SIG_IGN);
118: sigtable[sig].s_flag &= ~SDEFER;
119: return(old);
120: }
121: signal(sig, _sigtramp);
122: return(old);
123: }
124:
125: /*
126: * Hold a signal.
127: * This CAN be tricky if the signal's disposition is SIG_DFL.
128: * In that case, we still catch the signal so we can note it
129: * happened and do something crazy later.
130: */
131: sigtype
132: sighold(sig)
133: {
134: sigtype old;
135: extern int errno;
136:
137: if (sig < 1 || sig > NSIG) {
138: errno = EINVAL;
139: return(BADSIG);
140: }
141: old = sigdisp(sig);
142: if (sigtable[sig].s_flag & SHELD)
143: return(old);
144: /*
145: * When the default action is required, we have to
146: * set up to catch the signal to note signal's occurrance.
147: */
148: if (old == SIG_DFL) {
149: sigtable[sig].s_flag |= SSET;
150: signal(sig, _sigtramp);
151: }
152: sigtable[sig].s_flag |= SHELD;
153: return(old);
154: }
155:
156: /*
157: * Release a signal
158: * If the signal occurred while we had it held, cause the signal.
159: */
160: sigtype
161: sigrelse(sig)
162: {
163: sigtype old;
164: extern int errno;
165: int _sigtramp();
166:
167: if (sig < 1 || sig > NSIG) {
168: errno = EINVAL;
169: return(BADSIG);
170: }
171: old = sigdisp(sig);
172: if ((sigtable[sig].s_flag & SHELD) == 0)
173: return(old);
174: sigtable[sig].s_flag &= ~SHELD;
175: if (sigtable[sig].s_flag & SDEFER)
176: _sigtramp(sig);
177: /*
178: * If disposition was the default, then we can unset the
179: * catch to _sigtramp() and let the system do the work.
180: */
181: if (sigtable[sig].s_func == SIG_DFL)
182: signal(sig, SIG_DFL);
183: return(old);
184: }
185:
186: /*
187: * Ignore a signal.
188: */
189: sigtype
190: sigignore(sig)
191: {
192:
193: return(sigset(sig, SIG_IGN));
194: }
195:
196: /*
197: * Pause, waiting for sig to occur.
198: * We assume LUSER called us with the signal held.
199: * When we got the signal, mark the signal as having
200: * occurred. It will actually cause something when
201: * the signal is released.
202: *
203: * This is probably useless without job control anyway.
204: */
205: sigpause(sig)
206: {
207: extern int errno;
208:
209: if (sig < 1 || sig > NSIG) {
210: errno = EINVAL;
211: return;
212: }
213: sigtable[sig].s_flag |= SHELD|SPAUSE;
214: if (setjmp(_pause) == 0)
215: pause();
216: sigtable[sig].s_flag &= ~SPAUSE;
217: sigtable[sig].s_flag |= SDEFER;
218: }
219:
220: /*
221: * In the child process after fork(2), set the disposition of all held
222: * signals to SIG_IGN. This is a new procedure not in the real sigset()
223: * package, provided for retrofitting purposes.
224: */
225: sigchild()
226: {
227: register int i;
228:
229: for (i = 1; i <= NSIG; i++)
230: if (sigtable[i].s_flag & SHELD)
231: signal(i, SIG_IGN);
232: }
233:
234: /*
235: * Return the current disposition of a signal
236: * If we have not set this signal before, we have to
237: * ask the system
238: */
239: sigtype
240: sigdisp(sig)
241: {
242: extern int errno;
243: sigtype old;
244:
245: if (sig < 1 || sig > NSIG) {
246: errno = EINVAL;
247: return(BADSIG);
248: }
249: /*
250: * If we have no knowledge of this signal,
251: * ask the system, then save the result for later.
252: */
253: if ((sigtable[sig].s_flag & SSET) == 0) {
254: old = signal(sig, SIG_IGN);
255: sigtable[sig].s_func = old;
256: sigtable[sig].s_flag |= SSET;
257: signal(sig, old);
258: return(old);
259: }
260: /*
261: * If we have set this signal before, then sigset()
262: * will have been careful to leave something meaningful
263: * in s_func.
264: */
265: return(sigtable[sig].s_func);
266: }
267:
268: /*
269: * The following routine gets called for any signal
270: * that is to be trapped to a user function.
271: */
272: _sigtramp(sig)
273: {
274: extern int errno;
275: sigtype old;
276:
277: if (sig < 1 || sig > NSIG) {
278: errno = EINVAL;
279: return;
280: }
281:
282: top:
283: old = signal(sig, SIG_IGN);
284: /*
285: * If signal being paused on, wakeup sigpause()
286: */
287: if (sigtable[sig].s_flag & SPAUSE)
288: longjmp(_pause, 1);
289: /*
290: * If signal being held, mark its table entry
291: * so we can trigger it when signal released.
292: * Then just return.
293: */
294: if (sigtable[sig].s_flag & SHELD) {
295: sigtable[sig].s_flag |= SDEFER;
296: signal(sig, _sigtramp);
297: return;
298: }
299: /*
300: * If the signal is being ignored, just return.
301: * This would make SIGCONT more normal, but of course
302: * any system with SIGCONT also has the new signal pkg, so...
303: */
304: if (sigtable[sig].s_func == SIG_IGN)
305: return;
306: /*
307: * If the signal is SIG_DFL, then we probably got here
308: * by holding the signal, having it happen, then releasing
309: * the signal. I wonder if a process is allowed to send
310: * a signal to itself?
311: */
312: if (sigtable[sig].s_func == SIG_DFL) {
313: signal(sig, SIG_DFL);
314: kill(getpid(), sig);
315: /* Will we get back here? */
316: return;
317: }
318: /*
319: * Looks like we should just cause the signal...
320: * We hold the signal for the duration of the user's
321: * code with the signal re-enabled. If the signal
322: * happens again while in user code, we will recursively
323: * trap here and mark that we had another occurance
324: * and return to the user's trap code. When we return
325: * from there, we can cause the signal again.
326: */
327: sigtable[sig].s_flag &= ~SDEFER;
328: sigtable[sig].s_flag |= SHELD;
329: signal(sig, _sigtramp);
330: (*sigtable[sig].s_func)(sig);
331: /*
332: * If the signal re-occurred while in the user's routine,
333: * just go try it again...
334: */
335: sigtable[sig].s_flag &= ~SHELD;
336: if (sigtable[sig].s_flag & SDEFER)
337: goto top;
338: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.