mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 14:18:26 +02:00
Run the child process
This commit is contained in:
@@ -2,15 +2,11 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
import os
|
|
||||||
import fcntl
|
|
||||||
import termios
|
|
||||||
import struct
|
|
||||||
|
|
||||||
from PyQt5.QtCore import QObject
|
from PyQt5.QtCore import QObject
|
||||||
|
|
||||||
from .screen import Screen
|
from .screen import Screen
|
||||||
from .term import TerminalWidget
|
from .term import TerminalWidget
|
||||||
|
from .utils import resize_pty, hangup
|
||||||
|
|
||||||
|
|
||||||
class Boss(QObject):
|
class Boss(QObject):
|
||||||
@@ -20,7 +16,7 @@ class Boss(QObject):
|
|||||||
self.screen = Screen(opts, parent=self)
|
self.screen = Screen(opts, parent=self)
|
||||||
self.term = TerminalWidget(opts, self.screen.linebuf, parent)
|
self.term = TerminalWidget(opts, self.screen.linebuf, parent)
|
||||||
self.term.relayout_lines.connect(self.relayout_lines)
|
self.term.relayout_lines.connect(self.relayout_lines)
|
||||||
self.master_fd, self.slave_fd = os.openpty()
|
resize_pty(self.screen.columns, self.screen.lines)
|
||||||
|
|
||||||
def apply_opts(self, opts):
|
def apply_opts(self, opts):
|
||||||
self.screen.apply_opts(opts)
|
self.screen.apply_opts(opts)
|
||||||
@@ -28,9 +24,9 @@ class Boss(QObject):
|
|||||||
|
|
||||||
def relayout_lines(self, previous, cells_per_line, previousl, lines_per_screen):
|
def relayout_lines(self, previous, cells_per_line, previousl, lines_per_screen):
|
||||||
self.screen.resize(lines_per_screen, cells_per_line)
|
self.screen.resize(lines_per_screen, cells_per_line)
|
||||||
fcntl.ioctl(self.master_fd, termios.TIOCSWINSZ, struct.pack('4H', cells_per_line, lines_per_screen, 0, 0))
|
resize_pty(cells_per_line, lines_per_screen)
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
os.close(self.slave_fd), os.close(self.master_fd)
|
|
||||||
del self.master_fd
|
del self.master_fd
|
||||||
del self.slave_fd
|
del self.slave_fd
|
||||||
|
hangup()
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox
|
|||||||
from .config import load_config, validate_font
|
from .config import load_config, validate_font
|
||||||
from .constants import appname, str_version, config_dir
|
from .constants import appname, str_version, config_dir
|
||||||
from .boss import Boss
|
from .boss import Boss
|
||||||
|
from .utils import fork_child
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
@@ -70,7 +71,7 @@ def option_parser():
|
|||||||
a('--class', default=appname, dest='cls', help=_('Set the class part of the WM_CLASS property'))
|
a('--class', default=appname, dest='cls', help=_('Set the class part of the WM_CLASS property'))
|
||||||
a('--config', default=os.path.join(config_dir, 'kitty.conf'), help=_('Specify a path to the config file to use'))
|
a('--config', default=os.path.join(config_dir, 'kitty.conf'), help=_('Specify a path to the config file to use'))
|
||||||
a('--cmd', '-c', default=None, help=_('Run python code in the kitty context'))
|
a('--cmd', '-c', default=None, help=_('Run python code in the kitty context'))
|
||||||
a('--exec', '-e', default=pwd.getpwuid(os.geteuid()).pw_shell or '/bin/sh', help=_('Run the specified command instead of the shell'))
|
a('--exec', '-e', dest='child', default=pwd.getpwuid(os.geteuid()).pw_shell or '/bin/sh', help=_('Run the specified command instead of the shell'))
|
||||||
a('-d', '--directory', default='.', help=_('Change to the specified directory when launching'))
|
a('-d', '--directory', default='.', help=_('Change to the specified directory when launching'))
|
||||||
a('--version', action='version', version='{} {} by Kovid Goyal'.format(appname, '.'.join(str_version)))
|
a('--version', action='version', version='{} {} by Kovid Goyal'.format(appname, '.'.join(str_version)))
|
||||||
return parser
|
return parser
|
||||||
@@ -81,8 +82,10 @@ def main():
|
|||||||
if args.cmd:
|
if args.cmd:
|
||||||
exec(args.cmd)
|
exec(args.cmd)
|
||||||
return
|
return
|
||||||
|
# Ensure the child process gets no environment from Qt
|
||||||
opts = load_config(args.config)
|
opts = load_config(args.config)
|
||||||
os.chdir(args.directory)
|
fork_child(args.child, args.directory, opts)
|
||||||
|
|
||||||
QApplication.setAttribute(Qt.AA_DisableHighDpiScaling, True)
|
QApplication.setAttribute(Qt.AA_DisableHighDpiScaling, True)
|
||||||
app = QApplication([appname])
|
app = QApplication([appname])
|
||||||
app.setOrganizationName(args.cls)
|
app.setOrganizationName(args.cls)
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import os
|
||||||
|
import termios
|
||||||
|
import struct
|
||||||
|
import shlex
|
||||||
|
import fcntl
|
||||||
|
import signal
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
|
|
||||||
from PyQt5.QtGui import QFontMetrics
|
from PyQt5.QtGui import QFontMetrics
|
||||||
@@ -24,3 +30,48 @@ def set_current_font_metrics(fm: QFontMetrics, cw: int) -> None:
|
|||||||
global current_font_metrics, cell_width
|
global current_font_metrics, cell_width
|
||||||
current_font_metrics, cell_width = fm, cw
|
current_font_metrics, cell_width = fm, cw
|
||||||
wcwidth.cache_clear()
|
wcwidth.cache_clear()
|
||||||
|
|
||||||
|
|
||||||
|
def create_pty():
|
||||||
|
if not hasattr(create_pty, 'master'):
|
||||||
|
create_pty.master, create_pty.slave = os.openpty()
|
||||||
|
fcntl.fcntl(create_pty.slave, fcntl.F_SETFD, fcntl.fcntl(create_pty.slave, fcntl.F_GETFD) & ~fcntl.FD_CLOEXEC)
|
||||||
|
return create_pty.master, create_pty.slave
|
||||||
|
|
||||||
|
|
||||||
|
def fork_child(cmd, cwd, opts):
|
||||||
|
argv = shlex.split(cmd)
|
||||||
|
master, slave = create_pty()
|
||||||
|
pid = os.fork()
|
||||||
|
if pid == 0:
|
||||||
|
try:
|
||||||
|
os.chdir(cwd)
|
||||||
|
except EnvironmentError:
|
||||||
|
os.chdir('/')
|
||||||
|
os.setsid()
|
||||||
|
for i in range(3):
|
||||||
|
os.dup2(slave, i)
|
||||||
|
os.close(slave), os.close(master)
|
||||||
|
# Establish the controlling terminal (see man 7 credentials)
|
||||||
|
os.close(os.open(os.ttyname(1), os.O_RDWR))
|
||||||
|
os.environ['TERM'] = opts.term
|
||||||
|
os.environ['COLORTERM'] = 'truecolor'
|
||||||
|
os.execvp(argv[0], argv)
|
||||||
|
else:
|
||||||
|
os.close(slave)
|
||||||
|
fork_child.pid = pid
|
||||||
|
return pid
|
||||||
|
|
||||||
|
|
||||||
|
def resize_pty(w, h):
|
||||||
|
master = create_pty()[0]
|
||||||
|
fcntl.ioctl(master, termios.TIOCSWINSZ, struct.pack('4H', w, h, 0, 0))
|
||||||
|
|
||||||
|
|
||||||
|
def hangup():
|
||||||
|
if hasattr(fork_child, 'pid'):
|
||||||
|
pid = fork_child.pid
|
||||||
|
del fork_child.pid
|
||||||
|
pgrp = os.getpgid(pid)
|
||||||
|
os.killpg(pgrp, signal.SIGHUP)
|
||||||
|
os.close(create_pty()[0])
|
||||||
|
|||||||
Reference in New Issue
Block a user