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