1 /*
2 * A simple command-line exerciser for the library.
3 * Not really useful for anything but debugging.
4 * SPDX-License-Identifier: BSD-2-clause
5 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdbool.h>
9 #include <string.h>
10 #include <errno.h>
11 #include <stdarg.h>
12 #include <ctype.h>
13
14 #include "../gps.h"
15 #include "../libgps.h"
16 #include "../gpsdclient.h"
17
18 #include <unistd.h>
19 #include <getopt.h>
20 #include <signal.h>
21
onsig(int sig)22 static void onsig(int sig)
23 {
24 (void)fprintf(stderr, "libgps: died with signal %d\n", sig);
25 exit(EXIT_FAILURE);
26 }
27
28 #ifdef SOCKET_EXPORT_ENABLE
29 /* must start zeroed, otherwise the unit test will try to chase garbage pointer fields. */
30 static struct gps_data_t gpsdata;
31 #endif
32
main(int argc,char * argv[])33 int main(int argc, char *argv[])
34 {
35 struct gps_data_t collect;
36 struct fixsource_t source;
37 char buf[BUFSIZ];
38 int option;
39 bool batchmode = false;
40 bool forwardmode = false;
41 char *fmsg = NULL;
42 #ifdef CLIENTDEBUG_ENABLE
43 int debug = 0;
44 #endif
45
46 (void)signal(SIGSEGV, onsig);
47 #ifdef SIGBUS
48 (void)signal(SIGBUS, onsig);
49 #endif
50
51 while ((option = getopt(argc, argv, "bf:hsD:?")) != -1) {
52 switch (option) {
53 case 'b':
54 batchmode = true;
55 break;
56 case 'f':
57 forwardmode = true;
58 fmsg = optarg;
59 break;
60 case 's':
61 (void)
62 printf("Sizes: fix=%zd gpsdata=%zd rtcm2=%zd rtcm3=%zd "
63 "ais=%zd compass=%zd raw=%zd devices=%zd policy=%zd "
64 "version=%zd, noise=%zd\n",
65 sizeof(struct gps_fix_t),
66 sizeof(struct gps_data_t), sizeof(struct rtcm2_t),
67 sizeof(struct rtcm3_t), sizeof(struct ais_t),
68 sizeof(struct attitude_t), sizeof(struct rawdata_t),
69 sizeof(collect.devices), sizeof(struct gps_policy_t),
70 sizeof(struct version_t), sizeof(struct gst_t));
71 exit(EXIT_SUCCESS);
72 #ifdef CLIENTDEBUG_ENABLE
73 case 'D':
74 debug = atoi(optarg);
75 break;
76 #endif
77 case '?':
78 case 'h':
79 default:
80 (void)fputs("usage: test_libgps [-b] [-f fwdmsg] [-D lvl] [-s] [server[:port:[device]]]\n", stderr);
81 exit(EXIT_FAILURE);
82 }
83 }
84
85 /* Grok the server, port, and device. */
86 if (optind < argc) {
87 gpsd_source_spec(argv[optind], &source);
88 } else
89 gpsd_source_spec(NULL, &source);
90
91 #ifdef CLIENTDEBUG_ENABLE
92 gps_enable_debug(debug, stdout);
93 #endif
94 if (batchmode) {
95 #ifdef SOCKET_EXPORT_ENABLE
96 while (fgets(buf, sizeof(buf), stdin) != NULL) {
97 if (buf[0] == '{' || isalpha( (int) buf[0])) {
98 gps_unpack(buf, &gpsdata);
99 #ifdef LIBGPS_DEBUG
100 libgps_dump_state(&gpsdata);
101 #endif
102 }
103 }
104 #endif
105 } else if (gps_open(source.server, source.port, &collect) != 0) {
106 (void)fprintf(stderr,
107 "test_libgps: no gpsd running or network error: %d, %s\n",
108 errno, gps_errstr(errno));
109 exit(EXIT_FAILURE);
110 } else if (forwardmode) {
111 if (gps_send(&collect, fmsg) == -1) {
112 (void)fprintf(stderr,
113 "test_libgps: gps send error: %d, %s\n",
114 errno, gps_errstr(errno));
115 }
116 if (gps_read(&collect, NULL, 0) == -1) {
117 (void)fprintf(stderr,
118 "test_libgps: gps read error: %d, %s\n",
119 errno, gps_errstr(errno));
120 }
121 #ifdef SOCKET_EXPORT_ENABLE
122 #ifdef LIBGPS_DEBUG
123 libgps_dump_state(&collect);
124 #endif
125 #endif
126 (void)gps_close(&collect);
127 } else {
128 int tty = isatty(0);
129
130 if (tty)
131 (void)fputs("This is the gpsd exerciser.\n", stdout);
132 for (;;) {
133 if (tty)
134 (void)fputs("> ", stdout);
135 if (fgets(buf, sizeof(buf), stdin) == NULL) {
136 if (tty)
137 putchar('\n');
138 break;
139 }
140 collect.set = 0;
141 (void)gps_send(&collect, buf);
142 (void)gps_read(&collect, NULL, 0);
143 #ifdef SOCKET_EXPORT_ENABLE
144 #ifdef LIBGPS_DEBUG
145 libgps_dump_state(&collect);
146 #endif
147 #endif
148 }
149 (void)gps_close(&collect);
150 }
151 return 0;
152 }
153
154