While loop not continuing after fork and execvp calls - c++

After running my program for the first time around it runs correctly but the loop does not continue.
I have tried adding more forks into my function but it seems to not work.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;
int main(){
int pipefd[2];
int rs;
pid_t cpid;
char* args1[256];
char* args2[256];
char cmd1[256];
char cmd2[256];
char path1[10];
char path2[10];
//starts while loop
while(true){
//creates pipe
rs = pipe(pipefd);
if (rs < 0){
perror("pipe");
exit(1);
}
//gets comands from user
cout << "Command 1";
cin.getline(cmd1,256);
cout << "command 2";
cin.getline(cmd2,256);
//checks id with commands are quit
if (strcmp(cmd1,"quit") == 0)
break;
if (strcmp(cmd2,"quit") == 0)
break;
char *token;
token = strtok(cmd1," ");
int i=0;
//splits char arrays up
while(token != NULL){
args1[i] = token;
token = strtok(NULL, " ");
i++;
}
args1[i] = NULL;
token = strtok(cmd2," ");
i = 0;
while(token != NULL){
args2[i] = token;
token = strtok(NULL, " ");
i++;
}
args2[i] = NULL;
strcpy(path1,args1[0]);//copis the command to the path file
strcpy(path2,args2[0]);
//forks and creates child process
rs = fork();
if (rs == 0){//child process
close(pipefd[1]);//close write end of pipe
close(0);//close standard input
dup(pipefd[0]);//duplicate read end of pipe into standard
input
close(pipefd[0]);//close read end of pipe
rs = execvp(path2,args2);//runs program 2
if (rs < 0){
perror("execl");
exit(1);
}
}
else{//PARENT PROCESS
close(pipefd[0]);//close read end of pipe
close(1);//close standard input
dup(pipefd[1]);//duplicate write end of pipe into standard
input
close(pipefd[1]);//clsoe write end of pipe
rs = execvp(path1,args1);//runs command 1
if (rs < 0){
perror("execl");
exit(1);
}
}
}
return 0;
}
After going through the loop the first time the user should be asked for enter in two more commands or be able to quit out of the function

rs = execvp(path1,args1);//runs command 1
This line in the "parent process" replaces the current program. There is no while loop after this succeeds anymore, only program 1.
Think of it this way. When user inputs m pairs of commands to your program, how many processes do you expect to be spawned? You expect a total of 2m processes each corresponding to a command but you only fork m times each corresponding to an iterations of the while loop in your current code.
You should instead fork a different process for program 1 as well, similar to how you did it for program 2.

Related

Multiple Pipes, C++

I've been stuck on an issue with my program and just hoping for any help at this point :(
or guidance towards the right direction. In my code, I'm implenting a mini shell in c++ where the user can pipe 2 or more processes together, yet an issue keeps coming up whenever I execute it. Only the first and last commands actually execute so say I run:
cat b.txt | sort | tail -2
only cat b.txt and tail -2 would execute.
Here is my attempt at the whole program, also referenced to this which helped me tremendously with the setup.
#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 variable will take in the line of input submitted by the user
char buf[1024];
//PIDs for the two child processes
pid_t pid[300];
//these will be use to check the status of each child in the parent process
int status;
int status2;
int pid_num = 1;
//initializes the pipe
int pipeA[2] = {-1,-1};
int g = 0;
void first_command(int pipeA[], char * command[], bool pipeExists){
if(pipeExists){
dup2(pipeA[1], 1);
close(pipeA[0]);
}
// this will run command[0] as the file to execute, and command as the arg
execvp(command[0], command);
printf("Can not execute FIRST command, please enter a valid command \n");
exit(127);
}
void other_command(int pipeA[], char * command0[], int index){
dup2(pipeA[0], 0);
close(pipeA[1]);
execvp(command0[0], command0);
printf("Can not execute SECOND command, please enter a valid command\n");
exit(127);
}
void main_func() {
//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 *command0[1024] = {NULL, NULL, NULL};
char *command1[] = {NULL, NULL, NULL};
char *command2[] = {NULL, NULL, NULL};
char *command3[] = {NULL, NULL, NULL};
char ** my_commands[] = {
command0,
command1,
command2,
command3,
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 the user types exit at any moment, the program will exit gracefully and terminate
if(strcmp( ptr, "exit" ) == 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){
command0[index] = ptr;
ptr = strtok(NULL, " ");
index++;
}
g++;
printf("%s %i\n", ptr, g);
}
for (int s = 0; my_commands[s] != NULL; s++) {
cout << command0[s] << " \n" << endl;
}
//if pipes exists then initialize it
if(pipeExists){
pipe(pipeA);
}
//create first child
if ((pid[0] = fork()) == 0) {
//pass in the pipe, commands and pipe to function to execute
first_command(pipeA, command, pipeExists);
}
else if(pid[0] < 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){
for(int f = 0; my_commands[f] != NULL; f++) {
//create second child
if ((pid[f] = fork()) == 0) {
other_command(pipeA, command0, index);
}
else if(pid[f] < 0){
//error with second child
cerr<<"error forking child "<< pid_num << endl;
}
}
pid_num++;
}
//if the pipe was created then we close its ends
if(pipeExists){
for(int z = 0; z < pid_num; z++) {
close(pipeA[z]);
}
}
//wait for the first child that ALWAYS executes
if ( (pid[0] = waitpid(pid[0], &status, 0)) < 0)
cerr<<"error waiting for first child"<<endl;
//wait for the second child but only if user wanted to created to use piping
if(pipeExists){
for(int j = 1; j < pid_num; j++) {
if ( (pid[j] = waitpid(pid[j], &status2, 0)) < 0){
printf("Status: %d", pid[j]);
cerr<<"error waiting for child " << j <<endl;
}
}
}
pid_num = 1;
}//endwhile
}

How to fix loop not working using execv and forks

When running this program after the first iteration the program stops. This is because of execv function. What can I do so my loop still continues on until the user types quit.
I have tried creating a fork process before doing the execv in the child process but that does not work.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;
int main(){
int pipefd[2];
int rs;
pid_t cpid;
pid_t cpid2;
rs = pipe(pipefd);
char* args1[256];
char* args2[256];
if (rs < 0){
perror("pipe");
exit(1);
}
char cmd1[256];
char cmd2[256];
char path1[10];
char path2[10];
while(true){
cout << "Command 1";
cin.getline(cmd1,256);
cout << "command 2";
cin.getline(cmd2,256);
if (strcmp(cmd1,"quit") == 0)
break;
if (strcmp(cmd2,"quit") == 0)
break;
char *token;
token = strtok(cmd1," ");
int i=0;
while(token != NULL){
args1[i] = token;
token = strtok(NULL, " ");
i++;
}
args1[i] = NULL;
token = strtok(cmd2," ");
i = 0;
while(token != NULL){
args2[i] = token;
token = strtok(NULL, " ");
i++;
}
args2[i] = NULL;
strcpy(path1,args1[0]);
strcpy(path2,args2[0]);
rs = fork();
if (rs < 0){
perror("Fork");
exit(1);
}
if (rs == 0){//child process
close(pipefd[1]);
close(0);
dup(pipefd[0]);
close(pipefd[0]);
rs = execvp(path2,args2);
if (rs < 0){
perror("execl");
exit(EXIT_FAILURE);
}
}
else{//PARENT PROCESS
close(pipefd[0]);
close(1);
dup(pipefd[1]);
close(pipefd[1]);
wait(&rs);
rs = execvp(path1,args1);
if (rs < 0){
perror("execl");
exit(EXIT_FAILURE);
}
}
};
return 0;
}
After outputting the answer the function should then ask the user for two more commands, This should go on until the user types in quit.
First of all exit(EXIT_FAILURE) is making your program exit.So remove it.
And you can put the possible exception creating code in try {} catch {} block.
In your case like this..
try{
rs = execvp(path1,args1);
if (rs < 0){
perror("execl");
//exit(EXIT_FAILURE);
}
}catch(int y){
continue;//here you can put your handling logic
}
By this you will get the desired output.

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);
}

Myshell Segmentation Fault, Possible issue with getting input?

I have been working on this project for a while. The purpose is to make a functioning shell that can do pretty much all the shell commands (except cd). It does almost everything I want it to do, except for a couple things. The first is that when I put an '&' to signify background processing, it does it, but then doesn't print another myshell> line. I can still input something, but the myshell> never shows up, no matter where I put another cout<<"myshell> ";.
Another issue is if I press enter, making myString empty, many times, it crashes the program with a seg fault. Also after I do the '&' background processing and press enter to get the myshell> to come back up, it prints one myshell> but then seg faults on the next hit of enter. I'm sorry if I didn't explain this well, but it is really driving me crazy. Please let me know if you have any suggestions.
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <cstring>
#include <sys/types.h>
#include <cstdio>
#include <sys/wait.h>
#include <stdio.h>
/*Function that parses the command the user inputs.
It takes myArgv and myString as inputs.
It returns the value of exitcond, which is used to see if the user wants to exit or not.
Also, this is where myString is tokenized using strok()*/
int parseCommand(char *myArgv[10], char myString[255])
{
int exitcond=0;
if((strcmp(myArgv[0], "exit") == 0)||(strcmp(myArgv[0], "quit")==0))
{
exitcond = 1;
return exitcond;
}
int i;
char *token;
token = strtok(myString," ");
i=0;
while (token != NULL)
{
myArgv[i] = token;
token = strtok(NULL," ");
i++;
}
/*
* Set the last entry our new argv to a null char
* (see man execvp to understand why).
*/
myArgv[i] = '\0';
return exitcond;
}
/*Function that gets the command from the user and sees if they want
background processing or not (presence of '&').
It takes inputs of choose and myString. choose is the variable for
whether background processing is necessary or not, while myString is
an empty character array.
It outputs the value of the choose variable for lter use.*/
int getCommand(int choose, char myString[255])
{
int i;
choose=0;
fgets(myString, 256, stdin);
if (myString[0]=='\0')
{
choose=0;
return choose;
}
for (i=0; myString[i]; i++)
{
if (myString[i]== '&')
{
choose=1;
myString[i]=' ';
}
if (myString[i] == '\n')
{
myString[i] = '\0';
}
}
return choose;
}
/*Main function where all the calling of other functions and processes
is done. This is where the user enters and exits the shell also. All
usage of fork, pid, waitpid and execvp is done here.*/
int main()
{
using namespace std;
int exitCondition=0, i=0, status;
char myString[255];
char *token, *myArgv[10];
pid_t pid, waiting;
int bg=0;
while (!exitCondition)
{
/* print a prompt and allow the user to enter a stream of characters */
cout << "myshell> ";
bg=0;
int choose=0;
bg=getCommand(choose,myString);
exitCondition=parseCommand(myArgv,myString);
if(exitCondition==1)
{
cout<<"Thank you for using my shell.\n";
}
else {
/* while (myString[0]=='\0')
{
cout<<"myshell> ";
bg=getCommand(choose,myString);
}*/
/* The user has a command, so spawn it in a child process */
pid = fork();
if (pid == -1)
{
/* to understand why this is here, see man 2 fork */
cout << "A problem arose, the shell failed to spawn a child process" << endl;
return(1);
}
else if (pid == 0)
{
// Child process
execvp(myArgv[0],myArgv);
cout << "Bad command or file name, please try again!\n" << endl;
return 0;
} else {
/* This makes sure that the spawned process is run in the foreground,
because the user did not choose background */
if(bg==0)
{
waitpid(pid,NULL,0);
}
}
}
}
return 0;
}
Okay, you had three bugs, one of which caused the segfault. Of the others, one would put a garbage argument in the array passed to execvp and the other would leak zombie processes for background jobs.
I've corrected the code and annotated it with where the bugs were along with the fixes [please pardon the gratuitous style cleanup]:
#include <cstdio>
#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define AVCOUNT 100
#define STRBUFLEN 2000
/*Function that parses the command the user inputs.
It takes myArgv and myString as inputs.
It returns the value of exitcond, which is used to see if the user wants to
exit or not.
Also, this is where myString is tokenized using strok()*/
int
parseCommand(char **myArgv, char *myString)
{
char *token;
char *bp;
int exitcond = 0;
int i;
// NOTE/BUG: original check for exit/quit was here -- at this point
// myArgv is undefined (hence the segfault)
// NOTE/BUG: your original loop -- at the end i was one beyond where it
// should have been so that when myArgv gets passed to execvp it would
// have an undefined value at the end
#if 0
token = strtok(myString, " ");
i = 0;
while (token != NULL) {
myArgv[i] = token;
token = strtok(NULL, " ");
i++;
}
#endif
// NOTE/BUGFIX: here is the corrected loop
i = 0;
bp = myString;
while (1) {
token = strtok(bp, " ");
bp = NULL;
if (token == NULL)
break;
myArgv[i++] = token;
}
/*
* Set the last entry our new argv to a null pointer
* (see man execvp to understand why).
*/
// NOTE/BUG: with your code, i was one too high here
myArgv[i] = NULL;
// NOTE/BUGFIX: moved exit/quit check to here now that myArgv is valid
token = myArgv[0];
if (token != NULL) {
if ((strcmp(token, "exit") == 0) || (strcmp(token, "quit") == 0))
exitcond = 1;
}
return exitcond;
}
/*Function that gets the command from the user and sees if they want
background processing or not (presence of '&').
It takes inputs of choose and myString. choose is the variable for
whether background processing is necessary or not, while myString is
an empty character array.
It outputs the value of the choose variable for lter use.*/
int
getCommand(int choose, char *myString)
{
int i;
choose = 0;
fgets(myString, STRBUFLEN, stdin);
if (myString[0] == '\0') {
choose = 0;
return choose;
}
for (i = 0; myString[i]; i++) {
if (myString[i] == '&') {
choose = 1;
myString[i] = ' ';
}
if (myString[i] == '\n') {
myString[i] = '\0';
break;
}
}
return choose;
}
/*Main function where all the calling of other functions and processes
is done. This is where the user enters and exits the shell also. All
usage of fork, pid, waitpid and execvp is done here.*/
int
main()
{
using namespace std;
int exitCondition = 0;
int status;
char myString[STRBUFLEN];
char *myArgv[AVCOUNT];
pid_t pid;
int bg = 0;
while (!exitCondition) {
// NOTE/BUGFIX: without this, any background process that completed
// would become a zombie because it was never waited for [again]
// reap any finished background jobs
while (1) {
pid = waitpid(0,&status,WNOHANG);
if (pid < 0)
break;
}
/* print a prompt and allow the user to enter a stream of characters */
cout << "myshell> ";
bg = 0;
int choose = 0;
bg = getCommand(choose, myString);
exitCondition = parseCommand(myArgv, myString);
if (exitCondition == 1) {
cout << "Thank you for using my shell.\n";
break;
}
/* while (myString[0]=='\0') { cout<<"myshell> "; bg=getCommand(choose,myString); } */
/* The user has a command, so spawn it in a child process */
pid = fork();
if (pid == -1) {
/* to understand why this is here, see man 2 fork */
cout << "A problem arose, the shell failed to spawn a child process" << endl;
return 1;
}
if (pid == 0) {
// Child process
execvp(myArgv[0], myArgv);
cout << "Bad command or file name, please try again!\n" << endl;
return 1;
}
/* This makes sure that the spawned process is run in the
foreground, because the user did not choose background */
if (bg == 0)
waitpid(pid, &status, 0);
}
return 0;
}

IPC using pipes?

I m trying to implement a program using pipes where parent process accepts a string and passes it to child process. Need to be done with only single pipe. How does the pipe read & write accepts string.
Here is my sample code! all!
#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
using namespace std;
int main()
{
int pid[2];
ssize_t fbytes;
pid_t childpid;
char str[20], rev[20];
char buf[20], red[20];
pipe(pid);
if ((childpid = fork()) == -1) {
perror("Fork");
return(1);
}
if (childpid == 0) {
// child process close the input side of the pipe
close(pid[0]);
int i = -1, j = 0;
while (str[++i] != '\0') {
while(i >= 0) {
rev[j++] = str[--i];
}
rev[j] = '\0';
}
// Send reversed string through the output side of pipe
write(pid[1], rev, sizeof(rev));
close(pid[0]);
return(0);
} else {
cout << "Enter a String: ";
cin.getline(str, 20);
// Parent process closing the output side of pipe.
close(pid[1]);
// reading the string from the pipe
fbytes = read(pid[0], buf, sizeof(buf));
cout << "Reversed string: " << buf;
close(pid[0]);
}
return 0;
}
You never pass the string to be reversed to the child, so it reverses some random garbage and sends it to the parent.
Minor issues:
write(pid[1], rev, sizeof(rev));
close(pid[0]); // Should be pid[1]
return(0); // Should be _exit(0)
The reason you don't want to return from main in the child is that you don't know what consequences that will have. You may call exit handlers that manipulate real world objects that the parent expects to remain intact.