|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.