util.c (3591B)
1 /* 2 * This work is dedicated to the public domain. 3 * See COPYING file for more information. 4 */ 5 6 #include <sys/socket.h> 7 #include <sys/stat.h> 8 9 #include <errno.h> 10 #include <fcntl.h> 11 #include <netdb.h> 12 #include <stdarg.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <unistd.h> 17 18 #define FALSE 0 19 #define TRUE 1 20 21 #ifdef __gnu_linux__ 22 char *strlcpy(char *dst, const char *src, size_t n) 23 { 24 return strncpy(dst, src, n); 25 } 26 #endif 27 28 void 29 print_log(int level, FILE *stream, const char *fmt, va_list arg) 30 { 31 size_t len; 32 33 if (level > LOG_LEVEL) 34 return; 35 36 vfprintf(stream, fmt, arg); 37 len = strlen(fmt); 38 if (len && fmt[len-1] == ':') 39 fprintf(stream, " %s\n", strerror(errno)); 40 else 41 fprintf(stream, "\n"); 42 } 43 44 void 45 debug(int level, const char *fmt, ...) 46 { 47 va_list arg; 48 va_start(arg, fmt); 49 print_log(level, stdout, fmt, arg); 50 va_end(arg); 51 } 52 53 void 54 warnf(const char *fmt, ...) 55 { 56 va_list arg; 57 fprintf(stderr, "warn: "); 58 va_start(arg, fmt); 59 print_log(0, stderr, fmt, arg); 60 va_end(arg); 61 } 62 63 void 64 fatal(const char *fmt, ...) 65 { 66 va_list arg; 67 fprintf(stderr, "error: "); 68 va_start(arg, fmt); 69 print_log(0, stderr, fmt, arg); 70 va_end(arg); 71 exit(1); 72 } 73 74 void * 75 emalloc(size_t size) 76 { 77 void *p; 78 if ((p = malloc(size)) == NULL) 79 fatal("malloc:"); 80 return p; 81 } 82 83 void * 84 ecalloc(size_t nmemb, size_t size) 85 { 86 void *p; 87 if ((p = calloc(nmemb, size)) == NULL) 88 fatal("calloc:"); 89 return p; 90 } 91 92 void * 93 erealloc(void *ptr, size_t size) 94 { 95 void *p; 96 if ((p = realloc(ptr, size)) == NULL) 97 fatal("realloc:"); 98 return p; 99 } 100 101 char* 102 split(char **str, char ch) 103 { 104 char *token = *str; 105 106 if (**str == '\0') return *str; 107 108 while (**str != ch && **str != '\0') 109 (*str)++; 110 if (**str == '\0') 111 return token; 112 **str = '\0'; 113 (*str)++; 114 while(**str == ch && **str != '\0') 115 (*str)++; 116 return token; 117 } 118 119 int 120 dial(char *host, char *port) 121 { 122 static struct addrinfo hints, *res = NULL, *res0; 123 int fd = -1, r; 124 125 memset(&hints, 0, sizeof(hints)); 126 hints.ai_family = AF_UNSPEC; 127 hints.ai_socktype = SOCK_STREAM; 128 129 if ((r = getaddrinfo(host, port, &hints, &res0)) != 0) { 130 warnf("getaddrinfo: %s", gai_strerror(r)); 131 return -1; 132 } 133 for (res = res0; res != NULL; res = res->ai_next) { 134 fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 135 if (fd == -1) { 136 warnf("socket:"); 137 continue; 138 } 139 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { 140 warnf("fnctl:"); 141 continue; 142 } 143 if ((connect(fd, res->ai_addr, res->ai_addrlen) == -1) && 144 (errno == EINPROGRESS)) 145 break; 146 warnf("connect:"); 147 close(fd); 148 fd = -1; 149 } 150 if (fd == -1) 151 warnf("failed to connect to %s", host); 152 153 freeaddrinfo(res0); 154 return fd; 155 } 156 157 int 158 fifo_open(char *path) 159 { 160 struct stat st; 161 int fd; 162 163 /* make a fifo file if it doesn't exists */ 164 if (lstat(path, &st) != -1) { 165 if (!(st.st_mode & S_IFIFO)) 166 fatal("%s: not a fifo file", path); 167 } else if (mkfifo(path, S_IRWXU) == -1) { 168 fatal("mkfifo: %s:", path); 169 } 170 171 fd = open(path, O_RDONLY | O_NONBLOCK, 0); 172 if (fd == -1) 173 fatal("open: %s:", path); 174 175 return fd; 176 } 177 178 ssize_t 179 readline(int fd, char *buffer, size_t size) 180 { 181 size_t i = 0; 182 char c; 183 ssize_t l; 184 185 while (i < size) { 186 l = read(fd, &c, sizeof(char)); 187 if (l == -1 && errno == EAGAIN) 188 continue; 189 else if (l == -1 || l == 0) 190 return l; 191 192 if (c == '\r' || c == '\n') 193 break; 194 buffer[i++] = c; 195 } 196 buffer[i++] = '\0'; 197 return (ssize_t)i; 198 } 199 200 /* very simple string hash function */ 201 unsigned int 202 hash_str(void *key, unsigned int cap) 203 { 204 unsigned int i, sum = 0; 205 206 for (i = 0; i < (unsigned int)strlen(key); i++) { 207 sum += ((unsigned char *)key)[i] * (i + 1); 208 } 209 return (sum % cap); 210 }