#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cstdlib>
#include <cerrno>
#include <exception>
#include <unistd.h>

using std::string;

void 
split_string(const std::string s, 
             const std::string sep, 
             std::vector<std::string> &components)
{
    typedef std::pair<size_t, size_t> Range;
    size_t pos, old_pos;
    Range trange;
    std::vector<Range> ranges;
    trange.first = 0;
    trange.second = s.find(sep, trange.first);
    if (trange.second == string::npos){
        trange.second = s.length();
    }        
    ranges.push_back(trange);
    while(trange.second < s.length()){
        trange.first = trange.second + 1;
        trange.second = s.find(sep, trange.first);
        if (trange.second == string::npos){
            trange.second = s.length();
        }
        ranges.push_back(trange);
    }
    
    for (int i = 0; i < ranges.size() ; ++i){
       components.push_back(s.substr(ranges[i].first, 
                ranges[i].second - ranges[i].first) );
    }
}

class InvalidCommandLine : public std::exception {

};

class Command {
    private:
        char *name;
        char **arguments;
        size_t arg_num;
        bool has_run;
        unsigned int pid;
        int ret_status;
    public:
        Command(const std::string& line)
            : has_run(false) { parse_line(line); };
        ~Command();
        
        unsigned int sync_run();
    private:
        void parse_line(const std::string&);
};

Command::~Command(){
    delete [] name;
}

void Command::parse_line(const std::string& s){
    std::vector<std::string> args;
    split_string(s, " ", args);
    if (args.size() >0 ){
        name =  new char[args[0].size()];
        std::copy(args[0].begin(), args[0].end(), name);
        arg_num = args.size();
        arguments = new  char* [arg_num + 1];
        for(int i = 0; i < arg_num; ++i){
            arguments[i] = new char[args[i].size()];
            std::copy(args[i].begin(), 
                      args[i].end(),
                      arguments[i]);
        }
        arguments[arg_num] = 0;
    } else {
        throw InvalidCommandLine();
    }
}

unsigned int Command::sync_run(){
    pid = fork();
    if (pid){
        printf("Waiting for child (%d)\n", pid);
        pid = wait(&ret_status);
        printf("Child (%d) finished\n", pid);
    } else {
            if( execvp(args[0], args)) {
                puts(strerror(errno));
                exit(127);
            }    }
    return ret_status;
}

int main(){
    while(1){
        std::cout << "$ ";
        std::string line;
        std::getline(std::cin, line);
        Command c(line);
        c.sync_run();
    }
    return 0;
}
