diff --git a/kittens/panel/main.py b/kittens/panel/main.py index 9549f64c1..741773d46 100644 --- a/kittens/panel/main.py +++ b/kittens/panel/main.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # License: GPL v3 Copyright: 2018, Kovid Goyal +import os import sys from collections.abc import Callable from contextlib import suppress @@ -189,6 +190,10 @@ Detach from the controlling terminal, if any, running in an independent child pr the parent process exits immediately. +--detached-log +Path to a log file to store STDOUT/STDERR when using :option:`--detach` + + --debug-rendering type=bool-set For internal debugging use. @@ -346,7 +351,7 @@ def main(sys_args: list[str]) -> None: args, items = parse_panel_args(sys_args[1:]) if args.detach: from kitty.utils import detach - detach() + detach(log_file=args.detached_log or os.devnull) sys.argv = ['kitty'] if args.debug_rendering: sys.argv.append('--debug-rendering') diff --git a/kitty/data-types.c b/kitty/data-types.c index bff95c9ad..5922b98d4 100644 --- a/kitty/data-types.c +++ b/kitty/data-types.c @@ -67,12 +67,13 @@ process_group_map(PyObject *self UNUSED, PyObject *args UNUSED) { #endif static PyObject* -redirect_std_streams(PyObject UNUSED *self, PyObject *args) { - char *devnull = NULL; - if (!PyArg_ParseTuple(args, "s", &devnull)) return NULL; - if (freopen(devnull, "r", stdin) == NULL) return PyErr_SetFromErrno(PyExc_OSError); - if (freopen(devnull, "w", stdout) == NULL) return PyErr_SetFromErrno(PyExc_OSError); - if (freopen(devnull, "w", stderr) == NULL) return PyErr_SetFromErrno(PyExc_OSError); +redirect_std_streams(PyObject UNUSED *self, PyObject *args, PyObject *kw) { + char *in = "", *out = "", *err = ""; + static const char* kwlist[] = {"stdin", "stdout", "stderr", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kw, "|sss", (char**)kwlist, &in, &out, &err)) return NULL; + if (in[0] && freopen(in, "r", stdin) == NULL) return PyErr_SetFromErrno(PyExc_OSError); + if (out[0] && freopen(out, "a", stdout) == NULL) return PyErr_SetFromErrno(PyExc_OSError); + if (out[0] && freopen(err, "a", stderr) == NULL) return PyErr_SetFromErrno(PyExc_OSError); Py_RETURN_NONE; } @@ -663,7 +664,7 @@ static PyMethodDef module_methods[] = { {"char_props_for", py_char_props_for, METH_O, ""}, {"split_into_graphemes", (PyCFunction)split_into_graphemes, METH_O, ""}, {"thread_write", (PyCFunction)cm_thread_write, METH_VARARGS, ""}, - {"redirect_std_streams", (PyCFunction)redirect_std_streams, METH_VARARGS, ""}, + {"redirect_std_streams", (PyCFunction)(void (*) (void))(redirect_std_streams), METH_VARARGS | METH_KEYWORDS, NULL}, {"locale_is_valid", (PyCFunction)locale_is_valid, METH_VARARGS, ""}, {"shm_open", (PyCFunction)py_shm_open, METH_VARARGS, ""}, {"shm_unlink", (PyCFunction)py_shm_unlink, METH_VARARGS, ""}, diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index 518c1f910..6797bba6c 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -335,7 +335,7 @@ def log_error_string(s: str) -> None: pass -def redirect_std_streams(devnull: str) -> None: +def redirect_std_streams(stdin: str = '', stdout: str = '', stderr: str = '') -> None: pass diff --git a/kitty/utils.py b/kitty/utils.py index 634d999e4..b1882c089 100644 --- a/kitty/utils.py +++ b/kitty/utils.py @@ -257,7 +257,7 @@ def open_url(url: str, program: str | list[str] = 'default', cwd: str | None = N return open_cmd(command_for_open(program), url, cwd=cwd, extra_env=extra_env) -def detach(fork: bool = True, setsid: bool = True, redirect: bool = True) -> None: +def detach(fork: bool = True, setsid: bool = True, redirect: bool = True, log_file: str = os.devnull) -> None: if fork: # Detach from the controlling process. if os.fork() != 0: @@ -266,7 +266,7 @@ def detach(fork: bool = True, setsid: bool = True, redirect: bool = True) -> Non os.setsid() if redirect: from .fast_data_types import redirect_std_streams - redirect_std_streams(os.devnull) + redirect_std_streams(stdin=os.devnull, stdout=log_file, stderr=log_file) def init_startup_notification_x11(window_handle: int, startup_id: str | None = None) -> Optional['StartupCtx']: