/* * Venus GPS Server * * Copyright (C) 2010 by Multi-Tech Systems * Copyright (C) 2004-2009 by James Maki * * Author: James Maki * * 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 #include #include #include #include #include #include #define UDP_CORK 1 #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: %m"); return err; } err = fcntl(fd, F_SETFL, err | O_NONBLOCK); if (err < 0) { log_warning("fcntl(fd, F_SETFL, opts | O_NONBLOCK) failed: %m"); return err; } return err; } int udp_cork(int fd, int corked) { int tmp; tmp = setsockopt(fd, IPPROTO_UDP, UDP_CORK, &corked, sizeof(corked)); if (tmp < 0) { log_error("setsockopt UDP_CORK failed"); } return -1; } int tcp_cork(int fd, int corked) { int tmp; tmp = setsockopt(fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked)); if (tmp < 0) { log_error("setsockopt TCP_CORK failed"); } return -1; } 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(const 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: %m"); 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: %m"); 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: %m"); 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: %m"); close(sd); return -1; } return sd; }