diff options
Diffstat (limited to 'src/kernel/signal.c')
-rw-r--r-- | src/kernel/signal.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/kernel/signal.c b/src/kernel/signal.c new file mode 100644 index 0000000..c6afb3a --- /dev/null +++ b/src/kernel/signal.c | |||
@@ -0,0 +1,119 @@ | |||
1 | /* | ||
2 | * linux/kernel/signal.c | ||
3 | * | ||
4 | * (C) 1991 Linus Torvalds | ||
5 | */ | ||
6 | |||
7 | #include <linux/sched.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <asm/segment.h> | ||
10 | |||
11 | #include <signal.h> | ||
12 | |||
13 | void do_exit(int error_code); | ||
14 | |||
15 | int sys_sgetmask() | ||
16 | { | ||
17 | return current->blocked; | ||
18 | } | ||
19 | |||
20 | int sys_ssetmask(int newmask) | ||
21 | { | ||
22 | int old=current->blocked; | ||
23 | |||
24 | current->blocked = newmask & ~(1<<(SIGKILL-1)); | ||
25 | return old; | ||
26 | } | ||
27 | |||
28 | static inline void save_old(char * from,char * to) | ||
29 | { | ||
30 | int i; | ||
31 | |||
32 | verify_area(to, sizeof(struct sigaction)); | ||
33 | for (i=0 ; i< sizeof(struct sigaction) ; i++) { | ||
34 | put_fs_byte(*from,to); | ||
35 | from++; | ||
36 | to++; | ||
37 | } | ||
38 | } | ||
39 | |||
40 | static inline void get_new(char * from,char * to) | ||
41 | { | ||
42 | int i; | ||
43 | |||
44 | for (i=0 ; i< sizeof(struct sigaction) ; i++) | ||
45 | *(to++) = get_fs_byte(from++); | ||
46 | } | ||
47 | |||
48 | int sys_signal(int signum, long handler, long restorer) | ||
49 | { | ||
50 | struct sigaction tmp; | ||
51 | |||
52 | if (signum<1 || signum>32 || signum==SIGKILL) | ||
53 | return -1; | ||
54 | tmp.sa_handler = (void (*)(int)) handler; | ||
55 | tmp.sa_mask = 0; | ||
56 | tmp.sa_flags = SA_ONESHOT | SA_NOMASK; | ||
57 | tmp.sa_restorer = (void (*)(void)) restorer; | ||
58 | handler = (long) current->sigaction[signum-1].sa_handler; | ||
59 | current->sigaction[signum-1] = tmp; | ||
60 | return handler; | ||
61 | } | ||
62 | |||
63 | int sys_sigaction(int signum, const struct sigaction * action, | ||
64 | struct sigaction * oldaction) | ||
65 | { | ||
66 | struct sigaction tmp; | ||
67 | |||
68 | if (signum<1 || signum>32 || signum==SIGKILL) | ||
69 | return -1; | ||
70 | tmp = current->sigaction[signum-1]; | ||
71 | get_new((char *) action, | ||
72 | (char *) (signum-1+current->sigaction)); | ||
73 | if (oldaction) | ||
74 | save_old((char *) &tmp,(char *) oldaction); | ||
75 | if (current->sigaction[signum-1].sa_flags & SA_NOMASK) | ||
76 | current->sigaction[signum-1].sa_mask = 0; | ||
77 | else | ||
78 | current->sigaction[signum-1].sa_mask |= (1<<(signum-1)); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | void do_signal(long signr,long eax, long ebx, long ecx, long edx, | ||
83 | long fs, long es, long ds, | ||
84 | long eip, long cs, long eflags, | ||
85 | unsigned long * esp, long ss) | ||
86 | { | ||
87 | unsigned long sa_handler; | ||
88 | long old_eip=eip; | ||
89 | struct sigaction * sa = current->sigaction + signr - 1; | ||
90 | int longs; | ||
91 | unsigned long * tmp_esp; | ||
92 | |||
93 | sa_handler = (unsigned long) sa->sa_handler; | ||
94 | if (sa_handler==1) | ||
95 | return; | ||
96 | if (!sa_handler) { | ||
97 | if (signr==SIGCHLD) | ||
98 | return; | ||
99 | else | ||
100 | do_exit(1<<(signr-1)); | ||
101 | } | ||
102 | if (sa->sa_flags & SA_ONESHOT) | ||
103 | sa->sa_handler = NULL; | ||
104 | *(&eip) = sa_handler; | ||
105 | longs = (sa->sa_flags & SA_NOMASK)?7:8; | ||
106 | *(&esp) -= longs; | ||
107 | verify_area(esp,longs*4); | ||
108 | tmp_esp=esp; | ||
109 | put_fs_long((long) sa->sa_restorer,tmp_esp++); | ||
110 | put_fs_long(signr,tmp_esp++); | ||
111 | if (!(sa->sa_flags & SA_NOMASK)) | ||
112 | put_fs_long(current->blocked,tmp_esp++); | ||
113 | put_fs_long(eax,tmp_esp++); | ||
114 | put_fs_long(ecx,tmp_esp++); | ||
115 | put_fs_long(edx,tmp_esp++); | ||
116 | put_fs_long(eflags,tmp_esp++); | ||
117 | put_fs_long(old_eip,tmp_esp++); | ||
118 | current->blocked |= sa->sa_mask; | ||
119 | } | ||