diff options
Diffstat (limited to 'src/kernel/exit.c')
-rw-r--r-- | src/kernel/exit.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/kernel/exit.c b/src/kernel/exit.c new file mode 100644 index 0000000..b22de34 --- /dev/null +++ b/src/kernel/exit.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * linux/kernel/exit.c | ||
3 | * | ||
4 | * (C) 1991 Linus Torvalds | ||
5 | */ | ||
6 | |||
7 | #include <errno.h> | ||
8 | #include <signal.h> | ||
9 | #include <sys/wait.h> | ||
10 | |||
11 | #include <linux/sched.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/tty.h> | ||
14 | #include <asm/segment.h> | ||
15 | |||
16 | int sys_pause(void); | ||
17 | int sys_close(int fd); | ||
18 | |||
19 | void release(struct task_struct * p) | ||
20 | { | ||
21 | int i; | ||
22 | |||
23 | if (!p) | ||
24 | return; | ||
25 | for (i=1 ; i<NR_TASKS ; i++) | ||
26 | if (task[i]==p) { | ||
27 | task[i]=NULL; | ||
28 | free_page((long)p); | ||
29 | schedule(); | ||
30 | return; | ||
31 | } | ||
32 | panic("trying to release non-existent task"); | ||
33 | } | ||
34 | |||
35 | static inline int send_sig(long sig,struct task_struct * p,int priv) | ||
36 | { | ||
37 | if (!p || sig<1 || sig>32) | ||
38 | return -EINVAL; | ||
39 | if (priv || (current->euid==p->euid) || suser()) | ||
40 | p->signal |= (1<<(sig-1)); | ||
41 | else | ||
42 | return -EPERM; | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | static void kill_session(void) | ||
47 | { | ||
48 | struct task_struct **p = NR_TASKS + task; | ||
49 | |||
50 | while (--p > &FIRST_TASK) { | ||
51 | if (*p && (*p)->session == current->session) | ||
52 | (*p)->signal |= 1<<(SIGHUP-1); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * XXX need to check permissions needed to send signals to process | ||
58 | * groups, etc. etc. kill() permissions semantics are tricky! | ||
59 | */ | ||
60 | int sys_kill(int pid,int sig) | ||
61 | { | ||
62 | struct task_struct **p = NR_TASKS + task; | ||
63 | int err, retval = 0; | ||
64 | |||
65 | if (!pid) while (--p > &FIRST_TASK) { | ||
66 | if (*p && (*p)->pgrp == current->pid) | ||
67 | if ((err=send_sig(sig,*p,1))) | ||
68 | retval = err; | ||
69 | } else if (pid>0) while (--p > &FIRST_TASK) { | ||
70 | if (*p && (*p)->pid == pid) | ||
71 | if ((err=send_sig(sig,*p,0))) | ||
72 | retval = err; | ||
73 | } else if (pid == -1) while (--p > &FIRST_TASK) { | ||
74 | if ((err = send_sig(sig,*p,0))) | ||
75 | retval = err; | ||
76 | } else while (--p > &FIRST_TASK) | ||
77 | if (*p && (*p)->pgrp == -pid) | ||
78 | if ((err = send_sig(sig,*p,0))) | ||
79 | retval = err; | ||
80 | return retval; | ||
81 | } | ||
82 | |||
83 | static void tell_father(int pid) | ||
84 | { | ||
85 | int i; | ||
86 | |||
87 | if (pid) | ||
88 | for (i=0;i<NR_TASKS;i++) { | ||
89 | if (!task[i]) | ||
90 | continue; | ||
91 | if (task[i]->pid != pid) | ||
92 | continue; | ||
93 | task[i]->signal |= (1<<(SIGCHLD-1)); | ||
94 | return; | ||
95 | } | ||
96 | /* if we don't find any fathers, we just release ourselves */ | ||
97 | /* This is not really OK. Must change it to make father 1 */ | ||
98 | printk("BAD BAD - no father found\n\r"); | ||
99 | release(current); | ||
100 | } | ||
101 | |||
102 | int do_exit(long code) | ||
103 | { | ||
104 | int i; | ||
105 | free_page_tables(get_base(current->ldt[1]),get_limit(0x0f)); | ||
106 | free_page_tables(get_base(current->ldt[2]),get_limit(0x17)); | ||
107 | for (i=0 ; i<NR_TASKS ; i++) | ||
108 | if (task[i] && task[i]->father == current->pid) { | ||
109 | task[i]->father = 1; | ||
110 | if (task[i]->state == TASK_ZOMBIE) | ||
111 | /* assumption task[1] is always init */ | ||
112 | (void) send_sig(SIGCHLD, task[1], 1); | ||
113 | } | ||
114 | for (i=0 ; i<NR_OPEN ; i++) | ||
115 | if (current->filp[i]) | ||
116 | sys_close(i); | ||
117 | iput(current->pwd); | ||
118 | current->pwd=NULL; | ||
119 | iput(current->root); | ||
120 | current->root=NULL; | ||
121 | iput(current->executable); | ||
122 | current->executable=NULL; | ||
123 | if (current->leader && current->tty >= 0) | ||
124 | tty_table[current->tty].pgrp = 0; | ||
125 | if (last_task_used_math == current) | ||
126 | last_task_used_math = NULL; | ||
127 | if (current->leader) | ||
128 | kill_session(); | ||
129 | current->state = TASK_ZOMBIE; | ||
130 | current->exit_code = code; | ||
131 | tell_father(current->father); | ||
132 | schedule(); | ||
133 | return (-1); /* just to suppress warnings */ | ||
134 | } | ||
135 | |||
136 | int sys_exit(int error_code) | ||
137 | { | ||
138 | return do_exit((error_code&0xff)<<8); | ||
139 | } | ||
140 | |||
141 | int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options) | ||
142 | { | ||
143 | int flag, code; | ||
144 | struct task_struct ** p; | ||
145 | |||
146 | verify_area(stat_addr,4); | ||
147 | repeat: | ||
148 | flag=0; | ||
149 | for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) { | ||
150 | if (!*p || *p == current) | ||
151 | continue; | ||
152 | if ((*p)->father != current->pid) | ||
153 | continue; | ||
154 | if (pid>0) { | ||
155 | if ((*p)->pid != pid) | ||
156 | continue; | ||
157 | } else if (!pid) { | ||
158 | if ((*p)->pgrp != current->pgrp) | ||
159 | continue; | ||
160 | } else if (pid != -1) { | ||
161 | if ((*p)->pgrp != -pid) | ||
162 | continue; | ||
163 | } | ||
164 | switch ((*p)->state) { | ||
165 | case TASK_STOPPED: | ||
166 | if (!(options & WUNTRACED)) | ||
167 | continue; | ||
168 | put_fs_long(0x7f,stat_addr); | ||
169 | return (*p)->pid; | ||
170 | case TASK_ZOMBIE: | ||
171 | current->cutime += (*p)->utime; | ||
172 | current->cstime += (*p)->stime; | ||
173 | flag = (*p)->pid; | ||
174 | code = (*p)->exit_code; | ||
175 | release(*p); | ||
176 | put_fs_long(code,stat_addr); | ||
177 | return flag; | ||
178 | default: | ||
179 | flag=1; | ||
180 | continue; | ||
181 | } | ||
182 | } | ||
183 | if (flag) { | ||
184 | if (options & WNOHANG) | ||
185 | return 0; | ||
186 | current->state=TASK_INTERRUPTIBLE; | ||
187 | schedule(); | ||
188 | if (!(current->signal &= ~(1<<(SIGCHLD-1)))) | ||
189 | goto repeat; | ||
190 | else | ||
191 | return -EINTR; | ||
192 | } | ||
193 | return -ECHILD; | ||
194 | } | ||
195 | |||
196 | |||