tags:

views:

119

answers:

5

I am trying to create a simple shell in Unix. I read a lot and found that everybody uses the strtok function a lot. But I want to do it without any special functions. So I wrote the code but I can't seem to get it to work. What am I doing wrong here?

void process(char**);
int arg_count;
char **splitcommand(char* input)
{
    char temp[81][81] ,*cmdptr[40];
    int k,done=0,no=0,arg_count=0;
    for(int i=0 ; input[i] != '\0' ; i++)
    {
        k=0;
        while(1)
        {
            if(input[i] == ' ')
            {
                arg_count++;
                break;
            }
            if(input[i] == '\0')
            {
                arg_count++;
                done = 1;
                break;
            }
            temp[arg_count][k++] = input[i++];
        }
        temp[arg_count][k++] = '\0';
        if(done == 1)
        {
            break;
        }
    }
    for(int i=0 ; i<arg_count ; i++)
    {
        cmdptr[i] = temp[i];
        cout<<endl;
    }
    cout<<endl;
}


void process(char* cmd[])
{
    int pid = fork();
    if (pid < 0)
    {
        cout << "Fork Failed" << endl;
        exit(-1);
    }
    else if (pid == 0)
    {
        cout<<endl<<"in pid";
        execvp(cmd[0], cmd);
    }
    else
    {
        wait(NULL);
        cout << "Job's Done" << endl;
    }
}


int main()
{
    cout<<"Welcome to shell !!!!!!!!!!!"<<endl;
    char input[81];
    cin.getline(input,81);
    splitcommand(input);
}
+1  A: 

strtok isn't really a special function as it's standard function in standard include string.h, so there is no good reason not to use it.

Axarydax
Thank you sir, for the reply. But i just want to work with this code. Can you help me?
yuneek
+1  A: 

If you decide to make your shell more complicated then you may reason about using a tool for lexical analysis.

For example:

http://en.wikipedia.org/wiki/Flex_lexical_analyser

MartyIX
No sir, I just want to make this work. I cant understand the problem with this code. can u help?
yuneek
+2  A: 

Several things:

  • you don't return anything from the splitcommand function
  • everything you do in the splitcommand function is done in local variables, so it (esp. the strings you make) will not survive its end
  • the code that attaches the null terminator is wrong (you put it to the following string, not the current one)
  • using fixed-size buffer is a great choice; people love it
  • note that in real UNIX shells, not every space designates an argument, and not every argument is designated by spaces

I'd suggest you use strings and some (real) parser framework, provided it is not too special for you.

jpalecek
Thank you sir, :). But i dont have to return anything in the splitcommand(). Do I? All i do is call process from the splitcommand by passing the cmdptr. and how is the NULL a problem? it is the same string itself rt?arg_count is not changing there? Only k is?I worked with it and i got the command separated. that is if i give ls -l, i will get cmdptr[0] = ls and cmdptr[1] = -l. But my execvp is not working. arent the arguments passed to the exec correct?
yuneek
A: 

The problem is with the

arg_count++;  

inside the if(input[i] == ' ') and if(input[i] == '\0')

when you are parsing the command line and you find a space or you reach the end of the command line you are increment arg_count before you put a \0 at the end of the command you were reading.

So change it to:

        if(input[i] == ' ')  
        {  
            // arg_count++;  REMOVE THIS.
            break;  
        }  
        if(input[i] == '\0')  
        {  
            // arg_count++;  REMOVE THIS.
            done = 1;  
            break;  
        }  
        temp[arg_count][k++] = input[i++];  
    }  
    temp[arg_count][k++] = '\0'; // add null-char at the end. 
    arg_count++; // increment should happen here.

More bugs:

  • You are not returning anything from splitcommand
  • You cannot just return cmdptr because they point to local char arrays(temp) which will not persist after the function returns. So you'll have to make sure that the array temp persists even after function call by allocating it dynamically or making it global.
  • Arguments to execvp look good to me. Others please take a look.
codaddict
Thank you sir, That was a big mistake. But the problem still persists. Actually is my arguments passed to exec correct?I mean when i print the cmd[0] and cmd[1] . When i give the command ls -l, i get cmd[0] =ls and cmd[1]= -l. And the code works just before the exec function. But the exec doesnt work. What might be the problem,? thanks in advance
yuneek
Thank you very much sir. The program worked : Thank you very very much :)
yuneek
+2  A: 

This is almost certainly homework. There is no reason to avoid library functions unless you were told to. In fact, most likely you were told to implement strtok.

frankc