summaryrefslogtreecommitdiffstats
path: root/src/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/signal.c')
-rw-r--r--src/kernel/signal.c119
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
13void do_exit(int error_code);
14
15int sys_sgetmask()
16{
17 return current->blocked;
18}
19
20int sys_ssetmask(int newmask)
21{
22 int old=current->blocked;
23
24 current->blocked = newmask & ~(1<<(SIGKILL-1));
25 return old;
26}
27
28static 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
40static 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
48int 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
63int 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
82void 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}