4a230d362a
This patch currently supports the following requests: * Run custom commands with arguments (similar to key bind functions) * Get monitor properties * Get all available layouts * Get available tags * Get client properties * Subscribe to tag change, client focus change, and layout change, monitor focus change, focused title change, and client state change events This patch includes a dwm-msg cli program that supports all of the above requests for easy integration into shell scripts. The messages are sent in a JSON format to promote integration to increase scriptability in languages like Python/JavaScript. The patch requires YAJL for JSON parsing and a system with epoll support. Portability is planned to be increased in the future. This patch is best applied after all other patches to avoid merge conflicts. For more info on the IPC implementation and how to send/receive messages, documentation can be found at https://github.com/mihirlad55/dwm-ipc
172 lines
3.1 KiB
C
172 lines
3.1 KiB
C
/* See LICENSE file for copyright and license details. */
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "util.h"
|
|
|
|
void
|
|
die(const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
vfprintf(stderr, fmt, ap);
|
|
va_end(ap);
|
|
|
|
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
|
|
fputc(' ', stderr);
|
|
perror(NULL);
|
|
} else {
|
|
fputc('\n', stderr);
|
|
}
|
|
|
|
exit(1);
|
|
}
|
|
|
|
int
|
|
normalizepath(const char *path, char **normal)
|
|
{
|
|
size_t len = strlen(path);
|
|
*normal = (char *)malloc((len + 1) * sizeof(char));
|
|
const char *walk = path;
|
|
const char *match;
|
|
size_t newlen = 0;
|
|
|
|
while ((match = strchr(walk, '/'))) {
|
|
// Copy everything between match and walk
|
|
strncpy(*normal + newlen, walk, match - walk);
|
|
newlen += match - walk;
|
|
walk += match - walk;
|
|
|
|
// Skip all repeating slashes
|
|
while (*walk == '/')
|
|
walk++;
|
|
|
|
// If not last character in path
|
|
if (walk != path + len)
|
|
(*normal)[newlen++] = '/';
|
|
}
|
|
|
|
(*normal)[newlen++] = '\0';
|
|
|
|
// Copy remaining path
|
|
strcat(*normal, walk);
|
|
newlen += strlen(walk);
|
|
|
|
*normal = (char *)realloc(*normal, newlen * sizeof(char));
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
parentdir(const char *path, char **parent)
|
|
{
|
|
char *normal;
|
|
char *walk;
|
|
|
|
normalizepath(path, &normal);
|
|
|
|
// Pointer to last '/'
|
|
if (!(walk = strrchr(normal, '/'))) {
|
|
free(normal);
|
|
return -1;
|
|
}
|
|
|
|
// Get path up to last '/'
|
|
size_t len = walk - normal;
|
|
*parent = (char *)malloc((len + 1) * sizeof(char));
|
|
|
|
// Copy path up to last '/'
|
|
strncpy(*parent, normal, len);
|
|
// Add null char
|
|
(*parent)[len] = '\0';
|
|
|
|
free(normal);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
mkdirp(const char *path)
|
|
{
|
|
char *normal;
|
|
char *walk;
|
|
size_t normallen;
|
|
|
|
normalizepath(path, &normal);
|
|
normallen = strlen(normal);
|
|
walk = normal;
|
|
|
|
while (walk < normal + normallen + 1) {
|
|
// Get length from walk to next /
|
|
size_t n = strcspn(walk, "/");
|
|
|
|
// Skip path /
|
|
if (n == 0) {
|
|
walk++;
|
|
continue;
|
|
}
|
|
|
|
// Length of current path segment
|
|
size_t curpathlen = walk - normal + n;
|
|
char curpath[curpathlen + 1];
|
|
struct stat s;
|
|
|
|
// Copy path segment to stat
|
|
strncpy(curpath, normal, curpathlen);
|
|
strcpy(curpath + curpathlen, "");
|
|
int res = stat(curpath, &s);
|
|
|
|
if (res < 0) {
|
|
if (errno == ENOENT) {
|
|
DEBUG("Making directory %s\n", curpath);
|
|
if (mkdir(curpath, 0700) < 0) {
|
|
fprintf(stderr, "Failed to make directory %s\n", curpath);
|
|
perror("");
|
|
free(normal);
|
|
return -1;
|
|
}
|
|
} else {
|
|
fprintf(stderr, "Error statting directory %s\n", curpath);
|
|
perror("");
|
|
free(normal);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// Continue to next path segment
|
|
walk += n;
|
|
}
|
|
|
|
free(normal);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
nullterminate(char **str, size_t *len)
|
|
{
|
|
if ((*str)[*len - 1] == '\0')
|
|
return 0;
|
|
|
|
(*len)++;
|
|
*str = (char*)realloc(*str, *len * sizeof(char));
|
|
(*str)[*len - 1] = '\0';
|
|
|
|
return 0;
|
|
}
|
|
|
|
void *
|
|
ecalloc(size_t nmemb, size_t size)
|
|
{
|
|
void *p;
|
|
|
|
if (!(p = calloc(nmemb, size)))
|
|
die("calloc:");
|
|
return p;
|
|
}
|