This source file includes following definitions.
- release
- send_sig
- kill_session
- sys_kill
- tell_father
- do_exit
- sys_exit
- sys_waitpid
1
2
3
4
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
58
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
97
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
106 free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
107 free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
108 for (i=0 ; i<NR_TASKS ; i++)
109 if (task[i] && task[i]->father == current->pid) {
110 task[i]->father = 1;
111 if (task[i]->state == TASK_ZOMBIE)
112
113 (void) send_sig(SIGCHLD, task[1], 1);
114 }
115 for (i=0 ; i<NR_OPEN ; i++)
116 if (current->filp[i])
117 sys_close(i);
118 iput(current->pwd);
119 current->pwd=NULL;
120 iput(current->root);
121 current->root=NULL;
122 iput(current->executable);
123 current->executable=NULL;
124 if (current->leader && current->tty >= 0)
125 tty_table[current->tty].pgrp = 0;
126 if (last_task_used_math == current)
127 last_task_used_math = NULL;
128 if (current->leader)
129 kill_session();
130 current->state = TASK_ZOMBIE;
131 current->exit_code = code;
132 tell_father(current->father);
133 schedule();
134 return (-1);
135 }
136
137 int sys_exit(int error_code)
138 {
139 return do_exit((error_code&0xff)<<8);
140 }
141
142 int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
143 {
144 int flag, code;
145 struct task_struct ** p;
146
147 verify_area(stat_addr,4);
148 repeat:
149 flag=0;
150 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
151 if (!*p || *p == current)
152 continue;
153 if ((*p)->father != current->pid)
154 continue;
155 if (pid>0) {
156 if ((*p)->pid != pid)
157 continue;
158 } else if (!pid) {
159 if ((*p)->pgrp != current->pgrp)
160 continue;
161 } else if (pid != -1) {
162 if ((*p)->pgrp != -pid)
163 continue;
164 }
165 switch ((*p)->state) {
166 case TASK_STOPPED:
167 if (!(options & WUNTRACED))
168 continue;
169 put_fs_long(0x7f,stat_addr);
170 return (*p)->pid;
171 case TASK_ZOMBIE:
172 current->cutime += (*p)->utime;
173 current->cstime += (*p)->stime;
174 flag = (*p)->pid;
175 code = (*p)->exit_code;
176 release(*p);
177 put_fs_long(code,stat_addr);
178 return flag;
179 default:
180 flag=1;
181 continue;
182 }
183 }
184 if (flag) {
185 if (options & WNOHANG)
186 return 0;
187 current->state=TASK_INTERRUPTIBLE;
188 schedule();
189 if (!(current->signal &= ~(1<<(SIGCHLD-1))))
190 goto repeat;
191 else
192 return -EINTR;
193 }
194 return -ECHILD;
195 }
196
197