This problem works with 2 piped commands (ie ls | grep main) but when I try to do more than 2 commands the program freezes.The int main() basically does the i/o and the execute command function is pretty much where im having all the problems. Thanks for any help. PS ParsedTokens is a class that parses completely the input. It puts the tokens in a vector of strings.
Code:
// Program asks user for input and tries to execute linux commands based on that input
// User can use multiple input piped commands ie ls | grep main | grep o.
#define _GNU_SOURCE 1
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include "parsedTokens.h"
#include <string>
#include <iostream>
#include <deque>
using namespace std;
void execute_command(string left_command, string right_command);
int main()
{
char input[256];
string temp;
string temp2;
string temp3;
ParsedTokens Tokens;
unsigned int num_tokens;
vector<string> commands;
int len, len2;
// get input
cout << "enter text: ";
cin.getline(input, 256, '\n');
Tokens.Clear();
Tokens.ParseAndAddTokens(input);
cout << "you typed: " << input << endl;
cout << "Parsed: " << endl;
// lists parsed input
for(unsigned int i = 0; i < Tokens.GetNumTokens(); i++)
{
cout << Tokens[i] << endl;
}
// puts the tokens (not including the "|") into a vector
for(unsigned int i = 0; i < Tokens.GetNumTokens(); i++)
{
if(Tokens[i] != "|")
{
if(temp3.empty())
{
temp3 = Tokens[i];
cout << "temp3: " << temp3 << endl;
//if not at last token dont push but add the next token that isn't a pipe to temp3
if(i == Tokens.GetNumTokens() - 1)
{
commands.push_back(temp3);
temp3.erase(0, temp3.length());
}
else if(Tokens[i+1] == "|") // if the next token is a | then push token in temp3
{
commands.push_back(temp3);
temp3.erase(0, temp3.length());
}
}
else // if temp3 isn't empty then add space to temp3 and add next token to temp3
{
temp3.insert(temp3.length()," ");
temp3.insert(temp3.length(), Tokens[i]);
cout << "temp3: " << temp3 << " after getting put together" << endl;
if(i == Tokens.GetNumTokens() - 1) // if you're at last token then push
{
commands.push_back(temp3);
temp3.erase(0, temp3.length());
}
else if(Tokens[i+1] == "|") // if the next token is a | then push token in temp3
{
commands.push_back(temp3);
temp3.erase(0, temp3.length());
}
}
}
/*else
{
commands.push_back(temp3);
temp3.erase(0, temp3.length());
}*/
}
cout << "all the commands to be executed" << endl;
for(int i = 0; i < commands.size(); i++)
cout << commands[i] << endl;
//execute_command(commands[0], commands[1]);
for(int i = 0; i < commands.size() - 1; i++)
{
cout << "left command: " << commands[i] << endl;
cout << "right command: " << commands[i+1] << endl;
execute_command(commands[i], commands[i+1]);
}
return 0;
}
void execute_command(string left_command, string right_command)
{
//char *argv[] = {"ls", "ls", 0};
//char *left_arg[] = {"ls", 0};
//char *right_arg[] = {"grep", "main", 0};
int p[2];
int pid;
int len, len2;
ParsedTokens left_comm_toks;
ParsedTokens right_comm_toks;
// int pipe(int filedes[2]);
// filedes[0] is for reading, filedes[1] is for writing
if(pipe(p) < 0)
{
cerr << strerror(errno) << endl;
exit(EXIT_FAILURE);
}
pid = fork();
if(pid < 0)
{
cerr << strerror(errno) << endl;
exit(EXIT_FAILURE);
}
if(pid == 0)
{
cout << "exec left command" << endl;
char * tempstring;
tempstring = new char[left_command.length() + 1];
strcpy(tempstring, left_command.c_str());
left_comm_toks.ParseAndAddTokens(tempstring);
len = left_comm_toks[0].length();
const char * arg0 = left_comm_toks[0].c_str();
// converts left_command into left_argv[] which execvp uses
/*len = left_command.length();
char * const myArr = new char[len + 1];
for(int x = 0; x < len; x++)
myArr[x] = left_command[x];
myArr[len] = '\0';
char * const left_argv[] = {myArr,0};*/
delete [] tempstring;
vector<string> left_args;
for(int i = 0; i < left_comm_toks.GetNumTokens(); i++)
{
left_args.push_back(left_comm_toks[i]);
}
vector<char *> left_argv;
for(int i = 0; i < left_args.size(); i ++)
left_argv.push_back(const_cast<char *>(left_args[i].c_str()));
left_argv.push_back('\0');
close(p[0]);
dup2(p[1], 1);
close(p[1]);
//argv[2] = 0;
//
execvp(arg0, &left_argv[0]);
cerr << "Error on exec of " << arg0 << ": " << strerror(errno) << endl;
_exit(errno == ENOENT ? 127 : 126);
}
pid = fork();
if(pid < 0)
{
cerr << strerror(errno) << endl;
exit(EXIT_FAILURE);
}
if(pid == 0)
{
cout << "executing right command" << endl;
// converts left_command into left_argv[] which execvp uses
/*len2 = right_command.length();
char * const myArr2 = new char[len +1];
for(int x = 0; x < len2; x++)
myArr2[x] = right_command[x];
myArr2[len2] = '\0';
char *const right_argv[] = {myArr2, 0};*/
char * tempstring2;
tempstring2 = new char[right_command.length() + 1];
strcpy(tempstring2, right_command.c_str());
right_comm_toks.ParseAndAddTokens(tempstring2);
len = right_comm_toks[0].length();
const char * arg02 = right_comm_toks[0].c_str();
delete [] tempstring2;
vector<string> right_args;
for(int i = 0; i < right_comm_toks.GetNumTokens(); i++)
{
right_args.push_back(right_comm_toks[i]);
}
vector<char *> right_argv;
for(int i = 0; i < right_args.size(); i ++)
right_argv.push_back(const_cast<char *>(right_args[i].c_str()));
right_argv.push_back('\0');
close(p[1]);
dup2(p[0], 0);
close(p[0]);
//execvp(right_argv[0], right_argv);
execvp(arg02, &right_argv[0]);
cerr << "Error on exec of " << right_argv[0] << ": " << strerror(errno) << endl;
_exit(errno == ENOENT ? 127 : 126);
}
close(p[0]);
close(p[1]);
wait(0);
wait(0);
}