summaryrefslogtreecommitdiff
path: root/gpsd.c
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2009-08-12 13:25:43 +0000
committerEric S. Raymond <esr@thyrsus.com>2009-08-12 13:25:43 +0000
commite087b7d3ab3ba204a97197380cd6e43e05f5c290 (patch)
treef1369f30492eda5508a7ab8158a06ab81081a68e /gpsd.c
parente7e6df300793e13d52ea9aecc73c21e6b040bf8a (diff)
downloadgpsd-e087b7d3ab3ba204a97197380cd6e43e05f5c290.tar.gz
Multiple GPSD-NG commands per line are now supported.
Diffstat (limited to 'gpsd.c')
-rw-r--r--gpsd.c238
1 files changed, 130 insertions, 108 deletions
diff --git a/gpsd.c b/gpsd.c
index aff89ece..89dbb5c7 100644
--- a/gpsd.c
+++ b/gpsd.c
@@ -1032,14 +1032,16 @@ static void set_serial(struct gps_device_t *device,
#endif /* ALLOW_RECONFIGURE */
#ifdef OLDSTYLE_ENABLE
-static int handle_oldstyle(struct subscriber_t *sub, char *buf)
+static bool handle_oldstyle(struct subscriber_t *sub, char *buf,
+ char *reply, size_t replylen)
/* interpret a client request; cfd is the socket back to the client */
{
- char reply[BUFSIZ], phrase[BUFSIZ], *p, *stash;
+ char phrase[BUFSIZ], *p, *stash;
int i, j;
struct channel_t *channel = NULL;
- (void)strlcpy(reply, "GPSD", BUFSIZ);
+ (void)strlcpy(reply, "GPSD", replylen);
+ replylen -= 4;
p = buf;
while (*p != '\0') {
phrase[0] = '\0';
@@ -1049,7 +1051,7 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
(void)snprintf(phrase, sizeof(phrase), ",A=%.3f",
channel->fixbuffer.altitude);
else
- (void)strlcpy(phrase, ",A=?", BUFSIZ);
+ (void)strlcpy(phrase, ",A=?", sizeof(phrase));
break;
#ifdef ALLOW_RECONFIGURE
case 'B': /* change baud rate */
@@ -1078,12 +1080,12 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
(int)channel->device->gpsdata.parity,
channel->device->gpsdata.stopbits);
} else {
- (void)strlcpy(phrase, ",B=?", BUFSIZ);
+ (void)strlcpy(phrase, ",B=?", sizeof(phrase));
}
break;
case 'C':
if ((channel=assign_channel(sub, GPS, NULL))==NULL || channel->device->device_type==NULL)
- (void)strlcpy(phrase, ",C=?", BUFSIZ);
+ (void)strlcpy(phrase, ",C=?", sizeof(phrase));
else {
const struct gps_type_t *dev = channel->device->device_type;
if (*p == '=' && privileged_channel(channel)) {
@@ -1102,15 +1104,15 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
break;
#endif /* ALLOW_RECONFIGURE */
case 'D':
- (void)strlcpy(phrase, ",D=", BUFSIZ);
+ (void)strlcpy(phrase, ",D=", sizeof(phrase));
if ((channel=assign_channel(sub, GPS, NULL))!= NULL && isnan(channel->fixbuffer.time)==0)
(void)unix_to_iso8601(channel->fixbuffer.time,
phrase+3, sizeof(phrase)-3);
else
- (void)strlcat(phrase, "?", BUFSIZ);
+ (void)strlcat(phrase, "?", sizeof(phrase));
break;
case 'E':
- (void)strlcpy(phrase, ",E=", BUFSIZ);
+ (void)strlcpy(phrase, ",E=", sizeof(phrase));
if ((channel=assign_channel(sub, GPS, NULL))!= NULL && have_fix(channel)) {
#if 0
/*
@@ -1161,7 +1163,7 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
(void)snprintf(phrase, sizeof(phrase), ",F=%s",
channel->device->gpsdata.gps_device);
else
- (void)strlcpy(phrase, ",F=?", BUFSIZ);
+ (void)strlcpy(phrase, ",F=?", sizeof(phrase));
break;
case 'G':
if (*p == '=') {
@@ -1180,7 +1182,7 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
} else
channel = assign_channel(sub, ANY, NULL);
if (channel==NULL||channel->device==NULL||channel->device->packet.type==BAD_PACKET)
- (void)strlcpy(phrase, ",G=?", BUFSIZ);
+ (void)strlcpy(phrase, ",G=?", sizeof(phrase));
else if (channel->device->packet.type == RTCM2_PACKET)
(void)snprintf(phrase, sizeof(phrase), ",G=RTCM104v2");
else
@@ -1191,7 +1193,7 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
(void)snprintf(phrase, sizeof(phrase), ",I=%s",
gpsd_id(channel->device));
} else
- (void)strlcpy(phrase, ",I=?", BUFSIZ);
+ (void)strlcpy(phrase, ",I=?", sizeof(phrase));
break;
case 'J':
if (channel != NULL) {
@@ -1205,7 +1207,7 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
}
(void)snprintf(phrase, sizeof(phrase), ",J=%u", channel->conf.buffer_policy);
} else
- (void)strlcpy(phrase, ",J=?", BUFSIZ);
+ (void)strlcpy(phrase, ",J=?", sizeof(phrase));
break;
case 'K':
for (j = i = 0; i < MAXDEVICES; i++)
@@ -1214,8 +1216,8 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
(void)snprintf(phrase, sizeof(phrase), ",K=%d ", j);
for (i = 0; i < MAXDEVICES; i++) {
if (allocated_device(&devices[i]) && strlen(phrase)+strlen(devices[i].gpsdata.gps_device)+1 < sizeof(phrase)) {
- (void)strlcat(phrase, devices[i].gpsdata.gps_device, BUFSIZ);
- (void)strlcat(phrase, " ", BUFSIZ);
+ (void)strlcat(phrase, devices[i].gpsdata.gps_device, sizeof(phrase));
+ (void)strlcat(phrase, " ", sizeof(phrase));
}
}
phrase[strlen(phrase)-1] = '\0';
@@ -1225,15 +1227,15 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
break;
case 'M':
if ((channel=assign_channel(sub, GPS, NULL))== NULL && (!channel->device || channel->fixbuffer.mode == MODE_NOT_SEEN))
- (void)strlcpy(phrase, ",M=?", BUFSIZ);
+ (void)strlcpy(phrase, ",M=?", sizeof(phrase));
else
(void)snprintf(phrase, sizeof(phrase), ",M=%d", channel->fixbuffer.mode);
break;
case 'N':
if ((channel=assign_channel(sub, GPS, NULL))== NULL || channel->device->device_type == NULL)
- (void)strlcpy(phrase, ",N=?", BUFSIZ);
+ (void)strlcpy(phrase, ",N=?", sizeof(phrase));
else if (!channel->device->device_type->mode_switcher)
- (void)strlcpy(phrase, ",N=0", BUFSIZ);
+ (void)strlcpy(phrase, ",N=0", sizeof(phrase));
#ifdef ALLOW_RECONFIGURE
else if (privileged_channel(channel) && !context.readonly) {
if (*p == '=') ++p;
@@ -1253,7 +1255,7 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
break;
case 'O':
if ((channel=assign_channel(sub, GPS, NULL))== NULL || !have_fix(channel))
- (void)strlcpy(phrase, ",O=?", BUFSIZ);
+ (void)strlcpy(phrase, ",O=?", sizeof(phrase));
else {
(void)snprintf(phrase, sizeof(phrase), ",O=%s",
channel->device->gpsdata.tag[0]!='\0' ? channel->device->gpsdata.tag : "-");
@@ -1263,47 +1265,47 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
" %.3f",
channel->fixbuffer.time);
else
- (void)strlcat(phrase, " ?", BUFSIZ);
+ (void)strlcat(phrase, " ?", sizeof(phrase));
if (isnan(channel->fixbuffer.ept)==0)
(void)snprintf(phrase+strlen(phrase),
sizeof(phrase)-strlen(phrase),
" %.3f",
channel->fixbuffer.ept);
else
- (void)strlcat(phrase, " ?", BUFSIZ);
+ (void)strlcat(phrase, " ?", sizeof(phrase));
if (isnan(channel->fixbuffer.latitude)==0)
(void)snprintf(phrase+strlen(phrase),
sizeof(phrase)-strlen(phrase),
" %.9f",
channel->fixbuffer.latitude);
else
- (void)strlcat(phrase, " ?", BUFSIZ);
+ (void)strlcat(phrase, " ?", sizeof(phrase));
if (isnan(channel->fixbuffer.longitude)==0)
(void)snprintf(phrase+strlen(phrase),
sizeof(phrase)-strlen(phrase),
" %.9f",
channel->fixbuffer.longitude);
else
- (void)strlcat(phrase, " ?", BUFSIZ);
+ (void)strlcat(phrase, " ?", sizeof(phrase));
if (isnan(channel->fixbuffer.altitude)==0)
(void)snprintf(phrase+strlen(phrase),
sizeof(phrase)-strlen(phrase),
" %.3f",
channel->fixbuffer.altitude);
else
- (void)strlcat(phrase, " ?", BUFSIZ);
+ (void)strlcat(phrase, " ?", sizeof(phrase));
if (isnan(channel->fixbuffer.eph)==0)
(void)snprintf(phrase+strlen(phrase),
sizeof(phrase)-strlen(phrase),
" %.3f", channel->fixbuffer.eph);
else
- (void)strlcat(phrase, " ?", BUFSIZ);
+ (void)strlcat(phrase, " ?", sizeof(phrase));
if (isnan(channel->fixbuffer.epv)==0)
(void)snprintf(phrase+strlen(phrase),
sizeof(phrase)-strlen(phrase),
" %.3f", channel->fixbuffer.epv);
else
- (void)strlcat(phrase, " ?", BUFSIZ);
+ (void)strlcat(phrase, " ?", sizeof(phrase));
if (isnan(channel->fixbuffer.track)==0)
(void)snprintf(phrase+strlen(phrase),
sizeof(phrase)-strlen(phrase),
@@ -1311,39 +1313,39 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
channel->fixbuffer.track,
channel->fixbuffer.speed);
else
- (void)strlcat(phrase, " ? ?", BUFSIZ);
+ (void)strlcat(phrase, " ? ?", sizeof(phrase));
if (isnan(channel->fixbuffer.climb)==0)
(void)snprintf(phrase+strlen(phrase),
sizeof(phrase)-strlen(phrase),
" %.3f",
channel->fixbuffer.climb);
else
- (void)strlcat(phrase, " ?", BUFSIZ);
+ (void)strlcat(phrase, " ?", sizeof(phrase));
if (isnan(channel->fixbuffer.epd)==0)
(void)snprintf(phrase+strlen(phrase),
sizeof(phrase)-strlen(phrase),
" %.4f",
channel->fixbuffer.epd);
else
- (void)strlcat(phrase, " ?", BUFSIZ);
+ (void)strlcat(phrase, " ?", sizeof(phrase));
if (isnan(channel->fixbuffer.eps)==0)
(void)snprintf(phrase+strlen(phrase),
sizeof(phrase)-strlen(phrase),
" %.2f", channel->fixbuffer.eps);
else
- (void)strlcat(phrase, " ?", BUFSIZ);
+ (void)strlcat(phrase, " ?", sizeof(phrase));
if (isnan(channel->fixbuffer.epc)==0)
(void)snprintf(phrase+strlen(phrase),
sizeof(phrase)-strlen(phrase),
" %.2f", channel->fixbuffer.epc);
else
- (void)strlcat(phrase, " ?", BUFSIZ);
+ (void)strlcat(phrase, " ?", sizeof(phrase));
if (channel->fixbuffer.mode > 0)
(void)snprintf(phrase+strlen(phrase),
sizeof(phrase)-strlen(phrase),
" %d", channel->fixbuffer.mode);
else
- (void)strlcat(phrase, " ?", BUFSIZ);
+ (void)strlcat(phrase, " ?", sizeof(phrase));
}
break;
case 'P':
@@ -1352,7 +1354,7 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
channel->fixbuffer.latitude,
channel->fixbuffer.longitude);
else
- (void)strlcpy(phrase, ",P=?", BUFSIZ);
+ (void)strlcpy(phrase, ",P=?", sizeof(phrase));
break;
case 'Q':
#define ZEROIZE(x) (isnan(x)!=0 ? 0.0 : x)
@@ -1368,12 +1370,12 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
ZEROIZE(channel->device->gpsdata.tdop),
ZEROIZE(channel->device->gpsdata.gdop));
else
- (void)strlcpy(phrase, ",Q=?", BUFSIZ);
+ (void)strlcpy(phrase, ",Q=?", sizeof(phrase));
#undef ZEROIZE
break;
case 'R':
if ((channel = assign_channel(sub, ANY, NULL))==NULL)
- (void)strlcpy(phrase, ",R=?", sizeof(reply));
+ (void)strlcpy(phrase, ",R=?", sizeof(phrase));
else {
if (*p == '=') ++p;
if (*p == '2') {
@@ -1406,29 +1408,29 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
if ((channel=assign_channel(sub, GPS, NULL))!= NULL)
(void)snprintf(phrase, sizeof(phrase), ",S=%d", channel->device->gpsdata.status);
else
- (void)strlcpy(phrase, ",S=?", BUFSIZ);
+ (void)strlcpy(phrase, ",S=?", sizeof(phrase));
break;
case 'T':
if ((channel=assign_channel(sub, GPS, NULL))!= NULL && have_fix(channel) && isnan(channel->fixbuffer.track)==0)
(void)snprintf(phrase, sizeof(phrase), ",T=%.4f", channel->fixbuffer.track);
else
- (void)strlcpy(phrase, ",T=?", BUFSIZ);
+ (void)strlcpy(phrase, ",T=?", sizeof(phrase));
break;
case 'U':
if ((channel=assign_channel(sub, GPS, NULL))!= NULL && have_fix(channel) && channel->fixbuffer.mode == MODE_3D)
(void)snprintf(phrase, sizeof(phrase), ",U=%.3f", channel->fixbuffer.climb);
else
- (void)strlcpy(phrase, ",U=?", BUFSIZ);
+ (void)strlcpy(phrase, ",U=?", sizeof(phrase));
break;
case 'V':
if ((channel=assign_channel(sub, GPS, NULL))!= NULL && have_fix(channel) && isnan(channel->fixbuffer.speed)==0)
(void)snprintf(phrase, sizeof(phrase), ",V=%.3f", channel->fixbuffer.speed * MPS_TO_KNOTS);
else
- (void)strlcpy(phrase, ",V=?", BUFSIZ);
+ (void)strlcpy(phrase, ",V=?", sizeof(phrase));
break;
case 'W':
if ((channel = assign_channel(sub, ANY, NULL))==NULL)
- (void)strlcpy(phrase, ",W=?", sizeof(reply));
+ (void)strlcpy(phrase, ",W=?", sizeof(phrase));
else {
if (*p == '=') ++p;
if (*p == '1' || *p == '+') {
@@ -1453,23 +1455,23 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
if ((channel=assign_channel(sub, ANY, NULL))!= NULL && channel->device != NULL)
(void)snprintf(phrase, sizeof(phrase), ",X=%f", channel->device->gpsdata.online);
else
- (void)strlcpy(phrase, ",X=?", BUFSIZ);
+ (void)strlcpy(phrase, ",X=?", sizeof(phrase));
break;
case 'Y':
if ((channel=assign_channel(sub, GPS, NULL))!= NULL && channel->device->gpsdata.satellites > 0) {
int used, reported = 0;
- (void)strlcpy(phrase, ",Y=", BUFSIZ);
+ (void)strlcpy(phrase, ",Y=", sizeof(phrase));
if (channel->device->gpsdata.tag[0] != '\0')
- (void)strlcat(phrase, channel->device->gpsdata.tag, BUFSIZ);
+ (void)strlcat(phrase, channel->device->gpsdata.tag, sizeof(phrase));
else
- (void)strlcat(phrase, "-", BUFSIZ);
+ (void)strlcat(phrase, "-", sizeof(phrase));
if (isnan(channel->device->gpsdata.sentence_time)==0)
(void)snprintf(phrase+strlen(phrase),
sizeof(phrase)-strlen(phrase),
" %.3f ",
channel->device->gpsdata.sentence_time);
else
- (void)strlcat(phrase, " ? ", BUFSIZ);
+ (void)strlcat(phrase, " ? ", sizeof(phrase));
/* insurance against flaky drivers */
for (i = 0; i < channel->device->gpsdata.satellites; i++)
if (channel->device->gpsdata.PRN[i])
@@ -1498,11 +1500,11 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
gpsd_report(LOG_WARN,"Satellite count %d != PRN count %d\n",
channel->device->gpsdata.satellites, reported);
} else
- (void)strlcpy(phrase, ",Y=?", BUFSIZ);
+ (void)strlcpy(phrase, ",Y=?", sizeof(phrase));
break;
case 'Z':
if ((channel = assign_channel(sub, GPS, NULL))==NULL)
- (void)strlcpy(phrase, ",Z=?", sizeof(reply));
+ (void)strlcpy(phrase, ",Z=?", sizeof(phrase));
else {
if (*p == '=') ++p;
if (channel->device == NULL) {
@@ -1528,7 +1530,7 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
break;
case '$':
if ((channel=assign_channel(sub, GPS, NULL))== NULL)
- (void)strlcpy(phrase, ",$=?", BUFSIZ);
+ (void)strlcpy(phrase, ",$=?", sizeof(phrase));
else if (channel->device->gpsdata.sentence_time!=0)
(void)snprintf(phrase, sizeof(phrase), ",$=%s %d %lf %lf %lf %lf %lf %lf",
channel->device->gpsdata.tag,
@@ -1552,88 +1554,92 @@ static int handle_oldstyle(struct subscriber_t *sub, char *buf)
case '\r': case '\n':
goto breakout;
}
- if (strlen(reply) + strlen(phrase) < sizeof(reply) - 1)
- (void)strlcat(reply, phrase, BUFSIZ);
+ if (strlen(reply) + strlen(phrase) < replylen - 1)
+ (void)strlcat(reply, phrase, replylen);
else
- return -1; /* Buffer would overflow. Just return an error */
+ return false; /* Buffer would overflow. Just return an error */
}
breakout:
- (void)strlcat(reply, "\r\n", BUFSIZ);
-
- return (int)throttled_write(sub, reply, (ssize_t)strlen(reply));
+ (void)strlcat(reply, "\r\n", replylen);
+ return true;
}
#endif /* OLDSTYLE_ENABLE */
#ifdef GPSDNG_ENABLE
-static int handle_newstyle_request(struct subscriber_t *sub, const char *buf)
+static void handle_newstyle_request(struct subscriber_t *sub,
+ const char *buf, const char **after,
+ char *reply, size_t replylen)
{
- char reply[GPS_JSON_RESPONSE_MAX+1];
struct channel_t *channel;
const char *end;
+#if defined(OLDSTYLE_ENABLE) && defined(GPSDNG_ENABLE)
+ sub->new_style_responses = true;
+#endif /* defined(OLDSTYLE_ENABLE) && defined(GPSDNG_ENABLE) */
+
/*
* Still to be implemented: equivalents of B C N Z $
*/
if (strncmp(buf, "?TPV;", 5) == 0) {
if ((channel=assign_channel(sub, GPS, NULL))!= NULL && have_fix(channel)) {
json_tpv_dump(&channel->device->gpsdata, &channel->fixbuffer,
- reply, sizeof(reply));
+ reply, replylen);
} else {
(void)strlcpy(reply,
- "{\"class\":\"TPV\"}", sizeof(reply));
+ "{\"class\":\"TPV\"}", replylen);
}
buf += 5;
} else if (strncmp(buf, "?SKY;", 5) == 0) {
if ((channel=assign_channel(sub, GPS, NULL))!= NULL && channel->device->gpsdata.satellites > 0) {
- json_sky_dump(&channel->device->gpsdata, reply, sizeof(reply));
+ json_sky_dump(&channel->device->gpsdata, reply, replylen);
} else {
(void)strlcpy(reply,
- "{\"class\":\"SKY\"}", sizeof(reply));
+ "{\"class\":\"SKY\"}", replylen);
}
buf += 5;
} else if (strncmp(buf, "?DEVICES;", 9) == 0) {
int i;
(void)strlcpy(reply,
- "{\"class\"=\"DEVICES\",\"devices\":[", sizeof(reply));
+ "{\"class\"=\"DEVICES\",\"devices\":[", replylen);
for (i = 0; i < MAXDEVICES; i++) {
- if (allocated_device(&devices[i]) && strlen(reply)+strlen(devices[i].gpsdata.gps_device)+3 < sizeof(reply)-1) {
+ if (allocated_device(&devices[i]) && strlen(reply)+strlen(devices[i].gpsdata.gps_device)+3 < replylen-1) {
struct classmap_t *cmp;
- (void)strlcat(reply, "{\"class\":\"DEVICE\",\"name\":\"", sizeof(reply));
- (void)strlcat(reply, devices[i].gpsdata.gps_device, sizeof(reply));
- (void)strlcat(reply, "\",", sizeof(reply));
+ (void)strlcat(reply, "{\"class\":\"DEVICE\",\"name\":\"", replylen);
+ (void)strlcat(reply, devices[i].gpsdata.gps_device, replylen);
+ (void)strlcat(reply, "\",", replylen);
if (devices[i].observed != 0) {
- (void)strlcat(reply, "\"type\":[", sizeof(reply));
+ (void)strlcat(reply, "\"type\":[", replylen);
for (cmp = classmap; cmp < classmap+NITEMS(classmap); cmp++)
if ((devices[i].observed & cmp->mask) != 0) {
- (void)strlcat(reply, "\"", sizeof(reply));
- (void)strlcat(reply, cmp->name, sizeof(reply));
- (void)strlcat(reply, "\",", sizeof(reply));
+ (void)strlcat(reply, "\"", replylen);
+ (void)strlcat(reply, cmp->name, replylen);
+ (void)strlcat(reply, "\",", replylen);
}
if (reply[strlen(reply)-1] == ',')
reply[strlen(reply)-1] = '\0';
- (void)strlcat(reply, "],", sizeof(reply));
+ (void)strlcat(reply, "],", replylen);
}
if (devices[i].device_type != NULL) {
- (void)strlcat(reply, "\"driver\":\"", sizeof(reply));
+ (void)strlcat(reply, "\"driver\":\"", replylen);
(void)strlcat(reply,
devices[i].device_type->type_name,
- sizeof(reply));
- (void)strlcat(reply, "\",", sizeof(reply));
+ replylen);
+ (void)strlcat(reply, "\",", replylen);
}
if (devices[i].subtype[0] != '\0') {
- (void)strlcat(reply, "\",\"subtype\":\"", sizeof(reply));
+ (void)strlcat(reply, "\",\"subtype\":\"", replylen);
(void)strlcat(reply,
devices[i].subtype,
- sizeof(reply));
+ replylen);
}
if (reply[strlen(reply)-1] == ',')
reply[strlen(reply)-1] = '\0';
- (void)strlcat(reply, "},", sizeof(reply));
+ (void)strlcat(reply, "},", replylen);
}
}
if (reply[strlen(reply)-1] == ',')
reply[strlen(reply)-1] = '\0';
- (void)strlcat(reply, "]}", sizeof(reply));
+ (void)strlcat(reply, "]}", replylen);
buf += 9;
} else if (strncmp(buf, "?WATCH", 6) == 0 && (buf[6] == ';' || buf[6] == '=')) {
if (buf[6] == ';') {
@@ -1674,23 +1680,24 @@ static int handle_newstyle_request(struct subscriber_t *sub, const char *buf)
sub_index(sub), sub->watcher);
}
} else {
- (void)snprintf(reply, sizeof(reply),
+ (void)snprintf(reply, replylen,
"{\"class\":ERROR\",\"message\":\"Invalid WATCH.\",\"error\":\"%s\"}\r\n",
json_error_string(status));
(void)throttled_write(sub, reply, (ssize_t)strlen(reply));
}
buf = end;
}
- json_watch_dump(sub->watcher, reply, sizeof(reply));
+ json_watch_dump(sub->watcher, reply, replylen);
} else if (strncmp(buf, "?CONFIGCHAN", 11) == 0 && (buf[11] == ';' || buf[11] == '=')) {
if (channel_count(sub) == 0) {
for (buf = buf + 10; ;end++) {
if (*buf == '}' || *buf == ';' || *buf == '\0')
continue;
+ ++buf;
}
(void)strlcpy(reply,
"{\"class\":ERROR\",\"message\":\"No channels attached.\"}",
- sizeof(reply));
+ replylen);
} else {
struct channel_t *chp;
const char *pathp = NULL;
@@ -1707,7 +1714,7 @@ static int handle_newstyle_request(struct subscriber_t *sub, const char *buf)
} else if (conf.buffer_policy != -1 && (chp->device->observed & GPS_TYPEMASK)==0) {
(void)strlcpy(reply,
"{\"class\":ERROR\",\"message\":\"Attempt to apply buffer policy to a non-GPS device.\"}\r\n",
- sizeof(reply));
+ replylen);
(void)throttled_write(sub,
reply,(ssize_t)strlen(reply));
} else {
@@ -1728,7 +1735,7 @@ static int handle_newstyle_request(struct subscriber_t *sub, const char *buf)
chp->conf.scaled = conf.scaled;
}
} else
- (void)snprintf(reply, sizeof(reply),
+ (void)snprintf(reply, replylen,
"{\"class\":ERROR\",\"message\":\"Invalid CONFIGCHAN.\",\"error\":\"%s\"}\r\n",
json_error_string(status));
}
@@ -1743,8 +1750,8 @@ static int handle_newstyle_request(struct subscriber_t *sub, const char *buf)
json_configchan_dump(&chp->conf,
chp->device->gpsdata.gps_device,
reply + strlen(reply),
- sizeof(reply) - strlen(reply));
- (void)strlcat(reply, "\r\n", sizeof(reply));
+ replylen - strlen(reply));
+ (void)strlcat(reply, "\r\n", replylen);
}
if (reply[1]) /* avoid extra line termination at end */
reply[strlen(reply)-2] = '\0';
@@ -1755,10 +1762,11 @@ static int handle_newstyle_request(struct subscriber_t *sub, const char *buf)
for (buf = buf + 10; ;end++) {
if (*buf == '}' || *buf == ';' || *buf == '\0')
continue;
+ ++buf;
}
(void)strlcpy(reply,
"{\"class\":ERROR\",\"message\":\"No channels attached.\"}",
- sizeof(reply));
+ replylen);
} else {
struct channel_t *chp;
struct devconfig_t devconf;
@@ -1767,11 +1775,11 @@ static int handle_newstyle_request(struct subscriber_t *sub, const char *buf)
int status;
status = json_configdev_read(&devconf, buf+11, &buf);
if (status != 0)
- (void)snprintf(reply, sizeof(reply),
+ (void)snprintf(reply, replylen,
"{\"class\":ERROR\",\"message\":\"Invalid CONFIGDEV.\",\"error\":\"%s\"}\r\n",
json_error_string(status));
else if (chcount > 1 && devconf.device[0] == '\0')
- (void)snprintf(reply, sizeof(reply),
+ (void)snprintf(reply, replylen,
"{\"class\":ERROR\",\"message\":\"No path specified in CONFIGDEV, but multiple channels are subscribed.\"}\r\n");
else {
/* we should have exactly one device now */
@@ -1785,7 +1793,7 @@ static int handle_newstyle_request(struct subscriber_t *sub, const char *buf)
break;
}
if (!privileged_channel(channel))
- (void)snprintf(reply, sizeof(reply),
+ (void)snprintf(reply, replylen,
"{\"class\":ERROR\",\"message\":\"Multiple subscribers, cannot change control bits.\"}\r\n");
else {
/* now that channel is selected, apply changes */
@@ -1816,47 +1824,59 @@ static int handle_newstyle_request(struct subscriber_t *sub, const char *buf)
devconf.native = chp->device->gpsdata.driver_mode;
json_configdev_dump(&devconf,
reply + strlen(reply),
- sizeof(reply) - strlen(reply));
- (void)strlcat(reply, "\r\n", sizeof(reply));
+ replylen - strlen(reply));
+ (void)strlcat(reply, "\r\n", replylen);
}
if (reply[1]) /* avoid extra line termination at end */
reply[strlen(reply)-2] = '\0';
}
} else if (strncmp(buf, "?VERSION;", 9) == 0) {
- (void)snprintf(reply, sizeof(reply),
+ (void)snprintf(reply, replylen,
"{\"class\":\"VERSION\",\"version\":\"" VERSION "\",\"rev\":$Id$,\"api_major\":%d,\"api_minor\":%d}",
GPSD_API_MAJOR_VERSION, GPSD_API_MINOR_VERSION);
buf += 9;
} else {
- end = buf + strlen(buf) - 1;
- if (isspace(*end))
- --end;
- (void)snprintf(reply, sizeof(reply),
+ const char *errend;
+ errend = buf + strlen(buf) - 1;
+ if (isspace(*errend))
+ --errend;
+ (void)snprintf(reply, replylen,
"{\"class\":ERROR\",\"message\":\"Unrecognized request '%.*s'\"}",
- (int)(end-buf), buf);
+ (int)(errend-buf), buf);
+ buf += strlen(buf);
}
- (void)strlcat(reply, "\r\n", sizeof(reply));
- return (int)throttled_write(sub, reply, (ssize_t)strlen(reply));
+ (void)strlcat(reply, "\r\n", replylen);
+ *after = buf;
+#if defined(OLDSTYLE_ENABLE) && defined(GPSDNG_ENABLE)
+ sub->new_style_responses = false;
+#endif /* defined(OLDSTYLE_ENABLE) && defined(GPSDNG_ENABLE) */
}
#endif /* GPSDNG_ENABLE */
static int handle_gpsd_request(struct subscriber_t *sub, const char *buf)
{
+ char reply[GPS_JSON_RESPONSE_MAX+1];
+
+ reply[0] = '\0';
#ifdef GPSDNG_ENABLE
if (buf[0] == '?') {
-#if defined(OLDSTYLE_ENABLE) && defined(GPSDNG_ENABLE)
- sub->new_style_responses = true;
-#endif /* defined(OLDSTYLE_ENABLE) && defined(GPSDNG_ENABLE) */
- return handle_newstyle_request(sub, buf);
+ const char *end;
+ for (; *buf; buf++) {
+ if (buf[0] == '?') {
+ handle_newstyle_request(sub, buf, &end, reply, sizeof(reply));
+ buf = end-1;
+ }
+ }
}
#endif /* GPSDNG_ENABLE */
#ifdef OLDSTYLE_ENABLE
-#if defined(OLDSTYLE_ENABLE) && defined(GPSDNG_ENABLE)
- sub->new_style_responses = false;
-#endif /* defined(OLDSTYLE_ENABLE) && defined(GPSDNG_ENABLE) */
/* fall back to old-style requests */
- return handle_oldstyle(sub, (char *)buf);
+ if (buf[0] != '\0')
+ if (!handle_oldstyle(sub, (char *)buf, reply,sizeof(reply)))
+ return -1;
#endif /* OLDSTYLE_ENABLE */
+
+ return (int)throttled_write(sub, reply, (ssize_t)strlen(reply));
}
/*@ -mustfreefresh @*/
@@ -2298,8 +2318,10 @@ int main(int argc, char *argv[])
(void)strlcat(cmds, "y", 4);
if (channel->device->gpsdata.profiling!=0)
(void)strlcat(cmds, "$", 4);
- if (cmds[0] != '\0')
- (void)handle_oldstyle(sub, cmds);
+ if (cmds[0] != '\0') {
+ (void)handle_oldstyle(sub, cmds, buf2, sizeof(buf2));
+ (void)throttled_write(sub, buf2, strlen(buf2));
+ }
#ifdef AIVDM_ENABLE
if ((changed & AIS_SET) != 0) {
aivdm_dump(&channel->device->aivdm.decoded,