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 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
|
#define _BSD_SOURCE
#include <cstdlib>
#include <string>
#include <vector>
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <cstring>
using namespace std;
int runCmd(const vector< vector <string> >&, vector<struct program_time>&);
struct program_time {
char *name;
struct timeval utime;
struct timeval stime;
};
int main (int argc, char **argv) {
int errStatus;
string input;
vector<vector < vector <string> > >commands; //vector of tokenized input from user line -> pipe delimited -> word tokenized
vector<struct program_time> program_times;
do {
fflush(stdout);
fflush(stderr);
int saveStdOut=dup(1);
cout << "statsh> ";
dup2(saveStdOut, 1);
close(saveStdOut); // credit for this line goes to Foonly below ;-)
fflush(stdout);
getline (cin,input);
//cout <<input<<endl;
if (input.compare("exit") !=0) {
if (input.compare("stats") !=0) { //start tokenizing
/*Create a single vector of strings that is delimited by the pipe symbol
* Then run a separate tokenizer on these strings usingin " " as a delimited */
vector < vector <string> > pipe_delimited;
vector<string> temp_pipe_delimited;
vector<string> space_delimited;
char *pipeToken= strtok(const_cast<char *>(input.c_str()), "|");
while (pipeToken != NULL) {
temp_pipe_delimited.push_back(pipeToken);
cout << pipeToken << endl;
pipeToken= strtok(NULL, "|");
}
for (vector<string>::iterator it = temp_pipe_delimited.begin(); it != temp_pipe_delimited.end(); ++it) {
char *token = strtok(const_cast<char *>(it->c_str()), " ");
while (token != NULL) {
space_delimited.push_back(token);
token = strtok(NULL, " ");
}
pipe_delimited.push_back(space_delimited);
//Test Run Comand
//errStatus= runCmd(space_delimited, program_times);
//Run command succeeds on each pipe
space_delimited.clear();
}
errStatus= runCmd(pipe_delimited, program_times);
commands.push_back(pipe_delimited);
}
else { //run stats
cout << "\nStat Shell\n";
for (vector<struct program_time>::iterator it = program_times.begin(); it!=program_times.end();++it) {
cout <<"--------\n " <<"Name: " << it->name <<"\n Sys Time: "<< it-> stime.tv_sec << "." << it->stime.tv_usec<<"\n User Time: " << it->utime.tv_sec<<"." << it->utime.tv_usec <<endl;
}
cout <<endl;
}
}
} while ((input.compare("exit") !=0));
/* Debug out of the commands entered by the user with pipes */
for (vector< vector < vector <string> > >::iterator it= commands.begin(); it != commands.end(); ++it) {
for (vector < vector <string> >::iterator piped_it= it->begin(); piped_it != it->end(); ++piped_it) {
for (vector<string>::iterator spaced_it= piped_it->begin(); spaced_it != piped_it->end(); ++spaced_it) {
cout << *spaced_it << " ";
}
cout << " | ";
}
cout << endl;
}
return 0;
}
// in: list2 of list1 of strings
//list1 of strings is space delimited string between pipes
//list2 is list of commands spearated by pipes
int runCmd(const vector<vector< string> > &cmdLine, vector<struct program_time> &_program_times ) {
//char *argv[100]; //assume max size
int args;
char *argv[255]; //hardcoded 255 token max //char *argv[args + 1];
int longestLength = 40; //assumed a token is at most 40 characters long
int forkNum= (cmdLine.size());
pid_t child_pid;
int child_status;
int **fdArray; //pointer to array of int
//Set up corrent number of pipes
fdArray = new int*[2]; //allocate memory for new pipe
for (unsigned int i=0; i<(cmdLine.size()-1); ++i) {
fdArray[i]= new int[2];
pipe(fdArray[i]);
cout << fdArray[i][0] <<"," << fdArray[i][1] <<endl;
}
cout << forkNum << " command to process.\n";
for (int i =0; i < forkNum; ++i) { //perform fork and exec from 0 to (n) processes
cout <<"inside loop\n";
child_pid= fork();
args=cmdLine[i].size();
//Get the character array from the vector here
for (int c_size = 0; c_size < args; ++c_size){ //c_size = single command size
argv[c_size] = (char *)malloc((sizeof(char) * longestLength + 1));
strcpy(argv[c_size], cmdLine.at(i).at(c_size).c_str());
//cout << argv[c_size] << endl;
//cout<<argv[i]<<endl; //print each element
}
*(argv + args)=NULL; //null terminate this string of tokens for the exec call
if (child_pid >0 ) { //Process is a parent
cout <<"Child PID is "<<child_pid<<endl;
cout <<"child status is "<< child_status<<endl;
/*this is commented out because we want to wait for all process to finish outside the fork loop
so we don't disturb interactive piped process */
//wait4(-1,&child_status,0,NULL);
}
if (child_pid == 0){
cout <<"In Child - " << cmdLine.at(i).at(0) << endl;
if ((i==0) && (cmdLine.size() > 1)) { //if first command and there is at least one pipe
close(fdArray[0][0]); //close reading file descriptor of first pipe
dup2(fdArray[0][1],1); //dup writing pipe to stdout
close(fdArray[0][1]);
}
if (i== (forkNum-1) && (cmdLine.size() > 1) ) { //if last command in pipe
dup2(fdArray[i-1][0],0); //duplicate reading pipe to standard input
close(fdArray[1][0]);
close(fdArray[0][1]);
}
execvp(cmdLine.at(i).at(0).c_str(), argv);
//Invalid execs proceed to here
cerr << "Unknown command!\n";
fflush(stderr);
fflush(stdout);
exit(0);
}
else if (child_pid < 0){ //some fork error
cerr <<"Error!\n";
}
for (int c_size=0;c_size < args;++c_size) { //free argument array for each piped process
free(argv[c_size]);
}
for (unsigned int proc_num=0; proc_num<cmdLine.size();++proc_num) { //wait for all spawned processes in pipe before continuing
//while
wait4(-1,&child_status,0,NULL);// {}
cout <<".";
}
}
for (unsigned int i=0; i<(cmdLine.size()-1); ++i) { //delete each pipe after they have all been accumulated
close(fdArray[i][0]); //catch all opened pipes
close(fdArray[i][1]);
delete fdArray[i];
}
return 0;
}
|