main: add -p,--print-pid=FILE|FD

When specified, print our PID to the file, or FD, after everything has
started up.
This commit is contained in:
Daniel Eklöf 2020-02-04 18:28:09 +01:00
parent ef98df1a95
commit d4755d94b0
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
3 changed files with 69 additions and 6 deletions

View file

@ -6,4 +6,5 @@ _arguments \
'(-h --help)'{-h,--help}'[show help message and quit]' \
'(-b --backend)'{-b,--backend}'[backend to use (default: auto)]:backend:(xcb wayland auto)' \
'(-c --config)'{-c,--config}'[alternative configuration file]:filename:_files' \
'(-C --validate)'{-C,--validate}'[verify configuration then quit]'
'(-C --validate)'{-C,--validate}'[verify configuration then quit]' \
'(-p --print-pid)'{-p,--print-pid}'[print PID to this file or FD when up and running]:pidfile:_files'

View file

@ -8,21 +8,26 @@ yambar - modular status panel for X11 and Wayland
# OPTIONS
*-b, --backend={xcb,wayland,auto}*
*-b*,*--backend*={*xcb*,*wayland*,*auto*}
Backend to use. The default is *auto*. In this mode, yambar will
look for the environment variable _WAYLAND\_DISPLAY_, and if
available, use the *Wayland* backend. If not, the *XCB* backend is
used.
*-c, --config=FILE*
*-c*,*--config*=_FILE_
Use an alternative configuration file instead of the default one.
*-C, --validate*
*-C*,*--validate*
Verify the configuration and then quit. If no errors are detected,
nothing is printed and the exit code is 0. If there are errors,
these are printed on stdout and the exit code is non-zero.
*-v, --version*
*-p*,*--print-pid*=_FILE_|_FD_
Print PID to this file, or FD, when successfully started. The file
(or FD) is closed immediately after writing the PID. When a _FILE_
as been specified, the file is unlinked when yambar exits.
*-v*,*--version*
Show the version number and quit
# DESCRIPTION

59
main.c
View file

@ -10,10 +10,12 @@
#include <threads.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/eventfd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pwd.h>
#include "bar/bar.h"
@ -128,9 +130,47 @@ print_usage(const char *prog_name)
printf(" -b,--backend={xcb,wayland,auto} backend to use (default: auto)\n"
" -c,--config=FILE alternative configuration file\n"
" -C,--validate verify configuration then quit\n"
" -p,--print-pid=FILE|FD print PID to file or FD\n"
" -v,--version print f00sel version and quit\n");
}
static bool
print_pid(const char *pid_file, bool *unlink_at_exit)
{
LOG_DBG("printing PID to %s", pid_file);
errno = 0;
char *end;
int pid_fd = strtoul(pid_file, &end, 10);
if (errno != 0 || *end != '\0') {
if ((pid_fd = open(pid_file,
O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
LOG_ERRNO("%s: failed to open", pid_file);
return false;
} else
*unlink_at_exit = true;
}
if (pid_fd >= 0) {
char pid[32];
snprintf(pid, sizeof(pid), "%u\n", getpid());
ssize_t bytes __attribute((unused)) = write(pid_fd, pid, strlen(pid));
close(pid_fd);
if (bytes < 0) {
LOG_ERRNO("failed to write PID to FD=%u", pid_fd);
return false;
}
LOG_DBG("wrote %zd bytes to FD=%d", bytes, pid_fd);
return true;
} else
return false;
}
int
main(int argc, char *const *argv)
{
@ -140,17 +180,21 @@ main(int argc, char *const *argv)
{"backend", required_argument, 0, 'b'},
{"config", required_argument, 0, 'c'},
{"validate", no_argument, 0, 'C'},
{"print-pid", required_argument, 0, 'p'},
{"version", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{NULL, no_argument, 0, 0},
};
bool unlink_pid_file = false;
const char *pid_file = NULL;
bool verify_config = false;
char *config_path = NULL;
enum bar_backend backend = BAR_BACKEND_AUTO;
while (true) {
int c = getopt_long(argc, argv, ":b:c:Cvh", longopts, NULL);
int c = getopt_long(argc, argv, ":b:c:Cp:vh", longopts, NULL);
if (c == -1)
break;
@ -185,6 +229,10 @@ main(int argc, char *const *argv)
verify_config = true;
break;
case 'p':
pid_file = optarg;
break;
case 'v':
printf("yambar version %s\n", YAMBAR_VERSION);
return EXIT_SUCCESS;
@ -251,6 +299,11 @@ main(int argc, char *const *argv)
/* Now unblock. We should be only thread receiving SIGINT */
pthread_sigmask(SIG_UNBLOCK, &signal_mask, NULL);
if (pid_file != NULL) {
if (!print_pid(pid_file, &unlink_pid_file))
goto done;
}
while (!aborted) {
struct pollfd fds[] = {{.fd = abort_fd, .events = POLLIN}};
int r __attribute__((unused)) = poll(fds, 1, -1);
@ -267,6 +320,7 @@ main(int argc, char *const *argv)
if (aborted)
LOG_INFO("aborted: %s (%d)", strsignal(aborted), aborted);
done:
/* Signal abort to other threads */
if (write(abort_fd, &(uint64_t){1}, sizeof(uint64_t)) != sizeof(uint64_t))
LOG_ERRNO("failed to signal abort to threads");
@ -278,5 +332,8 @@ main(int argc, char *const *argv)
bar->destroy(bar);
close(abort_fd);
if (unlink_pid_file)
unlink(pid_file);
return res;
}