c++ - Linux fork() + pipe() confusion -
c++ - Linux fork() + pipe() confusion -
i'm having little bit of problem writing lastly bit of recommended exercise (personal shell), mainly, forking final execvp in chained command composition via pipe ( | ). while actual piping works 1 execvp another, final execvp within of execute() function not forked , hence kill master programme when executed. however, when effort fork it, funny behavior on terminal. namely, duplicate entries on stdout.
ultimately, main question have this: how can fork final execvp in execute() without messing out input , output pipes?
could please point me in right direction how fork process 1 final time in order safely execute execvp without messing out final pipes , disrupting parent shell?
the logic works so: take in string of input --> convert vector of strings-- > pass vector execute(), fires off execprocess() if sees more 1 command because requires piping.
the final execvp in execute() meant run lone command of simple input "ls", or lastly command of chained statement. ie. "wc -w" of "ls -l | wc -w".
please seek not caught in casts, type conversions, , bad reusability repeated chunks of similar code, apologize in advance. understand it's little sloppy.
many in advance.
immediately relevant code below, or pastebin: http://pastebin.com/tst8uh9n 2 cases have been running against "ls -l" , "ls -l | wc -w". both spit out right output, overwrite parent process because can not figure out how safely fork() final execvp() in execute().
int main(){ initenviroment(); //creates directory of possible place executable can located cout << '\n'; cout<<"welcome. \n"; raiseprompt(0); string input = " "; vector<string> inputholder; while( ( input.compare("q") && input.compare("q") ) != 0 ){ cout << endl; // opens fresh line printf("\n ->"); getline(cin, input); printf("\n"); if( (input.compare("q") && input.compare("q") ) == 0){ cout << "see soon! \n"; homecoming 0; } inputholder = commandproc(input); int status = execute(inputholder); cout << status << endl; } int execprocess( vector<char*> argv, int readend, int writeend ){ string stringargv(argv.at(0)); int wordsinstr = wordsinstring(stringargv); if(wordsinstr != 1){ vector<char*> tempvect; argv.swap(tempvect); char *token; token = strtok( const_cast<char*>( stringargv.c_str() ) , " "); argv.push_back( (token) ); while (token != null){ token = strtok(null, " "); argv.push_back( (token) ); } } string stringargvnew(argv.at(0)); string programtofinddir = findprogdir(stringargvnew); const char* programchararr= (programtofinddir + stringargvnew).c_str(); pid_t pid; if ( (pid = fork () ) == 0) //child logic { if ( readend != 0 ) { //nullcheck pipe, if true close dup2 (readend, 0); //old, new close (readend); } if (writeend != 1){ dup2 (writeend, 1); close (writeend); } char **command = &argv[0]; //grab internal vect array homecoming execvp( programchararr, command); //fire off command. heavy lifting. } homecoming pid; } int execute(vector<string> cmd){ string rebuild = ""; //rebuild vector of substrings 1 big string 1 time again if(cmd.size() == 1){ rebuild += (cmd.at(0)); } else{ for(int = 0; < cmd.size(); i++){ rebuild += (cmd.at(i) + " "); } } vector< char*> argv; //argv vector of individual programs, broken downwards cmd string. needed execute char *token; token = strtok( const_cast<char*>( rebuild.c_str() ) , "<>|"); argv.push_back( (token) ); //tokenstr ); while (token != null){ token = strtok(null, "<>|"); argv.push_back( (token) ); //tokenstr ); } int pipeposition = 1; for(int = 1; < cmd.size(); i++){ if( ( cmd.at(i).compare("|") ) == 0){ pipeposition = i; break; } } int amountofcommands = pipeposition; //amount of commands in main code. if pipe position = 1, no pipe exists. int readpipe = read_end; int filedescriptor[2]; int i; for(i = 1; < amountofcommands; i++ ){ n pipe(filedescriptor); execprocess( argv, readpipe, filedescriptor[write_end] ); //execprocess( argv.at(i), readpipe, filedescriptor[write_end] ); close(filedescriptor[write_end]); readpipe = filedescriptor[read_end]; } if( readpipe != 0 ){ dup2(readpipe, 0); // replaces std input old readpipe because broke out } string stringargv(argv.at(pipeposition-1)); // char array string int wordsinstr = wordsinstring(stringargv); //count words, if more one, break downwards if(wordsinstr != 1){ vector<char*> tempvect; argv.swap(tempvect); char *token; token = strtok( const_cast<char*>( stringargv.c_str() ) , " "); argv.push_back( (token) ); while (token != null){ token = strtok(null, " "); argv.push_back( (token) ); } } string stringargvnew(argv.at(0)); //create string char* utilize findprogdir string programtofinddir = findprogdir(stringargvnew); //find respective dir string const char* programchararr= (programtofinddir + stringargvnew).c_str(); //stringargv).c_str(); //makes param 1 char **command = &argv[0]; homecoming execvp(programchararr, command ); //final execvp lastly in chain(or solo case) }
c++ c linux fork execvp
Comments
Post a Comment