2021-03-17 18:10:47 +01:00
|
|
|
#ifdef __unix__
|
|
|
|
|
2021-03-17 16:58:44 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "xrdb_parse.h"
|
|
|
|
|
|
|
|
extern char **environ;
|
|
|
|
|
|
|
|
static int join_path(char buf[], int buf_size, const char *path, const char *name) {
|
|
|
|
const char *path_delim = strchr(path, ':');
|
|
|
|
if (!path_delim) {
|
|
|
|
path_delim = path + strlen(path);
|
|
|
|
}
|
|
|
|
const int path_len = path_delim - path, name_len = strlen(name);
|
|
|
|
if (buf_size < path_len + 1 + name_len + 1) return -1;
|
|
|
|
memcpy(buf, path, path_len);
|
|
|
|
buf[path_len] = '/';
|
|
|
|
memcpy(buf + path_len + 1, name, name_len + 1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int xrdb_popen (int *pid_ptr) {
|
|
|
|
int fd[2];
|
|
|
|
|
2021-03-17 18:29:50 +01:00
|
|
|
if (pipe(fd) != 0) return -1;
|
2021-03-17 18:10:47 +01:00
|
|
|
int read_fd = fd[0];
|
|
|
|
int write_fd = fd[1];
|
2021-03-17 16:58:44 +01:00
|
|
|
|
|
|
|
int pid = fork();
|
|
|
|
if (pid == 0) {
|
|
|
|
close(read_fd);
|
|
|
|
dup2(write_fd, STDOUT_FILENO);
|
|
|
|
close(write_fd);
|
2021-03-17 18:10:47 +01:00
|
|
|
char *path = getenv("PATH");
|
2021-03-17 16:58:44 +01:00
|
|
|
char xrdb_filename[256];
|
|
|
|
while (path) {
|
|
|
|
char *xrgb_argv[3] = {"xrdb", "-query", NULL};
|
|
|
|
if (join_path(xrdb_filename, 256, path, "xrdb") == 0) {
|
|
|
|
execve(xrdb_filename, xrgb_argv, environ);
|
|
|
|
}
|
|
|
|
path = strchr(path, ':');
|
|
|
|
if (path) {
|
|
|
|
path++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*pid_ptr = pid;
|
|
|
|
close(write_fd);
|
|
|
|
return read_fd;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int xrdb_try_dpi_match(const char *line, int len) {
|
2021-03-18 10:00:03 +01:00
|
|
|
if (len >= 8 && strncmp(line, "Xft.dpi:", 8) == 0) {
|
|
|
|
for (line += 8; *line && (*line == '\t' || *line == ' '); line++) { }
|
|
|
|
int dpi = 0;
|
|
|
|
for ( ; *line >= '0' && *line <= '9'; line++) {
|
|
|
|
dpi = dpi * 10 + ((int) (*line) - (int) '0');
|
|
|
|
}
|
|
|
|
return dpi;
|
2021-03-17 16:58:44 +01:00
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-03-18 10:06:01 +01:00
|
|
|
static void xrdb_complete_reading(int read_fd, char *buf, size_t buf_size) {
|
2021-03-17 16:58:44 +01:00
|
|
|
while (1) {
|
2021-03-18 10:06:01 +01:00
|
|
|
int nr = read(read_fd, buf, buf_size);
|
2021-03-17 16:58:44 +01:00
|
|
|
if (nr <= 0) return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-18 10:06:01 +01:00
|
|
|
#define XRDB_READ_BUF_SIZE 256
|
2021-03-17 16:58:44 +01:00
|
|
|
static int xrdb_parse_for_dpi(int read_fd) {
|
|
|
|
char buf[XRDB_READ_BUF_SIZE];
|
2021-03-18 09:32:52 +01:00
|
|
|
char buf_remaining = 0;
|
2021-03-17 16:58:44 +01:00
|
|
|
while (1) {
|
2021-03-18 09:32:52 +01:00
|
|
|
int nr = read(read_fd, buf + buf_remaining, XRDB_READ_BUF_SIZE - buf_remaining);
|
2021-03-17 16:58:44 +01:00
|
|
|
if (nr > 0) {
|
2021-03-18 09:32:52 +01:00
|
|
|
const char * const buf_limit = buf + nr + buf_remaining;
|
2021-03-17 16:58:44 +01:00
|
|
|
char *line_start = buf;
|
|
|
|
while (line_start < buf_limit) {
|
|
|
|
char *nlptr = line_start;
|
|
|
|
while (nlptr < buf_limit && *nlptr != '\n') {
|
|
|
|
nlptr++;
|
|
|
|
}
|
|
|
|
if (nlptr < buf_limit) {
|
|
|
|
int dpi_read = xrdb_try_dpi_match(line_start, nlptr - line_start);
|
|
|
|
if (dpi_read > 0) {
|
2021-03-18 10:06:01 +01:00
|
|
|
xrdb_complete_reading(read_fd, buf, XRDB_READ_BUF_SIZE);
|
2021-03-17 16:58:44 +01:00
|
|
|
return dpi_read;
|
|
|
|
}
|
2021-03-17 18:10:47 +01:00
|
|
|
/* doesn't match: position after newline to search again */
|
2021-03-17 16:58:44 +01:00
|
|
|
line_start = nlptr + 1;
|
|
|
|
} else {
|
|
|
|
/* No newline found: copy the remaining part at the beginning of buf
|
|
|
|
and read again from file descriptor. */
|
2021-03-18 09:32:52 +01:00
|
|
|
buf_remaining = buf_limit - line_start;
|
|
|
|
if (buf_remaining >= XRDB_READ_BUF_SIZE) {
|
2021-03-17 16:58:44 +01:00
|
|
|
/* Line is too long for the buffer: skip. */
|
2021-03-18 09:32:52 +01:00
|
|
|
buf_remaining = 0;
|
2021-03-17 16:58:44 +01:00
|
|
|
} else {
|
2021-03-18 10:00:03 +01:00
|
|
|
memmove(buf, line_start, buf_remaining);
|
2021-03-17 16:58:44 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2021-03-18 09:32:52 +01:00
|
|
|
if (nr == 0 && buf_remaining > 0) {
|
|
|
|
int dpi_read = xrdb_try_dpi_match(buf, buf_remaining);
|
2021-03-17 16:58:44 +01:00
|
|
|
if (dpi_read > 0) {
|
|
|
|
return dpi_read;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int xrdb_find_dpi() {
|
|
|
|
int xrdb_pid;
|
|
|
|
int read_fd = xrdb_popen(&xrdb_pid);
|
|
|
|
if (read_fd >= 0) {
|
|
|
|
int dpi_read = xrdb_parse_for_dpi(read_fd);
|
|
|
|
int child_status;
|
|
|
|
waitpid(xrdb_pid, &child_status, 0);
|
|
|
|
close(read_fd);
|
|
|
|
return dpi_read;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
2021-03-17 18:10:47 +01:00
|
|
|
|
|
|
|
#endif
|