speedwm-personal/main.c
2022-12-18 21:16:00 +01:00

179 lines
3.3 KiB
C

/* This contains the code for ending speedwm, along with memory allocation and IPC support.
* See LICENSE file for copyright and license details.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "toggle.h"
#ifdef USEIPC
#include <errno.h>
#include <sys/stat.h>
#endif
#include "main.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);
}
void *
ecalloc(size_t nmemb, size_t size)
{
void *p;
if (!(p = calloc(nmemb, size)))
die("calloc:");
return p;
}
#if USEIPC
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;
}
#endif