| | |
Making a UNIX Shell, so inexperienced at it
Please support our C++ advertiser: Intel Parallel Studio Home
![]() |
So I have to make a UNIX shell that can basically take in any UNIX command and then keep a record of the time each process took, by forking off children processes, recording their time, and recording the parent's time, and then return that time into a linked list or vector so that i can print out all processes and their times when someone wants to see them.
Now the problem I am having is that I have no idea how a regular shell parses out bad input. Say for instance you type "pig" into the command line of your standar tcsh. It will say "pig": Bad command name or something to that effect. I want mine to do that but right now it is just accepting "pig" and calling it another running instance of my current shell. I know i have to do some sort of search for $PATH but no one has ever told me what functions do that kind of search, or even how to search that kind of thing so that I can error check. I pasted my code in here in hopes that perhaps someone can show me where and what the hell to do with making sure bad input stays bad input and doesn't get logged as a process.
If anyone could help me I would greatly appreciate it. In the meantime I'll keep hittin away at it and try to get it right.
Now the problem I am having is that I have no idea how a regular shell parses out bad input. Say for instance you type "pig" into the command line of your standar tcsh. It will say "pig": Bad command name or something to that effect. I want mine to do that but right now it is just accepting "pig" and calling it another running instance of my current shell. I know i have to do some sort of search for $PATH but no one has ever told me what functions do that kind of search, or even how to search that kind of thing so that I can error check. I pasted my code in here in hopes that perhaps someone can show me where and what the hell to do with making sure bad input stays bad input and doesn't get logged as a process.
C++ Syntax (Toggle Plain Text)
/* * Program: This is a shell that reports stats of running times of processes initiated in * the shell as well as the shell itself's process time */ #include <sys/types.h> #include <sys/wait.h> #include <sys/times.h> #include <sys/stat.h> #include <sys/ipc.h> #include <sys/msg.h> #include <sys/socket.h> #include <signal.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <string> #include <iostream> #include <iomanip> #include <cstdlib> using namespace std; /** * method displayID * returns: nothing * parameters: none * Description: This method displays the author information */ void displayID() { } /** * method displayInfo * returns: nothing * parameters: none * Description: This method displays the Game info */ void displayInfo() { cout << "The function of the shell is to operate child processes" << endl; cout << "And return statistics of process time of each process" << endl; cout << "That has been running in the shell as well as the shell's" << endl; cout << "process time" << endl; } /** * method takeInpt * returns: nothing * parameters: none * Description: This method takes the input for the shell */ void takeInpt(char* cmnd, char* cmd[], char inpt[]) { //ask for and get the input cout << "statsh$: "; cin.getline(inpt,81); cmnd = strtok(inpt, " "); int c = 0; while(cmnd != NULL) { cmd[c] = cmnd; c++; cmnd = strtok(NULL, " "); } } /** * method runProc * returns: nothing * parameters: none * Description: This method runs exec and forking commands */ void runProc(char* cmd[]) { pid_t pid; // fork / /do i check for bad input here??!! pid = fork(); if(pid < 0) { cout << "Fork Failed" << endl; exit(-1); } else if( pid == 0) { execvp(cmd[0], cmd); } else { wait(NULL); cout << "Job's Done" << endl; } } int main() { char* cmnd; char* cmd[40]; char inpt[81]; displayID(); displayInfo(); while(1) { //clean out the array each time for(int m=0; m < 40; m++) { cmd[m] = NULL; } takeInpt(cmnd, cmd, inpt); if(cmd[0] == NULL) { cout << "Enter a command please" << endl; } else if(strcmp(cmd[0], "exit") == 0 ) { break; } else { runProc(cmd); } /* * testing print statement to see user input is taken and tokenized for(int i=0; i < 40; i++) { if(cmd[i]) { cout<< cmd[i] << endl; } } */ } return 1; }
If anyone could help me I would greatly appreciate it. In the meantime I'll keep hittin away at it and try to get it right.
You can use getenv to get the contents of a certain environment value (such as "PATH"). Use man getenv for details.
The reason it seems like it's running another instance of your current shell is because you've forked your shell into a new process. So the program's doing exactly what you've asked it to do. If execvp fails, it simply returns -1. (If it succeeds, it never returns!) Then your child process keeps running until it finds a reason to exit, and then the parent's wait( ) call comes through, and the parent continues.
If you want to handle this, simply include something to handle it after your execvp call. If the call fails, you can write, "Bad command or filename\n", or whatever you want, and then exit() that process. Then the parent's wait() returns, and the parent continues running.
The reason it seems like it's running another instance of your current shell is because you've forked your shell into a new process. So the program's doing exactly what you've asked it to do. If execvp fails, it simply returns -1. (If it succeeds, it never returns!) Then your child process keeps running until it finds a reason to exit, and then the parent's wait( ) call comes through, and the parent continues.
If you want to handle this, simply include something to handle it after your execvp call. If the call fails, you can write, "Bad command or filename\n", or whatever you want, and then exit() that process. Then the parent's wait() returns, and the parent continues running.
All my posts may be redistributed under the GNU Free Documentation License.
•
•
•
•
Originally Posted by Rashakil Fol
You can use getenv to get the contents of a certain environment value (such as "PATH"). Use man getenv for details.
The reason it seems like it's running another instance of your current shell is because you've forked your shell into a new process. So the program's doing exactly what you've asked it to do. If execvp fails, it simply returns -1. (If it succeeds, it never returns!) Then your child process keeps running until it finds a reason to exit, and then the parent's wait( ) call comes through, and the parent continues.
If you want to handle this, simply include something to handle it after your execvp call. If the call fails, you can write, "Bad command or filename\n", or whatever you want, and then exit() that process. Then the parent's wait() returns, and the parent continues running.
Thank you first of all for replying to my concern, but I'm afraid I still am not quite getting it. I did this to my procedure. Now it is saying that all of my input is bad input. Am I using getenv wrong? It should search the environment for that variable named there in and return NULL if it doesn't find it right? So says the man pages. So I'm trying to do taht, but it isn't doing it.
C++ Syntax (Toggle Plain Text)
void runProc(char* cmd[], int argSz) //argSz should be the max amount of args they entered counted in another method { tms strt, end; long s,e; pid_t pid; bool badEx = false; for(int i=0; i < argSz; i++) { //cout << "What's wrong here" << endl; if(getenv(cmd[i]) == NULL) { cout << "The error occured at: " << i << endl; badEx = true; break; } } if(badEx == true) { cerr << "Bad Command or file name" << endl; } else { // fork times(&strt); pid = fork(); switch(pid) { case -1: cout << "Fork Failed" << endl; exit(-1); case 0: execvp(cmd[0], cmd); default: wait(NULL); times(&end); cout << "Process took: " << (end.tms_utime-strt.tms_utime)/100; cout << " seconds" << endl; cout << "Child has finished" << endl; } } //end else
And lastly, I don't get what you mean by putting a line after the execvp line. What would the line contain? An exit(0) statement? I'm a little confused about that.
You don't actually need getenv. If execvp fails, it returns. That's how you know it fails. But as a side note, you should be using getenv with Then pathstr contains the null memory address, or it contains the memory address of a string such as "/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games". That's the output of this miniprogram:
If execvp returns, you still have two processes running. The parent is wait()ing for the child process to terminate. What do you want your child process to do?
C++ Syntax (Toggle Plain Text)
char * pathstr = getenv("PATH");
C++ Syntax (Toggle Plain Text)
#include <stdlib.h> #include <stdio.h> int main(void) { char * s = getenv("PATH"); if (s) { printf("%s\n", s); } return 0; }
•
•
•
•
And lastly, I don't get what you mean by putting a line after the execvp line. What would the line contain? An exit(0) statement? I'm a little confused about that.
All my posts may be redistributed under the GNU Free Documentation License.
•
•
•
•
Originally Posted by Rashakil Fol
You don't actually need getenv. If execvp fails, it returns. That's how you know it fails. But as a side note, you should be using getenv withThen pathstr contains the null memory address, or it contains the memory address of a string such as "/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games". That's the output of this miniprogram:C++ Syntax (Toggle Plain Text)
char * pathstr = getenv("PATH");
C++ Syntax (Toggle Plain Text)
#include <stdlib.h> #include <stdio.h> int main(void) { char * s = getenv("PATH"); if (s) { printf("%s\n", s); } return 0; }
Let me know if I that is wrong. I think it seems to be working right now, but I need to remember that it must work for later commands when I add piping and duping crap...whcih as of yet I don't konw how to do.
Thanks again for the help btw. Good show!
If execvp returns, you still have two processes running. The parent is wait()ing for the child process to terminate. What do you want your child process to do?
Hmm, did you mean something like the following. Since execvp returns -1 when it fails, then this should work for exiting the process that isn't a real process right?
C++ Syntax (Toggle Plain Text)
// fork times(&strt); pid = fork(); switch(pid) { case -1: cout << "Fork Failed" << endl; exit(-1); case 0: execvp(cmd[0], cmd); if(execvp(cmd[0], cmd) == -1) { cout << "Command Not Found" << endl; exit(0); } default: wait(NULL); times(&end); cout << "Process took: " << (end.tms_utime-strt.tms_utime)/100; cout << " seconds" << endl; cout << "Child has finished" << endl; }
That looks like an appropriate change, though you don't need to check for execvp returning -1. If it returns, we already know something failed. It returns -1 from historic practice, but the return value has never been standardized. (Or so says the man page on my machine.)
All my posts may be redistributed under the GNU Free Documentation License.
•
•
•
•
Originally Posted by Rashakil Fol
That looks like an appropriate change, though you don't need to check for execvp returning -1. If it returns, we already know something failed. It returns -1 from historic practice, but the return value has never been standardized. (Or so says the man page on my machine.)
![]() |
Similar Threads
- Implementing a unix shell running commands (Java)
- i want help about the Simulate a Linux/UNIX shell, called MASH in the C (C)
- Bourne / Bash Unix/Linux shell scripting tutorial (Shell Scripting)
Other Threads in the C++ Forum
- Previous Thread: MFC problems
- Next Thread: hi
| Thread Tools | Search this Thread |
api array based binary c++ c/c++ calculator char char* class classes code coding compile console conversion count database delete deploy desktop developer directshow dll download dynamic dynamiccharacterarray email encryption error file forms fstream function functions game givemetehcodez google graph gui homeworkhelp iamthwee ifstream input int integer java lib linkedlist linker linux list loop looping loops map math matrix memory multiple news number numbertoword output pointer problem program programming project python random read recursion recursive reference return rpg sorting string strings struct temperature template templates test text text-file tree unix url variable vector video visual visualstudio win32 windows winsock wordfrequency wxwidgets






