pid_t forkpty(int *master, unused char *name, struct termios *tio, struct winsize *ws) { int slave = -1, fd, pipe_fd[2]; char *path, dummy; pid_t pid; if (pipe(pipe_fd) == -1) return (-1); if ((*master = open("/dev/ptc", O_RDWR|O_NOCTTY)) == -1) goto out; if ((path = ttyname(*master)) == NULL) goto out; if ((slave = open(path, O_RDWR|O_NOCTTY)) == -1) goto out; switch (pid = fork()) { case -1: goto out; case 0: close(*master); close(pipe_fd[1]); while (read(pipe_fd[0], &dummy, 1) == -1) { if (errno != EINTR) break; } close(pipe_fd[0]); fd = open(_PATH_TTY, O_RDWR|O_NOCTTY); if (fd >= 0) { ioctl(fd, TIOCNOTTY, NULL); close(fd); } if (setsid() < 0) fatal("setsid"); fd = open(_PATH_TTY, O_RDWR|O_NOCTTY); if (fd >= 0) fatalx("open succeeded (failed to disconnect)"); fd = open(path, O_RDWR); if (fd < 0) fatal("open failed"); close(fd); fd = open("/dev/tty", O_WRONLY); if (fd < 0) fatal("open failed"); close(fd); if (tio != NULL && tcsetattr(slave, TCSAFLUSH, tio) == -1) fatal("tcsetattr failed"); if (ioctl(slave, TIOCSWINSZ, ws) == -1) fatal("ioctl failed"); dup2(slave, 0); dup2(slave, 1); dup2(slave, 2); if (slave > 2) close(slave); return (0); } close(slave); close(pipe_fd[0]); close(pipe_fd[1]); return (pid); out: if (*master != -1) close(*master); if (slave != -1) close(slave); close(pipe_fd[0]); close(pipe_fd[1]); return (-1); }
// Execute cmd. Never returns. void runcmd(struct cmd *cmd) { int p[2]; struct backcmd *bcmd; struct execcmd *ecmd; struct listcmd *lcmd; struct pipecmd *pcmd; struct redircmd *rcmd; if(cmd == 0) exit(); switch(cmd->type){ default: panic("runcmd"); case EXEC: ecmd = (struct execcmd*)cmd; if(ecmd->argv[0] == 0) exit(); exec(ecmd->argv[0], ecmd->argv); printf(2, "exec %s failed\n", ecmd->argv[0]); break; case REDIR: rcmd = (struct redircmd*)cmd; close(rcmd->fd); if(open(rcmd->file, rcmd->mode) < 0){ printf(2, "open %s failed\n", rcmd->file); exit(); } runcmd(rcmd->cmd); break; case LIST: lcmd = (struct listcmd*)cmd; if(fork1() == 0) runcmd(lcmd->left); wait(); runcmd(lcmd->right); break; case PIPE: pcmd = (struct pipecmd*)cmd; if(pipe(p) < 0) panic("pipe"); if(fork1() == 0){ close(1); dup(p[1]); close(p[0]); close(p[1]); runcmd(pcmd->left); } if(fork1() == 0){ close(0); dup(p[0]); close(p[0]); close(p[1]); runcmd(pcmd->right); } close(p[0]); close(p[1]); wait(); wait(); break; case BACK: bcmd = (struct backcmd*)cmd; if(fork1() == 0) runcmd(bcmd->cmd); break; } exit(); }
void* CloudPinyinCreate(FcitxInstance* instance) { FcitxCloudPinyin *cloudpinyin = fcitx_utils_new(FcitxCloudPinyin); bindtextdomain("fcitx-cloudpinyin", LOCALEDIR); bind_textdomain_codeset("fcitx-cloudpinyin", "UTF-8"); cloudpinyin->owner = instance; int pipe1[2]; int pipe2[2]; if (!CloudPinyinConfigLoad(&cloudpinyin->config)) { free(cloudpinyin); return NULL; } if (pipe(pipe1) < 0) { free(cloudpinyin); return NULL; } if (pipe(pipe2) < 0) { close(pipe1[0]); close(pipe1[1]); free(cloudpinyin); return NULL; } cloudpinyin->pipeRecv = pipe1[0]; cloudpinyin->pipeNotify = pipe2[1]; fcntl(pipe1[0], F_SETFL, O_NONBLOCK); fcntl(pipe1[1], F_SETFL, O_NONBLOCK); fcntl(pipe2[0], F_SETFL, O_NONBLOCK); fcntl(pipe2[1], F_SETFL, O_NONBLOCK); cloudpinyin->pendingQueue = fcitx_utils_malloc0(sizeof(CurlQueue)); cloudpinyin->finishQueue = fcitx_utils_malloc0(sizeof(CurlQueue)); pthread_mutex_init(&cloudpinyin->pendingQueueLock, NULL); pthread_mutex_init(&cloudpinyin->finishQueueLock, NULL); FcitxFetchThread* fetch = fcitx_utils_malloc0(sizeof(FcitxFetchThread)); cloudpinyin->fetch = fetch; fetch->owner = cloudpinyin; fetch->pipeRecv = pipe2[0]; fetch->pipeNotify = pipe1[1]; fetch->pendingQueueLock = &cloudpinyin->pendingQueueLock; fetch->finishQueueLock = &cloudpinyin->finishQueueLock; fetch->queue = fcitx_utils_malloc0(sizeof(CurlQueue)); FcitxIMEventHook hook; hook.arg = cloudpinyin; hook.func = CloudPinyinAddCandidateWord; FcitxInstanceRegisterUpdateCandidateWordHook(instance, hook); hook.arg = cloudpinyin; hook.func = CloudPinyinHookForNewRequest; FcitxInstanceRegisterResetInputHook(instance, hook); FcitxInstanceRegisterInputFocusHook(instance, hook); FcitxInstanceRegisterInputUnFocusHook(instance, hook); FcitxInstanceRegisterTriggerOnHook(instance, hook); FcitxHotkeyHook hkhook; hkhook.arg = cloudpinyin; hkhook.hotkey = cloudpinyin->config.hkToggle.hotkey; hkhook.hotkeyhandle = CloudPinyinToggle; FcitxInstanceRegisterHotkeyFilter(instance, hkhook); pthread_create(&cloudpinyin->pid, NULL, FetchThread, fetch); CloudPinyinRequestKey(cloudpinyin); return cloudpinyin; }
int start_command(struct child_process *cmd) { int need_in, need_out, need_err; int fdin[2], fdout[2], fderr[2]; int failed_errno; char *str; if (!cmd->argv) cmd->argv = cmd->args.argv; if (!cmd->env) cmd->env = cmd->env_array.argv; /* * In case of errors we must keep the promise to close FDs * that have been passed in via ->in and ->out. */ need_in = !cmd->no_stdin && cmd->in < 0; if (need_in) { if (pipe(fdin) < 0) { failed_errno = errno; if (cmd->out > 0) close(cmd->out); str = "standard input"; goto fail_pipe; } cmd->in = fdin[1]; } need_out = !cmd->no_stdout && !cmd->stdout_to_stderr && cmd->out < 0; if (need_out) { if (pipe(fdout) < 0) { failed_errno = errno; if (need_in) close_pair(fdin); else if (cmd->in) close(cmd->in); str = "standard output"; goto fail_pipe; } cmd->out = fdout[0]; } need_err = !cmd->no_stderr && cmd->err < 0; if (need_err) { if (pipe(fderr) < 0) { failed_errno = errno; if (need_in) close_pair(fdin); else if (cmd->in) close(cmd->in); if (need_out) close_pair(fdout); else if (cmd->out) close(cmd->out); str = "standard error"; fail_pipe: error("cannot create %s pipe for %s: %s", str, cmd->argv[0], strerror(failed_errno)); argv_array_clear(&cmd->args); argv_array_clear(&cmd->env_array); errno = failed_errno; return -1; } cmd->err = fderr[0]; } trace_argv_printf(cmd->argv, "trace: run_command:"); fflush(NULL); #ifndef GIT_WINDOWS_NATIVE { int notify_pipe[2]; if (pipe(notify_pipe)) notify_pipe[0] = notify_pipe[1] = -1; cmd->pid = fork(); failed_errno = errno; if (!cmd->pid) { /* * Redirect the channel to write syscall error messages to * before redirecting the process's stderr so that all die() * in subsequent call paths use the parent's stderr. */ if (cmd->no_stderr || need_err) { int child_err = dup(2); set_cloexec(child_err); set_error_handle(fdopen(child_err, "w")); } close(notify_pipe[0]); set_cloexec(notify_pipe[1]); child_notifier = notify_pipe[1]; atexit(notify_parent); if (cmd->no_stdin) dup_devnull(0); else if (need_in) { dup2(fdin[0], 0); close_pair(fdin); } else if (cmd->in) { dup2(cmd->in, 0); close(cmd->in); } if (cmd->no_stderr) dup_devnull(2); else if (need_err) { dup2(fderr[1], 2); close_pair(fderr); } else if (cmd->err > 1) { dup2(cmd->err, 2); close(cmd->err); } if (cmd->no_stdout) dup_devnull(1); else if (cmd->stdout_to_stderr) dup2(2, 1); else if (need_out) { dup2(fdout[1], 1); close_pair(fdout); } else if (cmd->out > 1) { dup2(cmd->out, 1); close(cmd->out); } if (cmd->dir && chdir(cmd->dir)) die_errno("exec '%s': cd to '%s' failed", cmd->argv[0], cmd->dir); if (cmd->env) { for (; *cmd->env; cmd->env++) { if (strchr(*cmd->env, '=')) putenv((char *)*cmd->env); else unsetenv(*cmd->env); } } if (cmd->git_cmd) execv_git_cmd(cmd->argv); else if (cmd->use_shell) execv_shell_cmd(cmd->argv); else sane_execvp(cmd->argv[0], (char *const*) cmd->argv); if (errno == ENOENT) { if (!cmd->silent_exec_failure) error("cannot run %s: %s", cmd->argv[0], strerror(ENOENT)); exit(127); } else { die_errno("cannot exec '%s'", cmd->argv[0]); } } if (cmd->pid < 0) error("cannot fork() for %s: %s", cmd->argv[0], strerror(errno)); else if (cmd->clean_on_exit) mark_child_for_cleanup(cmd->pid); /* * Wait for child's execvp. If the execvp succeeds (or if fork() * failed), EOF is seen immediately by the parent. Otherwise, the * child process sends a single byte. * Note that use of this infrastructure is completely advisory, * therefore, we keep error checks minimal. */ close(notify_pipe[1]); if (read(notify_pipe[0], ¬ify_pipe[1], 1) == 1) { /* * At this point we know that fork() succeeded, but execvp() * failed. Errors have been reported to our stderr. */ wait_or_whine(cmd->pid, cmd->argv[0]); failed_errno = errno; cmd->pid = -1; } close(notify_pipe[0]); } #else { int fhin = 0, fhout = 1, fherr = 2; const char **sargv = cmd->argv; if (cmd->no_stdin) fhin = open("/dev/null", O_RDWR); else if (need_in) fhin = dup(fdin[0]); else if (cmd->in) fhin = dup(cmd->in); if (cmd->no_stderr) fherr = open("/dev/null", O_RDWR); else if (need_err) fherr = dup(fderr[1]); else if (cmd->err > 2) fherr = dup(cmd->err); if (cmd->no_stdout) fhout = open("/dev/null", O_RDWR); else if (cmd->stdout_to_stderr) fhout = dup(fherr); else if (need_out) fhout = dup(fdout[1]); else if (cmd->out > 1) fhout = dup(cmd->out); if (cmd->git_cmd) cmd->argv = prepare_git_cmd(cmd->argv); else if (cmd->use_shell) cmd->argv = prepare_shell_cmd(cmd->argv); cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, (char**) cmd->env, cmd->dir, fhin, fhout, fherr); failed_errno = errno; if (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT)) error("cannot spawn %s: %s", cmd->argv[0], strerror(errno)); if (cmd->clean_on_exit && cmd->pid >= 0) mark_child_for_cleanup(cmd->pid); if (cmd->git_cmd) free(cmd->argv); cmd->argv = sargv; if (fhin != 0) close(fhin); if (fhout != 1) close(fhout); if (fherr != 2) close(fherr); } #endif if (cmd->pid < 0) { if (need_in) close_pair(fdin); else if (cmd->in) close(cmd->in); if (need_out) close_pair(fdout); else if (cmd->out) close(cmd->out); if (need_err) close_pair(fderr); else if (cmd->err) close(cmd->err); argv_array_clear(&cmd->args); argv_array_clear(&cmd->env_array); errno = failed_errno; return -1; } if (need_in) close(fdin[0]); else if (cmd->in) close(cmd->in); if (need_out) close(fdout[1]); else if (cmd->out) close(cmd->out); if (need_err) close(fderr[1]); else if (cmd->err) close(cmd->err); return 0; }
ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL roken_detach_prep(int argc, char **argv, char *special_arg) { pid_t child; char buf[1]; ssize_t bytes; int status; pipefds[0] = -1; pipefds[1] = -1; #ifdef WIN32 if (_pipe(pipefds, 4, O_BINARY) == -1) err(1, "failed to setup to detach daemon (_pipe failed)"); #else if (pipe(pipefds) == -1) err(1, "failed to setup to detach daemon (pipe failed)"); #endif #ifndef WIN32 fflush(stdout); child = fork(); #else { intptr_t child_handle; int write_side; size_t i; char *fildes; char **new_argv; new_argv = calloc(argc + 2, sizeof(*new_argv)); if (new_argv == NULL) err(1, "Out of memory"); write_side = _dup(pipefds[1]); /* The new fd will be inherited */ if (write_side == -1) err(1, "Out of memory"); if (asprintf(&fildes, "%d", write_side) == -1 || fildes == NULL) err(1, "failed to setup to detach daemon (_dup failed)"); new_argv[0] = argv[0]; new_argv[1] = special_arg; new_argv[2] = fildes; for (i = 1; argv[i] != NULL; i++) new_argv[i + 1] = argv[i]; new_argv[argc + 2] = NULL; _flushall(); child_handle = spawnvp(_P_NOWAIT, argv[0], new_argv); if (child_handle == -1) child = (pid_t)-1; else child = GetProcessId((HANDLE)child_handle); } #endif if (child == (pid_t)-1) err(1, "failed to setup to fork daemon (fork failed)"); #ifndef WIN32 if (child == 0) { int fd; (void) close(pipefds[0]); pipefds[0] = -1; /* * Keep stdout/stderr for now so output and errors prior to * detach_finish() can be seen by the user. */ fd = open(_PATH_DEVNULL, O_RDWR, 0); if (fd == -1) err(1, "failed to open /dev/null"); (void) dup2(fd, STDIN_FILENO); if (fd > STDERR_FILENO) (void) close(fd); return; } #endif (void) close(pipefds[1]); pipefds[1] = -1; do { bytes = read(pipefds[0], buf, sizeof(buf)); } while (bytes == -1 && errno == EINTR); (void) close(pipefds[0]); pipefds[0] = -1; if (bytes == -1) { /* * No need to wait for the process. We've killed it. If it * doesn't want to exit, we'd have to wait potentially forever, * but we want to indicate failure to the user as soon as * possible. A wait with timeout would end the same way * (attempting to kill the process). */ err(1, "failed to setup daemon child (read from child pipe)"); } if (bytes == 0) { warnx("daemon child preparation failed, waiting for child"); status = wait_for_process(child); if (SE_IS_ERROR(status) || SE_PROCSTATUS(status) != 0) errx(SE_PROCSTATUS(status), "daemon child preparation failed (child exited)"); } _exit(0); }
/* * Run an external program. Optionally wait a specified number * of seconds. Program killed if wait exceeded. We open * a bi-directional pipe so that the user can read from and * write to the program. */ BPIPE *open_bpipe(char *prog, int wait, const char *mode) { char *bargv[MAX_ARGV]; int bargc, i; int readp[2], writep[2]; POOLMEM *tprog; int mode_read, mode_write; BPIPE *bpipe; int save_errno; bpipe = (BPIPE *)malloc(sizeof(BPIPE)); memset(bpipe, 0, sizeof(BPIPE)); mode_read = (mode[0] == 'r'); mode_write = (mode[0] == 'w' || mode[1] == 'w'); /* Build arguments for running program. */ tprog = get_pool_memory(PM_FNAME); pm_strcpy(tprog, prog); build_argc_argv(tprog, &bargc, bargv, MAX_ARGV); #ifdef xxxxxx printf("argc=%d\n", bargc); for (i=0; i<bargc; i++) { printf("argc=%d argv=%s:\n", i, bargv[i]); } #endif /* Each pipe is one way, write one end, read the other, so we need two */ if (mode_write && pipe(writep) == -1) { save_errno = errno; free(bpipe); free_pool_memory(tprog); errno = save_errno; return NULL; } if (mode_read && pipe(readp) == -1) { save_errno = errno; if (mode_write) { close(writep[0]); close(writep[1]); } free(bpipe); free_pool_memory(tprog); errno = save_errno; return NULL; } /* Start worker process */ switch (bpipe->worker_pid = fork()) { case -1: /* error */ save_errno = errno; if (mode_write) { close(writep[0]); close(writep[1]); } if (mode_read) { close(readp[0]); close(readp[1]); } free(bpipe); free_pool_memory(tprog); errno = save_errno; return NULL; case 0: /* child */ if (mode_write) { close(writep[1]); dup2(writep[0], 0); /* Dup our write to his stdin */ } if (mode_read) { close(readp[0]); /* Close unused child fds */ dup2(readp[1], 1); /* dup our read to his stdout */ dup2(readp[1], 2); /* and his stderr */ } /* Note, the close log cause problems, see bug #1536 */ /* closelog(); close syslog if open */ for (i=3; i<=32; i++) { /* close any open file descriptors */ close(i); } execvp(bargv[0], bargv); /* call the program */ /* Convert errno into an exit code for later analysis */ for (i=0; i< num_execvp_errors; i++) { if (execvp_errors[i] == errno) { exit(200 + i); /* exit code => errno */ } } exit(255); /* unknown errno */ default: /* parent */ break; } free_pool_memory(tprog); if (mode_read) { close(readp[1]); /* close unused parent fds */ bpipe->rfd = fdopen(readp[0], "r"); /* open file descriptor */ } if (mode_write) { close(writep[0]); bpipe->wfd = fdopen(writep[1], "w"); } bpipe->worker_stime = time(NULL); bpipe->wait = wait; if (wait > 0) { bpipe->timer_id = start_child_timer(NULL, bpipe->worker_pid, wait); } return bpipe; }
void cmd_clipboard(const char *e_line, command *commands) { xmlNodePtr db_node = NULL; xmlChar *key = NULL, *value = NULL, *value_nl = NULL, *value_line = NULL; char *cmd_line = NULL, *cmd = NULL, *inv = NULL; unsigned long int idx = 0, line_req = 1, lines = 0, value_line_len = 0, value_len = 0, i = 0; unsigned char app = 0; /* 1=tmux, 2=xclip PRIMARY, 3=xclip CLIPBOARD */ char **fork_argv = NULL; int child; int pipefd[2]; cmd_line = strdup(e_line); malloc_check(cmd_line); cmd = strtok(cmd_line, " "); if (!cmd) { puts(commands->usage); free(cmd_line); cmd_line = NULL; return; } if (strcmp(cmd, "tmux") == 0) app = 1; else if (strcmp(cmd, "xclip") == 0) app = 2; else if (strcmp(cmd, "Xclip") == 0) app = 3; if (app == 0) { puts(commands->usage); free(cmd_line); cmd_line = NULL; return; } cmd = strtok(NULL, " "); /* first parameter, the index number */ if (!cmd) { puts(commands->usage); free(cmd_line); cmd_line = NULL; return; } errno = 0; idx = strtoul((const char *)cmd, &inv, 10); if (inv[0] != '\0' || errno != 0 || cmd[0] == '-') { puts(commands->usage); free(cmd_line); cmd_line = NULL; return; } cmd = strtok(NULL, " "); /* second, optional parameter, the requested line number */ if (cmd) { errno = 0; line_req = strtoul((const char *)cmd, &inv, 10); if (inv[0] != '\0' || errno != 0 || cmd[0] == '-') { puts(commands->usage); free(cmd_line); cmd_line = NULL; return; } if (line_req < 1) { puts(commands->usage); free(cmd_line); cmd_line = NULL; return; } } free(cmd_line); cmd_line = NULL; db_node = find_key(idx); if (db_node) { value = xmlGetProp(db_node, BAD_CAST "value"); key = xmlGetProp(db_node, BAD_CAST "name"); value_nl = parse_newlines(value, 0); xmlFree(value); value = NULL; /* count how many (new)lines are in the string */ value_len = xmlStrlen(value_nl); for (i=0; i < value_len; i++) if (value_nl[i] == '\n') lines++; lines++; /* If the requested line number is greater than the * maximum, use the maximum. */ if (line_req > lines) line_req = lines; /* get a line out from the value */ value_line = get_line(value_nl, line_req); value_line_len = xmlStrlen(value_line); /* This is duplicated in cmd_getnum.c */ switch (app) { case 1: /* Copy value to tmux paste buffer */ switch (child = fork()) { case -1: perror("\nERROR: Couldn't fork(2) for tmux(1)"); break; case 0: /* Child */ #ifndef __OpenBSD__ close(0); #endif close(1); if (bio_chain) BIO_free_all(bio_chain); if (db_params.db_file) { if (close(db_params.db_file) == -1) { perror("ERROR: child: close(database file)"); exit(EXIT_FAILURE); } else { db_params.db_file = -1; } } fork_argv = malloc(5 * sizeof(char *)); malloc_check(fork_argv); fork_argv[0] = "tmux"; fork_argv[1] = "set-buffer"; fork_argv[2] = "--"; fork_argv[3] = (char *)value_line; fork_argv[4] = NULL; if (execvp(fork_argv[0], fork_argv) == -1) dprintf(STDERR_FILENO, "ERROR: tmux: %s\n", strerror(errno)); quit(EXIT_FAILURE); break; default: /* Parent */ printf("Copying #%lu from '%s' to tmux paste buffer.\n", line_req, key); break; } break; case 2: case 3: /* Copy value to X11 clipboard, using xclip(1) */ pipe(pipefd); switch (child = fork()) { case -1: perror("\nERROR: Couldn't fork(2) for xclip(1)"); break; case 0: /* Child */ close(0); close(1); close(pipefd[1]); if (bio_chain) BIO_free_all(bio_chain); if (db_params.db_file) { if (close(db_params.db_file) == -1) { perror("ERROR: child: close(database file)"); exit(EXIT_FAILURE); } else { db_params.db_file = -1; } } fork_argv = malloc(4 * sizeof(char *)); malloc_check(fork_argv); fork_argv[0] = "xclip"; fork_argv[1] = "-selection"; if (app == 2) { fork_argv[2] = "primary"; } else if (app == 3) { fork_argv[2] = "clipboard"; } fork_argv[3] = NULL; /* stdin becomes the read end of the pipe in the child, * and the exec'd process will have the same environment. */ dup2(pipefd[0], 0); if (execvp(fork_argv[0], fork_argv) == -1) dprintf(STDERR_FILENO, "ERROR: xclip: %s\n", strerror(errno)); quit(EXIT_FAILURE); break; default: /* Parent */ /* Write the value to the pipe's write end, which will * appear in the child's stdin (pipe's read end). */ close(pipefd[0]); write(pipefd[1], value_line, value_line_len); close(pipefd[1]); printf("Copying #%lu from '%s' to X11 clipboard.\n", line_req, key); break; } break; } } else puts("Invalid index!"); xmlFree(key); key = NULL; xmlFree(value_line); value_line = NULL; xmlFree(value_nl); value_nl = NULL; } /* cmd_clipboard() */
/* * The purpose of this function is to assign "long usage", short usage * and version information to a shell variable. Rather than wind our * way through all the logic necessary to emit the text directly, we * fork(), have our child process emit the text the normal way and * capture the output in the parent process. */ static void textToVariable(tOptions * pOpts, teTextTo whichVar, tOptDesc * pOD) { # define _TT_(n) static char const z ## n [] = #n; TEXTTO_TABLE # undef _TT_ # define _TT_(n) z ## n , static char const * apzTTNames[] = { TEXTTO_TABLE }; # undef _TT_ #if ! defined(HAVE_WORKING_FORK) printf("%1$s_%2$s_TEXT='no %2$s text'\n", pOpts->pzPROGNAME, apzTTNames[ whichVar ]); #else int pipeFd[2]; fflush(stdout); fflush(stderr); if (pipe(pipeFd) != 0) { fprintf(stderr, zBadPipe, errno, strerror(errno)); exit(EXIT_FAILURE); } switch (fork()) { case -1: fprintf(stderr, zForkFail, errno, strerror(errno), pOpts->pzProgName); exit(EXIT_FAILURE); break; case 0: /* * Send both stderr and stdout to the pipe. No matter which * descriptor is used, we capture the output on the read end. */ dup2(pipeFd[1], STDERR_FILENO); dup2(pipeFd[1], STDOUT_FILENO); close(pipeFd[0]); switch (whichVar) { case TT_LONGUSAGE: (*(pOpts->pUsageProc))(pOpts, EXIT_SUCCESS); /* NOTREACHED */ case TT_USAGE: (*(pOpts->pUsageProc))(pOpts, EXIT_FAILURE); /* NOTREACHED */ case TT_VERSION: if (pOD->fOptState & OPTST_ALLOC_ARG) { AGFREE(pOD->optArg.argString); pOD->fOptState &= ~OPTST_ALLOC_ARG; } pOD->optArg.argString = "c"; optionPrintVersion(pOpts, pOD); /* NOTREACHED */ default: exit(EXIT_FAILURE); } default: close(pipeFd[1]); } emit_var_text(pOpts->pzPROGNAME, apzTTNames[whichVar], pipeFd[0]); #endif }
// // OS_Create_Process: C // // flags: // 1: wait, is implied when I/O redirection is enabled // 2: console // 4: shell // 8: info // 16: show // // input_type/output_type/err_type: // 0: none // 1: string // 2: file // // Return -1 on error, otherwise the process return code. // // POSIX previous simple version was just 'return system(call);' // This uses 'execvp' which is "POSIX.1 conforming, UNIX compatible" // int OS_Create_Process( const REBCHR *call, int argc, const REBCHR* argv[], u32 flags, u64 *pid, int *exit_code, u32 input_type, char *input, u32 input_len, u32 output_type, char **output, u32 *output_len, u32 err_type, char **err, u32 *err_len ) { REBOOL flag_wait = FALSE; REBOOL flag_console = FALSE; REBOOL flag_shell = FALSE; REBOOL flag_info = FALSE; int stdin_pipe[] = {-1, -1}; int stdout_pipe[] = {-1, -1}; int stderr_pipe[] = {-1, -1}; int info_pipe[] = {-1, -1}; int status = 0; int ret = 0; char *info = NULL; off_t info_size = 0; u32 info_len = 0; pid_t fpid = 0; const unsigned int R = 0; const unsigned int W = 1; // We want to be able to compile with all warnings as errors, and // we'd like to use -Wcast-qual if possible. This is currently // the only barrier in the codebase...so we tunnel under the cast. char * const *argv_hack; if (flags & FLAG_WAIT) flag_wait = TRUE; if (flags & FLAG_CONSOLE) flag_console = TRUE; if (flags & FLAG_SHELL) flag_shell = TRUE; if (flags & FLAG_INFO) flag_info = TRUE; // suppress unused warnings but keep flags for future use (void)flag_info; (void)flag_console; // NOTE: pipe() is POSIX, but pipe2() is Linux-specific. if (input_type == STRING_TYPE || input_type == BINARY_TYPE) { #ifdef TO_LINUX if (pipe2(stdin_pipe, O_CLOEXEC | O_NONBLOCK) < 0) { #else if (pipe(stdin_pipe) < 0) { #endif goto stdin_pipe_err; } } if (output_type == STRING_TYPE || output_type == BINARY_TYPE) { #ifdef TO_LINUX if (pipe2(stdout_pipe, O_CLOEXEC | O_NONBLOCK) < 0) { #else if (pipe(stdout_pipe) < 0) { #endif goto stdout_pipe_err; } } if (err_type == STRING_TYPE || err_type == BINARY_TYPE) { #ifdef TO_LINUX if (pipe2(stderr_pipe, O_CLOEXEC | O_NONBLOCK) < 0) { #else if (pipe(stderr_pipe) < 0) { #endif goto stderr_pipe_err; } } #ifdef TO_LINUX if (pipe2(info_pipe, O_CLOEXEC | O_NONBLOCK) < 0) { #else if (pipe(info_pipe) < 0) { #endif goto info_pipe_err; } fpid = fork(); if (fpid == 0) { /* child */ if (input_type == STRING_TYPE || input_type == BINARY_TYPE) { close(stdin_pipe[W]); if (dup2(stdin_pipe[R], STDIN_FILENO) < 0) { goto child_error; } close(stdin_pipe[R]); } else if (input_type == FILE_TYPE) { int fd = open(input, O_RDONLY); if (fd < 0) { goto child_error; } if (dup2(fd, STDIN_FILENO) < 0) { goto child_error; } close(fd); } else if (input_type == NONE_TYPE) { int fd = open("/dev/null", O_RDONLY); if (fd < 0) { goto child_error; } if (dup2(fd, STDIN_FILENO) < 0) { goto child_error; } close(fd); } else { /* inherit stdin from the parent */ } if (output_type == STRING_TYPE || output_type == BINARY_TYPE) { close(stdout_pipe[R]); if (dup2(stdout_pipe[W], STDOUT_FILENO) < 0) { goto child_error; } close(stdout_pipe[W]); } else if (output_type == FILE_TYPE) { int fd = open(*output, O_CREAT|O_WRONLY, 0666); if (fd < 0) { goto child_error; } if (dup2(fd, STDOUT_FILENO) < 0) { goto child_error; } close(fd); } else if (output_type == NONE_TYPE) { int fd = open("/dev/null", O_WRONLY); if (fd < 0) { goto child_error; } if (dup2(fd, STDOUT_FILENO) < 0) { goto child_error; } close(fd); } else { /* inherit stdout from the parent */ } if (err_type == STRING_TYPE || err_type == BINARY_TYPE) { close(stderr_pipe[R]); if (dup2(stderr_pipe[W], STDERR_FILENO) < 0) { goto child_error; } close(stderr_pipe[W]); } else if (err_type == FILE_TYPE) { int fd = open(*err, O_CREAT|O_WRONLY, 0666); if (fd < 0) { goto child_error; } if (dup2(fd, STDERR_FILENO) < 0) { goto child_error; } close(fd); } else if (err_type == NONE_TYPE) { int fd = open("/dev/null", O_WRONLY); if (fd < 0) { goto child_error; } if (dup2(fd, STDERR_FILENO) < 0) { goto child_error; } close(fd); } else {/* inherit stderr from the parent */ } close(info_pipe[R]); //printf("flag_shell in child: %hhu\n", flag_shell); if (flag_shell) { const char* sh = NULL; const char ** argv_new = NULL; sh = getenv("SHELL"); if (sh == NULL) { int err = 2; /* shell does not exist */ if (write(info_pipe[W], &err, sizeof(err)) == -1) { // Nothing we can do, but need to stop compiler warning // (cast to void is insufficient for warn_unused_result) } exit(EXIT_FAILURE); } argv_new = c_cast( const char**, OS_ALLOC_N(const char*, argc + 3) ); argv_new[0] = sh; argv_new[1] = "-c"; memcpy(&argv_new[2], argv, argc * sizeof(argv[0])); argv_new[argc + 2] = NULL; memcpy(&argv_hack, &argv_new, sizeof(argv_hack)); execvp(sh, argv_hack); } else { memcpy(&argv_hack, &argv, sizeof(argv_hack)); execvp(argv[0], argv_hack); } child_error: if (write(info_pipe[W], &errno, sizeof(errno)) == -1) { // Nothing we can do, but need to stop compiler warning // (cast to void is insufficient for warn_unused_result) } exit(EXIT_FAILURE); /* get here only when exec fails */ } else if (fpid > 0) { /* parent */ #define BUF_SIZE_CHUNK 4096 nfds_t nfds = 0; struct pollfd pfds[4]; pid_t xpid; unsigned int i; ssize_t nbytes; off_t input_size = 0; off_t output_size = 0; off_t err_size = 0; int exited = 0; int valid_nfds; /* initialize outputs */ if (output_type != NONE_TYPE && output_type != INHERIT_TYPE && (output == NULL || output_len == NULL)) { return -1; } if (output != NULL) *output = NULL; if (output_len != NULL) *output_len = 0; if (err_type != NONE_TYPE && err_type != INHERIT_TYPE && (err == NULL || err_len == NULL)) { return -1; } if (err != NULL) *err = NULL; if (err_len != NULL) *err_len = 0; // Only put the input pipe in the consideration if we can write to // it and we have data to send to it. if ((stdin_pipe[W] > 0) && (input_size = strlen(input)) > 0) { //printf("stdin_pipe[W]: %d\n", stdin_pipe[W]); /* the passed in input_len is in characters, not in bytes */ input_len = 0; pfds[nfds].fd = stdin_pipe[W]; pfds[nfds].events = POLLOUT; nfds++; close(stdin_pipe[R]); stdin_pipe[R] = -1; } if (stdout_pipe[R] > 0) { //printf("stdout_pipe[R]: %d\n", stdout_pipe[R]); output_size = BUF_SIZE_CHUNK; *output = OS_ALLOC_N(char, output_size); pfds[nfds].fd = stdout_pipe[R]; pfds[nfds].events = POLLIN; nfds++; close(stdout_pipe[W]); stdout_pipe[W] = -1; } if (stderr_pipe[R] > 0) { //printf("stderr_pipe[R]: %d\n", stderr_pipe[R]); err_size = BUF_SIZE_CHUNK; *err = OS_ALLOC_N(char, err_size); pfds[nfds].fd = stderr_pipe[R]; pfds[nfds].events = POLLIN; nfds++; close(stderr_pipe[W]); stderr_pipe[W] = -1; } if (info_pipe[R] > 0) { pfds[nfds].fd = info_pipe[R]; pfds[nfds].events = POLLIN; nfds++; info_size = 4; info = OS_ALLOC_N(char, info_size); close(info_pipe[W]); info_pipe[W] = -1; }
static ngx_int_t ngx_rtmp_exec_run(ngx_rtmp_exec_t *e) { #if !(NGX_WIN32) ngx_pid_t pid; int fd, maxfd; int pipefd[2]; int ret; ngx_rtmp_exec_conf_t *ec; ngx_str_t *arg, a; char **args; ngx_uint_t n; ec = e->conf; ngx_log_debug1(NGX_LOG_DEBUG_RTMP, e->log, 0, "exec: starting child '%V'", &ec->cmd); if (e->active) { ngx_log_debug1(NGX_LOG_DEBUG_RTMP, e->log, 0, "exec: already active '%V'", &ec->cmd); return NGX_OK; } if (pipe(pipefd) == -1) { ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno, "exec: pipe failed"); return NGX_ERROR; } /* make pipe write end survive through exec */ ret = fcntl(pipefd[1], F_GETFD); if (ret != -1) { ret &= ~FD_CLOEXEC; ret = fcntl(pipefd[1], F_SETFD, ret); } if (ret == -1) { close(pipefd[0]); close(pipefd[1]); ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno, "exec: fcntl failed"); return NGX_ERROR; } pid = fork(); switch (pid) { case -1: close(pipefd[0]); close(pipefd[1]); ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno, "exec: fork failed"); return NGX_ERROR; case 0: /* child */ #if (NGX_LINUX) prctl(PR_SET_PDEATHSIG, e->kill_signal, 0, 0, 0); #endif /* close all descriptors but pipe write end */ maxfd = sysconf(_SC_OPEN_MAX); for (fd = 0; fd < maxfd; ++fd) { if (fd == pipefd[1]) { continue; } close(fd); } fd = open("/dev/null", O_RDWR); dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); args = ngx_alloc((ec->args.nelts + 2) * sizeof(char *), e->log); if (args == NULL) { exit(1); } arg = ec->args.elts; args[0] = (char *) ec->cmd.data; for (n = 0; n < ec->args.nelts; ++n, ++arg) { if (e->session == NULL) { a = *arg; } else { ngx_rtmp_eval(e->session, arg, ngx_rtmp_exec_eval_p, &a); } args[n + 1] = (char *) a.data; } args[n + 1] = NULL; if (execvp((char *) ec->cmd.data, args) == -1) { exit(1); } break; default: /* parent */ close(pipefd[1]); e->active = 1; e->pid = pid; e->pipefd = pipefd[0]; if (e->save_pid) { *e->save_pid = pid; } e->dummy_conn.fd = e->pipefd; e->dummy_conn.data = e; e->dummy_conn.read = &e->read_evt; e->dummy_conn.write = &e->write_evt; e->read_evt.data = &e->dummy_conn; e->write_evt.data = &e->dummy_conn; e->read_evt.log = e->log; e->read_evt.handler = ngx_rtmp_exec_child_dead; if (ngx_add_event(&e->read_evt, NGX_READ_EVENT, 0) != NGX_OK) { ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno, "exec: failed to add child control event"); } ngx_log_debug2(NGX_LOG_DEBUG_RTMP, e->log, 0, "exec: child '%V' started pid=%i", &ec->cmd, (ngx_int_t) pid); break; } #endif /* NGX_WIN32 */ return NGX_OK; }
int main(int argc, char **argv) { /* UCP temporary vars */ ucp_params_t ucp_params; ucp_worker_params_t worker_params; ucp_config_t *config; ucs_status_t status; /* UCP handler objects */ ucp_context_h ucp_context; /* OOB connection vars */ uint64_t addr_len = 0; char *server = NULL; int oob_sock = -1; int ret = -1; /* create the signalling pipe */ pipe(signal_pipe); /* Parse the command line */ if (parse_cmd(argc, argv, &server) != UCS_OK) { goto err; } /* UCP initialization */ status = ucp_config_read(NULL, NULL, &config); if (status != UCS_OK) { goto err; } ucp_params.features = UCP_FEATURE_TAG; if (ucp_test_mode == TEST_MODE_WAIT || ucp_test_mode == TEST_MODE_EVENTFD) { ucp_params.features |= UCP_FEATURE_WAKEUP; } ucp_params.request_size = sizeof(struct ucx_context); ucp_params.request_init = request_init; ucp_params.request_cleanup = NULL; status = ucp_init(&ucp_params, config, &ucp_context); ucp_config_print(config, stdout, NULL, UCS_CONFIG_PRINT_CONFIG); ucp_config_release(config); if (status != UCS_OK) { goto err; } worker_params.field_mask = UCP_WORKER_PARAM_FIELD_THREAD_MODE; worker_params.thread_mode = UCS_THREAD_MODE_SINGLE; status = ucp_worker_create(ucp_context, &worker_params, &ucp_worker); if (status != UCS_OK) { goto err_cleanup; } status = ucp_worker_get_address(ucp_worker, &local_addr, &local_addr_len); if (status != UCS_OK) { goto err_worker; } status = ucp_worker_get_efd(ucp_worker, &epoll_fd); if (status != UCS_OK) { goto err; } printf("[0x%x] local address length: %zu\n", (unsigned int)pthread_self(), local_addr_len); /* OOB connection establishment */ if (server) { peer_addr_len = local_addr_len; oob_sock = run_client(server); if (oob_sock < 0) { goto err_addr; } ret = recv(oob_sock, &addr_len, sizeof(addr_len), 0); if (ret < 0) { fprintf(stderr, "failed to receive address length\n"); goto err_addr; } peer_addr_len = addr_len; peer_addr = malloc(peer_addr_len); if (!peer_addr) { fprintf(stderr, "unable to allocate memory\n"); goto err_addr; } ret = recv(oob_sock, peer_addr, peer_addr_len, 0); if (ret < 0) { fprintf(stderr, "failed to receive address\n"); goto err_peer_addr; } } else { oob_sock = run_server(); if (oob_sock < 0) { goto err_peer_addr; } addr_len = local_addr_len; ret = send(oob_sock, &addr_len, sizeof(addr_len), 0); if (ret < 0 || ret != sizeof(addr_len)) { fprintf(stderr, "failed to send address length\n"); goto err_peer_addr; } ret = send(oob_sock, local_addr, local_addr_len, 0); if (ret < 0 || ret != local_addr_len) { fprintf(stderr, "failed to send address\n"); goto err_peer_addr; } } ret = run_test(NULL == server); /* Make sure remote is disconnected before destroying local worker */ barrier(oob_sock); close(oob_sock); err_peer_addr: free(peer_addr); err_addr: ucp_worker_release_address(ucp_worker, local_addr); err_worker: ucp_worker_destroy(ucp_worker); err_cleanup: ucp_cleanup(ucp_context); err: return ret; }
int mypipe(int *fd) { return pipe(fd); }
static int exec_conf(void) { int pipefd[2], stat, size; struct sigaction sa; sigset_t sset, osset; sigemptyset(&sset); sigaddset(&sset, SIGINT); sigprocmask(SIG_BLOCK, &sset, &osset); signal(SIGINT, SIG_DFL); sa.sa_handler = winch_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sigaction(SIGWINCH, &sa, NULL); *argptr++ = NULL; pipe(pipefd); pid = fork(); if (pid == 0) { sigprocmask(SIG_SETMASK, &osset, NULL); dup2(pipefd[1], 2); close(pipefd[0]); close(pipefd[1]); execv(args[0], args); _exit(EXIT_FAILURE); } close(pipefd[1]); bufptr = input_buf; while (1) { size = input_buf + sizeof(input_buf) - bufptr; size = read(pipefd[0], bufptr, size); if (size <= 0) { if (size < 0) { if (errno == EINTR || errno == EAGAIN) continue; perror("read"); } break; } bufptr += size; } *bufptr++ = 0; close(pipefd[0]); waitpid(pid, &stat, 0); if (do_resize) { init_wsize(); do_resize = 0; sigprocmask(SIG_SETMASK, &osset, NULL); return -1; } if (WIFSIGNALED(stat)) { printf("\finterrupted(%d)\n", WTERMSIG(stat)); exit(1); } #if 0 printf("\fexit state: %d\nexit data: '%s'\n", WEXITSTATUS(stat), input_buf); sleep(1); #endif sigpending(&sset); if (sigismember(&sset, SIGINT)) { printf("\finterrupted\n"); exit(1); } sigprocmask(SIG_SETMASK, &osset, NULL); return WEXITSTATUS(stat); }
int main(int argc, char *argv[]) { int n; int fd[2]; pid_t pid; char *pager, *argv0; char line[1024]; FILE *fp; if(argc != 2){ printf("usage: a.out <pathname>\n"); return -1; } if((fp = fopen(argv[1], "r")) == NULL){ printf("open file [%s] error: %s\n", argv[1], strerror(errno)); return -2; } if(pipe(fd) < 0){ perror("pipe"); return -3; } if((pid = fork()) < 0){ perror("fork"); return -4; }else if(pid > 0){ close(fd[0]); while(fgets(line, sizeof(line), fp) != NULL){ n = strlen(line); if(write(fd[1], line, n) != n){ perror("write"); return -5; } } if(ferror(fp)){ /*读文件结束或者读文件出错,fgets都会返回NULL,用ferror来判断是不是发生了错误*/ printf("read file [%s] error\n", argv[1]); return -6; } close(fd[1]); /*等待子进程退出*/ if(waitpid(pid, NULL, 0) < 0){ perror("waitpid"); return -7; } return 0; }else{ close(fd[1]); /*要先判断是不相等了才进行文件符复制*/ if(fd[0] != STDIN_FILENO){ if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO){ perror("dup2"); return -8; } close(fd[0]);/*要关闭该文件描述符,因为被复制出来了,共享文件描述符,以后都不用了*/ } /*文件描述符已被复制,子进程的标准输入是管道了,即复制前的fd[0]*/ /*获取页的大小*/ if((pager = getenv("PAGER")) == NULL) pager = DEF_PAGER; if((argv0 = strrchr(pager, '/')) != NULL) argv0++; else argv0 = pager; if(execl(pager, argv0, (char *)0) < 0){ perror("execl"); return -9; } return 0; } }
int proc_create(proc_obj_t* proc, char* bin_path, char** args) { pid_t child; int pfd1[2], pfd2[2]; char c; ttevent_t ev; ev.tte_events = TTEVT_SYSCALL|TTEVT_EXEC|TTEVT_EXIT| TTEVT_BPT_SSTEP|TTEVT_SIGNAL; ev.tte_opts = TTEO_NONE; /* ** Technique de Roumain avec des pipes ** pour synchoniser les deux process */ if (pipe(pfd1) < 0 || pipe(pfd2) < 0) return (-1); switch ((child = fork())) { case -1: return (-1); /* ** Child Process */ case 0: if (setpgid(0, 0) == -1) return (-1); if (ttrace(TT_PROC_SETTRC, 0, 0, 0, TT_VERSION, 0) == -1) return -1; /* tell parent we are SETTRC'ed */ if (write(pfd2[1], (void *)&c, sizeof c) != sizeof c) return (-1); /* wait for exec event to be set*/ if (read(pfd1[0], (void *)&c, sizeof c) != sizeof c) return (-1); close(pfd1[0]); close(pfd1[1]); close(pfd2[0]); close(pfd2[1]); if (execvp(bin_path, args) == -1) return (-1); return (-1); } /* ** Ftrace process */ if (read(pfd2[0], (void *)&c, sizeof c) != sizeof c) return (-1); proc->pid = child; if (ttrace(TT_PROC_SET_EVENT_MASK, proc->pid, 0, (uint64_t)&ev, sizeof ev, 0) == -1) return (-1); /* tell the child to exec */ if (write(pfd1[1], (void *)&c, sizeof c) != sizeof c) return (-1); close(pfd1[0]); close(pfd1[1]); close(pfd2[0]); close(pfd2[1]); /* ** TODO: ** Attendre la fin de l'exec() ** set des breakpoints */ proc->luse = NULL; if (proc_wait_debug_event(proc, NULL) == -1) return (-1); return child; }
static int do_one_test (void) { in_sh_body = 0; cleanups = 0; if (pipe (fd) != 0 || pipe (fd + 2) != 0) { puts ("pipe failed"); return 1; } pthread_t th; if (pthread_create (&th, NULL, tf, NULL) != 0) { puts ("create failed"); return 1; } int r = pthread_barrier_wait (&b); if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("parent thread: barrier_wait failed"); return 1; } sleep (1); r = pthread_kill (th, SIGHUP); if (r) { errno = r; printf ("pthread_kill failed %m\n"); return 1; } while (in_sh_body == 0) sleep (1); if (pthread_cancel (th) != 0) { puts ("cancel failed"); return 1; } /* This will cause the read in the child to return. */ close (fd[0]); close (fd[1]); close (fd[2]); close (fd[3]); void *ret; if (pthread_join (th, &ret) != 0) { puts ("join failed"); return 1; } if (ret != PTHREAD_CANCELED) { puts ("result is wrong"); return 1; } if (cleanups != 0x1234L) { printf ("called cleanups %lx\n", cleanups); return 1; } return 0; }
int main(int argc[], char *argv[]){ int dimensao; float **matriz; float *vetorIndependente; int i, j, t, l, status_t, tam, *vet; int linha = 0; pid_t pid = 1; printf("Digite o dimensao da matriz seguido dos elementos e do vetor independente:"); scanf("%d", &dimensao); int TAM_BUFFER = dimensao+3; matriz = le_matriz(dimensao, dimensao); vetorIndependente = le_vetor(dimensao); //criação dos filhos int REF = 1; int inicio = 0; while(REF != dimensao){ int fd[2]; float buffer[TAM_BUFFER]; if(pipe(fd) == -1) printf("Erro na funcao que cria o descritor de arquivo!\n"); for(i=0; i<(dimensao-REF); i++){ if(pid!=0){ sleep(10); pid = fork(); inicio = i+REF; // inicio vai determinar a linha que será usada como referencia } } if(pid == 0){ float constante = (matriz[inicio][REF-1]) / (matriz[REF-1][REF-1]); float *vetor_auxiliar; vetor_auxiliar = calloc(dimensao+2,sizeof(float)); int w = REF-1; for(i=(REF-1); i<dimensao; i++){ vetor_auxiliar[w] = matriz[inicio][i] - ((matriz[REF-1][i])*constante); w++; } vetor_auxiliar[w] = vetorIndependente[inicio] - ((vetorIndependente[REF-1])*constante); vetor_auxiliar[w+1] = inicio; close(fd[0]); write(fd[1], vetor_auxiliar, (TAM_BUFFER)*sizeof(float)); exit(0); sleep(5); } // FIM DA EXECUÇÃO DOS FILHOS if (pid != 0){ close(fd[1]); for (l=0; l<dimensao-REF; l++){ read(fd[0], buffer, sizeof(buffer)); linha = (buffer[dimensao+1]); int y = 0; for(i=0; i<dimensao+1; i++){ matriz[linha][i] = buffer[y]; y++; } vetorIndependente[linha] = buffer[dimensao]; } } REF += 1; } sleep(5); // REALIZANDO A ELIMINAÇÃO float *vetor_resultados = NULL; vetor_resultados = (float *) calloc(dimensao, sizeof(float)); float soma = 0; for (i = dimensao; i>0; i=i-1){ soma = vetorIndependente[i-1]; for (j=i; j<dimensao; j++){ soma += (matriz[i-1][j]*vetor_resultados[j]) * (-1); } vetor_resultados[i-1] = soma / matriz[i-1][i-1]; } // REALIZANDO A ELIMINAÇÃO printf("\n"); //Imprimindo o vetor resultado for(i=0; i<dimensao; i++){ printf("%f ",vetor_resultados[i]); } free_matrix(dimensao, matriz); free_vector(vetorIndependente); return 0; }
/** Fork and exec entire filter chain. * @param chain The head of the chain. * @return true on success. */ bool filter_apply_chain (struct filter * chain) { int pid, pipes[2]; int r; const int readsz = 512; char *buf; /* Tricky recursion, since we want to begin the chain * at the END. Why? Because we need all the forked processes * to be children of the main flex process. */ if (chain) filter_apply_chain (chain->next); else return true; /* Now we are the right-most unprocessed link in the chain. */ fflush (stdout); fflush (stderr); if (pipe (pipes) == -1) flexerror (_("pipe failed")); if ((pid = fork ()) == -1) flexerror (_("fork failed")); if (pid == 0) { /* child */ /* We need stdin (the FILE* stdin) to connect to this new pipe. * There is no portable way to set stdin to a new file descriptor, * as stdin is not an lvalue on some systems (BSD). * So we dup the new pipe onto the stdin descriptor and use a no-op fseek * to sync the stream. This is a Hail Mary situation. It seems to work. */ close (pipes[1]); clearerr(stdin); if (dup2 (pipes[0], fileno (stdin)) == -1) flexfatal (_("dup2(pipes[0],0)")); close (pipes[0]); fseek (stdin, 0, SEEK_CUR); /* run as a filter, either internally or by exec */ if (chain->filter_func) { int r; if ((r = chain->filter_func (chain)) == -1) flexfatal (_("filter_func failed")); exit (0); } else { execvp (chain->argv[0], (char **const) (chain->argv)); lerrsf_fatal ( _("exec of %s failed"), chain->argv[0]); } exit (1); } /* Parent */ close (pipes[0]); if (dup2 (pipes[1], fileno (stdout)) == -1) flexfatal (_("dup2(pipes[1],1)")); close (pipes[1]); fseek (stdout, 0, SEEK_CUR); return true; }
static int do_test (void) { int result = 0; int piped[2]; /* Make a pipe that we will never write to, so we can block reading it. */ if (pipe (piped) < 0) { perror ("pipe"); return 1; } /* Test for aio_cancel() detecting invalid file descriptor. */ { struct aiocb cb; int fd = -1; cb.aio_fildes = fd; cb.aio_offset = 0; cb.aio_buf = NULL; cb.aio_nbytes = 0; cb.aio_reqprio = 0; cb.aio_sigevent.sigev_notify = SIGEV_NONE; errno = 0; /* Case one: invalid fds that match. */ if (aio_cancel (fd, &cb) != -1 || errno != EBADF) { if (errno == ENOSYS) { puts ("no aio support in this configuration"); return 0; } puts ("aio_cancel( -1, {-1..} ) did not return -1 or errno != EBADF"); ++result; } cb.aio_fildes = -2; errno = 0; /* Case two: invalid fds that do not match; just print warning. */ if (aio_cancel (fd, &cb) != -1 || errno != EBADF) puts ("aio_cancel( -1, {-2..} ) did not return -1 or errno != EBADF"); } /* Test for aio_fsync() detecting bad fd. */ { struct aiocb cb; int fd = -1; cb.aio_fildes = fd; cb.aio_offset = 0; cb.aio_buf = NULL; cb.aio_nbytes = 0; cb.aio_reqprio = 0; cb.aio_sigevent.sigev_notify = SIGEV_NONE; errno = 0; /* Case one: invalid fd. */ if (aio_fsync (O_SYNC, &cb) != -1 || errno != EBADF) { puts ("aio_fsync( op, {-1..} ) did not return -1 or errno != EBADF"); ++result; } } /* Test for aio_suspend() suspending even if completed elements in list. */ { #define BYTES 8 const int ELEMS = 2; int i, r, fd; static char buff[BYTES]; char name[] = "/tmp/aio7.XXXXXX"; struct timespec timeout; static struct aiocb cb0, cb1; struct aiocb *list[ELEMS]; fd = mkstemp (name); if (fd < 0) error (1, errno, "creating temp file"); if (unlink (name)) error (1, errno, "unlinking temp file"); if (write (fd, "01234567", BYTES) != BYTES) error (1, errno, "writing to temp file"); cb0.aio_fildes = fd; cb0.aio_offset = 0; cb0.aio_buf = buff; cb0.aio_nbytes = BYTES; cb0.aio_reqprio = 0; cb0.aio_sigevent.sigev_notify = SIGEV_NONE; r = aio_read (&cb0); if (r != 0) error (1, errno, "reading from file"); while (aio_error (&(cb0)) == EINPROGRESS) usleep (10); for (i = 0; i < BYTES; i++) printf ("%c ", buff[i]); printf ("\n"); /* At this point, the first read is completed, so start another one on the read half of a pipe on which nothing will be written. */ cb1.aio_fildes = piped[0]; cb1.aio_offset = 0; cb1.aio_buf = buff; cb1.aio_nbytes = BYTES; cb1.aio_reqprio = 0; cb1.aio_sigevent.sigev_notify = SIGEV_NONE; r = aio_read (&cb1); if (r != 0) error (1, errno, "reading from file"); /* Now call aio_suspend() with the two reads. It should return * immediately according to the POSIX spec. */ list[0] = &cb0; list[1] = &cb1; timeout.tv_sec = 3; timeout.tv_nsec = 0; r = aio_suspend ((const struct aiocb * const *) list, ELEMS, &timeout); if (r == -1 && errno == EAGAIN) { puts ("aio_suspend([done,blocked],2,3) suspended thread"); ++result; } /* Note that CB1 is still pending, and so cannot be an auto variable. Thus we also test that exiting with an outstanding request works. */ } return result; }
void startcmd(Conn *c, char *cmd, int *kidpid, int *kidin) { int i, pid, kpid; int pfd[3][2]; char *dir; char *sysname, *tz; Msg *m; Waitmsg *w; for(i=0; i<3; i++) if(pipe(pfd[i]) < 0) sysfatal("pipe: %r"); sysname = getenv("sysname"); tz = getenv("timezone"); switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){ case -1: sysfatal("fork: %r"); case 0: switch(kpid = rfork(RFPROC|RFNOTEG|RFENVG|RFFDG)){ case -1: sysfatal("fork: %r"); case 0: for(i=0; i<3; i++){ if(dup(pfd[i][1], i) < 0) sysfatal("dup: %r"); close(pfd[i][0]); close(pfd[i][1]); } putenv("user", c->user); if(sysname) putenv("sysname", sysname); if(tz) putenv("tz", tz); dir = smprint("/usr/%s", c->user); if(dir == nil || chdir(dir) < 0) chdir("/"); if(cmd){ putenv("service", "rx"); execl("/bin/rc", "rc", "-lc", cmd, nil); sysfatal("cannot exec /bin/rc: %r"); }else{ putenv("service", "con"); execl("/bin/ip/telnetd", "telnetd", "-tn", nil); sysfatal("cannot exec /bin/ip/telnetd: %r"); } default: *kidpid = kpid; rendezvous(kidpid, 0); for(;;){ if((w = wait()) == nil) sysfatal("wait: %r"); if(w->pid == kpid) break; free(w); } if(w->msg[0]){ m = allocmsg(c, SSH_MSG_DISCONNECT, 4+strlen(w->msg)); putstring(m, w->msg); sendmsg(m); }else{ m = allocmsg(c, SSH_SMSG_EXITSTATUS, 4); putlong(m, 0); sendmsg(m); } for(i=0; i<3; i++) close(pfd[i][0]); free(w); exits(nil); break; } default: atexitkill(pid); rendezvous(kidpid, 0); break; } for(i=0; i<3; i++) close(pfd[i][1]); copyout(c, pfd[1][0], SSH_SMSG_STDOUT_DATA); copyout(c, pfd[2][0], SSH_SMSG_STDERR_DATA); *kidin = pfd[0][0]; }
int forkinet(int port) { FILE *fp; char logbuf[256]; int sock; int pipeid[2]; pid_t cpid; /* process id of the child */ pid_t pid; /* create the pipe */ if (pipe(pipeid) <0) return -1; /* The pipe was non-blocking, but this causes a problem if the client cannot cope with the incoming data rate from multiplexed streams. if ((status=fcntl(pipeid[1],F_GETFL))==-1) return -1; status|=O_NONBLOCK; if ((status=fcntl(pipeid[1],F_SETFL,status))==-1) return -1; */ if ((cpid=fork()) !=0) { close(pipeid[0]); return pipeid[1]; } close(pipeid[1]); loginfo(logfname,"Child Server Process Starting"); sock=createsocket(&port); if (sock==-1) { loginfo(logfname,"Failed to create socket"); close(pipeid[0]); exit(0); } fp=fopen(pname,"w"); fprintf(fp,"%d\n",port); fclose(fp); sprintf(logbuf,"Listening on port %d.",port); loginfo(logfname,logbuf); sprintf(logbuf,"Port number recorded in file %s.",pname); loginfo(logfname,logbuf); sprintf(logbuf,"Time of last packet recorded in file %s.",timefname); loginfo(logfname,logbuf); fp=fopen(pidname,"w"); pid=getppid(); sprintf(logbuf,"Process ID recorded in file %s.",pidname); loginfo(logfname,logbuf); sprintf(logbuf,"Parent PID %d.",(int) pid); loginfo(logfname,logbuf); fprintf(fp,"%d\n",(int) pid); pid=getpid(); sprintf(logbuf,"Child PID %d.",(int) pid); loginfo(logfname,logbuf); fprintf(fp,"%d\n",(int) pid); fclose(fp); processsocket(sock,pipeid[0]); close(sock); close(pipeid[0]); loginfo(logfname,"Child Server Process Terminating"); exit(0); return -1; }
int main(){ int a2b[2], b2a[2]; pipe(a2b); pipe(b2a); int num; printf("Enter number: "); scanf("%d", &num); //forking switch(fork()) { //error handling case -1: printf("Error at forking\n!"); break; //child case 0: close(a2b[W]); close(b2a[R]); while(1){ read(a2b[R], &num, sizeof(int)); if( num % 2 == 0) { num = num / 2; printf("S number: %d\n", num); write(b2a[W], &num, sizeof(int)); } else { printf("DONE"); break; } } close(a2b[R]); close(b2a[W]); exit(0); break; default: close(a2b[R]); close(b2a[W]); write(a2b[W], &num, sizeof(int)); while(1){ read(b2a[R], &num, sizeof(int)); if(num / 3 != 0){ num = num /3; printf("F. number: %d\n", num); write(a2b[W], &num, sizeof(int)); } else { printf("Done"); break; } } close(a2b[W]); close(b2a[R]); wait(0); break; } return 0; }
int main(int argc, char *argv[]){ //DO NOT EDIT char * cmd[] = {"cat", NULL}; int cpid; int pfd_1[2] = {-1,-1} ,pfd_2[2] = {-1,-1}; char c; //TODO: add neccesary pipeline code if ( pipe(pfd_1) < 0){ perror("pipe"); return 1; } if ( pipe(pfd_2) < 0){ perror("pipe"); return 1; } if( (cpid = fork()) ) { /* CHILD 1 */ //TODO: add neccesary pipeline code close(0); close(1); dup2(pfd_1[0], 0); dup2(pfd_2[1], 1); if( (cpid = fork()) ) { /* CHILD 2*/ //TODO: add neccesary pipeline code close(0); //duplicate reading end to stdin dup2(pfd_2[0], 0); //close the writing end close(pfd_2[1]); //DO NOT EDIT///////////////////////// //read from pfd_2 and write to stdout while(1){ if(read(pfd_2[0],&c,1) > 0){ write(1,&c,1); }else{ exit(0); } } //////////////////////////////////// }else if(cpid == 0){ /* CHILD 1 */ //TODO: add neccesary pipeline code close(pfd_2[0]); //close(pfd_2[1]); close(0); close(1); //DO NOT EDIT///////////////////////// //read from pfd_1 and write to pfd_2 while(1){ if(read(pfd_1[0],&c,1) > 0){ write(pfd_2[1],&c,1); }else{ exit(0); } } //////////////////////////////////// } }else if(cpid == 0){ /* PARENT */ //close stdout should duplicate pipe onto it close(1); //TODO: add neccesary pipeline and duplication dup2(pfd_1[1], 1); close(pfd_1[0]); //DO NOT EDIT///////////////////////// //execute the cat command execvp(cmd[0], cmd); perror("exec failure"); _exit(1); //////////////////////////////////// } }
int lisp_pipe(int pipefd[2]) { return pipe(pipefd); }
const size_t assemble_armv7( uint8_t *const bytecode, const size_t bytecode_sz, const char *const assembly, const size_t asm_sz) { size_t sz = 0; char path[PATH_MAX]; snprintf(path, sizeof(path), "/tmp/rappel-output.XXXXXX"); const int t = mkstemp(path); if (t == -1) { perror("mkstemp"); exit(EXIT_FAILURE); } REQUIRE (unlink(path) == 0); int fildes[2] = {-1, -1}; REQUIRE (pipe(fildes) == 0); const pid_t asm_pid = fork(); if (asm_pid < 0) { perror("fork"); exit(EXIT_FAILURE); } else if (asm_pid == 0) { _child_assemble(fildes, t); // Not reached abort(); } verbose_printf("as is pid %d\n", asm_pid); REQUIRE (close(fildes[0]) == 0); write_data(fildes[1], (uint8_t *)assembly, asm_sz); REQUIRE (close(fildes[1]) == 0); int asm_status = -1; REQUIRE (waitpid(asm_pid, &asm_status, 0) != -1); if (WIFSIGNALED(asm_status)) { fprintf(stderr, "as exited with signal %d.\n", WTERMSIG(asm_status)); } else if (WIFEXITED(asm_status) && WEXITSTATUS(asm_status)) { fprintf(stderr, "as exited %d.\n", WEXITSTATUS(asm_status)); goto exit; } REQUIRE (lseek(t, SEEK_SET, 0) != -1); int results[2] = {-1, -1}; REQUIRE (pipe(results) == 0); const pid_t objcopy_pid = fork(); if (objcopy_pid < 0) { perror("fork"); exit(EXIT_FAILURE); } else if (objcopy_pid == 0) { _child_objcopy(results, t); // Not reached abort(); } verbose_printf("objcopy is pid %d\n", objcopy_pid); REQUIRE (close(results[1]) == 0); mem_assign(bytecode, bytecode_sz, TRAP, TRAP_SZ); sz = read_data(results[0], bytecode, bytecode_sz); REQUIRE (close(results[0]) == 0); if (sz >= bytecode_sz) { fprintf(stderr, "Too much bytecode to handle, exiting...\n"); exit(EXIT_FAILURE); } int objcopy_status = -1; REQUIRE (waitpid(objcopy_pid, &objcopy_status, 0) != -1); if (WIFEXITED(objcopy_status) && WIFSIGNALED(objcopy_status)) fprintf(stderr, "objcopy exited with signal %d.\n", WTERMSIG(objcopy_status)); else if (WIFEXITED(objcopy_status) && WEXITSTATUS(objcopy_status)) fprintf(stderr, "objcopy exited %d.\n", WEXITSTATUS(objcopy_status)); exit: REQUIRE (close(t) == 0); return sz; }
/** A work queue is a mechanism to allow thread-to-thread * communication in a libevent-based, multithreaded system. * * One thread can send work to another thread. The receiving thread * should be libevent-based, with a processing loop handled by * libevent. * * Use work_queue_init() to initialize a work_queue structure, * where the work_queue structure memory is owned by the caller. * * Returns true on success. */ bool work_queue_init(work_queue *m, struct event_base *event_base) { assert(m != NULL); memset(m, 0, sizeof(work_queue)); pthread_mutex_init(&m->work_lock, NULL); m->work_head = NULL; m->work_tail = NULL; m->num_items = 0; m->tot_sends = 0; m->tot_recvs = 0; m->event_base = event_base; assert(m->event_base != NULL); int fds[2] = {0}; #ifdef WIN32 struct sockaddr_in serv_addr; int sockfd; if ((sockfd = createLocalListSock(&serv_addr)) < 0 || createLocalSocketPair(sockfd,fds,&serv_addr) == -1) { fprintf(stderr, "Can't create notify pipe: %s", strerror(errno)); return false; } #else if (pipe(fds)) { perror("Can't create notify pipe"); return false; } #endif m->recv_fd = fds[0]; m->send_fd = fds[1]; event_set(&m->event, m->recv_fd, EV_READ | EV_PERSIST, work_recv, m); event_base_set(m->event_base, &m->event); if (event_add(&m->event, 0) == 0) { #ifdef WORK_DEBUG moxi_log_write("work_queue_init %x %x %x %d %d %u %llu\n", (int) pthread_self(), (int) m, (int) m->event_base, m->send_fd, m->recv_fd, m->work_head != NULL, m->tot_sends); #endif return true; } #ifdef WORK_DEBUG moxi_log_write("work_queue_init error\n"); #endif return false; }
int start_async(struct async *async) { int need_in, need_out; int fdin[2], fdout[2]; int proc_in, proc_out; need_in = async->in < 0; if (need_in) { if (pipe(fdin) < 0) { if (async->out > 0) close(async->out); return error("cannot create pipe: %s", strerror(errno)); } async->in = fdin[1]; } need_out = async->out < 0; if (need_out) { if (pipe(fdout) < 0) { if (need_in) close_pair(fdin); else if (async->in) close(async->in); return error("cannot create pipe: %s", strerror(errno)); } async->out = fdout[0]; } if (need_in) proc_in = fdin[0]; else if (async->in) proc_in = async->in; else proc_in = -1; if (need_out) proc_out = fdout[1]; else if (async->out) proc_out = async->out; else proc_out = -1; #ifdef NO_PTHREADS /* Flush stdio before fork() to avoid cloning buffers */ fflush(NULL); async->pid = fork(); if (async->pid < 0) { error("fork (async) failed: %s", strerror(errno)); goto error; } if (!async->pid) { if (need_in) close(fdin[1]); if (need_out) close(fdout[0]); git_atexit_clear(); exit(!!async->proc(proc_in, proc_out, async->data)); } mark_child_for_cleanup(async->pid); if (need_in) close(fdin[0]); else if (async->in) close(async->in); if (need_out) close(fdout[1]); else if (async->out) close(async->out); #else if (!main_thread_set) { /* * We assume that the first time that start_async is called * it is from the main thread. */ main_thread_set = 1; main_thread = pthread_self(); pthread_key_create(&async_key, NULL); pthread_key_create(&async_die_counter, NULL); set_die_routine(die_async); set_die_is_recursing_routine(async_die_is_recursing); } if (proc_in >= 0) set_cloexec(proc_in); if (proc_out >= 0) set_cloexec(proc_out); async->proc_in = proc_in; async->proc_out = proc_out; { int err = pthread_create(&async->tid, NULL, run_thread, async); if (err) { error("cannot create thread: %s", strerror(err)); goto error; } } #endif return 0; error: if (need_in) close_pair(fdin); else if (async->in) close(async->in); if (need_out) close_pair(fdout); else if (async->out) close(async->out); return -1; }
/* * invoke RSH */ int rsh_exec(struct socket *so, struct socket *ns, char *user, char *host, char *args) { int fd[2]; int fd0[2]; int s; char buff[256]; DEBUG_CALL("rsh_exec"); DEBUG_ARG("so = %lx", (long)so); if (pipe(fd)<0) { lprint("Error: pipe failed: %s\n", strerror(errno)); return 0; } /* #ifdef HAVE_SOCKETPAIR */ #if 1 if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) { close(fd[0]); close(fd[1]); lprint("Error: openpty failed: %s\n", strerror(errno)); return 0; } #else if (slirp_openpty(&fd0[0], &fd0[1]) == -1) { close(fd[0]); close(fd[1]); lprint("Error: openpty failed: %s\n", strerror(errno)); return 0; } #endif switch(fork()) { case -1: lprint("Error: fork failed: %s\n", strerror(errno)); close(fd[0]); close(fd[1]); close(fd0[0]); close(fd0[1]); return 0; case 0: close(fd[0]); close(fd0[0]); /* Set the DISPLAY */ if (x_port >= 0) { #ifdef HAVE_SETENV sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); setenv("DISPLAY", buff, 1); #else sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen); putenv(buff); #endif } dup2(fd0[1], 0); dup2(fd0[1], 1); dup2(fd[1], 2); for (s = 3; s <= 255; s++) close(s); execlp("rsh","rsh","-l", user, host, args, NULL); /* Ooops, failed, let's tell the user why */ sprintf(buff, "Error: execlp of %s failed: %s\n", "rsh", strerror(errno)); write(2, buff, strlen(buff)+1); close(0); close(1); close(2); /* XXX */ exit(1); default: close(fd[1]); close(fd0[1]); ns->s=fd[0]; so->s=fd0[0]; return 1; } }
int spawn(char *program, char *argv[], int sin, int sout, int serr, int search, char *envp[], char *pty_name, int wait, char *pwd) { pid_t pid; int fd; int channel[2]; sigset_t sset; int failure_code = 2; channel[0] = -1; channel[1] = -1; if (!pipe(channel)) { if (-1==fcntl(channel[1], F_SETFD, FD_CLOEXEC)) { close(channel[1]); channel[1] = -1; } } pid = fork(); if (pid) { if ((-1 != pid) && (-1 != channel[1])) { int child_errno = 0; int bytes = sizeof(int); int n; char *p = (char*)&child_errno; close(channel[1]); /* Try to read child errno from channel. */ while ((bytes > 0) && (n = read(channel[0], p, bytes))) { if (-1 == n) { if (EINTR == errno) { continue; } else { break; } } else { bytes -= n; p += n; } } close(channel[0]); if (child_errno) { int status; waitpid(pid, &status, 0); /* Our convention to tell Lisp that it was the exec or chdir that failed, not the fork. */ /* FIXME: there are other values waitpid(2) can return. */ if (WIFEXITED(status)) { pid = -WEXITSTATUS(status); } errno = child_errno; } } return pid; } close (channel[0]); /* Put us in our own process group, but only if we need not * share stdin with our parent. In the latter case we claim * control of the terminal. */ if (sin >= 0) { #if defined(LISP_FEATURE_HPUX) || defined(LISP_FEATURE_OPENBSD) setsid(); #elif defined(LISP_FEATURE_DARWIN) setpgid(0, getpid()); #elif defined(SVR4) || defined(__linux__) || defined(__osf__) || defined(__GLIBC__) setpgrp(); #else setpgrp(0, getpid()); #endif } else { tcsetpgrp(0, getpgrp()); } /* unblock signals */ sigemptyset(&sset); sigprocmask(SIG_SETMASK, &sset, NULL); /* If we are supposed to be part of some other pty, go for it. */ if (pty_name) set_pty(pty_name); else { /* Set up stdin, stdout, and stderr */ if (sin >= 0) dup2(sin, 0); if (sout >= 0) dup2(sout, 1); if (serr >= 0) dup2(serr, 2); } /* Close all other fds. */ #ifdef SVR4 for (fd = sysconf(_SC_OPEN_MAX)-1; fd >= 3; fd--) if (fd != channel[1]) close(fd); #else for (fd = getdtablesize()-1; fd >= 3; fd--) if (fd != channel[1]) close(fd); #endif if (pwd && chdir(pwd) < 0) { failure_code = 3; } else { if (envp) { environ = envp; } /* Exec the program. */ if (search) execvp(program, argv); else execv(program, argv); } /* When exec or chdir fails and channel is available, send the errno value. */ if (-1 != channel[1]) { int our_errno = errno; int bytes = sizeof(int); int n; char *p = (char*)&our_errno; while ((bytes > 0) && (n = write(channel[1], p, bytes))) { if (-1 == n) { if (EINTR == errno) { continue; } else { break; } } else { bytes -= n; p += n; } } close(channel[1]); } _exit(failure_code); }
void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize) { int msgpipe[2]; struct android_app* android_app; (void)savedState; (void)savedStateSize; RARCH_LOG("Creating Native Activity: %p\n", activity); activity->callbacks->onDestroy = onDestroy; activity->callbacks->onStart = onStart; activity->callbacks->onResume = onResume; activity->callbacks->onSaveInstanceState = NULL; activity->callbacks->onPause = onPause; activity->callbacks->onStop = onStop; activity->callbacks->onConfigurationChanged = onConfigurationChanged; activity->callbacks->onLowMemory = NULL; activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; activity->callbacks->onInputQueueCreated = onInputQueueCreated; activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; // these are set only for the native activity, and are reset when it ends ANativeActivity_setWindowFlags(activity, AWINDOW_FLAG_KEEP_SCREEN_ON | AWINDOW_FLAG_FULLSCREEN, 0); if (pthread_key_create(&thread_key, jni_thread_destruct)) RARCH_ERR("Error initializing pthread_key\n"); android_app = (struct android_app*)calloc(1, sizeof(*android_app)); if (!android_app) { RARCH_ERR("Failed to initialize android_app\n"); return; } memset(android_app, 0, sizeof(struct android_app)); android_app->activity = activity; android_app->mutex = slock_new(); android_app->cond = scond_new(); if (pipe(msgpipe)) { RARCH_ERR("could not create pipe: %s.\n", strerror(errno)); activity->instance = NULL; } android_app->msgread = msgpipe[0]; android_app->msgwrite = msgpipe[1]; android_app->thread = sthread_create(android_app_entry, android_app); // Wait for thread to start. slock_lock(android_app->mutex); while (!android_app->running) scond_wait(android_app->cond, android_app->mutex); slock_unlock(android_app->mutex); activity->instance = android_app; }