Simple Shell in C++ - Programmers Heaven

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

Simple Shell in C++

I am new to linux programming, and to get my bearings, I have been writing some small programs. I have already written a ls clone that will do ls, ls -l, and ls -lR. My current project is to write a simple shell. My understanding on how to do this is to loop the following: Get some input from the user and parse it into an array of cstrings, fork the program, have the child exec the user's command. I tried this, but I found that I lost i/o with the child after the exec, which make sense considering what it does. I did some reading online, I found that I need to use pipes to connect the child stdout and stdin to the parents before the exec. I did a few experiments with the pipes, but they all either crashed or didn't work, so I'm clearly missing something.

Is my understanding of what I need to do correct? Am I missing some small, but important detail? Is it even possible to connect out pipe to the parent's stdout so the child's output is automatically output to the console, or do I need to manually read the pipe and output its contents. Can you give me some examples of using pipes in this context, preferably in C++? Thanks in advance.


My code so far:
[code]
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

const unsigned int MAX_ARGS = 128;

using namespace std;

// Execute a parsed command line returning the command's exit code
int doit(const vector& tok)
{
if (!tok.size() || tok[0] == "") return 0;
// If user entered cd, change to specified dir. If no dir specified, change to the users home dir
else if (tok[0] == "cd")
{
if (tok.size() > 1) chdir(tok[1].c_str());
else chdir(getenv("HOME"));
return 0;
}

//Else execute the command specified by the user
if (pid_t kidpid = fork())
{
//Parent
int status = 0;
if (tok.back().at(tok.back().size() - 1) != '&')
{
waitpid(kidpid, &status, 0);

#ifdef _INSPECT_EXIT_STATUS
cout << "exit status=" << status << endl;
#endif //_INSPECT_EXIT_STATUS
}
return status;
}
//Child - execute the command
char* arglist[MAX_ARGS];
for (unsigned int x = 0; x < tok.size() && x < MAX_ARGS - 1; x++)
strcpy(arglist[x], tok[x].c_str());
arglist[tok.size()] = NULL;

execvp(tok[0].c_str(), arglist);

//Program will never reach here unless execvp failed
cerr << "execpv failed: " << strerror(errno) << endl;
exit(errno);
}

int main(int argc, char* argv[], char* envp[])
{
while (!cin.eof())
{
cout << "? ";
string temp;
getline(cin, temp);
if (temp == "exit") break;

vector<string> v;
//Break string into separate strings on whitespace
{
stringstream foo(temp);
string s;
while (foo >> s)
{
if (s[0]=='~') s = getenv("HOME") + s.substr(1);
v.push_back(s);
}
}
doit(v);
}
cout << "exit" << endl;
return 0;
}[/code]

Comments

Sign In or Register to comment.