Created
May 26, 2009 23:36
-
-
Save patrickt/118360 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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