def switch_pgid(self): try: if os.getpgrp() != os.tcgetpgrp(0): self.__old_pgid = os.getpgrp() os.setpgid(0, os.tcgetpgrp(0)) else: self.__old_pgid = None except OSError: self.__old_pgid = None
def stop_was_requested(self): """Check whether a 'keyboard stop' instruction has been sent. Returns true if ^X has been sent on the controlling terminal. Consumes all available input on /dev/tty. """ if not self.enabled: return False # Don't try to read the terminal if we're in the background. # There's a race here, if we're backgrounded just after this check, but # I don't see a clean way to avoid it. if os.tcgetpgrp(self.tty.fileno()) != os.getpid(): return False try: termios.tcsetattr(self.tty, termios.TCSANOW, self.cbreak_tcattr) except EnvironmentError: return False try: seen_ctrl_x = False while True: c = os.read(self.tty.fileno(), 1) if not c: break if c == "\x18": seen_ctrl_x = True except EnvironmentError: seen_ctrl_x = False finally: termios.tcsetattr(self.tty, termios.TCSANOW, self.clean_tcattr) return seen_ctrl_x
def _shell_tty(): try: _st = sys.stderr.fileno() if os.tcgetpgrp(_st) != os.getpgid(os.getpid()): # we don't own it _st = None except OSError: _st = None return _st
def tcgetpgrp(space, fd): """ tcgetpgrp(fd) -> pgid Return the process group associated with the terminal given by a fd. """ try: pgid = os.tcgetpgrp(fd) except OSError, e: raise wrap_oserror(space, e)
def get_name_for_fd(fd): """ Return the process name for a given process ID. """ pgrp = os.tcgetpgrp(fd) try: return get_proc_name(pgrp) except IOError: pass
def is_stdout_attached_to_terminal(): '''判断当前进程组是不是前台进程组(主要关注stdout是否被关联到/dev/tty)''' try: # 如果stdout被绑定到终端设备上,则是前端进程组 if os.getpgrp() == os.tcgetpgrp(sys.stdout.fileno()): return True else: return False except OSError: # sys.stdout 未绑定到任何设备 return False
def initialise(self): if not self.enabled: return if termios is None: self.enabled = False return try: self.tty = open("/dev/tty", "w+") os.tcgetpgrp(self.tty.fileno()) self.clean_tcattr = termios.tcgetattr(self.tty) iflag, oflag, cflag, lflag, ispeed, ospeed, cc = self.clean_tcattr new_lflag = lflag & (0xffffffff ^ termios.ICANON) new_cc = cc[:] new_cc[termios.VMIN] = 0 self.cbreak_tcattr = [ iflag, oflag, cflag, new_lflag, ispeed, ospeed, new_cc] except Exception: self.enabled = False return
def tcgetpgrp(space, fd): """ tcgetpgrp(fd) -> pgid Return the process group associated with the terminal given by a fd. """ try: pgid = os.tcgetpgrp(fd) except OSError as e: raise wrap_oserror(space, e) return space.newint(pgid)
def execWithRedirect(command, argv, stdin = 0, stdout = 1, stderr = 2, searchPath = 0, root = '/', newPgrp = 0, ignoreTermSigs = 0): stdin = getfd(stdin) if stdout == stderr: stdout = getfd(stdout) stderr = stdout else: stdout = getfd(stdout) stderr = getfd(stderr) childpid = os.fork() if (not childpid): if (root and root != '/'): os.chroot(root) os.chdir("/") if ignoreTermSigs: signal.signal(signal.SIGTSTP, signal.SIG_IGN) signal.signal(signal.SIGINT, signal.SIG_IGN) if type(stdin) == type("a"): stdin = os.open(stdin, os.O_RDONLY) if type(stdout) == type("a"): stdout = os.open(stdout, os.O_RDWR) if type(stderr) == type("a"): stderr = os.open(stderr, os.O_RDWR) if stdin != 0: os.dup2(stdin, 0) os.close(stdin) if stdout != 1: os.dup2(stdout, 1) if stdout != stderr: os.close(stdout) if stderr != 2: os.dup2(stderr, 2) os.close(stderr) if (searchPath): os.execvp(command, argv) else: os.execv(command, argv) sys.exit(1) if newPgrp: os.setpgid(childpid, childpid) oldPgrp = os.tcgetpgrp(0) os.tcsetpgrp(0, childpid) status = -1 try: (pid, status) = os.waitpid(childpid, 0) except OSError, (errno, msg): print __name__, "waitpid:", msg
def show_progress(self, done=False): """Display progress bar if enabled and if running on correct terminal""" if SHOWPROG and self.showprog and (done or self.index % 500 == 0) \ and (os.getpgrp() == os.tcgetpgrp(sys.stderr.fileno())): rows, columns = struct.unpack('hh', fcntl.ioctl(2, termios.TIOCGWINSZ, "1234")) if columns < 100: sps = 30 else: # Terminal is wide enough, include bytes/sec sps = 42 # Progress bar length wlen = int(columns) - len(str_units(self.filesize)) - sps # Number of bytes per progress bar unit xunit = float(self.filesize)/wlen # Progress bar units done so far xdone = int(self.offset/xunit) xtime = time.time() progress = 100.0*self.offset/self.filesize # Display progress only if there is some change in progress if (done and not self.progdone) or (self.prevdone != xdone or \ int(self.prevtime) != int(xtime) or \ round(self.prevprog) != round(progress)): if done: # Do not display progress again when done=True self.progdone = 1 otime = xtime - self.timestart # Overall time tdelta = xtime - self.prevtime # Segment time self.prevprog = progress self.prevdone = xdone self.prevtime = xtime # Number of progress bar units for completion slen = wlen - xdone if done: # Overall average bytes/sec bps = self.offset / otime else: # Segment average bytes/sec bps = (self.offset - self.prevoff) / tdelta self.prevoff = self.offset # Progress bar has both foreground and background colors # as green and in case the terminal does not support colors # then a "=" is displayed instead instead of a green block pbar = " [\033[32m\033[42m%s\033[m%s] " % ("="*xdone, " "*slen) # Add progress percentage and how many bytes have been # processed so far relative to the total number of bytes pbar += "%5.1f%% %9s/%s" % (progress, str_units(self.offset), str_units(self.filesize)) if columns < 100: sys.stderr.write("%s %-6s\r" % (pbar, str_time(otime))) else: # Terminal is wide enough, include bytes/sec sys.stderr.write("%s %9s/s %-6s\r" % (pbar, str_units(bps), str_time(otime))) if done: sys.stderr.write("\n")
def get_name_for_fd(fd): """ Return the process name for a given process ID. """ pgrp = os.tcgetpgrp(fd) try: with open("/proc/%s/cmdline" % pgrp, "rb") as f: return f.read().decode("utf-8", "ignore").split("\0")[0] except IOError: pass
def initialise(self): if not self.enabled: return if termios is None: self.enabled = False return try: self.tty = open("/dev/tty", "w+") os.tcgetpgrp(self.tty.fileno()) self.clean_tcattr = termios.tcgetattr(self.tty) iflag, oflag, cflag, lflag, ispeed, ospeed, cc = self.clean_tcattr new_lflag = lflag & (0xffffffff ^ termios.ICANON) new_cc = cc[:] new_cc[termios.VMIN] = 0 self.cbreak_tcattr = [ iflag, oflag, cflag, new_lflag, ispeed, ospeed, new_cc ] except Exception: self.enabled = False return
def get_name_for_fd(fd): """ Return the process name for a given process ID. """ pgrp = os.tcgetpgrp(fd) try: with open('/proc/%s/cmdline' % pgrp, 'rb') as f: return f.read().decode('utf-8', 'ignore').partition('\0')[0] except IOError: pass
def cb_launchSpectra(self): ''' make sure that main() is started as a foreground process ''' if os.getpgrp() == os.tcgetpgrp(sys.stdout.fileno()): Spectra.gra_input() else: QtGui.QMessageBox.critical( self, 'Error', "cb_launchSpectra: no TTY connected.\nMain runs as a background process", QtGui.QMessageBox.Ok)
def get_name_for_fd(fd): """ Return the process name for a given process ID. """ pgrp = os.tcgetpgrp(fd) try: with open('/proc/%s/cmdline' % pgrp, 'rb') as f: return f.read().decode('utf-8', 'ignore').split('\0')[0] except IOError: pass
def is_interactive(fd=None): if fd is None: return False if isatty(fd): # Compare the current process group to the process group associated # with terminal of the given file descriptor to determine if the process # is running in the background. return getpgrp() == tcgetpgrp(fd) else: return False
def isRunningInBackground(): # type: () -> bool import os import sys try: if os.getpgrp() == os.tcgetpgrp(sys.stdout.fileno()): return False else: return True except OSError: return True
def _is_daemon(): try: is_daemon = os.getpgrp() != os.tcgetpgrp(sys.stdout.fileno()) except OSError as err: if err.errno == errno.ENOTTY: is_daemon = True else: raise except UnsupportedOperation: is_daemon = True return is_daemon
def runing_in_terminal() -> bool: # by BlackJack: http://stackoverflow.com/a/24862213/2334951 try: terminal_prgc_gr_id = os.tcgetpgrp(sys.stdout.fileno()) except OSError: return False else: current_prgc_gr_id = os.getpgrp() if current_prgc_gr_id == terminal_prgc_gr_id: return True else: return False
def _shell_is_busy(self): """Check if the shell is waiting for a command or not.""" pty = self.term.get_pty() fd = pty.get_fd() fgpid = os.tcgetpgrp(fd) if fgpid == -1 or fgpid == self.shell_pid: return False return True
def get_name_for_fd(fd): """ Return the process name for a given process ID. """ if sys.platform in ('linux', 'linux2'): pgrp = os.tcgetpgrp(fd) try: with open('/proc/%s/cmdline' % pgrp, 'rb') as f: return f.read().decode('utf-8', 'ignore').split('\0')[0] except IOError: pass
def _is_daemon(): try: is_daemon = os.getpgrp() != os.tcgetpgrp(sys.stdout.fileno()) except OSError as err: if err.errno == errno.ENOTTY: # Assume we are a daemon because there is no terminal. is_daemon = True else: raise except UnsupportedOperation: # Could not get the fileno for stdout, so we must be a daemon. is_daemon = True return is_daemon
def check_foreground(): ''' function that returns True if the process executing this module is in foreground. If in background, this module won't print to stderr/stdout. ''' if (not platform.system().lower().startswith('linux')): return True try: if (os.getpgrp() == os.tcgetpgrp(sys.stdout.fileno())): return True except OSError: pass return False
def signalHandler(self, signo, _frame): logging.debug("signalHandler: signo=%d", signo) if signo == signal.SIGINT or signo == signal.SIGTERM: self.job.kill() elif signo == signal.SIGCHLD: # Get status of child try: (pid, status) = os.waitpid( self.job.pid, os.WNOHANG + os.WCONTINUED + os.WUNTRACED) except OSError as ex: # Simulate success in case of error (very rare case...) logging.debug("waitpid: %s", str(ex)) pid = self.job.pid status = 512 logging.debug("waitpid: pid=%d status=%s", pid, status) self.job.updateStatus(status) if self.job.stopped: # If sub-process was associated with console, change it to us if os.tcgetpgrp(0) == self.job.pgid: logging.debug("tcsetpgrp(0, %d)", os.getpgrp()) os.tcsetpgrp(0, os.getpgrp()) # Propagate the stop to our process group logging.debug("killpg(0, SIGSTOP)") os.killpg(0, signal.SIGSTOP) elif signo == signal.SIGCONT: # If we are associated with console, change it to sub-process self.tcpgrp = os.tcgetpgrp(0) self.foreground = (self.tcpgrp == os.getpgrp()) logging.debug("tcpgrp=%d foreground=%d", self.tcpgrp, self.foreground) if self.foreground: logging.debug("tcsetpgrp(0, %d)", self.job.pgid) os.tcsetpgrp(0, self.job.pgid) # Propagate continue to sub-process logging.debug("killpg(%d, SIGCONT)", self.job.pgid) os.killpg(self.job.pgid, signal.SIGCONT)
def serve_forever(self): ctx = context.get_context() ctx.running = True try: # set up greenlet switch monitoring import greenlet greenlet.settrace(ctx._trace) except AttributeError: pass # oh well if not self.prefork: self.start() log_msg = 'Group initialized and serving forever...' ctx.log.critical('GROUP.INIT').success(log_msg) if ctx.dev and ctx.dev_service_repl_enabled and os.isatty(0): if not hasattr(os, "getpgrp"): # Windows fg = True else: try: fg = os.getpgrp() == os.tcgetpgrp(sys.stdout.fileno()) except OSError: fg = False if fg: # only start REPL on unix machines if running in foreground async .start_repl({'server': ctx.server_group}) try: while 1: async .sleep(1.0) finally: self.stop() return if not ufork: raise RuntimeError( 'attempted to run pre-forked on platform without fork') if ctx.tracing: # a little bit hacky, disable tracing in aribter self.trace_in_child = True ctx.set_greenlet_trace(False) else: self.trace_in_child = False self.arbiter = ufork.Arbiter(post_fork=self._post_fork, child_pre_exit=self.stop, parent_pre_stop=ctx.stop, size=self.num_workers, sleep=async .sleep, fork=gevent.fork, child_memlimit=ctx.worker_memlimit) if self.daemonize: pgrpfile = os.path.join(ctx.process_group_file_path, '{0}.pgrp'.format(ctx.appname)) self.arbiter.spawn_daemon(pgrpfile=pgrpfile) else: self.arbiter.run()
def signalHandler(self, signo, _frame): logging.debug("signalHandler: signo=%d", signo) if signo == signal.SIGINT or signo == signal.SIGTERM: self.job.kill() elif signo == signal.SIGCHLD: # Get status of child try: (pid, status) = os.waitpid(self.job.pid, os.WNOHANG + os.WCONTINUED + os.WUNTRACED) except OSError as ex: # Simulate success in case of error (very rare case...) logging.debug("waitpid: %s", str(ex)) pid = self.job.pid status = 512 logging.debug("waitpid: pid=%d status=%s", pid, status) self.job.updateStatus(status) if self.job.stopped: # If sub-process was associated with console, change it to us if os.tcgetpgrp(0) == self.job.pgid: logging.debug("tcsetpgrp(0, %d)", os.getpgrp()) os.tcsetpgrp(0, os.getpgrp()) # Propagate the stop to our process group logging.debug("killpg(0, SIGSTOP)") os.killpg(0, signal.SIGSTOP) elif signo == signal.SIGCONT: # If we are associated with console, change it to sub-process self.tcpgrp = os.tcgetpgrp(0) self.foreground = (self.tcpgrp == os.getpgrp()) logging.debug("tcpgrp=%d foreground=%d", self.tcpgrp, self.foreground) if self.foreground: logging.debug("tcsetpgrp(0, %d)", self.job.pgid) os.tcsetpgrp(0, self.job.pgid) # Propagate continue to sub-process logging.debug("killpg(%d, SIGCONT)", self.job.pgid) os.killpg(self.job.pgid, signal.SIGCONT)
def _safe_tcsetpgrp(fd, pgrp): """Set |pgrp| as the controller of the tty |fd|.""" try: curr_pgrp = os.tcgetpgrp(fd) except OSError as e: # This can come up when the fd is not connected to a terminal. if e.errno == errno.ENOTTY: return raise # We can change the owner only if currently own it. Otherwise we'll get # stopped by the kernel with SIGTTOU and that'll hit the whole group. if curr_pgrp == os.getpgrp(): os.tcsetpgrp(fd, pgrp)
def setup_py_main(): """Main function for setup script.""" if sys.stdin.isatty() and sys.stdout.isatty() and sys.stderr.isatty(): if os.getpgrp() == os.tcgetpgrp(sys.stdout.fileno()): if os.geteuid() == 0: main() terminate() else: print("[!] Run me as superuser (a.k.a. root)") sys.exit(2) else: sys.exit(2) else: sys.exit(2)
def get_name_for_fd(fd): """ Return the process name for a given process ID. """ try: pgrp = os.tcgetpgrp(fd) except OSError: # See: https://github.com/jonathanslenders/pymux/issues/46 return try: with open('/proc/%s/cmdline' % pgrp, 'rb') as f: return f.read().decode('utf-8', 'ignore').partition('\0')[0] except IOError: pass
def determine_interactive(self): """Determine whether we're in an interactive shell. Sets interactivity off if appropriate. cf http://stackoverflow.com/questions/24861351/how-to-detect-if-python-script-is-being-run-as-a-background-process """ try: if not sys.stdout.isatty() or os.getpgrp() != os.tcgetpgrp(sys.stdout.fileno()): self.interactive = 0 return False except Exception: self.interactive = 0 return False if self.interactive == 0: return False return True
def _maybe_become_foreground(self): """ Become the foreground process if the user requested it and it is possible. Allows the "Parent" process (aka this one) to get SIGINT (Ctrl+C). Useful if running in your terminal or from python repl. :return: """ if self._should_become_foreground(): hdlr = signal.signal(signal.SIGTTOU, signal.SIG_IGN) # ignore since would cause this process to stop self.controlling_terminal = os.open(os.ctermid(), os.O_RDWR) self.orig_fore_pg = os.tcgetpgrp(self.controlling_terminal) # sends SIGTTOU to this process os.tcsetpgrp(self.controlling_terminal, self.childpid) signal.signal(signal.SIGTTOU, hdlr) return True return False
def determine_interactive(self): """Determine whether we're in an interactive shell. Sets interactivity off if appropriate. cf http://stackoverflow.com/questions/24861351/how-to-detect-if-python-script-is-being-run-as-a-background-process """ try: if not sys.stdout.isatty() or os.getpgrp() != os.tcgetpgrp(sys.stdout.fileno()): self.set_noninteractive() return False except Exception: self.set_noninteractive(msg='Problems determining interactivity, assuming not.') return False if self.interactive == 0: return False return True
def __enter__(self): assert not self._tty_settings # False if the pipeline is being piped somewhere if sys.stdin.isatty() and sys.stdout.isatty(): # False if the process is running in the background if os.getpgrp() == os.tcgetpgrp(sys.stdout.fileno()): try: # Store old settings self._tty_settings = termios.tcgetattr(sys.stdin) # Disable echo tty.setcbreak(sys.stdin.fileno()) except tty.error: pass # Silently ignore failures return self
def get_name_for_fd(fd): """ Return the process name for a given process ID. NOTE: on Linux, this seems to require the master FD. """ try: pgrp = os.tcgetpgrp(fd) except OSError: return try: return get_proc_name(pgrp) except IOError: pass
def __init__(self,debug): """ Constructor """ self._debug = debug self._lock = threading.Lock() try: if os.getpgrp() == os.tcgetpgrp(sys.stdout.fileno()): self._syslog = False self._debug = "1" else: self._syslog = True except: self._syslog = True if self._syslog: syslog.openlog("nerd-alarmclock")
def foreground_processes(self): try: pgrp = os.tcgetpgrp(self.child_fd) foreground_processes = processes_in_group(pgrp) if pgrp >= 0 else [] def process_desc(pid): ans = {'pid': pid} with suppress(Exception): ans['cmdline'] = cmdline_of_process(pid) with suppress(Exception): ans['cwd'] = cwd_of_process(pid) or None return ans return list(map(process_desc, foreground_processes)) except Exception: return []
def serve_forever(self): ctx = context.get_context() ctx.running = True try: # set up greenlet switch monitoring import greenlet greenlet.settrace(ctx._trace) except AttributeError: pass # oh well if not self.prefork: self.start() log_msg = 'Group initialized and serving forever...' ctx.log.critical('GROUP.INIT').success(log_msg) if ctx.dev and ctx.dev_service_repl_enabled and os.isatty(0): if not hasattr(os, "getpgrp"): # Windows fg = True else: try: fg = os.getpgrp() == os.tcgetpgrp(sys.stdout.fileno()) except OSError: fg = False if fg: # only start REPL on unix machines if running in foreground async.start_repl({'server': ctx.server_group}) try: while 1: async.sleep(1.0) finally: self.stop() return if not ufork: raise RuntimeError('attempted to run pre-forked on platform without fork') if ctx.tracing: # a little bit hacky, disable tracing in aribter self.trace_in_child = True ctx.set_greenlet_trace(False) else: self.trace_in_child = False self.arbiter = ufork.Arbiter( post_fork=self._post_fork, child_pre_exit=self.stop, parent_pre_stop=ctx.stop, size=self.num_workers, sleep=async.sleep, fork=gevent.fork, child_memlimit=ctx.worker_memlimit) if self.daemonize: pgrpfile = os.path.join(ctx.process_group_file_path, '{0}.pgrp'.format(ctx.appname)) self.arbiter.spawn_daemon(pgrpfile=pgrpfile) else: self.arbiter.run()
def _is_daemon(): # The process group for a foreground process will match the # process group of the controlling terminal. If those values do # not match, or ioctl() fails on the stdout file handle, we assume # the process is running in the background as a daemon. # http://www.gnu.org/software/bash/manual/bashref.html#Job-Control-Basics try: is_daemon = os.getpgrp() != os.tcgetpgrp(sys.stdout.fileno()) except io.UnsupportedOperation: # Could not get the fileno for stdout, so we must be a daemon. is_daemon = True except OSError as err: if err.errno == errno.ENOTTY: # Assume we are a daemon because there is no terminal. is_daemon = True else: raise return is_daemon
def get_name_for_fd(fd): """ Return the process name for a given process ID. :param fd: Slave file descriptor. (Often the master fd works as well, but apparentsly on WSL only the slave FD works.) """ try: pgrp = os.tcgetpgrp(fd) except OSError: # See: https://github.com/jonathanslenders/pymux/issues/46 return try: with open('/proc/%s/cmdline' % pgrp, 'rb') as f: return f.read().decode('utf-8', 'ignore').partition('\0')[0] except IOError: pass
def foreground_processes(self) -> List[ProcessDesc]: if self.child_fd is None: return [] try: pgrp = os.tcgetpgrp(self.child_fd) foreground_processes = processes_in_group(pgrp) if pgrp >= 0 else [] def process_desc(pid: int) -> ProcessDesc: ans: ProcessDesc = {'pid': pid, 'cmdline': None, 'cwd': None} with suppress(Exception): ans['cmdline'] = cmdline_of_process(pid) with suppress(Exception): ans['cwd'] = cwd_of_process(pid) or None return ans return [process_desc(x) for x in foreground_processes] except Exception: return []
def _is_daemon(): # The process group for a foreground process will match the # process group of the controlling terminal. If those values do # not match, or ioctl() fails on the stdout file handle, we assume # the process is running in the background as a daemon. # http://www.gnu.org/software/bash/manual/bashref.html#Job-Control-Basics try: is_daemon = os.getpgrp() != os.tcgetpgrp(sys.stdout.fileno()) except OSError as err: if err.errno == errno.ENOTTY: # Assume we are a daemon because there is no terminal. is_daemon = True else: raise except UnsupportedOperation: # Could not get the fileno for stdout, so we must be a daemon. is_daemon = True return is_daemon
def get_pid_for_cwd(self, oldest: bool = False) -> Optional[int]: with suppress(Exception): assert self.child_fd is not None pgrp = os.tcgetpgrp(self.child_fd) foreground_processes = processes_in_group(pgrp) if pgrp >= 0 else [] if foreground_processes: # there is no easy way that I know of to know which process is the # foreground process in this group from the users perspective, # so we assume the one with the highest PID is as that is most # likely to be the newest process. This situation can happen # for example with a shell script such as: # #!/bin/bash # cd /tmp # vim # With this script , the foreground process group will contain # both the bash instance running the script and vim. return min(foreground_processes) if oldest else max(foreground_processes) return self.pid
def __init__(self, parent, model): super().__init__(model) self.width = parent.width self.height = parent.height self.previous_screen = 0 # ncurses stops the process if in the background if os.tcgetpgrp(sys.stdin.fileno()) != os.getpgrp(): logging.getLogger("display").warn("please run speculos in the foreground to allow the initialization of the display") self.stdscr = curses.initscr() curses.noecho() curses.cbreak() curses.start_color() curses.init_pair(1, curses.COLOR_CYAN, curses.COLOR_BLACK) curses.init_pair(2, curses.COLOR_BLACK, curses.COLOR_WHITE) self.stdscr.nodelay(1) # returns -1 if nothing self.stdscr.clear() self.stdscr.keypad(1) # interpret escape sequences generated by keypad and function keys
def stdin_is_foregrounded_tty(stream): """ Detect if given stdin ``stream`` seems to be in the foreground of a TTY. Specifically, compares the current Python process group ID to that of the stream's file descriptor to see if they match; if they do not match, it is likely that the process has been placed in the background. This is used as a test to determine whether we should manipulate an active stdin so it runs in a character-buffered mode; touching the terminal in this way when the process is backgrounded, causes most shells to pause execution. .. note:: Processes that aren't attached to a terminal to begin with, will always fail this test, as it starts with "do you have a real ``fileno``?". """ if not has_fileno(stream): return False return os.getpgrp() == os.tcgetpgrp(stream.fileno())
def send_signal_for_key(self, key_num: int) -> bool: import signal import termios if self.child_fd is None: return False t = termios.tcgetattr(self.child_fd) if not t[3] & termios.ISIG: return False cc = t[-1] if key_num == cc[termios.VINTR]: s = signal.SIGINT elif key_num == cc[termios.VSUSP]: s = signal.SIGTSTP elif key_num == cc[termios.VQUIT]: s = signal.SIGQUIT else: return False pgrp = os.tcgetpgrp(self.child_fd) os.killpg(pgrp, s) return True
def _goto_current_terminal_directory(self): """Navigate the active Nemo pane to the current working directory of the VTE This functionality depends on some changes to Nemo's extension interface. """ # Well behaved shells will be updating VTE for us but it doesn't always # work. workingDir = self.term.get_current_directory_uri() if workingDir is None: # Find the current foreground process in terminal pty = self.term.get_pty_object() ptyfd = pty.get_fd() pgroup = os.tcgetpgrp(ptyfd) workingDir = os.readlink('/proc/%s/cwd' % pgroup) gfile = Gio.file_parse_name(workingDir) workingDirUri = gfile.get_uri() print workingDirUri # TODO: something useful (like changing the working dir) return
def check_dir(self, out_dir): if os.path.exists(out_dir): #check if the process is run in background try: if os.getpgrp() == os.tcgetpgrp(sys.stdout.fileno()): print self.user_message % out_dir user_input = raw_input() while user_input not in ["1", "2", "3"]: user_input = raw_input().strip() if user_input == "1": return False if user_input == "2": shutil.rmtree(out_dir) os.mkdir(out_dir) return True if user_input == "3": sys.exit(1) else: sys.stderr.write(self.error_message % out_dir) except OSError: sys.stderr.write(self.error_message % out_dir) else: os.mkdir(out_dir) return True
def startLog(self): """Starts the log to path. The parent process becomes the "slave" process: its stdin, stdout, and stderr are redirected to a pseudo tty. A child logging process controls the real stdin, stdout, and stderr, and writes stdout and stderr both to the screen and to the logfile at path. """ self.restoreTerminalControl = (sys.stdin.isatty() and os.tcgetpgrp(0) == os.getpid()) masterFd, slaveFd = os.openpty() signal.signal(signal.SIGTTOU, signal.SIG_IGN) pid = os.fork() if pid: # make parent process the pty slave - the opposite of # pty.fork(). In this setup, the parent process continues # to act normally, while the child process performs the # logging. This makes it simple to kill the logging process # when we are done with it and restore the parent process to # normal, unlogged operation. os.close(masterFd) self._becomeLogSlave(slaveFd, pid) return try: os.close(slaveFd) for writer in self.writers: writer.start() logger = _ChildLogger(masterFd, self.lexer, self.restoreTerminalControl, self.withStdin) try: logger.log() finally: self.lexer.close() finally: os._exit(0)
def _running_in_bg(): try: return (not os.isatty(0)) or (os.getpgrp() != os.tcgetpgrp(0)) except OSError: return True
def _give_terminal_to(pgid): # over-simplified version of: # give_terminal_to from bash 4.3 source, jobs.c, line 4030 # this will give the terminal to the process group pgid if _shell_tty is not None and os.isatty(_shell_tty): oldmask = signal.pthread_sigmask(signal.SIG_BLOCK, _block_when_giving) os.tcsetpgrp(_shell_tty, pgid) signal.pthread_sigmask(signal.SIG_SETMASK, oldmask) # check for shell tty try: _shell_tty = sys.stderr.fileno() if os.tcgetpgrp(_shell_tty) != os.getpgid(os.getpid()): # we don't own it _shell_tty = None except OSError: _shell_tty = None def wait_for_active_job(signal_to_send=None): """ Wait for the active job to finish, to be killed by SIGINT, or to be suspended by ctrl-z. """ _clear_dead_jobs() act = builtins.__xonsh_active_job__ if act is None: return
peer = peer.split(':') if len(peer) != 2: raise Exception('peer %s is not valid' % ':'.join(peer)) _discoro_config['peers'].append(asyncoro.Location(peer[0], peer[1])) del peer, peers _discoro_name = _discoro_config['name'] if not _discoro_name: _discoro_name = socket.gethostname() if not _discoro_name: _discoro_name = 'discoro_server' _discoro_daemon = _discoro_config.pop('daemon', False) if not _discoro_daemon: try: if os.getpgrp() != os.tcgetpgrp(sys.stdin.fileno()): _discoro_daemon = True except: pass _discoro_auth = hashlib.sha1(''.join(hex(_)[2:] for _ in os.urandom(10)).encode()).hexdigest() # delete variables not needed anymore del parser for _discoro_var in ['argparse', 'socket', 'os']: del sys.modules[_discoro_var], globals()[_discoro_var] del _discoro_var _discoro_server_infos = [] _discoro_ServerInfo = collections.namedtuple('DiscoroServerInfo', ['Proc', 'Queue']) _discoro_mp_queue = None _discoro_ntotal_coros = multiprocessing.Value('L', 0)
def _create_preexec_fn(self, process): """Create and return a function to do cleanup before exec The cleanup function will close all file descriptors which are not needed by the child process. This is required to prevent unnecessary blocking on the final read of pipes not set FD_CLOEXEC due to gpg inheriting an open copy of the input end of the pipe. This can cause delays in unrelated parts of the program or deadlocks in the case that one end of the pipe is passed to attach_fds. FIXME: There is a race condition where a pipe can be created in another thread after this function runs before exec is called and it will not be closed. This race condition will remain until a better way to avoid closing the error pipe created by submodule is identified. """ if sys.platform == "win32": return None # No cleanup necessary try: MAXFD = os.sysconf("SC_OPEN_MAX") if MAXFD == -1: MAXFD = 256 except: MAXFD = 256 # Get list of fds to close now, so we don't close the error pipe # created by submodule for reporting exec errors child_fds = [p.child for p in process._pipes.values()] child_fds.sort() child_fds.append(MAXFD) # Sentinel value, simplifies code greatly child_fds_iter = iter(child_fds) child_fd = next(child_fds_iter) while child_fd < 3: child_fd = next(child_fds_iter) extra_fds = [] # FIXME: Is there a better (portable) way to list all open FDs? for fd in range(3, MAXFD): if fd > child_fd: child_fd = next(child_fds_iter) if fd == child_fd: continue try: # Note: Can't use lseek, can cause nul byte in pipes # where the position has not been set by read/write #os.lseek(fd, os.SEEK_CUR, 0) os.tcgetpgrp(fd) except OSError: # FIXME: When support for Python 2.5 is dropped, use 'as' oe = sys.exc_info()[1] if oe.errno == errno.EBADF: continue extra_fds.append(fd) def preexec_fn(): # Note: This function runs after standard FDs have been renumbered # from their original values to 0, 1, 2 for fd in extra_fds: try: os.close(fd) except OSError: pass # Ensure that all descriptors passed to the child will remain open # Arguably FD_CLOEXEC descriptors should be an argument error # But for backwards compatibility, we just fix it here (after fork) for fd in [0, 1, 2] + child_fds[:-1]: try: fcntl.fcntl(fd, fcntl.F_SETFD, 0) except OSError: # Will happen for renumbered FDs pass return preexec_fn
def main(): """clush script entry point""" sys.excepthook = clush_excepthook # # Argument management # usage = "%prog [options] command" parser = OptionParser(usage) parser.add_option("-n", "--nostdin", action="store_true", dest="nostdin", help="don't watch for possible input from stdin") parser.install_groupsconf_option() parser.install_clush_config_options() parser.install_nodes_options() parser.install_display_options(verbose_options=True) parser.install_filecopy_options() parser.install_connector_options() (options, args) = parser.parse_args() set_std_group_resolver_config(options.groupsconf) # # Load config file and apply overrides # config = ClushConfig(options, options.conf) # Initialize logging if config.verbosity >= VERB_DEBUG: logging.basicConfig(level=logging.DEBUG) logging.debug("clush: STARTING DEBUG") else: logging.basicConfig(level=logging.CRITICAL) # Should we use ANSI colors for nodes? if config.color == "auto": color = sys.stdout.isatty() and (options.gatherall or \ sys.stderr.isatty()) else: color = config.color == "always" try: # Create and configure display object. display = Display(options, config, color) except ValueError as exc: parser.error("option mismatch (%s)" % exc) if options.groupsource: # Be sure -a/g -s source work as espected. std_group_resolver().default_source_name = options.groupsource # Compute the nodeset and warn for possible use of shell pathname # expansion (#225) wnodelist = [] xnodelist = [] if options.nodes: wnodelist = [NodeSet(nodes) for nodes in options.nodes] if options.exclude: xnodelist = [NodeSet(nodes) for nodes in options.exclude] for (opt, nodelist) in (('w', wnodelist), ('x', xnodelist)): for nodes in nodelist: if len(nodes) == 1 and exists(str(nodes)): display.vprint_err(VERB_STD, "Warning: using '-%s %s' and " "local path '%s' exists, was it expanded " "by the shell?" % (opt, nodes, nodes)) # --hostfile support (#235) for opt_hostfile in options.hostfile: try: fnodeset = NodeSet() with open(opt_hostfile) as hostfile: for line in hostfile.read().splitlines(): fnodeset.updaten(nodes for nodes in line.split()) display.vprint_err(VERB_DEBUG, "Using nodeset %s from hostfile %s" % (fnodeset, opt_hostfile)) wnodelist.append(fnodeset) except IOError as exc: # re-raise as OSError to be properly handled errno, strerror = exc.args raise OSError(errno, strerror, exc.filename) # Instantiate target nodeset from command line and hostfile nodeset_base = NodeSet.fromlist(wnodelist) # Instantiate filter nodeset (command line only) nodeset_exclude = NodeSet.fromlist(xnodelist) # Specified engine prevails over default engine DEFAULTS.engine = options.engine # Do we have nodes group? task = task_self() task.set_info("debug", config.verbosity >= VERB_DEBUG) if config.verbosity == VERB_DEBUG: std_group_resolver().set_verbosity(1) if options.nodes_all: all_nodeset = NodeSet.fromall() display.vprint(VERB_DEBUG, "Adding nodes from option -a: %s" % \ all_nodeset) nodeset_base.add(all_nodeset) if options.group: grp_nodeset = NodeSet.fromlist(options.group, resolver=RESOLVER_NOGROUP) for grp in grp_nodeset: addingrp = NodeSet("@" + grp) display.vprint(VERB_DEBUG, \ "Adding nodes from option -g %s: %s" % (grp, addingrp)) nodeset_base.update(addingrp) if options.exgroup: grp_nodeset = NodeSet.fromlist(options.exgroup, resolver=RESOLVER_NOGROUP) for grp in grp_nodeset: removingrp = NodeSet("@" + grp) display.vprint(VERB_DEBUG, \ "Excluding nodes from option -X %s: %s" % (grp, removingrp)) nodeset_exclude.update(removingrp) # Do we have an exclude list? (-x ...) nodeset_base.difference_update(nodeset_exclude) if len(nodeset_base) < 1: parser.error('No node to run on.') if options.pick and options.pick < len(nodeset_base): # convert to string for sample as nsiter() is slower for big # nodesets; and we assume options.pick will remain small-ish keep = random.sample(list(nodeset_base), options.pick) nodeset_base.intersection_update(','.join(keep)) if config.verbosity >= VERB_VERB: msg = "Picked random nodes: %s" % nodeset_base print(Display.COLOR_RESULT_FMT % msg) # Set open files limit. set_fdlimit(config.fd_max, display) # # Task management # # check for clush interactive mode interactive = not len(args) and \ not (options.copy or options.rcopy) # check for foreground ttys presence (input) stdin_isafgtty = sys.stdin.isatty() and \ os.tcgetpgrp(sys.stdin.fileno()) == os.getpgrp() # check for special condition (empty command and stdin not a tty) if interactive and not stdin_isafgtty: # looks like interactive but stdin is not a tty: # switch to non-interactive + disable ssh pseudo-tty interactive = False # SSH: disable pseudo-tty allocation (-T) ssh_options = config.ssh_options or '' ssh_options += ' -T' config._set_main("ssh_options", ssh_options) if options.nostdin and interactive: parser.error("illegal option `--nostdin' in that case") # Force user_interaction if Clush._f_user_interaction for test purposes user_interaction = hasattr(sys.modules[__name__], '_f_user_interaction') if not options.nostdin: # Try user interaction: check for foreground ttys presence (ouput) stdout_isafgtty = sys.stdout.isatty() and \ os.tcgetpgrp(sys.stdout.fileno()) == os.getpgrp() user_interaction |= stdin_isafgtty and stdout_isafgtty display.vprint(VERB_DEBUG, "User interaction: %s" % user_interaction) if user_interaction: # Standard input is a terminal and we want to perform some user # interactions in the main thread (using blocking calls), so # we run cluster commands in a new ClusterShell Task (a new # thread is created). task = Task() # else: perform everything in the main thread # Handle special signal only when user_interaction is set task.set_default("USER_handle_SIGUSR1", user_interaction) task.excepthook = sys.excepthook task.set_default("USER_stdin_worker", not (sys.stdin.isatty() or \ options.nostdin or \ user_interaction)) display.vprint(VERB_DEBUG, "Create STDIN worker: %s" % \ task.default("USER_stdin_worker")) task.set_info("debug", config.verbosity >= VERB_DEBUG) task.set_info("fanout", config.fanout) if options.worker: try: if options.remote == 'no': task.set_default('local_worker', _load_workerclass(options.worker)) else: task.set_default('distant_worker', _load_workerclass(options.worker)) except (ImportError, AttributeError): msg = "ERROR: Could not load worker '%s'" % options.worker display.vprint_err(VERB_QUIET, msg) clush_exit(1, task) if options.topofile or task._default_tree_is_enabled(): if options.topofile: task.load_topology(options.topofile) if config.verbosity >= VERB_VERB: roots = len(task.topology.root.nodeset) gws = task.topology.inner_node_count() - roots msg = "enabling tree topology (%d gateways)" % gws print("clush: %s" % msg, file=sys.stderr) if options.grooming_delay: if config.verbosity >= VERB_VERB: msg = Display.COLOR_RESULT_FMT % ("Grooming delay: %f" % options.grooming_delay) print(msg, file=sys.stderr) task.set_info("grooming_delay", options.grooming_delay) elif options.rcopy: # By default, --rcopy should inhibit grooming task.set_info("grooming_delay", 0) if config.ssh_user: task.set_info("ssh_user", config.ssh_user) if config.ssh_path: task.set_info("ssh_path", config.ssh_path) if config.ssh_options: task.set_info("ssh_options", config.ssh_options) if config.scp_path: task.set_info("scp_path", config.scp_path) if config.scp_options: task.set_info("scp_options", config.scp_options) if config.rsh_path: task.set_info("rsh_path", config.rsh_path) if config.rcp_path: task.set_info("rcp_path", config.rcp_path) if config.rsh_options: task.set_info("rsh_options", config.rsh_options) # Set detailed timeout values task.set_info("connect_timeout", config.connect_timeout) task.set_info("command_timeout", config.command_timeout) # Enable stdout/stderr separation task.set_default("stderr", not options.gatherall) # Prevent reading from stdin? task.set_default("stdin", not options.nostdin) # Disable MsgTree buffering if not gathering outputs task.set_default("stdout_msgtree", display.gather or display.line_mode) # Always disable stderr MsgTree buffering task.set_default("stderr_msgtree", False) # Set timeout at worker level when command_timeout is defined. if config.command_timeout > 0: timeout = config.command_timeout else: timeout = -1 # Configure task custom status task.set_default("USER_interactive", interactive) task.set_default("USER_running", False) if (options.copy or options.rcopy) and not args: parser.error("--[r]copy option requires at least one argument") if options.copy: if not options.dest_path: # append '/' to clearly indicate a directory for tree mode options.dest_path = join(dirname(abspath(args[0])), '') op = "copy sources=%s dest=%s" % (args, options.dest_path) elif options.rcopy: if not options.dest_path: options.dest_path = dirname(abspath(args[0])) op = "rcopy sources=%s dest=%s" % (args, options.dest_path) else: op = "command=\"%s\"" % ' '.join(args) # print debug values (fanout value is get from the config object # and not task itself as set_info() is an asynchronous call. display.vprint(VERB_DEBUG, "clush: nodeset=%s fanout=%d [timeout " \ "conn=%.1f cmd=%.1f] %s" % (nodeset_base, config.fanout, config.connect_timeout, config.command_timeout, op)) if not task.default("USER_interactive"): if display.verbosity >= VERB_DEBUG and task.topology: print(Display.COLOR_RESULT_FMT % '-' * 15) print(Display.COLOR_RESULT_FMT % task.topology, end='') print(Display.COLOR_RESULT_FMT % '-' * 15) if options.copy: run_copy(task, args, options.dest_path, nodeset_base, timeout, options.preserve_flag, display) elif options.rcopy: run_rcopy(task, args, options.dest_path, nodeset_base, timeout, options.preserve_flag, display) else: run_command(task, ' '.join(args), nodeset_base, timeout, display, options.remote != 'no') if user_interaction: ttyloop(task, nodeset_base, timeout, display, options.remote != 'no') elif task.default("USER_interactive"): display.vprint_err(VERB_QUIET, \ "ERROR: interactive mode requires a tty") clush_exit(1, task) rc = 0 if options.maxrc: # Instead of clush return code, return commands retcode rc = task.max_retcode() if task.num_timeout() > 0: rc = 255 clush_exit(rc, task)
nodeset_base.difference_update(nodeset_exclude) if len(nodeset_base) < 1: parser.error('No node to run on.') # Set open files limit. set_fdlimit(config.fd_max, display) # # Task management # # check for clush interactive mode interactive = not len(args) and \ not (options.copy or options.rcopy) # check for foreground ttys presence (input) stdin_isafgtty = sys.stdin.isatty() and \ os.tcgetpgrp(sys.stdin.fileno()) == os.getpgrp() # check for special condition (empty command and stdin not a tty) if interactive and not stdin_isafgtty: # looks like interactive but stdin is not a tty: # switch to non-interactive + disable ssh pseudo-tty interactive = False # SSH: disable pseudo-tty allocation (-T) ssh_options = config.ssh_options or '' ssh_options += ' -T' config._set_main("ssh_options", ssh_options) if options.nostdin and interactive: parser.error("illegal option `--nostdin' in that case") # Force user_interaction if Clush._f_user_interaction for test purposes user_interaction = hasattr(sys.modules[__name__], '_f_user_interaction') if not options.nostdin: