C Board  

Go Back   C Board > General Programming Boards > C++ Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 11-01-2003, 10:53 AM   #1
Registered User
 
Join Date: Oct 2003
Posts: 9
getting input from keyboard, passing to execvp

Hi, I'm trying to create a simple shell program that reads in a command from the keyboard and passes it to execvp to execute. I'm working in a Linux environment. I'm splitting the input line into a command (the first token) and arguments (the remaining tokens). For example, ls -l has ls as command and -l as the sole argument. The problem is that execvp does not recognize the first argument. If I input "ls -l", it executes just "ls" and drops the "-l." If I input "ls -l -a", then it executes "ls -a." If I input "ls," it doesn't execute anything. Any thoughts? Thanks! Here is my code:

Code:
#include <unistd.h>
#include <iostream>
#include </usr/include/errno.h>
#include </usr/include/sys/errno.h>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
        // issue prompt
        cout << "> ";

        // get input from user
        string inputStr;
        char inputStrArr[128];
        char * argArr[128];
        char separators[]   = " ,\t\n";
        char *token, *command;
        int numArgs = -1;
        int k;
        int i;

        getline(cin, inputStr);
        for(i=0; i<inputStr.length(); i++)
                inputStrArr[i] = inputStr[i];
	inputStrArr[i] = '\0';
	token = strtok(inputStrArr, separators);
	command = token;

        while( token != NULL )
        {
                token = strtok( NULL, separators );

                argArr[++numArgs] = token;
        }

        argArr[++numArgs] = '\0';
 
        // fork
        int childpid, flag;

        if ((childpid = fork()) == 0) // child code
        {
                cout << "Process ID: child: " << getpid();
                flag = execvp(command, argArr);

                if (flag < 0)
                {
                        perror("execvp failed");
                }
        }
        else if (childpid > 0) // parent code
    {
        cout << "Process ID: " << getpid();
    }
    else // fork unsuccessful
    {
        cout << "\nError: fork failed\n";
    }

return 0;
}
jumpyg is offline   Reply With Quote
Old 11-01-2003, 11:00 AM   #2
and the hat of vanishing
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,214
> command = token;
Follow with

argArr[++numArgs] = token;

argv[0] is the name of the program, not the first parameter

> argArr[++numArgs] = '\0';
This is a pointer, not a character, so
argArr[++numArgs] = NULL;
is more usual
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
Up to 8Mb PlusNet broadband from only £5.99 a month!
Salem is offline   Reply With Quote
Old 11-02-2003, 01:32 PM   #3
Registered User
 
Join Date: Oct 2003
Posts: 9
Thanks Salem, I missed that one!

Now I have another question about comparing the value in a char pointer.
I need to see if the last token on the line is "&" -- which indicates a background process. If so, it needs to be excluded from the argument array and a bool flag set. The problem is I don't know how to compare the value in this last token with "&". Here is my code:
Code:
#include <unistd.h>
#include <iostream>
#include </usr/include/errno.h>
#include </usr/include/sys/errno.h>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
        cout << "program has started\n";

        // issue prompt
        cout << "> ";

        // get input from user
        bool background = false;
        string inputStr;
        string commandStr;
        char inputStrArr[128];
        char * argArr[128];
        char separators[]   = " ,\t\n";
        char *token, *command;
        int numArgs = -1;
        int k;
        int i;

        getline(cin, inputStr);
        while (inputStr.length() == 0)
        {
                cout << "> ";
                getline(cin, inputStr);
        }

        for(i=0; i<inputStr.length(); i++)
                inputStrArr[i] = inputStr[i];
        inputStrArr[i] = '\0';
                                                                   
	token = strtok( inputStrArr, separators );
        command = token;

        for (i=0; token[i] != '\0'; i++)
        {
                commandStr += token[i];

        }

        argArr[++numArgs] = token;

        while( token != NULL )
        {
                token = strtok( NULL, separators );
                argArr[++numArgs] = token;
        }

        if (argArr[numArgs] == '&')
        {
                background = true;
                argArr[numArgs] = NULL;
        }
        else
                argArr[++numArgs] = NULL;

    // is command built-in?
        if(commandStr == "quit")
        {
                cout << "============= quit called\n";
                return 0;
        }
        else
        {
	    // execute external command
	        int childpid, flag;
	        childpid = fork();
	        cout << "forking\n";
	        if (childpid == 0) // child code
	        {
	                cout << "Process ID: child: " << getpid();
	                flag = execvp(command, argArr);
	
	                if (flag < 0)
	                {
	                        perror("execvp failed");
	                }
	        }
	        else if (childpid > 0) // parent code
	        {
	                cout << "Process ID: " << getpid();
	        }
	        else // fork unsuccessful
	        {
	                cout << "\nError: fork failed\n";
	        }
	} // end else
return 0;
}
jumpyg is offline   Reply With Quote
Old 11-02-2003, 01:38 PM   #4
and the hat of vanishing
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,214
> if (argArr[numArgs] == '&')
Try
if (argArr[numArgs][0] == '&')

> #include </usr/include/errno.h>
> #include </usr/include/sys/errno.h>
1. You shouldn't specify the paths
2. you should only need errno.h
3. perhaps it should be called
#include <cerrno>
if you're following current C++ conventions for including standard C header files
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
Up to 8Mb PlusNet broadband from only £5.99 a month!
Salem is offline   Reply With Quote
Old 11-02-2003, 08:49 PM   #5
Registered User
 
Join Date: Oct 2003
Posts: 9
Thanks again. I've got my shell working well at this point. However, I would like to create a class and split the main pieces of code into functions. The problem I have is with the get_command function. It takes the command from the user and does everything as before. The client then should be able to access the command and arguments. However, I must not be passing the argments to get_command properly, because I'm getting a segmentation error when the client tries to access "command" and "args." Here is the function delaration:
void get_command(char* command, char* args[]);
and the client code:
Code:
        char * argArr[128];
        char * command;
        shell1.get_command(command, argArr);
I tried passing the arguments as pointer references:
void get_command(char*& command, char*& args[]);
but no luck there, either. Then the program won't even compile. Any ideas? Thanks!
jumpyg is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
How do I input an unbuffered character via the keyboard??? Michael_in_Ohio C Programming 1 03-23-2008 12:00 PM
Need some help with C program writing The_PC_Gamer C Programming 9 02-12-2008 09:12 PM
User Input - Keyboard Scarvenger Windows Programming 2 08-02-2006 07:56 PM
Intercepting keyboard input EvBladeRunnervE Windows Programming 3 01-08-2004 09:03 AM
Keyboard input without waiting (Borland C++) adamdalziel Game Programming 6 09-24-2001 04:20 PM


All times are GMT -6. The time now is 07:25 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22