/* This a snippet I found in sourceforge. I just changed the identing
style to my own and deleted the main function. */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
#include "peopen.h"
#include "sysexits.h"
#include "masqmail.h"
static
void destroy_argv(char **arr)
{
char *p = arr[0];
int i = 0;
while(p){
free(p);
p = arr[i++];
}
free(arr);
}
static
char **create_argv(const char *cmd, int count)
{
char buf[strlen(cmd)+1];
char **arr, *q;
const char *p;
int i = 0;
arr = (char **)malloc(sizeof(char *) * count);
p = cmd;
while(*p && i < (count-1)){
while(*p && isspace(*p)) p++;
q = buf;
while(*p && !isspace(*p)) *q++ = *p++;
*q = 0;
arr[i++] = strdup(buf);
while(*p && isspace(*p)) p++;
}
arr[i] = NULL;
return arr;
}
FILE* peidopen(const char *command,
const char *type,
char *const envp [],
int *ret_pid,
uid_t uid, gid_t gid
)
{
enum { Read, Write } mode;
int pipe_fd [2];
pid_t pid;
if (command == NULL || type == NULL) {
errno = EINVAL;
return NULL;
}
if (strcmp (type, "r")) {
if (strcmp (type, "w")) {
errno = EINVAL;
return NULL;
} else
mode = Write;
} else
mode = Read;
if (pipe (pipe_fd) == -1)
return NULL;
switch (pid = fork ()) {
case 0: /* child thread */
{
int i, max_fd = sysconf(_SC_OPEN_MAX);
if(max_fd <= 0) max_fd = 64;
for(i = 0; i < max_fd; i++)
if((i != pipe_fd[0]) && (i != pipe_fd[1])) close(i);
}
if (close (pipe_fd [mode == Read ? 0 : 1]) != -1 &&
dup2 (pipe_fd [mode == Read ? 1 : 0], mode == Read ? STDOUT_FILENO : STDIN_FILENO) != -1) {
// char *argv [] = { "/bin/sh", "-c", (char*) command, NULL };
char **argv = create_argv(command, 10);
int ret;
if(uid != (uid_t)-1){
if((ret = seteuid(0)) != 0){
exit(EX_NOPERM);
}
}
if(gid != (gid_t)-1){
if((ret = setgid(gid)) != 0){
exit(EX_NOPERM);
}
}
if(uid != (uid_t)-1){
if((ret = setuid(uid)) != 0){
exit(EX_NOPERM);
}
}
execve (*argv, argv, envp);
}
_exit (errno);
default: /* parent thread */
*ret_pid = pid;
close (pipe_fd [mode == Read ? 1 : 0]);
return fdopen (pipe_fd [mode == Read ? 0 : 1], type);
case -1:
close (pipe_fd [0]);
close (pipe_fd [1]);
return NULL;
}
}
FILE* peopen(const char *command,
const char *type,
char *const envp [],
int *ret_pid
)
{
return peidopen(command, type, envp, ret_pid, -1 ,-1);
}
syntax highlighted by Code2HTML, v. 0.9.1