It seems like there's no good library function I can use for popen with array of arguments instead of single shell-interpreted shell. So I implemented my own one: c h.popen_arr.h#pragma oncestruct FILE;// Implemented by Vitaly _Vi Shukela in 2013, License=MIT/*** Fork and exec the program, enabling stdio access to stdin and stdout of the program* You may close opened streams with fclose.* Note: the procedure does no signal handling except of signal(SIGPIPE, SIG_IGN);* You should waitpid for the returned PID to collect the zombie or use signal(SIGCHLD, SIG_IGN);** @arg in stdin of the program, to be written to. If NULL then not redirected* @arg out stdout of the program, to be read from. If NULL then not redirected* @arg program full path of the program, without reference to $PATH* @arg argv NULL terminated array of strings, program arguments (includiong program name)* @arg envp NULL terminated array of environment variables, NULL => preserve environment* @return PID of the program or -1 if failed*/int popen2_arr (FILE** in, FILE** out, const char* program, const char* const argv[], const char* const envp[]);/** like popen2_arr, but uses execvp/execvpe instead of execve/execv, so looks up $PATH */int popen2_arr_p(FILE** in, FILE** out, const char* program, const char* const argv[], const char* const envp[]);/*** Simplified interface to popen2_arr.* You may close the returned stream with fclose.* Note: the procedure does no signal handling except of signal(SIGPIPE, SIG_IGN);* You should wait(2) after closing the descriptor to collect zombie process or use signal(SIGCHLD, SIG_IGN)** @arg program program name, can rely on $PATH* @arg argv program arguments, NULL-terminated const char* array* @arg pipe_into_program 1 to be like popen(...,w), 0 to be like popen(...,r)* @return FILE* instance or NULL if error*/FILE* popen_arr(const char* program, const char* const argv[], int pipe_into_program);popen_arr.c#define _GNU_SOURCE // execvpe #include <stdio.h>#include <unistd.h>#include <errno.h>#include <signal.h>#include popen_arr.h// Implemented by Vitaly _Vi Shukela in 2013, License=MITstatic int popen2_impl(FILE** in, FILE** out,  const char* program, const char* const argv[], const char* const envp[], int lookup_path) {    int child_stdout = -1;    int child_stdin = -1;    int to_be_written = -1;    int to_be_read = -1;    if(in) {        int p[2]={-1,-1};         int ret = pipe(p);        if(ret!=0) { return -1; }        to_be_written=p[1];        child_stdin =p[0];        *in = fdopen(to_be_written, w);        if (*in == NULL) {            close(to_be_written);            close(child_stdin);            return -1;        }    }    if(out) {        int p[2]={-1,-1};        int ret = pipe(p);        if(ret!=0) {            if (in) {               close(child_stdin);               fclose(*in);               *in = NULL;            }            return -1;        }        to_be_read   =p[0];        child_stdout=p[1];        *out = fdopen(to_be_read, r);    }    int childpid = fork();    if(!childpid) {       if(child_stdout!=-1) {           close(to_be_read);           dup2(child_stdout, 1);           close(child_stdout);       }       if(child_stdin!=-1) {           close(to_be_written);           dup2(child_stdin, 0);           close(child_stdin);       }       if (lookup_path) {           if (envp) {               execvpe(program, (char**)argv, (char**)envp);           } else {               execvp (program, (char**)argv);           }       } else {           if (envp) {               execve(program, (char**)argv, (char**)envp);           } else {               execv (program, (char**)argv);           }       }       _exit(ENOSYS);    }    if(child_stdout!=-1) {        close(child_stdout);    }    if(child_stdin!=-1) {        close(child_stdin);    }    return childpid;}int popen2_arr  (FILE** in, FILE** out,  const char* program, const char* const argv[], const char* const envp[]){    signal(SIGPIPE, SIG_IGN);    return popen2_impl(in, out, program, argv, envp, 0);}int popen2_arr_p(FILE** in, FILE** out,  const char* program, const char* const argv[], const char* const envp[]){    signal(SIGPIPE, SIG_IGN);    return popen2_impl(in, out, program, argv, envp, 1);}FILE* popen_arr(const char* program, const char* const argv[], int pipe_into_program) {    FILE* f = NULL;    if (pipe_into_program) {        popen2_arr_p(&f, NULL, program, argv, NULL);    } else {        popen2_arr_p(NULL, &f, program, argv, NULL);    }    return f;}Do you have any advice on promoting it from just a project's code snippet into a reusable little library? Is API good? Shall it provide more features (at expence of being complexier) or more simpler (but a bit tricker to use)? Are there obviously bad parts of the code?
popen with array of arguments
c;linux