-
Another pipe() problem.
For some reason pipe() is returning an error when I try to pipe. Any idea why? Here's the code:
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;
struct filedesc { int desc[2]; };
int main()
{
//char *argv[] = {"ls", "ls", 0};
//char *left_arg[] = {"ls", 0};
//char *right_arg[] = {"grep", "main", 0};
//int p[2];
int pid;
int len;
ParsedTokens left_comm_toks;
ParsedTokens right_comm_toks;
ParsedTokens command_toks;
vector<string> commands; // = {"ls", "grep main", "grep cpp"};
commands.push_back("ls");
commands.push_back("grep main");
commands.push_back("grep cpp");
vector<filedesc> p;
//const int size = commands.size();
//int p[size][2];
// int pipe(int filedes[2]);
// filedes[0] is for reading, filedes[1] is for writing
for(int i = 0; i < commands.size() - 1; i++)
{
cout << "Pipe" << i << endl;
if(pipe(p[i].desc) < 0)
{
cerr << strerror(errno) << endl;
exit(EXIT_FAILURE);
}
cout << "got completed" << endl;
}
for(int x = 0; x < commands.size(); x++)
{
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[commands[x].length() + 1];
strcpy(tempstring, commands[x].c_str());
command_toks.ParseAndAddTokens(tempstring);
len = command_toks[0].length();
const char * arg0 = command_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> args;
for(int j = 0; j < command_toks.GetNumTokens(); j++)
{
args.push_back(left_comm_toks[j]);
}
vector<char *> argv;
for(int k = 0; k < args.size(); k++)
argv.push_back(const_cast<char *>(args[k].c_str()));
argv.push_back('\0');
if(x == 0)
{
close(p[x].desc[0]);
dup2(p[x].desc[1], 1);
close(p[x].desc[1]);
}
else if(x==commands.size()-1)
{
close(p[x-1].desc[1]);
dup2(p[x-1].desc[0],0);
close(p[x-1].desc[0]);
}
else
{
for(int y = 0; y < commands.size() - 1; y++)
{
if(y == x-1)
close(p[y].desc[1]);
else if(y == x)
close(p[y].desc[0]);
else
{
close(p[y].desc[0]);
close(p[y].desc[1]);
}
}
dup2(p[x-1].desc[0],0);
close(p[x-1].desc[0]);
dup2(p[x].desc[1],1);
close(p[x].desc[1]);
}
execvp(arg0, &argv[0]);
cerr << "Error on exec of " << arg0 << ": " << strerror(errno) << endl;
_exit(errno == ENOENT ? 127 : 126);
}
}
for(int z = 0; z < commands.size() - 1; z++)
{
close(p[z].desc[0]);
close(p[z].desc[1]);
}
for(int zz = 0; zz < commands.size(); zz++)
wait(0);
}
heres the program output
Code:
dell1(22)>./mshell
Pipe0
Bad address
-
changed the code to use 2d arrays
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;
struct filedesc { int desc[2]; };
int main()
{
//char *argv[] = {"ls", "ls", 0};
//char *left_arg[] = {"ls", 0};
//char *right_arg[] = {"grep", "main", 0};
//int p[2];
int pid;
int len;
int status;
ParsedTokens left_comm_toks;
ParsedTokens right_comm_toks;
ParsedTokens command_toks;
vector<string> commands; // = {"ls", "grep main", "grep cpp"};
commands.push_back("ls");
commands.push_back("grep main");
//commands.push_back("grep cpp");
//vector<filedesc> p;
int (*p)[2];
p = new int[commands.size()][2];
//const int size = commands.size();
//int p[size][2];
// int pipe(int filedes[2]);
// filedes[0] is for reading, filedes[1] is for writing
for(int i = 0; i < commands.size() - 1; i++)
{
//if(pipe(p[i].desc) < 0)
if(pipe(p[i]))
{
cerr << strerror(errno) << endl;
exit(EXIT_FAILURE);
}
cout << "got completed" << endl;
}
for(int x = 0; x < commands.size(); x++)
{
pid = fork();
if(pid < 0)
{
cerr << strerror(errno) << endl;
exit(EXIT_FAILURE);
}
if(pid == 0)
{
cout << "executing command " << commands[x] << endl;
char * tempstring;
tempstring = new char[commands[x].length() + 1];
strcpy(tempstring, commands[x].c_str());
command_toks.ParseAndAddTokens(tempstring);
len = command_toks[0].length();
const char * arg0 = command_toks[0].c_str();
delete [] tempstring;
vector<string> args;
for(int j = 0; j < command_toks.GetNumTokens(); j++)
{
args.push_back(command_toks[j]);
}
vector<char *> argv;
for(int k = 0; k < args.size(); k++)
argv.push_back(const_cast<char *>(args[k].c_str()));
argv.push_back('\0');
cout << "freeze before dupes and closes?" << endl;
if(x == 0)
{
cout << "freezes at first close" << endl;
close(p[x][0]);
dup2(p[x][1], 1);
close(p[x][1]);
}
else if(x==commands.size()-1)
{
cout << "freezes at second close" << endl;
close(p[x-1][1]);
dup2(p[x-1][0],0);
close(p[x-1][0]);
}
else
{
cout << "freezes before loop" << endl;
for(int y = 0; y < commands.size() - 1; y++)
{
if(y == x-1)
close(p[y][1]);
else if(y == x)
close(p[y][0]);
else
{
close(p[y][0]);
close(p[y][1]);
}
}
cout << "freezes in last dupes" << endl;
dup2(p[x-1][0],0);
close(p[x-1][0]);
dup2(p[x][1],1);
close(p[x][1]);
}
cout << "freezes at exec" << endl;
execvp(arg0, &argv[0]);
cerr << "Error on exec of " << arg0 << ": " << strerror(errno) << endl;
_exit(errno == ENOENT ? 127 : 126);
cout << "freeze before wait?" << endl;
while(wait(&status) != pid);
}
cout << "freeze before closes?" << endl;
for(int z = 0; z < commands.size() - 1; z++)
{
close(p[z][0]);
close(p[z][1]);
}
}
for (int ii=0; ii<commands.size()-1; ii++)
delete [] p[ii];
// 2) when all arrays of columns are deleted
// for each row we can proceed with
// deleting the array of rows
delete [] p;
}
program freezes on the second interation of the loop that execvps.
-
updated code still not working. I dont know what is wrong. I just cant get it working at all. Please any help or suggestions would be greatly appreciated. I've googled and googled, recoded and recoded. I cannot get this program to work.
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;
struct filedesc { int desc[2]; };
int main()
{
//char *argv[] = {"ls", "ls", 0};
//char *left_arg[] = {"ls", 0};
//char *right_arg[] = {"grep", "main", 0};
//int p[2];
pid_t pid;
int len;
int status;
int num_of_pipes;
int pipe_num = 0;
ParsedTokens left_comm_toks;
ParsedTokens right_comm_toks;
ParsedTokens command_toks;
vector<string> commands; // = {"ls", "grep main", "grep cpp"};
commands.push_back("ls");
commands.push_back("grep main");
//commands.push_back("grep cpp");
num_of_pipes = commands.size() - 1;
//vector<filedesc> p;
int (*p)[2];
p = new int[commands.size()][2];
//const int size = commands.size();
//int p[size][2];
// int pipe(int filedes[2]);
// filedes[0] is for reading, filedes[1] is for writing
for(int i = 0; i < num_of_pipes; i++)
{
//if(pipe(p[i].desc) < 0)
cout << "Pipe" << i << endl;
if(pipe(p[i]) < 0)
{
cerr << strerror(errno) << endl;
exit(EXIT_FAILURE);
}
cout << "got completed" << endl;
}
for(int x = 0; x < commands.size(); x++)
{
pid = fork();
if(pid < 0)
{
cerr << strerror(errno) << endl;
exit(EXIT_FAILURE);
}
if(pid == 0)
{
// parses command line and forms arg0, this block of code has been proven to work.
cout << "executing command " << commands[x] << endl;
char * tempstring;
tempstring = new char[commands[x].length() + 1];
strcpy(tempstring, commands[x].c_str());
command_toks.Clear();
command_toks.ParseAndAddTokens(tempstring);
len = command_toks[0].length();
const char * arg0 = command_toks[0].c_str();
delete [] tempstring;
vector<string> args;
for(int j = 0; j < command_toks.GetNumTokens(); j++)
{
args.push_back(command_toks[j]);
}
vector<char *> argv;
for(int k = 0; k < args.size(); k++)
argv.push_back(const_cast<char *>(args[k].c_str()));
argv.push_back('\0');
cout << "freeze before dupes and closes?" << endl;
// this stuff is what i think is wrong.
if(x == 0)
{
cout << "freezes at first close" << endl;
for(int y = 0; y < commands.size() - 1; y++)
{
if(y == 0)
close(p[y][0]); // pipe 0's read end is closed
else
{
close(p[y][0]); // close the rest, only pipe 0's we is open
close(p[y][1]);
}
}
dup2(p[x][1], 1);
close(p[x][1]);
}
else if(x==commands.size()-1)
{
cout << "freezes at second close" << endl;
for(int y = 0; y < commands.size() - 1; y++)
{
if(y == x-1)
close(p[y][1]); //close last pipes write end, leave last pipes read end open
else
{
close(p[y][0]); // close rest of the pipes, only last pipes read end open
close(p[y][1]);
}
}
//close(p[x-1][1]);
dup2(p[x-1][0],0);
close(p[x-1][0]);
}
else
{
cout << "freezes before loop" << endl;
for(int y = 0; y < commands.size() - 1; y++)
{
if(y == x-1)
close(p[y][1]);
else if(y == x)
close(p[y][0]);
else
{
close(p[y][0]);
close(p[y][1]);
}
}
cout << "freezes in last dupes" << endl;
dup2(p[x-1][0],0);
close(p[x-1][0]);
dup2(p[x][1],1);
close(p[x][1]);
}
cout << "freezes at exec" << endl;
execvp(arg0, &argv[0]);
cerr << "Error on exec of " << arg0 << ": " << strerror(errno) << endl;
_exit(errno == ENOENT ? 127 : 126);
cout << "freeze before wait?" << endl;
while(wait(&status) != pid);
}
cout << "freeze before closes?" << endl;
for(int z = 0; z < commands.size() - 1; z++)
{
close(p[z][0]);
close(p[z][1]);
}
}
for(int ii=0; ii<commands.size()-1; ii++)
delete [] p[ii];
// 2) when all arrays of columns are deleted
// for each row we can proceed with
// deleting the array of rows
delete [] p;
}
-
here's the output:
Code:
Pipe0
got completed
freeze before closes?
freeze before closes?
executing command ls
freeze before dupes and closes?
freezes at first close
executing command grep main
freeze before dupes and closes?
freezes at second close
freezes at exec
dell1(115)>grep: (standard input): Input/output error
-
i know this code is long, if anybody wants me to explain my thought process or something over aim or yim, pm me or something. I'm pretty desperate over here.