String written to child process corrupted? - c++

I want to execute a program in a child process. The program works when I run it directly in the terminal: It waits for some input and Control+D/EOF has to be send before it processes it.
In my code below the program does not seem to receive a string properly, it seems as if it only sees some part or nothing at all when it receives EOF which also seems to happen several times even though I only send it once.
If anyone can tell me what is going wrong here?
int main(int argc, char** argv) {
int pipes[2][2]; //pipe[0] read, pipe[1] write
#define PARENT_READ_FD ( pipes[1][0] )
#define PARENT_WRITE_FD ( pipes[0][1] )
#define CHILD_READ_FD ( pipes[0][0] )
#define CHILD_WRITE_FD ( pipes[1][1] )
// pipes for parent to write and read
assert( (pipe(pipes[1])) == 0 );
assert( (pipe(pipes[0])) == 0 );
int pid = fork();
if(pid == 0) {
char *argv[]={"/workspace/osm/overpass/osm3s_v0.7.51/bin/osm3s_query", "--db-dir=$DB_DIR"};
assert( (dup2(CHILD_READ_FD, STDIN_FILENO)) != -1);
assert( (dup2(CHILD_WRITE_FD, STDOUT_FILENO)) != -1);
close(CHILD_READ_FD);
close(CHILD_WRITE_FD);
close(PARENT_READ_FD);
close(PARENT_WRITE_FD);
execv(argv[0], argv);
} else if(pid > 0) {
char buffer[1000];
int count;
close(CHILD_READ_FD);
close(CHILD_WRITE_FD);
int query_size = strlen(query.c_str()) + 1;
int succesful_write = write(PARENT_WRITE_FD, &query, query_size);
assert(succesful_write==query_size);
close(PARENT_WRITE_FD);
// Read from child’s stdout
while( count = read(PARENT_READ_FD, buffer, sizeof(buffer)-1) > 0){
cerr << buffer << endl;
}
} else {
cerr << "Could not fork child process" << endl;
exit(EXIT_FAILURE);
}
}
The error output from the program is for example (it changes every time the program is run):
line 1: parse error: Unknown type "�"
line 1: parse error: An empty query is not allowed
line 1: parse error: Unknown type "n"
line 1: parse error: An empty query is not allowed
line 1: parse error: Unknown type "�"
...

Related

How to handle pipe channels correctly in order to implement pipe command (similar to pipe command in linux)?

i want to implement a pipe command (similar to this in linux bash ) where it basically works like this :
command1 | command2: using the pipe character “|” will produce a pipe, redirects command1 stdout to its write channel and command2 stdin to its read channel.
or:
command1 |& command2: using the pipe character “|&” will produce a pipe, redirects command1 stderr to the pipe’s write channel and command2 stdin to the pipe’s read channel.
now command 1 can be either an external command from linux that i run using execv or a built in command that i wrote , and command2 is always an external command
my code is not working correctly , i implemented many commands and they all worked perfect for example (cp, redirection ... ) , so the base is good in my code , but the pipe is just wrong ! for example if the command is : showpid | ./parser.exe 1
where parser.exe is a giving file that does parsing on the command , for example here if showpid prints : shell process pid is 12311 , then calling this command showpid | ./parser.exe 1 the output should be "shell" , but in my code the output is shell process pid is 12311
the reason the code is not working because i am handling the channels of the pipe and the stdin / stdout wrong ! i tried literally every combination possible i think but something is still wrong !
this is my pipe command implementation :
this is the class of the pipe command :
class PipeCommand : public Command {
private:
int pipeNum;
int split;
string cmd1;
string cmd2;
public:
PipeCommand(const char* cmd_line);
virtual ~PipeCommand() {}
void execute() override;
};
// the pipe constructor , here i want to extract each command from the right and left side of the pipe from the cmd_line , which is the command line that i get
// fro example : " showpid | grep 1 "
PipeCommand::PipeCommand(const char* cmd_line):Command(cmd_line) {
pipeNum = -1;
isBackground = _isBackgroundComamnd(cmd_line);
string cmd1 = "", cmd2 = "";
int split = -1;
for (int i = 0; i < this->num_args; i++) {
if (strcmp(args[i], "|") == 0) {
split = i;
pipeNum = 1;
break;
}
if (strcmp(args[i], "|&") == 0) {
split = i;
pipeNum = 2;
break;
}
}
for (int i = 0; i < split; i++) {
cmd1 = cmd1 + args[i] + " ";
}
for (int i = split + 1; i < num_args; i++) {
cmd2 = cmd2 + args[i] + " ";
}
// the implementation of the pipe command
void PipeCommand::execute() {
int pipeFd[2];
int pid;
pipe(pipeFd);
pid = fork();
if (pid == 0) { // child process .
close(pipeFd[1]);
dup2(pipeFd[1], pipeNum);
if (isBuiltInCMD(args[0])) { // if the command is built in which means i wrote it i run it like this ( this works fine i checked it)
Command *newCmd = CreateBuiltInCommand(const_cast<char *>(cmd1.c_str()));
newCmd->execute();
exit(0);
} else { // if the command is external than use execv
const char **argv = new const char *[4];
argv[0] = "/bin/bash";
argv[1] = "-c";
argv[2] = cmd1.c_str();
argv[3] = nullptr;
execv(argv[0], const_cast<char **>(argv));
perror("execvp failed");
}
} else { // the parent process , basically runs the command2 , which it can be only an external command
pid = fork(); // we fork again in the parent process
if (pid == 0) { // the child process executes the secomd command using execv
dup2(pipeFd[0], STDIN_FILENO);
close(pipeFd[0]);
dup2(pipeFd[0], pipeNum);
// execute
const char **argv = new const char *[4];
argv[0] = "/bin/bash";
argv[1] = "-c";
argv[2] = cmd2.c_str();
argv[3] = nullptr;
execv(argv[0], const_cast<char **>(argv));
perror("execvp failed");
} else { // the parent process waits
waitpid(pid,NULL,0);
close(pipeFd[1]);
close(pipeFd[0]);
}
This code makes the pipe, but I think the problem may be in the Parser.exe program not getting the first word, but all the input.
int main(int argc, char** argv)
{
int pipes[2] {0};
int pid {0};
if (argc < 3) {
printf ("No file to cat and/or no text to grep.\n");
return 1;
}
pipe (pipes);
pid = fork();
if (pid == 0) {
dup2 (pipes[1], STDOUT_FILENO);
close (pipes[1]);
close (pipes[0]);
execl ("/bin/cat", "/bin/cat", argv[1], nullptr);
} else {
int pid = fork();
if (pid == 0) {
dup2 (pipes[0], STDIN_FILENO);
close (pipes[1]);
close (pipes[0]);
execl ("/bin/grep", "/bin/grep", argv[2], nullptr);
} else {
close (pipes[0]);
close (pipes[1]);
waitpid (pid, nullptr, 0);
}
}
return 0;
}
It is working but you may have to adapt to your class.
This is my output:
manuel#desktop:~/projects$ ./main sync_client.cpp boost
Going to cat sync_client.cpp
Going to grep for boost
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
std::cout << " sync_client www.boost.org /LICENSE_1_0.txt\n";
boost::asio::io_service io_service;
boost::system::error_code error = boost::asio::error::host_not_found;
throw boost::system::system_error(error);
boost::asio::streambuf request;
boost::asio::write(socket, request);
boost::asio::streambuf response;
boost::asio::read_until(socket, response, "\r\n");
boost::asio::read_until(socket, response, "\r\n\r\n");
while (boost::asio::read(socket, response,
boost::asio::transfer_at_least(1), error))
if (error != boost::asio::error::eof)
throw boost::system::system_error(error);

C++ microshell, input a command and pipe it to a process using fork(), dup(), pipe(). Is just I don't get the results I want

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <sys/utsname.h>
#include <unistd.h>
using namespace std;
//first comannd to execute
void first(int pipeA[], char * command[]){
//redirect STDOUT to pipe[1] and close the pipe[0] we are not using
dup2(pipeA[1], 1);
close(pipeA[0]);
execvp(command[0], command);
printf(" first error ");
exit(127);
}
void second(int pipeA[], char * command2[]){
//redirect STDIN to pipe[0] and close the pipe[1] that we are not using
dup2(pipeA[0], 0);
close(pipeA[1]);
//This doesnt seem to be doing anything at times
execvp(command2[0], command2);
perror(" second error ");
exit(127);
}
int main(void)
{
char buf[1024];
char * command[1024];// this one is the first input usually 'cat file.txt'
//Use only one or the other, sort never works and 'grep U' works sometimes
char * command2[] = {(char *)"sort", (char *) NULL};// this is wants to sort the above 'command[1024]' and its use in the second function
//char * command2[] = {(char *)"grep",(char *)"U",(char *) NULL};// this is wants to grep the above 'command[1024]' and its use in the second function
//variables for forks and waits
pid_t pid;
pid_t pid2;
int status;
int status2;
//see if || exists not in use currently
bool pipeExists = false;
//create pipe
int pipeA[2];
pipe(pipeA);
//first line and ask for input,
cout<< "command: ";
while (fgets(buf,1024,stdin) != NULL)
{
buf[strlen(buf) -1] = 0;
//Save input into buf and tokenized? it
//NOT YET CATCHING ||, im only debugging and usually use use 'cat file.txt'
int number =0;
char * ptr;
ptr = strtok(buf, " ");
while(ptr != NULL){
command[number] = ptr;
ptr = strtok(NULL, " ");
number++;
}
//***************************************************************
//1. do the pipes go here or after the children?
//They seem to be working here but im not really sure where they should be
close(pipeA[0]);
close(pipeA[1]);
//create first child
if ((pid = fork()) <0)
printf("fork error");
else if (pid == 0)
{ /* child */
//create second child INSIDE ORIGINAL CHILD
//2. Is this correct? or is there not supposed to be grandchildren?
if ((pid2 = fork()) <0)
printf("fork 2 error");
else if (pid == 0)
{ /* child */
second(pipeA, command2);
printf("couldn't execute: %s");
exit(127);
}
//first command from buf
first(pipeA, command);
printf("couldn't execute: %s");
exit(127);
//3. Do I wait for this child aswell?
if ( (pid2 = waitpid(pid2, &status2, 0)) < 0)
printf("waitpid error");
}
/* parent */
if ( (pid = waitpid(pid, &status, 0)) < 0)
printf("waitpid error");
printf("Command :");
//***************************************************************
//***************************************************************
//SECOND WAY OF DOING IT
// THIS WAY IT TRIGGERS WAITPID ERRORS.
/*
close(pipeA[0]);
close(pipeA[1]);
//create first child
if ((pid = fork()) <0)
printf("fork error");
else if (pid == 0)
{
first(pipeA, command);
printf("couldn't execute: %s");
exit(127);
}
//create second child INSIDE ORIGINAL CHILD
if ((pid2 = fork()) <0)
printf("fork 2 error");
else if (pid == 0)
{
second(pipeA, command2);
printf("couldn't execute: %s");
exit(127);
}
//3. Do I wait for this child aswell?
if ( (pid2 = waitpid(pid2, &status2, 0)) < 0)
printf("waitpid error");
if ( (pid = waitpid(pid, &status, 0)) < 0)
printf("waitpid error");
printf("Command :");
*/
//***************************************************************
}
exit(0);
}
Pretty much what the code shows here with its questions.
I need to create a microshell that takes in a command ("cat file.txt") and execute it with execvp() and pipe it to another process and either "sort" or "grep U" or anyother.
It's just that my processes won't run correctly at time or wont display anything. I have closed pipes all over the place and nothing has happen.
Solution by OP.
This is the code that works for microshell.
I ended up with creating two processes in the original parents process.
Moving some variables inside the while loop and resetting them to work again. Also create the pipe everytime the code runs and close the pipes.
Created a waitpid() for both processes not just one.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <sys/utsname.h>
#include <unistd.h>
using namespace std;
//This function will execute the users first command.
//It takes in a pipe the command array and a boolean to check for piping
//If a pipe exists then the boolean is true and will dup() the STDOUT into the write part of the pipe
//We close unecessary parts of the pipe and execvp() the command in the command array
//there it some error checkink in case the command doesn't execute
void first_command(int pipeA[], char * command[], bool pipeExists){
if(pipeExists){
dup2(pipeA[1], 1);
close(pipeA[0]);
}
execvp(command[0], command);
printf("can not execute first command. \n");
exit(127);
}
//This function is only called in the main is a piping exists
//It takes in a pipe and a command array
//It dup() the STDIN from the read end of the pipe and closes the unsued end
//It will execute the command accorind to what was provided in the the pipe
void second_command(int pipeA[], char * command2[]){
dup2(pipeA[0], 0);
close(pipeA[1]);
execvp(command2[0], command2);
printf("can not execute second command. \n");
exit(127);
}
int main(void)
{
//this variable will take in the line of input submitted by the user
char buf[1024];
//PIDs for the two child processes
pid_t pid;
pid_t pid2;
//these will be use to check the status of each child in the parent process
int status;
int status2;
//initializes the pipe
int pipeA[2];
//out put the first line to ask user for input
cout<< "480shel> ";
//stay inside the loop and keep asking the user for input until the user quits the program
while (fgets(buf,1024,stdin) != NULL){
//initialize a boolean to check if user wants to pipe something, set to false by default until we check with user
bool pipeExists = false;
//initialize this arrays to NULL so anything that store in them gets cleared out.
//these arrays will hold the commands that the user wants to carry out.
char * command[1024] = {NULL, NULL, NULL};
char * command2[1024] = {NULL, NULL, NULL};
//Important to delete mark the last byte as 0 in our input
buf[strlen(buf) -1] = 0;
//initialize this number to zero to start save the tokens at this index
int index = 0;
//a char * to hold the token saved by strtok
char * ptr;
ptr = strtok(buf, " ");
//Loop through 'buf' and save tokens accordingly
while(ptr != NULL){
//If ptr is equal to q or quit then user want to exit program
if(strcmp( ptr, "q" ) == 0){
exit(0);
}
if(strcmp( ptr, "quit" ) == 0){
exit(0);
}
//if ptr is equal to || user wants to pipe something and we change pipeExists to true
if(strcmp( ptr, "||" ) == 0){
pipeExists = true;
index= 0;
ptr = strtok(NULL, " ");
}
//enter here while user doesnt want to user pipes
if(!pipeExists){
command[index] = ptr;
ptr = strtok(NULL, " ");
index++;
}
//enter here if user want to use pipes
if(pipeExists){
command2[index] = ptr;
ptr = strtok(NULL, " ");
index++;
}
}
//if pipes exists then initialize it
if(pipeExists){
pipe(pipeA);
}
//create first child
if ((pid = fork()) == 0) {
//pass in the pipe, commands and pipe to function to execute
first_command(pipeA, command, pipeExists);
}
else if(pid < 0){
//error with child
cerr<<"error forking first child"<<endl;
}
// if pipe exists create a second process to execute the second part of the command
if(pipeExists){
//create second child
if ((pid2 = fork()) == 0) {
second_command(pipeA, command2);
}
else if(pid2 < 0){
//error with second child
cerr<<"error forking second child"<<endl;
}
}
//if the pipe was created then we close its ends
if(pipeExists){
close(pipeA[0]);
close(pipeA[1]);
}
//wait for the first child that ALWAYS executes
if ( (pid = waitpid(pid, &status, 0)) < 0)
cerr<<"error waiting for first child"<<endl;
//wait for the second child bu only if user wanted to created to use piping
if(pipeExists){
if ( (pid2 = waitpid(pid2, &status2, 0)) < 0)
cerr<<"error waiting for second child"<<endl;
}
cerr<<"480shell> ";
}//endwhile
exit(0);
}

ferror leads to access violation

I get an Access Violation when calling ferror(f). The thing is I check that f isn't a null pointer. I'm also able to read out of the file, before I get the Access Violation. It happens in the bzip library from http://www.bzip.org, (which is only modified, so that it is possible to build, eg. disable error and remove the multiple main functions).
Here is the my main
int main() {
int e = 0;
int *error = &e;
FILE *f = fopen("./test", "r"); //open file
if (f == NULL) { //Changed, as beforehand both checks happend at the same time
//However the programm passes both checks
std::cout << "f* is NULL\n";
exit(1);
}
if (ferror(f)) {
std::cerr << "Can't open the file " << ferror(f) << '\n';
exit(1);
}
char *c = char[20];
fread(c, 1, 20, f); // Here we can read succesfully out of the file
std::cout << c;
BZFILE* bzfile = BZ2_bzReadOpen(error, f, 1, 0, NULL, 0); //The failing function call
}
Here is the function out of the library which fails:
BZFILE* BZ_API(BZ2_bzReadOpen)
( int* bzerror,
FILE* f,
int verbosity,
int small,
void* unused,
int nUnused )
{
bzFile* bzf = NULL;
int ret;
BZ_SETERR(BZ_OK);
if (f == NULL || //A check in the function itself, which also passes
(small != 0 && small != 1) ||
(verbosity < 0 || verbosity > 4) ||
(unused == NULL && nUnused != 0) ||
(unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)))
{ BZ_SETERR(BZ_PARAM_ERROR); return NULL; };
if (ferror(f)) // Here is the access violation
{ BZ_SETERR(BZ_IO_ERROR); return NULL; };
}
The specific error is
Exception thrown at 0x0003E5C4 in wikiParser.exe: 0xC0000005: Access violation executing location 0x0003E5C4.
I tried moving the program to a different pc, however the same error still occurs. The pointer isn't NULL; there are two checks for that, and I can call ferror myself, without it being an access violation.
if(f == NULL || ferror(f)) // Check that f isn't NULL nor has an Error
std::cerr << "Can't open the file " << ferror(f) << '\n';
In other words, if f== NULL then cerr << ferror(f).
No wonder it blows up.

Shell Pipe Implementation single level

I am writing my shell and this is the piece of code. Can anyone please explain why I am not reaching in the end of following function i.e OUT is not printed.I have read shell related article but they don't seem to help.
commandargs() function returns formatted string i.e removing spaces and storing arguments. My 2 nights are wasted doing debugging only.
It works fine and output is correct but program execution stops after this function.
int shellpipe(char **arg)
{
// pid_t childpid;
int status;
int pfd[2];
pid_t cpid;
char c;
char **p=commandargs(arg[0]);
char **q=commandargs(arg[1]);
cout<<"q0";//not printed
if ( pipe(pfd) < 0){
perror("pipe");
return 1;
}
cpid = fork();
if( cpid == 0 )
{
/* CHILD 1*/
close(0);
dup2(pfd[0], 0);
close(pfd[1]);
if (execvp(q[0],q)==-1)
perror("Executing Error");
exit(0);
} else if ( cpid > 0){
/* PARENT */
close(1);
dup2(pfd[1], 1);
close(pfd[0]);
if (execvp(p[0],p)==-1)
perror("Executing Error");
close(pfd[1]);
close(1);
wait(&status);
}else{
/* ERROR */
perror("fork");
return 1;
}
cout<<"Out";//control don't reach here
}
"Out" isn't printed because the output stream is already closed. It might also be that the child process never finishes, but this would require a closer look on the argument strings.

Toy shell not piping correctly

I'm not going to lie. This is a homework question. However, as far as I'm concerned, the points are gone baby gone. Right now, I'm just looking for an answer, because I -think- I might be insane.
The goal of this program is to execute the command ps -A | grep (inputstring) | wc -l in a way similar to how the shell does it. So, I spawn the processes, and have them wait on each other. The newest process, the great-grandchild, execlp("ps","ps","-A",NULL) which replaces itself with the ps -A process. Before it execlp, I make sure its standard output is going to the pipe output. The next process in line is wait()ing, and already has itself set up so that the input pipe goes to standard in, and standard out goes to the output pipe, and it will execute grep, and so on.
I'm almost positive I have it set up correctly. And yet... the program does. Not. Work.
#include <stdlib.h>
#include <iostream>
#include <string>
#define MAXLINE 1500
#define READ 0
#define WRITE 1
using namespace std;
int main( int argc, char** argv ) {
//* start of input block
if ( argc != 2 ) {
cout << "Usage: ./a.out arg1" << endl;
return 0;
}
string in = argv[1];
// end of input block */
int pipeA[2], pipeB[2], pid, stat;
// get our first set of pipes
if ( pipe(pipeA) < 0 ) {
cerr << "Pipe error.\n";
exit(-1);
}
if ( pipe(pipeB) < 0 ) {
cerr << "Pipe error.\n";
exit(-1);
}
// make the first fork
if ( (pid = fork() ) < 0 ) { cerr << "Fork error.\n"; exit(-1); }
if ( pid > 0 ) { // parent case
wait(&stat);
} else { // child case
if ( (pid = fork()) < 0 ) { cerr << "Fork Error\n"; exit(-1); }
if ( pid > 0 ) { // child
wait(&stat);
dup2(pipeA[READ],READ);
execlp("wc","wc","-l",NULL);
} else { // grand-child
if ( (pid = fork()) < 0 ) { cerr << "Fork Error\n"; exit(-1); }
if ( pid > 0 ) { // still grand-child
wait(&stat);
dup2(pipeB[READ],READ);
dup2(pipeA[WRITE],WRITE);
close(pipeB[READ]);
execlp("grep","grep",in.c_str(),NULL);
} else { // great grand-child
dup2(pipeB[WRITE],WRITE); // t now goes to pipeB[1]
close(READ);
close(pipeB[READ]);
execlp("ps", "ps", "-A", NULL);
}
}
}
return 0;
}
EDIT: Changed to the two-pipe variant of my code.
I'm virtually certain this is what you're trying to do. Apologies in advance for the sloppy coding. its somewhat late here and I really should be sleeping right now:
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#define READ 0
#define WRITE 1
// ps -A | grep argv[1] | wc -l
int main( int argc, char** argv )
{
// start of input block
if ( argc != 2 )
{
std::cout << "Usage: ./a.out arg1" << std::endl;
return 0;
}
// make local copy of argument
std::string in = argv[1];
int fd1[2], fd2[2], pid;
// allocate two pipe sets
if (pipe(fd1) < 0 || pipe(fd2) < 0)
{
perror("Failed to create pipe.");
return EXIT_FAILURE;
}
// launch first child process.
if ((pid = fork()) < 0)
{
perror("Failed to fork child(1)");
return EXIT_FAILURE;
}
if (pid == 0)
{
// wc -l process.
// stdin = fd2(read)
close(fd1[READ]);
close(fd1[WRITE]);
close(fd2[WRITE]);
dup2(fd2[READ],STDIN_FILENO);
execlp("wc","wc","-l",NULL);
}
// fork again. this time for grep
if ((pid = fork()) < 0)
{
perror("Failed to fork child(2)");
return EXIT_FAILURE;
}
if (pid == 0)
{
// grep argv[1] process.
// stdin = fd1(read)
// stdout = fd2(write)
close(fd1[WRITE]);
close(fd2[READ]);
dup2(fd2[WRITE], STDOUT_FILENO);
dup2(fd1[READ], STDIN_FILENO);
execlp("grep", "grep", in.c_str(), NULL);
}
// fork once more. this time for ps -A
if ((pid = fork()) < 0)
{
perror("Failed to fork child(3)");
return EXIT_FAILURE;
}
if (pid == 0)
{
// ps -A process.
// stdout = fd1(write)
close(fd2[WRITE]);
close(fd2[READ]);
close(fd1[READ]);
dup2(fd1[WRITE], STDOUT_FILENO);
execlp("ps", "ps", "-A", NULL);
}
int stat=0;
wait(&stat);
return EXIT_SUCCESS;
}
On my system, ps -A reports 141 lines, of those 41 have the word System somewhere within, verified by simply running ps -A | grep System | wc -l. The above code generates precisely the same output.
I'm not sure but maybe calling dup2 before waiting on the child would fix the pipe problem.
The reason I'm not sure is that it normally stdin and stdout are bufferized so I suppose that even if you hook your pipe up with them after the child has finish running you should get the same results but maybe (if someone knows the answer to this please correct me) the buffers for stdin and stdout get wiped with the end of the child process.
Also, could you update the code in your question to contain the modified code with two sets of pipes ?