1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
/*******************************************************************************
* Copyright (c) 2003, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
#include "exec0.h"
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <libgen.h>
#include <stdlib.h>
/* from pfind.c */
extern char *pfind(const char *name);
pid_t
exec0(const char *path, char *const argv[], char *const envp[],
const char *dirpath, int channels[3])
{
int pipe0[2], pipe1[2], pipe2[2];
pid_t childpid;
char *full_path;
/*
* We use pfind() to check that the program exists and is an executable.
* If not pass the error up. Also execve() wants a full path.
*/
full_path = pfind(path);
if (full_path == NULL) {
fprintf(stderr, "Unable to find full path for \"%s\"\n", (path) ? path : "");
return -1;
}
/*
* Make sure we can create our pipes before forking.
*/
if (channels != NULL) {
if (pipe(pipe0) < 0 || pipe(pipe1) < 0 || pipe(pipe2) < 0) {
fprintf(stderr, "%s(%d): returning due to error.\n",
__FUNCTION__, __LINE__);
free(full_path);
return -1;
}
}
childpid = fork();
if (childpid < 0) {
fprintf(stderr, "%s(%d): returning due to error: %s\n",
__FUNCTION__, __LINE__, strerror(errno));
free(full_path);
return -1;
} else if (childpid == 0) { /* child */
char *ptr;
chdir(dirpath);
if (channels != NULL) {
/* Close the write end of pipe0 */
if (close(pipe0[1]) == -1)
perror("close(pipe0[1])");
/* Close the read end of pipe1 */
if (close(pipe1[0]) == -1)
perror("close(pipe1[0])");
/* Close the read end of pipe2 */
if (close(pipe2[0]) == -1)
perror("close(pipe2[0]))");
/* redirections */
dup2(pipe0[0], STDIN_FILENO); /* dup stdin */
dup2(pipe1[1], STDOUT_FILENO); /* dup stdout */
dup2(pipe2[1], STDERR_FILENO); /* dup stderr */
}
/* Close all the fd's in the child */
{
int fdlimit = sysconf(_SC_OPEN_MAX);
int fd = 3;
while (fd < fdlimit)
close(fd++);
}
if (envp[0] == NULL) {
execv(full_path, argv);
} else {
execve(full_path, argv, envp);
}
_exit(127);
} else if (childpid != 0) { /* parent */
char b;
if (channels != NULL) {
/* close the read end of pipe1 */
if (close(pipe0[0]) == -1)
perror("close(pipe0[0])");
/* close the write end of pipe2 */
if (close(pipe1[1]) == -1)
perror("close(pipe1[1])");
/* close the write end of pipe2 */
if (close(pipe2[1]) == -1)
perror("close(pipe2[1])");
channels[0] = pipe0[1]; /* Output Stream. */
channels[1] = pipe1[0]; /* Input Stream. */
channels[2] = pipe2[0]; /* Input Stream. */
}
free(full_path);
return childpid;
}
free(full_path);
return -1; /*NOT REACHED */
}
int wait0(pid_t pid)
{
int status;
int val = -1;
if (pid < 0 || waitpid(pid, &status, 0) < 0)
return -1;
if (WIFEXITED(status)) {
val = WEXITSTATUS(status);
}
return val;
}
|