wm: ticl

ref: 8d0c143cd5f978544806f8b58bcefc22aef92cb5
dir: /util.c/

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

#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netdb.h>
#include <poll.h>
#include <unistd.h>


/*
 * ecalloc - calloc with error handling
 */
void *
ecalloc(size_t nmemb, size_t size)
{
	void *p;
	if ((p = calloc(nmemb, size)) == NULL) {
		printf("error: calloc: %s\n", strerror(errno));
		exit(1);
	}
	return p;
}

/*
 * erecalloc -- allocate more memory, zero new memory, handle error
 * 	ptr	- pointer of the old memory
 * 	omemb	- no. of member of old pointer
 * 	nmemb	- no. of member to extend
 * 	size	- size of one member
 */
void *
erecalloc(void *ptr, size_t omemb, size_t nmemb, size_t size)
{
	void *p;
	if ((p = realloc(ptr, (omemb + nmemb) * size)) == NULL) {
		printf("error: realloc: %s\n", strerror(errno));
		exit(1);
	}
	/* memset(p + omemb * size, 0, nmemb * size); */
	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
fifo_open(char *path)
{
	struct stat st;
	int fd;

	/* make fifo if it doesn't exists */
	if (lstat(path, &st) != -1) {
		if (!(st.st_mode & S_IFIFO)) {
			printf("error: '%s' is not a fifo file\n", path);
			return -1;
		}
	} else if (mkfifo(path, S_IRWXU) != 0) {
		printf("error: failed to create fifo file '%s'\n", path);
		return -1;
	}

	/* open fifo */
	fd = open(path, O_RDONLY | O_NONBLOCK, 0);
	if (fd == -1)
		printf("error: cannot open() '%s'\n", path);

	return fd;
}

ssize_t
writeall(int fd, char *buf)
{
	ssize_t left, sent, n;
	left = (ssize_t)strlen(buf);
	sent = 0;
	while (sent < left) {
		if ((n = write(fd, buf+sent, (size_t)left)) == -1) {
			printf("error: write failed: %s\n", strerror(errno));
			return -1;
		}
		sent += n;
		left -= n;
	}
	return sent;
}

int
connect_wait(int s)
{
	struct pollfd pfd[1];
	int error = 0;
	socklen_t len = sizeof(error);

	pfd[0].fd = s;
	pfd[0].events = POLLOUT;

	if (poll(pfd, 1, -1) == -1)
		return -1;
	if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) == -1)
		return -1;
	if (error != 0) {
		errno = error;
		return -1;
	}
	return 0;
}

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) {
		printf("error: getaddrinfo: %s\n", gai_strerror(r));
		return -1;
	}
	for (res = res0; res != NULL; res = res->ai_next) {
		if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1)
			continue;
		if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
			printf("error: fcntl: %s\n", strerror(errno));
			continue;
		}
		if ((connect(fd, res->ai_addr, res->ai_addrlen) == -1)
		&& (errno == EINPROGRESS))
			break;

		printf("error: connect: %s\n", strerror(errno));
		close(fd);
		fd = -1;
	}
	if (fd == -1)
		printf("error: cannot connect to host '%s'\n", host);

	freeaddrinfo(res0);
	return fd;
}

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

	do {
		if ((n = read(fd, &c, sizeof(char))) != sizeof(char))
			return n;
		buffer[i++] = c;
	} while ((i < (ssize_t)size) && (c != '\n') && (c != '\0'));

	buffer[i-1] = '\0';
	return i;
}