/* This file is part of Eclat. Copyright (C) 2012-2014 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 "eclat.h" #include #include int translation_enabled; char *custom_map; void translate_ids(int argc, char **argv, const char *mapname) { int i; struct eclat_map *map; char *val; char *q, *realname; int dir; int rc; if (!translation_enabled || argc == 0) return; if (custom_map) mapname = custom_map; dir = eclat_map_name_split(mapname, &realname, &q); if (dir == -1) die(EX_USAGE, "bad qualifier: %s", q); map = eclat_map_lookup(realname); if (!map) { debug(ECLAT_DEBCAT_MAIN, 1, ("no such map: %s", realname)); return; } if (eclat_map_open(map) != eclat_map_ok) die(EX_UNAVAILABLE, "failed to open map %s", realname); free(realname); for (i = 0; i < argc; i++) { if (!strchr(argv[i], '=')) { switch (rc = eclat_map_get(map, dir, argv[i], &val)) { case eclat_map_ok: argv[i] = val; break; case eclat_map_not_found: debug(ECLAT_DEBCAT_MAIN, 1, ("%s not found in map %s", argv[i], mapname)); break; default: die(EX_UNAVAILABLE, "cannot translate %s: %s", argv[i], eclat_map_strerror(rc)); } } } } char * eclat_stpcpy(char *p, char *q) { while (*p = *q++) ++p; return p; } #define RESOURCE_ID_PFX "resource-id=" #define RESOURCE_ID_LEN (sizeof(RESOURCE_ID_PFX) - 1) void translate_resource_ids(int argc, char **argv) { int i, j, rc, ecnt; size_t len; struct eclat_map *map; char *val, *p; struct wordsplit ws; int wsflags = WRDSF_DEFFLAGS|WRDSF_DELIM; if (!translation_enabled || argc == 0) return; ws.ws_delim = ","; for (i = 0; i < argc; i++) { if (strncmp(argv[i], RESOURCE_ID_PFX, RESOURCE_ID_LEN)) continue; if (wordsplit(argv[i] + RESOURCE_ID_LEN, &ws, wsflags)) die(EX_SOFTWARE, "error expanding argument %s: %s", argv[i] + RESOURCE_ID_LEN, wordsplit_strerror(&ws)); wsflags |= WRDSF_REUSE; for (j = 0, ecnt = 0; j < ws.ws_wordc; j++) { if (!(p = strchr(ws.ws_wordv[j], ':'))) continue; *p++ = 0; map = eclat_map_lookup(ws.ws_wordv[j]); if (!map) die(EX_UNAVAILABLE, "no such map: %s", ws.ws_wordv[j]); if (eclat_map_open(map) != eclat_map_ok) die(EX_UNAVAILABLE, "failed to open map %s", ws.ws_wordv[j]); rc = eclat_map_get(map, MAP_DIR, p, &val); if (rc != eclat_map_ok) { die(EX_UNAVAILABLE, "cannot translate %s using map %s: %s", p, ws.ws_wordv[j], eclat_map_strerror(rc)); } free(ws.ws_wordv[j]); ws.ws_wordv[j] = val; ecnt++; } if (ecnt == 0) continue; len = RESOURCE_ID_LEN + ws.ws_wordc - 1; for (j = 0; j < ws.ws_wordc; j++) len += strlen(ws.ws_wordv[j]); val = grecs_malloc(len + 1); strcpy(val, RESOURCE_ID_PFX); p = val + RESOURCE_ID_LEN; for (j = 0; j < ws.ws_wordc; j++) { if (j) *p++ = ','; p = eclat_stpcpy(p, ws.ws_wordv[j]); } argv[i] = val; } if (wsflags & WRDSF_REUSE) wordsplit_free(&ws); } int get_scr_cols() { struct winsize ws; ws.ws_col = ws.ws_row = 0; if ((ioctl(1, TIOCGWINSZ, (char *) &ws) < 0) || ws.ws_col == 0) { const char *p = getenv ("COLUMNS"); if (p) ws.ws_col = strtol(p, NULL, 10); } return ws.ws_col ? ws.ws_col : 80; } void describe_query_update(eclat_command_env_t *env, int argc, char **argv, const char *uparm, int n_in, int *n_out) { int i, j, k; struct ec2_query *q = env->query; char *bufptr = NULL; size_t bufsize = 0; struct wordsplit ws; int wsflags; int upn = 0; ws.ws_delim = ","; wsflags = WRDSF_DEFFLAGS | WRDSF_DELIM; for (i = 0, j = n_in; i < argc; i++) { char *p = strchr(argv[i], '='); if (!p) { if (uparm) { grecs_asprintf(&bufptr, &bufsize, "%s.%d", uparm, upn++); eclat_query_add_param(q, bufptr, argv[i]); continue; } die(EX_USAGE, "maformed filter: %s", argv[i]); } *p++ = 0; grecs_asprintf(&bufptr, &bufsize, "Filter.%d.Name", j); eclat_query_add_param(q, bufptr, argv[i]); if (wordsplit(p, &ws, wsflags)) die(EX_SOFTWARE, "wordsplit failed at \"%s\": %s", p, wordsplit_strerror(&ws)); wsflags |= WRDSF_REUSE; for (k = 0; k < ws.ws_wordc; k++) { grecs_asprintf(&bufptr, &bufsize, "Filter.%d.Value.%d", j, k+1); eclat_query_add_param(q, bufptr, ws.ws_wordv[k]); } ++j; } if (wsflags & WRDSF_REUSE) wordsplit_free(&ws); free(bufptr); if (n_out) *n_out = j; } void describe_query_create(eclat_command_env_t *env, int argc, char **argv, const char *uparm) { describe_query_update(env, argc, argv, uparm, 1, NULL); } int eclat_send_query(CURL *curl, struct ec2_query *q) { char *url; CURLcode res; int rc = 0; eclat_query_add_param(q, "AWSAccessKeyId", access_key); eclat_query_sign(q, secret_key, signature_version); url = eclat_query_to_url(q, NULL); debug(ECLAT_DEBCAT_MAIN, 1, ("using URL: %s", url)); curl_easy_setopt(curl, CURLOPT_URL, url); free(url); eclat_query_free(q); if (dry_run_mode) debug(ECLAT_DEBCAT_MAIN, 1, ("not sending request")); else { res = curl_easy_perform(curl); if (res != CURLE_OK) { err("CURL: %s", curl_easy_strerror(res)); rc = 1; } } return rc; } int eclat_actcmp(const char *a, const char *b) { int rc = 0; enum { cmp_init, cmp_norm, cmp_upca, cmp_upcb } state = cmp_init; while (rc == 0) { if (!*a) return *b ? - *b : 0; if (!*b) return *a ? *a : 0; if (*a == '-') { a++; if (state == cmp_norm) state = cmp_upca; else state = cmp_norm; } else if (*b == '-') { b++; if (state == cmp_norm) state = cmp_upcb; else state = cmp_norm; } else { switch (state) { case cmp_init: rc = toupper(*a) - toupper(*b); break; case cmp_norm: rc = *a - *b; break; case cmp_upca: rc = toupper(*a) - *b; break; case cmp_upcb: rc = *a - toupper(*b); break; } a++; b++; state = cmp_norm; } } return rc; } char **available_attrs; void list_attrs(FILE *fp) { size_t ncols = get_scr_cols(); int i, col, len; char *delim = ""; fprintf(fp, "Available attributes are:\n"); col = 0; for (i = 0; available_attrs[i]; i++) { len = strlen(delim) + strlen(available_attrs[i]); if (col + len > ncols) { fprintf(fp, ",\n%s", available_attrs[i]); col = strlen(available_attrs[i]); } else col += fprintf(fp, "%s%s", delim, available_attrs[i]); delim = ", "; } fputc('\n', fp); fputc('\n', fp); } char * canonattrname(char **attrs, const char *arg, char *delim, size_t *plen) { size_t len = strlen(arg); int i; for (i = 0; attrs[i]; i++) { size_t alen = delim ? strcspn(attrs[i], delim) : strlen(attrs[i]); if (alen == len && strncasecmp(arg, attrs[i], len) == 0) { if (plen) *plen = len; return attrs[i]; } } return NULL; }