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