module patch.rightclicktoplumb;

import core.sys.posix.unistd : fork, chdir, execvp, pid_t, _exit;
import core.sys.posix.sys.wait : waitpid;
import core.stdc.stdio : snprintf;
import core.stdc.stdlib : exit;
import std.string : toStringz;

import patches : isPatchEnabled;
import st : pid;

enum PATH_MAX = 4096;

// Define plumb_cmd
enum plumb_cmd = "plumb";

static if (isPatchEnabled!"RIGHTCLICKTOPLUMB_PATCH") {
    version(linux) {
        int subprocwd(char* path) {
            if (snprintf(path, PATH_MAX, "/proc/%d/cwd", pid) < 0)
                return -1;
            return 0;
        }
    } else version(OpenBSD) {
        import core.sys.openbsd.sys.sysctl : sysctl, CTL_KERN, KERN_PROC_CWD;
        
        int subprocwd(char* path) {
            size_t sz = PATH_MAX;
            int[3] name = [CTL_KERN, KERN_PROC_CWD, pid];
            if (sysctl(name.ptr, 3, path, &sz, null, 0) == -1)
                return -1;
            return 0;
        }
    } else {
        int subprocwd(char* path) {
            return -1;
        }
    }

    void plumb(char* sel) {
        if (sel == null)
            return;
        char[PATH_MAX] cwd;
        pid_t child;
        if (subprocwd(cwd.ptr) != 0)
            return;

        switch(child = fork()) {
            case -1:
                return;
            case 0:
                if (chdir(cwd.ptr) != 0)
                    exit(1);
                char*[3] argv = [cast(char*)plumb_cmd.toStringz, sel, null];
                if (execvp(plumb_cmd.toStringz, argv.ptr) == -1)
                    exit(1);
                exit(0);
            default:
                waitpid(child, null, 0);
        }
    }
}