add -q option to disable printing to stdout

Printing the status to stdout can be undesirable, as blocking pipes with
a filled buffer … block.  Because of that, when using -s for starting a
process not reading its stdin, such as service managers, after some
usage dwl will freeze.
This commit is contained in:
Humm 2021-10-06 17:31:02 +02:00
parent 96ce40cfe9
commit a56c88b15b
2 changed files with 23 additions and 11 deletions

View File

@ -56,6 +56,8 @@ When dwl is run with no arguments, it will launch the server and begin handling
If you would like to run a script or command automatically at startup, you can specify the command using the `-s` option. The argument to this option will be parsed as a shell command (using `sh -c`) and can serve a similar function to `.xinitrc`. Unlike `.xinitrc`, the display server will not shut down when this process terminates. Instead, as dwl is shutting down, it will send this process a SIGTERM and wait for it to terminate (if it hasn't already). This makes it ideal for execing into a user service manager like [s6](https://skarnet.org/software/s6/), [anopa](https://jjacky.com/anopa/), [runit](http://smarden.org/runit/faq.html#userservices), or [`systemd --user`](https://wiki.archlinux.org/title/Systemd/User).
While dwl is running, it prints status information to stdout or, if `-s` is given, to a pipe connected to stdin of that process. That is disabled by the `-q` option, which closes the child process's stdin instead.
Note: The `-s` command is run as a *child process* of dwl, which means that it does not have the ability to affect the environment of dwl or of any processes that it spawns. If you need to set environment variables that affect the entire dwl session (such as `XDG_RUNTIME_DIR` in the note below), these must be set prior to running dwl.
Note: Wayland requires a valid `XDG_RUNTIME_DIR`, which is usually set up by a session manager such as `elogind` or `systemd-logind`. If your system doesn't do this automatically, you will need to configure it prior to launching `dwl`, e.g.:

32
dwl.c
View File

@ -267,7 +267,7 @@ static void renderclients(Monitor *m, struct timespec *now);
static void renderlayer(struct wl_list *layer_surfaces, struct timespec *now);
static void rendermon(struct wl_listener *listener, void *data);
static void resize(Client *c, int x, int y, int w, int h, int interact);
static void run(char *startup_cmd);
static void run(char *startup_cmd, int quiet);
static void scalebox(struct wlr_box *box, float scale);
static Client *selclient(void);
static void setcursor(struct wl_listener *listener, void *data);
@ -1804,7 +1804,7 @@ resize(Client *c, int x, int y, int w, int h, int interact)
}
void
run(char *startup_cmd)
run(char *startup_cmd, int quiet)
{
pid_t startup_pid = -1;
@ -1817,19 +1817,27 @@ run(char *startup_cmd)
/* Now that the socket exists, run the startup command */
if (startup_cmd) {
int piperw[2];
pipe(piperw);
if (!quiet)
pipe(piperw);
startup_pid = fork();
if (startup_pid < 0)
EBARF("startup: fork");
if (startup_pid == 0) {
dup2(piperw[0], STDIN_FILENO);
close(piperw[1]);
if (!quiet) {
dup2(piperw[0], STDIN_FILENO);
close(piperw[1]);
} else
close(STDIN_FILENO);
execl("/bin/sh", "/bin/sh", "-c", startup_cmd, NULL);
EBARF("startup: execl");
}
dup2(piperw[1], STDOUT_FILENO);
close(piperw[0]);
if (!quiet) {
dup2(piperw[1], STDOUT_FILENO);
close(piperw[0]);
}
}
if (quiet)
close(STDOUT_FILENO);
/* If nobody is reading the status output, don't terminate */
signal(SIGPIPE, SIG_IGN);
printstatus();
@ -2583,11 +2591,13 @@ int
main(int argc, char *argv[])
{
char *startup_cmd = NULL;
int c;
int c, q = 0;
while ((c = getopt(argc, argv, "s:h")) != -1) {
while ((c = getopt(argc, argv, "qs:h")) != -1) {
if (c == 's')
startup_cmd = optarg;
else if (c == 'q')
++q;
else
goto usage;
}
@ -2599,10 +2609,10 @@ main(int argc, char *argv[])
if (!getenv("XDG_RUNTIME_DIR"))
BARF("XDG_RUNTIME_DIR must be set");
setup();
run(startup_cmd);
run(startup_cmd, q);
cleanup();
return EXIT_SUCCESS;
usage:
BARF("Usage: %s [-s startup command]", argv[0]);
BARF("Usage: %s [-q] [-s startup command]", argv[0]);
}