17db96d56Sopenharmony_ci""" 27db96d56Sopenharmony_ciBasic subprocess implementation for POSIX which only uses os functions. Only 37db96d56Sopenharmony_ciimplement features required by setup.py to build C extension modules when 47db96d56Sopenharmony_cisubprocess is unavailable. setup.py is not used on Windows. 57db96d56Sopenharmony_ci""" 67db96d56Sopenharmony_ciimport os 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ci# distutils.spawn used by distutils.command.build_ext 107db96d56Sopenharmony_ci# calls subprocess.Popen().wait() 117db96d56Sopenharmony_ciclass Popen: 127db96d56Sopenharmony_ci def __init__(self, cmd, env=None): 137db96d56Sopenharmony_ci self._cmd = cmd 147db96d56Sopenharmony_ci self._env = env 157db96d56Sopenharmony_ci self.returncode = None 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_ci def wait(self): 187db96d56Sopenharmony_ci pid = os.fork() 197db96d56Sopenharmony_ci if pid == 0: 207db96d56Sopenharmony_ci # Child process 217db96d56Sopenharmony_ci try: 227db96d56Sopenharmony_ci if self._env is not None: 237db96d56Sopenharmony_ci os.execve(self._cmd[0], self._cmd, self._env) 247db96d56Sopenharmony_ci else: 257db96d56Sopenharmony_ci os.execv(self._cmd[0], self._cmd) 267db96d56Sopenharmony_ci finally: 277db96d56Sopenharmony_ci os._exit(1) 287db96d56Sopenharmony_ci else: 297db96d56Sopenharmony_ci # Parent process 307db96d56Sopenharmony_ci _, status = os.waitpid(pid, 0) 317db96d56Sopenharmony_ci self.returncode = os.waitstatus_to_exitcode(status) 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ci return self.returncode 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_cidef _check_cmd(cmd): 377db96d56Sopenharmony_ci # Use regex [a-zA-Z0-9./-]+: reject empty string, space, etc. 387db96d56Sopenharmony_ci safe_chars = [] 397db96d56Sopenharmony_ci for first, last in (("a", "z"), ("A", "Z"), ("0", "9")): 407db96d56Sopenharmony_ci for ch in range(ord(first), ord(last) + 1): 417db96d56Sopenharmony_ci safe_chars.append(chr(ch)) 427db96d56Sopenharmony_ci safe_chars.append("./-") 437db96d56Sopenharmony_ci safe_chars = ''.join(safe_chars) 447db96d56Sopenharmony_ci 457db96d56Sopenharmony_ci if isinstance(cmd, (tuple, list)): 467db96d56Sopenharmony_ci check_strs = cmd 477db96d56Sopenharmony_ci elif isinstance(cmd, str): 487db96d56Sopenharmony_ci check_strs = [cmd] 497db96d56Sopenharmony_ci else: 507db96d56Sopenharmony_ci return False 517db96d56Sopenharmony_ci 527db96d56Sopenharmony_ci for arg in check_strs: 537db96d56Sopenharmony_ci if not isinstance(arg, str): 547db96d56Sopenharmony_ci return False 557db96d56Sopenharmony_ci if not arg: 567db96d56Sopenharmony_ci # reject empty string 577db96d56Sopenharmony_ci return False 587db96d56Sopenharmony_ci for ch in arg: 597db96d56Sopenharmony_ci if ch not in safe_chars: 607db96d56Sopenharmony_ci return False 617db96d56Sopenharmony_ci 627db96d56Sopenharmony_ci return True 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci 657db96d56Sopenharmony_ci# _aix_support used by distutil.util calls subprocess.check_output() 667db96d56Sopenharmony_cidef check_output(cmd, **kwargs): 677db96d56Sopenharmony_ci if kwargs: 687db96d56Sopenharmony_ci raise NotImplementedError(repr(kwargs)) 697db96d56Sopenharmony_ci 707db96d56Sopenharmony_ci if not _check_cmd(cmd): 717db96d56Sopenharmony_ci raise ValueError(f"unsupported command: {cmd!r}") 727db96d56Sopenharmony_ci 737db96d56Sopenharmony_ci tmp_filename = "check_output.tmp" 747db96d56Sopenharmony_ci if not isinstance(cmd, str): 757db96d56Sopenharmony_ci cmd = " ".join(cmd) 767db96d56Sopenharmony_ci cmd = f"{cmd} >{tmp_filename}" 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_ci try: 797db96d56Sopenharmony_ci # system() spawns a shell 807db96d56Sopenharmony_ci status = os.system(cmd) 817db96d56Sopenharmony_ci exitcode = os.waitstatus_to_exitcode(status) 827db96d56Sopenharmony_ci if exitcode: 837db96d56Sopenharmony_ci raise ValueError(f"Command {cmd!r} returned non-zero " 847db96d56Sopenharmony_ci f"exit status {exitcode!r}") 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci try: 877db96d56Sopenharmony_ci with open(tmp_filename, "rb") as fp: 887db96d56Sopenharmony_ci stdout = fp.read() 897db96d56Sopenharmony_ci except FileNotFoundError: 907db96d56Sopenharmony_ci stdout = b'' 917db96d56Sopenharmony_ci finally: 927db96d56Sopenharmony_ci try: 937db96d56Sopenharmony_ci os.unlink(tmp_filename) 947db96d56Sopenharmony_ci except OSError: 957db96d56Sopenharmony_ci pass 967db96d56Sopenharmony_ci 977db96d56Sopenharmony_ci return stdout 98