File:  [Early Linux] / linux / kernel / exit.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:02:23 2018 UTC (20 months, 3 weeks ago) by root
Branches: linus, MAIN
CVS tags: linux011, HEAD
linux 0.11

    1: /*
    2:  *  linux/kernel/exit.c
    3:  *
    4:  *  (C) 1991  Linus Torvalds
    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:  * 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)
   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: /* if we don't find any fathers, we just release ourselves */
   97: /* This is not really OK. Must change it to make father 1 */
   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: 				/* assumption task[1] is always init */
  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);	/* just to suppress warnings */
  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: 

unix.superglobalmegacorp.com