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