/* See LICENSE file for copyright and license details. */ #include "common.h" static char * spawn_read(struct libgeome_context *ctx, const char *path, const char *const *argv, size_t limit, unsigned int alarm_seconds) { struct spawn_join_info info; char *ret = NULL, *new; size_t size = 0; size_t len = 0; ssize_t r; int fd, status; if (libgeome_util_spawn_async_read(ctx, path, argv, alarm_seconds, &info, &fd)) return NULL; for (;;) { if (len == size) { size += 512U; new = realloc(ret, size); if (!new) { ctx->print_error(ctx, "realloc: %s\n", strerror(errno)); goto read_fail; } ret = new; } r = read(fd, &ret[len], size - len); if (r <= 0) { if (!r) break; if (errno == EINTR) continue; ctx->print_error(ctx, "read : %s\n", strerror(errno)); read_fail: close(fd); free(ret); ret = NULL; libgeome_util_spawn_async_kill(ctx, &info, SIGKILL); break; } len += (size_t)r; if (len >= limit) break; } if (len) { if (len == size) len--; ret[len] = '\0'; } else { free(ret); ret = NULL; } if (libgeome_util_spawn_async_join(ctx, &info, &status) || status != 0) { free(ret); ret = NULL; } return ret; } int libgeome_get_from_command(struct libgeome_context *ctx, struct libgeome_data *out, size_t limit, unsigned int alarm_secs, const char *path, const char *const *argv) { struct location location; char *text; text = spawn_read(ctx, path, argv, limit ? limit : 2048U, alarm_secs); if (!text) return -1; out->requested_data &= libgeome_util_parse_output(text, &location); free(text); if (out->requested_data & LIBGEOME_DATUM_LATITUDE) { if (!isfinite(location.latitude) || location.latitude < -90 || location.latitude > 90) { ctx->print_debug(ctx, "invalid latitude retrieved: %g\n", location.latitude); out->requested_data ^= LIBGEOME_DATUM_LATITUDE; } else { out->latitude = location.latitude; } } if (out->requested_data & LIBGEOME_DATUM_LONGITUDE) { if (!isfinite(location.longitude) || location.longitude < -180 || location.longitude > 180) { ctx->print_debug(ctx, "invalid longitude retrieved: %g\n", location.longitude); out->requested_data ^= LIBGEOME_DATUM_LONGITUDE; } else { out->longitude = location.longitude; } } return 0; }