LinuxQuestions.org
Go Job Hunting at the LQ Job Marketplace
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 12-14-2009, 10:59 PM   #1
Tblade
LQ Newbie
 
Registered: Dec 2009
Posts: 5

Rep: Reputation: 0
Making a C++ shell


Hello, I am looking for help on getting my basic shell to change directories, and I'm kind of lost. This is for a program in my operating systems class and I'm kind of confused. I was given the following code and right now it will list whats in a directory but I don't know how to make it work for changing directory's .
We are supposed to use cd (folder name) and cd .. (to go back up just like in bash)
Please help me!!

Code:
#include <unistd.h>     // getpid(), getcwd()
#include <sys/types.h>  // type definitions, e.g., pid_t
#include <sys/wait.h>   // wait()
#include <signal.h>     // signal name constants and kill()
#include <iostream>
#include <vector>
#include <string>
using namespace std;


int main()
{
  while ( true )
  {
    // Show prompt.
    cout << getcwd(NULL, 0) << ">> " << flush;
    char command[128];
    cin.getline( command, 128 );

    vector<char*> args;
    char* prog = strtok( command, " " );
    char* tmp = prog;
    while ( tmp != NULL )
    {
      args.push_back( tmp );
      tmp = strtok( NULL, " " );
    }

    char** argv = new char*[args.size()+1];
    for ( int k = 0; k < args.size(); k++ )
      argv[k] = args[k];

    argv[args.size()] = NULL;

    if ( strcmp( command, "exit" ) == 0 )
    {
      return 0;
    }
    else
    {
      pid_t kidpid = fork();
      if ( kidpid < 0 )
      {
        perror( "Internal error: cannot fork." );
        return -1;
      }
      else if ( kidpid == 0 )
      {
        // I am the child.
        execvp( prog, argv );
        // The following lines should not happen (normally).
        perror( command );
        return -1;
      }
      else
      {
        // I am the parent.  Wait for the child.
        if ( waitpid( kidpid, 0, 0 ) < 0 )
        {
          perror( "Internal error: cannot wait for child." );
          return -1;
        }
      }
    }
  }

  return 0;
}
 
Old 12-15-2009, 01:36 AM   #2
smeezekitty
Senior Member
 
Registered: Sep 2009
Location: Washington U.S.
Distribution: M$ Windows / Debian / Ubuntu / DSL / many others
Posts: 2,234

Rep: Reputation: 184Reputation: 184
http://www.cs.cf.ac.uk/Dave/C/node20.html
 
1 members found this post helpful.
Old 12-15-2009, 11:35 AM   #3
Tblade
LQ Newbie
 
Registered: Dec 2009
Posts: 5

Original Poster
Rep: Reputation: 0
I would really like help here

If any one can help me please help. This is a bit over my head for all the stuff I need to do for it. Please help.
 
Old 12-15-2009, 11:52 AM   #4
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,125

Rep: Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119
Quote:
Originally Posted by Tblade View Post
This is a bit over my head for all the stuff I need to do for it. Please help.
Do you understand even the basic concepts in the code that you posted at the start of this thread? (Or did you copy it from somewhere with zero understanding of it?)

Did you click on the link Smeezekitty provided and read the example of the chdir() function there?

It is hard to imagine how anyone would be unable to adapt from that example into the code you posted, unless they don't understand any of the code you posted.

If you need more specific help, ask a more specific question.

Otherwise I think the link Smeezekitty provided is the only help that could be provided short of actually doing your homework for you, which is not appropriate here.

Last edited by johnsfine; 12-15-2009 at 11:55 AM.
 
Old 12-15-2009, 12:19 PM   #5
Tblade
LQ Newbie
 
Registered: Dec 2009
Posts: 5

Original Poster
Rep: Reputation: 0
What I am having trouble with is setting up the chdir() child more or less when I have tried implementing chdir() my shell stops running completely. (almost as if in an infinite loop). Also the concept of how to go 'up' in a directory setting by using .. is not making any sense I know to use the compare string but how to determine the directory im trying to get into is not making any sense.

Do i need to make the chdir() run in the background? I think I might be able to get that done. I'm new to C++ and linux completely this is my second programming based class ever and I'm quite confused.
 
Old 12-15-2009, 01:16 PM   #6
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,125

Rep: Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119
Quote:
Originally Posted by Tblade View Post
What I am having trouble with is setting up the chdir() child
Because chdir should not be a child!

It should be a function call within the shell itself. You don't want to fork at all for processing a chdir command.

Quote:
Also the concept of how to go 'up' in a directory setting by using .. is not making any sense
I'm not 100% sure. I think the chdir() function takes care of that for you. It should be pretty easy to test whether it does so. If it doesn't, then your code would need to do a little extra work, but even that shouldn't be very hard.

Quote:
I'm new to C++ and linux completely this is my second programming based class ever and I'm quite confused.
You asked a much better question this time. That got you a better answer. I hope you understand this answer.
 
1 members found this post helpful.
Old 12-15-2009, 01:39 PM   #7
smeezekitty
Senior Member
 
Registered: Sep 2009
Location: Washington U.S.
Distribution: M$ Windows / Debian / Ubuntu / DSL / many others
Posts: 2,234

Rep: Reputation: 184Reputation: 184
Quote:
I'm not 100% sure. I think the chdir() function takes care of that for you.
I thought so too, but it does not seem to. But its not that hard to implement with getcwd() and chdir() combo.
 
Old 12-15-2009, 11:40 PM   #8
TheIndependentAquarius
Senior Member
 
Registered: Dec 2008
Posts: 4,623
Blog Entries: 29

Rep: Reputation: 897Reputation: 897Reputation: 897Reputation: 897Reputation: 897Reputation: 897Reputation: 897
I have modified a part of this program. The modified part has been shown in RED.

Now test the program and tell me the results !!

Code:
#include <unistd.h>     // getpid(), getcwd()
#include <sys/types.h>  // type definitions, e.g., pid_t
#include <sys/wait.h>   // wait()
#include <signal.h>     // signal name constants and kill()
#include <iostream>
#include <vector>
#include <string>
using namespace std;


int main()
{
  while ( true )
    {
      // Show prompt.
      cout << get_current_dir_name () << "$ " ;
      char command[128];
      cin.getline( command, 128 );
      
      vector<char*> args;
      char* prog = strtok( command, " " );
      char* tmp = prog;
      while ( tmp != NULL )
	{
	  args.push_back( tmp );
	  tmp = strtok( NULL, " " );
	}
      
      char** argv = new char*[args.size()+1];
      for ( int k = 0; k < args.size(); k++ )
	argv[k] = args[k];
      
      argv[args.size()] = NULL;
      
      if ( strcmp( command, "exit" ) == 0 )
	{
	  return 0;
	}
      else
	{
	  if (!strcmp (prog, "cd"))
	    {
	      if (argv[1] == NULL)
		{
		  chdir ("/");
		}
	      else
		{
		  chdir (argv[1]);
		}
	      perror (command);
	    }
	  else
	    {
	      pid_t kidpid = fork();

	      if (kidpid < 0)
		{
		  perror( "Internal error: cannot fork." );
		  return -1;
		}
	      else if (kidpid == 0)
		{
		  // I am the child.
		  execvp (prog, argv);
		  
		  // The following lines should not happen (normally).
		  perror( command );
		  return -1;
		}
	      else
		{
		  // I am the parent.  Wait for the child.
		  if ( waitpid( kidpid, 0, 0 ) < 0 )
		    {
		      perror( "Internal error: cannot wait for child." );
		      return -1;
		    }
		}
	    }
	}
    }
  
  return 0;
}

Last edited by TheIndependentAquarius; 12-15-2009 at 11:48 PM.
 
Old 12-16-2009, 02:26 AM   #9
Tblade
LQ Newbie
 
Registered: Dec 2009
Posts: 5

Original Poster
Rep: Reputation: 0
Thanks so much

Quote:
Originally Posted by anishakaul View Post
I have modified a part of this program. The modified part has been shown in RED.
This worked great! Thanks so much. You solved the biggest question I had. Which was if I should nest it in the existing if statement or if I should put it before the existing one. This was a huge help and will make the rest of this project go smoothly.

I will ask though any pointers on how to use "&" to make a program run in the background. I know this will have to be forked and all. But my biggest problem is getting my shell to not recognize the & as a command line argument and as part of the string. I also think I might need to skip the getpid in the program, so the parent doesn't stay waiting.

Please let me know if I'm making any sense, or if you have any ideas on how to get it to use the & right.
 
1 members found this post helpful.
Old 12-16-2009, 03:22 AM   #10
TheIndependentAquarius
Senior Member
 
Registered: Dec 2008
Posts: 4,623
Blog Entries: 29

Rep: Reputation: 897Reputation: 897Reputation: 897Reputation: 897Reputation: 897Reputation: 897Reputation: 897
Quote:
Originally Posted by Tblade
This worked great! Thanks so much. You solved the biggest question I had. Which was if I should nest it in the existing if statement or if I should put it before the existing one. This was a huge help and will make the rest of this project go smoothly.

I will ask though any pointers on how to use "&" to make a program run in the background. I know this will have to be forked and all.
I am glad, it helped u !

By the way, did u understand why and what happened in the code, so that it started running ?

Quote:
Originally Posted by Tblade
But my biggest problem is getting my shell to not recognize the & as a command line argument and as part of the string.
Actually i do not know much about '&' , let me start a thread for knowing about '&' , how does it work !!

Last edited by TheIndependentAquarius; 12-16-2009 at 05:15 AM.
 
Old 12-16-2009, 03:52 AM   #11
Tblade
LQ Newbie
 
Registered: Dec 2009
Posts: 5

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by anishakaul View Post
I am glad, it helped u !

By the way, did u understand why and what happened in the code, so that it started running ?
Yea I understand exactly whats happening now. I set up a bunch of print statements as per to trouble shoot and I got the gist of what was really going on. It makes a lot more sense for me now.
 
Old 12-16-2009, 05:14 AM   #12
TheIndependentAquarius
Senior Member
 
Registered: Dec 2008
Posts: 4,623
Blog Entries: 29

Rep: Reputation: 897Reputation: 897Reputation: 897Reputation: 897Reputation: 897Reputation: 897Reputation: 897
Quote:
Originally Posted by Tblade
Yea I understand exactly whats happening now. I set up a bunch of print statements as per to trouble shoot and I got the gist of what was really going on. It makes a lot more sense for me now.
If this thread has solved your basic problems may be u should label it [SOLVED].
 
Old 12-16-2009, 09:04 AM   #13
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,125

Rep: Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119
Quote:
Originally Posted by anishakaul View Post
I have modified a part of this program. The modified part has been shown in RED.
Please don't do homework for those who request it.

There is an important difference between help, which is OK and do, which is not.

Also, you made some mistakes.
 
0 members found this post helpful.
Old 12-16-2009, 09:17 AM   #14
johnsfine
Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,125

Rep: Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119Reputation: 1119
Quote:
Originally Posted by Tblade View Post
how to use "&" to make a program run in the background.
http://www.linuxquestions.org/questi...79#post3793379
As smeezekitty and wje_lq explained (in the other thread anishakaul helpfully started for you), you implement the & behavior by not doing the waitpid() that the parent currently does in your code.

(It needs to be conditional, because if you don't have the &, you still need the waitpid())

Quote:
But my biggest problem is getting my shell to not recognize the & as a command line argument and as part of the string.
That should be easy at any one of several points in the existing code you have to parse the command.

1) You start with a command in a char array.
2) You tokenize it into a std::vector of char*
3) You copy that to an array of char*

The easiest point (by a very slight margin) to handle the & would be after step 2, before step 3. If the last arg at that point is "&" then flag that fact (for later suppression of the waitpid) and reduce the arg count by 1.

Last edited by johnsfine; 12-16-2009 at 09:20 AM.
 
  


Reply

Tags
bash, c++, help, linux, plus, programming, shell


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Shell Script for making directories from a file name vikki Linux - Server 7 06-24-2009 08:18 AM
Making a Shell Script better seefor Programming 7 03-04-2009 10:22 AM
Making mv -i the default when calling mv in the shell? rylan76 Linux - Desktop 1 01-26-2007 08:27 AM
Making my own shell in C? diam0nd Linux - General 2 06-06-2004 05:53 AM
making background a shell lippy Linux - General 3 04-02-2003 09:11 PM


All times are GMT -5. The time now is 10:13 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration