ref: e09ff804102de75826409b6043619d2668d9cef8
dir: /util.c/
/* * 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) == 0) break; else if ((errno == EINPROGRESS) && (connect_wait(fd) == 0)) 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; }