marrakesh/mrk.c

1758 lines
53 KiB
C

/*
gcc mrk.c -o mrk `pkg-config --cflags --libs eina ecore-file eet`
*/
// note that this code is far from clean or nice at all. it's not very robust
// but it works for the purposes of a proof of concept and getting things off
// the ground - so please judge it by that for now
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <Eina.h>
#include <Ecore.h>
#include <Ecore_File.h>
#include <Ecore_Ipc.h>
#include <Eet.h>
#include "mrk-proto.h"
typedef enum
{
TMODE_EOL,
TMODE_PATH,
TMODE_TEXT,
TMODE_PATH_CP,
TMODE_PATH_CP_LIST,
TMODE_PATH_LIST,
} Tag_Mode;
typedef struct
{
const char *tag;
Tag_Mode mode;
} Tag_Type;
typedef struct
{
char *bin;
Eina_List *srcs;
Eina_List *deps;
Eina_List *incs;
} Build_Bin;
typedef struct
{
char *src;
char *dest;
} Build_Data;
typedef struct
{
char *name;
char *icon;
char *brief;
char *version;
char *license;
char *domain;
char *repo;
char *devrepo;
char *contact;
Eina_List *tags;
Eina_List *categories;
Eina_List *copying;
char *needs;
Eina_List *bins;
Eina_List *data;
Eina_List *desktops;
Eina_List *icons;
Eina_List *po;
} Build;
static const Tag_Type tags[] =
{
{"PROJ:", TMODE_EOL},
{"PROJICON:", TMODE_PATH},
{"BRIEF:", TMODE_TEXT},
{"VERSION:", TMODE_EOL},
{"LICENSE:", TMODE_EOL},
{"COPYING:", TMODE_PATH_LIST},
{"NEEDS:", TMODE_EOL},
{"DOMAIN:", TMODE_PATH},
{"REPO:", TMODE_EOL},
{"DEVREPO:", TMODE_EOL},
{"CONTACT:", TMODE_TEXT},
{"CATEGORY:", TMODE_PATH_LIST},
{"TAGS:", TMODE_PATH_LIST},
{"BIN:", TMODE_PATH},
{"SRC:", TMODE_PATH_LIST},
{"DEPS:", TMODE_PATH_LIST},
{"INC:", TMODE_PATH_LIST},
{"DATA:", TMODE_PATH_CP_LIST},
{"DESKTOP:", TMODE_PATH_LIST},
{"ICON:", TMODE_PATH_LIST},
{"PODOMAIN:", TMODE_PATH},
{"PO:", TMODE_PATH_LIST},
{NULL, 0} // END OF LIST
};
static Build build = { 0 };
static char *tmpd = "Marrakesh";
static const char *sane_name_veto[] = {"../", "./", "/", NULL};
static const char *sane_name_ok = "01234567890-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ. ";
static const char *sane_path_veto[] = {"../", "./", NULL};
static const char *sane_path_ok = "01234567890-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ. ";
static char *server = "devs.enlightenment.org";
static int server_port = 10077;
static char *arch = ARCH;
static char *os = OS;
static void
err(char *msg)
{
fprintf(stderr, "ERROR: %s\n", msg);
exit(1);
}
static int
sane_forbidden_path(const char *file, const char **forbidden)
{
int i;
for (i = 0; forbidden[i]; i++)
{
if (strstr(forbidden[i], file)) return 0;
}
return 1;
}
static int
sane_allowed_path(const char *file, const char *allowed)
{
int i, j;
for (i = 0; file[i]; i++)
{
int ok;
ok = 0;
for (j = 0; allowed[j]; j++)
{
if (file[i] == allowed[j])
{
ok = 1;
break;
}
}
if (!ok) return 0;
}
return 1;
}
static char *
parse_token(char **p, char *end)
{
char *tok, *seg;
while ((*p < end) && (isspace(**p))) (*p)++;
if (*p >= end) return NULL;
tok = *p;
while (*p < end)
{
if (isspace(**p)) goto token;
(*p)++;
}
token:
seg = malloc(*p - tok + 1);
if (!seg) return NULL;
memcpy(seg, tok, *p - tok);
seg[*p - tok] = 0;
return seg;
}
static char *
parse_eol(char **p, char *end)
{
char *tok, *seg;
while ((*p < end) && (isspace(**p))) (*p)++;
if (*p >= end) return NULL;
tok = *p;
while (*p < end)
{
if (**p == '\n') goto token;
(*p)++;
}
token:
seg = malloc(*p - tok + 1);
if (!seg) return NULL;
memcpy(seg, tok, *p - tok);
seg[*p - tok] = 0;
return seg;
}
static char *
path_check(char *tok)
{
// XXX: check me
return strdup(tok);
}
static int
parse_content(char *mem, size_t size)
{
char prevc = '\n';
char *end = mem + size;
char *p = mem;
int skipline = 0;
int startline = 0;
char *seg = NULL, *s;
char *data1 = NULL, *data2 = NULL;
int i;
Tag_Mode mode = TMODE_TEXT;
while (p < end)
{
if (prevc == '\n')
{
if (*p == '#') skipline = 1;
else skipline = 0;
startline = 1;
}
if (!skipline)
{
char *tok;
char *prevp;
prevp = p;
tok = parse_token(&p, end);
if (!tok) return 1;
if (startline)
{
for (i = 0; tags[i].tag; i++)
{
if (!strcmp(tok, tags[i].tag))
{
// printf("#: %s\n", tok);
free(seg);
seg = strdup(tok);
mode = tags[i].mode;
break;
}
}
if (!tags[i].tag) goto not_tag;
}
else
{
not_tag:
switch (mode)
{
case TMODE_EOL:
case TMODE_TEXT:
// prse eol of prevp
p = prevp;
data1 = parse_eol(&p, end);
if (!data1) err("no content");
break;
case TMODE_PATH:
case TMODE_PATH_LIST:
// sanitize (check) path tok put into data1
data1 = path_check(tok);
if (!data1) err("path invalid");
break;
case TMODE_PATH_CP:
case TMODE_PATH_CP_LIST:
// sanitize path, then next token > then path 2 -> data1, data2
data1 = path_check(tok);
if (!data1) err("path invalid");
s = parse_token(&p, end);
if (!s) err("missing > in path copy");
if (!(!strcmp(s, ">"))) err("copy token is not >");
free(s);
s = parse_token(&p, end);
if (!s) err("missing destination path in path copy");
data2 = path_check(s);
if (!data2) err("destination path not valid");
free(s);
break;
default:
break;
}
// if (data2)
// printf(" %i> %s '%s' '%s'\n",
// mode, seg, data1, data2);
// else
// printf(" %i> %s '%s'\n",
// mode, seg, data1);
if (seg)
{
if (!strcmp(seg, "PROJ:"))
{
if (!(sane_forbidden_path(data1, sane_name_veto) &&
sane_allowed_path(data1, sane_name_ok)))
err("name failed sanity check");
free(build.name);
build.name = strdup(data1);
}
else if (!strcmp(seg, "PROJICON:"))
{
free(build.icon);
build.icon = strdup(data1);
}
else if (!strcmp(seg, "BRIEF:"))
{
if (!build.brief) build.brief = strdup(data1);
else
{
s = malloc(strlen(build.brief) + 1 + strlen(data1) + 1);
if (s)
{
strcpy(s, build.brief);
strcat(s, " ");
strcat(s, data1);
free(build.brief);
build.brief = s;
}
}
}
else if (!strcmp(seg, "VERSION:"))
{
free(build.version);
build.version = strdup(data1);
}
else if (!strcmp(seg, "LICENSE:"))
{
free(build.license);
build.license = strdup(data1);
}
else if (!strcmp(seg, "COPYING:"))
{
build.copying = eina_list_append(build.copying,
strdup(data1));
}
else if (!strcmp(seg, "NEEDS:"))
{
free(build.needs);
build.license = strdup(data1);
}
else if (!strcmp(seg, "DOMAIN:"))
{
free(build.domain);
build.domain = strdup(data1);
}
else if (!strcmp(seg, "REPO:"))
{
free(build.repo);
build.repo = strdup(data1);
}
else if (!strcmp(seg, "DEVREPO:"))
{
free(build.devrepo);
build.devrepo = strdup(data1);
}
else if (!strcmp(seg, "CATEGORY:"))
{
build.categories = eina_list_append(build.categories,
strdup(data1));
}
else if (!strcmp(seg, "TAGS:"))
{
build.tags = eina_list_append(build.tags,
strdup(data1));
}
else if (!strcmp(seg, "CONTACT:"))
{
if (!build.contact) build.contact = strdup(data1);
else
{
s = malloc(strlen(build.contact) + 1 + strlen(data1) + 1);
if (s)
{
strcpy(s, build.contact);
strcat(s, " ");
strcat(s, data1);
free(build.contact);
build.contact = s;
}
}
}
else if (!strcmp(seg, "BIN:"))
{
Build_Bin *build_bin = calloc(1, sizeof(Build_Bin));
if (build_bin)
{
build_bin->bin = strdup(data1);
build.bins = eina_list_append(build.bins,
build_bin);
}
}
else if (!strcmp(seg, "SRC:"))
{
Build_Bin *build_bin = eina_list_data_get(eina_list_last(build.bins));
if (build_bin)
{
build_bin->srcs = eina_list_append(build_bin->srcs,
strdup(data1));
}
}
else if (!strcmp(seg, "DEPS:"))
{
Build_Bin *build_bin = eina_list_data_get(eina_list_last(build.bins));
if (build_bin)
{
build_bin->deps = eina_list_append(build_bin->deps,
strdup(data1));
}
}
else if (!strcmp(seg, "INC:"))
{
Build_Bin *build_bin = eina_list_data_get(eina_list_last(build.bins));
if (build_bin)
{
build_bin->incs = eina_list_append(build_bin->incs,
strdup(data1));
}
}
else if (!strcmp(seg, "DATA:"))
{
Build_Data *build_data = calloc(1, sizeof(Build_Data));
if (build_data)
{
build_data->src = strdup(data1);
build_data->dest = strdup(data2);
build.data = eina_list_append(build.data,
build_data);
}
}
else if (!strcmp(seg, "DESKTOP:"))
{
build.desktops = eina_list_append(build.desktops,
strdup(data1));
}
else if (!strcmp(seg, "ICON:"))
{
build.icons = eina_list_append(build.icons,
strdup(data1));
}
else if (!strcmp(seg, "PO:"))
{
build.po = eina_list_append(build.po,
strdup(data1));
}
}
free(data1);
free(data2);
data1 = NULL;
data2 = NULL;
}
free(tok);
prevc = *p;
}
else
{
prevc = *p;
p++;
}
startline = 0;
}
return 1;
}
static int
parse_bld(const char *file)
{
Eina_File *ef;
char *mem;
size_t size;
int ret;
ef = eina_file_open(file, EINA_FALSE);
if (!ef) return 0;
size = eina_file_size_get(ef);
mem = eina_file_map_all(ef, EINA_FILE_SEQUENTIAL);
if ((size == 0) || (!mem)) return 0;
ret = parse_content(mem, size);
eina_file_close(ef);
return ret;
}
static int
build_proj(void)
{
Eina_List *l, *ll;
Build_Bin *bin;
Build_Data *data;
Eina_Strbuf *buf;
char *s, *extn, *s2;
char tmp[4096];
char tmp2[4096];
const char *ss, *cc;
EINA_LIST_FOREACH(build.po, l, s)
{
snprintf(tmp, sizeof(tmp), "%s/share/locale/%s/LC_MESSAGES/", tmpd, s);
ecore_file_mkpath(tmp);
snprintf(tmp2, sizeof(tmp2), "po/%s.gmo", s);
snprintf(tmp, sizeof(tmp), "%s/share/locale/%s/LC_MESSAGES/%s.mo", tmpd, s, build.domain);
ecore_file_cp(tmp2, tmp);
}
EINA_LIST_FOREACH(build.data, l, data)
{
s = ecore_file_dir_get(data->dest);
if (s)
{
snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, s);
ecore_file_mkpath(tmp);
free(s);
}
snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, data->dest);
ecore_file_cp(data->src, tmp);
}
snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, "share/applications");
ecore_file_mkpath(tmp);
EINA_LIST_FOREACH(build.desktops, l, s)
{
ss = ecore_file_file_get(s);
if (!(!strncmp(ss, build.domain, strlen(build.domain))))
err("destkop file wrong domain");
snprintf(tmp, sizeof(tmp), "%s/share/applications/%s", tmpd, ss);
ecore_file_cp(s, tmp);
}
snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, "share/icons");
ecore_file_mkpath(tmp);
EINA_LIST_FOREACH(build.icons, l, s)
{
ss = ecore_file_file_get(s);
if (!(!strncmp(ss, build.domain, strlen(build.domain))))
err("icon file wrong domain");
snprintf(tmp, sizeof(tmp), "%s/share/icons/%s", tmpd, ss);
ecore_file_cp(s, tmp);
}
EINA_LIST_FOREACH(build.copying, l, s)
{
if (strchr(s, '/'))
{
s2 = ecore_file_dir_get(s);
snprintf(tmp, sizeof(tmp), "%s/share/licenses/%s", tmpd, s2);
free(s2);
}
else
snprintf(tmp, sizeof(tmp), "%s/share/licenses", tmpd);
ecore_file_mkpath(tmp);
snprintf(tmp, sizeof(tmp), "%s/share/licenses/%s", tmpd, s);
ecore_file_cp(s, tmp);
}
EINA_LIST_FOREACH(build.bins, l, bin)
{
if ((buf = eina_strbuf_new()))
{
s = ecore_file_dir_get(bin->bin);
if (s)
{
snprintf(tmp, sizeof(tmp), "%s/%s", tmpd, s);
ecore_file_mkpath(tmp);
free(s);
}
cc = getenv("CC");
if (!cc) cc = "gcc";
eina_strbuf_append(buf, cc);
eina_strbuf_append(buf, " -I. -lm -o ");
eina_strbuf_append(buf, tmpd);
eina_strbuf_append(buf, "/");
eina_strbuf_append(buf, bin->bin);
eina_strbuf_append(buf, " -DLOCALEDIR=\\\"/tmp/X/share/locale\\\"");
eina_strbuf_append(buf, " -DPACKAGE_BIN_DIR=\\\"/tmp/X/bin\\\"");
eina_strbuf_append(buf, " -DPACKAGE_LIB_DIR=\\\"/tmp/X/lib\\\"");
eina_strbuf_append(buf, " -DPACKAGE_DATA_DIR=\\\"/tmp/X/share/");
eina_strbuf_append(buf, build.domain);
eina_strbuf_append(buf, "\\\"");
eina_strbuf_append(buf, " -DPACKAGE_NAME=\\\"");
eina_strbuf_append(buf, build.domain);
eina_strbuf_append(buf, "\\\"");
eina_strbuf_append(buf, " -DPACKAGE_VERSION=\\\"");
eina_strbuf_append(buf, build.version);
eina_strbuf_append(buf, "\\\"");
eina_strbuf_append(buf, " -D_REENTRANT -DHAVE_CONFIG_H -pthread ");
eina_strbuf_append(buf, " $CFLAGS ");
EINA_LIST_FOREACH(bin->srcs, ll, s)
{
extn = strrchr(s, '.');
if ((extn) && (!strcasecmp(extn, ".c")))
{
eina_strbuf_append(buf, s);
eina_strbuf_append(buf, " ");
}
}
EINA_LIST_FOREACH(bin->deps, ll, s)
{
eina_strbuf_append(buf, " `pkg-config --cflags --libs ");
eina_strbuf_append(buf, s);
eina_strbuf_append(buf, "` ");
}
EINA_LIST_FOREACH(bin->incs, ll, s)
{
eina_strbuf_append(buf, " -I");
eina_strbuf_append(buf, s);
eina_strbuf_append(buf, " ");
}
s = (char *)eina_strbuf_string_get(buf);
if (s) system(s);
eina_strbuf_free(buf);
}
}
return 1;
}
static void
package_file(Eet_File *ef, const char *file, const char *key)
{
Eina_File *enf = eina_file_open(file, EINA_FALSE);
if (enf)
{
void *mem = eina_file_map_all(enf, EINA_FILE_SEQUENTIAL);
if (mem)
{
size_t size = eina_file_size_get(enf);
eet_write(ef, key, mem, size, EET_COMPRESSION_VERYFAST);
}
eina_file_close(enf);
}
}
static void
package_bin_iter(Eet_File *ef, const char *dir, const char *key)
{
Eina_List *files;
Eina_File *enf;
char *s;
char tmp[4096];
char tmp2[4096];
files = ecore_file_ls(dir);
EINA_LIST_FREE(files, s)
{
if (!strcmp(s, ".")) continue;
else if (!strcmp(s, "..")) continue;
snprintf(tmp, sizeof(tmp), "%s/%s", dir, s);
snprintf(tmp2, sizeof(tmp2), "%s/%s", key, s);
if (ecore_file_is_dir(tmp))
{
if (ecore_file_can_exec(tmp)) tmp2[4] = 'D';
package_bin_iter(ef, tmp, tmp2);
}
else
{
if (ecore_file_can_exec(tmp)) tmp2[4] = 'X';
else tmp2[4] = 'f';
package_file(ef, tmp, tmp2);
}
free(s);
}
}
static int
pakage_bin(void)
{
Eet_File *ef;
char tmp[4096];
Eina_List *l;
char *s;
int i;
snprintf(tmp, sizeof(tmp), "%s-%s.mkb", build.name, build.version);
ef = eet_open(tmp, EET_FILE_MODE_WRITE);
if (ef)
{
#define WRTS(key, var) \
if (var) eet_write(ef, key, var, strlen(var), EET_COMPRESSION_VERYFAST)
WRTS("name", build.name);
if (build.icon) package_file(ef, build.icon, "icon");
WRTS("brief", build.brief);
WRTS("version", build.version);
WRTS("license", build.license);
WRTS("repo", build.repo);
WRTS("devrepo", build.devrepo);
WRTS("contact", build.contact);
WRTS("needs", build.needs);
snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
WRTS("arch", tmp);
i = 0;
EINA_LIST_FOREACH(build.tags, l, s)
{
snprintf(tmp, sizeof(tmp), "tag/%i", i++);
WRTS(tmp, s);
}
i = 0;
EINA_LIST_FOREACH(build.categories, l, s)
{
snprintf(tmp, sizeof(tmp), "category/%i", i++);
WRTS(tmp, s);
}
package_bin_iter(ef, tmpd, "bin/f");
eet_close(ef);
return 1;
}
return 0;
}
static int
pakage_src(const char *file)
{
Eet_File *ef;
char tmp[4096];
char tmp2[4096];
snprintf(tmp, sizeof(tmp), "%s-%s.mks", build.name, build.version);
ef = eet_open(tmp, EET_FILE_MODE_WRITE);
if (ef)
{
Eina_File *enf;
Eina_List *l, *ll;
void *mem;
size_t size;
char *s;
Build_Bin *bin;
Build_Data *data;
enf = eina_file_open(file, EINA_FALSE);
if (!enf) err("can't open build file");
mem = eina_file_map_all(enf, EINA_FILE_SEQUENTIAL);
if (!mem) err("can't map build file");
size = eina_file_size_get(enf);
eet_write(ef, "buildinfo", mem, size, EET_COMPRESSION_VERYFAST);
eina_file_close(enf);
EINA_LIST_FOREACH(build.copying, l, s)
{
snprintf(tmp, sizeof(tmp), "src/%s", s);
package_file(ef, s, tmp);
}
EINA_LIST_FOREACH(build.desktops, l, s)
{
snprintf(tmp, sizeof(tmp), "src/%s", s);
package_file(ef, s, tmp);
}
EINA_LIST_FOREACH(build.icons, l, s)
{
snprintf(tmp, sizeof(tmp), "src/%s", s);
package_file(ef, s, tmp);
}
EINA_LIST_FOREACH(build.po, l, s)
{
snprintf(tmp2, sizeof(tmp2), "po/%s.gmo", s);
snprintf(tmp, sizeof(tmp), "src/po/%s.gmo", s);
package_file(ef, tmp2, tmp);
}
EINA_LIST_FOREACH(build.bins, l, bin)
{
EINA_LIST_FOREACH(bin->srcs, ll, s)
{
snprintf(tmp, sizeof(tmp), "src/%s", s);
package_file(ef, s, tmp);
}
}
EINA_LIST_FOREACH(build.data, l, data)
{
snprintf(tmp, sizeof(tmp), "src/%s", data->src);
package_file(ef, data->src, tmp);
}
eet_close(ef);
return 1;
}
return 0;
}
static int
write_file(Eet_File *ef, const char *key, const char *file)
{
FILE *f;
void *mem;
int size;
char *s;
mem = eet_read(ef, key, &size);
if (mem)
{
s = ecore_file_dir_get(file);
if (s)
{
ecore_file_mkpath(s);
free(s);
}
f = fopen(file, "wb");
if (f)
{
fwrite(mem, size, 1, f);
fclose(f);
return 1;
}
}
err("file write failed");
return 0;
}
static int
package_extract(const char *file)
{
Eet_File *ef;
ef = eet_open(file, EET_FILE_MODE_READ);
if (ef)
{
int i, num = 0;
char **keys = eet_list(ef, "src/*", &num);
if (keys)
{
for (i = 0; i < num; i++)
{
if (!strncmp(keys[i], "src/", 4))
{
if (!sane_forbidden_path(keys[i], sane_path_veto)) continue;
write_file(ef, keys[i], &(keys[i][4]));
}
}
}
write_file(ef, "buildinfo", "Marrakesh.mrk");
eet_close(ef);
return 1;
}
err("file does not open");
return 0;
}
static char *
read_string(Eet_File *ef, const char *key)
{
int size = 0;
char *str;
char *s = eet_read(ef, key, &size);
if (!s) return NULL;
str = malloc(size + 1);
if (!str)
{
free(s);
return NULL;
}
memcpy(str, s, size);
str[size] = 0;
free(s);
return str;
}
static void
clean_symlinks(const char *dir)
{
Eina_List *files;
char *s, *ss;
char tmp[4096];
files = ecore_file_ls(dir);
EINA_LIST_FREE(files, s)
{
snprintf(tmp, sizeof(tmp), "%s/%s", dir, s);
ss = ecore_file_readlink(tmp);
if (ss)
{
free(ss);
if (!ecore_file_exists(tmp))
{
printf("clean '%s'\n", tmp);
ecore_file_unlink(tmp);
}
}
free(s);
}
}
static int
field_copy(Eet_File *ef, Eet_File *ef2, const char *key)
{
int size = 0;
char *s = eet_read(ef, key, &size);
if (s)
{
eet_write(ef2, key, s, size, EET_COMPRESSION_VERYFAST);
free(s);
return 1;
}
return 0;
}
static const char *
get_home(void)
{
static char buf[4096] = "";
const char *tmps, *home;
if (buf[0]) return buf;
tmps = getenv("XDG_DATA_HOME");
home = getenv("HOME");
if (!home) home = "/tmp";
if (tmps) snprintf(buf, sizeof(buf), "%s", tmps);
else snprintf(buf, sizeof(buf), "%s", home);
return buf;
}
static int
package_clean(void)
{
char tmp[4096];
snprintf(tmp, sizeof(tmp), "%s/.local/share/icons", get_home());
clean_symlinks(tmp);
snprintf(tmp, sizeof(tmp), "%s/.local/share/applications", get_home());
clean_symlinks(tmp);
snprintf(tmp, sizeof(tmp), "%s/Applications/.bin", get_home());
clean_symlinks(tmp);
return 1;
}
static int
package_install(const char *file)
{
Eet_File *ef, *ef2;
ef = eet_open(file, EET_FILE_MODE_READ);
if (ef)
{
int i, num = 0;
char **keys = eet_list(ef, "bin/*", &num);
char inst[4096];
char dir[4096];
char tmp[4096];
char tmp2[4096];
char *s;
Eina_List *files;
char *name;
name = read_string(ef, "name");
if (!name) err("no name");
if (!(sane_forbidden_path(name, sane_name_veto) &&
sane_allowed_path(name, sane_name_ok)))
err("name failed sanity check");
snprintf(tmp, sizeof(tmp), "%s/Applications/.bin", get_home());
ecore_file_mkpath(tmp);
snprintf(inst, sizeof(inst), "%s/Applications/%s", get_home(), name);
if (ecore_file_exists(inst)) err("destination already exists");
ecore_file_mkpath(inst);
if (keys)
{
for (i = 0; i < num; i++)
{
if (!strncmp(keys[i], "bin/", 4))
{
if (!sane_forbidden_path(keys[i], sane_path_veto)) continue;
snprintf(tmp, sizeof(tmp), "%s/%s", inst, &(keys[i][6]));
write_file(ef, keys[i], tmp);
if (keys[i][4] == 'X')
{
printf("+x '%s'\n", &(keys[i][6]));
chmod(tmp, 00500);
}
}
}
}
snprintf(dir, sizeof(dir), "%s/share/icons", inst);
files = ecore_file_ls(dir);
EINA_LIST_FREE(files, s)
{
if (!strcmp(s, ".")) continue;
else if (!strcmp(s, "..")) continue;
snprintf(tmp, sizeof(tmp), "../../../Applications/%s/share/icons/%s", name, s);
snprintf(tmp2, sizeof(tmp2), "%s/.local/share/icons/%s", get_home(), s);
if (ecore_file_exists(tmp2)) err("icon file symlink already exists");
ecore_file_symlink(tmp, tmp2);
free(s);
}
snprintf(dir, sizeof(dir), "%s/share/applications", inst);
files = ecore_file_ls(dir);
EINA_LIST_FREE(files, s)
{
if (!strcmp(s, ".")) continue;
else if (!strcmp(s, "..")) continue;
snprintf(tmp, sizeof(tmp), "../../../Applications/%s/share/applications/%s", name, s);
snprintf(tmp2, sizeof(tmp2), "%s/.local/share/applications/%s", get_home(), s);
if (ecore_file_exists(tmp2)) err("desktop file symlink already exists");
ecore_file_symlink(tmp, tmp2);
free(s);
}
snprintf(dir, sizeof(dir), "%s/bin", inst);
files = ecore_file_ls(dir);
EINA_LIST_FREE(files, s)
{
if (!strcmp(s, ".")) continue;
else if (!strcmp(s, "..")) continue;
snprintf(tmp, sizeof(tmp), "../%s/bin/%s", name, s);
snprintf(tmp2, sizeof(tmp2), "%s/Applications/.bin/%s", get_home(), s);
if (ecore_file_exists(tmp2)) err("bin file symlink already exists");
ecore_file_symlink(tmp, tmp2);
free(s);
}
snprintf(tmp, sizeof(tmp), "%s/Applications/%s/.icon.png", get_home(), name);
write_file(ef, "icon", tmp);
snprintf(tmp, sizeof(tmp), "%s/Applications/%s/.info.mki", get_home(), name);
ef2 = eet_open(tmp, EET_FILE_MODE_WRITE);
free(name);
if (ef2)
{
field_copy(ef, ef2, "name");
field_copy(ef, ef2, "brief");
field_copy(ef, ef2, "version");
field_copy(ef, ef2, "license");
field_copy(ef, ef2, "repo");
field_copy(ef, ef2, "devrepo");
field_copy(ef, ef2, "contact");
field_copy(ef, ef2, "needs");
for (i = 0; i < 9999; i++)
{
snprintf(tmp, sizeof(tmp), "tag/%i", i);
if (!field_copy(ef, ef2, tmp)) break;
}
for (i = 0; i < 9999; i++)
{
snprintf(tmp, sizeof(tmp), "category/%i", i);
if (!field_copy(ef, ef2, tmp)) break;
}
eet_close(ef2);
}
eet_close(ef);
return 1;
}
err("file does not open");
return 0;
}
static int
package_remove(const char *name)
{
char tmp[4096];
snprintf(tmp, sizeof(tmp), "%s/Applications/%s", get_home(), name);
if (!ecore_file_recursive_rm(tmp)) return 0;
return 1;
}
static Ecore_Ipc_Server *ipc = NULL;
static char *up_file = NULL;
static char *up_path = NULL;
static Eina_Bool
_ipc_cb_add(void *data, int type, void *event)
{
Ecore_Ipc_Event_Server_Add *e = event;
FILE *f;
char tmp[4096];
snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
ecore_ipc_server_send(ipc, 10, M_ID_ARCH, 0, 0, 0,
tmp, strlen(tmp));
snprintf(tmp, sizeof(tmp), "%i.%i.%i",
eina_version->major, eina_version->minor, eina_version->micro);
ecore_ipc_server_send(ipc, 10, M_ID_VERSION, 0, 0, 0,
tmp, strlen(tmp));
f = fopen(up_path, "rb");
if (f)
{
char buf[10000];
size_t size;
ecore_ipc_server_send(ipc, 10, M_UP_START, 0, 0, 0,
up_file, strlen(up_file));
for (;;)
{
size = fread(buf, 1, 10000, f);
if (size > 0)
ecore_ipc_server_send(ipc, 10, M_UP_DATA, 0, 0, 0,
buf, size);
else break;
}
ecore_ipc_server_send(ipc, 10, M_UP_END, 0, 0, 0,
NULL, 0);
fclose(f);
}
return EINA_TRUE;
}
static Eina_Bool
_ipc_cb_del(void *data, int type, void *event)
{
Ecore_Ipc_Event_Server_Del *e = event;
err("disconnect...");
ecore_main_loop_quit();
return EINA_TRUE;
}
static Eina_Bool
_ipc_cb_dat(void *data, int type, void *event)
{
Ecore_Ipc_Event_Server_Data *e = event;
if (e->major == 10)
{
if (e->minor == M_UP_OK)
{
printf("OK\n");
ecore_main_loop_quit();
}
else if (e->minor == M_UP_FAIL)
{
printf("FAIL\n");
err("upload rejected");
}
}
return EINA_TRUE;
}
static int
package_up(const char *file)
{
ipc = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM, server, server_port, NULL);
if (!ipc) return 0;
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, _ipc_cb_add, NULL);
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, _ipc_cb_del, NULL);
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, _ipc_cb_dat, NULL);
up_path = strdup(file);
up_file = strdup(ecore_file_file_get(file));
ecore_main_loop_begin();
return 1;
}
static char *down_name = NULL;
static char *down_file = NULL;
static FILE *down_f = NULL;
static Eina_Bool
_ipc2_cb_add(void *data, int type, void *event)
{
Ecore_Ipc_Event_Server_Add *e = event;
char tmp[4096];
snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
ecore_ipc_server_send(ipc, 10, M_ID_ARCH, 0, 0, 0,
tmp, strlen(tmp));
snprintf(tmp, sizeof(tmp), "%i.%i.%i",
eina_version->major, eina_version->minor, eina_version->micro);
ecore_ipc_server_send(ipc, 10, M_ID_VERSION, 0, 0, 0,
tmp, strlen(tmp));
ecore_ipc_server_send(ipc, 10, M_QRY_GET, 0, 0, 0,
down_name, strlen(down_name));
return EINA_TRUE;
}
static Eina_Bool
_ipc2_cb_del(void *data, int type, void *event)
{
Ecore_Ipc_Event_Server_Del *e = event;
err("disconnect...");
ecore_main_loop_quit();
return EINA_TRUE;
}
static Eina_Bool
_ipc2_cb_dat(void *data, int type, void *event)
{
Ecore_Ipc_Event_Server_Data *e = event;
if (e->major == 10)
{
switch (e->minor)
{
case M_DOWN_START:
if ((e->size > 0) && (e->size <= 1000) && (e->data))
{
char *file = malloc(e->size + 1);
if (file)
{
memcpy(file, e->data, e->size);
file[e->size] = 0;
if ((sane_forbidden_path(file, sane_name_veto) &&
sane_allowed_path(file, sane_name_ok)))
{
if (!down_f)
{
char tmp[4096];
down_file = file;
snprintf(tmp, sizeof(tmp),
"%s/Applications/.tmp",
getenv("HOME"));
ecore_file_mkpath(tmp);
snprintf(tmp, sizeof(tmp),
"%s/Applications/.tmp/%s",
getenv("HOME"), down_file);
if (ecore_file_exists(tmp))
err("file already exists");
down_f = fopen(file, "wb");
printf("%s\n", file);
}
else err("already have download");
}
else err("mangled filename");
}
else err("download file not sane");
}
else err("no such package");
break;
case M_DOWN_DATA:
if ((down_f) && (e->data) && (e->size > 0) && (e->size <= 10000))
{
fwrite(e->data, e->size, 1, down_f);
}
break;
case M_DOWN_END:
if (down_f)
{
fclose(down_f);
down_f = NULL;
ecore_main_loop_quit();
}
break;
default:
break;
}
}
return EINA_TRUE;
}
static int
package_down(const char *name)
{
ipc = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM, server, server_port, NULL);
if (!ipc) return 0;
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, _ipc2_cb_add, NULL);
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, _ipc2_cb_del, NULL);
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, _ipc2_cb_dat, NULL);
down_name = strdup(name);
ecore_main_loop_begin();
return 1;
}
static char *downsrc_name = NULL;
static char *downsrc_file = NULL;
static FILE *downsrc_f = NULL;
static Eina_Bool
_ipc3_cb_add(void *data, int type, void *event)
{
Ecore_Ipc_Event_Server_Add *e = event;
char tmp[4096];
snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
ecore_ipc_server_send(ipc, 10, M_ID_ARCH, 0, 0, 0,
tmp, strlen(tmp));
snprintf(tmp, sizeof(tmp), "%i.%i.%i",
eina_version->major, eina_version->minor, eina_version->micro);
ecore_ipc_server_send(ipc, 10, M_ID_VERSION, 0, 0, 0,
tmp, strlen(tmp));
ecore_ipc_server_send(ipc, 10, M_QRY_GETSRC, 0, 0, 0,
downsrc_name, strlen(downsrc_name));
return EINA_TRUE;
}
static Eina_Bool
_ipc3_cb_del(void *data, int type, void *event)
{
Ecore_Ipc_Event_Server_Del *e = event;
err("disconnect...");
ecore_main_loop_quit();
return EINA_TRUE;
}
static Eina_Bool
_ipc3_cb_dat(void *data, int type, void *event)
{
Ecore_Ipc_Event_Server_Data *e = event;
if (e->major == 10)
{
switch (e->minor)
{
case M_SRC_START:
if ((e->size > 0) && (e->size <= 1000) && (e->data))
{
char *file = malloc(e->size + 1);
if (file)
{
memcpy(file, e->data, e->size);
file[e->size] = 0;
if ((sane_forbidden_path(file, sane_name_veto) &&
sane_allowed_path(file, sane_name_ok)))
{
if (!downsrc_f)
{
char tmp[4096];
downsrc_file = file;
snprintf(tmp, sizeof(tmp),
"%s/Applications/.tmp",
getenv("HOME"));
ecore_file_mkpath(tmp);
snprintf(tmp, sizeof(tmp),
"%s/Applications/.tmp/%s",
getenv("HOME"), downsrc_file);
if (ecore_file_exists(tmp))
err("file already exists");
downsrc_f = fopen(file, "wb");
printf("%s\n", file);
}
else err("already have download");
}
else err("mangled filename");
}
else err("download file not sane");
}
else err("no such package");
break;
case M_SRC_DATA:
if ((downsrc_f) && (e->data) && (e->size > 0) && (e->size <= 10000))
{
fwrite(e->data, e->size, 1, downsrc_f);
}
break;
case M_SRC_END:
if (downsrc_f)
{
fclose(downsrc_f);
downsrc_f = NULL;
ecore_main_loop_quit();
}
break;
default:
break;
}
}
return EINA_TRUE;
}
static int
package_downsrc(const char *name)
{
ipc = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM, server, server_port, NULL);
if (!ipc) return 0;
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, _ipc3_cb_add, NULL);
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, _ipc3_cb_del, NULL);
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, _ipc3_cb_dat, NULL);
downsrc_name = strdup(name);
ecore_main_loop_begin();
return 1;
}
static int qry_op = 0;
static char *qry_data;
static Eina_Bool
_ipc4_cb_add(void *data, int type, void *event)
{
Ecore_Ipc_Event_Server_Add *e = event;
char tmp[4096];
snprintf(tmp, sizeof(tmp), "%s-%s", os, arch);
ecore_ipc_server_send(ipc, 10, M_ID_ARCH, 0, 0, 0,
tmp, strlen(tmp));
snprintf(tmp, sizeof(tmp), "%i.%i.%i",
eina_version->major, eina_version->minor, eina_version->micro);
ecore_ipc_server_send(ipc, 10, M_ID_VERSION, 0, 0, 0,
tmp, strlen(tmp));
ecore_ipc_server_send(ipc, 10, qry_op, 0, 0, 0,
qry_data, qry_data ? strlen(qry_data) : 0);
return EINA_TRUE;
}
static Eina_Bool
_ipc4_cb_del(void *data, int type, void *event)
{
Ecore_Ipc_Event_Server_Del *e = event;
err("disconnect...");
ecore_main_loop_quit();
return EINA_TRUE;
}
static Eina_Bool
_ipc4_cb_dat(void *data, int type, void *event)
{
Ecore_Ipc_Event_Server_Data *e = event;
if (e->major == 10)
{
switch (e->minor)
{
case M_ANS_START:
break;
case M_ANS_DATA:
if ((e->data) && (e->size > 0) && (e->size <= 10000))
{
fwrite(e->data, e->size, 1, stdout);
fwrite("\n", 1, 1, stdout);
}
break;
case M_ANS_END:
if (qry_data) free(qry_data);
qry_data = NULL;
ecore_main_loop_quit();
break;
default:
break;
}
}
return EINA_TRUE;
}
static int
package_qry(int op, const char *opdat)
{
ipc = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM, server, server_port, NULL);
if (!ipc) return 0;
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, _ipc4_cb_add, NULL);
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, _ipc4_cb_del, NULL);
ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, _ipc4_cb_dat, NULL);
qry_op = op;
if (opdat) qry_data = strdup(opdat);
ecore_main_loop_begin();
return 1;
}
static int
package_file_isbin(const char *file)
{
const char *p;
p = strchr(file, '.');
if (p)
{
if (!strcasecmp(p, ".png")) return 1;
if (!strcasecmp(p, ".jpg")) return 1;
if (!strcasecmp(p, ".edj")) return 1;
if (!strcasecmp(p, ".gif")) return 1;
if (!strcasecmp(p, ".bmp")) return 1;
}
return 0;
}
static Eina_Bool
string_rep(const Eina_Hash *hash, const void *key, void *data, void *fdata)
{
eina_strbuf_replace_all(fdata, key, data);
return EINA_TRUE;
}
static int
package_dir_dup(const char *src, const char *dst, Eina_Hash *vars)
{
char tmp[4096];
char tmp2[4096];
Eina_Strbuf *dstsbuf;
dstsbuf = eina_strbuf_new();
if (!dstsbuf) return 0;
eina_strbuf_append(dstsbuf, dst);
eina_hash_foreach(vars, string_rep, dstsbuf);
if (ecore_file_is_dir(src))
{
Eina_List *files;
char *s;
ecore_file_mkdir(eina_strbuf_string_get(dstsbuf));
files = ecore_file_ls(src);
EINA_LIST_FREE(files, s)
{
if (s[0] != '.')
{
snprintf(tmp, sizeof(tmp), "%s/%s", src, s);
snprintf(tmp2, sizeof(tmp2), "%s/%s", eina_strbuf_string_get(dstsbuf), s);
package_dir_dup(tmp, tmp2, vars);
}
free(s);
}
}
else
{
if (package_file_isbin(src))
ecore_file_cp(src, eina_strbuf_string_get(dstsbuf));
else
{
FILE *fsrc, *fdst;
fsrc = fopen(src, "rb");
fdst = fopen(eina_strbuf_string_get(dstsbuf), "wb");
if ((fsrc) && (fdst))
{
long size;
fseek(fsrc, 0, SEEK_END);
size = ftell(fsrc);
fseek(fsrc, 0, SEEK_SET);
if (size > 0)
{
char *buf = malloc(size + 1);
if (buf)
{
Eina_Strbuf *tmpsbuf;
tmpsbuf = eina_strbuf_new();
if (tmpsbuf)
{
fread(buf, size, 1, fsrc);
buf[size] = 0;
eina_strbuf_append(tmpsbuf, buf);
eina_hash_foreach(vars, string_rep, tmpsbuf);
fwrite(eina_strbuf_string_get(tmpsbuf),
eina_strbuf_length_get(tmpsbuf),
1, fdst);
eina_strbuf_free(tmpsbuf);
}
free(buf);
}
}
}
if (fsrc) fclose(fsrc);
if (fdst) fclose(fdst);
}
}
eina_strbuf_free(dstsbuf);
return 1;
}
static int
package_gen(const char *tmpldir, const char *tmpl, Eina_Hash *vars)
{
char tmp[4096];
char tmp2[4096];
const char *domain;
domain = eina_hash_find(vars, "@APPDOM@");
ecore_file_mkdir(domain);
snprintf(tmp, sizeof(tmp), "%s/apps/%s", tmpldir, tmpl);
package_dir_dup(tmp, domain, vars);
snprintf(tmp, sizeof(tmp), "%s/licenses/%s",
tmpldir, eina_hash_find(vars, "@APPCOPY@"));
snprintf(tmp2, sizeof(tmp2), "%s/COPYING", domain);
ecore_file_cp(tmp, tmp2);
}
static int
package_new(void)
{
Eina_Hash *vars = eina_hash_string_superfast_new(NULL);
char tmp[4096];
if (!vars) return 0;
printf("App Name: (e.g. Hello)\n");
if (scanf("%500s", tmp) <= 0) return 0;
eina_hash_add(vars, "@APPNAME@", eina_stringshare_add(tmp));
printf("App Domain: (e.g. hello)\n");
if (scanf("%500s", tmp) <= 0) return 0;
eina_hash_add(vars, "@APPDOM@", eina_stringshare_add(tmp));
printf("App Version: (e.g. 1.0.0)\n");
if (scanf("%150s", tmp) <= 0) return 0;
eina_hash_add(vars, "@APPVER@", eina_stringshare_add(tmp));
printf("App License: (e.g. BSD-2 | GPL2 | APACHE | GPL3)\n");
if (scanf("%20s", tmp) <= 0) return 0;
eina_hash_add(vars, "@APPCOPY@", eina_stringshare_add(tmp));
printf("App Brief Description: (1 line)\n");
if (scanf("%400s", tmp) <= 0) return 0;
eina_hash_add(vars, "@APPDESC@", eina_stringshare_add(tmp));
printf("App Categories: (e.g. media)\n");
if (scanf("%1000s", tmp) <= 0) return 0;
eina_hash_add(vars, "@APPCATEGORIES@", eina_stringshare_add(tmp));
printf("App Tags: (e.g. video audio media film movies music player)\n");
if (scanf("%4000s", tmp) <= 0) return 0;
eina_hash_add(vars, "@APPTAGS@", eina_stringshare_add(tmp));
printf("Developer Name + E-Mail: Bob Jones <bob@bob.com>\n");
if (scanf("%1000s", tmp) <= 0) return 0;
eina_hash_add(vars, "@DEVMAIL@", eina_stringshare_add(tmp));
printf("App EFL Minimum Version: (e.g. 1.11)\n");
if (scanf("%50s", tmp) <= 0) return 0;
eina_hash_add(vars, "@EFLVER@", eina_stringshare_add(tmp));
package_gen("/home/raster/C/marrakesh/tmpl", "default", vars);
return 1;
}
int
main(int argc, char **argv)
{
char *s;
eina_init();
eet_init();
ecore_ipc_init();
ecore_file_init();
if (argc < 2)
{
printf("sub commands:\n"
" new\n"
" build\n"
" bin\n"
" check\n"
" src\n"
" extract FILE\n"
" inst FILE\n"
" rm PKGNAME\n"
" rel [FILE]\n"
" down PKGNAME\n"
" get PKGNAME\n"
" getsrc PKGNAME\n"
" clean\n"
" list [CATEGORY]\n"
" search KEY1 [KEY2] [KEY3] [...]\n"
"\n");
return -1;
}
s = getenv("DESTDIR");
if (s) tmpd = s;
if (getenv("MRKHOST")) server = getenv("MRKHOST");
if (getenv("MRKPORT")) server_port = atoi(getenv("MRKPORT"));
if (getenv("MRKARCH")) arch = getenv("MRKARCH");
if (getenv("MRKOS")) os = getenv("MRKOS");
if (!strcmp(argv[1], "build"))
{
if (!parse_bld("Marrakesh.mrk")) return 1;
if (!build_proj()) return 1;
}
else if (!strcmp(argv[1], "src"))
{
if (!parse_bld("Marrakesh.mrk")) return 1;
if (!pakage_src("Marrakesh.mrk")) return 1;
}
else if (!strcmp(argv[1], "bin"))
{
if (!parse_bld("Marrakesh.mrk")) return 1;
if (!pakage_bin()) return 1;
}
else if (!strcmp(argv[1], "extract"))
{
if (argc < 3) err("need file to extract");
if (!package_extract(argv[2])) return 1;
}
else if (!strcmp(argv[1], "inst"))
{
if (argc < 3) err("need file to install");
package_clean();
if (!package_install(argv[2])) return 1;
}
else if (!strcmp(argv[1], "clean"))
{
package_clean();
}
else if (!strcmp(argv[1], "rm"))
{
if (argc < 3) err("need package to remove");
if (!package_remove(argv[2])) return 1;
package_clean();
}
else if (!strcmp(argv[1], "rel"))
{
char tmp[4096];
char *pk;
if (argc < 3)
{
printf("making src...\n");
if (!parse_bld("Marrakesh.mrk")) return 1;
if (!pakage_src("Marrakesh.mrk")) return 1;
snprintf(tmp, sizeof(tmp), "%s-%s.mks", build.name, build.version);
pk = tmp;
}
else pk = argv[2];
printf("upload + build...\n");
if (!package_up(pk)) return 1;
}
else if (!strcmp(argv[1], "down"))
{
if (argc < 3) err("need package to download");
if (!package_down(argv[2])) return 1;
}
else if (!strcmp(argv[1], "get"))
{
if (argc < 3) err("need package to get");
if (!package_down(argv[2])) return 1;
if (!down_file) err("no download");
package_remove(argv[2]);
package_clean();
if (!package_install(down_file)) return 1;
ecore_file_unlink(down_file);
}
else if (!strcmp(argv[1], "list"))
{
if (argc < 3) package_qry(M_QRY_LIST, NULL);
else package_qry(M_QRY_LIST, argv[2]);
}
else if (!strcmp(argv[1], "search"))
{
if (argc < 3) err("need search strings");
else
{
int i;
int len = 0;
char *ts;
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, " ");
}
package_qry(M_QRY_SEARCH, ts);
free(ts);
}
}
}
else if (!strcmp(argv[1], "new"))
{
package_new();
}
else if (!strcmp(argv[1], "getsrc"))
{
if (argc < 3) err("need package to download");
if (!package_downsrc(argv[2])) return 1;
}
else if (!strcmp(argv[1], "check"))
{
char tmp[4096];
ecore_file_recursive_rm("Marrakesh-Check");
ecore_file_mkdir("Marrakesh-Check");
if (!parse_bld("Marrakesh.mrk")) err("Parse build failed");
if (!pakage_src("Marrakesh.mrk")) err("Source packaging failed");
chdir("Marrakesh-Check");
snprintf(tmp, sizeof(tmp), "../%s-%s.mks", build.name, build.version);
if (!package_extract(tmp)) err("Source extract failed");
memset(&build, 0, sizeof(Build));
if (!parse_bld("Marrakesh.mrk")) err("Parse build 2 from source failed");
if (!build_proj()) err("Build project failed");
memset(&build, 0, sizeof(Build));
if (!parse_bld("Marrakesh.mrk")) err("Parse build 3 failed");
if (!pakage_bin()) err("Package binary failed");
printf("OK\n");
}
else
{
err("unknown subcommand!");
return 1;
}
ecore_file_shutdown();
ecore_ipc_shutdown();
eet_shutdown();
eina_shutdown();
return 0;
}