masqmail

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