|
|
1.1 root 1: /*
2: * linux/kernel/signal.c
3: *
4: * (C) 1991 Linus Torvalds
5: */
6:
7: #include <linux/sched.h>
8: #include <linux/kernel.h>
9: #include <asm/segment.h>
10:
11: #include <signal.h>
1.1.1.3 ! root 12: #include <errno.h>
! 13:
1.1 root 14: int sys_sgetmask()
15: {
16: return current->blocked;
17: }
18:
19: int sys_ssetmask(int newmask)
20: {
21: int old=current->blocked;
22:
1.1.1.3 ! root 23: current->blocked = newmask & ~(1<<(SIGKILL-1)) & ~(1<<(SIGSTOP-1));
1.1 root 24: return old;
25: }
26:
1.1.1.3 ! root 27: int sys_sigpending(sigset_t *set)
! 28: {
! 29: /* fill in "set" with signals pending but blocked. */
! 30: verify_area(set,4);
! 31: put_fs_long(current->blocked & current->signal, (unsigned long *)set);
! 32: return 0;
! 33: }
! 34:
! 35: /* atomically swap in the new signal mask, and wait for a signal.
! 36: *
! 37: * we need to play some games with syscall restarting. We get help
! 38: * from the syscall library interface. Note that we need to coordinate
! 39: * the calling convention with the libc routine.
! 40: *
! 41: * "set" is just the sigmask as described in 1003.1-1988, 3.3.7.
! 42: * It is assumed that sigset_t can be passed as a 32 bit quantity.
! 43: *
! 44: * "restart" holds a restart indication. If it's non-zero, then we
! 45: * install the old mask, and return normally. If it's zero, we store
! 46: * the current mask in old_mask and block until a signal comes in.
! 47: */
! 48: int sys_sigsuspend(int restart, unsigned long old_mask, unsigned long set)
! 49: {
! 50: extern int sys_pause(void);
! 51:
! 52: if (restart) {
! 53: /* we're restarting */
! 54: current->blocked = old_mask;
! 55: return -EINTR;
! 56: }
! 57: /* we're not restarting. do the work */
! 58: *(&restart) = 1;
! 59: *(&old_mask) = current->blocked;
! 60: current->blocked = set;
! 61: (void) sys_pause(); /* return after a signal arrives */
! 62: return -ERESTARTNOINTR; /* handle the signal, and come back */
! 63: }
! 64:
1.1 root 65: static inline void save_old(char * from,char * to)
66: {
67: int i;
68:
69: verify_area(to, sizeof(struct sigaction));
70: for (i=0 ; i< sizeof(struct sigaction) ; i++) {
71: put_fs_byte(*from,to);
72: from++;
73: to++;
74: }
75: }
76:
77: static inline void get_new(char * from,char * to)
78: {
79: int i;
80:
81: for (i=0 ; i< sizeof(struct sigaction) ; i++)
82: *(to++) = get_fs_byte(from++);
83: }
84:
85: int sys_signal(int signum, long handler, long restorer)
86: {
87: struct sigaction tmp;
88:
1.1.1.3 ! root 89: if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)
! 90: return -EINVAL;
1.1 root 91: tmp.sa_handler = (void (*)(int)) handler;
92: tmp.sa_mask = 0;
93: tmp.sa_flags = SA_ONESHOT | SA_NOMASK;
94: tmp.sa_restorer = (void (*)(void)) restorer;
95: handler = (long) current->sigaction[signum-1].sa_handler;
96: current->sigaction[signum-1] = tmp;
97: return handler;
98: }
99:
100: int sys_sigaction(int signum, const struct sigaction * action,
101: struct sigaction * oldaction)
102: {
103: struct sigaction tmp;
104:
1.1.1.3 ! root 105: if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)
! 106: return -EINVAL;
1.1 root 107: tmp = current->sigaction[signum-1];
108: get_new((char *) action,
109: (char *) (signum-1+current->sigaction));
110: if (oldaction)
111: save_old((char *) &tmp,(char *) oldaction);
112: if (current->sigaction[signum-1].sa_flags & SA_NOMASK)
113: current->sigaction[signum-1].sa_mask = 0;
114: else
115: current->sigaction[signum-1].sa_mask |= (1<<(signum-1));
116: return 0;
117: }
118:
1.1.1.3 ! root 119: /*
! 120: * Routine writes a core dump image in the current directory.
! 121: * Currently not implemented.
! 122: */
! 123: int core_dump(long signr)
! 124: {
! 125: return(0); /* We didn't do a dump */
! 126: }
! 127:
! 128: int do_signal(long signr,long eax,long ebx, long ecx, long edx, long orig_eax,
1.1 root 129: long fs, long es, long ds,
130: long eip, long cs, long eflags,
131: unsigned long * esp, long ss)
132: {
1.1.1.2 root 133: unsigned long sa_handler;
1.1 root 134: long old_eip=eip;
135: struct sigaction * sa = current->sigaction + signr - 1;
136: int longs;
1.1.1.3 ! root 137:
1.1 root 138: unsigned long * tmp_esp;
139:
1.1.1.3 ! root 140: #ifdef notdef
! 141: printk("pid: %d, signr: %x, eax=%d, oeax = %d, int=%d\n",
! 142: current->pid, signr, eax, orig_eax,
! 143: sa->sa_flags & SA_INTERRUPT);
! 144: #endif
! 145: if ((orig_eax != -1) &&
! 146: ((eax == -ERESTARTSYS) || (eax == -ERESTARTNOINTR))) {
! 147: if ((eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT) ||
! 148: signr < SIGCONT || signr > SIGTTOU))
! 149: *(&eax) = -EINTR;
! 150: else {
! 151: *(&eax) = orig_eax;
! 152: *(&eip) = old_eip -= 2;
! 153: }
! 154: }
1.1.1.2 root 155: sa_handler = (unsigned long) sa->sa_handler;
1.1 root 156: if (sa_handler==1)
1.1.1.3 ! root 157: return(1); /* Ignore, see if there are more signals... */
1.1 root 158: if (!sa_handler) {
1.1.1.3 ! root 159: switch (signr) {
! 160: case SIGCONT:
! 161: case SIGCHLD:
! 162: return(1); /* Ignore, ... */
! 163:
! 164: case SIGSTOP:
! 165: case SIGTSTP:
! 166: case SIGTTIN:
! 167: case SIGTTOU:
! 168: current->state = TASK_STOPPED;
! 169: current->exit_code = signr;
! 170: if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags &
! 171: SA_NOCLDSTOP))
! 172: current->p_pptr->signal |= (1<<(SIGCHLD-1));
! 173: return(1); /* Reschedule another event */
! 174:
! 175: case SIGQUIT:
! 176: case SIGILL:
! 177: case SIGTRAP:
! 178: case SIGIOT:
! 179: case SIGFPE:
! 180: case SIGSEGV:
! 181: if (core_dump(signr))
! 182: do_exit(signr|0x80);
! 183: /* fall through */
! 184: default:
! 185: do_exit(signr);
! 186: }
1.1 root 187: }
1.1.1.3 ! root 188: /*
! 189: * OK, we're invoking a handler
! 190: */
1.1 root 191: if (sa->sa_flags & SA_ONESHOT)
192: sa->sa_handler = NULL;
193: *(&eip) = sa_handler;
194: longs = (sa->sa_flags & SA_NOMASK)?7:8;
195: *(&esp) -= longs;
196: verify_area(esp,longs*4);
197: tmp_esp=esp;
198: put_fs_long((long) sa->sa_restorer,tmp_esp++);
199: put_fs_long(signr,tmp_esp++);
200: if (!(sa->sa_flags & SA_NOMASK))
201: put_fs_long(current->blocked,tmp_esp++);
202: put_fs_long(eax,tmp_esp++);
203: put_fs_long(ecx,tmp_esp++);
204: put_fs_long(edx,tmp_esp++);
205: put_fs_long(eflags,tmp_esp++);
206: put_fs_long(old_eip,tmp_esp++);
207: current->blocked |= sa->sa_mask;
1.1.1.3 ! root 208: return(0); /* Continue, execute handler */
1.1 root 209: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.