diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-01-21 14:53:33 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-01-21 14:56:15 +0200 |
commit | 03c5b9aac73c6a70b1c67f467bbd484d2a532f10 (patch) | |
tree | 33f32c496f86708cce8c6b914a08ece723ba72ee /src | |
parent | 5fe918d1f84af9b1f70deb152bf20d0b8a296524 (diff) | |
download | eclat-03c5b9aac73c6a70b1c67f467bbd484d2a532f10.tar.gz eclat-03c5b9aac73c6a70b1c67f467bbd484d2a532f10.tar.bz2 |
Improve ispeek
* doc/ispeek.1: Update.
* grecs: Upgrade
* src/ispeek-cl.opt: New options.
* src/ispeek.c: Optionally print variable types,
quote strings, etc.
Add heuristics to determine whether the obtained data are
a directory listing or a text.
Diffstat (limited to 'src')
-rw-r--r-- | src/ispeek-cl.opt | 24 | ||||
-rw-r--r-- | src/ispeek.c | 173 |
2 files changed, 133 insertions, 64 deletions
diff --git a/src/ispeek-cl.opt b/src/ispeek-cl.opt index 0762f06..dd0698c 100644 --- a/src/ispeek-cl.opt +++ b/src/ispeek-cl.opt @@ -48,10 +48,28 @@ BEGIN recursive = 1; END -OPTION(no-names,N,, - [<don't print key names>]) +OPTION(names,N,, + [<print key names>]) BEGIN - print_names = 0; + print_options |= PRINT_NAME; +END + +OPTION(quote,Q,, + [<quote strings>]) +BEGIN + print_options |= PRINT_QUOTE; +END + +OPTION(type,T,, + [<print value types>]) +BEGIN + print_options |= PRINT_TYPE; +END + +OPTION(delimiter,D,STRING, + [<use STRING as a delimiter, instead of colon>]) +BEGIN + delim = optarg; END OPTION(debug,d,, diff --git a/src/ispeek.c b/src/ispeek.c index c2e02ab..95e1a4c 100644 --- a/src/ispeek.c +++ b/src/ispeek.c @@ -30,7 +30,13 @@ #include "json.h" const char *base_url = "http://169.254.169.254/latest"; -int print_names = 1; + +#define PRINT_QUOTE 0x01 +#define PRINT_TYPE 0x02 +#define PRINT_NAME 0x04 + +int print_options; +char *delim = ":"; int recursive; long port; @@ -64,20 +70,17 @@ acc_cb(void *ptr, size_t size, size_t nmemb, void *data) return realsize; } -static void -list(const char *path, CURL *curl, struct grecs_txtacc *acc) +static char * +read_from(const char *path, CURL *curl, struct grecs_txtacc *acc) { CURLcode res; long http_resp; char *text; char *url; - struct wordsplit ws; - size_t i; - int isroot = strcmp(path, "/") == 0; url = make_url(base_url, path); curl_easy_setopt(curl, CURLOPT_URL, url); - + res = curl_easy_perform(curl); if (res != CURLE_OK) die(EX_UNAVAILABLE, "CURL: %s", curl_easy_strerror(res)); @@ -85,7 +88,7 @@ list(const char *path, CURL *curl, struct grecs_txtacc *acc) res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_resp); if (res != CURLE_OK) die(EX_UNAVAILABLE, "CURL: %s", curl_easy_strerror(res)); - + grecs_txtacc_grow_char(acc, 0); text = grecs_txtacc_finish(acc, 0); @@ -95,13 +98,46 @@ list(const char *path, CURL *curl, struct grecs_txtacc *acc) case 404: grecs_txtacc_free_string(acc, text); - return; + return NULL; default: die(EX_UNAVAILABLE, "CURL: got response %3d, url %s", http_resp, url); } free(url); + return text; +} + +struct closure { + char *text; + CURL *curl; + struct grecs_txtacc *acc; + char **argv; +}; + +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, @@ -120,54 +156,31 @@ list(const char *path, CURL *curl, struct grecs_txtacc *acc) url = make_url(path, ws.ws_wordv[i]); } else continue; - list(url, curl, acc); + list(url, cl); free(url); } } wordsplit_free(&ws); - grecs_txtacc_free_string(acc, text); } static void -cat(const char *path, CURL *curl, struct grecs_txtacc *acc, char **argv) +print_file(const char *path, struct closure *cl) { - CURLcode res; - long http_resp; - char *text; - char *url; - - url = make_url(base_url, path); - curl_easy_setopt(curl, CURLOPT_URL, url); + char *text = cl->text; + char **argv = cl->argv; - res = curl_easy_perform(curl); - if (res != CURLE_OK) - die(EX_UNAVAILABLE, "CURL: %s", curl_easy_strerror(res)); - - res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_resp); - if (res != CURLE_OK) - die(EX_UNAVAILABLE, "CURL: %s", curl_easy_strerror(res)); - - grecs_txtacc_grow_char(acc, 0); - text = grecs_txtacc_finish(acc, 0); - - switch (http_resp) { - case 200: - break; - - case 404: - grecs_txtacc_free_string(acc, text); - return; - - default: - die(EX_UNAVAILABLE, "CURL: got response %3d, url %s", - http_resp, url); - } - free(url); - 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, @@ -178,10 +191,12 @@ cat(const char *path, CURL *curl, struct grecs_txtacc *acc, char **argv) struct json_object *p; char *s; - if (print_names) - printf("%s:", key); + 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"); @@ -194,13 +209,17 @@ cat(const char *path, CURL *curl, struct grecs_txtacc *acc, char **argv) printf("%e", p->v.n); break; case json_string: - putchar('"'); - for (s = p->v.s; *s; s++) { - if (*s == '"' || *s == '\\') - putchar('\\'); - putchar(*s); - } - putchar('"'); + 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"); @@ -208,8 +227,6 @@ cat(const char *path, CURL *curl, struct grecs_txtacc *acc, char **argv) case json_obj: printf("object"); break; - default: - abort(); } } putchar('\n'); @@ -226,23 +243,57 @@ ispeek_do(char **argv) struct grecs_txtacc *acc; CURL *curl; const char *path = *argv++; + char *text; curl = curl_easy_init(); if (!curl) die(EX_UNAVAILABLE, "curl_easy_init failed"); if (port) curl_easy_setopt(curl, CURLOPT_PORT, (long) port); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); eclat_set_curl_trace(curl, debug_level(0)); - + acc = grecs_txtacc_create(); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, acc_cb); curl_easy_setopt(curl, CURLOPT_WRITEDATA, acc); - if (path[strlen(path) - 1] == '/') - list(path, curl, acc); - else - cat(path, curl, acc, argv); + 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); } |