Linux 0.10 (November 11, 1991 ???)
[davej-history.git] / kernel / RCS / exit.c,v
blobae8e8b150823cc984aaed5e11b18c169134d2146
1 head     1.3;
2 branch   ;
3 access   ;
4 symbols  ;
5 locks    ; strict;
6 comment  @ * @;
9 1.3
10 date     91.12.01.09.21.46;  author tytso;  state Exp;
11 branches ;
12 next     1.2;
14 1.2
15 date     91.11.20.00.10.00;  author tytso;  state Exp;
16 branches ;
17 next     1.1;
19 1.1
20 date     91.11.16.21.02.17;  author tytso;  state Exp;
21 branches ;
22 next     ;
25 desc
29 1.3
30 log
31 @Patches sent to Linus
33 text
34 @/*
35  *  linux/kernel/exit.c
36  *
37  *  (C) 1991  Linus Torvalds
38  */
40 #include <errno.h>
41 #include <signal.h>
42 #include <sys/wait.h>
44 #include <linux/sched.h>
45 #include <linux/kernel.h>
46 #include <linux/tty.h>
47 #include <asm/segment.h>
49 int sys_pause(void);
50 int sys_close(int fd);
52 void release(struct task_struct * p)
54         int i;
56         if (!p)
57                 return;
58         for (i=1 ; i<NR_TASKS ; i++)
59                 if (task[i]==p) {
60                         task[i]=NULL;
61                         free_page((long)p);
62                         schedule();
63                         return;
64                 }
65         panic("trying to release non-existent task");
68 static inline int send_sig(long sig,struct task_struct * p,int priv)
70         if (!p || sig<1 || sig>32)
71                 return -EINVAL;
72         if (priv || (current->euid==p->euid) || suser())
73                 p->signal |= (1<<(sig-1));
74         else
75                 return -EPERM;
76         return 0;
79 static void kill_session(void)
81         struct task_struct **p = NR_TASKS + task;
82         
83         while (--p > &FIRST_TASK) {
84                 if (*p && (*p)->session == current->session)
85                         (*p)->signal |= 1<<(SIGHUP-1);
86         }
90  * XXX need to check permissions needed to send signals to process
91  * groups, etc. etc.  kill() permissions semantics are tricky!
92  */
93 int sys_kill(int pid,int sig)
95         struct task_struct **p = NR_TASKS + task;
96         int err, retval = 0;
98         if (!pid) while (--p > &FIRST_TASK) {
99                 if (*p && (*p)->pgrp == current->pid) 
100                         if (err=send_sig(sig,*p,1))
101                                 retval = err;
102         } else if (pid>0) while (--p > &FIRST_TASK) {
103                 if (*p && (*p)->pid == pid) 
104                         if (err=send_sig(sig,*p,0))
105                                 retval = err;
106         } else if (pid == -1) while (--p > &FIRST_TASK)
107                 if (err = send_sig(sig,*p,0))
108                         retval = err;
109         else while (--p > &FIRST_TASK)
110                 if (*p && (*p)->pgrp == -pid)
111                         if (err = send_sig(sig,*p,0))
112                                 retval = err;
113         return retval;
116 static void tell_father(int pid)
118         int i;
120         if (pid)
121                 for (i=0;i<NR_TASKS;i++) {
122                         if (!task[i])
123                                 continue;
124                         if (task[i]->pid != pid)
125                                 continue;
126                         task[i]->signal |= (1<<(SIGCHLD-1));
127                         return;
128                 }
129 /* if we don't find any fathers, we just release ourselves */
130         release(current);
133 int do_exit(long code)
135         int i;
137         free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
138         free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
139         for (i=0 ; i<NR_TASKS ; i++)
140                 if (task[i] && task[i]->father == current->pid)
141                         task[i]->father = 0;
142         for (i=0 ; i<NR_OPEN ; i++)
143                 if (current->filp[i])
144                         sys_close(i);
145         iput(current->pwd);
146         current->pwd=NULL;
147         iput(current->root);
148         current->root=NULL;
149         if (current->leader && current->tty >= 0)
150                 tty_table[current->tty].pgrp = 0;
151         if (last_task_used_math == current)
152                 last_task_used_math = NULL;
153         if (current->leader)
154                 kill_session();
155         current->state = TASK_ZOMBIE;
156         current->exit_code = code;
157         tell_father(current->father);
158         schedule();
159         return (-1);    /* just to suppress warnings */
162 int sys_exit(int error_code)
164         return do_exit((error_code&0xff)<<8);
167 int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
169         int flag;
170         struct task_struct ** p;
172         verify_area(stat_addr,4);
173 repeat:
174         flag=0;
175         for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
176                 if (!*p || *p == current)
177                         continue;
178                 if ((*p)->father != current->pid)
179                         continue;
180                 if (pid>0) {
181                         if ((*p)->pid != pid)
182                                 continue;
183                 } else if (!pid) {
184                         if ((*p)->pgrp != current->pgrp)
185                                 continue;
186                 } else if (pid != -1) {
187                         if ((*p)->pgrp != -pid)
188                                 continue;
189                 }
190                 switch ((*p)->state) {
191                         case TASK_STOPPED:
192                                 if (!(options & WUNTRACED))
193                                         continue;
194                                 put_fs_long(0x7f,stat_addr);
195                                 return (*p)->pid;
196                         case TASK_ZOMBIE:
197                                 current->cutime += (*p)->utime;
198                                 current->cstime += (*p)->stime;
199                                 flag = (*p)->pid;
200                                 put_fs_long((*p)->exit_code,stat_addr);
201                                 release(*p);
202                                 return flag;
203                         default:
204                                 flag=1;
205                                 continue;
206                 }
207         }
208         if (flag) {
209                 if (options & WNOHANG)
210                         return 0;
211                 current->state=TASK_INTERRUPTIBLE;
212                 schedule();
213                 if (!(current->signal &= ~(1<<(SIGCHLD-1))))
214                         goto repeat;
215                 else
216                         return -EINTR;
217         }
218         return -ECHILD;
227 @Fixed bug in waitpid() so that the proper exit code would be returned.
229 text
230 @d35 1
231 a35 1
232 static inline void send_sig(long sig,struct task_struct * p,int priv)
233 d38 2
234 a39 6
235                 return;
236         if (priv ||
237                 current->uid==p->uid ||
238                 current->euid==p->uid ||
239                 current->uid==p->euid ||
240                 current->euid==p->euid)
241 d41 3
242 d49 1
243 a49 1
245 d56 5
246 a60 1
247 void do_kill(long pid,long sig,int priv)
248 d63 1
249 d66 3
250 a68 2
251                 if (*p && (*p)->pgrp == current->pid)
252                         send_sig(sig,*p,priv);
253 d70 3
254 a72 2
255                 if (*p && (*p)->pid == pid)
256                         send_sig(sig,*p,priv);
257 d74 2
258 a75 1
259                 send_sig(sig,*p,priv);
260 d78 3
261 a80 7
262                         send_sig(sig,*p,priv);
265 int sys_kill(int pid,int sig)
267         do_kill(pid,sig,!(current->uid || current->euid));
268         return 0;
274 @Initial revision
276 text
277 @d164 1
278 a165 1
279                                 put_fs_long((*p)->exit_code,stat_addr);