|
|
1.1.1.2 root 1: /*
2: * linux/kernel/exit.c
3: *
4: * (C) 1991 Linus Torvalds
5: */
6:
1.1 root 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:
1.1.1.2 root 35: static inline int send_sig(long sig,struct task_struct * p,int priv)
1.1 root 36: {
37: if (!p || sig<1 || sig>32)
1.1.1.2 root 38: return -EINVAL;
39: if (priv || (current->euid==p->euid) || suser())
1.1 root 40: p->signal |= (1<<(sig-1));
1.1.1.2 root 41: else
42: return -EPERM;
43: return 0;
1.1 root 44: }
45:
1.1.1.2 root 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)
1.1 root 61: {
62: struct task_struct **p = NR_TASKS + task;
1.1.1.2 root 63: int err, retval = 0;
1.1 root 64:
65: if (!pid) while (--p > &FIRST_TASK) {
1.1.1.2 root 66: if (*p && (*p)->pgrp == current->pid)
67: if (err=send_sig(sig,*p,1))
68: retval = err;
1.1 root 69: } else if (pid>0) while (--p > &FIRST_TASK) {
1.1.1.2 root 70: if (*p && (*p)->pid == pid)
71: if (err=send_sig(sig,*p,0))
72: retval = err;
1.1 root 73: } else if (pid == -1) while (--p > &FIRST_TASK)
1.1.1.2 root 74: if (err = send_sig(sig,*p,0))
75: retval = err;
1.1 root 76: else while (--p > &FIRST_TASK)
77: if (*p && (*p)->pgrp == -pid)
1.1.1.2 root 78: if (err = send_sig(sig,*p,0))
79: retval = err;
80: return retval;
1.1 root 81: }
82:
1.1.1.2 root 83: static void tell_father(int pid)
1.1 root 84: {
1.1.1.2 root 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 */
1.1.1.3 ! root 97: /* This is not really OK. Must change it to make father 1 */
! 98: printk("BAD BAD - no father found\n\r");
1.1.1.2 root 99: release(current);
1.1 root 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++)
1.1.1.3 ! root 109: if (task[i] && task[i]->father == current->pid) {
! 110: task[i]->father = 1;
! 111: if (task[i]->state == TASK_ZOMBIE)
! 112: /* assumption task[1] is always init */
! 113: (void) send_sig(SIGCHLD, task[1], 1);
! 114: }
1.1 root 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;
1.1.1.3 ! root 122: iput(current->executable);
! 123: current->executable=NULL;
1.1 root 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;
1.1.1.2 root 128: if (current->leader)
129: kill_session();
130: current->state = TASK_ZOMBIE;
131: current->exit_code = code;
132: tell_father(current->father);
1.1 root 133: schedule();
134: return (-1); /* just to suppress warnings */
135: }
136:
137: int sys_exit(int error_code)
138: {
139: return do_exit((error_code&0xff)<<8);
140: }
141:
1.1.1.2 root 142: int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
1.1 root 143: {
1.1.1.3 ! root 144: int flag, code;
1.1 root 145: struct task_struct ** p;
146:
147: verify_area(stat_addr,4);
148: repeat:
1.1.1.2 root 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;
1.1.1.3 ! root 175: code = (*p)->exit_code;
1.1.1.2 root 176: release(*p);
1.1.1.3 ! root 177: put_fs_long(code,stat_addr);
1.1.1.2 root 178: return flag;
179: default:
1.1 root 180: flag=1;
1.1.1.2 root 181: continue;
182: }
183: }
1.1 root 184: if (flag) {
185: if (options & WNOHANG)
186: return 0;
1.1.1.2 root 187: current->state=TASK_INTERRUPTIBLE;
188: schedule();
1.1 root 189: if (!(current->signal &= ~(1<<(SIGCHLD-1))))
190: goto repeat;
191: else
192: return -EINTR;
193: }
194: return -ECHILD;
195: }
196:
197:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.