wm: ticl

ref: c280d99d0354f96611acaa905c46c3eee4e3a37b
dir: /util.c/

View raw version
/*
 * This work is dedicated to the public domain.
 * See COPYING file for more information.
 */

#include <sys/socket.h>
#include <sys/stat.h>

#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define FALSE	0
#define TRUE	1

#ifdef __gnu_linux__
char *strlcpy(char *dst, const char *src, size_t n)
{
	return strncpy(dst, src, n);
}
#endif

void
print_log(int level, FILE *stream, const char *fmt, va_list arg)
{
	size_t	len;

	if (level > LOG_LEVEL)
		return;

	vfprintf(stream, fmt, arg);
	len = strlen(fmt);
	if (len && fmt[len-1] == ':')
		fprintf(stream, " %s\n", strerror(errno));
	else
		fprintf(stream, "\n");
}

void
debug(int level, const char *fmt, ...)
{
	va_list arg;
	va_start(arg, fmt);
	print_log(level, stdout, fmt, arg);
	va_end(arg);
}

void
warnf(const char *fmt, ...)
{
	va_list arg;
	fprintf(stderr, "warn: ");
	va_start(arg, fmt);
	print_log(0, stderr, fmt, arg);
	va_end(arg);
}

void
fatal(const char *fmt, ...)
{
	va_list arg;
	fprintf(stderr, "error: ");
	va_start(arg, fmt);
	print_log(0, stderr, fmt, arg);
	va_end(arg);
	exit(1);
}

void *
emalloc(size_t size)
{
	void *p;
	if ((p = malloc(size)) == NULL)
		fatal("malloc:");
	return p;
}

void *
ecalloc(size_t nmemb, size_t size)
{
	void *p;
	if ((p = calloc(nmemb, size)) == NULL)
		fatal("calloc:");
	return p;
}

void *
erealloc(void *ptr, size_t size)
{
	void *p;
	if ((p = realloc(ptr, size)) == NULL)
		fatal("realloc:");
	return p;
}

char*
split(char **str, char ch)
{
	char *token = *str;

	if (**str == '\0') return *str;

	while (**str != ch && **str != '\0')
		(*str)++;
	if (**str == '\0')
		return token;
	**str = '\0';
	(*str)++;
	while(**str == ch && **str != '\0')
		(*str)++;
	return token;
}

int
dial(char *host, char *port)
{
	static struct addrinfo hints, *res = NULL, *res0;
	int fd = -1, r;

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;

	if ((r = getaddrinfo(host, port, &hints, &res0)) != 0) {
		warnf("getaddrinfo: %s", gai_strerror(r));
		return -1;
	}
	for (res = res0; res != NULL; res = res->ai_next) {
		fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (fd == -1) {
			warnf("socket:");
			continue;
		}
		if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
			warnf("fnctl:");
			continue;
		}
		if ((connect(fd, res->ai_addr, res->ai_addrlen) == -1) &&
		    (errno == EINPROGRESS))
			break;
		warnf("connect:");
		close(fd);
		fd = -1;
	}
	if (fd == -1)
		warnf("failed to connect to %s", host);

	freeaddrinfo(res0);
	return fd;
}

int
fifo_open(char *path)
{
	struct stat st;
	int fd;

	/* make a fifo file if it doesn't exists */
	if (lstat(path, &st) != -1) {
		if (!(st.st_mode & S_IFIFO))
			fatal("%s: not a fifo file", path);
	} else if (mkfifo(path, S_IRWXU) == -1) {
		fatal("mkfifo: %s:", path);
	}

	fd = open(path, O_RDONLY | O_NONBLOCK, 0);
	if (fd == -1)
		fatal("open: %s:", path);

	return fd;
}

ssize_t
readline(int fd, char *buffer, size_t size)
{
	size_t i = 0;
	char c;
	ssize_t l;

	while (i < size) {
		l = read(fd, &c, sizeof(char));
		if (l == -1 && errno == EAGAIN)
			continue;
		else if (l == -1 || l == 0)
			return l;

		if (c == '\r' || c == '\n')
			break;
		buffer[i++] = c;
	}
	buffer[i++] = '\0';
	return (ssize_t)i;
}

/* very simple string hash function */
unsigned int
hash_str(void *key, unsigned int cap)
{
	unsigned int i, sum = 0;

	for (i = 0; i < (unsigned int)strlen(key); i++) {
		sum += ((unsigned char *)key)[i] * (i + 1);
	}
	return (sum % cap);
}