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