Hi all, I am using apr_proc_create() to run a process in the middle of parsing a command line (think something similar to bash completion), and have run into a problem.
Key to both the replxx and the libedit libraries is that stdin has to be set unbuffered so that key bindings can be processed immediately. After apr_proc_create() returns, stdin of the parent process finds itself reset back to linebuffered mode, and both command line libraries break. Modifying the replxx library to “fix” stdin after calling apr_proc_create() works around the problem, but I’ll have to do this somehow for libedit as well. Is there something that can be done to make apr_proc_create() not touch the parent’s stdin, stdout and stderr at all? Tried lots of code combinations, the current incarnation looks like this: if ((status = apr_procattr_create(&procattr, first->pool)) != APR_SUCCESS) { apr_file_printf(d->err, "cannot create procattr: %pm\n", &status); break; } // if ((status = apr_procattr_detach_set(procattr, 1)) // != APR_SUCCESS) { // apr_file_printf(d->err, "cannot set detached in procattr: %pm\n", &status); // break; // } if ((status = apr_file_pipe_create_ex(&ioread, &iowrite, APR_FULL_BLOCK, first->pool)) != APR_SUCCESS) { apr_file_printf(d->err, "cannot create pipes: %pm\n", &status); break; } if ((status = apr_procattr_child_in_set(procattr, NULL, NULL)) != APR_SUCCESS) { apr_file_printf(d->err, "cannot set stdin: %pm\n", &status); break; } // if ((status = apr_procattr_child_out_set(procattr, &iowrite, &ioread)) != APR_SUCCESS) { if ((status = apr_procattr_child_out_set(procattr, NULL, NULL)) != APR_SUCCESS) { apr_file_printf(d->err, "cannot set out pipe: %pm\n", &status); break; } if ((status = apr_procattr_child_err_set(procattr, NULL, NULL)) != APR_SUCCESS) { apr_file_printf(d->err, "cannot set stderr: %pm\n", &status); break; } // if ((status = apr_procattr_io_set(procattr, APR_NO_PIPE, APR_FULL_BLOCK, // APR_NO_PIPE)) != APR_SUCCESS) { // apr_file_printf(d->err, "cannot set io procattr: %pm\n", &status); // break; // } if ((status = apr_procattr_dir_set(procattr, command->r.sysconf)) != APR_SUCCESS) { apr_file_printf(d->err, "cannot set directory in procattr: %pm\n", &status); break; } if ((status = apr_procattr_cmdtype_set(procattr, APR_PROGRAM)) != APR_SUCCESS) { apr_file_printf(d->err, "cannot set command type in procattr: %pm\n", &status); break; } proc = apr_pcalloc(first->pool, sizeof(apr_proc_t)); if ((status = apr_proc_create(proc, command->r.libexec, (const char* const*) argv->elts, device_environment_make(d), procattr, first->pool)) != APR_SUCCESS) { apr_file_printf(d->err, "cannot run command: %pm\n", &status); break; } apr_file_close(proc->in); apr_file_close(proc->err); [do stuff that reads proc->out] apr_file_close(proc->out); if ((status = apr_proc_wait(proc, NULL, NULL, APR_WAIT)) != APR_CHILD_DONE) { apr_file_printf(d->err, "cannot wait for command: %pm\n", &status); break; } Regards, Graham —