00001 #include "threadfork.h"
00002
00003 #include <stdlib.h>
00004 #include <string.h>
00005 #include <sys/types.h>
00006 #include <sys/wait.h>
00007 #include <unistd.h>
00008
00009 #define MAX_ARGS 32
00010
00011
00012
00013
00014 ThreadFork::ThreadFork()
00015 {
00016 pid = 0;
00017 tid = 0;
00018 pthread_mutexattr_t attr;
00019 pthread_mutexattr_init(&attr);
00020 pthread_mutex_init(&start_lock, &attr);
00021
00022
00023
00024 arguments = new char*[MAX_ARGS];
00025 total_arguments = 0;
00026 stdin_fd = 0;
00027 pipe_stdin = 0;
00028 command_line = "";
00029 }
00030
00031 ThreadFork::~ThreadFork()
00032 {
00033
00034
00035 pclose(stdin_fd);
00036
00037
00038
00039
00040
00041
00042
00043 for(int i = 0; i < total_arguments; i++)
00044 delete [] arguments[i];
00045
00046 pthread_mutex_destroy(&start_lock);
00047 delete [] arguments;
00048 }
00049
00050 void* ThreadFork::entrypoint(void *ptr)
00051 {
00052 ThreadFork *threadfork = (ThreadFork*)ptr;
00053 threadfork->run();
00054 }
00055
00056 void ThreadFork::start_command(char *command_line, int pipe_stdin)
00057 {
00058 this->command_line = command_line;
00059 this->pipe_stdin = pipe_stdin;
00060
00061 pthread_attr_t attr;
00062 pthread_attr_init(&attr);
00063
00064
00065 stdin_fd = popen(command_line, "w");
00066
00067
00068
00069
00070
00071
00072
00073 }
00074
00075
00076 void ThreadFork::run()
00077 {
00078 char *path_ptr;
00079 char *ptr;
00080 char *argument_ptr;
00081 char argument[BCTEXTLEN];
00082 char command_line[BCTEXTLEN];
00083 int new_pid;
00084
00085 strcpy(command_line, this->command_line);
00086
00087
00088
00089
00090 ptr = command_line;
00091 path_ptr = path;
00092 while(*ptr != ' ' && *ptr != 0)
00093 {
00094 *path_ptr++ = *ptr++;
00095 }
00096 *path_ptr = 0;
00097
00098 arguments[total_arguments] = new char[strlen(path) + 1];
00099 strcpy(arguments[total_arguments], path);
00100
00101 total_arguments++;
00102 arguments[total_arguments] = 0;
00103
00104 while(*ptr != 0)
00105 {
00106 ptr++;
00107 argument_ptr = argument;
00108 while(*ptr != ' ' && *ptr != 0)
00109 {
00110 *argument_ptr++ = *ptr++;
00111 }
00112 *argument_ptr = 0;
00113
00114 arguments[total_arguments] = new char[strlen(argument) + 1];
00115 strcpy(arguments[total_arguments], argument);
00116 total_arguments++;
00117 arguments[total_arguments] = 0;
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 if(pipe_stdin)
00130 {
00131 pipe(filedes);
00132 stdin_fd = fdopen(filedes[1], "w");
00133 }
00134
00135 pthread_mutex_unlock(&start_lock);
00136
00137
00138
00139 new_pid = vfork();
00140
00141
00142 if(new_pid == 0)
00143 {
00144 if(pipe_stdin) dup2(filedes[0], fileno(stdin));
00145
00146
00147
00148 execvp(path, arguments);
00149
00150
00151
00152 perror("execvp");
00153 _exit(0);
00154 }
00155 else
00156 {
00157 pid = new_pid;
00158 pthread_mutex_unlock(&start_lock);
00159
00160 int return_value;
00161 if(waitpid(pid, &return_value, WUNTRACED) == -1)
00162 {
00163 perror("ThreadFork::run: waitpid");
00164 }
00165 }
00166
00167
00168 }
00169
00170
00171 FILE* ThreadFork::get_stdin()
00172 {
00173 return stdin_fd;
00174 }