masqmail

annotate src/peopen.c @ 381:33b893124c81

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