aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2015-01-21 11:05:45 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2015-01-21 11:13:33 +0200
commit5fe918d1f84af9b1f70deb152bf20d0b8a296524 (patch)
treebf97fd6460a92260a1f3563c7583febe6ca863d1 /src
parentf896658fd2c2c2b832536adb8af5ae6789c387a2 (diff)
downloadeclat-5fe918d1f84af9b1f70deb152bf20d0b8a296524.tar.gz
eclat-5fe918d1f84af9b1f70deb152bf20d0b8a296524.tar.bz2
Add ispeek.
* src/ispeek.c: New file. * src/ispeek-cl.opt: New file * src/Makefile.am: Add ispeek * src/io.c (dump, eclat_trace_fun): Moved to the library. (eclat_io_setup): Use eclat_set_curl_trace. * NEWS: Document ispeek. * doc/Makefile.inc: Add ispeek.1 * doc/eclat.1man: Mention ispeek(1) in the "see also" section. * doc/eclat.conf.5: Update. * doc/ispeek.1: New file. * lib/Makefile.am (libeclat_a_SOURCES): Add trace.c * lib/libeclat.h (eclat_trace_fun) (eclat_set_curl_trace): New proto. * lib/trace.c: New file.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am8
-rw-r--r--src/io.c95
-rw-r--r--src/ispeek-cl.opt76
-rw-r--r--src/ispeek.c262
4 files changed, 347 insertions, 94 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 1c83ec2..0cd910e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with Eclat. If not, see <http://www.gnu.org/licenses/>.
-bin_PROGRAMS=eclat
+bin_PROGRAMS=eclat ispeek
eclat_SOURCES=\
accfile.c\
@@ -66,6 +66,10 @@ eclat_SOURCES=\
startstop.c\
util.c
+ispeek_SOURCES = \
+ ispeek.c\
+ ispeek-cl.h
+
LDADD=../lib/libeclat.a @LIBOBJS@ ../grecs/src/libgrecs.a $(CURL_LIBS) @MAPLIBS@
AM_CPPFLAGS = \
-I$(top_srcdir)/grecs/src/ -I$(top_srcdir)/lib $(CURL_CFLAGS)\
@@ -103,12 +107,14 @@ eclat_SOURCES += $(OPTFILES:.opt=.h)
BUILT_SOURCES=\
cmdline.h\
+ ispeek-cl.h\
$(OPTFILES:.opt=.h)\
comtab.man\
xref.man
EXTRA_DIST=\
cmdline.opt\
+ ispeek-cl.opt\
$(OPTFILES)\
comtab.man\
xref.man\
diff --git a/src/io.c b/src/io.c
index 366861e..2f40da7 100644
--- a/src/io.c
+++ b/src/io.c
@@ -1,5 +1,5 @@
/* This file is part of Eclat.
- Copyright (C) 2012-2014 Sergey Poznyakoff.
+ 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
@@ -20,92 +20,6 @@ extern FILE *xml_dump_file;
static void
-dump(const char *text, FILE *stream, unsigned char *ptr, size_t size)
-{
- size_t i;
- size_t c;
- unsigned int width = 0x10;
- int hex = debug_level(ECLAT_DEBCAT_CURL) > 2;
-
- if (!hex)
- /* without the hex output, we can fit more on screen */
- width = 0x40;
-
- fprintf(stream, "%s, %zd bytes (0x%zx)\n", text, size, size);
-
- for (i = 0; i < size; i += width) {
- fprintf(stream, "%04zx: ", i);
-
- if (hex) {
- for (c = 0; c < width; c++)
- if (i+c < size)
- fprintf(stream, "%02x ", ptr[i+c]);
- else
- fputs(" ", stream);
- }
-
- for(c = 0; (c < width) && (i+c < size); c++) {
- /* check for CRLf; if found, skip past and start a
- new line of output */
- if (!hex && (i + c + 1 < size) &&
- ptr[i+c] == '\r' && ptr[i+c+1] == '\n') {
- i += (c + 2 -width);
- break;
- }
- fprintf(stream, "%c",
- isprint(ptr[i+c]) ? ptr[i+c] : '.');
- /* check again for CRLF, to avoid an extra \n if
- it's at width */
- if (!hex && (i + c + 2 < size) &&
- ptr[i+c+1] == '\r' && ptr[i+c+2] == '\n') {
- i += (c + 3 - width);
- break;
- }
- }
- fputc('\n', stream); /* newline */
- }
- fflush(stream);
-}
-
-int
-eclat_trace_fun(CURL *handle, curl_infotype type,
- char *data, size_t size,
- void *userp)
-{
-/* struct data *config = (struct data *)userp;*/
- const char *text;
-
- switch (type) {
- case CURLINFO_TEXT:
- fprintf(stderr, "== Info: %s", data);
- default: /* in case a new one is introduced to shock us */
- return 0;
-
- case CURLINFO_HEADER_OUT:
- text = "=> Send header";
- break;
- case CURLINFO_DATA_OUT:
- text = "=> Send data";
- break;
- case CURLINFO_SSL_DATA_OUT:
- text = "=> Send SSL data";
- break;
- case CURLINFO_HEADER_IN:
- text = "<= Recv header";
- break;
- case CURLINFO_DATA_IN:
- text = "<= Recv data";
- break;
- case CURLINFO_SSL_DATA_IN:
- text = "<= Recv SSL data";
- break;
- }
-
- dump(text, stderr, (unsigned char *)data, size);
- return 0;
-}
-
-static void
dumpxml(void *ptr, size_t realsize)
{
static int open_failed = 0;
@@ -163,12 +77,7 @@ eclat_io_setup(struct eclat_io *io, int errfatal)
}
}
- if (debug_level(ECLAT_DEBCAT_CURL)) {
- curl_easy_setopt(io->curl, CURLOPT_VERBOSE, 1L);
- if (debug_level(ECLAT_DEBCAT_CURL) > 1)
- curl_easy_setopt(io->curl, CURLOPT_DEBUGFUNCTION,
- eclat_trace_fun);
- }
+ eclat_set_curl_trace(io->curl, debug_level(ECLAT_DEBCAT_CURL));
/* Create XML parser */
io->parser = XML_ParserCreate("UTF-8");
diff --git a/src/ispeek-cl.opt b/src/ispeek-cl.opt
new file mode 100644
index 0000000..0762f06
--- /dev/null
+++ b/src/ispeek-cl.opt
@@ -0,0 +1,76 @@
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_GETOPT_H
+# include <getopt.h>
+#endif
+
+OPTIONS_BEGIN("ispeek",
+ [<EC2 instance store lister>],
+ [<PATH [KEY...]>],
+ [<gnu>],
+ [<copyright_year=2012-2015>],
+ [<copyright_holder=Sergey Poznyakoff>])
+
+OPTION(base,b,URL,
+ [<base URL>])
+BEGIN
+ base_url = optarg;
+END
+
+OPTION(port,p,NUMBER,
+ [<set remote port number>])
+BEGIN
+ char *p;
+
+ errno = 0;
+ port = strtol(optarg, &p, 10);
+ if (port <= 0 || port > USHRT_MAX || errno || *p)
+ die(EX_USAGE, "invalid port number");
+END
+
+OPTION(recursive,r,,
+ [<list recursively>])
+BEGIN
+ recursive = 1;
+END
+
+OPTION(no-names,N,,
+ [<don't print key names>])
+BEGIN
+ print_names = 0;
+END
+
+OPTION(debug,d,,
+ [<increase debugging level>])
+BEGIN
+ debug_category[0].level++;
+END
+
+OPTIONS_END
+
+static void
+parse_options(int *pargc, char **pargv[])
+{
+ int argc = *pargc;
+ char **argv = *pargv;
+ int index;
+
+ GETOPT(argc, argv, index)
+ *pargc -= index;
+ *pargv += index;
+}
+
diff --git a/src/ispeek.c b/src/ispeek.c
new file mode 100644
index 0000000..c2e02ab
--- /dev/null
+++ b/src/ispeek.c
@@ -0,0 +1,262 @@
+/* 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 <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <curl/curl.h>
+#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";
+int print_names = 1;
+int recursive;
+long port;
+
+static char *
+make_url(const char *url, const char *path)
+{
+ char *p;
+ size_t len = strlen(url);
+
+ while (len > 0 && url[len-1] == '/')
+ --len;
+
+ while (*path == '/')
+ ++path;
+
+ p = grecs_malloc(len + strlen(path) + 2);
+ memcpy(p, url, len);
+ p[len++] = '/';
+ strcpy(p + len, path);
+ return p;
+}
+
+static size_t
+acc_cb(void *ptr, size_t size, size_t nmemb, void *data)
+{
+ size_t realsize = size * nmemb;
+ struct grecs_txtacc *acc = data;
+
+ grecs_txtacc_grow(acc, ptr, realsize);
+
+ return realsize;
+}
+
+static void
+list(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));
+
+ 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);
+
+ 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 = make_url(path, ws.ws_wordv[i]);
+ url = make_url(p, "/");
+ free(p);
+ } else if (ws.ws_wordv[i][strlen(ws.ws_wordv[i]) - 1] == '/') {
+ url = make_url(path, ws.ws_wordv[i]);
+ } else
+ continue;
+ list(url, curl, acc);
+ 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)
+{
+ CURLcode res;
+ long http_resp;
+ char *text;
+ char *url;
+
+ 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));
+
+ 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;
+
+ 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_names)
+ printf("%s:", key);
+ p = json_object_lookup(obj, key);
+ if (p) {
+ 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:
+ putchar('"');
+ for (s = p->v.s; *s; s++) {
+ if (*s == '"' || *s == '\\')
+ putchar('\\');
+ putchar(*s);
+ }
+ putchar('"');
+ break;
+ case json_arr:
+ printf("array");
+ break;
+ case json_obj:
+ printf("object");
+ break;
+ default:
+ abort();
+ }
+ }
+ 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++;
+
+ curl = curl_easy_init();
+ if (!curl)
+ die(EX_UNAVAILABLE, "curl_easy_init failed");
+ if (port)
+ curl_easy_setopt(curl, CURLOPT_PORT, (long) port);
+ 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);
+ 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;
+}

Return to:

Send suggestions and report system problems to the System administrator.