Skip to content

Instantly share code, notes, and snippets.

@patrickt
Created May 26, 2009 23:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save patrickt/118360 to your computer and use it in GitHub Desktop.
Save patrickt/118360 to your computer and use it in GitHub Desktop.
// We don't actually execute the command given in prog, as we don't want
// to have to split it up into its individual components. Instead, we execute
// all of its components as an argument to /bin/sh -c.
char *spawnedArgs[] = {(char*)_PATH_BSHELL, "-c", (char*)RSTRING_PTR(prog), NULL};
posix_spawn_file_actions_t actions;
if ((pipe(read_pipe) < 0) || (pipe(write_pipe) < 0)) {
posix_spawn_file_actions_destroy(&actions);
rb_sys_fail("pipe() failed.");
}
#define STREAM_OUTPUT read_pipe[0]
#define PROCESS_OUTPUT read_pipe[1]
#define STREAM_INPUT write_pipe[1]
#define PROCESS_INPUT write_pipe[0]
rb_sys_fail_unless(posix_spawn_file_actions_init(&actions), "could not init file actions");
rb_sys_fail_unless(posix_spawn_file_actions_adddup2(&actions, PROCESS_OUTPUT, STDOUT_FILENO),
"could not add dup2() to stdout");
rb_sys_fail_unless(posix_spawn_file_actions_addclose(&actions, PROCESS_OUTPUT), "");
errno = posix_spawn(&pid, spawnedArgs[0], &actions, NULL, spawnedArgs, *(_NSGetEnviron()));
if(errno != 0) {
int err = errno;
close(write_pipe[0]);
close(write_pipe[1]);
errno = err;
rb_sys_fail("posix_spawn failed.");
}
posix_spawn_file_actions_destroy(&actions);
if (convert_mode_string_to_fmode(mode) != FMODE_WRITABLE) {
// the mode was either 'r', 'r+', or 'w+', so make a read stream.
r = _CFReadStreamCreateFromFileDescriptor(NULL, PROCESS_INPUT);
if (r != NULL) {
CFReadStreamOpen(r);
CFMakeCollectable(r);
GC_WB(&io_struct->readStream, r);
}
}
if (convert_mode_string_to_fmode(mode) != FMODE_READABLE) {
// the mode was either 'r+', 'w', or 'w+', so make a write stream.
w = _CFWriteStreamCreateFromFileDescriptor(NULL, PROCESS_OUTPUT);
if (w != NULL) {
CFWriteStreamOpen(w);
CFMakeCollectable(w);
GC_WB(&io_struct->writeStream, w);
} else {
printf("oh god, things didn't work...");
}
}
// TODO: Eventually make the ungetc_buf a ByteString
io_struct->fd = PROCESS_OUTPUT;
io_struct->pipe = read_pipe[1];
io_struct->ungetc_buf = NULL;
io_struct->ungetc_buf_len = 0;
io_struct->ungetc_buf_pos = 0;
io_struct->pid = pid;
io_struct->sync = 0;
rb_objc_keep_for_exit_finalize((VALUE)io);
return io;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment