diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-01-21 11:05:45 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-01-21 11:13:33 +0200 |
commit | 5fe918d1f84af9b1f70deb152bf20d0b8a296524 (patch) | |
tree | bf97fd6460a92260a1f3563c7583febe6ca863d1 /src | |
parent | f896658fd2c2c2b832536adb8af5ae6789c387a2 (diff) | |
download | eclat-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.am | 8 | ||||
-rw-r--r-- | src/io.c | 95 | ||||
-rw-r--r-- | src/ispeek-cl.opt | 76 | ||||
-rw-r--r-- | src/ispeek.c | 262 |
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\ @@ -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; +} |