summaryrefslogtreecommitdiffstats
path: root/src/blogc-git-receiver
diff options
context:
space:
mode:
Diffstat (limited to 'src/blogc-git-receiver')
-rw-r--r--src/blogc-git-receiver/main.c44
-rw-r--r--src/blogc-git-receiver/post-receive.c91
-rw-r--r--src/blogc-git-receiver/post-receive.h14
-rw-r--r--src/blogc-git-receiver/pre-receive-parser.c84
-rw-r--r--src/blogc-git-receiver/pre-receive-parser.h17
-rw-r--r--src/blogc-git-receiver/pre-receive.c318
-rw-r--r--src/blogc-git-receiver/pre-receive.h14
-rw-r--r--src/blogc-git-receiver/settings.c110
-rw-r--r--src/blogc-git-receiver/settings.h19
-rw-r--r--src/blogc-git-receiver/shell-command-parser.c101
-rw-r--r--src/blogc-git-receiver/shell-command-parser.h14
-rw-r--r--src/blogc-git-receiver/shell.c190
-rw-r--r--src/blogc-git-receiver/shell.h15
13 files changed, 0 insertions, 1031 deletions
diff --git a/src/blogc-git-receiver/main.c b/src/blogc-git-receiver/main.c
deleted file mode 100644
index 13218dd..0000000
--- a/src/blogc-git-receiver/main.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <libgen.h>
-#include "shell.h"
-#include "pre-receive.h"
-#include "post-receive.h"
-
-
-int
-main(int argc, char *argv[])
-{
- if (argc > 0) {
- if (0 == strcmp(basename(argv[0]), "pre-receive"))
- return bgr_pre_receive_hook(argc, argv);
- if (0 == strcmp(basename(argv[0]), "post-receive"))
- return bgr_post_receive_hook(argc, argv);
- }
-
- if (argc == 3 && (0 == strcmp(argv[1], "-c"))) {
- return bgr_shell(argc, argv);
- }
-
- // this is a hack to make blogc-git-receiver work out-of-the-box as a
- // `command=` in authorized_keys file. it will only work if the command
- // path is absolute.
- char *ssh_orig = getenv("SSH_ORIGINAL_COMMAND");
- if (argc == 1 && ssh_orig != NULL && argv[0][0] == '/') {
- setenv("SHELL", argv[0], 1);
- char* _argv[] = {argv[0], "-c", ssh_orig};
- return bgr_shell(3, _argv);
- }
-
- fprintf(stderr, "error: this is a special shell, go away!\n");
- return 1;
-}
diff --git a/src/blogc-git-receiver/post-receive.c b/src/blogc-git-receiver/post-receive.c
deleted file mode 100644
index 17a8aa7..0000000
--- a/src/blogc-git-receiver/post-receive.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-#include <libgen.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include "../common/utils.h"
-#include "../common/config-parser.h"
-#include "settings.h"
-#include "post-receive.h"
-
-
-int
-bgr_post_receive_hook(int argc, char *argv[])
-{
- int rv = 0;
- char *mirror = NULL;
-
- char *hooks_dir = dirname(argv[0]); // this was validated by main()
- char *real_hooks_dir = realpath(hooks_dir, NULL);
- if (real_hooks_dir == NULL) {
- fprintf(stderr, "error: failed to guess repository root: %s\n",
- strerror(errno));
- return 1;
- }
-
- char *repo_path = bc_strdup(dirname(real_hooks_dir));
- free(real_hooks_dir);
- if (0 != chdir(repo_path)) {
- fprintf(stderr, "error: failed to change to repository root\n");
- rv = 1;
- goto cleanup;
- }
-
- // local repository settings should take precedence, so if the repo have
- // the 'mirror' remote, just push to it.
- // this will be removed at some point, but will be kept for compatibility
- // with old setups.
- if ((0 == system("git config --local remote.mirror.pushurl > /dev/null")) ||
- (0 == system("git config --local remote.mirror.url > /dev/null")))
- {
- mirror = bc_strdup("mirror");
- goto push;
- }
-
- bc_config_t *config = bgr_settings_parse();
- if (config == NULL) {
- fprintf(stderr, "warning: repository mirroring disabled\n");
- goto cleanup;
- }
-
- char *section = bgr_settings_get_section(config, repo_path);
- if (section == NULL) {
- fprintf(stderr, "warning: repository mirroring disabled\n");
- bc_config_free(config);
- goto cleanup;
- }
-
- mirror = bc_strdup(bc_config_get(config, section, "mirror"));
- free(section);
- bc_config_free(config);
-
- if (mirror == NULL) {
- fprintf(stderr, "warning: repository mirroring disabled\n");
- goto cleanup;
- }
-
-push:
-
- {
- char *git_cmd = bc_strdup_printf("git push --mirror %s", mirror);
- if (0 != system(git_cmd))
- fprintf(stderr, "warning: failed push to git mirror\n");
- free(git_cmd);
- }
-
- free(mirror);
-
-cleanup:
- free(repo_path);
-
- return rv;
-}
diff --git a/src/blogc-git-receiver/post-receive.h b/src/blogc-git-receiver/post-receive.h
deleted file mode 100644
index fc56dc3..0000000
--- a/src/blogc-git-receiver/post-receive.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _POST_RECEIVE_H
-#define _POST_RECEIVE_H
-
-int bgr_post_receive_hook(int argc, char *argv[]);
-
-#endif /* _POST_RECEIVE_H */
diff --git a/src/blogc-git-receiver/pre-receive-parser.c b/src/blogc-git-receiver/pre-receive-parser.c
deleted file mode 100644
index 61a533c..0000000
--- a/src/blogc-git-receiver/pre-receive-parser.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2020 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include "../common/utils.h"
-#include "pre-receive-parser.h"
-
-typedef enum {
- START_OLD = 1,
- OLD,
- START_NEW,
- NEW,
- START_REF,
- REF
-} input_state_t;
-
-
-bc_trie_t*
-bgr_pre_receive_parse(const char *input, size_t input_len)
-{
- input_state_t state = START_OLD;
- size_t start = 0;
- size_t start_new = 0;
-
- bc_trie_t* rv = bc_trie_new(free);
-
- for (size_t current = 0; current < input_len; current++) {
-
- char c = input[current];
-
- switch (state) {
- case START_OLD:
- start = current;
- state = OLD;
- break;
- case OLD:
- if (c != ' ')
- break;
- // no need to store old
- state = START_NEW;
- break;
- case START_NEW:
- start = current;
- state = NEW;
- break;
- case NEW:
- if (c != ' ')
- break;
- state = START_REF;
- start_new = start;
- break;
- case START_REF:
- start = current;
- state = REF;
- break;
- case REF:
- if (c != '\n')
- break;
- state = START_OLD;
- if ((current - start > 11) &&
- (0 == strncmp("refs/heads/", input + start, 11)))
- {
- char *key = bc_strndup(input + start + 11, current - start - 11);
- bc_trie_insert(rv, key, bc_strndup(input + start_new, start - 1 - start_new));
- free(key);
- }
- break;
- }
- }
-
- if (bc_trie_size(rv) == 0) {
- bc_trie_free(rv);
- return NULL;
- }
-
- return rv;
-}
diff --git a/src/blogc-git-receiver/pre-receive-parser.h b/src/blogc-git-receiver/pre-receive-parser.h
deleted file mode 100644
index 45a9da8..0000000
--- a/src/blogc-git-receiver/pre-receive-parser.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2020 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _PRE_RECEIVE_PARSER_H
-#define _PRE_RECEIVE_PARSER_H
-
-#include <stddef.h>
-#include "../common/utils.h"
-
-bc_trie_t* bgr_pre_receive_parse(const char *input, size_t input_len);
-
-#endif /* _PRE_RECEIVE_PARSER_H */
diff --git a/src/blogc-git-receiver/pre-receive.c b/src/blogc-git-receiver/pre-receive.c
deleted file mode 100644
index 12d29cf..0000000
--- a/src/blogc-git-receiver/pre-receive.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2020 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
-#include <dirent.h>
-#include <time.h>
-#include <libgen.h>
-#include "../common/compat.h"
-#include "../common/utils.h"
-#include "../common/stdin.h"
-#include "settings.h"
-#include "pre-receive-parser.h"
-#include "pre-receive.h"
-
-
-static size_t
-cpu_count(void)
-{
-#ifdef _SC_NPROCESSORS_ONLN
- long num = sysconf(_SC_NPROCESSORS_ONLN);
- if (num >= 1)
- return (size_t) num;
-#endif
- return 1;
-}
-
-
-static void
-rmdir_recursive(const char *dir)
-{
- if (dir == NULL)
- return;
- struct stat buf;
- if (0 != stat(dir, &buf)) {
- return;
- }
- if (!S_ISDIR(buf.st_mode)) {
- fprintf(stderr, "error: trying to remove invalid directory: %s\n", dir);
- exit(2);
- }
- DIR *d = opendir(dir);
- if (d == NULL) {
- fprintf(stderr, "error: failed to open directory: %s\n",
- strerror(errno));
- exit(2);
- }
- struct dirent *e;
- while (NULL != (e = readdir(d))) {
- if ((0 == strcmp(e->d_name, ".")) || (0 == strcmp(e->d_name, "..")))
- continue;
- char *f = bc_strdup_printf("%s/%s", dir, e->d_name);
- if (0 != stat(f, &buf)) {
- fprintf(stderr, "error: failed to stat directory entry (%s): %s\n",
- e->d_name, strerror(errno));
- free(f);
- exit(2);
- }
- if (S_ISDIR(buf.st_mode)) {
- rmdir_recursive(f);
- }
- else if (0 != unlink(f)) {
- fprintf(stderr, "error: failed to remove file (%s): %s\n", f,
- strerror(errno));
- free(f);
- exit(2);
- }
- free(f);
- }
- if (0 != closedir(d)) {
- fprintf(stderr, "error: failed to close directory: %s\n",
- strerror(errno));
- exit(2);
- }
- if (0 != rmdir(dir)) {
- fprintf(stderr, "error: failed to remove directory: %s\n",
- strerror(errno));
- exit(2);
- }
-}
-
-
-int
-bgr_pre_receive_hook(int argc, char *argv[])
-{
- int rv = 0;
- char *ref = NULL;
- char *output_dir = NULL;
- char *tmpdir = NULL;
- char *sym = NULL;
-
- char *hooks_dir = dirname(argv[0]); // this was validated by main()
- char *real_hooks_dir = realpath(hooks_dir, NULL);
- if (real_hooks_dir == NULL) {
- fprintf(stderr, "error: failed to guess repository root: %s\n",
- strerror(errno));
- return 1;
- }
-
- char *repo_dir = bc_strdup(dirname(real_hooks_dir));
- free(real_hooks_dir);
- if (0 != chdir(repo_dir)) {
- fprintf(stderr, "error: failed to change to repository root\n");
- rv = 1;
- goto cleanup;
- }
-
- bc_config_t *config = bgr_settings_parse();
- if (config == NULL) {
- goto default_sym;
- }
-
- char *section = bgr_settings_get_section(config, repo_dir);
- if (section == NULL) {
- bc_config_free(config);
- goto default_sym;
- }
-
- const char *sym_tmp = bc_config_get(config, section, "symlink");
- if (sym_tmp == NULL) {
- free(section);
- bc_config_free(config);
- goto default_sym;
- }
-
- sym = bc_str_starts_with(sym_tmp, "/") ? bc_strdup(sym_tmp) :
- bc_strdup_printf("%s/%s", repo_dir, sym_tmp);
- free(section);
- bc_config_free(config);
-
-default_sym:
-
- if (sym == NULL) {
- sym = bc_strdup_printf("%s/htdocs", repo_dir);
- }
-
- if (NULL == getenv("GIT_DIR")) {
- if (0 != access(sym, R_OK)) {
- fprintf(stderr, "error: no previous build found. nothing to "
- "rebuild.\n");
- rv = 1;
- goto cleanup;
- }
- char *build_dir = realpath(sym, NULL);
- if (build_dir == NULL) {
- fprintf(stderr, "error: failed to get the hash of last built "
- "commit: %s\n", strerror(errno));
- rv = 1;
- goto cleanup;
- }
- char **pieces = bc_str_split(basename(build_dir), '-', 2);
- free(build_dir);
- if (bc_strv_length(pieces) != 2) {
- fprintf(stderr, "error: failed to parse the hash of last built "
- "commit.\n");
- bc_strv_free(pieces);
- rv = 1;
- goto cleanup;
- }
- ref = bc_strdup(pieces[0]);
- bc_strv_free(pieces);
- }
- else {
- size_t input_len;
- char *input = bc_stdin_read(&input_len);
- bc_trie_t *branches = bgr_pre_receive_parse(input, input_len);
-
- // try 'master' by default to avoid breaking existing setups
- ref = bc_strdup(bc_trie_lookup(branches, "master"));
- if (ref == NULL) {
- // try 'main'
- ref = bc_strdup(bc_trie_lookup(branches, "main"));
- }
-
- bc_trie_free(branches);
- free(input);
- }
-
- if (ref == NULL) {
- fprintf(stderr, "warning: no suitable branch found. "
- "nothing to deploy.\n");
- goto cleanup;
- }
-
- char dir[] = "/tmp/blogc_XXXXXX";
- if (NULL == mkdtemp(dir)) {
- rv = 1;
- goto cleanup;
- }
- tmpdir = dir;
-
- char *git_archive_cmd = bc_strdup_printf(
- "git archive \"%s\" | tar -x -C \"%s\" -f -", ref, tmpdir);
- if (0 != system(git_archive_cmd)) {
- fprintf(stderr, "error: failed to extract git content to temporary "
- "directory: %s\n", tmpdir);
- rv = 1;
- free(git_archive_cmd);
- goto cleanup;
- }
- free(git_archive_cmd);
-
- if (0 != chdir(tmpdir)) {
- fprintf(stderr, "error: failed to chdir (%s): %s\n", tmpdir,
- strerror(errno));
- rv = 1;
- goto cleanup;
- }
-
- char *buildsd = bgr_settings_get_builds_dir();
- if (buildsd == NULL) {
- fprintf(stderr, "error: failed to find builds directory path\n");
- rv = 1;
- goto cleanup;
- }
-
- unsigned long epoch = time(NULL);
- output_dir = bc_strdup_printf("%s/%s-%lu", buildsd, ref, epoch);
- free(buildsd);
-
- if (0 == access(output_dir, F_OK)) {
- char *tmp = output_dir;
- output_dir = bc_strdup_printf("%s-", tmp);
- free(tmp);
- }
-
- // detect if we will run blogc-make, make or nothing, and generate the
- // command.
- char *build_cmd = NULL;
- if (0 == access("blogcfile", F_OK)) {
- int status_bmake = system("blogc-make -v 2> /dev/null > /dev/null");
- if (127 == bc_compat_status_code(status_bmake)) {
- fprintf(stderr, "error: failed to find blogc-make binary\n");
- rv = 1;
- goto cleanup;
- }
- build_cmd = bc_strdup_printf("OUTPUT_DIR=\"%s\" blogc-make -V all",
- output_dir);
- }
- else if ((0 == access("Makefile", F_OK)) || (0 == access("GNUMakefile", F_OK))) {
- const char *make_impl = NULL;
-
- int status_gmake = system("gmake -f /dev/null 2> /dev/null > /dev/null");
- if (127 != bc_compat_status_code(status_gmake)) {
- make_impl = "gmake";
- }
- else {
- int status_make = system("make -f /dev/null 2> /dev/null > /dev/null");
- if (127 != bc_compat_status_code(status_make)) {
- make_impl = "make";
- }
- }
-
- if (make_impl == NULL) {
- fprintf(stderr, "error: no 'make' implementation found\n");
- rv = 1;
- goto cleanup;
- }
- build_cmd = bc_strdup_printf(
- "%s -j%d OUTPUT_DIR=\"%s\" BLOGC_GIT_RECEIVER=1", make_impl,
- cpu_count(), output_dir);
- }
- else {
- fprintf(stderr, "warning: no blogcfile or Makefile found. skipping ...\n");
- goto cleanup;
- }
-
- fprintf(stdout, "running command: %s\n\n", build_cmd);
- fflush(stdout);
- if (0 != system(build_cmd)) {
- fprintf(stderr, "error: failed to build website ...\n");
- rmdir_recursive(output_dir);
- free(build_cmd);
- rv = 1;
- goto cleanup;
- }
- free(build_cmd);
-
- char *htdocs_sym = realpath(sym, NULL);
- if ((htdocs_sym != NULL) && (0 != unlink(sym))) {
- fprintf(stderr, "error: failed to remove symlink (%s): %s\n", sym,
- strerror(errno));
- rmdir_recursive(output_dir);
- rv = 1;
- goto cleanup2;
- }
-
- if (0 != symlink(output_dir, sym)) {
- fprintf(stderr, "error: failed to create symlink (%s): %s\n", sym,
- strerror(errno));
- rmdir_recursive(output_dir);
- rv = 1;
- goto cleanup2;
- }
-
- if (htdocs_sym != NULL)
- rmdir_recursive(htdocs_sym);
-
-cleanup2:
- free(htdocs_sym);
-
-cleanup:
- free(sym);
- free(ref);
- free(output_dir);
- rmdir_recursive(tmpdir);
- free(repo_dir);
- return rv;
-}
diff --git a/src/blogc-git-receiver/pre-receive.h b/src/blogc-git-receiver/pre-receive.h
deleted file mode 100644
index ab19c47..0000000
--- a/src/blogc-git-receiver/pre-receive.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _PRE_RECEIVE_H
-#define _PRE_RECEIVE_H
-
-int bgr_pre_receive_hook(int argc, char *argv[]);
-
-#endif /* _PRE_RECEIVE_H */
diff --git a/src/blogc-git-receiver/settings.c b/src/blogc-git-receiver/settings.c
deleted file mode 100644
index db29b18..0000000
--- a/src/blogc-git-receiver/settings.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <stdio.h>
-#include <libgen.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdbool.h>
-#include "../common/utils.h"
-#include "../common/config-parser.h"
-#include "../common/error.h"
-#include "../common/file.h"
-#include "settings.h"
-
-
-const char*
-bgr_settings_get_base_dir(void)
-{
- char *rv = getenv("BLOGC_GIT_RECEIVER_BASE_DIR");
- if (rv != NULL) {
- return rv;
- }
- return getenv("HOME");
-}
-
-
-char*
-bgr_settings_get_builds_dir(void)
-{
- char *rv = getenv("BLOGC_GIT_RECEIVER_BUILDS_DIR");
- if (rv != NULL) {
- return bc_strdup(rv);
- }
- return bc_strdup_printf("%s/builds", bgr_settings_get_base_dir());
-}
-
-
-char*
-bgr_settings_get_section(bc_config_t *config, const char *repo_path)
-{
- const char *bd = bgr_settings_get_base_dir();
- if (bd == NULL) {
- return NULL;
- }
- char *rv = NULL;
- char** sections = bc_config_list_sections(config);
- for (size_t i = 0; sections[i] != NULL; i++) {
- if (bc_str_starts_with(sections[i], "repo:")) {
- char *tmp_repo = bc_strdup_printf("%s/repos/%s", bd, sections[i] + 5);
- char *real_tmp_repo = realpath(tmp_repo, NULL); // maybe not needed
- free(tmp_repo);
- if (real_tmp_repo == NULL)
- continue;
- if (0 == strcmp(real_tmp_repo, repo_path)) {
- rv = bc_strdup(sections[i]);
- free(real_tmp_repo);
- break;
- }
- free(real_tmp_repo);
- }
- }
- bc_strv_free(sections);
- return rv;
-}
-
-
-bc_config_t*
-bgr_settings_parse(void)
-{
- const char *bd = bgr_settings_get_base_dir();
- if (bd == NULL) {
- return NULL;
- }
- char *config_file = bc_strdup_printf("%s/blogc-git-receiver.ini", bd);
- if ((0 != access(config_file, F_OK))) {
- free(config_file);
- return NULL;
- }
-
- size_t len;
- bc_error_t *err = NULL;
- char* config_content = bc_file_get_contents(config_file, true, &len, &err);
- if (err != NULL) {
- fprintf(stderr, "warning: failed to read configuration file (%s): %s\n",
- config_file, err->msg);
- bc_error_free(err);
- free(config_file);
- free(config_content);
- return NULL;
- }
-
- bc_config_t *config = bc_config_parse(config_content, len, NULL, &err);
- free(config_content);
- if (err != NULL) {
- fprintf(stderr, "warning: failed to parse configuration file (%s): %s\n",
- config_file, err->msg);
- bc_error_free(err);
- free(config_file);
- return NULL;
- }
- free(config_file);
-
- return config;
-}
diff --git a/src/blogc-git-receiver/settings.h b/src/blogc-git-receiver/settings.h
deleted file mode 100644
index 04c1a2b..0000000
--- a/src/blogc-git-receiver/settings.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _SETTINGS_H
-#define _SETTINGS_H
-
-#include "../common/config-parser.h"
-
-const char* bgr_settings_get_base_dir(void);
-char* bgr_settings_get_builds_dir(void);
-char* bgr_settings_get_section(bc_config_t *config, const char *repo_path);
-bc_config_t* bgr_settings_parse(void);
-
-#endif /* _SETTINGS_H */
diff --git a/src/blogc-git-receiver/shell-command-parser.c b/src/blogc-git-receiver/shell-command-parser.c
deleted file mode 100644
index 0091e0b..0000000
--- a/src/blogc-git-receiver/shell-command-parser.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include "../common/utils.h"
-#include "shell-command-parser.h"
-
-typedef enum {
- START_COMMAND = 1,
- START_REPO,
- START_REPO2,
- REPO,
- START_ESCAPED,
-} command_state_t;
-
-
-char*
-bgr_shell_command_parse(const char *command)
-{
- command_state_t state = START_COMMAND;
- size_t start = 0;
- size_t command_len = strlen(command);
-
- bc_string_t *rv = bc_string_new();
-
- for (size_t current = 0; current < command_len; current++) {
-
- char c = command[current];
-
- switch (state) {
- case START_COMMAND:
- if (c == ' ') {
- if (((current == 16) &&
- (0 == strncmp("git-receive-pack", command, 16))) ||
- ((current == 15) &&
- (0 == strncmp("git-upload-pack", command, 15))) ||
- ((current == 18) &&
- (0 == strncmp("git-upload-archive", command, 18))))
- {
- state = START_REPO;
- break;
- }
- goto error;
- }
- break;
-
- case START_REPO:
- if (c == '\'') { // never saw git using double-quotes
- state = START_REPO2;
- break;
- }
- if (c == '\\') { // escaped ! or '
- state = START_ESCAPED;
- break;
- }
- goto error;
-
- case START_REPO2:
- if (c == '\'') {
- state = START_REPO;
- break;
- }
- start = current;
- if (rv->len == 0 && c == '/') { // no absolute urls
- start = current + 1;
- }
- state = REPO;
- break;
-
- case START_ESCAPED:
- if (c == '!' || c == '\'') {
- bc_string_append_c(rv, c);
- state = START_REPO;
- break;
- }
- goto error;
-
- case REPO:
- if (c == '\'') {
- bc_string_append_len(rv, command + start, current - start);
- state = START_REPO;
- break;
- }
- break;
- }
- }
-
- if (rv->len > 0)
- return bc_string_free(rv, false);
-
-error:
- bc_string_free(rv, true);
- return NULL;
-}
diff --git a/src/blogc-git-receiver/shell-command-parser.h b/src/blogc-git-receiver/shell-command-parser.h
deleted file mode 100644
index 818d098..0000000
--- a/src/blogc-git-receiver/shell-command-parser.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _SHELL_COMMAND_PARSER_H
-#define _SHELL_COMMAND_PARSER_H
-
-char* bgr_shell_command_parse(const char *command);
-
-#endif /* _SHELL_COMMAND_PARSER_H */
diff --git a/src/blogc-git-receiver/shell.c b/src/blogc-git-receiver/shell.c
deleted file mode 100644
index a4c8a2d..0000000
--- a/src/blogc-git-receiver/shell.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2020 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
-#include "../common/utils.h"
-#include "settings.h"
-#include "shell-command-parser.h"
-#include "shell.h"
-
-
-static bool
-lexists(const char *pathname)
-{
- struct stat b;
- int tmp_errno = errno;
- bool rv = lstat(pathname, &b) == 0;
- errno = tmp_errno;
- return rv;
-}
-
-
-int
-bgr_shell(int argc, char *argv[])
-{
- int rv = 0;
-
- char *repo = NULL;
- char *quoted_repo = NULL;
-
- // get shell path
- char *self = getenv("SHELL");
- if (self == NULL) {
- fprintf(stderr, "error: failed to find blogc-git-receiver path\n");
- rv = 1;
- goto cleanup;
- }
-
- // get base dir path
- const char *bd = bgr_settings_get_base_dir();
- if (bd == NULL) {
- fprintf(stderr, "error: failed to find base directory path\n");
- rv = 1;
- goto cleanup;
- }
-
- // validate command and extract git repository
- char *tmp_repo = bgr_shell_command_parse(argv[2]);
- if (tmp_repo == NULL) {
- fprintf(stderr, "error: invalid git-shell command: %s\n", argv[2]);
- rv = 1;
- goto cleanup;
- }
-
- repo = bc_strdup_printf("%s/repos/%s", bd, tmp_repo);
- quoted_repo = bc_shell_quote(repo);
- free(tmp_repo);
-
- if (0 == strncmp(argv[2], "git-upload-", 11)) // no need to check len here
- goto git_exec;
-
- if (0 != access(repo, F_OK)) {
- char *git_init_cmd = bc_strdup_printf(
- "git init --bare %s > /dev/null", quoted_repo);
- if (0 != system(git_init_cmd)) {
- fprintf(stderr, "error: failed to create git repository: %s\n",
- repo);
- rv = 1;
- free(git_init_cmd);
- goto cleanup;
- }
- free(git_init_cmd);
- }
-
- if (0 != chdir(repo)) {
- fprintf(stderr, "error: failed to chdir (%s): %s\n", repo,
- strerror(errno));
- rv = 1;
- goto cleanup;
- }
-
- if (0 != access("hooks", F_OK)) {
- // openwrt git package won't install git templates, then the git
- // repositories created with it won't have the hooks/ directory.
- if (0 != mkdir("hooks", 0777)) { // mkdir honors umask for us.
- fprintf(stderr, "error: failed to create directory (%s/hooks): "
- "%s\n", repo, strerror(errno));
- rv = 1;
- goto cleanup;
- }
- }
-
- if (0 != chdir("hooks")) {
- fprintf(stderr, "error: failed to chdir (%s/hooks): %s\n", repo,
- strerror(errno));
- rv = 1;
- goto cleanup;
- }
-
- if (lexists("pre-receive")) {
- if (0 != unlink("pre-receive")) {
- fprintf(stderr, "error: failed to remove old symlink "
- "(%s/hooks/pre-receive): %s\n", repo, strerror(errno));
- rv = 1;
- goto cleanup;
- }
- }
-
- if (0 != symlink(self, "pre-receive")) {
- fprintf(stderr, "error: failed to create symlink "
- "(%s/hooks/pre-receive): %s\n", repo, strerror(errno));
- rv = 1;
- goto cleanup;
- }
-
- if (lexists("post-receive")) {
- if (0 != unlink("post-receive")) {
- fprintf(stderr, "error: failed to remove old symlink "
- "(%s/hooks/post-receive): %s\n", repo, strerror(errno));
- rv = 1;
- goto cleanup;
- }
- }
-
- if (0 != symlink(self, "post-receive")) {
- fprintf(stderr, "error: failed to create symlink "
- "(%s/hooks/post-receive): %s\n", repo, strerror(errno));
- rv = 1;
- goto cleanup;
- }
-
-git_exec:
-
- if (0 != chdir(bd)) {
- fprintf(stderr, "error: failed to chdir (%s): %s\n", bd, strerror(errno));
- rv = 1;
- goto cleanup;
- }
-
- // static allocation instead of bc_strdup_printf to avoid leaks
- char buffer[4096];
- char *command = bc_strdup(argv[2]);
- char *p;
- for (p = command; *p != ' ' && *p != '\0'; p++);
- if (*p == ' ')
- *p = '\0';
-
- if (sizeof(buffer) < (strlen(command) + strlen(quoted_repo) + 2)) {
- fprintf(stderr, "error: git-shell command is too big\n");
- rv = 1;
- goto cleanup;
- }
-
- if (0 > snprintf(buffer, sizeof(buffer), "%s %s", command, quoted_repo)) {
- fprintf(stderr, "error: failed to generate git-shell command\n");
- rv = 1;
- goto cleanup;
- }
-
- free(command);
- free(repo);
- free(quoted_repo);
-
- // this is a hack. no memory handling should be done inside this block
- if (NULL == getenv("__VALGRIND_ENABLED")) {
- execlp("git-shell", "git-shell", "-c", buffer, NULL);
-
- // execlp only returns on error, then something bad happened
- fprintf(stderr, "error: failed to execute git-shell\n");
- return 1;
- }
-
- printf("git-shell -c \"%s\"\n", buffer); // used by tests, ignore
- return 0;
-
-cleanup:
- free(repo);
- free(quoted_repo);
- return rv;
-}
diff --git a/src/blogc-git-receiver/shell.h b/src/blogc-git-receiver/shell.h
deleted file mode 100644
index b59ff40..0000000
--- a/src/blogc-git-receiver/shell.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _SHELL_H
-#define _SHELL_H
-
-char* bgr_shell_get_repo(const char *command);
-int bgr_shell(int argc, char *argv[]);
-
-#endif /* _SHELL_H */