#!/usr/bin/env python3
import sys
import os
import os.path
import ctypes
import fcntl
import select
import errno

libc = ctypes.CDLL(None, use_errno=True)
CLONE_NEWPID = 0x20000000


def nonblock_cloexec(fd):
    fcntl.fcntl(
        fd,
        fcntl.F_SETFD,
        fcntl.fcntl(fd, fcntl.F_GETFD) | os.O_NONBLOCK | fcntl.FD_CLOEXEC,
    )


def exit_status(status):
    sig = status & 0xff
    ret = status >> 8
    if sig:
        raise SystemExit(128 + sig)
    if ret >= 128:
        raise SystemExit(128)
    raise SystemExit(ret)


def main(argv):
    (parent_rfd, parent_wfd) = os.pipe()
    nonblock_cloexec(parent_rfd)
    nonblock_cloexec(parent_wfd)
    if libc.unshare(CLONE_NEWPID) != 0:
        raise OSError(ctypes.get_errno())
    fork_pid = os.fork()
    if fork_pid == 0:
        # child
        assert os.getpid() == 1
        os.close(parent_wfd)
        fork2_pid = os.fork()
        if fork2_pid == 0:
            # child
            if argv[1][0] == '/':
                os.execv(argv[1], argv[1:])
            for d in os.environ['PATH'].split(':'):
                try:
                    os.execv(os.path.join(d, argv[1]), argv[1:])
                except FileNotFoundError:
                    continue
            raise SystemExit(127)
        else:
            # parent
            rlist, wlist, elist = (parent_rfd,), (), ()
            while True:
                (pid, status) = os.waitpid(0, os.WNOHANG)
                if pid == fork2_pid:
                    exit_status(status)
                try:
                    r, w, x = select.select(rlist, wlist, elist, 1.0)
                except select.error as e:
                    code, msg = e.args
                    # We might get interrupted by SIGCHLD here
                    if code != errno.EINTR:
                        raise
    else:
        # parent
        os.close(parent_rfd)
        (pid, status) = os.waitpid(fork_pid, 0)
        exit_status(status)


if __name__ == '__main__':
    main(sys.argv)