R_API int r_socket_spawn (RSocket *s, const char *cmd, unsigned int timeout) { // XXX TODO: dont use sockets, we can achieve the same with pipes const int port = 2000 + r_num_rand (2000); int childPid = r_sys_fork(); if (childPid == 0) { char *a = r_str_replace (strdup (cmd), "\\", "\\\\", true); r_sys_cmdf ("rarun2 system=\"%s\" listen=%d", a, port); free (a); #if 0 // TODO: use the api char *profile = r_str_newf ( "system=%s\n" "listen=%d\n", cmd, port); RRunProfile *rp = r_run_new (profile); r_run_start (rp); r_run_free (rp); free (profile); #endif eprintf ("r_socket_spawn: %s is dead\n", cmd); exit (0); } r_sys_sleep (1); r_sys_usleep (timeout); char aport[32]; sprintf (aport, "%d", port); // redirect stdin/stdout/stderr return r_socket_connect (s, "127.0.0.1", aport, R_SOCKET_PROTO_TCP, 2000); }
R_API struct r_socket_proc_t *r_socket_proc_open(char* const argv[]) { #if __UNIX__ && LIBC_HAVE_FORK RSocketProc *sp = R_NEW (RSocketProc); #ifdef O_CLOEXEC const int flags = O_CLOEXEC; //O_NONBLOCK|O_CLOEXEC; #else const int flags = 0; //O_NONBLOCK|O_CLOEXEC; #endif if (!sp) { return NULL; } if (pipe (sp->fd0)==-1) { perror ("pipe"); goto error; } if (fcntl (sp->fd0[0], flags) < 0) { goto error; } if (fcntl (sp->fd0[1], flags) < 0) { goto error; } if (pipe (sp->fd1)==-1) { perror ("pipe"); goto error; } if (fcntl (sp->fd1[0], flags) < 0) { goto error; } if (fcntl (sp->fd1[1], flags) < 0) { goto error; } sp->pid = r_sys_fork (); switch (sp->pid) { case 0: close (0); dup2 (sp->fd0[0], 0); close (1); dup2 (sp->fd1[1], 1); execv (argv[0], argv); exit (1); break; case -1: perror ("fork"); r_socket_proc_close (sp); goto error; //r_socket_block_time (sp, false, 0); } return sp; error: free (sp); return NULL; #else return NULL; #endif }
R_API int r_sys_run(const ut8 *buf, int len) { const int sz = 4096; int pdelta, ret, (*cb)(); #if USE_FORK int st, pid; #endif // TODO: define R_SYS_ALIGN_FORWARD in r_util.h ut8 *ptr, *p = malloc ((sz + len) << 1); ptr = p; pdelta = ((size_t)(p)) & (4096 - 1); if (pdelta) { ptr += (4096 - pdelta); } if (!ptr || !buf) { eprintf ("r_sys_run: Cannot run empty buffer\n"); free (p); return false; } memcpy (ptr, buf, len); r_mem_protect (ptr, sz, "rx"); //r_mem_protect (ptr, sz, "rwx"); // try, ignore if fail cb = (int (*)())ptr; #if USE_FORK #if __UNIX__ || __CYGWIN__ && !defined(MINGW32) pid = r_sys_fork (); #else pid = -1; #endif if (pid < 0) { return cb (); } if (!pid) { ret = cb (); exit (ret); return ret; } st = 0; waitpid (pid, &st, 0); if (WIFSIGNALED (st)) { int num = WTERMSIG(st); eprintf ("Got signal %d\n", num); ret = num; } else { ret = WEXITSTATUS (st); } #else ret = (*cb) (); #endif free (p); return ret; }
R_API int r_sys_cmdbg (const char *str) { #if __UNIX__ int ret, pid = r_sys_fork (); if (pid == -1) return -1; if (pid) return pid; ret = r_sandbox_system (str, 0); eprintf ("{exit: %d, pid: %d, cmd: \"%s\"}", ret, pid, str); exit (0); return -1; #else #warning r_sys_cmdbg is not implemented for this platform return -1; #endif }
R_API bool r_socket_spawn(RSocket *s, const char *cmd, unsigned int timeout) { // XXX TODO: dont use sockets, we can achieve the same with pipes const int port = 2000 + r_num_rand (2000); int childPid = r_sys_fork (); if (childPid == 0) { char *a = r_str_replace (strdup (cmd), "\\", "\\\\", true); int res = r_sys_cmdf ("rarun2 system=\"%s\" listen=%d", a, port); free (a); #if 0 // TODO: use the api char *profile = r_str_newf ( "system=%s\n" "listen=%d\n", cmd, port); RRunProfile *rp = r_run_new (profile); r_run_start (rp); r_run_free (rp); free (profile); #endif if (res != 0) { eprintf ("r_socket_spawn: rarun2 failed\n"); exit (1); } eprintf ("r_socket_spawn: %s is dead\n", cmd); exit (0); } r_sys_sleep (1); r_sys_usleep (timeout); char aport[32]; sprintf (aport, "%d", port); // redirect stdin/stdout/stderr bool sock = r_socket_connect (s, "127.0.0.1", aport, R_SOCKET_PROTO_TCP, 2000); if (!sock) { return false; } #if __UNIX__ r_sys_sleep (4); r_sys_usleep (timeout); int status = 0; int ret = waitpid (childPid, &status, WNOHANG); if (ret != 0) { r_socket_close (s); return false; } #endif return true; }
R_API int r_sys_cmdbg (const char *str) { #if __UNIX__ || __CYGWIN && !defined(MINGW32) int ret, pid = r_sys_fork (); if (pid == -1) { return -1; } if (pid) { return pid; } ret = r_sandbox_system (str, 0); eprintf ("{exit: %d, pid: %d, cmd: \"%s\"}", ret, pid, str); exit (0); return -1; #else #ifdef _MSC_VER #pragma message ("r_sys_cmdbg is not implemented for this platform") #else #warning r_sys_cmdbg is not implemented for this platform #endif return -1; #endif }
// __UNIX__ (not windows) static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) { char **argv; int ret, status, pid = r_sys_fork (); switch (pid) { case -1: perror ("fork_and_ptraceme"); break; case 0: #if __APPLE__ signal (SIGTRAP, SIG_IGN); //NEED BY STEP #endif #if __APPLE__ || __BSD__ /* we can probably remove this #if..as long as PT_TRACE_ME is redefined for OSX in r_debug.h */ signal (SIGABRT, inferior_abort_handler); if (ptrace (PT_TRACE_ME, 0, 0, 0) != 0) { #else if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) != 0) { #endif r_sys_perror ("ptrace-traceme"); exit (MAGIC_EXIT); } if (io->runprofile && *(io->runprofile)) { char *expr = NULL; int i; RRunProfile *rp = r_run_new (NULL); argv = r_str_argv (cmd, NULL); for (i=0; argv[i]; i++) { rp->_args[i] = argv[i]; } rp->_args[i] = NULL; rp->_program = argv[0]; if (io->runprofile && *io->runprofile) { if (!r_run_parsefile (rp, io->runprofile)) { eprintf ("Can't find profile '%s'\n", io->runprofile); exit (MAGIC_EXIT); } } if (bits==64) r_run_parseline (rp, expr=strdup ("bits=64")); else if (bits==32) r_run_parseline (rp, expr=strdup ("bits=32")); free (expr); r_run_start (rp); r_run_free (rp); // double free wtf // r_str_argv_free (argv); exit (1); } else { // TODO: Add support to redirect filedescriptors // TODO: Configure process environment char *_cmd = strdup (cmd); argv = r_str_argv (_cmd, NULL); if (!argv) { free (_cmd); return -1; } #if __APPLE__ { #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 ut32 ps_flags = POSIX_SPAWN_SETEXEC; posix_spawnattr_t attr = {0}; size_t copied = 1; cpu_type_t cpu; pid_t p = -1; int ret; int useASLR = 1; posix_spawnattr_init (&attr); if (useASLR != -1) { if (useASLR) { // enable aslr if not enabled? really? } else { ps_flags |= _POSIX_SPAWN_DISABLE_ASLR; } } (void)posix_spawnattr_setflags (&attr, ps_flags); #if __i386__ || __x86_64__ cpu = CPU_TYPE_I386; if (bits == 64) cpu |= CPU_ARCH_ABI64; #else cpu = CPU_TYPE_ANY; #endif posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied); ret = posix_spawnp (&p, argv[0], NULL, &attr, argv, NULL); switch (ret) { case 0: eprintf ("Success\n"); break; case 22: eprintf ("posix_spawnp: Invalid argument\n"); break; case 86: eprintf ("Unsupported architecture\n"); break; default: eprintf ("posix_spawnp: unknown error %d\n", ret); perror ("posix_spawnp"); break; } /* only required if no SETEXEC called if (p != -1) wait (p); */ exit (MAGIC_EXIT); /* error */ } #else if (argv && *argv) { execvp (argv[0], argv); } else { eprintf ("Invalid execvp\n"); } #endif free (_cmd); } perror ("fork_and_attach: execv"); //printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename); exit (MAGIC_EXIT); /* error */ return 0; // invalid pid // if exit is overriden.. :) default: /* XXX: clean this dirty code */ do { ret = wait (&status); if (ret == -1) return -1; if (ret != pid) eprintf ("Wait event received by different pid %d\n", ret); } while (ret!=pid); if (WIFSTOPPED (status)) eprintf ("Process with PID %d started...\n", (int)pid); if (WEXITSTATUS (status) == MAGIC_EXIT) pid = -1; // XXX kill (pid, SIGSTOP); break; } eprintf ("PID = %d\n", pid); return pid; } #endif static int __plugin_open(RIO *io, const char *file, ut8 many) { if (!strncmp (file, "dbg://", 6) && file[6]) return R_TRUE; return R_FALSE; } static RIODesc *__open(RIO *io, const char *file, int rw, int mode) { char uri[128]; if (__plugin_open (io, file, 0)) { const char *pidfile = file + 6; char *endptr; int pid = (int)strtol (pidfile, &endptr, 10); if (endptr == pidfile || pid < 0) pid = -1; if (pid == -1) { pid = fork_and_ptraceme (io, io->bits, file+6); if (pid == -1) return NULL; #if __WINDOWS__ sprintf (uri, "w32dbg://%d", pid); #elif __APPLE__ sprintf (uri, "mach://%d", pid); #else // TODO: use io_procpid here? faster or what? sprintf (uri, "ptrace://%d", pid); #endif my_io_redirect (io, file, uri); } else { sprintf (uri, "attach://%d", pid); my_io_redirect (io, file, uri); } return NULL; } my_io_redirect (io, file, NULL); return NULL; }
R_API int r_sys_cmd_str_full(const char *cmd, const char *input, char **output, int *len, char **sterr) { char buffer[1024], *outputptr = NULL; char *inputptr = (char *)input; int pid, bytes = 0, status; int sh_in[2], sh_out[2], sh_err[2]; if (len) *len = 0; if (pipe (sh_in)) return R_FALSE; if (output) { if (pipe (sh_out)) { close (sh_in[0]); close (sh_in[1]); close (sh_out[0]); close (sh_out[1]); return R_FALSE; } } if (pipe (sh_err)) { close (sh_in[0]); close (sh_in[1]); return R_FALSE; } switch ((pid = r_sys_fork ())) { case -1: return R_FALSE; case 0: dup2 (sh_in[0], 0); close (sh_in[0]); close (sh_in[1]); if (output) { dup2 (sh_out[1], 1); close (sh_out[0]); close (sh_out[1]); } if (sterr) dup2 (sh_err[1], 2); else close (2); close (sh_err[0]); close (sh_err[1]); exit (r_sandbox_system (cmd, 0)); default: outputptr = strdup (""); if (!outputptr) return R_FALSE; if (sterr) { *sterr = strdup (""); if (!*sterr) { free (outputptr); return R_FALSE; } } if (output) close (sh_out[1]); close (sh_err[1]); close (sh_in[0]); if (!inputptr || !*inputptr) close (sh_in[1]); // we should handle broken pipes somehow better signal (SIGPIPE, SIG_IGN); for (;;) { fd_set rfds, wfds; int nfd; FD_ZERO (&rfds); FD_ZERO (&wfds); if (output) FD_SET (sh_out[0], &rfds); if (sterr) FD_SET (sh_err[0], &rfds); if (inputptr && *inputptr) FD_SET (sh_in[1], &wfds); memset (buffer, 0, sizeof (buffer)); nfd = select (sh_err[0] + 1, &rfds, &wfds, NULL, NULL); if (nfd < 0) break; if (output && FD_ISSET (sh_out[0], &rfds)) { if ((bytes = read (sh_out[0], buffer, sizeof (buffer)-1)) == 0) break; buffer[sizeof(buffer) - 1] = '\0'; if (len) *len += bytes; outputptr = r_str_concat (outputptr, buffer); } else if (FD_ISSET (sh_err[0], &rfds) && sterr) { if (read (sh_err[0], buffer, sizeof (buffer)-1) == 0) break; buffer[sizeof(buffer) - 1] = '\0'; *sterr = r_str_concat (*sterr, buffer); } else if (FD_ISSET (sh_in[1], &wfds) && inputptr && *inputptr) { int inputptr_len = strlen (inputptr); bytes = write (sh_in[1], inputptr, inputptr_len); if (bytes != inputptr_len) { break; } inputptr += bytes; if (!*inputptr) { close (sh_in[1]); /* If neither stdout nor stderr should be captured, * abort now - nothing more to do for select(). */ if (!output && !sterr) break; } } } if (output) close (sh_out[0]); close (sh_err[0]); close (sh_in[1]); waitpid (pid, &status, 0); if (status != 0) { char *escmd = r_str_escape (cmd); eprintf ("%s: failed command '%s'\n", __func__, escmd); free (escmd); return R_FALSE; } if (output) *output = outputptr; else free (outputptr); return R_TRUE; } return R_FALSE; }
static int lang_pipe_run(RLang *lang, const char *code, int len) { #if __UNIX__ int safe_in = dup (0); int child, ret; int input[2]; int output[2]; pipe (input); pipe (output); env ("R2PIPE_IN", input[0]); env ("R2PIPE_OUT", output[1]); child = r_sys_fork (); if (child == -1) { /* error */ } else if (child == 0) { /* children */ #if 1 r_sandbox_system (code, 1); #else /* DEMO */ char buf[1024]; /* kid stuff here */ while (1) { write (output[1], "pd 3\n", 6); res = read (input[0], buf, sizeof (buf)-1); if (res <1) break; printf ("---> ((%s))\n", buf); sleep (1); } #endif write (input[1], "", 1); close (input[0]); close (input[1]); close (output[0]); close (output[1]); exit (0); return R_FALSE; } else { /* parent */ char *res, buf[1024]; /* Close pipe ends not required in the parent */ close(output[1]); close(input[0]); r_cons_break (NULL, NULL); for (;;) { if (r_cons_singleton ()->breaked) { break; } memset (buf, 0, sizeof (buf)); ret = read (output[0], buf, sizeof (buf)-1); if (ret <1 || !buf[0]) { break; } buf[sizeof (buf)-1] = 0; res = lang->cmd_str ((RCore*)lang->user, buf); //eprintf ("%d %s\n", ret, buf); if (res) { write (input[1], res, strlen (res)+1); free (res); } else { eprintf ("r_lang_pipe: NULL reply for (%s)\n", buf); write (input[1], "", 1); // NULL byte } } /* workaround to avoid stdin closed */ if (safe_in != -1) close (safe_in); safe_in = open (ttyname(0), O_RDONLY); if (safe_in != -1) { dup2 (safe_in, 0); } else eprintf ("Cannot open ttyname(0) %s\n", ttyname(0)); r_cons_break_end (); } close (input[0]); close (input[1]); close (output[0]); close (output[1]); if (safe_in != -1) close (safe_in); waitpid (child, NULL, 0); return R_TRUE; #else #if __WINDOWS__ HANDLE hPipeInOut = NULL; HANDLE hproc=NULL; DWORD dwRead, dwWritten; CHAR buf[1024]; BOOL bSuccess = FALSE; int res=0; sprintf(buf,"R2PIPE_IN%x",_getpid()); SetEnvironmentVariable("R2PIPE_PATH",buf); sprintf(buf,"\\\\.\\pipe\\R2PIPE_IN%x",_getpid()); hPipeInOut = CreateNamedPipe(buf, PIPE_ACCESS_DUPLEX,PIPE_TYPE_MESSAGE | \ PIPE_READMODE_MESSAGE | \ PIPE_NOWAIT,PIPE_UNLIMITED_INSTANCES, sizeof (buf), sizeof (buf), 0, NULL); hproc=myCreateChildProcess (code); if (hproc==NULL) { //eprintf("Error spawning process: %s\n",code); return R_TRUE; } r_cons_break (NULL, NULL); for (;;) { res = ConnectNamedPipe(hPipeInOut, NULL); if (GetLastError()==ERROR_PIPE_CONNECTED) { //eprintf("new client\n"); break; } if (r_cons_singleton ()->breaked) { TerminateProcess(hproc,0); break; } } for (;;) { if (r_cons_singleton ()->breaked) { TerminateProcess(hproc,0); break; } memset (buf, 0, sizeof (buf)); bSuccess = ReadFile( hPipeInOut, buf, sizeof (buf), &dwRead, NULL); if (dwRead!=0) { buf[sizeof(buf)-1] = 0; res = lang->cmd_str ((RCore*)lang->user, buf); if (res) { WriteFile(hPipeInOut, res, strlen (res)+1, &dwWritten, NULL); free (res); } else { WriteFile(hPipeInOut, "", 1, &dwWritten, NULL); } } } CloseHandle(hPipeInOut); r_cons_break_end (); return R_TRUE; #endif #endif }
R_API int r_run_config_env(RRunProfile *p) { int ret; if (!p->_program && !p->_system && !p->_runlib) { printf ("No program, system or runlib rule defined\n"); return 1; } // when IO is redirected to a process, handle them together if (handle_redirection (p->_stdio, true, true, false) != 0) { return 1; } if (handle_redirection (p->_stdin, true, false, false) != 0) { return 1; } if (handle_redirection (p->_stdout, false, true, false) != 0) { return 1; } if (handle_redirection (p->_stderr, false, false, true) != 0) { return 1; } if (p->_aslr != -1) { setASLR (p, p->_aslr); } #if __UNIX__ set_limit (p->_docore, RLIMIT_CORE, RLIM_INFINITY); if (p->_maxfd) { set_limit (p->_maxfd, RLIMIT_NOFILE, p->_maxfd); } #ifdef RLIMIT_NPROC if (p->_maxproc) { set_limit (p->_maxproc, RLIMIT_NPROC, p->_maxproc); } #endif if (p->_maxstack) { set_limit (p->_maxstack, RLIMIT_STACK, p->_maxstack); } #else if (p->_docore || p->_maxfd || p->_maxproc || p->_maxstack) eprintf ("Warning: setrlimits not supported for this platform\n"); #endif if (p->_connect) { char *q = strchr (p->_connect, ':'); if (q) { RSocket *fd = r_socket_new (0); *q = 0; if (!r_socket_connect_tcp (fd, p->_connect, q+1, 30)) { eprintf ("Cannot connect\n"); return 1; } if (p->_pty) { if (redirect_socket_to_pty (fd) != 0) { eprintf ("socket redirection failed\n"); r_socket_free (fd); return 1; } } else { redirect_socket_to_stdio (fd); } } else { eprintf ("Invalid format for connect. missing ':'\n"); return 1; } } if (p->_listen) { RSocket *child, *fd = r_socket_new (0); bool is_child = false; if (!r_socket_listen (fd, p->_listen, NULL)) { eprintf ("rarun2: cannot listen\n"); r_socket_free (fd); return 1; } while (true) { child = r_socket_accept (fd); if (child) { is_child = true; if (p->_dofork && !p->_dodebug) { #ifdef _MSC_VER int child_pid = r_sys_fork (); #else pid_t child_pid = r_sys_fork (); #endif if (child_pid == -1) { eprintf("rarun2: cannot fork\n"); r_socket_free (child); r_socket_free (fd); return 1; } else if (child_pid != 0){ // parent code is_child = false; } } if (is_child) { r_socket_close_fd (fd); eprintf ("connected\n"); if (p->_pty) { if (redirect_socket_to_pty (child) != 0) { eprintf ("socket redirection failed\n"); r_socket_free (child); r_socket_free (fd); return 1; } } else { redirect_socket_to_stdio (child); } break; } else { r_socket_close_fd (child); } } } if (!is_child) { r_socket_free (child); } r_socket_free (fd); } if (p->_r2sleep != 0) { r_sys_sleep (p->_r2sleep); } #if __UNIX__ if (p->_chroot) { if (chdir (p->_chroot) == -1) { eprintf ("Cannot chdir to chroot in %s\n", p->_chroot); return 1; } else { if (chroot (".") == -1) { eprintf ("Cannot chroot to %s\n", p->_chroot); return 1; } else { // Silenting pedantic meson flags... if (chdir ("/") == -1) { eprintf ("Cannot chdir to /\n"); return 1; } if (p->_chgdir) { if (chdir (p->_chgdir) == -1) { eprintf ("Cannot chdir after chroot to %s\n", p->_chgdir); return 1; } } } } } else if (p->_chgdir) { if (chdir (p->_chgdir) == -1) { eprintf ("Cannot chdir after chroot to %s\n", p->_chgdir); return 1; } } #else if (p->_chgdir) { ret = chdir (p->_chgdir); if (ret < 0) { return 1; } } if (p->_chroot) { ret = chdir (p->_chroot); if (ret < 0) { return 1; } } #endif #if __UNIX__ if (p->_setuid) { ret = setgroups (0, NULL); if (ret < 0) { return 1; } ret = setuid (atoi (p->_setuid)); if (ret < 0) { return 1; } } if (p->_seteuid) { ret = seteuid (atoi (p->_seteuid)); if (ret < 0) { return 1; } } if (p->_setgid) { ret = setgid (atoi (p->_setgid)); if (ret < 0) { return 1; } } if (p->_input) { char *inp; int f2[2]; if (pipe (f2) != -1) { close (0); dup2 (f2[0], 0); } else { eprintf ("[ERROR] rarun2: Cannot create pipe\n"); return 1; } inp = getstr (p->_input); if (inp) { size_t inpl = strlen (inp); if (write (f2[1], inp, inpl) != inpl) { eprintf ("[ERROR] rarun2: Cannot write to the pipe\n"); } close (f2[1]); free (inp); } else { eprintf ("Invalid input\n"); } } #endif if (p->_r2preload) { if (p->_preload) { eprintf ("WARNING: Only one library can be opened at a time\n"); } p->_preload = R2_LIBDIR"/libr2."R_LIB_EXT; } if (p->_libpath) { #if __WINDOWS__ eprintf ("rarun2: libpath unsupported for this platform\n"); #elif __HAIKU__ r_sys_setenv ("LIBRARY_PATH", p->_libpath); #elif __APPLE__ r_sys_setenv ("DYLD_LIBRARY_PATH", p->_libpath); #else r_sys_setenv ("LD_LIBRARY_PATH", p->_libpath); #endif } if (p->_preload) { #if __APPLE__ // 10.6 #ifndef __MAC_10_7 r_sys_setenv ("DYLD_PRELOAD", p->_preload); #endif r_sys_setenv ("DYLD_INSERT_LIBRARIES", p->_preload); // 10.8 r_sys_setenv ("DYLD_FORCE_FLAT_NAMESPACE", "1"); #else r_sys_setenv ("LD_PRELOAD", p->_preload); #endif } if (p->_timeout) { #if __UNIX__ int mypid = getpid (); if (!r_sys_fork ()) { int use_signal = p->_timeout_sig; if (use_signal < 1) { use_signal = SIGKILL; } sleep (p->_timeout); if (!kill (mypid, 0)) { eprintf ("\nrarun2: Interrupted by timeout\n"); } kill (mypid, use_signal); exit (0); } #else eprintf ("timeout not supported for this platform\n"); #endif } return 0; }
static int redirect_socket_to_pty(RSocket *sock) { #if HAVE_PTY // directly duplicating the fds using dup2() creates problems // in case of interactive applications int fdm, fds; if (openpty (&fdm, &fds, NULL, NULL, NULL) == -1) { perror ("opening pty"); return -1; } pid_t child_pid = r_sys_fork (); if (child_pid == -1) { eprintf ("cannot fork\n"); close(fdm); close(fds); return -1; } if (child_pid == 0) { // child process close (fds); char *buff = NULL; int sockfd = sock->fd; int max_fd = fdm > sockfd ? fdm : sockfd; while (true) { fd_set readfds; FD_ZERO (&readfds); FD_SET (fdm, &readfds); FD_SET (sockfd, &readfds); if (select (max_fd + 1, &readfds, NULL, NULL, NULL) == -1) { perror ("select error"); break; } if (FD_ISSET (fdm, &readfds)) { if (fd_forward (fdm, sockfd, &buff) != 0) { break; } } if (FD_ISSET (sockfd, &readfds)) { if (fd_forward (sockfd, fdm, &buff) != 0) { break; } } } free (buff); close (fdm); r_socket_free (sock); exit (0); } // parent r_socket_close_fd (sock); login_tty (fds); close (fdm); // disable the echo on slave stdin struct termios t; tcgetattr (0, &t); cfmakeraw (&t); tcsetattr (0, TCSANOW, &t); return 0; #else // Fallback to socket to I/O redirection return redirect_socket_to_stdio (sock); #endif }
// __UNIX__ (not windows) static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) { bool runprofile = io->runprofile && *(io->runprofile); char **argv; #if __APPLE__ && !__POWERPC__ pid_t p = -1; posix_spawn_file_actions_t fileActions; ut32 ps_flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; sigset_t no_signals; sigset_t all_signals; size_t copied = 1; cpu_type_t cpu = CPU_TYPE_ANY; posix_spawnattr_t attr = {0}; posix_spawnattr_init (&attr); sigemptyset (&no_signals); sigfillset (&all_signals); posix_spawnattr_setsigmask (&attr, &no_signals); posix_spawnattr_setsigdefault (&attr, &all_signals); posix_spawn_file_actions_init (&fileActions); posix_spawn_file_actions_addinherit_np (&fileActions, STDIN_FILENO); posix_spawn_file_actions_addinherit_np (&fileActions, STDOUT_FILENO); posix_spawn_file_actions_addinherit_np (&fileActions, STDERR_FILENO); ps_flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; ps_flags |= POSIX_SPAWN_START_SUSPENDED; #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 if (!runprofile) { int ret, useASLR = io->aslr; char *_cmd = io->args ? r_str_appendf (strdup (cmd), " %s", io->args) : strdup (cmd); argv = r_str_argv (_cmd, NULL); if (!argv) { free (_cmd); return -1; } if (!*argv) { r_str_argv_free (argv); free (_cmd); eprintf ("Invalid execvp\n"); return -1; } if (useASLR != -1) { if (!useASLR) { ps_flags |= _POSIX_SPAWN_DISABLE_ASLR; } } (void)posix_spawnattr_setflags (&attr, ps_flags); #if __x86_64__ if (bits == 32) { cpu = CPU_TYPE_I386; // cpu |= CPU_ARCH_ABI64; } #endif posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied); { char *dst = r_file_readlink (argv[0]); if (dst) { argv[0] = dst; } } ret = posix_spawnp (&p, argv[0], NULL, &attr, argv, NULL); handle_posix_error (ret); posix_spawn_file_actions_destroy (&fileActions); r_str_argv_free (argv); free (_cmd); return p; } else { int ret; argv = r_str_argv (cmd, NULL); if (!argv) { posix_spawn_file_actions_destroy (&fileActions); return -1; } RRunProfile *rp = _get_run_profile (io, bits, argv); if (!rp) { r_str_argv_free (argv); posix_spawn_file_actions_destroy (&fileActions); return -1; } handle_posix_redirection (rp, &fileActions); if (rp->_args[0]) { if (!rp->_aslr) { ps_flags |= _POSIX_SPAWN_DISABLE_ASLR; } #if __x86_64__ if (rp->_bits == 32) { cpu = CPU_TYPE_I386; } #endif (void)posix_spawnattr_setflags (&attr, ps_flags); posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied); ret = posix_spawnp (&p, rp->_args[0], &fileActions, &attr, rp->_args, NULL); handle_posix_error (ret); } r_str_argv_free (argv); r_run_free (rp); posix_spawn_file_actions_destroy (&fileActions); return p; } posix_spawn_file_actions_destroy (&fileActions); return -1; #endif int ret, status, child_pid; child_pid = r_sys_fork (); switch (child_pid) { case -1: perror ("fork_and_ptraceme"); break; case 0: if (runprofile) { argv = r_str_argv (cmd, NULL); if (!argv) { exit(1); } RRunProfile *rp = _get_run_profile (io, bits, argv); if (!rp) { r_str_argv_free (argv); exit (1); } trace_me (); r_run_start (rp); r_run_free (rp); r_str_argv_free (argv); exit (1); } else { char *_cmd = io->args ? r_str_appendf (strdup (cmd), " %s", io->args) : strdup (cmd); trace_me (); argv = r_str_argv (_cmd, NULL); if (!argv) { free (_cmd); return -1; } if (argv && *argv) { int i; for (i = 3; i < 1024; i++) (void)close (i); execvp (argv[0], argv); } else { eprintf ("Invalid execvp\n"); } r_str_argv_free (argv); free (_cmd); } perror ("fork_and_attach: execv"); //printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename); exit (MAGIC_EXIT); /* error */ return 0; // invalid pid // if exit is overriden.. :) default: /* XXX: clean this dirty code */ do { ret = wait (&status); if (ret == -1) return -1; if (ret != child_pid) { eprintf ("Wait event received by " "different pid %d\n", ret); } } while (ret != child_pid); if (WIFSTOPPED (status)) { eprintf ("Process with PID %d started...\n", (int)child_pid); } if (WEXITSTATUS (status) == MAGIC_EXIT) { child_pid = -1; } // XXX kill (pid, SIGSTOP); break; } return child_pid; }
R_API int r_run_start(RRunProfile *p) { #if __APPLE__ posix_spawnattr_t attr = {0}; pid_t pid = -1; #endif int ret; if (!p->_program && !p->_system) { printf ("No program or system rule defined\n"); return 1; } // when IO is redirected to a process, handle them together if (handle_redirection (p->_stdio, true, true, false) != 0) { return 1; } if (handle_redirection (p->_stdin, true, false, false) != 0) { return 1; } if (handle_redirection (p->_stdout, false, true, false) != 0) { return 1; } if (handle_redirection (p->_stderr, false, false, true) != 0) { return 1; } if (p->_aslr != -1) setASLR (p->_aslr); #if __UNIX__ set_limit (p->_docore, RLIMIT_CORE, RLIM_INFINITY); if (p->_maxfd) set_limit (p->_maxfd, RLIMIT_NOFILE, p->_maxfd); #ifdef RLIMIT_NPROC if (p->_maxproc) set_limit (p->_maxproc, RLIMIT_NPROC, p->_maxproc); #endif if (p->_maxstack) set_limit (p->_maxstack, RLIMIT_STACK, p->_maxstack); #else if (p->_docore || p->_maxfd || p->_maxproc || p->_maxstack) eprintf ("Warning: setrlimits not supported for this platform\n"); #endif if (p->_connect) { char *q = strchr (p->_connect, ':'); if (q) { RSocket *fd = r_socket_new (0); *q = 0; if (!r_socket_connect_tcp (fd, p->_connect, q+1, 30)) { eprintf ("Cannot connect\n"); return 1; } eprintf ("connected\n"); close (0); close (1); close (2); dup2 (fd->fd, 0); dup2 (fd->fd, 1); dup2 (fd->fd, 2); } else { eprintf ("Invalid format for connect. missing ':'\n"); return 1; } } if (p->_listen) { RSocket *child, *fd = r_socket_new (0); if (!r_socket_listen (fd, p->_listen, NULL)) { eprintf ("rarun2: cannot listen\n"); r_socket_free (fd); return 1; } while (true) { child = r_socket_accept (fd); if (child) { int is_child = true; if (p->_dofork && !p->_dodebug) { pid_t child_pid = r_sys_fork (); if (child_pid == -1) { eprintf("rarun2: cannot fork\n"); r_socket_free (child); r_socket_free (fd); return 1; } else if (child_pid != 0){ // parent code is_child = false; } } if (is_child) { r_socket_close_fd (fd); eprintf ("connected\n"); close (0); close (1); close (2); dup2 (child->fd, 0); dup2 (child->fd, 1); dup2 (child->fd, 2); break; } else { r_socket_close_fd (child); } } } } if (p->_r2sleep != 0) { r_sys_sleep (p->_r2sleep); } if (p->_chgdir) { ret = chdir (p->_chgdir); if (ret < 0) return 1; } if (p->_chroot) { ret = chdir (p->_chroot); if (ret < 0) return 1; } #if __UNIX__ if (p->_chroot) { if (chroot (p->_chroot)) { eprintf ("rarun2: cannot chroot\n"); return 1; } chdir("/"); } if (p->_setuid) { ret = setgroups(0, NULL); if (ret < 0) return 1; ret = setuid (atoi (p->_setuid)); if (ret < 0) return 1; } if (p->_seteuid) { ret = seteuid (atoi (p->_seteuid)); if (ret < 0) return 1; } if (p->_setgid) { ret = setgid (atoi (p->_setgid)); if (ret < 0) return 1; } if (p->_input) { char *inp; int f2[2]; pipe (f2); close (0); dup2 (f2[0], 0); inp = getstr (p->_input); if (inp) { write (f2[1], inp, strlen (inp)); close (f2[1]); free (inp); } else { eprintf ("Invalid input\n"); } } #endif if (p->_r2preload) { if (p->_preload) { eprintf ("WARNING: Only one library can be opened at a time\n"); } p->_preload = R2_LIBDIR"/libr2."R_LIB_EXT; } if (p->_libpath) { #if __WINDOWS__ eprintf ("rarun2: libpath unsupported for this platform\n"); #elif __HAIKU__ r_sys_setenv ("LIBRARY_PATH", p->_libpath); #elif __APPLE__ r_sys_setenv ("DYLD_LIBRARY_PATH", p->_libpath); #else r_sys_setenv ("LD_LIBRARY_PATH", p->_libpath); #endif } if (p->_preload) { #if __APPLE__ // 10.6 r_sys_setenv ("DYLD_PRELOAD", p->_preload); r_sys_setenv ("DYLD_INSERT_LIBRARIES", p->_preload); // 10.8 r_sys_setenv ("DYLD_FORCE_FLAT_NAMESPACE", "1"); #else r_sys_setenv ("LD_PRELOAD", p->_preload); #endif } if (p->_timeout) { #if __UNIX__ int mypid = getpid (); if (!r_sys_fork ()) { sleep (p->_timeout); if (!kill (mypid, 0)) eprintf ("\nrarun2: Interrupted by timeout\n"); kill (mypid, SIGKILL); exit (0); } #else eprintf ("timeout not supported for this platform\n"); #endif } #if __APPLE__ posix_spawnattr_init (&attr); if (p->_args[0]) { char **envp = r_sys_get_environ(); ut32 spflags = 0; //POSIX_SPAWN_START_SUSPENDED; spflags |= POSIX_SPAWN_SETEXEC; if (p->_aslr == 0) { #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 spflags |= _POSIX_SPAWN_DISABLE_ASLR; } (void)posix_spawnattr_setflags (&attr, spflags); if (p->_bits) { size_t copied = 1; cpu_type_t cpu; #if __i386__ || __x86_64__ cpu = CPU_TYPE_I386; if (p->_bits == 64) cpu |= CPU_ARCH_ABI64; #else cpu = CPU_TYPE_ANY; #endif posix_spawnattr_setbinpref_np ( &attr, 1, &cpu, &copied); } ret = posix_spawnp (&pid, p->_args[0], NULL, &attr, p->_args, envp); switch (ret) { case 0: break; case 22: eprintf ("posix_spawnp: Invalid argument\n"); break; case 86: eprintf ("posix_spawnp: Unsupported architecture\n"); break; default: eprintf ("posix_spawnp: unknown error %d\n", ret); perror ("posix_spawnp"); break; } exit (ret); } #endif if (p->_system) { if (p->_pid) { eprintf ("PID: Cannot determine pid with 'system' directive. Use 'program'.\n"); } exit (r_sys_cmd (p->_system)); } if (p->_program) { if (!r_file_exists (p->_program)) { char *progpath = r_file_path (p->_program); if (progpath && *progpath) { free (p->_program); p->_program = progpath; } else { free (progpath); eprintf ("rarun2: %s: file not found\n", p->_program); return 1; } } #if __UNIX__ // XXX HACK close all non-tty fds { int i; for (i=3; i<10; i++) close (i); } // TODO: use posix_spawn if (p->_setgid) { ret = setgid (atoi (p->_setgid)); if (ret < 0) return 1; } if (p->_pid) { eprintf ("PID: %d\n", getpid ()); } if (p->_pidfile) { char pidstr[32]; snprintf (pidstr, sizeof (pidstr), "%d\n", getpid ()); r_file_dump (p->_pidfile, (const ut8*)pidstr, strlen (pidstr), 0); } #endif if (p->_nice) { #if __UNIX__ && !defined(__HAIKU__) if (nice (p->_nice) == -1) { return 1; } #else eprintf ("nice not supported for this platform\n"); #endif } exit (execv (p->_program, (char* const*)p->_args)); } return 0; }
static void trace_me () { #if __APPLE__ signal (SIGTRAP, SIG_IGN); //NEED BY STEP #endif #if __APPLE__ || __BSD__ /* we can probably remove this #if..as long as PT_TRACE_ME is redefined for OSX in r_debug.h */ signal (SIGABRT, inferior_abort_handler); if (ptrace (PT_TRACE_ME, 0, 0, 0) != 0) { #else if (ptrace (PTRACE_TRACEME, 0, NULL, NULL) != 0) { #endif r_sys_perror ("ptrace-traceme"); exit (MAGIC_EXIT); } } // __UNIX__ (not windows) static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) { bool runprofile = io->runprofile && *(io->runprofile); char **argv; #if __APPLE__ && !__POWERPC__ if (!runprofile) { #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 posix_spawn_file_actions_t fileActions; ut32 ps_flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; sigset_t no_signals; sigset_t all_signals; sigemptyset (&no_signals); sigfillset (&all_signals); posix_spawnattr_t attr = {0}; size_t copied = 1; cpu_type_t cpu; pid_t p = -1; int ret, useASLR = io->aslr; char *_cmd = io->args ? r_str_concatf (strdup (cmd), " %s", io->args) : strdup (cmd); argv = r_str_argv (_cmd, NULL); if (!argv) { free (_cmd); return -1; } if (!*argv) { r_str_argv_free (argv); free (_cmd); eprintf ("Invalid execvp\n"); return -1; } posix_spawnattr_init (&attr); if (useASLR != -1) { if (!useASLR) ps_flags |= _POSIX_SPAWN_DISABLE_ASLR; } posix_spawn_file_actions_init (&fileActions); posix_spawn_file_actions_addinherit_np (&fileActions, STDIN_FILENO); posix_spawn_file_actions_addinherit_np (&fileActions, STDOUT_FILENO); posix_spawn_file_actions_addinherit_np (&fileActions, STDERR_FILENO); ps_flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; ps_flags |= POSIX_SPAWN_START_SUSPENDED; posix_spawnattr_setsigmask(&attr, &no_signals); posix_spawnattr_setsigdefault(&attr, &all_signals); (void)posix_spawnattr_setflags (&attr, ps_flags); #if __i386__ || __x86_64__ cpu = CPU_TYPE_I386; if (bits == 64) cpu |= CPU_ARCH_ABI64; #else cpu = CPU_TYPE_ANY; #endif posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &copied); { char *dst = r_file_readlink (argv[0]); if (dst) { argv[0] = dst; } } ret = posix_spawnp (&p, argv[0], &fileActions, &attr, argv, NULL); switch (ret) { case 0: // eprintf ("Success\n"); break; case 22: eprintf ("posix_spawnp: Invalid argument\n"); break; case 86: eprintf ("Unsupported architecture\n"); break; default: eprintf ("posix_spawnp: unknown error %d\n", ret); perror ("posix_spawnp"); break; } posix_spawn_file_actions_destroy (&fileActions); r_str_argv_free (argv); free (_cmd); return p; } #endif int ret, status, child_pid; child_pid = r_sys_fork (); switch (child_pid) { case -1: perror ("fork_and_ptraceme"); break; case 0: if (runprofile) { char *expr = NULL; int i; RRunProfile *rp = r_run_new (NULL); argv = r_str_argv (cmd, NULL); for (i = 0; argv[i]; i++) { rp->_args[i] = argv[i]; } rp->_args[i] = NULL; rp->_program = argv[0]; rp->_dodebug = true; if (io->runprofile && *io->runprofile) { if (!r_run_parsefile (rp, io->runprofile)) { eprintf ("Can't find profile '%s'\n", io->runprofile); exit (MAGIC_EXIT); } } if (bits == 64) r_run_parseline (rp, expr=strdup ("bits=64")); else if (bits == 32) r_run_parseline (rp, expr=strdup ("bits=32")); free (expr); if (r_run_config_env (rp)) { eprintf ("Can't config the environment.\n"); exit (1); } trace_me (); r_run_start (rp); r_run_free (rp); r_str_argv_free (argv); exit (1); } else { char *_cmd = io->args ? r_str_concatf (strdup (cmd), " %s", io->args) : strdup (cmd); trace_me (); argv = r_str_argv (_cmd, NULL); if (!argv) { free (_cmd); return -1; } if (argv && *argv) { int i; for (i = 3; i < 1024; i++) (void)close (i); execvp (argv[0], argv); } else { eprintf ("Invalid execvp\n"); } r_str_argv_free (argv); free (_cmd); } perror ("fork_and_attach: execv"); //printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename); exit (MAGIC_EXIT); /* error */ return 0; // invalid pid // if exit is overriden.. :) default: /* XXX: clean this dirty code */ do { ret = wait (&status); if (ret == -1) return -1; if (ret != child_pid) { eprintf ("Wait event received by " "different pid %d\n", ret); } } while (ret != child_pid); if (WIFSTOPPED (status)) eprintf ("Process with PID %d started...\n", (int)child_pid); if (WEXITSTATUS (status) == MAGIC_EXIT) child_pid = -1; // XXX kill (pid, SIGSTOP); break; } return child_pid; }
R_API int r_sys_cmd_str_full(const char *cmd, const char *input, char **output, int *len, char **sterr) { char *mysterr = NULL; if (!sterr) { sterr = &mysterr; } char buffer[1024], *outputptr = NULL; char *inputptr = (char *)input; int pid, bytes = 0, status; int sh_in[2], sh_out[2], sh_err[2]; if (len) { *len = 0; } if (pipe (sh_in)) { return false; } if (output) { if (pipe (sh_out)) { close (sh_in[0]); close (sh_in[1]); close (sh_out[0]); close (sh_out[1]); return false; } } if (pipe (sh_err)) { close (sh_in[0]); close (sh_in[1]); return false; } switch ((pid = r_sys_fork ())) { case -1: return false; case 0: dup2 (sh_in[0], 0); close (sh_in[0]); close (sh_in[1]); if (output) { dup2 (sh_out[1], 1); close (sh_out[0]); close (sh_out[1]); } if (sterr) { dup2 (sh_err[1], 2); } else { close (2); } close (sh_err[0]); close (sh_err[1]); exit (r_sandbox_system (cmd, 0)); default: outputptr = strdup (""); if (!outputptr) { return false; } if (sterr) { *sterr = strdup (""); if (!*sterr) { free (outputptr); return false; } } if (output) { close (sh_out[1]); } close (sh_err[1]); close (sh_in[0]); if (!inputptr || !*inputptr) { close (sh_in[1]); } // we should handle broken pipes somehow better signal (SIGPIPE, SIG_IGN); for (;;) { fd_set rfds, wfds; int nfd; FD_ZERO (&rfds); FD_ZERO (&wfds); if (output) { FD_SET (sh_out[0], &rfds); } if (sterr) { FD_SET (sh_err[0], &rfds); } if (inputptr && *inputptr) { FD_SET (sh_in[1], &wfds); } memset (buffer, 0, sizeof (buffer)); nfd = select (sh_err[0] + 1, &rfds, &wfds, NULL, NULL); if (nfd < 0) { break; } if (output && FD_ISSET (sh_out[0], &rfds)) { if (!(bytes = read (sh_out[0], buffer, sizeof (buffer)-1))) { break; } buffer[sizeof (buffer) - 1] = '\0'; if (len) { *len += bytes; } outputptr = r_str_append (outputptr, buffer); } else if (FD_ISSET (sh_err[0], &rfds) && sterr) { if (!read (sh_err[0], buffer, sizeof (buffer)-1)) { break; } buffer[sizeof (buffer) - 1] = '\0'; *sterr = r_str_append (*sterr, buffer); } else if (FD_ISSET (sh_in[1], &wfds) && inputptr && *inputptr) { int inputptr_len = strlen (inputptr); bytes = write (sh_in[1], inputptr, inputptr_len); if (bytes != inputptr_len) { break; } inputptr += bytes; if (!*inputptr) { close (sh_in[1]); /* If neither stdout nor stderr should be captured, * abort now - nothing more to do for select(). */ if (!output && !sterr) { break; } } } } if (output) { close (sh_out[0]); } close (sh_err[0]); close (sh_in[1]); waitpid (pid, &status, 0); bool ret = true; if (status) { // char *escmd = r_str_escape (cmd); // eprintf ("error code %d (%s): %s\n", WEXITSTATUS (status), escmd, *sterr); // eprintf ("(%s)\n", output); // eprintf ("%s: failed command '%s'\n", __func__, escmd); // free (escmd); ret = false; } if (output) { *output = outputptr; } else { free (outputptr); } return ret; } return false; }
static int lang_pipe_run(RLang *lang, const char *code, int len) { #if __UNIX__ int safe_in = dup (0); int child, ret; int input[2]; int output[2]; pipe (input); pipe (output); env ("R2PIPE_IN", input[0]); env ("R2PIPE_OUT", output[1]); child = r_sys_fork (); if (child == -1) { /* error */ } else if (child == 0) { /* children */ r_sandbox_system (code, 1); write (input[1], "", 1); close (input[0]); close (input[1]); close (output[0]); close (output[1]); exit (0); return false; } else { /* parent */ char *res, buf[1024]; /* Close pipe ends not required in the parent */ close (output[1]); close (input[0]); r_cons_break (NULL, NULL); for (;;) { if (r_cons_singleton ()->breaked) { break; } memset (buf, 0, sizeof (buf)); ret = read (output[0], buf, sizeof (buf)-1); if (ret <1 || !buf[0]) { break; } buf[sizeof (buf)-1] = 0; res = lang->cmd_str ((RCore*)lang->user, buf); //eprintf ("%d %s\n", ret, buf); if (res) { write (input[1], res, strlen (res)+1); free (res); } else { eprintf ("r_lang_pipe: NULL reply for (%s)\n", buf); write (input[1], "", 1); // NULL byte } } /* workaround to avoid stdin closed */ if (safe_in != -1) close (safe_in); safe_in = open (ttyname(0), O_RDONLY); if (safe_in != -1) { dup2 (safe_in, 0); } else eprintf ("Cannot open ttyname(0) %s\n", ttyname(0)); r_cons_break_end (); } close (input[0]); close (input[1]); close (output[0]); close (output[1]); if (safe_in != -1) close (safe_in); waitpid (child, NULL, 0); return true; #else #if __WINDOWS__ HANDLE hThread = 0; char buf[512]; sprintf(buf,"R2PIPE_IN%x",_getpid()); SetEnvironmentVariable("R2PIPE_PATH",buf); sprintf(buf,"\\\\.\\pipe\\R2PIPE_IN%x",_getpid()); hPipeInOut = CreateNamedPipe(buf, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, PIPE_BUF_SIZE, PIPE_BUF_SIZE, 0, NULL); hproc = myCreateChildProcess (code); if (!hproc) { return false; } bStopThread=FALSE; hThread = CreateThread (NULL, 0,ThreadFunction,lang, 0,0); WaitForSingleObject (hproc, INFINITE ); bStopThread = TRUE; DeleteFile (buf); WaitForSingleObject (hThread, INFINITE); CloseHandle (hPipeInOut); return true; #endif #endif }
static int fork_and_ptraceme(RIO *io, int bits, const char *cmd) { #if __APPLE__ && !__POWERPC__ return fork_and_ptraceme_for_mac(io, bits, cmd); #else int ret, status, child_pid; bool runprofile = io->runprofile && *(io->runprofile); char **argv; child_pid = r_sys_fork (); switch (child_pid) { case -1: perror ("fork_and_ptraceme"); break; case 0: if (runprofile) { argv = r_str_argv (cmd, NULL); if (!argv) { exit(1); } RRunProfile *rp = _get_run_profile (io, bits, argv); if (!rp) { r_str_argv_free (argv); exit (1); } trace_me (); r_run_start (rp); r_run_free (rp); r_str_argv_free (argv); exit (1); } else { char *_cmd = io->args ? r_str_appendf (strdup (cmd), " %s", io->args) : strdup (cmd); trace_me (); argv = r_str_argv (_cmd, NULL); if (!argv) { free (_cmd); return -1; } if (argv && *argv) { int i; for (i = 3; i < 1024; i++) { (void)close (i); } if (execvp (argv[0], argv) == -1) { eprintf ("Could not execvp: %s\n", strerror (errno)); exit (MAGIC_EXIT); } } else { eprintf ("Invalid execvp\n"); } r_str_argv_free (argv); free (_cmd); } perror ("fork_and_attach: execv"); //printf(stderr, "[%d] %s execv failed.\n", getpid(), ps.filename); exit (MAGIC_EXIT); /* error */ return 0; // invalid pid // if exit is overriden.. :) default: /* XXX: clean this dirty code */ do { ret = wait (&status); if (ret == -1) return -1; if (ret != child_pid) { eprintf ("Wait event received by " "different pid %d\n", ret); } } while (ret != child_pid); if (WIFSTOPPED (status)) { eprintf ("Process with PID %d started...\n", (int)child_pid); } if (WEXITSTATUS (status) == MAGIC_EXIT) { child_pid = -1; } // XXX kill (pid, SIGSTOP); break; } return child_pid; #endif }