CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12

Threaded View

  1. #1
    Join Date
    Mar 2003
    Location
    Orange County, CA
    Posts
    99

    Exclamation URGENT: Initializing the size of a char*[]

    I am writing a program that acts as a simple shell. Basically, my program outputs a prompt, then waits for the user to input a command. My program then handles that command and ouputs a new prompt. This process continues until the user quits. The specifics of the program are not relevant though. The only question I have is with the variable char *arg[] inside of my Info struct. I am not sure how to initialize it's size. I tried just saying char *arg[20], but that ended up giving it a size of 0 for some reason.
    Can anyone correct this problem in my code for me?
    Can anyone tell me how to initialize the size of a char*[]?
    I have the entire program below, or you can download the attachment of it.
    Thank You!

    Code:
    /*************************************************
     DESCRIPTION: This program will mimic a shell, displaying a prompt and
    		allowing the user to enter commands. If the commands 'cd' or
    		'exit' are input, the program will handle them. All other commands 
    		will be handled by a child process, which will be forked solely for 
    		the purpose of executing a command, then terminates. The shell will 
    		continue to display a prompt until the user inputs 'exit' or presses
    		CTRL-D.
    *************************************************/
    
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <wait.h>
    #include <cstring>
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    //Info - holds the information used to execute a user command
    struct Info {
    	char *path;	     //Path to the file
    	char *arg[];      //List of parsed user command
    };
    
    //PURPOSE: Displays a prompt and returns the user input
    //PRECONDITION: None
    //POSTCONDITION: The user input is returned
    void getPrompt(char command[], Info& data);
    
    //PURPOSE: Determines whether a command is intrinsic or not
    //PRECONDITION: None
    //POSTCONDITION: True is returned if command is intrinsic, False otherwise
    int checkIntrinsic(char command[]);
    
    //PURPOSE: Peforms the two intrinisc commands 'cd' and 'exit'
    //PRECONDITION: User inputs the 'cd' or 'exit' command
    //POSTCONDITION: The appropriate task is performed
    void performIntrinsic(char command[]);
    
    //PURPOSE: Sets the path when 'cd' is performed
    //PRECONDITION: User inputs the 'cd' command
    //POSTCONDITION: If a path is specified, it is set to that; 
    //	otherwise, the path is HOME
    void setPath(char command[], char path[]);
    
    //PURPOSE: Parses the user command to be used with exec()
    //PRECONDITION: None
    //POSTCONDITION: The command is parsed and placed in *arg[]
    void parseCmd(char command[], char *args[]);
    
    // **************************************************
    
    
    int main (int argc, char **argv, char **envp) {
    
    	//cmd - holds the command that is input by the user
    	char cmd[200] = "";
    	//status - holds the return status of the forked child
    	int status;
    	//chpid - holds the process ID of the child
    	//ret - holds the status of the wait
    	pid_t chpid, ret;
    	//pInfo - holds the information to be executed in the
    	// child process
    	Info pInfo;
    
    	//Prompt for user input
    	getPrompt(cmd, pInfo);
    
    	//Process the input
    	while (strlen(cmd) != 0 && !cin.eof()) {
    		//If the command is intrinsic, do not fork
    		if (checkIntrinsic(cmd) != 0)
    			performIntrinsic(cmd);
    		//Else, fork a child process and execute the command
    		else {
    			if ((chpid = fork()) == 0) {
    				parseCmd(cmd, pInfo.arg);
    				execvp(pInfo.path, pInfo.arg);
    				//If an error occurs, report it
    				// and exit with a 1
    				perror("Error: command failed ");
    				exit(1);
    			}
    			//wait until the child process has terminated
    			ret = wait(&status);
    		}
    		//Prompt for user input
    		getPrompt(cmd, pInfo);
    	}
    	
    	cout << endl;
    	return 0;
    }
    
    // **************************************************
    
    
    void getPrompt(char command[], Info& data) {
    
    	//Display a prompt
    	cout << "[" << getenv("PWD") << "]$ ";
    
    	//Get the user input
    	cin.getline (command, 200);
    
    	//Remove any leading blank spaces
    	while (isspace(command[0])) {
    		//Move each character forward 1 so the leading
    		// space is overwritten.
    		for (int i = 0; i < strlen(command) - 1; i++)
    			command[i] = command[i + 1];
    
    		//Since the new array is now 1 character shorter,
    		// make the extra element NULL
    		command[strlen(command) - 1] = '\0';
    	}
    	
    	//Load the data structure's path
    	data.path = getenv("PWD");
    }
    
    // **************************************************
    
    
    int checkIntrinsic(char command[]) {
    
    	//Convert the C-string to a string
    	string cmd = command;
    
    	//Check if the command is 'cd'
    	if (cmd.substr(0, 2) == "cd") 
    		return 1;
    	//Else, check if the command is 'exit'
    	else if (cmd.substr(0, 4) == "exit")
    		return 2;
    	//Else, the command is not intrinsic
    	else
    		return 0;
    }
    
    // **************************************************
    
    
    void performIntrinsic(char command[]) {
    
    	//path[] - holds the path used in 'cd'
    	char path[200] = "";
    
    	switch (checkIntrinsic(command)) {
    		//Perform 'cd' command
    		case 1:
    			//Set the path to 'cd' to
    			setPath(command, path);
    			//Now, 'cd' to the path if it exists
    			if (chdir(path) != 0)
    				cout << path << ": No such file or directory.\n";
    			break;
    			
    		//Perform 'exit' command
    		case 2:
    			exit(0);
    	}
    }
    
    // **************************************************
    
    
    void setPath(char command[], char path[]) {
    
    	//index - used to track the index of path[]
    	int index = 0;
    	//specified - flag for if a path is specified in the user command
    	bool specified = false;
    
    	//Check the rest of the command to see if
    	// a path was specified
    	for (int i = 2; command[i] != '\0'; i++) {
    		//If the character is not blank, assume that it is
    		// the part of the path
    		if (command[i] != ' ') {
    			specified = true;
    			path[index] = command[i];
    			index++;
    		}
    	}
    	
    	//If the path was not specified, set it to the HOME directory
    	if (!specified)
    		path = getenv("HOME");
    		
    }
    
    // **************************************************
    
    
    void parseCmd(char command[], char *args[]) {
    
    	//Convert the C-string to a string
    	string cmd = command;
    	//temp - holds the parsed substrings of cmd
    	string temp;
    	//index - used to track the index of *args[]
    	int index = 0;
    
    	//Skip any spaces at the beginning of the string
    	string::size_type lastPos = cmd.find_first_not_of(" ", 0);
    	//Find the first non-space in the string
    	string::size_type pos = cmd.find_first_of(" ", lastPos);
    	
    	while (string::npos != pos || string::npos != lastPos) {
    
    		//Found a token, so place it into the parse array
    		temp = cmd.substr(lastPos, pos - lastPos);
    		strcpy(args[index], temp.data());
    
    		//TEST LINE==============================
    		cout << "args[" << index << "]: " << args[index] << endl;
    		//=====================================
    
    		index++;
    		
    		//Skip the spaces
    		lastPos = cmd.find_first_not_of(" ", pos);
    		//Find the next non-space
    		pos = cmd.find_first_of(" ", lastPos);
    	}
    
    	//TEST LINE==============================
    	cout << "Made it out!\n";
    	cout << "Index is at " << index << endl;
    	cout << "Size of args[] is " << strlen(*args) << endl;
    	//=====================================
    
    	//Add the NULL terminator
    	strcpy(args[index], '\0');
    
    	//TEST LINE==============================
    	cout << "Added NULL!\n";
    	//=====================================
    }
    Attached Files Attached Files

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured