I'm running some code on Mac OSX 10.6.6 and XCode 3.2.4 and I have some pretty standard code: fork(), if pid == 0 then execvp with a command and the args (the args include the command as the first element in the array, and the array is null terminated).
We're going over this in my Operating Systems class and our assignment is to write a simple shell. Run commands with their args and switches, both redirects (< and >) and pipe (|). I'm getting several problems.
1) Sometimes I get the EXC_SOFTWARE signal while debugging (so far I haven't gotten it if I run the app outside of XCode, but I'm new to Mac and wouldn't know what that would look like if I did)
2) Sometimes the getline for the next command gets junk that seems to be printed by other couts. This begins looping forever, exponentially breaking. I have tested with printing getpid() with every prompt and only the beginning process prints these out, I don't appear to have an accidental "fork bomb."
Here's what I have so far:
#include <iostream>
#include <string>
#include <unistd.h>
using namespace std;
char** Split(char* buffer, int &count) {
count = 1;
for (int i = 0; i < strlen(buffer); i++) {
if (buffer[i] == ' ') {
count++;
}
}
const char* delim = " ";
char* t = strtok(buffer, delim);
char** args = new char*[count + 1];
for (int i = 0; i < count; i++) {
args[i] = t;
t = strtok(NULL, delim);
}
args[count] = 0;
return args;
}
void Run(char** argv, int argc) {
int pid = 0;
if ((pid = fork()) == 0) {
//for testing purposes, print all of argv
for (int i = 0; i < argc; i++) {
cout << "{" << argv[i] << "}" << endl;
}
execvp(argv[0], argv);
cout << "ERROR 1" << endl;
exit(1);
} else if (pid < 0) {
cout << "ERROR 2" << endl;
exit(2);
}
wait(NULL);
}
int main(int argc, char * const argv[]) {
char buffer[512];
char prompt[] = ":> ";
int count = 0;
while (true) {
cout << prompt;
cin.getline(buffer, 512);
char **split = Split(buffer, count);
Run(split, count);
}
}
It's exactly what I have, you should be able to cut, paste, and build.
I'm not the best at C++, and chances are there's a memory leak when I don't delete split
but my main focus is the EXC_SOFTWARE signal and see what I'm doing wrong with my looping issue. Any thoughts?
EDIT:
The assignment requires very limited error checking and I'm assuming all input is correct. By correct I mean properly formatted and limited for my app to run the command, i.e. no bizarre space count, no & to run async, no multi piping commands, etc.