masqmail

diff src/peopen.c @ 0:08114f7dcc23

this is masqmail-0.2.21 from oliver kurth
author meillo@marmaro.de
date Fri, 26 Sep 2008 17:05:23 +0200
parents
children 26e34ae9a3e3
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/peopen.c	Fri Sep 26 17:05:23 2008 +0200
     1.3 @@ -0,0 +1,136 @@
     1.4 +/* This a snippet I found in sourceforge. I just changed the identing
     1.5 +   style to my own and deleted the main function.  */
     1.6 +
     1.7 +#include <errno.h>
     1.8 +#include <stdio.h>
     1.9 +#include <stdlib.h>
    1.10 +#include <unistd.h>
    1.11 +#include <string.h>
    1.12 +#include <sys/types.h>
    1.13 +
    1.14 +#include "peopen.h"
    1.15 +#include "sysexits.h"
    1.16 +
    1.17 +#include "masqmail.h"
    1.18 +
    1.19 +static
    1.20 +void destroy_argv(char **arr)
    1.21 +{
    1.22 +  char *p = arr[0];
    1.23 +  int i = 0;
    1.24 +
    1.25 +  while(p){
    1.26 +    free(p);
    1.27 +    p = arr[i++];
    1.28 +  }
    1.29 +  free(arr);
    1.30 +}
    1.31 +
    1.32 +static
    1.33 +char **create_argv(const char *cmd, int count)
    1.34 +{
    1.35 +  char buf[strlen(cmd)+1];
    1.36 +  char **arr, *q;
    1.37 +  const char *p;
    1.38 +  int i = 0;
    1.39 +
    1.40 +  arr = (char **)malloc(sizeof(char *) * count);
    1.41 +  
    1.42 +  p = cmd;
    1.43 +  while(*p && i < (count-1)){
    1.44 +    while(*p && isspace(*p)) p++;
    1.45 +    q = buf;
    1.46 +    while(*p && !isspace(*p)) *q++ = *p++;
    1.47 +    *q = 0;
    1.48 +    arr[i++] = strdup(buf);
    1.49 +    while(*p && isspace(*p)) p++;
    1.50 +  }
    1.51 +  arr[i] = NULL;
    1.52 +
    1.53 +  return arr;
    1.54 +}
    1.55 +
    1.56 +FILE* peidopen(const char	*command,
    1.57 +	       const char	*type,
    1.58 +	       char *const envp [],
    1.59 +	       int *ret_pid,
    1.60 +	       uid_t uid, gid_t gid
    1.61 +	     )
    1.62 +{
    1.63 +  enum { Read, Write } mode;
    1.64 +  int pipe_fd [2];
    1.65 +  pid_t pid;
    1.66 +    
    1.67 +  if (command == NULL || type == NULL) {
    1.68 +    errno = EINVAL;
    1.69 +    return NULL;
    1.70 +  }
    1.71 +
    1.72 +  if (strcmp (type, "r")) {
    1.73 +    if (strcmp (type, "w")) {
    1.74 +      errno = EINVAL;
    1.75 +      return NULL;
    1.76 +    } else
    1.77 +      mode = Write;
    1.78 +  } else
    1.79 +    mode = Read;
    1.80 +
    1.81 +  if (pipe (pipe_fd) == -1)
    1.82 +    return NULL;
    1.83 +
    1.84 +  switch (pid = fork ()) {
    1.85 +  case 0: /* child thread */
    1.86 +
    1.87 +    {
    1.88 +      int i, max_fd = sysconf(_SC_OPEN_MAX);
    1.89 +      
    1.90 +      if(max_fd <= 0) max_fd = 64;
    1.91 +      for(i = 0; i < max_fd; i++)
    1.92 +	if((i != pipe_fd[0]) && (i != pipe_fd[1])) close(i);
    1.93 +    }
    1.94 +    if (close (pipe_fd [mode == Read ? 0 : 1]) != -1 &&
    1.95 +	dup2 (pipe_fd [mode == Read ? 1 : 0], mode == Read ? STDOUT_FILENO : STDIN_FILENO) != -1) {
    1.96 +      //      char *argv [] = { "/bin/sh", "-c", (char*) command, NULL };
    1.97 +      char **argv = create_argv(command, 10);
    1.98 +      int ret;
    1.99 +
   1.100 +      if(uid != (uid_t)-1){
   1.101 +	if((ret = seteuid(0)) != 0){
   1.102 +	  exit(EX_NOPERM);
   1.103 +	}
   1.104 +      }
   1.105 +      if(gid != (gid_t)-1){
   1.106 +	if((ret = setgid(gid)) != 0){
   1.107 +	  exit(EX_NOPERM);
   1.108 +	}
   1.109 +      }
   1.110 +      if(uid != (uid_t)-1){
   1.111 +	if((ret = setuid(uid)) != 0){
   1.112 +	  exit(EX_NOPERM);
   1.113 +	}
   1.114 +      }
   1.115 +      execve (*argv, argv, envp);
   1.116 +    }
   1.117 +	    
   1.118 +    _exit (errno);
   1.119 +	    
   1.120 +  default: /* parent thread */
   1.121 +    *ret_pid = pid;
   1.122 +    close (pipe_fd [mode == Read ? 1 : 0]);
   1.123 +    return fdopen (pipe_fd [mode == Read ? 0 : 1], type);
   1.124 +	    
   1.125 +  case -1:
   1.126 +    close (pipe_fd [0]);
   1.127 +    close (pipe_fd [1]);
   1.128 +    return NULL;
   1.129 +  }
   1.130 +}
   1.131 +
   1.132 +FILE* peopen(const char	*command,
   1.133 +	     const char	*type,
   1.134 +	     char *const envp [],
   1.135 +	     int *ret_pid
   1.136 +	     )
   1.137 +{
   1.138 +  return peidopen(command, type, envp, ret_pid, -1 ,-1);
   1.139 +}