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