diff src/peopen.c @ 0:08114f7dcc23 0.2.21

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 wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/peopen.c	Fri Sep 26 17:05:23 2008 +0200
@@ -0,0 +1,136 @@
+/* This a snippet I found in sourceforge. I just changed the identing
+   style to my own and deleted the main function.  */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "peopen.h"
+#include "sysexits.h"
+
+#include "masqmail.h"
+
+static
+void destroy_argv(char **arr)
+{
+  char *p = arr[0];
+  int i = 0;
+
+  while(p){
+    free(p);
+    p = arr[i++];
+  }
+  free(arr);
+}
+
+static
+char **create_argv(const char *cmd, int count)
+{
+  char buf[strlen(cmd)+1];
+  char **arr, *q;
+  const char *p;
+  int i = 0;
+
+  arr = (char **)malloc(sizeof(char *) * count);
+  
+  p = cmd;
+  while(*p && i < (count-1)){
+    while(*p && isspace(*p)) p++;
+    q = buf;
+    while(*p && !isspace(*p)) *q++ = *p++;
+    *q = 0;
+    arr[i++] = strdup(buf);
+    while(*p && isspace(*p)) p++;
+  }
+  arr[i] = NULL;
+
+  return arr;
+}
+
+FILE* peidopen(const char	*command,
+	       const char	*type,
+	       char *const envp [],
+	       int *ret_pid,
+	       uid_t uid, gid_t gid
+	     )
+{
+  enum { Read, Write } mode;
+  int pipe_fd [2];
+  pid_t pid;
+    
+  if (command == NULL || type == NULL) {
+    errno = EINVAL;
+    return NULL;
+  }
+
+  if (strcmp (type, "r")) {
+    if (strcmp (type, "w")) {
+      errno = EINVAL;
+      return NULL;
+    } else
+      mode = Write;
+  } else
+    mode = Read;
+
+  if (pipe (pipe_fd) == -1)
+    return NULL;
+
+  switch (pid = fork ()) {
+  case 0: /* child thread */
+
+    {
+      int i, max_fd = sysconf(_SC_OPEN_MAX);
+      
+      if(max_fd <= 0) max_fd = 64;
+      for(i = 0; i < max_fd; i++)
+	if((i != pipe_fd[0]) && (i != pipe_fd[1])) close(i);
+    }
+    if (close (pipe_fd [mode == Read ? 0 : 1]) != -1 &&
+	dup2 (pipe_fd [mode == Read ? 1 : 0], mode == Read ? STDOUT_FILENO : STDIN_FILENO) != -1) {
+      //      char *argv [] = { "/bin/sh", "-c", (char*) command, NULL };
+      char **argv = create_argv(command, 10);
+      int ret;
+
+      if(uid != (uid_t)-1){
+	if((ret = seteuid(0)) != 0){
+	  exit(EX_NOPERM);
+	}
+      }
+      if(gid != (gid_t)-1){
+	if((ret = setgid(gid)) != 0){
+	  exit(EX_NOPERM);
+	}
+      }
+      if(uid != (uid_t)-1){
+	if((ret = setuid(uid)) != 0){
+	  exit(EX_NOPERM);
+	}
+      }
+      execve (*argv, argv, envp);
+    }
+	    
+    _exit (errno);
+	    
+  default: /* parent thread */
+    *ret_pid = pid;
+    close (pipe_fd [mode == Read ? 1 : 0]);
+    return fdopen (pipe_fd [mode == Read ? 0 : 1], type);
+	    
+  case -1:
+    close (pipe_fd [0]);
+    close (pipe_fd [1]);
+    return NULL;
+  }
+}
+
+FILE* peopen(const char	*command,
+	     const char	*type,
+	     char *const envp [],
+	     int *ret_pid
+	     )
+{
+  return peidopen(command, type, envp, ret_pid, -1 ,-1);
+}