/* This file is part of Eclat. Copyright (C) 2012-2015 Sergey Poznyakoff. Eclat is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Eclat is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Eclat. If not, see . */ #include #include #include #include #include #include #include #include #include #include "grecs.h" #include "grecsopt.h" #include "wordsplit.h" #include "libeclat.h" #include "json.h" const char *base_url = "http://169.254.169.254/latest"; #define PRINT_QUOTE 0x01 #define PRINT_TYPE 0x02 #define PRINT_NAME 0x04 int print_options; char *delim = ":"; int recursive; long port; struct closure { char *text; CURL *curl; struct grecs_txtacc *acc; char **argv; }; static char * read_from(const char *path, CURL *curl, struct grecs_txtacc *acc) { char *url; url = path_concat(base_url, path); if (instance_store_read(url, curl)) return NULL; grecs_txtacc_grow_char(acc, 0); return grecs_txtacc_finish(acc, 0); } static void print_dir(const char *path, struct closure *cl); static void list(const char *path, struct closure *cl) { char *text; cl->text = read_from(path, cl->curl, cl->acc); if (!cl->text) return; print_dir(path, cl); grecs_txtacc_free_string(cl->acc, cl->text); cl->text = NULL; } static void print_dir(const char *path, struct closure *cl) { char *text = cl->text; char *url; struct wordsplit ws; size_t i; int isroot = strcmp(path, "/") == 0; ws.ws_delim = "\r\n"; if (wordsplit(text, &ws, WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_SQUEEZE_DELIMS | WRDSF_DELIM | WRDSF_SHOWERR | WRDSF_ENOMEMABRT)) exit(EX_UNAVAILABLE); for (i = 0; i < ws.ws_wordc; i++) { printf("%s%s\n", path, ws.ws_wordv[i]); if (recursive) { if (isroot) { char *p = path_concat(path, ws.ws_wordv[i]); url = path_concat(p, "/"); free(p); } else if (ws.ws_wordv[i][strlen(ws.ws_wordv[i]) - 1] == '/') { url = path_concat(path, ws.ws_wordv[i]); } else continue; list(url, cl); free(url); } } wordsplit_free(&ws); } static void print_file(const char *path, struct closure *cl) { char *text = cl->text; char **argv = cl->argv; if (argv[0]) { char *key; struct json_object *obj; static char typestr[] = { [json_null] = '0', [json_bool] = 'b', [json_number] = 'n', [json_string] = 's', [json_arr] = 'a', [json_obj] = 'o' }; obj = json_parse_string(text, strlen(text)); if (!obj) die(EX_DATAERR, "%s: near %s", json_err_diag, json_err_ptr); while (key = *argv++) { struct json_object *p; char *s; if (print_options & PRINT_NAME) printf("%s%s", key, delim); p = json_object_lookup(obj, key); if (p) { if (print_options & PRINT_TYPE) printf("%c%s", typestr[p->type], delim); switch (p->type) { case json_null: printf("null"); break; case json_bool: printf("%s", p->v.b ? "true" : "false"); break; case json_number: printf("%e", p->v.n); break; case json_string: if (print_options & PRINT_QUOTE) { putchar('"'); for (s = p->v.s; *s; s++) { if (*s == '"' || *s == '\\') putchar('\\'); putchar(*s); } putchar('"'); } else printf("%s", p->v.s); break; case json_arr: printf("array"); break; case json_obj: printf("object"); break; } } putchar('\n'); } } else { printf("%s\n", text); } } static void ispeek_do(char **argv) { CURLcode res; struct grecs_txtacc *acc; CURL *curl; const char *path = *argv++; char *text; acc = grecs_txtacc_create(); curl = instance_store_curl_new(acc); if (port) curl_easy_setopt(curl, CURLOPT_PORT, (long) port); eclat_set_curl_trace(curl, debug_level(0)); text = read_from(path, curl, acc); if (text) { struct closure clos; void (*printer)(const char *, struct closure *); /* Decide how to print the data */ if (text[0] == '{') printer = print_file; else { CURLcode res; char *url; res = curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url); if (res != CURLE_OK) die(EX_UNAVAILABLE, "CURL: %s", curl_easy_strerror(res)); if (url[strlen(url) - 1] == '/') { if (path[strlen(path) - 1] != '/') { url = grecs_malloc(strlen(path) + 2); strcpy(url, path); strcat(url, "/"); path = url; } printer = print_dir; } else printer = print_file; } clos.text = text; clos.curl = curl; clos.acc = acc; clos.argv = argv; printer(path, &clos); } grecs_txtacc_free(acc); curl_easy_cleanup(curl); } #include "ispeek-cl.h" int main(int argc, char **argv) { set_program_name(argv[0]); debug_register("main"); parse_options(&argc, &argv); if (argc == 0) die(EX_USAGE, "not enough arguments"); ispeek_do(argv); return 0; }