1 /* This file handles signals, which are asynchronous events and are generally
2 * a messy and unpleasant business. Signals can be generated by the KILL
3 * system call, or from the keyboard (SIGINT) or from the clock (SIGALRM).
4 * In all cases control eventually passes to check_sig() to see which processes
5 * can be signaled. The actual signaling is done by sig_proc().
6 *
7 * The entry points into this file are:
8 * do_sigaction: perform the SIGACTION system call
9 * do_sigpending: perform the SIGPENDING system call
10 * do_sigprocmask: perform the SIGPROCMASK system call
11 * do_sigreturn: perform the SIGRETURN system call
12 * do_sigsuspend: perform the SIGSUSPEND system call
13 * do_kill: perform the KILL system call
14 * do_ksig: accept a signal originating in the kernel (e.g., SIGINT)
15 * do_alarm: perform the ALARM system call by calling set_alarm()
16 * set_alarm: tell the clock task to start or stop a timer
17 * do_pause: perform the PAUSE system call
18 * do_reboot: kill all processes, then reboot system
19 * sig_proc: interrupt or terminate a signaled process
20 * check_sig: check which processes to signal with sig_proc()
21 */
22
23 #include "mm.h"
24 #include <sys/stat.h>
25 #include <minix/callnr.h>
26 #include <minix/com.h>
27 #include <signal.h>
28 #include <sys/sigcontext.h>
29 #include <string.h>
30 #include "mproc.h"
31 #include "param.h"
32
33 #define CORE_MODE 0777 /* mode to use on core image files */
34 #define DUMPED 0200 /* bit set in status when core dumped */
35 #define DUMP_SIZE ((INT_MAX / BLOCK_SIZE) * BLOCK_SIZE)
36 /* buffer size for core dumps */
37
38 FORWARD _PROTOTYPE( void check_pending, (void) );
39 FORWARD _PROTOTYPE( void dump_core, (struct mproc *rmp) );
40 FORWARD _PROTOTYPE( void unpause, (int pro) );
41
42
43 /*===========================================================================*
44 * do_sigaction *
45 *===========================================================================*/
46 PUBLIC int do_sigaction()
47 {
48 int r;
49 struct sigaction svec;
50 struct sigaction *svp;
51
52 if (sig_nr == SIGKILL) return(OK);
53 if (sig_nr < 1 || sig_nr > _NSIG) return (EINVAL);
54 svp = &mp->mp_sigact[sig_nr];
55 if ((struct sigaction *) sig_osa != (struct sigaction *) NULL) {
56 r = sys_copy(MM_PROC_NR,D, (phys_bytes) svp,
57 who, D, (phys_bytes) sig_osa, (phys_bytes) sizeof(svec));
58 if (r != OK) return(r);
59 }
60
61 if ((struct sigaction *) sig_nsa == (struct sigaction *) NULL) return(OK);
62
63 /* Read in the sigaction structure. */
64 r = sys_copy(who, D, (phys_bytes) sig_nsa,
65 MM_PROC_NR, D, (phys_bytes) &svec, (phys_bytes) sizeof(svec));
66 if (r != OK) return(r);
67
68 if (svec.sa_handler == SIG_IGN) {
69 sigaddset(&mp->mp_ignore, sig_nr);
70 sigdelset(&mp->mp_sigpending, sig_nr);
71 sigdelset(&mp->mp_catch, sig_nr);
72 } else {
73 sigdelset(&mp->mp_ignore, sig_nr);
74 if (svec.sa_handler == SIG_DFL)
75 sigdelset(&mp->mp_catch, sig_nr);
76 else
77 sigaddset(&mp->mp_catch, sig_nr);
78 }
79 mp->mp_sigact[sig_nr].sa_handler = svec.sa_handler;
80 sigdelset(&svec.sa_mask, SIGKILL);
81 mp->mp_sigact[sig_nr].sa_mask = svec.sa_mask;
82 mp->mp_sigact[sig_nr].sa_flags = svec.sa_flags;
83 mp->mp_sigreturn = (vir_bytes) sig_ret;
84 return(OK);
85 }
86
87 /*===========================================================================*
88 * do_sigpending *
89 *===========================================================================*/
90 PUBLIC int do_sigpending()
91 {
92 ret_mask = (long) mp->mp_sigpending;
93 return OK;
94 }
95
96 /*===========================================================================*
97 * do_sigprocmask *
98 *===========================================================================*/
99 PUBLIC int do_sigprocmask()
100 {
101 /* Note that the library interface passes the actual mask in sigmask_set,
102 * not a pointer to the mask, in order to save a sys_copy. Similarly,
103 * the old mask is placed in the return message which the library
104 * interface copies (if requested) to the user specified address.
105 *
106 * The library interface must set SIG_INQUIRE if the 'act' argument
107 * is NULL.
108 */
109
110 int i;
111
112 ret_mask = (long) mp->mp_sigmask;
113
114 switch (sig_how) {
115 case SIG_BLOCK:
116 sigdelset((sigset_t *)&sig_set, SIGKILL);
117 for (i = 1; i < _NSIG; i++) {
118 if (sigismember((sigset_t *)&sig_set, i))
119 sigaddset(&mp->mp_sigmask, i);
120 }
121 break;
122
123 case SIG_UNBLOCK:
124 for (i = 1; i < _NSIG; i++) {
125 if (sigismember((sigset_t *)&sig_set, i))
126 sigdelset(&mp->mp_sigmask, i);
127 }
128 check_pending();
129 break;
130
131 case SIG_SETMASK:
132 sigdelset((sigset_t *)&sig_set, SIGKILL);
133 mp->mp_sigmask = (sigset_t)sig_set;
134 check_pending();
135 break;
136
137 case SIG_INQUIRE:
138 break;
139
140 default:
141 return(EINVAL);
142 break;
143 }
144 return OK;
145 }
146
147 /*===========================================================================*
148 * do_sigsuspend *
149 *===========================================================================*/
150 PUBLIC int do_sigsuspend()
151 {
152 mp->mp_sigmask2 = mp->mp_sigmask; /* save the old mask */
153 mp->mp_sigmask = (sigset_t) sig_set;
154 sigdelset(&mp->mp_sigmask, SIGKILL);
155 mp->mp_flags |= SIGSUSPENDED;
156 dont_reply = TRUE;
157 check_pending();
158 return OK;
159 }
160
161
162 /*===========================================================================*
163 * do_sigreturn *
164 *===========================================================================*/
165 PUBLIC int do_sigreturn()
166 {
167 /* A user signal handler is done. Restore context and check for
168 * pending unblocked signals.
169 */
170
171 int r;
172
173 mp->mp_sigmask = (sigset_t) sig_set;
174 sigdelset(&mp->mp_sigmask, SIGKILL);
175
176 r = sys_sigreturn(who, (vir_bytes)sig_context, sig_flags);
177 check_pending();
178 return(r);
179 }
180
181 /*===========================================================================*
182 * do_kill *
183 *===========================================================================*/
184 PUBLIC int do_kill()
185 {
186 /* Perform the kill(pid, signo) system call. */
187
188 return check_sig(pid, sig_nr);
189 }
190
191
192 /*===========================================================================*
193 * do_ksig *
194 *===========================================================================*/
195 PUBLIC int do_ksig()
196 {
197 /* Certain signals, such as segmentation violations and DEL, originate in the
198 * kernel. When the kernel detects such signals, it sets bits in a bit map.
199 * As soon as MM is awaiting new work, the kernel sends MM a message containing
200 * the process slot and bit map. That message comes here. The File System
201 * also uses this mechanism to signal writing on broken pipes (SIGPIPE).
202 */
203
204 register struct mproc *rmp;
205 int i, proc_nr;
206 pid_t proc_id, id;
207 sigset_t sig_map;
208
209 /* Only kernel may make this call. */
210 if (who != HARDWARE) return(EPERM);
211 dont_reply = TRUE; /* don't reply to the kernel */
212 proc_nr = mm_in.SIG_PROC;
213 rmp = &mproc[proc_nr];
214 if ( (rmp->mp_flags & IN_USE) == 0 || (rmp->mp_flags & HANGING) ) return(OK);
215 proc_id = rmp->mp_pid;
216 sig_map = (sigset_t) mm_in.SIG_MAP;
217 mp = &mproc[0]; /* pretend kernel signals are from MM */
218 mp->mp_procgrp = rmp->mp_procgrp; /* get process group right */
219
220 /* Stack faults are passed from kernel to MM as pseudo-signal SIGSTKFLT. */
221 if (sigismember(&sig_map, SIGSTKFLT)) stack_fault(proc_nr);
222
223 /* Check each bit in turn to see if a signal is to be sent. Unlike
224 * kill(), the kernel may collect several unrelated signals for a
225 * process and pass them to MM in one blow. Thus loop on the bit
226 * map. For SIGINT and SIGQUIT, use proc_id 0 to indicate a broadcast
227 * to the recipient's process group. For SIGKILL, use proc_id -1 to
228 * indicate a systemwide broadcast.
229 */
230 for (i = 1; i <= _NSIG; i++) {
231 if (!sigismember(&sig_map, i)) continue;
232 switch (i) {
233 case SIGSTKFLT:
234 continue; /* XXX - not sure if this special case
235 * is still necessary; however it would be
236 * nice to eliminate the special test for
237 * SIGSTKFLT above */
238 case SIGINT:
239 case SIGQUIT:
240 id = 0; break; /* broadcast to process group */
241 case SIGKILL:
242 id = -1; break; /* broadcast to all except INIT */
243 case SIGALRM:
244 /* Disregard SIGALRM when the target process has not
245 * requested an alarm. This only applies for a KERNEL
246 * generated signal.
247 */
248 if ((rmp->mp_flags & ALARM_ON) == 0) continue;
249 rmp->mp_flags &= ~ALARM_ON;
250 /* fall through */
251 default:
252 id = proc_id;
253 break;
254 }
255 check_sig(id, i);
256 sys_endsig(proc_nr); /* tell kernel it's done */
257 }
258 return(OK);
259 }
260
261
262 /*===========================================================================*
263 * do_alarm *
264 *===========================================================================*/
265 PUBLIC int do_alarm()
266 {
267 /* Perform the alarm(seconds) system call. */
268
269 return(set_alarm(who, seconds));
270 }
271
272
273 /*===========================================================================*
274 * set_alarm *
275 *===========================================================================*/
276 PUBLIC int set_alarm(proc_nr, sec)
277 int proc_nr; /* process that wants the alarm */
278 int sec; /* how many seconds delay before the signal */
279 {
280 /* This routine is used by do_alarm() to set the alarm timer. It is also used
281 * to turn the timer off when a process exits with the timer still on.
282 */
283
284 message m_sig;
285 int remaining;
286
287 if (sec != 0)
288 mproc[proc_nr].mp_flags |= ALARM_ON;
289 else
290 mproc[proc_nr].mp_flags &= ~ALARM_ON;
291
292 /* Tell the clock task to provide a signal message when the time comes.
293 *
294 * Large delays cause a lot of problems. First, the alarm system call
295 * takes an unsigned seconds count and the library has cast it to an int.
296 * That probably works, but on return the library will convert "negative"
297 * unsigneds to errors. Presumably no one checks for these errors, so
298 * force this call through. Second, If unsigned and long have the same
299 * size, converting from seconds to ticks can easily overflow. Finally,
300 * the kernel has similar overflow bugs adding ticks.
301 *
302 * Fixing this requires a lot of ugly casts to fit the wrong interface
303 * types and to avoid overflow traps. DELTA_TICKS has the right type
304 * (clock_t) although it is declared as long. How can variables like
305 * this be declared properly without combinatorial explosion of message
306 * types?
307 */
308 m_sig.m_type = SET_ALARM;
309 m_sig.CLOCK_PROC_NR = proc_nr;
310 m_sig.DELTA_TICKS = (clock_t) (HZ * (unsigned long) (unsigned) sec);
311 if ( (unsigned long) m_sig.DELTA_TICKS / HZ != (unsigned) sec)
312 m_sig.DELTA_TICKS = LONG_MAX; /* eternity (really CLOCK_T_MAX) */
313 if (sendrec(CLOCK, &m_sig) != OK) panic("alarm er", NO_NUM);
314 remaining = (int) m_sig.SECONDS_LEFT;
315 if (remaining != m_sig.SECONDS_LEFT || remaining < 0)
316 remaining = INT_MAX; /* true value is not representable */
317 return(remaining);
318 }
319
320
321 /*===========================================================================*
322 * do_pause *
323 *===========================================================================*/
324 PUBLIC int do_pause()
325 {
326 /* Perform the pause() system call. */
327
328 mp->mp_flags |= PAUSED;
329 dont_reply = TRUE;
330 return(OK);
331 }
332
333
334 /*=====================================================================*
335 * do_reboot *
336 *=====================================================================*/
337 PUBLIC int do_reboot()
338 {
339 register struct mproc *rmp = mp;
340 char monitor_code[64];
341
342 if (rmp->mp_effuid != SUPER_USER) return EPERM;
343
344 switch (reboot_flag) {
345 case RBT_HALT:
346 case RBT_REBOOT:
347 case RBT_PANIC:
348 case RBT_RESET:
349 break;
350 case RBT_MONITOR:
351 if (reboot_size > sizeof(monitor_code)) return EINVAL;
352 memset(monitor_code, 0, sizeof(monitor_code));
353 if (sys_copy(who, D, (phys_bytes) reboot_code,
354 MM_PROC_NR, D, (phys_bytes) monitor_code,
355 (phys_bytes) reboot_size) != OK) return EFAULT;
356 if (monitor_code[sizeof(monitor_code)-1] != 0) return EINVAL;
357 break;
358 default:
359 return EINVAL;
360 }
361
362 /* Kill all processes except init. */
363 check_sig(-1, SIGKILL);
364
365 tell_fs(EXIT, INIT_PROC_NR, 0, 0); /* cleanup init */
366
367 tell_fs(SYNC,0,0,0);
368
369 sys_abort(reboot_flag, monitor_code);
370 /* NOTREACHED */
371 }
372
373
374 /*===========================================================================*
375 * sig_proc *
376 *===========================================================================*/
377 PUBLIC void sig_proc(rmp, signo)
378 register struct mproc *rmp; /* pointer to the process to be signaled */
379 int signo; /* signal to send to process (1 to _NSIG) */
380 {
381 /* Send a signal to a process. Check to see if the signal is to be caught,
382 * ignored, or blocked. If the signal is to be caught, coordinate with
383 * KERNEL to push a sigcontext structure and a sigframe structure onto
384 * the catcher's stack. Also, KERNEL will reset the program counter and
385 * stack pointer, so that when the process next runs, it will be executing
386 * the signal handler. When the signal handler returns, sigreturn(2)
387 * will be called. Then KERNEL will restore the signal context from the
388 * sigcontext structure.
389 *
390 * If there is insufficient stack space, kill the process.
391 */
392
393 vir_bytes new_sp;
394 int slot;
395 int sigflags;
396 struct sigmsg sm;
397
398 slot = (int) (rmp - mproc);
399 if (!(rmp->mp_flags & IN_USE)) {
400 printf("MM: signal %d sent to dead process %d\n", signo, slot);
401 panic("", NO_NUM);
402 }
403 if (rmp->mp_flags & HANGING) {
404 printf("MM: signal %d sent to HANGING process %d\n", signo, slot);
405 panic("", NO_NUM);
406 }
407 if (rmp->mp_flags & TRACED && signo != SIGKILL) {
408 /* A traced process has special handling. */
409 unpause(slot);
410 stop_proc(rmp, signo); /* a signal causes it to stop */
411 return;
412 }
413 /* Some signals are ignored by default. */
414 if (sigismember(&rmp->mp_ignore, signo)) return;
415
416 if (sigismember(&rmp->mp_sigmask, signo)) {
417 /* Signal should be blocked. */
418 sigaddset(&rmp->mp_sigpending, signo);
419 return;
420 }
421 sigflags = rmp->mp_sigact[signo].sa_flags;
422 if (sigismember(&rmp->mp_catch, signo)) {
423 if (rmp->mp_flags & SIGSUSPENDED)
424 sm.sm_mask = rmp->mp_sigmask2;
425 else
426 sm.sm_mask = rmp->mp_sigmask;
427 sm.sm_signo = signo;
428 sm.sm_sighandler = (vir_bytes) rmp->mp_sigact[signo].sa_handler;
429 sm.sm_sigreturn = rmp->mp_sigreturn;
430 sys_getsp(slot, &new_sp);
431 sm.sm_stkptr = new_sp;
432
433 /* Make room for the sigcontext and sigframe struct. */
434 #if (MACHINE == SUN)
435 new_sp = stack_align(new_sp - sizeof(struct sigcontext) - INIT_SP);
436 if (adjust_stack(rmp, new_sp) != OK)
437 goto doterminate;
438 #else
439 new_sp -= sizeof(struct sigcontext)
440 + 3 * sizeof(char *) + 2 * sizeof(int);
441 if (adjust(rmp, rmp->mp_seg[D].mem_len, new_sp) != OK)
442 goto doterminate;
443 #endif
444
445 rmp->mp_sigmask |= rmp->mp_sigact[signo].sa_mask;
446 if (sigflags & SA_NODEFER)
447 sigdelset(&rmp->mp_sigmask, signo);
448 else
449 sigaddset(&rmp->mp_sigmask, signo);
450
451 if (sigflags & SA_RESETHAND) {
452 sigdelset(&rmp->mp_catch, signo);
453 rmp->mp_sigact[signo].sa_handler = SIG_DFL;
454 }
455
456 sys_sendsig(slot, &sm);
457 sigdelset(&rmp->mp_sigpending, signo);
458 /* If process is hanging on PAUSE, WAIT, SIGSUSPEND, tty, pipe, etc.,
459 * release it.
460 */
461 unpause(slot);
462 return;
463 }
464 doterminate:
465 /* Signal should not or cannot be caught. Terminate the process. */
466 rmp->mp_sigstatus = (char) signo;
467 if (sigismember(&core_sset, signo)) {
468 /* Switch to the user's FS environment and dump core. */
469 tell_fs(CHDIR, slot, FALSE, 0);
470 dump_core(rmp);
471 }
472 mm_exit(rmp, 0); /* terminate process */
473 }
474
475
476 /*===========================================================================*
477 * check_sig *
478 *===========================================================================*/
479 PUBLIC int check_sig(proc_id, signo)
480 pid_t proc_id; /* pid of proc to sig, or 0 or -1, or -pgrp */
481 int signo; /* signal to send to process (0 to _NSIG) */
482 {
483 /* Check to see if it is possible to send a signal. The signal may have to be
484 * sent to a group of processes. This routine is invoked by the KILL system
485 * call, and also when the kernel catches a DEL or other signal.
486 */
487
488 register struct mproc *rmp;
489 int count; /* count # of signals sent */
490 int error_code;
491
492 if (signo < 0 || signo > _NSIG) return(EINVAL);
493
494 /* Return EINVAL for attempts to send SIGKILL to INIT alone. */
495 if (proc_id == INIT_PID && signo == SIGKILL) return(EINVAL);
496
497 /* Search the proc table for processes to signal. (See forkexit.c about
498 * pid magic.)
499 */
500 count = 0;
501 error_code = ESRCH;
502 for (rmp = &mproc[INIT_PROC_NR]; rmp < &mproc[NR_PROCS]; rmp++) {
503 if ( (rmp->mp_flags & IN_USE) == 0) continue;
504 if (rmp->mp_flags & HANGING && signo != 0) continue;
505
506 /* Check for selection. */
507 if (proc_id > 0 && proc_id != rmp->mp_pid) continue;
508 if (proc_id == 0 && mp->mp_procgrp != rmp->mp_procgrp) continue;
509 if (proc_id == -1 && rmp->mp_pid == INIT_PID) continue;
510 if (proc_id < -1 && rmp->mp_procgrp != -proc_id) continue;
511
512 /* Check for permission. */
513 if (mp->mp_effuid != SUPER_USER
514 && mp->mp_realuid != rmp->mp_realuid
515 && mp->mp_effuid != rmp->mp_realuid
516 && mp->mp_realuid != rmp->mp_effuid
517 && mp->mp_effuid != rmp->mp_effuid) {
518 error_code = EPERM;
519 continue;
520 }
521
522 count++;
523 if (signo == 0) continue;
524
525 /* 'sig_proc' will handle the disposition of the signal. The
526 * signal may be caught, blocked, ignored, or cause process
527 * termination, possibly with core dump.
528 */
529 sig_proc(rmp, signo);
530
531 if (proc_id > 0) break; /* only one process being signaled */
532 }
533
534 /* If the calling process has killed itself, don't reply. */
535 if ((mp->mp_flags & IN_USE) == 0 || (mp->mp_flags & HANGING))
536 dont_reply = TRUE;
537 return(count > 0 ? OK : error_code);
538 }
539
540
541 /*===========================================================================*
542 * check_pending *
543 *===========================================================================*/
544 PRIVATE void check_pending()
545 {
546 /* Check to see if any pending signals have been unblocked. The
547 * first such signal found is delivered.
548 *
549 * If multiple pending unmasked signals are found, they will be
550 * delivered sequentially.
551 *
552 * There are several places in this file where the signal mask is
553 * changed. At each such place, check_pending() should be called to
554 * check for newly unblocked signals.
555 */
556
557 int i;
558
559 for (i = 1; i < _NSIG; i++) {
560 if (sigismember(&mp->mp_sigpending, i) &&
561 !sigismember(&mp->mp_sigmask, i)) {
562 sigdelset(&mp->mp_sigpending, i);
563 sig_proc(mp, i);
564 break;
565 }
566 }
567 }
568
569
570 /*===========================================================================*
571 * unpause *
572 *===========================================================================*/
573 PRIVATE void unpause(pro)
574 int pro; /* which process number */
575 {
576 /* A signal is to be sent to a process. If that process is hanging on a
577 * system call, the system call must be terminated with EINTR. Possible
578 * calls are PAUSE, WAIT, READ and WRITE, the latter two for pipes and ttys.
579 * First check if the process is hanging on an MM call. If not, tell FS,
580 * so it can check for READs and WRITEs from pipes, ttys and the like.
581 */
582
583 register struct mproc *rmp;
584
585 rmp = &mproc[pro];
586
587 /* Check to see if process is hanging on a PAUSE call. */
588 if ( (rmp->mp_flags & PAUSED) && (rmp->mp_flags & HANGING) == 0) {
589 rmp->mp_flags &= ~PAUSED;
590 reply(pro, EINTR, 0, NIL_PTR);
591 return;
592 }
593
594 /* Check to see if process is hanging on a WAIT call. */
595 if ( (rmp->mp_flags & WAITING) && (rmp->mp_flags & HANGING) == 0) {
596 rmp->mp_flags &= ~WAITING;
597 reply(pro, EINTR, 0, NIL_PTR);
598 return;
599 }
600
601 /* Check to see if process is hanging on a SIGSUSPEND call. */
602 if ((rmp->mp_flags & SIGSUSPENDED) && (rmp->mp_flags & HANGING) == 0) {
603 rmp->mp_flags &= ~SIGSUSPENDED;
604 reply(pro, EINTR, 0, NIL_PTR);
605 return;
606 }
607
608 /* Process is not hanging on an MM call. Ask FS to take a look. */
609 tell_fs(UNPAUSE, pro, 0, 0);
610 }
611
612
613 /*===========================================================================*
614 * dump_core *
615 *===========================================================================*/
616 PRIVATE void dump_core(rmp)
617 register struct mproc *rmp; /* whose core is to be dumped */
618 {
619 /* Make a core dump on the file "core", if possible. */
620
621 int fd, fake_fd, nr_written, seg, slot;
622 char *buf;
623 vir_bytes current_sp;
624 phys_bytes left; /* careful; 64K might overflow vir_bytes */
625 unsigned nr_to_write; /* unsigned for arg to write() but < INT_MAX */
626 long trace_data, trace_off;
627
628 slot = (int) (rmp - mproc);
629
630 /* Can core file be written? We are operating in the user's FS environment,
631 * so no special permission checks are needed.
632 */
633 if (rmp->mp_realuid != rmp->mp_effuid) return;
634 if ( (fd = creat(core_name, CORE_MODE)) < 0) return;
635 rmp->mp_sigstatus |= DUMPED;
636
637 /* Make sure the stack segment is up to date.
638 * We don't want adjust() to fail unless current_sp is preposterous,
639 * but it might fail due to safety checking. Also, we don't really want
640 * the adjust() for sending a signal to fail due to safety checking.
641 * Maybe make SAFETY_BYTES a parameter.
642 */
643 sys_getsp(slot, ¤t_sp);
644 #if (MACHINE == SUN)
645 adjust_stack(rmp, current_sp);
646 #else
647 adjust(rmp, rmp->mp_seg[D].mem_len, current_sp);
648 #endif
649
650 /* Write the memory map of all segments to begin the core file. */
651 if (write(fd, (char *) rmp->mp_seg, (unsigned) sizeof rmp->mp_seg)
652 != (unsigned) sizeof rmp->mp_seg) {
653 close(fd);
654 return;
655 }
656
657 /* Write out the whole kernel process table entry to get the regs. */
658 trace_off = 0;
659 while (sys_trace(3, slot, trace_off, &trace_data) == OK) {
660 if (write(fd, (char *) &trace_data, (unsigned) sizeof (long))
661 != (unsigned) sizeof (long)) {
662 close(fd);
663 return;
664 }
665 trace_off += sizeof (long);
666 }
667
668 /* Loop through segments and write the segments themselves out. */
669 for (seg = 0; seg < NR_SEGS; seg++) {
670 buf = (char *) ((vir_bytes) rmp->mp_seg[seg].mem_vir << CLICK_SHIFT);
671 left = (phys_bytes) rmp->mp_seg[seg].mem_len << CLICK_SHIFT;
672 fake_fd = (slot << 8) | (seg << 6) | fd;
673
674 /* Loop through a segment, dumping it. */
675 while (left != 0) {
676 nr_to_write = (unsigned) MIN(left, DUMP_SIZE);
677 if ( (nr_written = write(fake_fd, buf, nr_to_write)) < 0) {
678 close(fd);
679 return;
680 }
681 buf += nr_written;
682 left -= nr_written;
683 }
684 }
685 close(fd);
686 }
687
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.