marrakesh/mrk.c

505 lines
16 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <Eina.h>
#include <Ecore.h>
#include <Ecore_File.h>
#include "mrklib.h"
#define _mrk_err(args...) do { fprintf(stderr, ##args); exit(-1); } while (0)
static const char *server_host = "devs.enlightenment.org";
static int server_port = 10077;
static const char *build_tmpdir = "Marrakesh";
static const char *build_chkdir = "Marrakesh-Check";
static const char *build_objdir = "Marrakesh-Obj";
static const char *arch = NULL;
static const char *os = NULL;
static char key_priv_buf[4096];
static char key_cert_buf[4096];
static char get_cert_buf[4096];
static const char *key_priv = NULL;
static const char *key_cert = NULL;
static const char *get_cert = NULL;
static Eina_Bool move_to_cwd = EINA_FALSE;
static Eina_Bool install_bin = EINA_FALSE;
static Eina_Bool get_new_key = EINA_FALSE;
static void
_cb_connect(void *data EINA_UNUSED, Mrk *server EINA_UNUSED)
{
}
static void
_cb_disconnect(void *data EINA_UNUSED, Mrk *server EINA_UNUSED)
{
_mrk_err("Disconnect\n");
}
static void
status(double pos)
{
int i, p;
p = pos * 60;
putchar('\r');
putchar('[');
for (i = 0; i < p; i++) putchar('#');
printf("] %2.1f%%", pos * 100.0);
}
static void
_cb_upload_begin(void *data EINA_UNUSED, Mrk *server EINA_UNUSED)
{
status(0.0);
fflush(stdout);
}
static void
_cb_upload_progress(void *data EINA_UNUSED, Mrk *server EINA_UNUSED, double pos)
{
status(pos);
fflush(stdout);
}
static void
_cb_upload_end(void *data EINA_UNUSED, Mrk *server EINA_UNUSED)
{
status(1.0);
printf("\n");
fflush(stdout);
}
static void
_cb_upload_success(void *data EINA_UNUSED, Mrk *server EINA_UNUSED, Eina_Bool success)
{
if (!success) _mrk_err("Upload Failed\n");
ecore_main_loop_quit();
}
static void
_cb_download_begin(void *data EINA_UNUSED, Mrk *server EINA_UNUSED)
{
status(0.0);
fflush(stdout);
}
static void
_cb_download_progress(void *data EINA_UNUSED, Mrk *server EINA_UNUSED, double pos)
{
status(pos);
fflush(stdout);
}
static void
_cb_download_end(void *data EINA_UNUSED, Mrk *server EINA_UNUSED)
{
status(1.0);
printf("\n");
fflush(stdout);
}
static void
_cb_download_success(void *data EINA_UNUSED, Mrk *server EINA_UNUSED, const char *file)
{
if (!file) _mrk_err("Download Failed\n");
if (move_to_cwd)
{
const char *fname = ecore_file_file_get(file);
char tmp[PATH_MAX], wd[PATH_MAX];
if (!mrk_package_verify(file, get_cert))
_mrk_err("Failed to verify signature\n");
if (fname)
{
if (ecore_file_exists(fname)) _mrk_err("File: '%s' exists in ./\n", fname);
if (getcwd(wd, sizeof(wd)))
{
snprintf(tmp, sizeof(tmp), "%s/%s", wd, fname);
ecore_file_mv(file, tmp);
}
}
}
else if (install_bin)
{
if (!mrk_package_verify(file, get_cert))
_mrk_err("Failed to verify signature\n");
if (!mrk_package_bin_install(file, os, arch))
_mrk_err("Failed to install\n");
if (!mrk_package_bin_clean()) _mrk_err("Failed to clean\n");
ecore_file_unlink(file);
}
ecore_main_loop_quit();
}
static void
_cb_answer_begin(void *data EINA_UNUSED, Mrk *server EINA_UNUSED)
{
}
static void
_cb_answer_progress(void *data EINA_UNUSED, Mrk *server EINA_UNUSED, const char *result)
{
printf("%s\n", result);
}
static void
_cb_answer_end(void *data EINA_UNUSED, Mrk *server EINA_UNUSED)
{
ecore_main_loop_quit();
}
static void
_cb_getkey(void *data EINA_UNUSED, Mrk *server EINA_UNUSED, const char *result)
{
if (get_new_key)
{
FILE *f;
char *dir;
dir = ecore_file_dir_get(get_cert);
if (dir)
{
ecore_file_mkpath(dir);
free(dir);
}
f = fopen(get_cert, "wb");
if (f)
{
fwrite(result, strlen(result), 1, f);
fclose(f);
}
if ((!install_bin) && (!move_to_cwd)) ecore_main_loop_quit();
}
}
int
main(int argc, char **argv)
{
if (argc < 2)
{
printf("mrk sub commands:\n"
// " new\n"
" build\n"
" clean\n"
" bin\n"
" check\n"
" src\n"
" newkey\n"
" fixup\n"
" verify FILE\n"
" extract FILE\n"
" inst FILE\n"
" rm PKGNAME\n"
" rel [FILE]\n"
" getkey\n"
" down PKGNAME\n"
" get PKGNAME\n"
" getsrc PKGNAME\n"
" list [CATEGORY]\n"
" search KEY1 [KEY2] [KEY3] [...]\n"
" server REPODIR BUILDSCRIPT\n"
" index DIR1 [DIR2] [DIR3] [...]\n"
"\n");
return -1;
}
eina_init();
ecore_init();
mrk_init();
os = mrk_os_get();
arch = mrk_arch_get();
snprintf(key_priv_buf, sizeof(key_priv_buf),
"%s/.marrakesh/keys/default-priv.pem", getenv("HOME"));
snprintf(key_cert_buf, sizeof(key_cert_buf),
"%s/.marrakesh/keys/default-cert.pem", getenv("HOME"));
key_priv = key_priv_buf;
key_cert = key_cert_buf;
snprintf(get_cert_buf, sizeof(get_cert_buf),
"%s/.marrakesh/keys/Marrakesh-cert.pem", getenv("HOME"));
get_cert = get_cert_buf;
if (getenv("MRKHOST")) server_host = getenv("MRKHOST");
if (getenv("MRKPORT")) server_port = atoi(getenv("MRKPORT"));
if (getenv("MRKARCH")) arch = getenv("MRKARCH");
if (getenv("MRKOS")) os = getenv("MRKOS");
if (getenv("MRKDIR")) build_tmpdir = getenv("MRKDIR");
if (getenv("MRKCHKDIR")) build_chkdir = getenv("MRKCHKDIR");
if (getenv("MRKOBJDIR")) build_objdir = getenv("MRKOBJDIR");
if (getenv("MRKKEY")) key_priv = getenv("MRKKEY");
if (getenv("MRKCERT")) key_cert = getenv("MRKCERT");
if (!strcmp(argv[1], "build"))
{
Mrk_Build *bld = mrk_build_load("Marrakesh.mrk");
if (!bld) _mrk_err("Failed to load Marrakesh.mrk\n");
if (!mrk_build_do(bld, build_tmpdir, build_objdir))
{
mrk_build_free(bld);
_mrk_err("Failed to build Marrakesh.mrk\n");
}
mrk_build_free(bld);
}
else if (!strcmp(argv[1], "clean"))
{
ecore_file_recursive_rm(build_tmpdir);
ecore_file_recursive_rm(build_chkdir);
ecore_file_recursive_rm(build_objdir);
}
else if (!strcmp(argv[1], "newkey"))
{
char tmp[4096];
snprintf(tmp, sizeof(tmp), "%s/.marrakesh/keys", getenv("HOME"));
ecore_file_mkpath(tmp);
chmod(tmp, S_IRUSR | S_IWUSR | S_IXUSR);
snprintf(tmp, sizeof(tmp), "%s/.marrakesh", getenv("HOME"));
chmod(tmp, S_IRUSR | S_IWUSR | S_IXUSR);
snprintf(tmp, sizeof(tmp),
"openssl genrsa -out "
"%s/.marrakesh/keys/default-priv.pem "
"4096"
,
getenv("HOME"));
system(tmp);
snprintf(tmp, sizeof(tmp),
"openssl req "
"-x509 -new "
"-key %s/.marrakesh/keys/default-priv.pem "
"-out %s/.marrakesh/keys/default-cert.pem "
"-days 999999 "
"-subj /prompt=no"
,
getenv("HOME"),
getenv("HOME"));
system(tmp);
}
else if (!strcmp(argv[1], "src"))
{
char tmp[4096];
Mrk_Build *bld = mrk_build_load("Marrakesh.mrk");
if (!bld) _mrk_err("Failed to load Marrakesh.mrk\n");
snprintf(tmp, sizeof(tmp), "%s-%s.mks", bld->name, bld->version);
if (!mrk_build_package_src(bld, "Marrakesh.mrk", tmp,
key_cert, key_priv))
{
mrk_build_free(bld);
_mrk_err("Failed to package up source\n");
}
mrk_build_free(bld);
}
else if (!strcmp(argv[1], "bin"))
{
char tmp[4096];
Mrk_Build *bld = mrk_build_load("Marrakesh.mrk");
if (!bld) _mrk_err("Failed to load Marrakesh.mrk\n");
snprintf(tmp, sizeof(tmp), "%s-%s.mkb", bld->name, bld->version);
if (!ecore_file_exists(build_tmpdir)) _mrk_err("No build dir!\n");
if (!mrk_build_package_bin(bld, tmp, build_tmpdir, os, arch,
key_cert, key_priv))
{
mrk_build_free(bld);
_mrk_err("Failed to package up binary\n");
}
mrk_build_free(bld);
}
else if (!strcmp(argv[1], "verify"))
{
if (argc < 2) _mrk_err("Must provide FILE.MK[SB]\n");
if (!mrk_package_verify(argv[2], key_cert)) _mrk_err("Failed to verify\n");
printf("OK\n");
}
else if (!strcmp(argv[1], "extract"))
{
if (argc < 2) _mrk_err("Must provide FILE.MKS\n");
if (!mrk_package_src_extract(argv[2], "./")) _mrk_err("Failed to extract\n");
}
else if (!strcmp(argv[1], "inst"))
{
if (argc < 2) _mrk_err("Must provide FILE.MKB\n");
if (!mrk_package_bin_install(argv[2], os, arch))
_mrk_err("Failed to install\n");
if (!mrk_package_bin_clean()) _mrk_err("Failed to clean\n");
}
else if (!strcmp(argv[1], "fixup"))
{
if (!mrk_package_bin_clean()) _mrk_err("Failed to fix up dangling links\n");
}
else if (!strcmp(argv[1], "rm"))
{
if (argc < 2) _mrk_err("Must provide PACKAGENAME\n");
if (!mrk_package_bin_remove(argv[2])) _mrk_err("Failed to remove\n");
if (!mrk_package_bin_clean()) _mrk_err("Failed to clean\n");
}
else if (!strcmp(argv[1], "new"))
{
}
else if (!strcmp(argv[1], "check"))
{
Mrk_Build *bld;
char tmp[4096];
ecore_file_recursive_rm(build_chkdir);
ecore_file_mkdir(build_chkdir);
bld = mrk_build_load("Marrakesh.mrk");
if (!bld) _mrk_err("Failed to load Marrakesh.mrk\n");
if (!mrk_build_do(bld, build_tmpdir, build_objdir))
{
mrk_build_free(bld);
_mrk_err("Failed to build Marrakesh.mrk\n");
}
snprintf(tmp, sizeof(tmp), "%s-%s.mks", bld->name, bld->version);
if (!mrk_build_package_src(bld, "Marrakesh.mrk", tmp,
key_cert, key_priv))
{
mrk_build_free(bld);
_mrk_err("Failed to package up source\n");
}
snprintf(tmp, sizeof(tmp), "%s-%s.mkb", bld->name, bld->version);
if (!mrk_build_package_bin(bld, tmp, build_tmpdir, os, arch,
key_cert, key_priv))
{
mrk_build_free(bld);
_mrk_err("Failed to package up binary\n");
}
mrk_build_free(bld);
}
else if (!strcmp(argv[1], "index"))
{
int i;
for (i = 2; i < argc; i++) mrk_index(argv[i]);
}
else if (!strcmp(argv[1], "server"))
{
Mrk_Serve *serve;
if (argc < 3) _mrk_err("Must provide REPODIR BUILDSCRIPT as arguments\n");
serve = mrk_serve(NULL, server_port, argv[2], argv[3]);
ecore_main_loop_begin();
mrk_unserve(serve);
}
else
{
static Mrk *server;
server = mrk_connect(server_host, server_port);
if (server)
{
mrk_callback_connect_set(server,
_cb_connect, NULL,
_cb_disconnect, NULL);
mrk_callback_upload_set(server,
_cb_upload_begin, NULL,
_cb_upload_progress, NULL,
_cb_upload_end, NULL,
_cb_upload_success, NULL);
mrk_callback_download_set(server,
_cb_download_begin, NULL,
_cb_download_progress, NULL,
_cb_download_end, NULL,
_cb_download_success, NULL);
mrk_callback_answer_set(server,
_cb_answer_begin, NULL,
_cb_answer_progress, NULL,
_cb_answer_end, NULL);
mrk_callback_getkey_set(server,
_cb_getkey, NULL);
if (!strcmp(argv[1], "down"))
{
if (argc < 2) _mrk_err("Must provide PKGNAME as argument\n");
move_to_cwd = EINA_TRUE;
mrk_download(server, argv[2]);
}
else if (!strcmp(argv[1], "getkey"))
{
get_new_key = EINA_TRUE;
mrk_getkey(server);
}
else if (!strcmp(argv[1], "get"))
{
if (argc < 2) _mrk_err("Must provide PKGNAME as argument\n");
install_bin = EINA_TRUE;
if (!ecore_file_exists(get_cert))
{
get_new_key = EINA_TRUE;
mrk_getkey(server);
}
mrk_download(server, argv[2]);
}
else if (!strcmp(argv[1], "rel"))
{
char tmp[4096];
Mrk_Build *bld = mrk_build_load("Marrakesh.mrk");
if (!bld) _mrk_err("Failed to load Marrakesh.mrk\n");
snprintf(tmp, sizeof(tmp), "%s-%s.mks", bld->name, bld->version);
if (!mrk_build_package_src(bld, "Marrakesh.mrk", tmp,
key_cert, key_priv))
{
mrk_build_free(bld);
_mrk_err("Failed to package up source\n");
}
mrk_build_free(bld);
mrk_upload(server, tmp);
}
else if (!strcmp(argv[1], "list"))
{
if (argc < 2) mrk_list(server, NULL);
else mrk_list(server, argv[2]);
}
else if (!strcmp(argv[1], "search"))
{
int i;
int len = 0;
char *ts;
if (argc < 2) _mrk_err("Must provide 1 or more keys as aruments\n");
for (i = 2; i < argc; i++)
{
len += strlen(argv[i]);
len++;
}
ts = malloc(len);
if (ts)
{
ts[0] = 0;
for (i = 2; i < argc; i++)
{
strcat(ts, argv[i]);
if (i < (argc - 1)) strcat(ts, " ");
}
mrk_search(server, ts);
free(ts);
}
}
else if (!strcmp(argv[1], "getsrc"))
{
if (argc < 2) _mrk_err("Must provide PKGNAME as argument\n");
move_to_cwd = EINA_TRUE;
if (!ecore_file_exists(get_cert))
{
get_new_key = EINA_TRUE;
mrk_getkey(server);
}
mrk_download_source(server, argv[2]);
}
ecore_main_loop_begin();
mrk_disconnect(server);
}
else _mrk_err("Cannot connect\n");
}
mrk_shutdown();
ecore_shutdown();
eina_shutdown();
return 0;
}