diff options
Diffstat (limited to 'src/utils.c')
-rw-r--r-- | src/utils.c | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..6f98ab0 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,217 @@ +/* + * Venus GPS Server + * + * Copyright (C) 2010 by Multi-Tech Systems + * Copyright (C) 2004-2009 by James Maki + * + * Author: James Maki <jmaki@multitech.com> + * + * safe_read, safe_write, full_write are from Busybox + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#define _GNU_SOURCE + +#include <string.h> +#include <netdb.h> +#include <fcntl.h> + +#include "log.h" +#include "utils.h" + +int systemf(const char *fmt, ...) { + int err; + va_list ap; + char *buf; + + va_start(ap, fmt); + err = vasprintf(&buf, fmt, ap); + va_end(ap); + if(err == -1) { + log_error("out of memory"); + return -1; + } + + log_debug("%s", buf); + + err = system(buf); + free(buf); + + return err; +} + +ssize_t safe_read(int fd, void *buf, size_t count) { + ssize_t n; + + do { + n = read(fd, buf, count); + } while(n < 0 && errno == EINTR); + + return n; +} + +ssize_t safe_readn(int fd, void *buf, size_t len) { + ssize_t cc; + ssize_t total; + + total = 0; + + while(len) { + cc = safe_read(fd, buf, len); + + if(cc < 0) { + if(total) { + return total; + } + return cc; + } + + total += cc; + buf = buf + cc; + len -= cc; + } + + return total; +} + +ssize_t safe_write(int fd, const void *buf, size_t count) { + ssize_t n; + + do { + n = write(fd, buf, count); + } while(n < 0 && errno == EINTR); + + return n; +} + +ssize_t full_write(int fd, const void *buf, size_t len) { + ssize_t cc; + ssize_t total; + + total = 0; + + while(len) { + cc = safe_write(fd, buf, len); + + if(cc < 0) { + if(total) { + return total; + } + return cc; + } + + total += cc; + buf = ((const char *)buf) + cc; + len -= cc; + } + + return total; +} + +int set_nonblocking(int fd) { + int err; + + err = fcntl(fd, F_GETFL, 0); + if(err < 0) { + log_warning("fcntl(fd, F_GETFL, 0) failed: errno %d", errno); + return err; + } + err = fcntl(fd, F_SETFL, err | O_NONBLOCK); + if(err < 0) { + log_warning("fcntl(fd, F_SETFL, opts | O_NONBLOCK) failed: errno %d", errno); + return err; + } + + return err; +} + +int host_to_inet(const char *host, struct in_addr *in) { + struct hostent h; + struct hostent *hp; + char buf[1024]; + int herrno; + int err; + + err = gethostbyname_r(host, &h, buf, sizeof(buf), &hp, &herrno); + if(hp == NULL) { + log_error("gethostbyname_r: %d", herrno); + return -1; + } + + memcpy(&in->s_addr, h.h_addr_list[0], 4); + + return 0; +} + +int inet_conn_str(char *host, int port, int type) { + struct hostent h; + struct hostent *hp; + char buf[1024]; + int herrno; + int err; + + err = gethostbyname_r(host, &h, buf, sizeof(buf), &hp, &herrno); + if(hp == NULL) { + log_error("gethostbyname_r: %d", herrno); + return -1; + } + + int sd = socket(PF_INET, type, 0); + if(sd == -1) { + log_error("socket: %d", errno); + return -1; + } + + struct sockaddr_in serv_addr; + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(port); + memcpy(&serv_addr.sin_addr.s_addr, h.h_addr_list[0], 4); + + err = connect(sd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); + if(err == -1) { + log_error("connect: %d", errno); + close(sd); + return -1; + } + + return sd; +} + +int inet_conn_ia(struct in_addr *host, int port, int type) { + int err; + + int sd = socket(PF_INET, type, 0); + if(sd == -1) { + log_error("socket: %d", errno); + return -1; + } + + struct sockaddr_in serv_addr; + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(port); + serv_addr.sin_addr.s_addr = host->s_addr; + + err = connect(sd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); + if(err == -1) { + log_error("connect: %d", errno); + close(sd); + return -1; + } + + return sd; +} + |