Bell 32V development
[unix-history] / usr / src / slowsys / sys / sig.c
CommitLineData
2500b869
TL
1#include "../h/param.h"
2#include "../h/systm.h"
3#include "../h/dir.h"
4#include "../h/user.h"
5#include "../h/proc.h"
6#include "../h/inode.h"
7#include "../h/reg.h"
8#include "../h/text.h"
9#include "../h/seg.h"
10#include "../h/mtpr.h"
11#include "../h/page.h"
12#include "../h/psl.h"
13
14/*
15 * Priority for tracing
16 */
17#define IPCPRI PZERO
18
19/*
20 * Tracing variables.
21 * Used to pass trace command from
22 * parent to child being traced.
23 * This data base cannot be
24 * shared and is locked
25 * per user.
26 */
27struct
28{
29 int ip_lock;
30 int ip_req;
31 int *ip_addr;
32 int ip_data;
33} ipc;
34
35/*
36 * Send the specified signal to
37 * all processes with 'pgrp' as
38 * process group.
39 * Called by tty.c for quits and
40 * interrupts.
41 */
42signal(pgrp, sig)
43register pgrp;
44{
45 register struct proc *p;
46
47 if(pgrp == 0)
48 return;
49 for(p = &proc[0]; p < &proc[NPROC]; p++)
50 if(p->p_pgrp == pgrp)
51 psignal(p, sig);
52}
53
54/*
55 * Send the specified signal to
56 * the specified process.
57 */
58psignal(p, sig)
59register struct proc *p;
60register unsigned sig;
61{
62
63 if((unsigned)sig >= NSIG)
64 return;
65 if(sig)
66 p->p_sig |= 1<<(sig-1);
67 if(p->p_pri > PUSER)
68 p->p_pri = PUSER;
69 if(p->p_stat == SSLEEP && p->p_pri > PZERO)
70 setrun(p);
71}
72
73/*
74 * Returns true if the current
75 * process has a signal to process.
76 * This is asked at least once
77 * each time a process enters the
78 * system.
79 * A signal does not do anything
80 * directly to a process; it sets
81 * a flag that asks the process to
82 * do something to itself.
83 */
84issig()
85{
86 register n;
87 register struct proc *p;
88
89 p = u.u_procp;
90 while(p->p_sig) {
91 n = fsig(p);
92 if((u.u_signal[n]&1) == 0 || (p->p_flag&STRC))
93 return(n);
94 p->p_sig &= ~(1<<(n-1));
95 }
96 return(0);
97}
98
99/*
100 * Enter the tracing STOP state.
101 * In this state, the parent is
102 * informed and the process is able to
103 * receive commands from the parent.
104 */
105stop()
106{
107 register struct proc *pp, *cp;
108
109loop:
110 cp = u.u_procp;
111 if(cp->p_ppid != 1)
112 for (pp = &proc[0]; pp < &proc[NPROC]; pp++)
113 if (pp->p_pid == cp->p_ppid) {
114 wakeup((caddr_t)pp);
115 cp->p_stat = SSTOP;
116 swtch();
117 if ((cp->p_flag&STRC)==0 || procxmt())
118 return;
119 goto loop;
120 }
121 exit(fsig(u.u_procp));
122}
123
124/*
125 * Perform the action specified by
126 * the current signal.
127 * The usual sequence is:
128 * if(issig())
129 * psig();
130 */
131psig()
132{
133 register n, p;
134 register struct proc *rp;
135
136 rp = u.u_procp;
137 if (rp->p_flag&STRC)
138 stop();
139 n = fsig(rp);
140 if (n==0)
141 return;
142 rp->p_sig &= ~(1<<(n-1));
143 if((p=u.u_signal[n]) != 0) {
144 u.u_error = 0;
145 if(n != SIGINS && n != SIGTRC)
146 u.u_signal[n] = 0;
147 sendsig(p, n);
148 return;
149 }
150 switch(n) {
151
152 case SIGQUIT:
153 case SIGINS:
154 case SIGTRC:
155 case SIGIOT:
156 case SIGEMT:
157 case SIGFPT:
158 case SIGBUS:
159 case SIGSEG:
160 case SIGSYS:
161 if(core())
162 n += 0200;
163 }
164 exit(n);
165}
166
167/*
168 * find the signal in bit-position
169 * representation in p_sig.
170 */
171fsig(p)
172struct proc *p;
173{
174 register n, i;
175
176 n = p->p_sig;
177 for(i=1; i<NSIG; i++) {
178 if(n & 1)
179 return(i);
180 n >>= 1;
181 }
182 return(0);
183}
184
185/*
186 * Create a core image on the file "core"
187 * If you are looking for protection glitches,
188 * there are probably a wealth of them here
189 * when this occurs to a suid command.
190 *
191 * It writes USIZE block of the
192 * user.h area followed by the entire
193 * data+stack segments.
194 */
195core()
196{
197 register struct inode *ip;
198 register s;
199 extern schar();
200
201 u.u_error = 0;
202 u.u_dirp = "core";
203 ip = namei(schar, 1);
204 if(ip == NULL) {
205 if(u.u_error)
206 return(0);
207 ip = maknode(0666);
208 if (ip==NULL)
209 return(0);
210 }
211 if(!access(ip, IWRITE) &&
212 (ip->i_mode&IFMT) == IFREG &&
213 u.u_uid == u.u_ruid) {
214 itrunc(ip);
215 u.u_offset = 0;
216 u.u_base = (caddr_t)&u;
217 u.u_count = ctob(USIZE);
218 u.u_segflg = 1;
219 writei(ip);
220 s = u.u_procp->p_size - USIZE;
221 estabur((unsigned)0, s, (unsigned)0, 0, RO);
222 u.u_base = 0;
223 u.u_count = ctob(s);
224 u.u_segflg = 0;
225 writei(ip);
226 }
227 iput(ip);
228 return(u.u_error==0);
229}
230
231/*
232 * grow the stack to include the SP
233 * true return if successful.
234 */
235
236grow(sp)
237unsigned sp;
238{
239 register si, i;
240 register struct proc *p;
241 register a;
242
243 if(sp >= USRSTACK-ctob(u.u_ssize))
244 return(0);
245 si = btoc((USRSTACK-sp)) - u.u_ssize + SINCR;
246 if(si <= 0)
247 return(0);
248 if(estabur(u.u_tsize, u.u_dsize, u.u_ssize+si, u.u_sep, RO))
249 return(0);
250 p = u.u_procp;
251 expand(p->p_size+si);
252 a = p->p_addr + p->p_size;
253 for(i=u.u_ssize; i; i--) {
254 a--;
255 copyseg(a-si, a);
256 }
257 for(i=si; i; i--)
258 clearseg(--a);
259 u.u_ssize += si;
260 return(1);
261}
262
263/*
264 * sys-trace system call.
265 */
266ptrace()
267{
268 register struct proc *p;
269 register struct a {
270 int req;
271 int pid;
272 int *addr;
273 int data;
274 } *uap;
275
276 uap = (struct a *)u.u_ap;
277 if (uap->req <= 0) {
278 u.u_procp->p_flag |= STRC;
279 return;
280 }
281 for (p=proc; p < &proc[NPROC]; p++)
282 if (p->p_stat==SSTOP
283 && p->p_pid==uap->pid
284 && p->p_ppid==u.u_procp->p_pid)
285 goto found;
286 u.u_error = ESRCH;
287 return;
288
289 found:
290 while (ipc.ip_lock)
291 sleep((caddr_t)&ipc, IPCPRI);
292 ipc.ip_lock = p->p_pid;
293 ipc.ip_data = uap->data;
294 ipc.ip_addr = uap->addr;
295 ipc.ip_req = uap->req;
296 p->p_flag &= ~SWTED;
297 setrun(p);
298 while (ipc.ip_req > 0)
299 sleep((caddr_t)&ipc, IPCPRI);
300 u.u_r.r_val1 = ipc.ip_data;
301 if (ipc.ip_req < 0)
302 u.u_error = EIO;
303 ipc.ip_lock = 0;
304 wakeup((caddr_t)&ipc);
305}
306
307int ipcreg[] = {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC};
308/*
309 * Code that the child process
310 * executes to implement the command
311 * of the parent process in tracing.
312 */
313procxmt()
314{
315 register int i;
316 register *p;
317 register struct text *xp;
318
319 if (ipc.ip_lock != u.u_procp->p_pid)
320 return(0);
321 i = ipc.ip_req;
322 ipc.ip_req = 0;
323 wakeup((caddr_t)&ipc);
324 switch (i) {
325
326 /* read user I */
327 case 1:
328 if ( !useracc((caddr_t)ipc.ip_addr, 4, 1))
329 goto error;
330 ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
331 break;
332
333 /* read user D */
334 case 2:
335 if ( !useracc((caddr_t)ipc.ip_addr, 4, 1))
336 goto error;
337 ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
338 break;
339
340 /* read u */
341 case 3:
342 i = (int)ipc.ip_addr;
343 if (i<0 || i >= ctob(USIZE))
344 goto error;
345 ipc.ip_data = ((physadr)&u)->r[i>>2];
346 break;
347
348 /* write user I */
349 /* Must set up to allow writing */
350 case 4:
351 /*
352 * If text, must assure exclusive use
353 */
354 if (xp = u.u_procp->p_textp) {
355 if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX)
356 goto error;
357 xp->x_iptr->i_flag &= ~ITEXT;
358 }
359 estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep, RW);
360 i = suiword((caddr_t)ipc.ip_addr, 0);
361 suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
362 estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep, RO);
363 if (i<0)
364 goto error;
365 if (xp)
366 xp->x_flag |= XWRIT;
367 break;
368
369 /* write user D */
370 case 5:
371 if (suword((caddr_t)ipc.ip_addr, 0) < 0)
372 goto error;
373 suword((caddr_t)ipc.ip_addr, ipc.ip_data);
374 break;
375
376 /* write u */
377 case 6:
378 i = (int)ipc.ip_addr;
379 p = (int *)&((physadr)&u)->r[i>>2];
380 for (i=0; i<16; i++)
381 if (p == &u.u_ar0[ipcreg[i]])
382 goto ok;
383 if (p == &u.u_ar0[PS]) {
384 ipc.ip_data |= 0x3c00000; /* modes == user */
385 ipc.ip_data &= ~0x3c20ff00; /* IS, FPD, ... */
386 goto ok;
387 }
388 goto error;
389
390 ok:
391 *p = ipc.ip_data;
392 break;
393
394 /* set signal and continue */
395 /* one version causes a trace-trap */
396 case 9:
397 u.u_ar0[PS] |= PSL_T;
398 case 7:
399 if ((int)ipc.ip_addr != 1)
400 u.u_ar0[PC] = (int)ipc.ip_addr;
401 u.u_procp->p_sig = 0;
402 if (ipc.ip_data)
403 psignal(u.u_procp, ipc.ip_data);
404 return(1);
405
406 /* force exit */
407 case 8:
408 exit(fsig(u.u_procp));
409
410 default:
411 error:
412 ipc.ip_req = -1;
413 }
414 return(0);
415}