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