Subversion Repositories HelenOS

Rev

Rev 2714 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2714 Rev 2927
1
/*  $NetBSD: trap.c,v 1.24 2000/05/22 10:18:47 elric Exp $  */
1
/*  $NetBSD: trap.c,v 1.24 2000/05/22 10:18:47 elric Exp $  */
2
 
2
 
3
/*-
3
/*-
4
 * Copyright (c) 1991, 1993
4
 * Copyright (c) 1991, 1993
5
 *  The Regents of the University of California.  All rights reserved.
5
 *  The Regents of the University of California.  All rights reserved.
6
 *
6
 *
7
 * This code is derived from software contributed to Berkeley by
7
 * This code is derived from software contributed to Berkeley by
8
 * Kenneth Almquist.
8
 * Kenneth Almquist.
9
 *
9
 *
10
 * Redistribution and use in source and binary forms, with or without
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
11
 * modification, are permitted provided that the following conditions
12
 * are met:
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
17
 *    documentation and/or other materials provided with the distribution.
18
 * 3. All advertising materials mentioning features or use of this software
18
 * 3. All advertising materials mentioning features or use of this software
19
 *    must display the following acknowledgement:
19
 *    must display the following acknowledgement:
20
 *  This product includes software developed by the University of
20
 *  This product includes software developed by the University of
21
 *  California, Berkeley and its contributors.
21
 *  California, Berkeley and its contributors.
22
 * 4. Neither the name of the University nor the names of its contributors
22
 * 4. Neither the name of the University nor the names of its contributors
23
 *    may be used to endorse or promote products derived from this software
23
 *    may be used to endorse or promote products derived from this software
24
 *    without specific prior written permission.
24
 *    without specific prior written permission.
25
 *
25
 *
26
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36
 * SUCH DAMAGE.
36
 * SUCH DAMAGE.
37
 */
37
 */
38
 
38
 
39
#include <sys/cdefs.h>
39
#include <sys/cdefs.h>
40
#ifndef lint
40
#ifndef lint
41
#if 0
41
#if 0
42
static char sccsid[] = "@(#)trap.c  8.5 (Berkeley) 6/5/95";
42
static char sccsid[] = "@(#)trap.c  8.5 (Berkeley) 6/5/95";
43
#else
43
#else
44
__RCSID("$NetBSD: trap.c,v 1.24 2000/05/22 10:18:47 elric Exp $");
44
__RCSID("$NetBSD: trap.c,v 1.24 2000/05/22 10:18:47 elric Exp $");
45
#endif
45
#endif
46
#endif /* not lint */
46
#endif /* not lint */
47
 
47
 
48
#include <signal.h>
48
#include <signal.h>
49
#include <unistd.h>
49
#include <unistd.h>
50
#include <stdlib.h>
50
#include <stdlib.h>
51
 
51
 
52
#include "shell.h"
52
#include "shell.h"
53
#include "main.h"
53
#include "main.h"
54
#include "nodes.h"  /* for other headers */
54
#include "nodes.h"  /* for other headers */
55
#include "eval.h"
55
#include "eval.h"
56
#include "jobs.h"
56
#include "jobs.h"
57
#include "show.h"
57
#include "show.h"
58
#include "options.h"
58
#include "options.h"
59
#include "syntax.h"
59
#include "syntax.h"
60
#include "output.h"
60
#include "output.h"
61
#include "memalloc.h"
61
#include "memalloc.h"
62
#include "error.h"
62
#include "error.h"
63
#include "trap.h"
63
#include "trap.h"
64
#include "mystring.h"
64
#include "mystring.h"
65
#include "mail.h"
65
#include "mail.h"
66
 
66
 
67
#ifdef HETIO
67
#ifdef HETIO
68
#include "hetio.h"
68
#include "hetio.h"
69
#endif
69
#endif
70
 
70
 
71
/*
71
/*
72
 * Sigmode records the current value of the signal handlers for the various
72
 * Sigmode records the current value of the signal handlers for the various
73
 * modes.  A value of zero means that the current handler is not known.
73
 * modes.  A value of zero means that the current handler is not known.
74
 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
74
 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
75
 */
75
 */
76
 
76
 
77
#define S_DFL 1         /* default signal handling (SIG_DFL) */
77
#define S_DFL 1         /* default signal handling (SIG_DFL) */
78
#define S_CATCH 2       /* signal is caught */
78
#define S_CATCH 2       /* signal is caught */
79
#define S_IGN 3         /* signal is ignored (SIG_IGN) */
79
#define S_IGN 3         /* signal is ignored (SIG_IGN) */
80
#define S_HARD_IGN 4        /* signal is ignored permenantly */
80
#define S_HARD_IGN 4        /* signal is ignored permenantly */
81
#define S_RESET 5       /* temporary - to reset a hard ignored sig */
81
#define S_RESET 5       /* temporary - to reset a hard ignored sig */
82
 
82
 
83
 
83
 
84
extern char nullstr[1];     /* null string */
84
extern char nullstr[1];     /* null string */
85
 
85
 
86
char *trap[NSIG+1];     /* trap handler commands */
86
char *trap[NSIG+1];     /* trap handler commands */
87
MKINIT char sigmode[NSIG];  /* current value of signal */
87
MKINIT char sigmode[NSIG];  /* current value of signal */
88
char gotsig[NSIG];      /* indicates specified signal received */
88
char gotsig[NSIG];      /* indicates specified signal received */
89
int pendingsigs;            /* indicates some signal received */
89
int pendingsigs;            /* indicates some signal received */
90
 
90
 
91
extern char *signal_names[];
91
extern char *signal_names[];
92
 
92
 
93
/*
93
/*
94
 * The trap builtin.
94
 * The trap builtin.
95
 */
95
 */
96
 
96
 
97
int
97
int
98
trapcmd(argc, argv)
98
trapcmd(argc, argv)
99
    int argc;
99
    int argc;
100
    char **argv;
100
    char **argv;
101
{
101
{
102
    char *action;
102
    char *action;
103
    char **ap;
103
    char **ap;
104
    int signo;
104
    int signo;
105
 
105
 
106
    if (argc <= 1) {
106
    if (argc <= 1) {
107
        for (signo = 0 ; signo <= NSIG ; signo++) {
107
        for (signo = 0 ; signo <= NSIG ; signo++) {
108
            if (trap[signo] != NULL)
108
            if (trap[signo] != NULL)
109
                out1fmt("%d: %s\n", signo, trap[signo]);
109
                out1fmt("%d: %s\n", signo, trap[signo]);
110
        }
110
        }
111
        return 0;
111
        return 0;
112
    }
112
    }
113
    ap = argv + 1;
113
    ap = argv + 1;
114
    if (argc == 2)
114
    if (argc == 2)
115
        action = NULL;
115
        action = NULL;
116
    else
116
    else
117
        action = *ap++;
117
        action = *ap++;
118
    while (*ap) {
118
    while (*ap) {
119
        if ((signo = decode_signal(*ap)) < 0)
119
        if ((signo = decode_signal(*ap)) < 0)
120
            error("%s: bad trap", *ap);
120
            error("%s: bad trap", *ap);
121
        INTOFF;
121
        INTOFF;
122
        if (action) {
122
        if (action) {
123
            if (action[0] == '-' && action[1] == '\0')
123
            if (action[0] == '-' && action[1] == '\0')
124
                action = NULL;
124
                action = NULL;
125
            else
125
            else
126
                action = savestr(action);
126
                action = savestr(action);
127
        }
127
        }
128
        if (trap[signo])
128
        if (trap[signo])
129
            ckfree(trap[signo]);
129
            ckfree(trap[signo]);
130
        trap[signo] = action;
130
        trap[signo] = action;
131
        if (signo != 0)
131
        if (signo != 0)
132
            setsignal(signo);
132
            setsignal(signo);
133
        INTON;
133
        INTON;
134
        ap++;
134
        ap++;
135
    }
135
    }
136
    return 0;
136
    return 0;
137
}
137
}
138
 
138
 
139
 
139
 
140
 
140
 
141
/*
141
/*
142
 * Clear traps on a fork.
142
 * Clear traps on a fork.
143
 */
143
 */
144
 
144
 
145
void
145
void
146
clear_traps() {
146
clear_traps() {
147
    char **tp;
147
    char **tp;
148
 
148
 
149
    for (tp = trap ; tp <= &trap[NSIG] ; tp++) {
149
    for (tp = trap ; tp <= &trap[NSIG] ; tp++) {
150
        if (*tp && **tp) {  /* trap not NULL or SIG_IGN */
150
        if (*tp && **tp) {  /* trap not NULL or SIG_IGN */
151
            INTOFF;
151
            INTOFF;
152
            ckfree(*tp);
152
            ckfree(*tp);
153
            *tp = NULL;
153
            *tp = NULL;
154
            if (tp != &trap[0])
154
            if (tp != &trap[0])
155
                setsignal(tp - trap);
155
                setsignal(tp - trap);
156
            INTON;
156
            INTON;
157
        }
157
        }
158
    }
158
    }
159
}
159
}
160
 
160
 
161
 
161
 
162
 
162
 
163
/*
163
/*
164
 * Set the signal handler for the specified signal.  The routine figures
164
 * Set the signal handler for the specified signal.  The routine figures
165
 * out what it should be set to.
165
 * out what it should be set to.
166
 */
166
 */
167
 
167
 
168
void
168
void
169
setsignal(signo)
169
setsignal(signo)
170
    int signo;
170
    int signo;
171
{
171
{
172
    int action;
172
    int action;
173
    char *t;
173
    char *t;
174
    struct sigaction act;
174
    struct sigaction act;
175
 
175
 
176
    if ((t = trap[signo]) == NULL)
176
    if ((t = trap[signo]) == NULL)
177
        action = S_DFL;
177
        action = S_DFL;
178
    else if (*t != '\0')
178
    else if (*t != '\0')
179
        action = S_CATCH;
179
        action = S_CATCH;
180
    else
180
    else
181
        action = S_IGN;
181
        action = S_IGN;
182
    if (rootshell && action == S_DFL) {
182
    if (rootshell && action == S_DFL) {
183
        switch (signo) {
183
        switch (signo) {
184
        case SIGINT:
184
        case SIGINT:
185
            if (iflag || minusc || sflag == 0)
185
            if (iflag || minusc || sflag == 0)
186
                action = S_CATCH;
186
                action = S_CATCH;
187
            break;
187
            break;
188
        case SIGQUIT:
188
        case SIGQUIT:
189
#ifdef DEBUG
189
#ifdef DEBUG
190
            {
190
            {
191
            extern int debug;
191
            extern int debug;
192
 
192
 
193
            if (debug)
193
            if (debug)
194
                break;
194
                break;
195
            }
195
            }
196
#endif
196
#endif
197
            /* FALLTHROUGH */
197
            /* FALLTHROUGH */
198
        case SIGTERM:
198
        case SIGTERM:
199
            if (iflag)
199
            if (iflag)
200
                action = S_IGN;
200
                action = S_IGN;
201
            break;
201
            break;
202
#if JOBS
202
#if JOBS
203
        case SIGTSTP:
203
        case SIGTSTP:
204
        case SIGTTOU:
204
        case SIGTTOU:
205
            if (mflag)
205
            if (mflag)
206
                action = S_IGN;
206
                action = S_IGN;
207
            break;
207
            break;
208
#endif
208
#endif
209
        }
209
        }
210
    }
210
    }
211
 
211
 
212
    t = &sigmode[signo - 1];
212
    t = &sigmode[signo - 1];
213
    if (*t == 0) {
213
    if (*t == 0) {
214
        /*
214
        /*
215
         * current setting unknown
215
         * current setting unknown
216
         */
216
         */
217
        if (sigaction(signo, 0, &act) == -1) {
217
        if (sigaction(signo, 0, &act) == -1) {
218
            /*
218
            /*
219
             * Pretend it worked; maybe we should give a warning
219
             * Pretend it worked; maybe we should give a warning
220
             * here, but other shells don't. We don't alter
220
             * here, but other shells don't. We don't alter
221
             * sigmode, so that we retry every time.
221
             * sigmode, so that we retry every time.
222
             */
222
             */
223
            return;
223
            return;
224
        }
224
        }
225
        if (act.sa_handler == SIG_IGN) {
225
        if (act.sa_handler == SIG_IGN) {
226
            if (mflag && (signo == SIGTSTP ||
226
            if (mflag && (signo == SIGTSTP ||
227
                 signo == SIGTTIN || signo == SIGTTOU)) {
227
                 signo == SIGTTIN || signo == SIGTTOU)) {
228
                *t = S_IGN; /* don't hard ignore these */
228
                *t = S_IGN; /* don't hard ignore these */
229
            } else
229
            } else
230
                *t = S_HARD_IGN;
230
                *t = S_HARD_IGN;
231
        } else {
231
        } else {
232
            *t = S_RESET;   /* force to be set */
232
            *t = S_RESET;   /* force to be set */
233
        }
233
        }
234
    }
234
    }
235
    if (*t == S_HARD_IGN || *t == action)
235
    if (*t == S_HARD_IGN || *t == action)
236
        return;
236
        return;
237
    switch (action) {
237
    switch (action) {
238
    case S_CATCH:
238
    case S_CATCH:
239
        act.sa_handler = onsig;
239
        act.sa_handler = onsig;
240
        break;
240
        break;
241
    case S_IGN:
241
    case S_IGN:
242
        act.sa_handler = SIG_IGN;
242
        act.sa_handler = SIG_IGN;
243
        break;
243
        break;
244
    default:
244
    default:
245
        act.sa_handler = SIG_DFL;
245
        act.sa_handler = SIG_DFL;
246
    }
246
    }
247
    *t = action;
247
    *t = action;
248
    act.sa_flags = 0;
248
    act.sa_flags = 0;
249
    sigemptyset(&act.sa_mask);
249
    sigemptyset(&act.sa_mask);
250
    sigaction(signo, &act, 0);
250
    sigaction(signo, &act, 0);
251
}
251
}
252
 
252
 
253
/*
253
/*
254
 * Ignore a signal.
254
 * Ignore a signal.
255
 */
255
 */
256
 
256
 
257
void
257
void
258
ignoresig(signo)
258
ignoresig(signo)
259
    int signo;
259
    int signo;
260
{
260
{
261
    if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
261
    if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
262
        signal(signo, SIG_IGN);
262
        signal(signo, SIG_IGN);
263
    }
263
    }
264
    sigmode[signo - 1] = S_HARD_IGN;
264
    sigmode[signo - 1] = S_HARD_IGN;
265
}
265
}
266
 
266
 
267
 
267
 
268
#ifdef mkinit
268
#ifdef mkinit
269
INCLUDE <signal.h>
269
INCLUDE <signal.h>
270
INCLUDE "trap.h"
270
INCLUDE "trap.h"
271
 
271
 
272
SHELLPROC {
272
SHELLPROC {
273
    char *sm;
273
    char *sm;
274
 
274
 
275
    clear_traps();
275
    clear_traps();
276
    for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
276
    for (sm = sigmode ; sm < sigmode + NSIG ; sm++) {
277
        if (*sm == S_IGN)
277
        if (*sm == S_IGN)
278
            *sm = S_HARD_IGN;
278
            *sm = S_HARD_IGN;
279
    }
279
    }
280
}
280
}
281
#endif
281
#endif
282
 
282
 
283
 
283
 
284
 
284
 
285
/*
285
/*
286
 * Signal handler.
286
 * Signal handler.
287
 */
287
 */
288
 
288
 
289
void
289
void
290
onsig(signo)
290
onsig(signo)
291
    int signo;
291
    int signo;
292
{
292
{
293
    signal(signo, onsig);
293
    signal(signo, onsig);
294
    if (signo == SIGINT && trap[SIGINT] == NULL) {
294
    if (signo == SIGINT && trap[SIGINT] == NULL) {
295
        onint();
295
        onint();
296
        return;
296
        return;
297
    }
297
    }
298
    gotsig[signo - 1] = 1;
298
    gotsig[signo - 1] = 1;
299
    pendingsigs++;
299
    pendingsigs++;
300
}
300
}
301
 
301
 
302
 
302
 
303
 
303
 
304
/*
304
/*
305
 * Called to execute a trap.  Perhaps we should avoid entering new trap
305
 * Called to execute a trap.  Perhaps we should avoid entering new trap
306
 * handlers while we are executing a trap handler.
306
 * handlers while we are executing a trap handler.
307
 */
307
 */
308
 
308
 
309
void
309
void
310
dotrap() {
310
dotrap() {
311
    int i;
311
    int i;
312
    int savestatus;
312
    int savestatus;
313
 
313
 
314
    for (;;) {
314
    for (;;) {
315
        for (i = 1 ; ; i++) {
315
        for (i = 1 ; ; i++) {
316
            if (gotsig[i - 1])
316
            if (gotsig[i - 1])
317
                break;
317
                break;
318
            if (i >= NSIG)
318
            if (i >= NSIG)
319
                goto done;
319
                goto done;
320
        }
320
        }
321
        gotsig[i - 1] = 0;
321
        gotsig[i - 1] = 0;
322
        savestatus=exitstatus;
322
        savestatus=exitstatus;
323
        evalstring(trap[i], 0);
323
        evalstring(trap[i], 0);
324
        exitstatus=savestatus;
324
        exitstatus=savestatus;
325
    }
325
    }
326
done:
326
done:
327
    pendingsigs = 0;
327
    pendingsigs = 0;
328
}
328
}
329
 
329
 
330
 
330
 
331
 
331
 
332
/*
332
/*
333
 * Controls whether the shell is interactive or not.
333
 * Controls whether the shell is interactive or not.
334
 */
334
 */
335
 
335
 
336
 
336
 
337
void
337
void
338
setinteractive(on)
338
setinteractive(on)
339
    int on;
339
    int on;
340
{
340
{
341
    static int is_interactive;
341
    static int is_interactive;
342
 
342
 
343
    if (on == is_interactive)
343
    if (on == is_interactive)
344
        return;
344
        return;
345
    setsignal(SIGINT);
345
    setsignal(SIGINT);
346
    setsignal(SIGQUIT);
346
    setsignal(SIGQUIT);
347
    setsignal(SIGTERM);
347
    setsignal(SIGTERM);
348
    chkmail(1);
348
    chkmail(1);
349
    is_interactive = on;
349
    is_interactive = on;
350
}
350
}
351
 
351
 
352
 
352
 
353
 
353
 
354
/*
354
/*
355
 * Called to exit the shell.
355
 * Called to exit the shell.
356
 */
356
 */
357
 
357
 
358
void
358
void
359
exitshell(status)
359
exitshell(status)
360
    int status;
360
    int status;
361
{
361
{
362
    struct jmploc loc1, loc2;
362
    struct jmploc loc1, loc2;
363
    char *p;
363
    char *p;
364
 
364
 
365
    TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
365
    TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
366
#ifdef HETIO
366
#ifdef HETIO
367
    hetio_reset_term();
367
    hetio_reset_term();
368
#endif
368
#endif
369
    if (setjmp(loc1.loc)) {
369
    if (setjmp(loc1.loc)) {
370
        goto l1;
370
        goto l1;
371
    }
371
    }
372
    if (setjmp(loc2.loc)) {
372
    if (setjmp(loc2.loc)) {
373
        goto l2;
373
        goto l2;
374
    }
374
    }
375
    handler = &loc1;
375
    handler = &loc1;
376
    if ((p = trap[0]) != NULL && *p != '\0') {
376
    if ((p = trap[0]) != NULL && *p != '\0') {
377
        trap[0] = NULL;
377
        trap[0] = NULL;
378
        evalstring(p, 0);
378
        evalstring(p, 0);
379
    }
379
    }
380
l1:   handler = &loc2;          /* probably unnecessary */
380
l1:   handler = &loc2;          /* probably unnecessary */
381
    flushall();
381
    flushall();
382
#if JOBS
382
#if JOBS
383
    setjobctl(0);
383
    setjobctl(0);
384
#endif
384
#endif
385
l2:   _exit(status);
385
l2:   _exit(status);
386
    /* NOTREACHED */
386
    /* NOTREACHED */
387
}
387
}
388
 
388
 
389
int decode_signal(const char *string)
389
int decode_signal(const char *string)
390
{
390
{
391
    int signo;
391
    int signo;
392
 
392
 
393
    if (is_number(string)) return atoi(string);
393
    if (is_number(string)) return atoi(string);
394
 
394
 
395
    for (signo=0; signo < NSIG; signo++)
395
    for (signo=0; signo < NSIG; signo++)
396
        if (strcasecmp(string, signal_names[signo]) == 0 ||
396
        if (strcasecmp(string, signal_names[signo]) == 0 ||
397
            strcasecmp(string, &(signal_names[signo])[3]) == 0)
397
            strcasecmp(string, &(signal_names[signo])[3]) == 0)
398
            return signo;
398
            return signo;
399
 
399
 
400
    return -1;
400
    return -1;
401
}
401
}
402
 
402