aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2015-01-21 14:53:33 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2015-01-21 14:56:15 +0200
commit03c5b9aac73c6a70b1c67f467bbd484d2a532f10 (patch)
tree33f32c496f86708cce8c6b914a08ece723ba72ee /src
parent5fe918d1f84af9b1f70deb152bf20d0b8a296524 (diff)
downloadeclat-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.opt24
-rw-r--r--src/ispeek.c173
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);
}

Return to:

Send suggestions and report system problems to the System administrator.