Howdy, Stranger!

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

Sign In with Facebook Sign In with Google Sign In with OpenID

Categories

We have migrated to a new platform! Please note that you will need to reset your password to log in (your credentials are still in-tact though). Please contact lee@programmersheaven.com if you have questions.
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

  • bragrbragr Posts: 5Member
    I found that my problem was that I was secretly seg faulting in the child, which was causing the child to silently fail. The code works if you substitute the strcpy() with "arglist[x] = strdup(tok[x].c_str());" which actually allocates memory. The pipes are only needed for commands like "ps aux | grep bragr" in which the output of one child needs to be piped to the input of another.
  • blkhd32blkhd32 Posts: 1Member
    Hi,
    I was wondering if you ever got your '|' '>' '<' up and running on your shell?

    thnks
  • bragrbragr Posts: 5Member
    I did but if you go to ucr, I'm not going to give you code. :)
Sign In or Register to comment.