/*===========================================================================* * do_reboot * *===========================================================================*/ int do_reboot() { message m; /* Check permission to abort the system. */ if (mp->mp_effuid != SUPER_USER) return(EPERM); /* See how the system should be aborted. */ abort_flag = m_in.m_lc_pm_reboot.how; /* notify readclock (some arm systems power off via RTC alarms) */ if (abort_flag & RB_POWERDOWN) { endpoint_t readclock_ep; if (ds_retrieve_label_endpt("readclock.drv", &readclock_ep) == OK) { message m; /* no params to set, nothing we can do if it fails */ _taskcall(readclock_ep, RTCDEV_PWR_OFF, &m); } } /* Order matters here. When VFS is told to reboot, it exits all its * processes, and then would be confused if they're exited again by * SIGKILL. So first kill, then reboot. */ check_sig(-1, SIGKILL, FALSE /* ksig*/); /* kill all users except init */ sys_stop(INIT_PROC_NR); /* stop init, but keep it around */ /* Tell VFS to reboot */ memset(&m, 0, sizeof(m)); m.m_type = VFS_PM_REBOOT; tell_vfs(&mproc[VFS_PROC_NR], &m); return(SUSPEND); /* don't reply to caller */ }
static void jargrep(regex_t *exp, regex_t *nl_exp, const char *jarfile, int options){ int fd; int floop = TRUE; pb_file pbf; ub1 scratch[16]; if((fd = open(jarfile, O_RDONLY)) == -1) { if(!(options & JG_SUPRESS_ERROR)) fprintf(stderr, "Error reading file '%s': %s\n", jarfile, strerror(errno)); } else { pb_init(&pbf, fd); do { if(pb_read(&pbf, scratch, 4) != 4) { perror("read"); floop = FALSE; } else { switch (check_sig(scratch, &pbf)) { case 0: floop = cont_grep(exp, nl_exp, fd, &pbf, options); break; case 1: floop = FALSE; break; case 2: continue; /* fall through continue */ } } } while(floop); } }
/*===========================================================================* * do_ksig * *===========================================================================*/ PUBLIC int do_ksig() { /* Certain signals, such as segmentation violations and DEL, originate in the * kernel. When the kernel detects such signals, it sets bits in a bit map. * As soon as MM is awaiting new work, the kernel sends MM a message containing * the process slot and bit map. That message comes here. The File System * also uses this mechanism to signal writing on broken pipes (SIGPIPE). */ register struct mproc *rmp; int i, proc_nr; pid_t proc_id, id; sigset_t sig_map; /* Only kernel may make this call. */ if (who != HARDWARE) return(EPERM); dont_reply = TRUE; /* don't reply to the kernel */ proc_nr = mm_in.SIG_PROC; rmp = &mproc[proc_nr]; if ( (rmp->mp_flags & IN_USE) == 0 || (rmp->mp_flags & HANGING) ) return(OK); proc_id = rmp->mp_pid; sig_map = (sigset_t) mm_in.SIG_MAP; mp = &mproc[0]; /* pretend kernel signals are from MM */ mp->mp_procgrp = rmp->mp_procgrp; /* get process group right */ /* Check each bit in turn to see if a signal is to be sent. Unlike * kill(), the kernel may collect several unrelated signals for a * process and pass them to MM in one blow. Thus loop on the bit * map. For SIGINT and SIGQUIT, use proc_id 0 to indicate a broadcast * to the recipient's process group. For SIGKILL, use proc_id -1 to * indicate a systemwide broadcast. */ for (i = 1; i <= _NSIG; i++) { if (!sigismember(&sig_map, i)) continue; switch (i) { case SIGINT: case SIGQUIT: id = 0; break; /* broadcast to process group */ case SIGKILL: id = -1; break; /* broadcast to all except INIT */ case SIGALRM: /* Disregard SIGALRM when the target process has not * requested an alarm. This only applies for a KERNEL * generated signal. */ if ((rmp->mp_flags & ALARM_ON) == 0) continue; rmp->mp_flags &= ~ALARM_ON; /* fall through */ default: id = proc_id; break; } check_sig(id, i); sys_endsig(proc_nr); /* tell kernel it's done */ } return(OK); }
/*===========================================================================* * do_srv_kill * *===========================================================================*/ int do_srv_kill() { /* Perform the srv_kill(pid, signo) system call. */ /* Only RS is allowed to use srv_kill. */ if (mp->mp_endpoint != RS_PROC_NR) return EPERM; /* Pretend the signal comes from the kernel when RS wants to deliver a signal * to a system process. RS sends a SIGKILL when it wants to perform cleanup. * In that case, ksig == TRUE forces PM to exit the process immediately. */ return check_sig(m_in.pid, m_in.sig_nr, TRUE /* ksig */); }
static int __init read_suspend_image(void) { int error = 0; if ((error = check_sig())) return error; if ((error = check_header())) return error; if ((error = read_pagedir())) return error; if ((error = data_read())) free_pages((unsigned long)pagedir_nosave, pagedir_order); return error; }
/*===========================================================================* * exec_restart * *===========================================================================*/ void exec_restart(struct mproc *rmp, int result, vir_bytes pc, vir_bytes sp, vir_bytes ps_str) { int r, sn; if (result != OK) { if (rmp->mp_flags & PARTIAL_EXEC) { /* Use SIGKILL to signal that something went wrong */ sys_kill(rmp->mp_endpoint, SIGKILL); return; } reply(rmp-mproc, result); return; } rmp->mp_flags &= ~PARTIAL_EXEC; /* Fix 'mproc' fields, tell kernel that exec is done, reset caught * sigs. */ for (sn = 1; sn < _NSIG; sn++) { if (sigismember(&rmp->mp_catch, sn)) { sigdelset(&rmp->mp_catch, sn); rmp->mp_sigact[sn].sa_handler = SIG_DFL; sigemptyset(&rmp->mp_sigact[sn].sa_mask); } } /* Cause a signal if this process is traced. * Do this before making the process runnable again! */ if (rmp->mp_tracer != NO_TRACER && !(rmp->mp_trace_flags & TO_NOEXEC)) { sn = (rmp->mp_trace_flags & TO_ALTEXEC) ? SIGSTOP : SIGTRAP; check_sig(rmp->mp_pid, sn, FALSE /* ksig */); } /* Call kernel to exec with SP and PC set by VFS. */ r = sys_exec(rmp->mp_endpoint, sp, (vir_bytes)rmp->mp_name, pc, ps_str); if (r != OK) panic("sys_exec failed: %d", r); }
static int __init read_suspend_image(void) { int error = 0; if ((error = check_sig())) return error; if ((error = check_header())) return error; if ((error = read_pagedir())) return error; if ((error = relocate_pagedir())) goto FreePagedir; if ((error = check_pagedir())) goto FreePagedir; if ((error = read_image_data())) goto FreePagedir; Done: return error; FreePagedir: free_pages((unsigned long)pm_pagedir_nosave,pagedir_order); goto Done; }
/*===========================================================================* * do_kill * *===========================================================================*/ PUBLIC int do_kill() { /* Perform the kill(pid, signo) system call. */ return check_sig(pid, sig_nr); }
/*===========================================================================* * do_trace * *===========================================================================*/ PUBLIC int do_trace() { register struct mproc *child; struct ptrace_range pr; int i, r, seg, req; req = m_in.request; /* The T_OK call is made by the child fork of the debugger before it execs * the process to be traced. The T_ATTACH call is made by the debugger itself * to attach to an existing process. */ switch (req) { case T_OK: /* enable tracing by parent for this proc */ if (mp->mp_tracer != NO_TRACER) return(EBUSY); mp->mp_tracer = mp->mp_parent; mp->mp_reply.reply_trace = 0; return(OK); case T_ATTACH: /* attach to an existing process */ if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH); if (child->mp_flags & EXITING) return(ESRCH); /* For non-root processes, user and group ID must match. */ if (mp->mp_effuid != SUPER_USER && (mp->mp_effuid != child->mp_effuid || mp->mp_effgid != child->mp_effgid || child->mp_effuid != child->mp_realuid || child->mp_effgid != child->mp_realgid)) return(EPERM); /* Only root may trace system servers. */ if (mp->mp_effuid != SUPER_USER && (child->mp_flags & PRIV_PROC)) return(EPERM); /* System servers may not trace anyone. They can use sys_trace(). */ if (mp->mp_flags & PRIV_PROC) return(EPERM); /* Can't trace self, PM or VM. */ if (child == mp || child->mp_endpoint == PM_PROC_NR || child->mp_endpoint == VM_PROC_NR) return(EPERM); /* Can't trace a process that is already being traced. */ if (child->mp_tracer != NO_TRACER) return(EBUSY); child->mp_tracer = who_p; child->mp_trace_flags = TO_NOEXEC; sig_proc(child, SIGSTOP, TRUE /*trace*/, FALSE /* ksig */); mp->mp_reply.reply_trace = 0; return(OK); case T_STOP: /* stop the process */ /* This call is not exposed to user programs, because its effect can be * achieved better by sending the traced process a signal with kill(2). */ return(EINVAL); case T_READB_INS: /* special hack for reading text segments */ if (mp->mp_effuid != SUPER_USER) return(EPERM); if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH); if (child->mp_flags & EXITING) return(ESRCH); r = sys_trace(req, child->mp_endpoint, m_in.PMTRACE_ADDR, &m_in.data); if (r != OK) return(r); mp->mp_reply.reply_trace = m_in.data; return(OK); case T_WRITEB_INS: /* special hack for patching text segments */ if (mp->mp_effuid != SUPER_USER) return(EPERM); if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH); if (child->mp_flags & EXITING) return(ESRCH); #if 0 /* Should check for shared text */ /* Make sure the text segment is not used as a source for shared * text. */ child->mp_ino = 0; child->mp_dev = 0; child->mp_ctime = 0; #endif r = sys_trace(req, child->mp_endpoint, m_in.PMTRACE_ADDR, &m_in.data); if (r != OK) return(r); mp->mp_reply.reply_trace = m_in.data; return(OK); } /* All the other calls are made by the tracing process to control execution * of the child. For all these calls, the child must be stopped. */ if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH); if (child->mp_flags & EXITING) return(ESRCH); if (child->mp_tracer != who_p) return(ESRCH); if (!(child->mp_flags & STOPPED)) return(EBUSY); switch (req) { case T_EXIT: /* exit */ child->mp_flags |= TRACE_EXIT; /* Defer the exit if the traced process has an VFS call pending. */ if (child->mp_flags & VFS_CALL) child->mp_exitstatus = (int) m_in.data; /* save for later */ else exit_proc(child, (int) m_in.data, FALSE /*dump_core*/); /* Do not reply to the caller until VFS has processed the exit * request. */ return(SUSPEND); case T_SETOPT: /* set trace options */ child->mp_trace_flags = m_in.data; mp->mp_reply.reply_trace = 0; return(OK); case T_GETRANGE: case T_SETRANGE: /* get/set range of values */ r = sys_datacopy(who_e, (vir_bytes) m_in.PMTRACE_ADDR, SELF, (vir_bytes) &pr, (phys_bytes) sizeof(pr)); if (r != OK) return(r); if (pr.pr_space != TS_INS && pr.pr_space != TS_DATA) return(EINVAL); if (pr.pr_size == 0 || pr.pr_size > LONG_MAX) return(EINVAL); seg = (pr.pr_space == TS_INS) ? T : D; if (req == T_GETRANGE) r = sys_vircopy(child->mp_endpoint, seg, (vir_bytes) pr.pr_addr, who_e, D, (vir_bytes) pr.pr_ptr, (phys_bytes) pr.pr_size); else r = sys_vircopy(who_e, D, (vir_bytes) pr.pr_ptr, child->mp_endpoint, seg, (vir_bytes) pr.pr_addr, (phys_bytes) pr.pr_size); if (r != OK) return(r); mp->mp_reply.reply_trace = 0; return(OK); case T_DETACH: /* detach from traced process */ if (m_in.data < 0 || m_in.data >= _NSIG) return(EINVAL); child->mp_tracer = NO_TRACER; /* Let all tracer-pending signals through the filter. */ for (i = 1; i < _NSIG; i++) { if (sigismember(&child->mp_sigtrace, i)) { (void) sigdelset(&child->mp_sigtrace, i); check_sig(child->mp_pid, i, FALSE /* ksig */); } } if (m_in.data > 0) { /* issue signal */ sig_proc(child, (int) m_in.data, TRUE /*trace*/, FALSE /* ksig */); } /* Resume the child as if nothing ever happened. */ child->mp_flags &= ~STOPPED; child->mp_trace_flags = 0; check_pending(child); break; case T_RESUME: case T_STEP: case T_SYSCALL: /* resume execution */ if (m_in.data < 0 || m_in.data >= _NSIG) return(EINVAL); if (m_in.data > 0) { /* issue signal */ sig_proc(child, (int) m_in.data, FALSE /*trace*/, FALSE /* ksig */); } /* If there are any other signals waiting to be delivered, * feign a successful resumption. */ for (i = 1; i < _NSIG; i++) { if (sigismember(&child->mp_sigtrace, i)) { mp->mp_reply.reply_trace = 0; return(OK); } } child->mp_flags &= ~STOPPED; check_pending(child); break; } r = sys_trace(req, child->mp_endpoint, m_in.PMTRACE_ADDR, &m_in.data); if (r != OK) return(r); mp->mp_reply.reply_trace = m_in.data; return(OK); }
/*===========================================================================* * process_ksig * *===========================================================================*/ int process_ksig(endpoint_t proc_nr_e, int signo) { register struct mproc *rmp; int proc_nr; pid_t proc_id, id; if(pm_isokendpt(proc_nr_e, &proc_nr) != OK || proc_nr < 0) { printf("PM: process_ksig: %d?? not ok\n", proc_nr_e); return EDEADEPT; /* process is gone. */ } rmp = &mproc[proc_nr]; if ((rmp->mp_flags & (IN_USE | EXITING)) != IN_USE) { #if 0 printf("PM: process_ksig: %d?? exiting / not in use\n", proc_nr_e); #endif return EDEADEPT; /* process is gone. */ } proc_id = rmp->mp_pid; mp = &mproc[0]; /* pretend signals are from PM */ mp->mp_procgrp = rmp->mp_procgrp; /* get process group right */ /* For SIGVTALRM and SIGPROF, see if we need to restart a * virtual timer. For SIGINT, SIGWINCH and SIGQUIT, use proc_id 0 * to indicate a broadcast to the recipient's process group. For * SIGKILL, use proc_id -1 to indicate a systemwide broadcast. */ switch (signo) { case SIGINT: case SIGQUIT: case SIGWINCH: id = 0; break; /* broadcast to process group */ case SIGVTALRM: case SIGPROF: check_vtimer(proc_nr, signo); /* fall-through */ default: id = proc_id; break; } check_sig(id, signo, TRUE /* ksig */); /* If SIGSNDELAY is set, an earlier sys_stop() failed because the process was * still sending, and the kernel hereby tells us that the process is now done * with that. We can now try to resume what we planned to do in the first * place: set up a signal handler. However, the process's message may have * been a call to PM, in which case the process may have changed any of its * signal settings. The process may also have forked, exited etcetera. */ if (signo == SIGSNDELAY && (rmp->mp_flags & DELAY_CALL)) { rmp->mp_flags &= ~DELAY_CALL; /* * If the VFS_CALL flag is still set we have a process which is stopped * and we only need to wait for a reply from VFS. We are going to check * the pending signal then */ if (rmp->mp_flags & VFS_CALL) return OK; if (rmp->mp_flags & PM_SIG_PENDING) panic("process_ksig: bad process state"); /* Process as many normal signals as possible. */ check_pending(rmp); if (rmp->mp_flags & DELAY_CALL) panic("process_ksig: multiple delay calls?"); } /* See if the process is still alive */ if ((mproc[proc_nr].mp_flags & (IN_USE | EXITING)) == IN_USE) { return OK; /* signal has been delivered */ } else { return EDEADEPT; /* process is gone */ } }
/*===========================================================================* * do_kill * *===========================================================================*/ int do_kill() { /* Perform the kill(pid, signo) system call. */ return check_sig(m_in.pid, m_in.sig_nr, FALSE /* ksig */); }
/*===========================================================================* * process_ksig * *===========================================================================*/ int process_ksig(endpoint_t proc_nr_e, int signo) { register struct mproc *rmp; int proc_nr; pid_t proc_id, id; if(pm_isokendpt(proc_nr_e, &proc_nr) != OK) { printf("PM: process_ksig: %d?? not ok\n", proc_nr_e); return EDEADEPT; /* process is gone. */ } rmp = &mproc[proc_nr]; if ((rmp->mp_flags & (IN_USE | EXITING)) != IN_USE) { #if 0 printf("PM: process_ksig: %d?? exiting / not in use\n", proc_nr_e); #endif return EDEADEPT; /* process is gone. */ } proc_id = rmp->mp_pid; mp = &mproc[0]; /* pretend signals are from PM */ mp->mp_procgrp = rmp->mp_procgrp; /* get process group right */ /* For SIGVTALRM and SIGPROF, see if we need to restart a * virtual timer. For SIGINT, SIGINFO, SIGWINCH and SIGQUIT, use proc_id 0 * to indicate a broadcast to the recipient's process group. For * SIGKILL, use proc_id -1 to indicate a systemwide broadcast. */ switch (signo) { case SIGINT: case SIGQUIT: case SIGWINCH: case SIGINFO: id = 0; break; /* broadcast to process group */ case SIGVTALRM: case SIGPROF: check_vtimer(proc_nr, signo); /* fall-through */ default: id = proc_id; break; } check_sig(id, signo, TRUE /* ksig */); /* If SIGSNDELAY is set, an earlier sys_stop() failed because the process was * still sending, and the kernel hereby tells us that the process is now done * with that. We can now try to resume what we planned to do in the first * place: set up a signal handler. However, the process's message may have * been a call to PM, in which case the process may have changed any of its * signal settings. The process may also have forked, exited etcetera. */ if (signo == SIGSNDELAY && (rmp->mp_flags & DELAY_CALL)) { /* When getting SIGSNDELAY, the process is stopped at least until the * receipt of the SIGSNDELAY signal is acknowledged to the kernel. The * process is not stopped on PROC_STOP in the kernel. However, now that * there is no longer a delay call, stop_proc() is guaranteed to * succeed immediately. */ rmp->mp_flags &= ~DELAY_CALL; assert(!(rmp->mp_flags & PROC_STOPPED)); /* If the delay call was to PM, it may have resulted in a VFS call. In * that case, we must wait with further signal processing until VFS has * replied. Stop the process. */ if (rmp->mp_flags & VFS_CALL) { stop_proc(rmp, FALSE /*may_delay*/); return OK; } /* Process as many normal signals as possible. */ check_pending(rmp); assert(!(rmp->mp_flags & DELAY_CALL)); } /* See if the process is still alive */ if ((mproc[proc_nr].mp_flags & (IN_USE | EXITING)) == IN_USE) { return OK; /* signal has been delivered */ } else { return EDEADEPT; /* process is gone */ } }
/*===========================================================================* * do_kill * *===========================================================================*/ int do_kill(void) { /* Perform the kill(pid, signo) system call. */ return check_sig(m_in.m_lc_pm_sig.pid, m_in.m_lc_pm_sig.nr, FALSE /* ksig */); }
/*===========================================================================* * do_exec * *===========================================================================*/ PUBLIC int do_exec() { /* Perform the execve(name, argv, envp) call. The user library builds a * complete stack image, including pointers, args, environ, etc. The stack * is copied to a buffer inside PM, and then to the new core image. */ /* * 执行 execve(name, argv, envp) 调用. 用户库函数构造了一个完整的栈映像, * 包括指针, 命令行参数, 环境变量等等. 栈先复制到 PM 内的一个缓冲区中, * 再复制给新的堆栈映像. */ register struct mproc *rmp; struct mproc *sh_mp; int m, r, fd, ft, sn; static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ static char name_buf[PATH_MAX]; /* the name of the file to exec */ char *new_sp, *name, *basename; vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp; phys_bytes tot_bytes; /* total space for program, including gap */ long sym_bytes; vir_clicks sc; struct stat s_buf[2], *s_p; vir_bytes pc; /* Do some validity checks. */ rmp = mp; // rmp = mp = 当前进程的 struct mproc 结构 stk_bytes = (vir_bytes) m_in.stack_bytes; if (stk_bytes > ARG_MAX) return(ENOMEM); /* stack too big */ if (m_in.exec_len <= 0 || m_in.exec_len > PATH_MAX) return(EINVAL); /* Get the exec file name and see if the file is executable. */ src = (vir_bytes) m_in.exec_name; dst = (vir_bytes) name_buf; // 将可执行文件的路径名从主调进程复制到 PM 的 name_buf[] 中. r = sys_datacopy(who, (vir_bytes) src, PM_PROC_NR, (vir_bytes) dst, (phys_bytes) m_in.exec_len); if (r != OK) return(r); /* file name not in user data segment */ /* Fetch the stack from the user before destroying the old core image. */ // 将主调进程的栈复制到 mbuf[], 在毁掉旧的核心映像之前 src = (vir_bytes) m_in.stack_ptr; dst = (vir_bytes) mbuf; r = sys_datacopy(who, (vir_bytes) src, PM_PROC_NR, (vir_bytes) dst, (phys_bytes)stk_bytes); /* can't fetch stack (e.g. bad virtual addr) */ if (r != OK) return(EACCES); r = 0; /* r = 0 (first attempt), or 1 (interpreted script) */ name = name_buf; /* name of file to exec. */ do { s_p = &s_buf[r]; // 切换到主调进程的当前工作目录 tell_fs(CHDIR, who, FALSE, 0); /* switch to the user's FS environ */ // 检查文件是否可执行, 如果可执行, 返回文件描述符 fd = allowed(name, s_p, X_BIT); /* is file executable? */ if (fd < 0) return(fd); /* file was not executable */ /* Read the file header and extract the segment sizes. */ sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT; // 读取文件头部数据, 并赋值给相应参数 m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes, &tot_bytes, &sym_bytes, sc, &pc); if (m != ESCRIPT || ++r > 1) break; } while ((name = patch_stack(fd, mbuf, &stk_bytes, name_buf)) != NULL); if (m < 0) { close(fd); /* something wrong with header */ return(stk_bytes > ARG_MAX ? ENOMEM : ENOEXEC); } /* Can the process' text be shared with that of one already running? */ sh_mp = find_share(rmp, s_p->st_ino, s_p->st_dev, s_p->st_ctime); /* Allocate new memory and release old memory. Fix map and tell kernel. */ r = new_mem(sh_mp, text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes); if (r != OK) { close(fd); /* insufficient core or program too big */ return(r); } /* Save file identification to allow it to be shared. */ rmp->mp_ino = s_p->st_ino; rmp->mp_dev = s_p->st_dev; rmp->mp_ctime = s_p->st_ctime; /* Patch up stack and copy it from PM to new core image. */ vsp = (vir_bytes) rmp->mp_seg[S].mem_vir << CLICK_SHIFT; vsp += (vir_bytes) rmp->mp_seg[S].mem_len << CLICK_SHIFT; vsp -= stk_bytes; patch_ptr(mbuf, vsp); src = (vir_bytes) mbuf; r = sys_datacopy(PM_PROC_NR, (vir_bytes) src, who, (vir_bytes) vsp, (phys_bytes)stk_bytes); if (r != OK) panic(__FILE__,"do_exec stack copy err on", who); /* Read in text and data segments. */ if (sh_mp != NULL) { lseek(fd, (off_t) text_bytes, SEEK_CUR); /* shared: skip text */ } else { rw_seg(0, fd, who, T, text_bytes); } rw_seg(0, fd, who, D, data_bytes); close(fd); /* don't need exec file any more */ /* Take care of setuid/setgid bits. */ if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */ if (s_buf[0].st_mode & I_SET_UID_BIT) { rmp->mp_effuid = s_buf[0].st_uid; tell_fs(SETUID,who, (int)rmp->mp_realuid, (int)rmp->mp_effuid); } if (s_buf[0].st_mode & I_SET_GID_BIT) { rmp->mp_effgid = s_buf[0].st_gid; tell_fs(SETGID,who, (int)rmp->mp_realgid, (int)rmp->mp_effgid); } } /* Save offset to initial argc (for ps) */ rmp->mp_procargs = vsp; /* Fix 'mproc' fields, tell kernel that exec is done, reset caught sigs. */ for (sn = 1; sn <= _NSIG; sn++) { if (sigismember(&rmp->mp_catch, sn)) { sigdelset(&rmp->mp_catch, sn); rmp->mp_sigact[sn].sa_handler = SIG_DFL; sigemptyset(&rmp->mp_sigact[sn].sa_mask); } } rmp->mp_flags &= ~SEPARATE; /* turn off SEPARATE bit */ rmp->mp_flags |= ft; /* turn it on for separate I & D files */ new_sp = (char *) vsp; tell_fs(EXEC, who, 0, 0); /* allow FS to handle FD_CLOEXEC files */ /* System will save command line for debugging, ps(1) output, etc. */ basename = strrchr(name, '/'); if (basename == NULL) basename = name; else basename++; strncpy(rmp->mp_name, basename, PROC_NAME_LEN-1); rmp->mp_name[PROC_NAME_LEN] = '\0'; sys_exec(who, new_sp, basename, pc); /* Cause a signal if this process is traced. */ if (rmp->mp_flags & TRACED) check_sig(rmp->mp_pid, SIGTRAP); return(SUSPEND); /* no reply, new program just runs */ }
inline bool check_sig(RDPDrawable & data, char * message, const char * shasig) { return check_sig(data.data(), data.height(), data.rowsize(), message, shasig); }
int main(int argc, char *argv[]) { char *filename = argc < 2 ? "fat.ima" : argv[1]; FILE *f = fopen(filename, "r"); if(f == NULL) { errorf("couldn't open file '%s'\n", filename); return 1; } if(!check_sig(f)) return 1; struct BPB_t bpb; read_bytes(f, 0x0, &bpb, sizeof(bpb)); if(bpb.BytsPerSec != 512 || bpb.NumFATs != 2) return 1; greenf( "FAT addr: 0x%x\n" "Root addr: 0x%x\n" "Data addr: 0x%x\n", BPB_FAT_addr(&bpb), BPB_Root_addr(&bpb), BPB_Data_addr(&bpb) ); for(int i = 0; i < bpb.RootEntCnt; i++) { struct dir_t dir; uint32_t offset = BPB_Root_addr(&bpb) + i*32; read_bytes(f, offset, &dir, sizeof(dir)); if(dir.Name[0] == 0) { break; } else if(dir.Name[0] == 0xE5) { printf("<unused space>\n"); continue; } purplef("\n%.*s", (int)(sizeof(dir.Name)/sizeof(char)), dir.Name); const char *type; if(dir.Attr & DIR_ATTR_LFN) { purplef("<LONG FILENAME>\n"); } else if(dir.Attr & DIR_ATTR_DIRECTORY) { purplef("<DIRECTORY>\n"); } else { purplef("<FILE>\n"); //if(i == 0xF) // print_cluster(f, &bpb, &dir); //else printf("<omitting print>\n"); } } fclose(f); return 0; }