//
//  bootstrap.m
//  g0blin
//
//  Created by Sticktron on 2017-12-27.
//  Copyright © 2017 xerub. All rights reserved.
//  Copyright © 2017 qwertyoruiop. All rights reserved.
//

#include "common.h"
#include <sys/spawn.h>
#include <sys/stat.h>
#include <copyfile.h>
#include <mach-o/dyld.h>
#include <stdint.h>
#include <spawn.h>
#include <sys/wait.h>

extern char **environ;

int RunCmd(const char *cmd)
{
    pid_t pid;
    char *argv[] = {"sh", "-c", (char*)cmd, NULL};
    int status;
    fprintf(stderr, "Run command: %s\n", cmd);
    status = posix_spawn(&pid, "/usr/bin/bash", NULL, NULL, argv, environ);
    if (status == 0) {
         printf("Child pid: %i\n", pid);
        if (waitpid(pid, &status, 0) != -1) {
               printf("Child exited with status %i\n", status);
            
        } else {
            perror("waitpid");
        }
    } else {
       // printf("posix_spawn: %s\n", strerror(status));
    }
    return status;
}



kern_return_t do_bootstrap(bool force) {
    
    char path[256];
    uint32_t size = sizeof(path);
    _NSGetExecutablePath(path, &size);
    char *pt = realpath(path, 0);
    pid_t pd = 0;
    NSString* execpath = [[NSString stringWithUTF8String:pt] stringByDeletingLastPathComponent];
    
    int f = open("/.installed_g0blin_rc0", O_RDONLY);
    if (f == -1 || force) {
        LOG("installing bootstrap...");
        
        NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
        NSLog(@"bundlePath: %@", bundlePath);
        NSString *tarPath = [[NSBundle mainBundle] pathForResource:@"tar" ofType:nil];
        NSLog(@"tar path: %@", tarPath);
        NSError *theError = nil;
        NSArray *pathArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/bin" error:&theError];
        NSString* bootstrap = [execpath stringByAppendingPathComponent:@"bootstrap.tar"];
        NSString* bintools = [execpath stringByAppendingPathComponent:@"binpack64-256.tar"];
        NSString* tar = [execpath stringByAppendingPathComponent:@"tar"];
        NSString* launchctl = [execpath stringByAppendingPathComponent:@"launchctl"];
        NSString* motd = [execpath stringByAppendingPathComponent:@"motd"];
        unlink("/bin/tar");
        unlink("/bin/launchctl");
        unlink("/private/etc/motd");
        
        copyfile([tar UTF8String], "/bin/tar", 0, COPYFILE_ALL);
        chmod("/bin/tar", 0755);
        pathArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/bin" error:&theError];
        //mkdir("/jb", 0755);
        
        chdir("/");

       // posix_spawn(&pd, "/bin/tar", 0, 0, (char**)&(const char*[]){"/bin/tar", "--preserve-permissions", "-k", "-xvf", [bootstrap UTF8String], NULL}, NULL);
         posix_spawn(&pd, "/bin/tar", 0, 0, (char**)&(const char*[]){"/bin/tar", "--preserve-permissions","-xvf", [bootstrap UTF8String], NULL}, NULL);
        waitpid(pd, 0, 0);
        LOG("bootstrap unpacked");
        copyfile([motd UTF8String], "/private/etc/motd", 0, COPYFILE_ALL);
        chmod("/private/etc/motd", 0755);
        /*
        mkdir("/jb", 0755);
        NSString *theCommand = [NSString stringWithFormat:@"/usr/bin/tar fxp %@ -C /jb", bintools];
       */
        LOG("extracting jons bootstrap to root... caution!");
        //testing
        NSString *theCommand = [NSString stringWithFormat:@"/usr/bin/tar fxpk %@ -C /", bintools];
        RunCmd([theCommand UTF8String]);
        
        
        copyfile([launchctl UTF8String], "/bin/launchctl", 0, COPYFILE_ALL);
        chmod("/bin/launchctl", 0755);
        //chown("-R", <#uid_t#>, <#gid_t#>)
        unlink(".installed_g0blin");
    
        open("/.installed_g0blin_rc0", O_RDWR|O_CREAT);
        
        
        //open("/.cydia_no_stash", O_RDWR|O_CREAT);
        
        
        // run nito install scripts
        {
            char *name = "/var/lib/dpkg/info/mobilesubstrate.postinst";
            RunCmd(name);
            RunCmd("/usr/libexec/substrate");
            RunCmd("/usr/libexec/nito/firmware.sh");
            //posix_spawn(&pd, name, 0, 0, (char**)&(const char*[]){name, NULL}, NULL);
            //waitpid(pd, 0, 0);
            //RunCmd(@")
        }
        LOG("ran nitoTV extrainst scripts");
        
        // block some Apple IPs
        posix_spawn(&pd, "/bin/bash", 0, 0, (char**)&(const char*[]){"/bin/bash", "-c", """echo '127.0.0.1 iphonesubmissions.apple.com' >> /etc/hosts""", NULL}, NULL);
        posix_spawn(&pd, "/bin/bash", 0, 0, (char**)&(const char*[]){"/bin/bash", "-c", """echo '127.0.0.1 radarsubmissions.apple.com' >> /etc/hosts""", NULL}, NULL);
        posix_spawn(&pd, "/bin/bash", 0, 0, (char**)&(const char*[]){"/bin/bash", "-c", """echo '127.0.0.1 mesu.apple.com' >> /etc/hosts""", NULL}, NULL);
        posix_spawn(&pd, "/bin/bash", 0, 0, (char**)&(const char*[]){"/bin/bash", "-c", """echo '127.0.0.1 appldnld.apple.com' >> /etc/hosts""", NULL}, NULL);
        LOG("modified hosts file");
       
        /*
        // set SBShowNonDefaultSystemApps = YES so we can see Cydia (TODO: set via cfprefsd instead?)
        posix_spawn(&pd, "killall", 0, 0, (char**)&(const char*[]){"killall", "-SIGSTOP", "cfprefsd", NULL}, NULL);
        NSMutableDictionary *plist = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/mobile/Library/Preferences/com.apple.springboard.plist"];
        [plist setObject:[NSNumber numberWithBool:YES] forKey:@"SBShowNonDefaultSystemApps"];
        [plist writeToFile:@"/var/mobile/Library/Preferences/com.apple.springboard.plist" atomically:YES];
        posix_spawn(&pd, "killall", 0, 0, (char**)&(const char*[]){"killall", "-9", "cfprefsd", NULL}, NULL);
        LOG("modified com.apple.springboard.plist");
        */
        // rebuild icon cache
       // LOG("uicache...");
        //posix_spawn(&pd, "/usr/bin/uicache", 0, 0, (char**)&(const char*[]){"/usr/bin/uicache", NULL}, NULL);
        //waitpid(pd, 0, 0);
        
        LOG("finished installing bootstrap");
    }
    LOG("bootstrap ready");
    
    // copy reload
    NSString *reload = [execpath stringByAppendingPathComponent:@"reload"];
    unlink("/usr/libexec/reload");
    copyfile([reload UTF8String], "/usr/libexec/reload", 0, COPYFILE_ALL);
    chmod("/usr/libexec/reload", 0755);
    chown("/usr/libexec/reload", 0, 0);
    
    // copy 0.reload.plist
    NSString *reloadPlist = [execpath stringByAppendingPathComponent:@"0.reload.plist"];
    unlink("/Library/LaunchDaemons/0.reload.plist");
    copyfile([reloadPlist UTF8String], "/Library/LaunchDaemons/0.reload.plist", 0, COPYFILE_ALL);
    chmod("/Library/LaunchDaemons/0.reload.plist", 0644);
    chown("/Library/LaunchDaemons/0.reload.plist", 0, 0);
    
    // copy dropbear.plist
    NSString *dropbearPlist = [execpath stringByAppendingPathComponent:@"dropbear.plist"];
    unlink("/Library/LaunchDaemons/dropbear.plist");
    copyfile([dropbearPlist UTF8String], "/Library/LaunchDaemons/dropbear.plist", 0, COPYFILE_ALL);
    chmod("/Library/LaunchDaemons/dropbear.plist", 0644);
    chown("/Library/LaunchDaemons/dropbear.plist", 0, 0);
    chmod("/etc/dropbear", 0755);
    //RunCmd("/usr/bin/chown -R root:wheel /usr/local/bin");
    //RunCmd("/usr/bin/chown -R root:wheel /usr/local/bin");
    //RunCmd("/usr/bin/chown -R root:wheel /private/etc/dropbear");
    //RunCmd("/usr/bin/chown -R root:wheel /private/etc/profile.d");
    //RunCmd("/usr/bin/chown -R root:wheel /private/etc/profile");
    // stop SU daemon
    unlink("/System/Library/LaunchDaemons/com.apple.mobile.softwareupdated.plist");
    
    // update permissions
    chmod("/private", 0777);
    chmod("/private/var", 0777);
    chmod("/private/var/mobile", 0777);
    chmod("/private/var/mobile/Library", 0777);
    chmod("/private/var/mobile/Library/Preferences", 0777);

    // kill OTA updater
    pid_t pid;
    unlink("/var/MobileAsset/Assets/com_apple_MobileAsset_SoftwareUpdate");
    posix_spawn(&pid, "touch", 0, 0, (char**)&(const char*[]){"touch", "/var/MobileAsset/Assets/com_apple_MobileAsset_SoftwareUpdate", NULL}, NULL);
    chmod("/var/MobileAsset/Assets/com_apple_MobileAsset_SoftwareUpdate", 000);
    chown("/var/MobileAsset/Assets/com_apple_MobileAsset_SoftwareUpdate", 0, 0);
    LOG("killed OTA updater");
    
    //RunCmd("/usr/local/bin/dropbear -F -R -p 22 &");
    //RunCmd("/jb/usr/local/bin/dropbear -R --shell /jb/bin/bash");
    LOG("bootstrapped");
        
    return KERN_SUCCESS; // TODO: handle errors?
}
