diff --git a/landerctl b/landerctl new file mode 100755 index 0000000..28f586f --- /dev/null +++ b/landerctl @@ -0,0 +1,53 @@ +#!/usr/bin/env sh + +API_KEY=test +URL=http://localhost:18080 + +if [[ "$2" != '-' ]]; then + filename="$2" + content_type="$(file --mime-type --brief $2)" +fi + + +if [ "$1" = g ]; then + exec curl -is "$URL/$2" | + sed -En 's/^[lL]ocation: (.*)/\1/p' + +elif [ "$1" = s ] || [ "$1" = sl ]; then + exec curl \ + --fail \ + -w "${URL}%header{location}" \ + -XPOST \ + -d "$2" \ + -H "X-Api-Key: $API_KEY" \ + "$URL/$1/$3" + +elif [ "$1" = p ] || [ "$1" = pl ]; then + exec curl \ + --fail \ + -w "${URL}%header{location}" \ + -XPOST \ + -H "X-Api-Key: $API_KEY" \ + -H "X-Lander-Filename: ${filename}" \ + --data-binary @"$2" \ + "$URL/$1/$3" + +elif [ "$1" = f ] || [ "$1" = fl ]; then + exec curl \ + --fail \ + -v \ + -w "${URL}%header{location}" \ + -XPOST \ + -H "X-Api-Key: $API_KEY" \ + -H "X-Lander-Content-Type: ${content_type}" \ + -H "X-Lander-Filename: ${filename}" \ + -T "$2" \ + "$URL/$1/$3" + +elif [ "$1" = d ]; then + exec curl \ + --fail \ + -XDELETE \ + -H "X-Api-Key: $API_KEY" \ + "$URL/$2" +fi diff --git a/landerctl/.landerrc b/landerctl/.landerrc deleted file mode 100644 index 964d3f2..0000000 --- a/landerctl/.landerrc +++ /dev/null @@ -1,2 +0,0 @@ -api_key = test -server_url = http://localhost:18080 diff --git a/landerctl/Makefile b/landerctl/Makefile deleted file mode 100644 index 72b8239..0000000 --- a/landerctl/Makefile +++ /dev/null @@ -1,120 +0,0 @@ -# https://spin.atomicobject.com/2016/08/26/makefile-c-projects/ was a great -# base for this Makefile - --include config.mk - -export CFLAGS -export LDFLAGS - -BIN := $(BUILD_DIR)/$(BIN_FILENAME) - -SRCS != find '$(SRC_DIR)' -iname '*.c' - -SRCS_H != find include -iname '*.h' - -OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) $(SRCS_THIRDPARTY:%=$(BUILD_DIR)/%.o) -DEPS := $(SRCS:%=$(BUILD_DIR)/%.d) - -_CFLAGS := $(addprefix -I,$(INC_DIRS)) $(CFLAGS) -Wall -Wextra -DLANDER_VERSION=\"$(VERSION)\" -_LDFLAGS := $(addprefix -L,$(LIB_DIRS)) $(addprefix -l,$(LIBS)) $(LDFLAGS) - -.PHONY: all -all: $(BIN) - - -# =====COMPILATION===== -# Utility used by the CI to lint -.PHONY: objs -objs: $(OBJS) - -$(BIN): $(OBJS) - $(CC) -o $@ $(OBJS) $(_LDFLAGS) - -$(BUILD_DIR)/$(SRC_DIR)/%.c.o: $(SRC_DIR)/%.c - mkdir -p $(dir $@) - $(CC) $(_CFLAGS) -c $< -o $@ - -$(BUILD_DIR)/$(THIRDPARTY_DIR)/%.c.o: $(THIRDPARTY_DIR)/%.c - mkdir -p $(dir $@) - $(CC) $(_CFLAGS) -c $< -o $@ - -# =====TESTING===== -.PHONY: run -run: $(BIN) - LANDER_API_KEY=test \ - LANDER_DATA_DIR=data \ - '$(BUILD_DIR)/$(BIN_FILENAME)' - -.PHONY: valgrind -valgrind: $(BIN) - LANDER_API_KEY=test \ - LANDER_DATA_DIR=data \ - valgrind '$(BUILD_DIR)/$(BIN_FILENAME)' - -.PHONY: test -test: $(TARGETS_TEST) - -.PHONY: test-mem -test-mem: $(TARGETS_MEM_TEST) - -.PHONY: $(TARGETS_TEST) -$(TARGETS_TEST): test-%: % - ./$^ - -.PHONY: $(TARGETS_MEM_TEST) -$(TARGETS_MEM_TEST): test-mem-%: % - valgrind --tool=memcheck --error-exitcode=1 --track-origins=yes --leak-check=full ./$^ - -.PHONY: build-test -build-test: $(BINS_TEST) - -$(BINS_TEST): %: %.c.o - $(CC) \ - $^ -o $@ - -# Along with the include directory, each test includes $(TEST_DIR) (which -# contains the acutest.h header file), and the src directory of the module it's -# testing. This allows tests to access internal methods, which aren't publicly -# exposed. -$(BUILD_DIR)/$(TEST_DIR)/%.c.o: $(TEST_DIR)/%.c - mkdir -p $(dir $@) - $(CC) $(_CFLAGS) -I$(TEST_DIR) \ - -I$(dir $(@:$(BUILD_DIR)/$(TEST_DIR)/%=$(SRC_DIR)/%)) \ - -c $< -o $@ - - -# =====MAINTENANCE===== -.PHONY: lint -lint: - clang-format -n --Werror $(SRCS) $(SRCS_H) $(SRCS_H_INTERNAL) - -.PHONY: fmt -fmt: - clang-format -i $(SRCS) $(SRCS_H) $(SRCS_H_INTERNAL) - -.PHONY: check -check: - mkdir -p $(BUILD_DIR)/cppcheck - cppcheck \ - $(addprefix -I,$(INC_DIRS)) \ - --cppcheck-build-dir=$(BUILD_DIR)/cppcheck \ - --project=compile_commands.json \ - --error-exitcode=1 \ - --enable=warning,style \ - --inline-suppr \ - --check-level=exhaustive \ - --quiet \ - -j$(shell nproc) - -.PHONY: clean -clean: - rm -rf $(BUILD_DIR) - -.PHONY: bear -bear: clean - bear -- make - bear --append -- make build-test - - -# Make make aware of the .d files --include $(DEPS) diff --git a/landerctl/config.mk b/landerctl/config.mk deleted file mode 100644 index 611faaf..0000000 --- a/landerctl/config.mk +++ /dev/null @@ -1,22 +0,0 @@ -VERSION := 0.2.0 - -BIN_FILENAME = landerctl - -BUILD_DIR = build -SRC_DIR = src -TEST_DIR = test - -INC_DIRS = include -LIBS = magic curl -LIB_DIRS = - -# -MMD: generate a .d file for every source file. This file can be imported by -# make and makes make aware that a header file has been changed, ensuring an -# object file is also recompiled if only a header is changed. -# -MP: generate a dummy target for every header file (according to the docs it -# prevents some errors when removing header files) -CFLAGS = -MMD -MP -g - -# When compiling release builds, these flags are better -# CLAGS = -O3 -# LDFLAGS = -flto diff --git a/landerctl/include/landerctl.h b/landerctl/include/landerctl.h deleted file mode 100644 index 7e01ed2..0000000 --- a/landerctl/include/landerctl.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef LANDERCTL -#define LANDERCTL - -#include - -#include - -typedef struct landerctl_cfg { - const char *api_key; - const char *server_url; -} landerctl_cfg; - -typedef enum landerctl_cfg_err { - landerctl_cfg_err_ok = 0, - landerctl_cfg_err_not_found, - landerctl_cfg_err_invalid, - landerctl_cfg_err_incomplete, -} landerctl_cfg_err; - -/** - * Try to parse the required config arguments from the config file - * - * @param out config to write values to. Existing values are overwritten - * @param path path to config file - */ -landerctl_cfg_err landerctl_cfg_parse(landerctl_cfg *out, const char *path); - -typedef enum landerctl_mode { - landerctl_mode_none = 0, - landerctl_mode_short, - landerctl_mode_paste, - landerctl_mode_file, -} landerctl_mode; - -struct curl_slist *landerctl_set_common(const landerctl_cfg *cfg, CURL *curl, - landerctl_mode mode, bool secure, - const char *key); -void landerctl_post_short(CURL *curl, const char *url); -void landerctl_post_paste(CURL *curl, const char *path); -void landerctl_post_file(CURL *curl, const char *path); - -#endif diff --git a/landerctl/src/cfg_parse.c b/landerctl/src/cfg_parse.c deleted file mode 100644 index 032a04b..0000000 --- a/landerctl/src/cfg_parse.c +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include -#include -#include - -#include "landerctl.h" - -static const char cfg_line_regex_expr[] = "^([^ ]+) *= *([^ ]+)$"; - -landerctl_cfg_err landerctl_cfg_parse(landerctl_cfg *out, const char *path) { - FILE *f = fopen(path, "r"); - - if (f == NULL) { - return landerctl_cfg_err_not_found; - } - - struct { - const char *key; - const char **var; - } key_to_vars[] = { - {"api_key", &out->api_key}, - {"server_url", &out->server_url}, - }; - size_t key_to_vars_len = sizeof(key_to_vars) / sizeof(key_to_vars[0]); - - // We NULL everything beforehand so we can check if we have all needed - // variables - for (size_t i = 0; i < key_to_vars_len; i++) { - *key_to_vars[i].var = NULL; - } - - regex_t cfg_line_regex; - regcomp(&cfg_line_regex, cfg_line_regex_expr, REG_EXTENDED); - - // Accept lines of at most 256 lines - char line[256]; - landerctl_cfg_err res = landerctl_cfg_err_ok; - - while (fgets(line, sizeof(line), f) != NULL) { - // Last character might be a newline - size_t len = strlen(line); - - if (line[len - 1] == '\n') { - line[len - 1] = '\0'; - } - - regmatch_t reg_groups[3]; - - if (regexec(&cfg_line_regex, line, 3, reg_groups, 0) != 0) { - res = landerctl_cfg_err_not_found; - - break; - } - - // api_key is currently the only value we parse - size_t key_len = reg_groups[1].rm_eo - reg_groups[1].rm_so; - - for (size_t i = 0; i < key_to_vars_len; i++) { - if ((key_len == strlen(key_to_vars[i].key)) && - (strncmp(&line[reg_groups[1].rm_so], key_to_vars[i].key, key_len) == - 0)) { - int val_len = reg_groups[2].rm_eo - reg_groups[2].rm_so; - char *buf = malloc(val_len + 1); - strncpy(buf, &line[reg_groups[2].rm_so], val_len); - buf[val_len] = '\0'; - - *key_to_vars[i].var = buf; - break; - } - } - } - - if (res == landerctl_cfg_err_ok) { - for (size_t i = 0; i < key_to_vars_len; i++) { - if (*key_to_vars[i].var == NULL) { - res = landerctl_cfg_err_incomplete; - break; - } - } - } - - fclose(f); - - return res; -} diff --git a/landerctl/src/main.c b/landerctl/src/main.c deleted file mode 100644 index a88d0cc..0000000 --- a/landerctl/src/main.c +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include - -#include "landerctl.h" - -const char *default_cfg_path = ".landerrc"; -const char *usage = "%s [-SPFsv] arg [key]\n"; - -int main(int argc, char **argv) { - landerctl_cfg cfg; - char *err_msg = NULL; - - switch (landerctl_cfg_parse(&cfg, default_cfg_path)) { - case landerctl_cfg_err_ok: - break; - case landerctl_cfg_err_not_found: - err_msg = "Config file not found"; - break; - case landerctl_cfg_err_invalid: - err_msg = "Invalid config file"; - break; - case landerctl_cfg_err_incomplete: - err_msg = "Incomplete config file"; - break; - } - - if (err_msg != NULL) { - fprintf(stderr, "%s\n", err_msg); - exit(1); - } - - opterr = 0; - - int c; - landerctl_mode mode = landerctl_mode_none; - bool secure = false; - bool verbose = false; - - while ((c = getopt(argc, argv, "SPFsv")) != -1) { - switch (c) { - case 'S': - mode = landerctl_mode_short; - break; - case 'P': - mode = landerctl_mode_paste; - break; - case 'F': - mode = landerctl_mode_file; - break; - case 's': - secure = true; - break; - case 'v': - verbose = true; - break; - case '?': - printf(usage, argv[0]); - exit(2); - } - } - - if (mode == landerctl_mode_none) { - printf("No mode specified.\n\n"); - printf(usage, argv[0]); - exit(2); - } - - if (optind == argc || (argc - optind > 2)) { - printf(usage, argv[0]); - exit(2); - } - - const char *arg = argv[optind]; - const char *key = argc - optind == 2 ? argv[optind + 1] : NULL; - - curl_global_init(CURL_GLOBAL_ALL); - CURL *curl = curl_easy_init(); - - if (curl == NULL) { - exit(255); - } - - struct curl_slist *list = landerctl_set_common(&cfg, curl, mode, secure, key); - - switch (mode) { - case landerctl_mode_short: - landerctl_post_short(curl, arg); - break; - } - - if (verbose) { - curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); - } - - int exit_code = 0; - - if (curl_easy_perform(curl) == CURLE_OK) { - long response_code; - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); - - if (response_code < 200 || response_code > 299) { - fprintf(stderr, "HTTP status code %li\n", response_code); - exit_code = 3; - } else { - struct curl_header *location_header; - - if (curl_easy_header(curl, "Location", 0, CURLH_HEADER, -1, - &location_header) == CURLHE_OK) { - printf("%s%s\n", cfg.server_url, location_header->value); - } else { - fprintf(stderr, "Server returned a 2xx without a Location header.\n"); - exit_code = 5; - } - } - } else { - fprintf(stderr, "Libcurl encountered an error.\n"); - exit_code = 4; - } - - curl_easy_cleanup(curl); - curl_slist_free_all(list); - - return exit_code; - - /* struct stat sb; */ - - /* stat(argv[1], &sb); */ - - /* printf("file size: %lu\n", sb.st_size); */ - - /* FILE *f = fopen(argv[1], "rb"); */ - - /* if (f == NULL) { */ - /* printf("Couldn't open file.\n"); */ - /* exit(1); */ - /* } */ - - /* CURL *curl = curl_easy_init(); */ - - /* if (curl == NULL) { */ - /* exit(1); */ - /* } */ - - /* curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:18080/f/"); */ - /* curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); */ - /* curl_easy_setopt(curl, CURLOPT_READDATA, f); */ - - /* curl_off_t file_size = sb.st_size; */ - /* /1* curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, file_size); *1/ */ - /* curl_easy_setopt(curl, CURLOPT_POST, 1L); */ - /* curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, file_size); */ - - /* magic_t cookie = magic_open(MAGIC_MIME_TYPE); */ - /* magic_load(cookie, NULL); */ - /* const char *mime_type = magic_file(cookie, argv[1]); */ - - /* char content_type_header[strlen(mime_type) + 24]; */ - /* sprintf(content_type_header, "X-Lander-Content-Type: %s", mime_type); */ - - /* char content_length_header[32]; */ - /* sprintf(content_length_header, "Content-Length: %lu", sb.st_size); */ - - /* struct curl_slist *list = NULL; */ - /* list = curl_slist_append(list, content_type_header); */ - /* list = curl_slist_append(list, content_length_header); */ - /* list = curl_slist_append(list, "X-Api-Key: test"); */ - - /* curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); */ - - /* curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); */ - /* curl_easy_perform(curl); */ - - /* curl_slist_free_all(list); */ -} diff --git a/landerctl/src/post.c b/landerctl/src/post.c deleted file mode 100644 index c0dd653..0000000 --- a/landerctl/src/post.c +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include - -#include "landerctl.h" - -struct curl_slist *landerctl_set_common(const landerctl_cfg *cfg, CURL *curl, - landerctl_mode mode, bool secure, - const char *key) { - size_t url_len = strlen(cfg->server_url) + 4; - - if (key != NULL) { - url_len += strlen(key); - } - - char mode_char; - - switch (mode) { - case landerctl_mode_short: - mode_char = 's'; - break; - case landerctl_mode_paste: - mode_char = 'p'; - break; - case landerctl_mode_file: - mode_char = 'f'; - break; - // Shouldn't be able to happen - default: - return NULL; - } - - char url[url_len + 1]; - - if (key == NULL) { - sprintf(url, "%s/%c%s/", cfg->server_url, mode_char, secure ? "l" : ""); - } else { - sprintf(url, "%s/%c%s/%s", cfg->server_url, mode_char, secure ? "l" : "", - key); - } - - curl_easy_setopt(curl, CURLOPT_URL, url); - - // Add API key header - char api_key_header[strlen(cfg->api_key) + 12]; - sprintf(api_key_header, "X-Api-Key: %s", cfg->api_key); - - struct curl_slist *list = NULL; - list = curl_slist_append(list, api_key_header); - - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); - - curl_easy_setopt(curl, CURLOPT_USERAGENT, "landerctl/" LANDER_VERSION ""); - - return list; -} - -void landerctl_post_short(CURL *curl, const char *url) { - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(url)); - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, url); -} diff --git a/src/http_loop/http_loop_steps.c b/src/http_loop/http_loop_steps.c index 99c5cce..c3ff36a 100644 --- a/src/http_loop/http_loop_steps.c +++ b/src/http_loop/http_loop_steps.c @@ -4,18 +4,6 @@ #include "http_loop.h" #include "lander.h" -// Just a naive pow implementation; might improve later -static uint64_t ipow(uint64_t base, uint64_t power) { - uint64_t res = 1; - - while (power > 0) { - res *= base; - power--; - } - - return res; -} - /* * Converts a string to a number, returning true if the string contained a valid * positive number. @@ -30,7 +18,7 @@ static bool string_to_num(size_t *res, const char *s, size_t len) { return false; } - *res += (uint64_t)val * ipow(10, (len - 1) - i); + *res += val * (int)pow(10, (len - 1) - i); } return true;