summaryrefslogtreecommitdiff
path: root/gpsdclient.c
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2009-03-02 23:05:21 +0000
committerEric S. Raymond <esr@thyrsus.com>2009-03-02 23:05:21 +0000
commit9713aad879931bade1a3158b8414777450674e08 (patch)
treea8744d8914b347460570ec7af037f06e42efe89c /gpsdclient.c
parentf156d8268b125de643ad4e7977e908ffa6e91987 (diff)
downloadgpsd-9713aad879931bade1a3158b8414777450674e08.tar.gz
Split up libps.c so the code overhead for users' clients will be lower.
Diffstat (limited to 'gpsdclient.c')
-rw-r--r--gpsdclient.c163
1 files changed, 163 insertions, 0 deletions
diff --git a/gpsdclient.c b/gpsdclient.c
new file mode 100644
index 00000000..5180d94c
--- /dev/null
+++ b/gpsdclient.c
@@ -0,0 +1,163 @@
+/* $Id$ */
+/* gpsclient.c -- support functions for GPSD clients */
+#include <sys/time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <math.h>
+
+#include "gpsd_config.h"
+#include "gpsd.h"
+
+#ifdef HAVE_SETLOCALE
+#include <locale.h>
+#endif
+
+/* convert double degrees to a static string and return a pointer to it
+ *
+ * deg_str_type:
+ * deg_dd : return DD.dddddd
+ * deg_ddmm : return DD MM.mmmm'
+ * deg_ddmmss : return DD MM' SS.sss"
+ *
+ */
+/*@observer@*/char *deg_to_str( enum deg_str_type type, double f)
+{
+ static char str[40];
+ int dsec, sec, deg, min;
+ long frac_deg;
+ double fdsec, fsec, fdeg, fmin;
+
+ if ( f < 0 || f > 360 ) {
+ (void)strlcpy( str, "nan", 40);
+ return str;
+ }
+
+ fmin = modf( f, &fdeg);
+ deg = (int)fdeg;
+ frac_deg = (long)(fmin * 1000000);
+
+ if ( deg_dd == type ) {
+ /* DD.dddddd */
+ (void)snprintf(str, sizeof(str), "%3d.%06ld", deg,frac_deg);
+ return str;
+ }
+ fsec = modf( fmin * 60, &fmin);
+ min = (int)fmin;
+ sec = (int)(fsec * 10000.0);
+
+ if ( deg_ddmm == type ) {
+ /* DD MM.mmmm */
+ (void)snprintf(str,sizeof(str), "%3d %02d.%04d'", deg,min,sec);
+ return str;
+ }
+ /* else DD MM SS.sss */
+ fdsec = modf( fsec * 60, &fsec);
+ sec = (int)fsec;
+ dsec = (int)(fdsec * 1000.0);
+ (void)snprintf(str,sizeof(str), "%3d %02d' %02d.%03d\"", deg,min,sec,dsec);
+
+ return str;
+}
+
+/*
+ * check the environment to determine proper GPS units
+ *
+ * clients should only call this if no user preference is specified on
+ * the command line or via X resources.
+ *
+ * return imperial - Use miles/feet
+ * nautical - Use knots/feet
+ * metric - Use km/meters
+ * unspecified - use compiled default
+ *
+ * In order check these environment vars:
+ * GPSD_UNITS one of:
+ * imperial = miles/feet
+ * nautical = knots/feet
+ * metric = km/meters
+ * LC_MEASUREMENT
+ * en_US = miles/feet
+ * C = miles/feet
+ * POSIX = miles/feet
+ * [other] = km/meters
+ * LANG
+ * en_US = miles/feet
+ * C = miles/feet
+ * POSIX = miles/feet
+ * [other] = km/meters
+ *
+ * if none found then return compiled in default
+ */
+enum unit gpsd_units(void)
+{
+ char *envu = NULL;
+
+#ifdef HAVE_SETLOCALE
+ (void)setlocale(LC_NUMERIC, "C");
+#endif
+ if ((envu = getenv("GPSD_UNITS")) != NULL && *envu != '\0') {
+ if (0 == strcasecmp(envu, "imperial")) {
+ return imperial;
+ }
+ if (0 == strcasecmp(envu, "nautical")) {
+ return nautical;
+ }
+ if (0 == strcasecmp(envu, "metric")) {
+ return metric;
+ }
+ /* unrecognized, ignore it */
+ }
+ if (((envu = getenv("LC_MEASUREMENT")) != NULL && *envu != '\0')
+ || ((envu = getenv("LANG")) != NULL && *envu != '\0')) {
+ if (strcasecmp(envu, "en_US")==0
+ || strcasecmp(envu, "C")==0
+ || strcasecmp(envu, "POSIX")==0) {
+ return imperial;
+ }
+ /* Other, must be metric */
+ return metric;
+ }
+ /* TODO: allow a compile time default here */
+ return unspecified;
+}
+
+/*@ -observertrans -nullpass -statictrans -mustfreeonly -kepttrans @*/
+void gpsd_source_spec(const char *arg, struct fixsource_t *source)
+/* standard parsing of a GPS data source spec */
+{
+ source->server = "127.0.0.1";
+ source->port = DEFAULT_GPSD_PORT;
+ source->device = NULL;
+
+ if (arg != NULL) {
+ char *colon1;
+ source->spec = strdup(arg);
+ colon1 = strchr(source->spec, ':');
+
+ if (colon1 != NULL) {
+ char *colon2;
+ *colon1 = '\0';
+ if (colon1 != source->spec)
+ source->server = source->spec;
+ source->port = colon1 + 1;
+ colon2 = strchr(source->port, ':');
+ if (colon2 != NULL) {
+ *colon2 = '\0';
+ source->device = colon2 + 1;
+ }
+ } else if (strchr(source->spec, '/') != NULL) {
+ source->device = source->spec;
+ } else {
+ source->server = source->spec;
+ }
+ }
+}
+/*@ +observertrans +nullpass +statictrans +mustfreeonly +kepttrans @*/
+
+/* gpsclient.c ends here */
+
+