masqmail

annotate src/peopen.c @ 6:c9bce6bb2a5d

switched tests dir to ordinary Makefile
author meillo@marmaro.de
date Fri, 26 Sep 2008 22:55:52 +0200
parents
children 26e34ae9a3e3
rev   line source
meillo@0 1 /* This a snippet I found in sourceforge. I just changed the identing
meillo@0 2 style to my own and deleted the main function. */
meillo@0 3
meillo@0 4 #include <errno.h>
meillo@0 5 #include <stdio.h>
meillo@0 6 #include <stdlib.h>
meillo@0 7 #include <unistd.h>
meillo@0 8 #include <string.h>
meillo@0 9 #include <sys/types.h>
meillo@0 10
meillo@0 11 #include "peopen.h"
meillo@0 12 #include "sysexits.h"
meillo@0 13
meillo@0 14 #include "masqmail.h"
meillo@0 15
meillo@0 16 static
meillo@0 17 void destroy_argv(char **arr)
meillo@0 18 {
meillo@0 19 char *p = arr[0];
meillo@0 20 int i = 0;
meillo@0 21
meillo@0 22 while(p){
meillo@0 23 free(p);
meillo@0 24 p = arr[i++];
meillo@0 25 }
meillo@0 26 free(arr);
meillo@0 27 }
meillo@0 28
meillo@0 29 static
meillo@0 30 char **create_argv(const char *cmd, int count)
meillo@0 31 {
meillo@0 32 char buf[strlen(cmd)+1];
meillo@0 33 char **arr, *q;
meillo@0 34 const char *p;
meillo@0 35 int i = 0;
meillo@0 36
meillo@0 37 arr = (char **)malloc(sizeof(char *) * count);
meillo@0 38
meillo@0 39 p = cmd;
meillo@0 40 while(*p && i < (count-1)){
meillo@0 41 while(*p && isspace(*p)) p++;
meillo@0 42 q = buf;
meillo@0 43 while(*p && !isspace(*p)) *q++ = *p++;
meillo@0 44 *q = 0;
meillo@0 45 arr[i++] = strdup(buf);
meillo@0 46 while(*p && isspace(*p)) p++;
meillo@0 47 }
meillo@0 48 arr[i] = NULL;
meillo@0 49
meillo@0 50 return arr;
meillo@0 51 }
meillo@0 52
meillo@0 53 FILE* peidopen(const char *command,
meillo@0 54 const char *type,
meillo@0 55 char *const envp [],
meillo@0 56 int *ret_pid,
meillo@0 57 uid_t uid, gid_t gid
meillo@0 58 )
meillo@0 59 {
meillo@0 60 enum { Read, Write } mode;
meillo@0 61 int pipe_fd [2];
meillo@0 62 pid_t pid;
meillo@0 63
meillo@0 64 if (command == NULL || type == NULL) {
meillo@0 65 errno = EINVAL;
meillo@0 66 return NULL;
meillo@0 67 }
meillo@0 68
meillo@0 69 if (strcmp (type, "r")) {
meillo@0 70 if (strcmp (type, "w")) {
meillo@0 71 errno = EINVAL;
meillo@0 72 return NULL;
meillo@0 73 } else
meillo@0 74 mode = Write;
meillo@0 75 } else
meillo@0 76 mode = Read;
meillo@0 77
meillo@0 78 if (pipe (pipe_fd) == -1)
meillo@0 79 return NULL;
meillo@0 80
meillo@0 81 switch (pid = fork ()) {
meillo@0 82 case 0: /* child thread */
meillo@0 83
meillo@0 84 {
meillo@0 85 int i, max_fd = sysconf(_SC_OPEN_MAX);
meillo@0 86
meillo@0 87 if(max_fd <= 0) max_fd = 64;
meillo@0 88 for(i = 0; i < max_fd; i++)
meillo@0 89 if((i != pipe_fd[0]) && (i != pipe_fd[1])) close(i);
meillo@0 90 }
meillo@0 91 if (close (pipe_fd [mode == Read ? 0 : 1]) != -1 &&
meillo@0 92 dup2 (pipe_fd [mode == Read ? 1 : 0], mode == Read ? STDOUT_FILENO : STDIN_FILENO) != -1) {
meillo@0 93 // char *argv [] = { "/bin/sh", "-c", (char*) command, NULL };
meillo@0 94 char **argv = create_argv(command, 10);
meillo@0 95 int ret;
meillo@0 96
meillo@0 97 if(uid != (uid_t)-1){
meillo@0 98 if((ret = seteuid(0)) != 0){
meillo@0 99 exit(EX_NOPERM);
meillo@0 100 }
meillo@0 101 }
meillo@0 102 if(gid != (gid_t)-1){
meillo@0 103 if((ret = setgid(gid)) != 0){
meillo@0 104 exit(EX_NOPERM);
meillo@0 105 }
meillo@0 106 }
meillo@0 107 if(uid != (uid_t)-1){
meillo@0 108 if((ret = setuid(uid)) != 0){
meillo@0 109 exit(EX_NOPERM);
meillo@0 110 }
meillo@0 111 }
meillo@0 112 execve (*argv, argv, envp);
meillo@0 113 }
meillo@0 114
meillo@0 115 _exit (errno);
meillo@0 116
meillo@0 117 default: /* parent thread */
meillo@0 118 *ret_pid = pid;
meillo@0 119 close (pipe_fd [mode == Read ? 1 : 0]);
meillo@0 120 return fdopen (pipe_fd [mode == Read ? 0 : 1], type);
meillo@0 121
meillo@0 122 case -1:
meillo@0 123 close (pipe_fd [0]);
meillo@0 124 close (pipe_fd [1]);
meillo@0 125 return NULL;
meillo@0 126 }
meillo@0 127 }
meillo@0 128
meillo@0 129 FILE* peopen(const char *command,
meillo@0 130 const char *type,
meillo@0 131 char *const envp [],
meillo@0 132 int *ret_pid
meillo@0 133 )
meillo@0 134 {
meillo@0 135 return peidopen(command, type, envp, ret_pid, -1 ,-1);
meillo@0 136 }