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