/*
 * Copyright (c) 2006-2007 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include <netinet/in.h>
#include <sys/ptrace.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <netdb.h>
#include <unistd.h>

#include <cerrno>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>

#include "base/arch_check.h"
#include "tracechild.hh"

using namespace std;

void
printUsage(const char * execName)
{
    cout << execName << " <options> -- <command> <arguments>" << endl;
    cout << "options:" << endl;
    cout << "         -h          print this help" << endl;
    cout << "         --host      remote m5 host to connect to" << endl;
    cout << "         -i          print initial stack state" << endl;
    cout << "         -nt         don't trace execution" << endl;
}

int
main(int argc, char * argv[], char * envp[])
{
    TraceChild * child = genTraceChild();
    string args;
    int startProgramArgs;

    //Parse the command line arguments
    bool printInitial = false;
    bool printTrace = true;
    string host = "localhost";

    if (argc == 1) {
        printUsage(argv[0]);
        return 0;
    }
    for (int x = 1; x < argc; x++) {
        if (!strcmp(argv[x], "-h")) {
            printUsage(argv[0]);
            return 0;
        }
        if (!strcmp(argv[x], "--host")) {
            x++;
            if (x >= argc) {
                cerr << "Incorrect usage.\n" << endl;
                printUsage(argv[0]);
                return 1;
            }
            host = argv[x];
        } else if (!strcmp(argv[x], "-i")) {
            printInitial = true;
        } else if (!strcmp(argv[x], "-nt")) {
            printTrace = false;
        } else if (!strcmp(argv[x], "--")) {
            x++;
            if (x >= argc) {
                cerr << "Incorrect usage.\n" << endl;
                printUsage(argv[0]);
                return 1;
            }
            startProgramArgs = x;
            break;
        } else {
            cerr << "Incorrect usage.\n" << endl;
            printUsage(argv[0]);
            return 1;
        }
    }
    if (!child->startTracing(argv[startProgramArgs],
                argv + startProgramArgs)) {
        cerr << "Couldn't start target program" << endl;
        return 1;
    }
    child->step();
    if (printInitial)
        child->outputStartState(cout);
    if (printTrace) {
        // Connect to m5
        bool portSet = false;
        int port;
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0) {
            cerr << "Error opening socket! " << strerror(errno) << endl;
            return 1;
        }
        struct hostent *server;
        server = gethostbyname(host.c_str());
        if (!server) {
            cerr << "Couldn't get host ip! " << strerror(errno) << endl;
            return 1;
        }
        struct sockaddr_in serv_addr;
        bzero((char *)&serv_addr, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        bcopy((char *)server->h_addr,
                (char *)&serv_addr.sin_addr.s_addr,
                server->h_length);
        serv_addr.sin_port = htons(8000);
        if (connect(sock, (sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
            cerr << "Couldn't connect to server! " << strerror(errno) << endl;
            return 1;
        }
        while (child->isTracing()) {
            if (!child->sendState(sock))
                break;
            child->step();
        }
    }
    if (!child->stopTracing()) {
        cerr << "Couldn't stop child" << endl;
        return 1;
    }
    return 0;
}

