meillo@0: /* This a snippet I found in sourceforge. I just changed the identing meillo@0: style to my own and deleted the main function. */ meillo@0: meillo@0: #include meillo@0: #include meillo@0: #include meillo@0: #include meillo@0: #include meillo@0: #include meillo@0: meillo@0: #include "peopen.h" meillo@0: #include "sysexits.h" meillo@0: meillo@0: #include "masqmail.h" meillo@0: meillo@0: static meillo@0: void destroy_argv(char **arr) meillo@0: { meillo@0: char *p = arr[0]; meillo@0: int i = 0; meillo@0: meillo@0: while(p){ meillo@0: free(p); meillo@0: p = arr[i++]; meillo@0: } meillo@0: free(arr); meillo@0: } meillo@0: meillo@0: static meillo@0: char **create_argv(const char *cmd, int count) meillo@0: { meillo@0: char buf[strlen(cmd)+1]; meillo@0: char **arr, *q; meillo@0: const char *p; meillo@0: int i = 0; meillo@0: meillo@0: arr = (char **)malloc(sizeof(char *) * count); meillo@0: meillo@0: p = cmd; meillo@0: while(*p && i < (count-1)){ meillo@0: while(*p && isspace(*p)) p++; meillo@0: q = buf; meillo@0: while(*p && !isspace(*p)) *q++ = *p++; meillo@0: *q = 0; meillo@0: arr[i++] = strdup(buf); meillo@0: while(*p && isspace(*p)) p++; meillo@0: } meillo@0: arr[i] = NULL; meillo@0: meillo@0: return arr; meillo@0: } meillo@0: meillo@0: FILE* peidopen(const char *command, meillo@0: const char *type, meillo@0: char *const envp [], meillo@0: int *ret_pid, meillo@0: uid_t uid, gid_t gid meillo@0: ) meillo@0: { meillo@0: enum { Read, Write } mode; meillo@0: int pipe_fd [2]; meillo@0: pid_t pid; meillo@0: meillo@0: if (command == NULL || type == NULL) { meillo@0: errno = EINVAL; meillo@0: return NULL; meillo@0: } meillo@0: meillo@0: if (strcmp (type, "r")) { meillo@0: if (strcmp (type, "w")) { meillo@0: errno = EINVAL; meillo@0: return NULL; meillo@0: } else meillo@0: mode = Write; meillo@0: } else meillo@0: mode = Read; meillo@0: meillo@0: if (pipe (pipe_fd) == -1) meillo@0: return NULL; meillo@0: meillo@0: switch (pid = fork ()) { meillo@0: case 0: /* child thread */ meillo@0: meillo@0: { meillo@0: int i, max_fd = sysconf(_SC_OPEN_MAX); meillo@0: meillo@0: if(max_fd <= 0) max_fd = 64; meillo@0: for(i = 0; i < max_fd; i++) meillo@0: if((i != pipe_fd[0]) && (i != pipe_fd[1])) close(i); meillo@0: } meillo@0: if (close (pipe_fd [mode == Read ? 0 : 1]) != -1 && meillo@0: dup2 (pipe_fd [mode == Read ? 1 : 0], mode == Read ? STDOUT_FILENO : STDIN_FILENO) != -1) { meillo@0: // char *argv [] = { "/bin/sh", "-c", (char*) command, NULL }; meillo@0: char **argv = create_argv(command, 10); meillo@0: int ret; meillo@0: meillo@0: if(uid != (uid_t)-1){ meillo@0: if((ret = seteuid(0)) != 0){ meillo@0: exit(EX_NOPERM); meillo@0: } meillo@0: } meillo@0: if(gid != (gid_t)-1){ meillo@0: if((ret = setgid(gid)) != 0){ meillo@0: exit(EX_NOPERM); meillo@0: } meillo@0: } meillo@0: if(uid != (uid_t)-1){ meillo@0: if((ret = setuid(uid)) != 0){ meillo@0: exit(EX_NOPERM); meillo@0: } meillo@0: } meillo@0: execve (*argv, argv, envp); meillo@0: } meillo@0: meillo@0: _exit (errno); meillo@0: meillo@0: default: /* parent thread */ meillo@0: *ret_pid = pid; meillo@0: close (pipe_fd [mode == Read ? 1 : 0]); meillo@0: return fdopen (pipe_fd [mode == Read ? 0 : 1], type); meillo@0: meillo@0: case -1: meillo@0: close (pipe_fd [0]); meillo@0: close (pipe_fd [1]); meillo@0: return NULL; meillo@0: } meillo@0: } meillo@0: meillo@0: FILE* peopen(const char *command, meillo@0: const char *type, meillo@0: char *const envp [], meillo@0: int *ret_pid meillo@0: ) meillo@0: { meillo@0: return peidopen(command, type, envp, ret_pid, -1 ,-1); meillo@0: }