diff --git a/SConstruct b/SConstruct index 1de0fa75..c780bcbb 100644 --- a/SConstruct +++ b/SConstruct @@ -750,9 +750,15 @@ else: announce("You do not have the endian.h header file. RTCM V2 support disabled.") env["rtcm104v2"] = False + for hdr in ("sys/un", "sys/socket", "sys/select", "netdb", "netinet/in", "netinet/ip", "arpa/inet", "termios", "winsock2"): + if config.CheckHeader(hdr + ".h"): + confdefs.append("#define HAVE_%s_H 1\n" % hdr.replace("/","_").upper()) + else: + confdefs.append("/* #undef HAVE_%s_H */\n" % hdr.replace("/","_").upper()) + # check function after libraries, because some function require libraries # for example clock_gettime() require librt on Linux glibc < 2.17 - for f in ("daemon", "strlcpy", "strlcat", "clock_gettime", "strptime", "gmtime_r" ): + for f in ("daemon", "strlcpy", "strlcat", "clock_gettime", "strptime", "gmtime_r", "inet_ntop", "fcntl"): if config.CheckFunc(f): confdefs.append("#define HAVE_%s 1\n" % f.upper()) else: diff --git a/gpsd.h b/gpsd.h index b3dc3c97..50aa759a 100644 --- a/gpsd.h +++ b/gpsd.h @@ -17,11 +17,16 @@ extern "C" { #include #include #include +#include "gpsd_config.h" +#ifdef HAVE_TERMIOS_H #include +#endif +#ifdef HAVE_WINSOCK2_H +#include /* for fd_set */ +#endif #include /* for time_t */ #include "gps.h" -#include "gpsd_config.h" #include "os_compat.h" /* @@ -361,11 +366,13 @@ struct gps_type_t { void (*init_query)(struct gps_device_t *session); void (*event_hook)(struct gps_device_t *session, event_t event); #ifdef RECONFIGURE_ENABLE +#ifdef HAVE_TERMIOS_H bool (*speed_switcher)(struct gps_device_t *session, speed_t speed, char parity, int stopbits); void (*mode_switcher)(struct gps_device_t *session, int mode); bool (*rate_switcher)(struct gps_device_t *session, double rate); double min_cycle; +#endif /* HAVE_TERMIOS_H */ #endif /* RECONFIGURE_ENABLE */ #ifdef CONTROLSEND_ENABLE ssize_t (*control_send)(struct gps_device_t *session, char *buf, size_t buflen); @@ -472,7 +479,9 @@ struct gps_device_t { sourcetype_t sourcetype; servicetype_t servicetype; int mode; +#ifdef HAVE_TERMIOS_H struct termios ttyset, ttyset_old; +#endif #ifndef FIXED_PORT_SPEED unsigned int baudindex; #endif /* FIXED_PORT_SPEED */ @@ -822,9 +831,11 @@ extern ssize_t gpsd_serial_write(struct gps_device_t *, const char *, const size_t); extern bool gpsd_next_hunt_setting(struct gps_device_t *); extern int gpsd_switch_driver(struct gps_device_t *, char *); +#ifdef HAVE_TERMIOS_H extern void gpsd_set_speed(struct gps_device_t *, speed_t, char, unsigned int); extern speed_t gpsd_get_speed(const struct gps_device_t *); extern speed_t gpsd_get_speed_old(const struct gps_device_t *); +#endif /* HAVE_TERMIOS_H */ extern int gpsd_get_stopbits(const struct gps_device_t *); extern char gpsd_get_parity(const struct gps_device_t *); extern void gpsd_assert_sync(struct gps_device_t *); diff --git a/libgps_sock.c b/libgps_sock.c index ea04b8cd..31f73f5c 100644 --- a/libgps_sock.c +++ b/libgps_sock.c @@ -16,11 +16,19 @@ #include /* expected to have a select(2) prototype a la SuS */ #include #include +#include "gpsd_config.h" +#ifdef HAVE_SYS_SELECT_H #include +#endif /* HAVE_SYS_SELECT_H */ #include #ifndef USE_QT +#ifdef HAVE_SYS_SOCKET_H #include +#endif /* HAVE_SYS_SOCKET_H */ +#ifdef HAVE_WINSOCK2_H +#include +#endif /* HAVE_WINSOCK2_H */ #else #include #endif /* USE_QT */ @@ -43,6 +51,33 @@ struct privdata_t #endif /* LIBGPS_DEBUG */ }; +#ifdef HAVE_WINSOCK2_H +static bool need_init = TRUE; +static bool need_finish = TRUE; + +static bool windows_init(void) +/* Ensure socket networking is initialized for Windows. */ +{ + WSADATA wsadata; + /* request access to Windows Sockets API version 2.2 */ + int res = WSAStartup(MAKEWORD(2, 2), &wsadata); + if (res != 0) { + libgps_debug_trace((DEBUG_CALLS, "WSAStartup returns error %d\n", res)); + } + return (res == 0); +} + +static bool windows_finish(void) +/* Shutdown Windows Sockets. */ +{ + int res = WSACleanup(); + if (res != 0) { + libgps_debug_trace((DEBUG_CALLS, "WSACleanup returns error %d\n", res)); + } + return (res == 0); +} +#endif /* HAVE_WINSOCK2_H */ + int gps_sock_open(const char *host, const char *port, struct gps_data_t *gpsdata) { @@ -54,6 +89,11 @@ int gps_sock_open(const char *host, const char *port, libgps_debug_trace((DEBUG_CALLS, "gps_sock_open(%s, %s)\n", host, port)); #ifndef USE_QT +#ifdef HAVE_WINSOCK2_H + if (need_init) { + need_init != windows_init(); + } +#endif if ((gpsdata->gps_fd = netlib_connectsock(AF_UNSPEC, host, port, "tcp")) < 0) { errno = gpsdata->gps_fd; @@ -62,7 +102,7 @@ int gps_sock_open(const char *host, const char *port, } else libgps_debug_trace((DEBUG_CALLS, "netlib_connectsock() returns socket on fd %d\n", gpsdata->gps_fd)); -#else +#else /* HAVE_WINSOCK2_H */ QTcpSocket *sock = new QTcpSocket(); gpsdata->gps_fd = sock; sock->connectToHost(host, QString(port).toInt()); @@ -119,7 +159,14 @@ int gps_sock_close(struct gps_data_t *gpsdata) gpsdata->privdata = NULL; #ifndef USE_QT int status; +#ifdef HAVE_WINSOCK2_H + status = closesocket(gpsdata->gps_fd); + if (need_finish) { + need_finish != windows_finish(); + } +#else status = close(gpsdata->gps_fd); +#endif /* HAVE_WINSOCK2_H */ gpsdata->gps_fd = -1; return status; #else @@ -160,7 +207,9 @@ int gps_sock_read(struct gps_data_t *gpsdata) sizeof(PRIVATE(gpsdata)->buffer) - PRIVATE(gpsdata)->waiting); #endif - +#ifdef HAVE_WINSOCK2_H + int wserr = WSAGetLastError(); +#endif /* HAVE_WINSOCK2_H */ /* if we just received data from the socket, it's in the buffer */ if (status > -1) PRIVATE(gpsdata)->waiting += status; @@ -175,9 +224,14 @@ int gps_sock_read(struct gps_data_t *gpsdata) return -1; #ifndef USE_QT /* count transient errors as success, we'll retry later */ +#ifdef HAVE_WINSOCK2_H + else if (wserr == WSAEINTR || wserr == WSAEWOULDBLOCK) + return 0; +#else else if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) return 0; +#endif /* HAVE_WINSOCK2_H */ #endif /* hard error return of -1, pass it along */ else @@ -245,7 +299,11 @@ int gps_sock_send(struct gps_data_t *gpsdata, const char *buf) /* send a command to the gpsd instance */ { #ifndef USE_QT +#ifdef HAVE_WINSOCK2_H + if (send(gpsdata->gps_fd, buf, strlen(buf), 0) == (ssize_t) strlen(buf)) +#else if (write(gpsdata->gps_fd, buf, strlen(buf)) == (ssize_t) strlen(buf)) +#endif /* HAVE_WINSOCK2_H */ return 0; else return -1; diff --git a/netlib.c b/netlib.c index c8969382..2939454d 100644 --- a/netlib.c +++ b/netlib.c @@ -3,21 +3,38 @@ * BSD terms apply: see the file COPYING in the distribution root for details. */ +#include "gpsd_config.h" #include #include +#ifdef HAVE_NETDB_H #include +#endif /* HAVE_NETDB_H */ #ifndef AF_UNSPEC #include #include +#ifdef HAVE_SYS_SOCKET_H #include +#endif /* HAVE_SYS_SOCKET_H */ #endif /* AF_UNSPEC */ +#ifdef HAVE_SYS_UN_H #include +#endif /* HAVE_SYS_UN_H */ #ifndef INADDR_ANY +#ifdef HAVE_NETINET_IN_H #include +#endif /* HAVE_NETINET_IN_H */ #endif /* INADDR_ANY */ +#ifdef HAVE_ARPA_INET_H #include /* for htons() and friends */ +#endif /* HAVE_ARPA_INET_H */ #include +#ifdef HAVE_NETINET_IN_H #include +#endif /* HAVE_NETINET_IN_H */ +#ifdef HAVE_WINSOCK2_H +#include +#include +#endif #include "gpsd.h" #include "sockaddr.h" @@ -97,7 +114,11 @@ socket_t netlib_connectsock(int af, const char *host, const char *service, } if (!BAD_SOCKET(s)) { - (void)close(s); +#ifdef HAVE_WINSOCK2_H + (void)closesocket(s); +#else + (void)close(s); +#endif } } freeaddrinfo(result); @@ -126,8 +147,12 @@ socket_t netlib_connectsock(int af, const char *host, const char *service, #endif /* set socket to noblocking */ +#ifdef HAVE_FCNTL (void)fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK); - +#elif defined(HAVE_WINSOCK2_H) + u_long one1 = 1; + (void)ioctlsocket(s, FIONBIO, &one1); +#endif return s; } @@ -155,6 +180,7 @@ const char *netlib_errstr(const int err) socket_t netlib_localsocket(const char *sockfile, int socktype) /* acquire a connection to an existing Unix-domain socket */ { +#ifdef HAVE_SYS_UN_H int sock; if ((sock = socket(AF_UNIX, socktype, 0)) < 0) { @@ -175,16 +201,19 @@ socket_t netlib_localsocket(const char *sockfile, int socktype) return sock; } +#else + return -1; +#endif /* HAVE_SYS_UN_H */ } char *netlib_sock2ip(socket_t fd) /* retrieve the IP address corresponding to a socket */ { + static char ip[INET6_ADDRSTRLEN]; + int r = 1; +#ifdef HAVE_INET_NTOP sockaddr_t fsin; socklen_t alen = (socklen_t) sizeof(fsin); - static char ip[INET6_ADDRSTRLEN]; - int r; - r = getpeername(fd, &(fsin.sa), &alen); if (r == 0) { switch (fsin.sa.sa_family) { @@ -203,6 +232,7 @@ char *netlib_sock2ip(socket_t fd) return ip; } } +#endif /* HAVE_INET_NTOP */ if (r != 0) { (void)strlcpy(ip, "", sizeof(ip)); } diff --git a/os_compat.c b/os_compat.c index b110f4ba..dafbb7a4 100644 --- a/os_compat.c +++ b/os_compat.c @@ -45,7 +45,8 @@ int clock_gettime(clockid_t clk_id, struct timespec *ts) /* End of clock_gettime section */ #ifndef HAVE_DAEMON - +#ifndef HAVE_WINSOCK2_H +/* No daemon() provided for Windows as not currently needed */ /* Simulate Linux/BSD daemon() on platforms that don't have it */ #include @@ -90,7 +91,7 @@ int os_daemon(int nochdir, int noclose) /* coverity[leaked_handle] Intentional handle duplication */ return 0; } - +#endif /* HAVE_WINSOCK2_H */ #else /* HAVE_DAEMON */ #ifdef __linux__ diff --git a/test_libgps.c b/test_libgps.c index 91dd65b3..933beba0 100644 --- a/test_libgps.c +++ b/test_libgps.c @@ -43,7 +43,9 @@ int main(int argc, char *argv[]) #endif (void)signal(SIGSEGV, onsig); +#ifdef SIGBUS (void)signal(SIGBUS, onsig); +#endif while ((option = getopt(argc, argv, "bf:hsD:?")) != -1) { switch (option) { @@ -144,7 +146,6 @@ int main(int argc, char *argv[]) } (void)gps_close(&collect); } - return 0; }