masqmail

view src/peopen.c @ 375:3f923f97563b

local_hosts now understands glob patterns like `*example.org'.
author markus schnalke <meillo@marmaro.de>
date Sat, 14 Jan 2012 18:14:07 +0100
parents dcb315792513
children 9bc3e47b0222
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 static void
19 destroy_argv(char **arr)
20 {
21 char *p = arr[0];
22 int i = 0;
24 while (p) {
25 free(p);
26 p = arr[i++];
27 }
28 free(arr);
29 }
31 static char**
32 create_argv(const char *cmd, int count)
33 {
34 char buf[strlen(cmd) + 1];
35 char **arr, *q;
36 const char *p;
37 int i = 0;
39 arr = (char **) g_malloc(sizeof(char *) * count);
41 p = cmd;
42 while (*p && i < (count - 1)) {
43 while (*p && isspace(*p))
44 p++;
45 q = buf;
46 while (*p && !isspace(*p))
47 *q++ = *p++;
48 *q = '\0';
49 arr[i++] = strdup(buf);
50 while (*p && isspace(*p))
51 p++;
52 }
53 arr[i] = NULL;
55 return arr;
56 }
58 FILE*
59 peidopen(const char *command, const char *type, char *const envp[],
60 int *ret_pid, uid_t uid, gid_t gid)
61 {
62 enum { Read, Write } mode;
63 int pipe_fd[2];
64 pid_t pid;
66 if (command == NULL || type == NULL) {
67 errno = EINVAL;
68 return NULL;
69 }
71 if (strcmp(type, "r")) {
72 if (strcmp(type, "w")) {
73 errno = EINVAL;
74 return NULL;
75 } else
76 mode = Write;
77 } else
78 mode = Read;
80 if (pipe(pipe_fd) == -1)
81 return NULL;
83 switch (pid = fork()) {
84 case 0: /* child thread */
86 {
87 int i, max_fd = sysconf(_SC_OPEN_MAX);
89 if (max_fd <= 0)
90 max_fd = 64;
91 for (i = 0; i < max_fd; i++)
92 if ((i != pipe_fd[0]) && (i != pipe_fd[1]))
93 close(i);
94 }
95 if (close(pipe_fd[mode == Read ? 0 : 1]) != -1 &&
96 dup2(pipe_fd[mode == Read ? 1 : 0],
97 mode == Read ? STDOUT_FILENO : STDIN_FILENO) != -1) {
98 /* char *argv [] = { "/bin/sh", "-c", (char*) command, NULL }; */
99 char **argv = create_argv(command, 10);
100 int ret;
102 if (uid != (uid_t) - 1) {
103 if ((ret = seteuid(0)) != 0) {
104 exit(EX_NOPERM);
105 }
106 }
107 if (gid != (gid_t) - 1) {
108 if ((ret = setgid(gid)) != 0) {
109 exit(EX_NOPERM);
110 }
111 }
112 if (uid != (uid_t) - 1) {
113 if ((ret = setuid(uid)) != 0) {
114 exit(EX_NOPERM);
115 }
116 }
117 execve(*argv, argv, envp);
118 }
120 _exit(errno);
122 default: /* parent thread */
123 *ret_pid = pid;
124 close(pipe_fd[mode == Read ? 1 : 0]);
125 return fdopen(pipe_fd[mode == Read ? 0 : 1], type);
127 case -1:
128 close(pipe_fd[0]);
129 close(pipe_fd[1]);
130 return NULL;
131 }
132 }
134 FILE*
135 peopen(const char *command, const char *type, char *const envp[], int *ret_pid)
136 {
137 return peidopen(command, type, envp, ret_pid, -1, -1);
138 }