├── po ├── LINGUAS ├── POTFILES └── meson.build ├── data ├── obj.s ├── debian-names.yaml ├── ymp.pc ├── ymp-extra.h ├── code-runner-plugins │ ├── local │ └── docker ├── org.turkman.ymp.extract.desktop ├── fix-turkish.sed ├── bash-completion.sh ├── ymp.yaml ├── ymp-mime.xml └── code-runner-gitea-webhook.py ├── debian ├── compat ├── copyright ├── changelog ├── rules └── control ├── test ├── hello.py ├── data │ ├── hello.py │ ├── main.tar.gz │ ├── hello.bf │ └── metadata-binary.yaml ├── rootfs │ └── var │ │ └── lib │ │ └── ymp │ │ └── index │ │ └── test.yaml ├── test2.vala └── test.vala ├── tool ├── preprocessor.sh ├── mkdoc.sh ├── check.sh └── mkctx.sh ├── scripts ├── git-ymp ├── detect-revdep ├── remove-symver ├── g++-ymp ├── gcc-ymp └── ympstrap ├── src ├── shcode │ ├── amogus.sh │ ├── code_runner_template.sh │ ├── pkgbuild_header.sh │ ├── flag.sh │ └── ympbuild_header.sh ├── cli │ ├── shell.c │ └── main.c ├── ccode │ ├── malloc.c │ ├── gettext.c │ ├── fetcher_none.c │ ├── plugin.c │ ├── users.c │ ├── ttysize.c │ ├── nostd.c │ ├── which.c │ ├── daemon.c │ ├── fetcher_soup.c │ ├── error.c │ ├── colorize.c │ ├── signal.c │ ├── job.c │ ├── value.c │ ├── brainfuck.c │ ├── logger.c │ ├── process.c │ ├── fetcher_curl.c │ ├── archive-create.c │ └── string.c ├── start │ ├── aarch64.s │ ├── x86_64.s │ ├── arm.s │ └── i686.s ├── include │ ├── value.h │ ├── error.h │ ├── jobs.h │ ├── array.h │ ├── archive_extract.h │ └── logger.h ├── operations │ ├── shell │ │ ├── dummy.vala │ │ ├── clear.vala │ │ ├── echo.vala │ │ ├── exit.vala │ │ ├── title.vala │ │ ├── amoguscat.vala │ │ ├── shitcat.vala │ │ ├── exec.vala │ │ └── chroot.vala │ ├── utility │ │ ├── brainfuck.vala │ │ ├── httpd.vala │ │ ├── fetch.vala │ │ ├── extract.vala │ │ ├── yamlget.vala │ │ ├── compress.vala │ │ ├── code_runner.vala │ │ ├── kill.vala │ │ ├── key.vala │ │ ├── shell.vala │ │ ├── run-sandbox.vala │ │ ├── sysconf.vala │ │ ├── debian.vala │ │ ├── file.vala │ │ └── help.vala │ └── package-manager │ │ ├── clean.vala │ │ ├── build.vala │ │ ├── bootstrap.vala │ │ ├── info.vala │ │ ├── remove.vala │ │ ├── template.vala │ │ └── search.vala ├── vapi │ ├── jobs.vapi │ ├── archive.vapi │ ├── value.vapi │ ├── array.vapi │ └── logger.vapi ├── process.vala ├── util │ ├── builder_target │ │ ├── dummy.vala │ │ └── deb.vala │ ├── code-runner.vala │ ├── string.vala │ ├── gpg.vala │ └── interface.vala ├── constants.h ├── wslblock.vala ├── README.md ├── operations.vala ├── ymp.vala ├── ymp-work-schema.drawio ├── data │ └── code_runner.vala ├── interpreter.vala └── settings.vala ├── .gitignore ├── example ├── plugin │ ├── template.vala │ └── template.c └── application │ ├── run_script.c │ └── array.c ├── ympbuild ├── meson_options.txt ├── .github └── workflows │ └── blank.yml ├── doc ├── sysconf.rst ├── ympshell.rst ├── coder-runner.rst └── ympbuild.rst ├── README.md ├── Makefile └── .gitlab-ci.yml /po/LINGUAS: -------------------------------------------------------------------------------- 1 | tr -------------------------------------------------------------------------------- /data/obj.s: -------------------------------------------------------------------------------- 1 | .text 2 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 12 2 | -------------------------------------------------------------------------------- /po/POTFILES: -------------------------------------------------------------------------------- 1 | src/ymp.pot -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | ../LICENSE -------------------------------------------------------------------------------- /test/hello.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | print("Hello World") -------------------------------------------------------------------------------- /test/data/hello.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | print("Hello World") -------------------------------------------------------------------------------- /po/meson.build: -------------------------------------------------------------------------------- 1 | i18n = import('i18n') 2 | i18n.gettext(meson.project_name(), preset: 'glib') -------------------------------------------------------------------------------- /test/data/main.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/turkmen-linux/ymp/HEAD/test/data/main.tar.gz -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | ymp (1.3) unstable; urgency=medium 2 | 3 | * Initial commit 4 | 5 | -- Ali Riza KESKIN Tue, 28 Jun 2022 14:08:16 +0300 6 | -------------------------------------------------------------------------------- /tool/preprocessor.sh: -------------------------------------------------------------------------------- 1 | output=$1 2 | file=$2 3 | shift 2 4 | mkdir -p $(dirname $output/$file) 5 | cat src/constants.h $file | gcc -E - $@ | sed "/^#.*/d"> $output/$file 6 | -------------------------------------------------------------------------------- /test/data/hello.bf: -------------------------------------------------------------------------------- 1 | >++++++++[<+++++++++>-]<.>++++[<+++++++>-]<+.+++++++..+++.>>++++++[<+++++++>-]<+ 2 | +.------------.>++++++[<+++++++++>-]<+.<.+++.------.--------.>>>++++[<++++++++>- 3 | ]<+. -------------------------------------------------------------------------------- /scripts/git-ymp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | arg="$1" 3 | shift 4 | git diff "$arg" | grep "^+++ b/" | grep ympbuild | sort |\ 5 | sed "s/[a-z]*$//g;s/+++ b\///g" | while read line ; do 6 | ymp build $@ $line 7 | done 8 | -------------------------------------------------------------------------------- /tool/mkdoc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cat | grep -v "src/tools/" | grep -v "src/operations/" | \ 3 | while read file ; do 4 | echo "# $file" 5 | cat $file | grep "//DOC:" | sed "s|.*//DOC: ||g;s/$/\n/g" 6 | done 7 | -------------------------------------------------------------------------------- /src/shcode/amogus.sh: -------------------------------------------------------------------------------- 1 | @@@@ 2 | @ @ 3 | @@@@ @ 4 | @ @ @@ 5 | @ @ @ @ 6 | @@@@ @ @ 7 | @ @ @ 8 | @ @ @ 9 | @ @@ 10 | @ @@@@ @ 11 | @ @ @ @ 12 | @@@ @@@ 13 | -------------------------------------------------------------------------------- /src/cli/shell.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char** argv){ 4 | ymp_init (argv, argc); 5 | add_process ("shell", argv + 1, argc - 1); 6 | ymp_run (); 7 | error (1); 8 | exit(0); 9 | } 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | ctx.vala 3 | test/example/rootfs 4 | obj-x86_64-linux-gnu 5 | debian/ymp 6 | debian/.debhelper 7 | debian/debhelper-build-stamp 8 | debian/files 9 | po/*.mo 10 | obj-*-linux-gnu 11 | .idea 12 | .generated 13 | -------------------------------------------------------------------------------- /data/debian-names.yaml: -------------------------------------------------------------------------------- 1 | debian: 2 | glib2.0: glib 3 | libx11: libX11 4 | gtk+3.0: gtk3 5 | libxcomposite: libXcomposite 6 | libxdamage: libXdamage 7 | libxext: libXext 8 | libxfixes: libXfixes 9 | libxrandr: libXrandr 10 | pango1.0: pango -------------------------------------------------------------------------------- /data/ymp.pc: -------------------------------------------------------------------------------- 1 | prefix=/usr 2 | includedir=${prefix}/include 3 | 4 | Name: Ymp 5 | Description: Package manager for Turkish 6 | Version: @version@ 7 | Requires: glib-2.0 8 | Cflags: -L/lib -O2 -s -g -DTURKMAN -flto -I${includedir}/ymp 9 | Libs: -lymp 10 | -------------------------------------------------------------------------------- /data/ymp-extra.h: -------------------------------------------------------------------------------- 1 | #ifndef _ymp_extra 2 | #define _ymp_extra 3 | #include 4 | 5 | #define try bool __HadError=false; 6 | #define catch(x) ExitJmp:if(__HadError) 7 | #define throw(x) {__HadError=true;goto ExitJmp;} 8 | 9 | #endif 10 | 11 | /* array library */ 12 | -------------------------------------------------------------------------------- /src/ccode/malloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #if defined(__x86_64__) 5 | void* g_malloc(size_t size){ 6 | return (void*) calloc((size_t)1, size); 7 | } 8 | 9 | void* malloc(size_t size){ 10 | return (void*) calloc((size_t)1, size); 11 | } 12 | #endif -------------------------------------------------------------------------------- /data/code-runner-plugins/local: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | if [[ "$ACTION" == "init" ]] ; then 4 | echo "cd $DIRECTORY" > .init 5 | elif [[ "$ACTION" == "run" ]] ; then 6 | source .init 7 | sh -c "$COMMAND" 8 | elif [[ "$ACTION" == "clean" ]] ; then 9 | rm .init 10 | fi 11 | -------------------------------------------------------------------------------- /src/start/aarch64.s: -------------------------------------------------------------------------------- 1 | .section .note.GNU-stack 2 | .section .text 3 | .global _start 4 | _start: 5 | ldr x0, [sp] 6 | add x1, sp, 8 7 | lsl x2, x0, 3 8 | add x2, x2, 8 9 | add x2, x2, x1 10 | and sp, x1, -16 11 | bl main 12 | mov x8, 93 13 | svc #0 14 | 15 | -------------------------------------------------------------------------------- /src/start/x86_64.s: -------------------------------------------------------------------------------- 1 | .section .note.GNU-stack 2 | .section .text 3 | .weak _start 4 | _start: 5 | pop %rdi 6 | mov %rsp, %rsi 7 | lea 8(%rsi,%rdi,8),%rdx 8 | xor %ebp, %ebp 9 | and $-16, %rsp 10 | call main 11 | mov %eax, %edi 12 | mov $60, %eax 13 | syscall 14 | 15 | -------------------------------------------------------------------------------- /src/include/value.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | char* get_value(char* name); 4 | void set_value(char* name, char* value); 5 | void set_value_readonly(char* name, char* value); 6 | bool get_bool(char* name); 7 | void set_bool(char* name, bool value); 8 | char** get_variable_names(int* len); 9 | -------------------------------------------------------------------------------- /src/start/arm.s: -------------------------------------------------------------------------------- 1 | .section .note.GNU-stack 2 | .section .text 3 | .global _start 4 | _start: 5 | pop {%r0} 6 | mov %r1, %sp 7 | add %r2, %r1, %r0, lsl #2 8 | add %r2, %r2, $4 9 | and %r3, %r1, $-8 10 | mov %sp, %r3 11 | bl main 12 | movs r7, $1 13 | svc $0x00 14 | 15 | -------------------------------------------------------------------------------- /test/data/metadata-binary.yaml: -------------------------------------------------------------------------------- 1 | ymp: 2 | package: 3 | name: hello 4 | version: 2.12 5 | release: 1 6 | description: Hello world Package 7 | group: 8 | - app.misc 9 | archive-hash: d9da81eaea6b9e6c572d38b800025269f010dd9d 10 | arch: x86_64 11 | archive-size: 185856 12 | -------------------------------------------------------------------------------- /src/ccode/gettext.c: -------------------------------------------------------------------------------- 1 | #ifndef no_locale 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | 9 | void locale_init(){ 10 | setlocale (LC_ALL, ""); 11 | bindtextdomain ("ymp", "/usr/share/locale/"); 12 | textdomain ("ymp"); 13 | 14 | } 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/shcode/code_runner_template.sh: -------------------------------------------------------------------------------- 1 | name: example 2 | on-fail: fail-job 3 | 4 | steps: 5 | - main 6 | 7 | jobs: 8 | main: 9 | uses: local 10 | image: undefined 11 | environs: 12 | - prefix=/usr 13 | run: 14 | - echo hello world 15 | 16 | fail-job: 17 | uses: local 18 | image: undefined 19 | run: | 20 | echo "Failed" 21 | -------------------------------------------------------------------------------- /src/ccode/fetcher_none.c: -------------------------------------------------------------------------------- 1 | #ifdef no_fetcher_backend 2 | #include 3 | 4 | int fetch (char* url, char* path) { 5 | gchar** cmd = {"wget", url, "-o", path, NULL}; 6 | return run_args(cmd); 7 | } 8 | 9 | char* fetch_string(char* url) { 10 | gchar* cmd = g_strdup_printf("wget -o - '%s'", url); 11 | return (char*)getoutput(cmd); 12 | } 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/start/i686.s: -------------------------------------------------------------------------------- 1 | .section .note.GNU-stack 2 | .section .text 3 | .global _start 4 | _start: 5 | pop %eax 6 | mov %esp, %ebx 7 | lea 4(%ebx,%eax,4),%ecx 8 | xor %ebp, %ebp 9 | and $-16, %esp 10 | sub $4, %esp 11 | push %ecx 12 | push %ebx 13 | push %eax 14 | call main 15 | mov %eax, %ebx 16 | movl $1, %eax 17 | int $0x80 18 | 19 | -------------------------------------------------------------------------------- /scripts/detect-revdep: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | file="$1" 3 | ls /var/lib/ymp/files/ | while read line ; do 4 | echo -ne "\033[2K\rCheck:$line" 5 | cat /var/lib/ymp/files/$line | cut -f2 -d" " | while read fline ; do 6 | if ldd /$fline |& grep $(basename $file) &>/dev/null ; then 7 | echo -e "\033[2K\r$line" 8 | break 9 | fi 10 | done 11 | done 12 | -------------------------------------------------------------------------------- /example/plugin/template.vala: -------------------------------------------------------------------------------- 1 | /* This is template ymp plugin. 2 | 3 | For build plugin you must run this command: 4 | valac template.vala --pkg ymp --library=libymp_template.so \ 5 | -X -shared -o libymp_template.so 6 | */ 7 | // Plugins require plugin_init function like this 8 | public void plugin_init () { 9 | // All plugins loaded after ctx_init function. 10 | info ("Hello World"); 11 | } 12 | -------------------------------------------------------------------------------- /example/application/run_script.c: -------------------------------------------------------------------------------- 1 | /* Ymp header */ 2 | #include 3 | /* 4 | Build command: 5 | gcc `pkg-config --cflags --libs ymp` run_script.c -o run_script 6 | */ 7 | 8 | /* Main function */ 9 | int main(int argc, char** argv){ 10 | /* Start ymp */ 11 | ymp_init(argv, argc); 12 | /* add a script */ 13 | add_script("echo hello world"); 14 | /* run */ 15 | return ymp_run(); 16 | } 17 | -------------------------------------------------------------------------------- /src/include/error.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern char* build_string(char* message, ...); 5 | 6 | void error(int status); 7 | void error_add(char* message); 8 | gboolean has_error(); 9 | 10 | #define ferror_add(A, ...) \ 11 | do { \ 12 | char* message = build_string(A, ##__VA_ARGS__); \ 13 | error_add(message); \ 14 | free(message); \ 15 | } while (0) 16 | 17 | -------------------------------------------------------------------------------- /test/rootfs/var/lib/ymp/index/test.yaml: -------------------------------------------------------------------------------- 1 | index: 2 | name: main 3 | package: 4 | name: test 5 | version: 1.0 6 | release: 1 7 | description: test 8 | group: 9 | - test.group 10 | depends: 11 | - glibc 12 | - ymp 13 | archive-hash: test 14 | arch: x86_64 15 | archive-size: 432613 16 | md5sum: test 17 | size: 422132 18 | uri: /test/test_1.0_1_x86_64.ymp 19 | 20 | -------------------------------------------------------------------------------- /example/plugin/template.c: -------------------------------------------------------------------------------- 1 | /* This is template ymp plugin. 2 | 3 | For build plugin you must run this command: 4 | gcc template.c `pkg-config --cflags --libs ymp` -shared \ 5 | -o libymp_template.so 6 | */ 7 | 8 | #include 9 | 10 | // Plugins require plugin_init function like this 11 | void plugin_init(){ 12 | // All plugins loaded after ctx_init function. 13 | info("Hello World",NULL); 14 | } 15 | -------------------------------------------------------------------------------- /tool/check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | touch "$1"/ymp.h 4 | touch "$1"/ymp.vapi 5 | touch "$1"/ymp-cli 6 | touch "$1"/ymp-shell 7 | touch "$1"/ymp-cli-static 8 | touch "$1"/ymp-shell-static 9 | touch "$1"/libymp.so 10 | touch "$1"/libymp-static.a 11 | as -o "$1"/obj.o data/obj.s 12 | for sec in $(readelf -WS "$1"/obj.o | grep "\[.*\] \."| cut -f 2 -d "]" | tr -s " " | cut -f2 -d" ") ; do 13 | objcopy -R$sec "$1"/obj.o &>/dev/null || true 14 | done 15 | -------------------------------------------------------------------------------- /src/operations/shell/dummy.vala: -------------------------------------------------------------------------------- 1 | private static int dummy_operation (string[] args) { 2 | return 0; 3 | } 4 | static void dummy_init () { 5 | operation op = new operation (); 6 | op.help = new helpmsg (); 7 | op.callback.connect (dummy_operation); 8 | op.names = {_ ("init"), "init", ":", "#"}; 9 | op.help.name = _ ("init"); 10 | op.help.shell_only = true; 11 | op.help.description = _ ("Do nothing."); 12 | add_operation (op); 13 | } 14 | -------------------------------------------------------------------------------- /data/org.turkman.ymp.extract.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Extract Archive with Ymp 3 | Name[tr]=Arşivi Ymp ile Çıkart 4 | Comment=Extract archive files with Ymp 5 | Comment[tr]=Arşiv dosyalarını Ymp ile çıkart 6 | Exec=ymp extract --verbose --allow-oem %f 7 | Icon=application-x-ymp 8 | Terminal=true 9 | NoDisplay=true 10 | MimeType=application/zip;application/x-gzip;application/x-bzip2;application/x-xz;application/x-tar; 11 | Type=Application 12 | Categories=Utility; 13 | -------------------------------------------------------------------------------- /scripts/remove-symver: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | sync 4 | if which nm && which patchelf ; then 5 | : Remove symver 6 | else 7 | exit 0 8 | fi 9 | for file in $@ ; do 10 | if [ ! -f $file ] ; then 11 | continue; 12 | fi 13 | nm --dynamic --undefined-only --with-symbol-versions $file | \ 14 | grep GLIBC | tr -s " " | cut -f3 -d" " | cut -f1 -d"@" | while read sym; do 15 | patchelf --clear-symbol-version $sym $file 16 | done 17 | done 18 | -------------------------------------------------------------------------------- /src/operations/shell/clear.vala: -------------------------------------------------------------------------------- 1 | private static int clear_main (string[] args) { 2 | stdout.printf ("\x1b" + "c"); 3 | return 0; 4 | } 5 | static void clear_init () { 6 | operation op = new operation (); 7 | op.help = new helpmsg (); 8 | op.callback.connect (clear_main); 9 | op.names = {_ ("clear"), "clear"}; 10 | op.help.name = _ ("clear"); 11 | op.help.description = _ ("Clear terminal screen."); 12 | op.help.shell_only = true; 13 | add_operation (op); 14 | } 15 | -------------------------------------------------------------------------------- /test/test2.vala: -------------------------------------------------------------------------------- 1 | public class test { 2 | public test(){} 3 | public void p(string message){ 4 | stdout.printf(message); 5 | } 6 | 7 | } 8 | 9 | public void test2(string message){ 10 | stdout.printf(message); 11 | } 12 | 13 | int main(string[] args){ 14 | jobs j = new jobs(); 15 | test t = new test(); 16 | t.p("Hello World\n"); 17 | j.add((void*)t.p, t, "Hello World\n"); 18 | j.add((void*)test2, "Hello World\n"); 19 | j.run(); 20 | ymp_init(args); 21 | return 0; 22 | } -------------------------------------------------------------------------------- /data/code-runner-plugins/docker: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | if [[ "$ACTION" == "init" ]] ; then 4 | container=$(docker run -it --env-file=<(cat /proc/self/environ | tr '\0' '\n') -d -v "$DIRECTORY":/root "$IMAGE" /bin/sh) 5 | echo "container=$container" > .init 6 | elif [[ "$ACTION" == "run" ]] ; then 7 | source .init 8 | docker exec "$container" sh -c "cd /root ; $COMMAND" 9 | elif [[ "$ACTION" == "clean" ]] ; then 10 | source .init 11 | docker rm -f "$container" >/dev/null 12 | rm .init 13 | fi 14 | -------------------------------------------------------------------------------- /src/operations/shell/echo.vala: -------------------------------------------------------------------------------- 1 | private static int echo_main (string[] args) { 2 | print (join (" ", args)); 3 | return 0; 4 | } 5 | static void echo_init () { 6 | operation op = new operation (); 7 | op.help = new helpmsg (); 8 | op.callback.connect (echo_main); 9 | op.names = {_ ("echo"), "echo", "print"}; 10 | op.help.name = _ ("echo"); 11 | op.help.minargs = 1; 12 | op.help.description = _ ("Write a message to terminal."); 13 | op.help.shell_only = true; 14 | add_operation (op); 15 | } 16 | -------------------------------------------------------------------------------- /src/vapi/jobs.vapi: -------------------------------------------------------------------------------- 1 | public struct job { 2 | public unowned void* callback; 3 | public unowned void* args; 4 | public int id; 5 | } 6 | 7 | [CCode (cheader_filename = "jobs.h")] 8 | public class jobs { 9 | public job* jobs; 10 | public jobs(); 11 | public int max; 12 | public int current; 13 | public int parallel; 14 | public int finished; 15 | public int total; 16 | 17 | public void unref (); 18 | public void add (void* callback, void* args, ...); 19 | public void run (); 20 | } 21 | -------------------------------------------------------------------------------- /src/vapi/archive.vapi: -------------------------------------------------------------------------------- 1 | [CCode (cheader_filename = "archive_extract.h")] 2 | public class archive { 3 | public archive(); 4 | public void load(string path); 5 | public void set_target(string path); 6 | public void extract_all(); 7 | public void extract(string path); 8 | public void create(); 9 | public void add(string path); 10 | public string readfile(string path); 11 | public string[] list_files(); 12 | public bool is_archive(string path); 13 | public void set_type(string aformat, string afilt); 14 | } 15 | -------------------------------------------------------------------------------- /src/ccode/plugin.c: -------------------------------------------------------------------------------- 1 | #ifndef _plugin 2 | #define _plugin 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | void load_plugin(char* path){ 9 | void *handle; 10 | handle = dlopen(path, RTLD_LAZY); 11 | if (!handle) { 12 | ferror_add("Failed to load plugin: %s from %s\n ",dlerror(), path); 13 | return; 14 | } 15 | dlerror(); 16 | void (*plugin_func)(); 17 | *(void**)(&plugin_func) = dlsym(handle, "plugin_init"); 18 | plugin_func(); 19 | dlclose(handle); 20 | } 21 | #endif 22 | -------------------------------------------------------------------------------- /src/ccode/users.c: -------------------------------------------------------------------------------- 1 | #ifndef _users 2 | #define _GNU_SOURCE 3 | #define _users 4 | #include 5 | #include 6 | 7 | int is_root(){ 8 | return 0 == getuid(); 9 | } 10 | 11 | uid_t get_uid_by_user(char* username){ 12 | struct passwd *p; 13 | if((p = getpwnam(username)) == NULL){ 14 | return p->pw_uid; 15 | } 16 | return -1; 17 | } 18 | 19 | int switch_user(char* username){ 20 | uid_t u = get_uid_by_user(username); 21 | if(u == (uid_t)setuid(u)){ 22 | return 1; 23 | } 24 | return 0; 25 | } 26 | #endif 27 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | SHELL=/bin/bash 4 | 5 | %: 6 | dh $@ --buildsystem=meson 7 | 8 | override_dh_auto_configure: 9 | mkdir -p obj-`uname -m`-linux-gnu 10 | cd obj-`uname -m`-linux-gnu && \ 11 | LC_ALL=C.UTF-8 meson setup ..\ 12 | --wrap-mode=nodownload \ 13 | --buildtype=plain \ 14 | --prefix=/usr \ 15 | --sysconfdir=/etc \ 16 | --localstatedir=/var \ 17 | --libdir=lib/`uname -m`-linux-gnu \ 18 | -Dlibbrotli=false 19 | 20 | 21 | override_dh_builddeb: 22 | dh_builddeb -- -Zgzip 23 | -------------------------------------------------------------------------------- /scripts/g++-ymp: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | is_shared=false 3 | for arg in "$@" ; do 4 | if [[ "$arg" == "-shared" ]] ; then 5 | is_shared=true 6 | elif [[ "$arg" == "-c" ]] ; then 7 | exec g++ "$@" 8 | elif [[ "$arg" == "-static" ]] ; then 9 | exec g++ "$@" 10 | elif [[ "$arg" == "-nostdlib" ]] ; then 11 | exec g++ "$@" 12 | fi 13 | done 14 | 15 | if [[ "${is_shared}" == true ]] ; then 16 | exec g++ "$@" -nostdlib -lc -fno-plt 17 | else 18 | exec g++ /usr/lib64/start-$(uname -m).o -fvisibility="hidden" "$@" -nostdlib -lc -fno-plt 19 | fi 20 | -------------------------------------------------------------------------------- /scripts/gcc-ymp: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | is_shared=false 3 | for arg in "$@" ; do 4 | if [[ "$arg" == "-shared" ]] ; then 5 | is_shared=true 6 | elif [[ "$arg" == "-c" ]] ; then 7 | exec gcc "$@" 8 | elif [[ "$arg" == "-static" ]] ; then 9 | exec gcc "$@" 10 | elif [[ "$arg" == "-nostdlib" ]] ; then 11 | exec gcc "$@" 12 | fi 13 | done 14 | 15 | if [[ "${is_shared}" == true ]] ; then 16 | exec gcc "$@" -nostdlib -lc -fno-plt 17 | else 18 | exec gcc /usr/lib64/start-$(uname -m).o -fvisibility="hidden" "$@" -nostdlib -lc -fno-plt 19 | fi 20 | -------------------------------------------------------------------------------- /data/fix-turkish.sed: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sed 2 | # This script is part of YMP 3 | # 4 | #This script replace turkish characters with ascii compatible 5 | # ÇİĞÖŞÜ -> CIGOSU and çığöşü -> cigosu 6 | # 7 | # Usage: sed -i -f fix-turkish.sed /path/to/file.po 8 | # For mo files you can use this: 9 | # msgunfmt /path/to/file.po > file.po 10 | # sed -i -f fix-turkish.sed file.po 11 | # msgfmt file.po -o /path/to/file.po 12 | # 13 | s/ç/c/g 14 | s/ı/i/g 15 | s/ğ/g/g 16 | s/ö/o/g 17 | s/ş/s/g 18 | s/ü/u/g 19 | s/Ç/C/g 20 | s/İ/I/g 21 | s/Ğ/G/g 22 | s/Ö/O/g 23 | s/Ş/S/g 24 | s/Ü/U/g 25 | -------------------------------------------------------------------------------- /src/operations/shell/exit.vala: -------------------------------------------------------------------------------- 1 | private static int exit_main (string[] args) { 2 | int status = 0; 3 | if (args.length > 0) { 4 | status = int.parse (args[0]); 5 | } 6 | exit (status); 7 | return 0; 8 | } 9 | static void exit_init () { 10 | operation op = new operation (); 11 | op.help = new helpmsg (); 12 | op.callback.connect (exit_main); 13 | op.names = {_ ("exit"), "exit", "bye"}; 14 | op.help.name = _ ("exit"); 15 | op.help.description = _ ("Exit ymp"); 16 | op.help.shell_only = true; 17 | add_operation (op); 18 | } 19 | -------------------------------------------------------------------------------- /src/vapi/value.vapi: -------------------------------------------------------------------------------- 1 | [CCode (cheader_filename = "value.h")] 2 | public string get_value(string name); 3 | 4 | [CCode (cheader_filename = "value.h")] 5 | public void set_value(string name, string value); 6 | 7 | [CCode (cheader_filename = "value.h")] 8 | public void set_value_readonly(string name, string value); 9 | 10 | [CCode (cheader_filename = "value.h")] 11 | public string[] get_variable_names(); 12 | 13 | [CCode (cheader_filename = "value.h")] 14 | public bool get_bool(string name); 15 | 16 | [CCode (cheader_filename = "value.h")] 17 | public void set_bool(string name, bool value); 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/shcode/pkgbuild_header.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | source @PKGBUILD@ 4 | name="$pkgname" 5 | version="$pkgver" 6 | release="$pkgrel" 7 | description="$pkgdesc" 8 | group=(archlinux unsafe) 9 | source+=(PKGBUILD) 10 | sha256sums+=("SKIP") 11 | pkgdir="$installdir" 12 | srcdir="$HOME" 13 | 14 | function msg(){ 15 | echo "$@" 16 | } 17 | readonly -f msg 18 | 19 | function msg2(){ 20 | echo "$@" 21 | } 22 | readonly -f msg2 23 | 24 | arch-meson(){ 25 | command meson setup \ 26 | --prefix /usr \ 27 | --wrap-mode nodownload \ 28 | "$@" 29 | } 30 | readonly -f arch-meson 31 | 32 | -------------------------------------------------------------------------------- /src/vapi/array.vapi: -------------------------------------------------------------------------------- 1 | [CCode (cheader_filename = "array.h")] 2 | public class array { 3 | public array(); 4 | int size; 5 | string[] data; 6 | public void add(string data); 7 | public void adds(string[] data); 8 | public string[] get(); 9 | public string get_string(); 10 | public int length(); 11 | public void reverse(); 12 | public void uniq(); 13 | public bool has(string item); 14 | public void set(string[] new_data); 15 | public void pop(int index); 16 | public void sort(); 17 | public void insert(string value, int index); 18 | public void remove(string item); 19 | } 20 | -------------------------------------------------------------------------------- /src/process.vala: -------------------------------------------------------------------------------- 1 | private class process { 2 | public string type = ""; 3 | public string[] args = {}; 4 | } 5 | private process[] proc; 6 | private process[] proc_backup; 7 | 8 | public void add_process(string type, string[] args){ 9 | if(proc == null){ 10 | proc = {}; 11 | } 12 | process op = new process (); 13 | op.type = type; 14 | op.args = args; 15 | proc += op; 16 | } 17 | 18 | public void backup_process(){ 19 | proc_backup = proc; 20 | } 21 | 22 | public void restore_process(){ 23 | proc = proc_backup; 24 | } 25 | 26 | 27 | public void clear_process(){ 28 | proc = {}; 29 | } 30 | -------------------------------------------------------------------------------- /src/operations/shell/title.vala: -------------------------------------------------------------------------------- 1 | private static int title_main (string[] args) { 2 | string data=""; 3 | foreach (string arg in args) { 4 | data += arg + " "; 5 | } 6 | set_terminal_title (data[0:data.length - 1]); 7 | return 0; 8 | } 9 | 10 | static void title_init () { 11 | operation op = new operation (); 12 | op.help = new helpmsg (); 13 | op.callback.connect (title_main); 14 | op.names = {_ ("title"), "title"} ; 15 | op.help.name = _ ("title"); 16 | op.help.minargs=1; 17 | op.help.shell_only = true; 18 | op.help.description = _ ("Set terminal title"); 19 | add_operation (op); 20 | } 21 | -------------------------------------------------------------------------------- /example/application/array.c: -------------------------------------------------------------------------------- 1 | /* ymp header */ 2 | #include 3 | /* for printf */ 4 | #include 5 | /* 6 | Build command: 7 | gcc `pkg-config --cflags --libs ymp` array.c -o array 8 | */ 9 | 10 | int main(int argc, char** argv){ 11 | /* define array */ 12 | array *a = array_new(); 13 | /* add items */ 14 | array_add(a,"hello"); 15 | array_add(a,"world"); 16 | array_add(a,"test"); 17 | /* delete item */ 18 | array_remove(a,"test"); 19 | /* get all items */ 20 | int len=0; 21 | char** arr = array_get(a,&len); 22 | /* print items */ 23 | for(int i=0;i 5 | Build-Depends: make, 6 | libarchive-dev, 7 | libreadline-dev, 8 | libcurl4-openssl-dev, 9 | libbrotli-dev, 10 | libmagic-dev, 11 | libidn2-dev, 12 | libpsl-dev, 13 | meson, gcc, valac 14 | Standards-Version: 4.3.0 15 | Homepage: https://turkman.gitlab.io 16 | 17 | Package: ymp 18 | Architecture: any 19 | Depends: ${misc:Depends}, libc6, libarchive13, libreadline8, libcurl4 20 | Description: Yerli ve Milli Package manager (ymp) 21 | A package manager for Turkish 22 | -------------------------------------------------------------------------------- /src/include/jobs.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct _job { 4 | void (*callback)(void*,...); 5 | void* args; 6 | void* ctx; 7 | int id; 8 | } job; 9 | 10 | typedef struct _jobs { 11 | job* jobs; 12 | int max; 13 | int current; 14 | int parallel; 15 | int finished; /* Track the number of finished jobs */ 16 | int total; /* Total number of jobs */ 17 | pthread_cond_t cond; /* Condition variable for signaling job completion */ 18 | } jobs; 19 | 20 | #define MAX_JOB 1024*1024 21 | 22 | void jobs_unref(jobs *j); 23 | void jobs_add(jobs* j, void (*callback)(void*,...), void* ctx, void* args, ...); 24 | void jobs_run(jobs* j); 25 | jobs* jobs_new(); 26 | -------------------------------------------------------------------------------- /src/shcode/flag.sh: -------------------------------------------------------------------------------- 1 | /#&@@@@@@&#* 2 | *%@@@@@@@@@@@@@@@@@@@&#* 3 | *&@@@@@@@@@@&(/* **/#&% 4 | /&@@@@@@@@@#* /(* 5 | *#@@@@@@@@@/ ** 6 | &@@@@@@@@#* *%&( 7 | %@@@@@@@@# *%@@&/*/#&@% 8 | @@@@@@@@&/ **(&@@@@@@@%* 9 | @@@@@@@@&* *#&@@@@@@@@@@@% 10 | @@@@@@@@@( *%@@@@@@@@# 11 | (@@@@@@@@&* *%@@( **(%/ 12 | (@@@@@@@@&/ *##* 13 | /@@@@@@@@@&* * 14 | (@@@@@@@@@@#* /#( 15 | *&@@@@@@@@@@@&#(//**//(%@@% 16 | (&@@@@@@@@@@@@@@@@%/ -------------------------------------------------------------------------------- /data/bash-completion.sh: -------------------------------------------------------------------------------- 1 | function _ymp_help() { 2 | local cur prev opts 3 | COMPREPLY=() 4 | cur="${COMP_WORDS[COMP_CWORD]}" 5 | prev="${COMP_WORDS[COMP_CWORD-1]}" 6 | if [[ "$prev" == ymp ]] ; then 7 | opts=$(command ymp help --no-color --allow-oem | cut -f1 -d" " | grep -v "Operation") 8 | elif [[ "$prev" == install ]] ; then 9 | opts=$(ymp list --no-color --allow-oem | tr -s " " | cut -f2 -d" ") 10 | elif [[ "$prev" == remove ]] ; then 11 | opts=$(ymp list --installed --no-color --allow-oem | tr -s " " | cut -f2 -d" ") 12 | fi 13 | opts=+$(ymp $prev --help --no-color |& grep -- "--[a-z]" | cut -f1 -d: | sed "s/ *//g") 14 | COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) 15 | } 16 | complete -F _ymp_help ymp 17 | 18 | -------------------------------------------------------------------------------- /src/ccode/ttysize.c: -------------------------------------------------------------------------------- 1 | #ifndef _ttysize 2 | #define _GNU_SOURCE 3 | #define _ttysize 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | struct winsize sz; 10 | 11 | int _tty_row; 12 | int _tty_col; 13 | 14 | int get_tty_height(){ 15 | if(_tty_row < 1){ 16 | return 24; 17 | } 18 | return _tty_row; 19 | } 20 | int get_tty_width(){ 21 | if(_tty_col < 1){ 22 | return 80; 23 | } 24 | return _tty_col; 25 | } 26 | 27 | void calculate_size( int signum ){ 28 | ioctl( 0, TIOCGWINSZ, &sz ); 29 | _tty_row = sz.ws_row ; 30 | _tty_col = sz.ws_col; 31 | } 32 | 33 | 34 | void tty_size_init(){ 35 | signal( SIGWINCH, calculate_size ); 36 | calculate_size(SIGWINCH); 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /data/ymp.yaml: -------------------------------------------------------------------------------- 1 | # Main ymp config 2 | ymp: 3 | allow-oem: false 4 | # default use flag settings 5 | use: all 6 | # unblock sigint when operation running 7 | unblock: false 8 | # ymp fetcher useragent 9 | useragent: Ymp fetcher 10 | # default package format 11 | compress: gzip 12 | # emerge mode 13 | no-emerge: false 14 | # debug mode 15 | debug: false 16 | # verbose output 17 | verbose: false 18 | 19 | # Config about build 20 | build: 21 | # if jobs 0 use all cpu cores 22 | jobs: 0 23 | directory: /tmp/ymp-build 24 | target: ymp 25 | debug: false 26 | cflags: -O2 -s 27 | cxxflags: -O2 -s 28 | ldflags: 29 | cc: gcc 30 | 31 | # Package section 32 | package: 33 | # Config about package spesific use flags 34 | use: 35 | #example: example_flag 36 | 37 | -------------------------------------------------------------------------------- /src/operations/utility/brainfuck.vala: -------------------------------------------------------------------------------- 1 | private static int brainfuck_main (string[] args) { 2 | if(get_bool("compile")){ 3 | bf_compile(readfile_raw (args[0])); 4 | //print(ccode); 5 | if(isfile("/tmp/bf.elf")){ 6 | move_file("/tmp/bf.elf",pwd()+"/main"); 7 | return 0; 8 | } 9 | return 1; 10 | } 11 | brainfuck (readfile_raw (args[0]), 1024 * 1024); 12 | return 0; 13 | } 14 | 15 | static void brainfuck_init () { 16 | operation op = new operation (); 17 | op.help = new helpmsg (); 18 | op.callback.connect (brainfuck_main); 19 | op.names = {_ ("brainfuck"), "brainfuck", "bf"}; 20 | op.help.name = _ ("brainfuck"); 21 | op.help.minargs = 1; 22 | op.help.description = _ ("Run a brainfuck script."); 23 | add_operation (op); 24 | } 25 | -------------------------------------------------------------------------------- /src/operations/utility/httpd.vala: -------------------------------------------------------------------------------- 1 | private static int httpd_main (string[] args) { 2 | string cur = pwd(); 3 | string source = get_value("source"); 4 | if(source != ""){ 5 | cd(source); 6 | } 7 | int status = start_httpd (); 8 | cd(cur); 9 | return status; 10 | } 11 | 12 | static void httpd_init () { 13 | operation op = new operation (); 14 | op.help = new helpmsg (); 15 | op.callback.connect (httpd_main); 16 | op.names = {_ ("httpd"), "httpd"}; 17 | op.help.name = _ ("httpd"); 18 | op.help.description = _ ("Simple http server."); 19 | op.help.add_parameter ("--port", _ ("port number")); 20 | op.help.add_parameter ("--source", _ ("source directory")); 21 | op.help.add_parameter ("--allow", _ ("allowed clients (0.0.0.0 for allow everyone)")); 22 | add_operation (op); 23 | } 24 | -------------------------------------------------------------------------------- /ympbuild: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | name=ymp 3 | version=master 4 | release=1 5 | description="Package manager for Turkish" 6 | arch=(i686 x86_64) 7 | url='https://gitlab.com/turkman/' 8 | license=('GPL') 9 | source=(https://gitlab.com/turkman/devel/sources/ymp/-/archive/master/ymp-master.zip) 10 | md5sums=(SKIP) 11 | group=(sys.apps) 12 | uses=(libarchive libcurl) 13 | depends=(readline ncurses glib) 14 | libarchive_depends=(libarchive) 15 | libcurl_depends=(curl) 16 | 17 | cd ymp-master 18 | 19 | setup(){ 20 | meson setup build --prefix=/usr \ 21 | -Ddoc=true \ 22 | -Dscripts=true \ 23 | -Dlibbrotli=false \ 24 | $(use_opt libarchive "" "-Dlibarchive=false") \ 25 | $(use_opt libcurl "" "-Dlibcurl=false") 26 | } 27 | 28 | build(){ 29 | ninja -C build 30 | } 31 | install(){ 32 | DESTDIR=$(DESTDIR) ninja -C build install 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/util/builder_target/dummy.vala: -------------------------------------------------------------------------------- 1 | private static void build_target_dummy_init() { 2 | build_target dummy_target = new build_target(); 3 | dummy_target.suffix = "dummy"; 4 | dummy_target.name = "dummy"; 5 | dummy_target.arch = "none"; 6 | dummy_target.create_source_archive.connect(() => { 7 | writefile("/tmp/dummy-src", ""); 8 | return "/tmp/dummy-src"; 9 | }); 10 | 11 | dummy_target.create_files_info.connect(() => { 12 | return true; 13 | }); 14 | 15 | dummy_target.create_metadata_info.connect(() => { 16 | return true; 17 | }); 18 | 19 | dummy_target.create_data_file.connect(() => { 20 | return; 21 | }); 22 | 23 | dummy_target.create_binary_package.connect(() => { 24 | writefile("/tmp/dummy-pkg", ""); 25 | return "/tmp/dummy-pkg"; 26 | }); 27 | add_build_target(dummy_target); 28 | } 29 | -------------------------------------------------------------------------------- /src/ccode/nostd.c: -------------------------------------------------------------------------------- 1 | #ifndef _nostd 2 | #define _GNU_SOURCE 3 | #define _nostd 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | int saved_stdout = -1; 10 | int saved_stderr = -1; 11 | 12 | int devnull; 13 | void no_stdin(){ 14 | fclose(stdin); 15 | } 16 | 17 | void no_stdout(){ 18 | if(saved_stdout == -1){ 19 | saved_stdout = dup(1); 20 | } 21 | devnull = open("/dev/null", O_WRONLY); 22 | dup2(devnull, STDOUT_FILENO); 23 | } 24 | 25 | void no_stderr(){ 26 | if(saved_stderr == -1){ 27 | saved_stderr = dup(2); 28 | } 29 | devnull = open("/dev/null", O_WRONLY); 30 | dup2(devnull, STDERR_FILENO); 31 | } 32 | 33 | void reset_std(){ 34 | if(saved_stderr != -1){ 35 | dup2(saved_stderr, STDERR_FILENO); 36 | } 37 | if(saved_stdout != -1){ 38 | dup2(saved_stdout, STDOUT_FILENO); 39 | } 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/operations/utility/fetch.vala: -------------------------------------------------------------------------------- 1 | private static int fetch_main (string[] args) { 2 | if (args.length < 1) { 3 | error_add (_ ("URL missing")); 4 | error (2); 5 | } 6 | 7 | if (args.length > 1) { 8 | fetch (args[0], args[1]); 9 | }else { 10 | string data = fetch_string (args[0]); 11 | if (data != null || data != "") { 12 | stdout.printf (data); 13 | } 14 | } 15 | return 0; 16 | } 17 | 18 | static void fetch_init () { 19 | operation op = new operation (); 20 | op.help = new helpmsg (); 21 | op.callback.connect (fetch_main); 22 | op.names = {_ ("fetch"), "fetch", "download", "dl"}; 23 | op.help.name = _ ("fetch"); 24 | op.help.minargs=1; 25 | op.help.description = _ ("Download files from network."); 26 | op.help.add_parameter ("--ignore-ssl", _ ("disable ssl check")); 27 | add_operation (op); 28 | } 29 | -------------------------------------------------------------------------------- /src/vapi/logger.vapi: -------------------------------------------------------------------------------- 1 | [CCode (cheader_filename = "logger.h")] 2 | public void print(string msg); 3 | 4 | [CCode (cheader_filename = "logger.h")] 5 | public void warning(string msg); 6 | 7 | #if DEBUG 8 | [CCode (cheader_filename = "logger.h")] 9 | public void debug(string msg); 10 | 11 | [CCode (cheader_filename = "logger.h")] 12 | public void debug_fn (string message); 13 | #endif 14 | 15 | [CCode (cheader_filename = "logger.h")] 16 | public void info(string msg); 17 | 18 | [CCode (cheader_filename = "logger.h")] 19 | public void print_stderr(string msg); 20 | 21 | [CCode (cheader_filename = "logger.h")] 22 | public void warning_fn (string message); 23 | 24 | [CCode (cheader_filename = "logger.h")] 25 | public void info_fn (string message); 26 | 27 | [CCode (cheader_filename = "logger.h")] 28 | public void logger_init (); 29 | 30 | [CCode (cheader_filename = "logger.h")] 31 | public void set_terminal_title (string message); 32 | -------------------------------------------------------------------------------- /src/operations/shell/amoguscat.vala: -------------------------------------------------------------------------------- 1 | private static int amoguscat_main (string[] args) { 2 | string data=""; 3 | if (args[0] == "-" || args.length == 0) { 4 | string line = " "; 5 | while (line != "") { 6 | line = stdin.read_line (); 7 | data += line+"\n"; 8 | print_with_amogus (data); 9 | } 10 | }else { 11 | data = readfile_raw (args[0]); 12 | print_with_amogus (data); 13 | } 14 | return 0; 15 | } 16 | 17 | static void amoguscat_init () { 18 | operation op = new operation (); 19 | op.help = new helpmsg (); 20 | op.callback.connect (amoguscat_main); 21 | op.names = {_ ("amogus"), "amogus", "sus"}; 22 | op.help.name = _ ("amogus"); 23 | op.help.minargs=1; 24 | op.help.shell_only = true; 25 | op.help.description = _ ("When message is sus."); 26 | op.help.add_parameter ("-", _ ("write from stdin")); 27 | add_operation (op); 28 | } 29 | -------------------------------------------------------------------------------- /src/operations/shell/shitcat.vala: -------------------------------------------------------------------------------- 1 | private static int shitcat_main (string[] args) { 2 | string data=""; 3 | if (args[0] == "-") { 4 | string line = " "; 5 | while (line != "") { 6 | line = stdin.read_line (); 7 | data += line + "\n"; 8 | } 9 | shitcat (data); 10 | }else { 11 | data = readfile_raw (args[0]); 12 | shitcat (data); 13 | } 14 | return 0; 15 | } 16 | 17 | static void shitcat_init () { 18 | operation op = new operation (); 19 | op.help = new helpmsg (); 20 | op.callback.connect (shitcat_main); 21 | op.names = {_ ("shit"), "shitcat", "shit"}; 22 | op.help.name = _ ("shitcat"); 23 | op.help.minargs=1; 24 | op.help.shell_only = true; 25 | op.help.description = _ ("Write message with bad appearance."); 26 | op.help.add_parameter ("!!!", _ ("FUCK LGBT")); 27 | op.help.add_parameter ("-", _ ("read from stdin")); 28 | add_operation (op); 29 | } 30 | -------------------------------------------------------------------------------- /data/ymp-mime.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ymp package 5 | 6 | 7 | 8 | 9 | 10 | Ymp RFP package 11 | 12 | 13 | 14 | 15 | 16 | Ymp Source package 17 | 18 | 19 | 20 | 21 | 22 | Ymp script 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/operations/utility/extract.vala: -------------------------------------------------------------------------------- 1 | private static int extract_main (string[] args) { 2 | var tar = new archive (); 3 | tar.load (args[0]); 4 | if (get_bool ("list")) { 5 | foreach (string file in tar.list_files ()) { 6 | print (file); 7 | } 8 | return 0; 9 | } 10 | tar.set_target(pwd()); 11 | if (args.length > 1) { 12 | foreach (string file in args[1:]) { 13 | tar.extract (file); 14 | } 15 | return 0; 16 | } 17 | tar.extract_all (); 18 | return 0; 19 | } 20 | 21 | static void extract_init () { 22 | operation op = new operation (); 23 | op.help = new helpmsg (); 24 | op.callback.connect (extract_main); 25 | op.names = {_ ("extract"), "extract", "x"}; 26 | op.help.name = _ ("extract"); 27 | op.help.minargs=1; 28 | op.help.description = _ ("Extract files from archive."); 29 | op.help.add_parameter ("--list", _ ("list archive files")); 30 | add_operation (op); 31 | } 32 | -------------------------------------------------------------------------------- /src/operations/package-manager/clean.vala: -------------------------------------------------------------------------------- 1 | public static int clean_main (string[] args) { 2 | print (colorize (_ ("Clean: "), yellow) + _ ("package cache")); 3 | remove_all (get_storage () + "/packages"); 4 | print (colorize (_ ("Clean: "), yellow) + _ ("repository index cache")); 5 | remove_all (get_storage () + "/index"); 6 | print (colorize (_ ("Clean: "), yellow) + _ ("build directory")); 7 | remove_all (DESTDIR + "/tmp/ymp-build/"); 8 | print (colorize (_ ("Clean: "), yellow) + _ ("quarantine")); 9 | quarantine_reset (); 10 | set_value ("OPERATION", "clean"); 11 | directories_init(); 12 | sysconf_main (args); 13 | return 0; 14 | } 15 | 16 | static void clean_init () { 17 | operation op = new operation (); 18 | op.help = new helpmsg (); 19 | op.names = {_ ("clean"), "clean", "cc"}; 20 | op.callback.connect (clean_main); 21 | op.help.name = _ ("clean"); 22 | op.help.description = _ ("Remove all caches."); 23 | add_operation (op); 24 | } 25 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('static', type: 'boolean', value: false) 2 | option('locale', type: 'boolean', value: true) 3 | option('experimental', type: 'boolean', value: false) 4 | option('ansi', type: 'boolean', value: true) 5 | option('optimize', type: 'boolean', value: true) 6 | option('test', type: 'boolean', value: false) 7 | option('doc', type: 'boolean', value: false) 8 | option('tools', type: 'boolean', value: true) 9 | option('scripts', type: 'boolean', value: false) 10 | option('colorize', type: 'boolean', value: true) 11 | option('check_oem', type: 'boolean', value: true) 12 | option('libarchive', type: 'boolean', value: true) 13 | option('libreadline', type: 'boolean', value: true) 14 | option('libcurl', type: 'boolean', value: true) 15 | option('libsoup', type: 'boolean', value: true) 16 | option('libbrotli', type: 'boolean', value: true) 17 | option('storagedir', type: 'string', value: 'var/lib/ymp') 18 | option('distrodir', type: 'string', value: 'lib/turkman') 19 | option('nolibc_path', type: 'string', value: '') 20 | -------------------------------------------------------------------------------- /src/include/array.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifndef GETTEXT_PACKAGE 6 | #define GETTEXT_PACKAGE "ymp" 7 | #endif 8 | 9 | #ifndef _array_h 10 | #define _array_h 11 | 12 | typedef struct { 13 | char **data; 14 | size_t size; 15 | size_t capacity; 16 | size_t removed; 17 | pthread_mutex_t lock; 18 | } array; 19 | 20 | array* array_new(); 21 | void array_add(array *arr, char* data); 22 | void array_adds(array *arr, char** data, size_t len); 23 | void array_set(array *arr, char** new_data, size_t len); 24 | char **array_get(array *arr, int* len); 25 | char *array_get_string(array *arr); 26 | size_t array_length(array *arr); 27 | void array_reverse(array *arr); 28 | void array_uniq(array *arr); 29 | void array_insert(array *arr, char* value, size_t index); 30 | void array_sort(array *arr); 31 | void array_unref(array *arr); 32 | void array_pop(array *arr, size_t index); 33 | bool array_has(array *arr, char* item); 34 | void array_remove(array* arr, char* item); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/constants.h: -------------------------------------------------------------------------------- 1 | // Colors 2 | #define black 30 3 | #define red 31 4 | #define green 32 5 | #define yellow 33 6 | #define blue 34 7 | #define magenta 35 8 | #define cyan 36 9 | #define white 37 10 | // CPU Architecture 11 | #if defined(__x86_64__) 12 | #define getArch() "x86_64" 13 | #define getDebianArch() "amd64" 14 | #elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) 15 | #define getArch() "i386" 16 | #define getDebianArch() "i386" 17 | #elif defined(__aarch64__) 18 | #define getArch() "aarch64" 19 | #define getDebianArch() "arm64" 20 | #elif defined(__ARM_EABI__) 21 | #define getArch() "arm" 22 | #define getDebianArch() "armhf" 23 | #else 24 | #define getArch() "UNKNOWN" 25 | #define getDebianArch() "UNKNOWN" 26 | #endif 27 | // debug function remove if non debug 28 | #ifndef DEBUG 29 | #define debug(A) 30 | #endif 31 | // no locale option 32 | #ifdef no_locale 33 | #define _(A) A 34 | #endif 35 | // define some functions 36 | #define pwd GLib.Environment.get_current_dir 37 | -------------------------------------------------------------------------------- /src/ccode/which.c: -------------------------------------------------------------------------------- 1 | /* for musl libc */ 2 | #ifndef F_OK 3 | #define F_OK 0 4 | #endif 5 | 6 | #ifndef _which 7 | #define _which 8 | #define _GNU_SOURCE 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | char* which(char* cmd){ 16 | char* fullPath = getenv("PATH"); 17 | 18 | struct stat buffer; 19 | int exists; 20 | char* fileOrDirectory = cmd; 21 | char *fullfilename = calloc(1024, sizeof(char)); 22 | 23 | char *token = strtok(fullPath, ":"); 24 | 25 | /* walk through other tokens */ 26 | while( token != NULL ){ 27 | sprintf(fullfilename, "%s/%s", token, fileOrDirectory); 28 | exists = stat( fullfilename, &buffer ); 29 | if ( exists == 0 && ( S_IFREG & buffer.st_mode ) ) { 30 | char ret[strlen(fullfilename)]; 31 | strcpy(ret,fullfilename); 32 | return (char*)fullfilename; 33 | } 34 | 35 | token = strtok(NULL, ":"); /* next token */ 36 | } 37 | return (char*)cmd; 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/operations/utility/yamlget.vala: -------------------------------------------------------------------------------- 1 | private static int yamlget_main (string[] args) { 2 | var file = args[0]; 3 | var path = args[1]; 4 | var yaml = new yamlfile (); 5 | yaml.load (file); 6 | var data = yaml.get (path); 7 | if (args.length > 2) { 8 | var fdata = yaml.get_value (data, args[2]); 9 | if (fdata == "") { 10 | foreach (string item in yaml.get_array (data, args[2])) { 11 | fdata += item + "\n"; 12 | } 13 | data = trim (fdata); 14 | }else { 15 | data = fdata; 16 | } 17 | } 18 | print (data); 19 | return 0; 20 | } 21 | 22 | static void yamlget_init () { 23 | operation op = new operation (); 24 | op.help = new helpmsg (); 25 | op.callback.connect (yamlget_main); 26 | op.names = {_ ("yamlget"), "yamlget", "yaml"}; 27 | op.help.name = _ ("yamlget"); 28 | op.help.minargs = 2; 29 | op.help.usage = _ ("yamlget [file] [path]"); 30 | op.help.description = _ ("Parse yaml files"); 31 | add_operation (op); 32 | } 33 | -------------------------------------------------------------------------------- /src/include/archive_extract.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCHIVE_CREATE_H 2 | #define ARCHIVE_CREATE_H 3 | 4 | #include 5 | 6 | typedef struct archive { 7 | struct archive *archive; 8 | char *archive_path; 9 | char *target_path; 10 | int add_list_size; 11 | int aformat; 12 | int afilter; 13 | array *a; 14 | } archive; 15 | 16 | archive* archive_new(); 17 | void archive_create(); 18 | void archive_unref(archive* arch); 19 | void archive_load(archive* arch, char* path); 20 | void archive_set_target(archive* arch, char* path); 21 | void archive_extract_all(archive* arch); 22 | void archive_extract(archive* arch, char* path); 23 | void archive_create_archive(archive* arch); 24 | void archive_add(archive* arch, char* path); 25 | char* archive_readfile(archive* arch, char* path); 26 | char** archive_list_files(archive* arch, int* len); 27 | int archive_is_archive(archive* arch, char* path); 28 | void archive_write(archive *data, const char *outname, const char **filename); 29 | void archive_set_type(archive *data, char* form, char* filt); 30 | 31 | #endif /* ARCHIVE_CREATE_H */ 32 | 33 | -------------------------------------------------------------------------------- /src/operations/utility/compress.vala: -------------------------------------------------------------------------------- 1 | private static int compress_main (string[] args) { 2 | var tar = new archive (); 3 | tar.load (args[0]); 4 | tar.set_type (get_value ("type"), get_value ("algorithm")); 5 | if (args.length > 1) { 6 | foreach (string file in args[1:]) { 7 | if (isdir (file)) { 8 | foreach (string path in find (file)) { 9 | tar.add (path); 10 | } 11 | }else { 12 | tar.add (file); 13 | } 14 | } 15 | } 16 | tar.create (); 17 | return 0; 18 | } 19 | 20 | static void compress_init () { 21 | operation op = new operation (); 22 | op.help = new helpmsg (); 23 | op.callback.connect (compress_main); 24 | op.names = {_ ("compress"), "compress", "prs"}; 25 | op.help.name = _ ("compress"); 26 | op.help.minargs=1; 27 | op.help.description = _ ("Compress file or directories."); 28 | op.help.add_parameter ("--algorithm", _ ("compress algorithm")); 29 | op.help.add_parameter ("--type", _ ("archive format")); 30 | add_operation (op); 31 | } 32 | -------------------------------------------------------------------------------- /src/operations/shell/exec.vala: -------------------------------------------------------------------------------- 1 | public static int exec_main (string[] args) { 2 | string cmd = join (" ", args); 3 | print_stderr (colorize (_ ("Executing: =>"), blue) + cmd); 4 | int status = 0; 5 | if (get_destdir () != "/") { 6 | status = run_args ( {"chroot", get_destdir (), cmd}) / 256; 7 | }else if (get_bool ("silent")) { 8 | status = run_args_silent (args) / 256; 9 | }else { 10 | status = run_args (args) / 256; 11 | } 12 | if (status != 0) { 13 | error_add (_ ("Failed to run command: %s").printf (cmd)); 14 | } 15 | print_stderr (_ ("Command %s done.".printf (colorize (cmd, blue)))); 16 | return status; 17 | } 18 | 19 | static void exec_init () { 20 | operation op = new operation (); 21 | op.help = new helpmsg (); 22 | op.callback.connect (exec_main); 23 | op.names = {_ ("exec"), "exec"}; 24 | op.help.name = _ ("exec"); 25 | op.help.description = _ ("Execute a command."); 26 | op.help.minargs = 1; 27 | op.help.shell_only = true; 28 | op.help.add_parameter ("--silent", _ ("run without output")); 29 | add_operation (op); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/include/logger.h: -------------------------------------------------------------------------------- 1 | #ifndef LOGGER_H 2 | #define LOGGER_H 3 | 4 | extern char* build_string(char* message, ...); 5 | 6 | void print(char* msg); 7 | void warning(char* msg); 8 | #if DEBUG 9 | void debug(char* msg); 10 | void debug_fn(char* message); 11 | #endif 12 | void info(char* msg); 13 | void print_stderr(char* msg); 14 | void warning_fn(char* message); 15 | void info_fn(char* message); 16 | void logger_init(); 17 | void set_terminal_title(char* message); 18 | 19 | #if DEBUG 20 | #define fdebug(A, ...) \ 21 | do { \ 22 | char* message = build_string(A, ##__VA_ARGS__); \ 23 | debug(message); \ 24 | free(message); \ 25 | } while (0) 26 | #else 27 | #define debug(A) 28 | #define fdebug(A,...) 29 | #endif 30 | 31 | #define finfo(A, ...) \ 32 | do { \ 33 | char* message = build_string(A, ##__VA_ARGS__); \ 34 | info(message); \ 35 | free(message); \ 36 | } while (0) 37 | 38 | #define fwarning(A, ...) \ 39 | do { \ 40 | char* message = build_string(A, ##__VA_ARGS__); \ 41 | warning(message); \ 42 | free(message); \ 43 | } while (0) 44 | 45 | #endif /* LOGGER_H */ 46 | 47 | -------------------------------------------------------------------------------- /src/ccode/daemon.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | #include 12 | 13 | void skeleton_daemon(){ 14 | pid_t pid; 15 | 16 | /* Fork off the parent process */ 17 | pid = fork(); 18 | 19 | /* An error occurred */ 20 | if (pid < 0) 21 | exit(EXIT_FAILURE); 22 | 23 | /* Success: Let the parent terminate */ 24 | if (pid > 0) 25 | exit(EXIT_SUCCESS); 26 | 27 | /* On success: The child process becomes session leader */ 28 | if (setsid() < 0) 29 | exit(EXIT_FAILURE); 30 | 31 | /* Catch, ignore and handle signals */ 32 | signal(SIGCHLD, SIG_IGN); 33 | signal(SIGHUP, SIG_IGN); 34 | 35 | /* Fork off for the second time*/ 36 | pid = fork(); 37 | 38 | /* An error occurred */ 39 | if (pid < 0) 40 | exit(EXIT_FAILURE); 41 | 42 | /* Success: Let the parent terminate */ 43 | if (pid > 0) 44 | exit(EXIT_SUCCESS); 45 | 46 | print_stderr(build_string("Daemon started:\t[%d]\n",getpid ()+1)); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/operations/utility/code_runner.vala: -------------------------------------------------------------------------------- 1 | private static int code_runner_operation (string[] args) { 2 | code_runner_plugin_init(); 3 | if(get_bool("create")){ 4 | if(args.length == 0){ 5 | error_add(_("You must give a new file name.")); 6 | error(2); 7 | } 8 | writefile(args[0],get_code_runner_template()+"\n\n"); 9 | return 0; 10 | }else{ 11 | int status = code_runner_simple(args[0]); 12 | if(status != 0){ 13 | return status; 14 | } 15 | } 16 | return 0; 17 | } 18 | 19 | private static int code_runner_simple(string arg){ 20 | var crun = new code_runner(); 21 | crun.load(arg); 22 | return crun.run(); 23 | } 24 | 25 | static void code_runner_init () { 26 | operation op = new operation (); 27 | op.help = new helpmsg (); 28 | op.help.minargs=1; 29 | op.callback.connect (code_runner_operation); 30 | op.names = {_ ("code-runner"), "code-runner", "cdrn"}; 31 | op.help.name = _ ("code-runner"); 32 | op.help.add_parameter ("--create", _ ("create new from template")); 33 | op.help.add_parameter ("--plugindir", _ ("plugin directory")); 34 | op.help.description = _ ("Run code-runner jobs."); 35 | add_operation (op); 36 | } 37 | -------------------------------------------------------------------------------- /src/ccode/fetcher_soup.c: -------------------------------------------------------------------------------- 1 | #ifdef libsoup 2 | 3 | #include 4 | #include 5 | 6 | int fetch (char* url, char* path){ 7 | GError *error = NULL; 8 | SoupSession * session = soup_session_new(); 9 | SoupMessage * msg = soup_message_new(SOUP_METHOD_GET, url); 10 | GInputStream * in_stream = soup_session_send( 11 | session, 12 | msg, 13 | NULL, 14 | &error); 15 | GFile * output_file = g_file_new_for_path(path); 16 | GFileOutputStream * out_stream = g_file_create(output_file, 17 | G_FILE_CREATE_NONE, NULL, NULL); 18 | g_output_stream_splice((GOutputStream * ) out_stream, in_stream, 19 | G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, 20 | NULL, &error); 21 | if(error){ 22 | return 0; 23 | } 24 | return 1; 25 | } 26 | 27 | char* fetch_string(char* url){ 28 | GError *error = NULL; 29 | SoupSession * session = soup_session_new(); 30 | SoupMessage * msg = soup_message_new(SOUP_METHOD_GET, url); 31 | GBytes *bytes = soup_session_send_and_read ( 32 | session, 33 | msg, 34 | NULL, 35 | &error); 36 | if(error){ 37 | return 0; 38 | } 39 | return strdup((char*)g_bytes_get_data(bytes,NULL)); 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/operations/utility/kill.vala: -------------------------------------------------------------------------------- 1 | private static int kill_main (string[] args) { 2 | string self_link = sreadlink ("/proc/self/exe"); 3 | int self_pid = Posix.getpid (); 4 | foreach (string dir in listdir ("/proc")) { 5 | if (int.parse (dir) != 0) { 6 | int pid = int.parse (dir); 7 | if (pid != self_pid) { 8 | if (issymlink ("/proc/" + dir + "/exe")) { 9 | try { 10 | GLib.FileUtils.read_link ("/proc/" + dir + "/exe"); 11 | }catch (Error e) { 12 | continue; 13 | } 14 | string link = sreadlink ("/proc/" + dir + "/exe"); 15 | if (link == self_link) { 16 | info (_ ("Kill: %s").printf (pid.to_string ())); 17 | ckill (pid); 18 | } 19 | 20 | } 21 | } 22 | } 23 | } 24 | return 0; 25 | } 26 | static void kill_init () { 27 | operation op = new operation (); 28 | op.help = new helpmsg (); 29 | op.callback.connect (kill_main); 30 | op.names = {_ ("kill"), "kill", "gg", "ğ"}; 31 | op.help.name = _ ("kill"); 32 | op.help.description = _ ("Kill all other ymp process."); 33 | add_operation (op); 34 | } 35 | -------------------------------------------------------------------------------- /src/operations/utility/key.vala: -------------------------------------------------------------------------------- 1 | private static int key_main (string[] args) { 2 | if(get_bool("add")){ 3 | if (get_value("name") == ""){ 4 | error_add (_ ("name not defined.")); 5 | return 1; 6 | } 7 | add_gpg_key(args[0], get_value("name")); 8 | }else if(get_bool("remove")){ 9 | remove_file(get_storage()+"/gpg/"+args[0]+".gpg"); 10 | }else if(get_bool("list")){ 11 | foreach(string key in listdir(get_storage()+"/gpg/")){ 12 | if(endswith(key,".gpg")){ 13 | print(key[:-4]); 14 | }else{ 15 | remove_all(key); 16 | } 17 | } 18 | } 19 | return 0; 20 | } 21 | 22 | static void key_init () { 23 | operation op = new operation (); 24 | op.help = new helpmsg (); 25 | op.callback.connect (key_main); 26 | op.names = {_ ("key"), "key"}; 27 | op.help.name = _ ("key"); 28 | op.help.description = _ ("Gpg key operations."); 29 | op.help.add_parameter ("--add", _ ("add new gpg key")); 30 | op.help.add_parameter ("--remove", _ ("remove gpg key")); 31 | op.help.add_parameter ("--list", _ ("list gpg keys")); 32 | op.help.add_parameter (colorize (_ ("Add options"), magenta), ""); 33 | op.help.add_parameter ("--name", _ ("key name")); 34 | add_operation (op); 35 | } 36 | -------------------------------------------------------------------------------- /.github/workflows/blank.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | 7 | workflow_dispatch: 8 | 9 | jobs: 10 | compile: 11 | name: Create deb package 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Check out the repo 15 | uses: actions/checkout@v2 16 | - name: Run the build process with Docker 17 | uses: addnab/docker-run-action@v3 18 | with: 19 | image: debian:testing 20 | options: -v ${{ github.workspace }}:/root -v /output:/output 21 | run: | 22 | set -ex 23 | cd /root 24 | apt update 25 | apt install devscripts equivs -y 26 | yes | mk-build-deps --install 27 | debuild -us -uc -b 28 | mkdir -p /output/ 29 | mv ../*.deb /output/ 30 | mv ./*.deb /output/ 31 | 32 | - uses: "marvinpinto/action-automatic-releases@latest" 33 | with: 34 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 35 | automatic_release_tag: "current" 36 | prerelease: false 37 | title: "Latest release" 38 | files: | 39 | /output/* 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/wslblock.vala: -------------------------------------------------------------------------------- 1 | //DOC: ## WSL shit bloker 2 | //DOC: detect & block WSL 3 | 4 | public extern int fork(); 5 | 6 | private static void wsl_block () { 7 | if (!isfile ("/proc/version")) { 8 | error_add ("/proc not mount"); 9 | } 10 | var cmdline = readfile ("/proc/version").down (); 11 | if ("microsoft" in cmdline) { 12 | fuck (); 13 | }else if ("wsl" in cmdline) { 14 | fuck (); 15 | } 16 | if (isdir ("/sys/class/dmi/id/")) { 17 | return; 18 | } 19 | foreach (string line in readfile ("/proc/cpuinfo").down ().split ("\n")) { 20 | if ("microcode" in line && "0xffffffff" in line) { 21 | fuck (); 22 | } 23 | } 24 | error (31); 25 | } 26 | private static void fuck () { 27 | fork (); 28 | print (_ ("Using ymp in Fucking WSL environment is not allowed.")); 29 | fuck (); 30 | } 31 | 32 | public static bool is_oem_available () { 33 | return isfile ("/sys/firmware/acpi/tables/MSDM"); 34 | } 35 | 36 | public static bool usr_is_merged () { 37 | if (issymlink ("/bin") || issymlink ("/sbin")) { 38 | return true; 39 | } 40 | if (issymlink ("/lib") || issymlink ("/lib64")) { 41 | if ("usr" in sreadlink ("/lib") || "usr" in sreadlink ("/lib64")) { 42 | return true; 43 | } 44 | } 45 | return false; 46 | } 47 | -------------------------------------------------------------------------------- /src/operations/utility/shell.vala: -------------------------------------------------------------------------------- 1 | private static int shell_main (string[] args) { 2 | backup_process(); 3 | clear_process (); 4 | if (args[0] == "-" || args.length == 0) { 5 | set_bool ("shellmode", true); 6 | while (!stdin.eof ()) { 7 | string prompt = colorize ("Ymp >> ", blue); 8 | #if no_libreadline 9 | print_fn (prompt, false, false); 10 | string line = stdin.read_line (); 11 | #else 12 | string line = Readline.readline (prompt); 13 | #endif 14 | if (line != null) { 15 | add_script (line); 16 | ymp_run (); 17 | clear_process (); 18 | }else { 19 | exit_main (args); 20 | } 21 | } 22 | }else { 23 | string data = readfile (args[0]); 24 | add_script (data); 25 | ymp_run (); 26 | clear_process (); 27 | } 28 | restore_process(); 29 | return 0; 30 | } 31 | 32 | static void shell_init () { 33 | operation op = new operation (); 34 | op.help = new helpmsg (); 35 | op.callback.connect (shell_main); 36 | op.names = {_ ("shell"), "shell", "sh"}; 37 | op.help.name = _ ("shell"); 38 | op.help.description = _ ("Create a ymp shell or execute ympsh script."); 39 | add_operation (op); 40 | } 41 | -------------------------------------------------------------------------------- /src/util/code-runner.vala: -------------------------------------------------------------------------------- 1 | private static bool code_runner_plugin_init_done = false; 2 | private static void code_runner_plugin_init(){ 3 | if(code_runner_plugin_init_done){ 4 | return; 5 | } 6 | string plugin_directory = get_value("plugindir"); 7 | if(plugin_directory == ""){ 8 | plugin_directory = "/lib/code-runner/"; 9 | } 10 | if(!isdir(plugin_directory)){ 11 | warning(_("%s directory does not exists.").printf(plugin_directory)); 12 | return; 13 | } 14 | foreach(string plugin in listdir(plugin_directory)){ 15 | code_runner_plugin script = new code_runner_plugin(); 16 | script.name = plugin; 17 | script.init.connect((image, directory)=>{ 18 | setenv("IMAGE", image, 1); 19 | setenv("DIRECTORY", directory, 1); 20 | setenv("ACTION", "init", 1); 21 | run("%s/%s".printf(plugin_directory ,plugin)); 22 | 23 | }); 24 | script.run.connect((command)=>{ 25 | setenv("COMMAND", command, 1); 26 | setenv("ACTION", "run", 1); 27 | int status = run("%s/%s".printf(plugin_directory, plugin)); 28 | return status; 29 | }); 30 | script.clean.connect(()=>{ 31 | setenv("ACTION", "clean", 1); 32 | run("%s/%s".printf(plugin_directory, plugin)); 33 | }); 34 | add_code_runner_plugin(script); 35 | } 36 | code_runner_plugin_init_done = true; 37 | } 38 | -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | # Ymp source code 2 | 3 | ## libymp documentation 4 | look **libymp.md** file 5 | 6 | # Writing documentation 7 | 8 | * Document line must starts with `//DOC:` 9 | * Document type is markdown. 10 | 11 | # source organization 12 | 13 | * **ccode/** has C source files. 14 | * **data/** has package, repository and other functions. 15 | * **operations/** has install/remove and other operation functions. 16 | * **tools/** has command line programs. 17 | * **util/** has utility functions for libymp. 18 | * **constants.h** common preprocessor definitions file 19 | * **ymp.vala** is main libymp file. 20 | * **settings.vala** has init functions and settings. 21 | * **wslblock.vala** has wsl blocker functions. 22 | 23 | # Exit status codes 24 | | Number | Meaning | 25 | |---------|-----------------------| 26 | | 31 | Ymp init error | 27 | | 3 | Archive extract error | 28 | | 2 | File not found | 29 | | 1 | Operation failed | 30 | | 0 | Successfull | 31 | 32 | # How to ymp works 33 | ![ymp-work-schema](ymp-work-schema.svg) 34 | 35 | # How to ymp build 36 | 1. vala sources preprocess with **gcc -E -** command 37 | 1. generated vala sources converted to C sources 38 | 1. gcc compile C sources 39 | 1. link all .o files for creating libymp.so 40 | 1. main.vala converted to C source 41 | 1. gcc compile main.c file 42 | 1. gcc create ymp-cli and link with libymp.so 43 | 44 | ![ymp-build-schema](ymp-build-schema.svg) 45 | -------------------------------------------------------------------------------- /src/ccode/error.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #ifdef __STRICT_ANSI__ 9 | #define strdup(A) strcpy(calloc(strlen(A) + 1, sizeof(char)), A) 10 | #endif 11 | 12 | #include 13 | 14 | extern bool get_bool(char* value); 15 | extern char* build_string(char* format, ...); 16 | extern void print_stderr(char* message); 17 | extern char* colorize(char* message, int color); 18 | extern char* gettext(char* message); 19 | #define _(A) gettext(A) 20 | #define red 31 21 | 22 | static array *error_arr; 23 | 24 | void error(gint status){ 25 | if(!error_arr){ 26 | return; 27 | } 28 | size_t i; 29 | size_t len = 0; 30 | char** errs = array_get(error_arr, &len); 31 | if(len > 0 && !get_bool ("ignore-error")) { 32 | for(i=0;i 0; 57 | } 58 | -------------------------------------------------------------------------------- /doc/sysconf.rst: -------------------------------------------------------------------------------- 1 | Writing sysconf file 2 | ==================== 3 | Sysconf files are package hook mechanism for ymp. 4 | Sysconf files is generally simple shell script but you can prefer any language. 5 | All sysconfig files located at **/etc/sysconf.d**. You can trigger manually with **ymp sysconf** command. 6 | 7 | Example sysconf script here: 8 | 9 | .. code-block:: shell 10 | 11 | current=$(date +%s -r /usr/share/glib-2.0/schemas/) 12 | last=$(cat /var/lib/ymp/sysconf/glib/update.date) 13 | if [ "$current" != "$last" ] ; then 14 | glib-compile-schemas /usr/share/glib-2.0/schemas/ 15 | date +%s -r /usr/share/glib-2.0/schemas/ > /var/lib/ymp/sysconf/glib/update.date 16 | fi 17 | 18 | * /var/lib/ymp/sysconf/ directory created by ymp. 19 | * Sysconf directories removed after package uninstallation. 20 | * You can check directory change time and process hook. 21 | 22 | Ymp forward current operation with **OPERATION** environment variable hovewer remove all other environment variables. 23 | 24 | .. code-block:: shell 25 | 26 | OPERATION=postinst 27 | SHLVL=2 28 | TERM=linux 29 | PATH=/usr/bin:/bin:/usr/sbin:/sbin 30 | PWD=/ 31 | 32 | * **prerm** called before remove operation 33 | * **postrm** called after remove operation 34 | * **preinst** called after install operation 35 | * **postinst** called after install operation 36 | * other operation names same as operation name 37 | 38 | Note: You can not use sysconf **preinst** and **postrm** from target package. 39 | Because package sysconf files are part of package. 40 | 41 | -------------------------------------------------------------------------------- /src/ccode/colorize.c: -------------------------------------------------------------------------------- 1 | #ifndef NOCOLOR 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #ifdef __STRICT_ANSI__ 12 | #define strdup(A) strcpy(calloc(strlen(A) + 1, sizeof(char)), A); 13 | extern int fileno(FILE *stream); 14 | #endif 15 | 16 | static char* int_to_string(int num){ 17 | char *ret = calloc(((sizeof(num) - 1) / 3 + 2), sizeof(char)); 18 | sprintf(ret, "%d", num); 19 | return ret; 20 | } 21 | 22 | 23 | static char* ccolorize(char* msg, char* num){ 24 | char* ret = calloc((strlen(msg)+strlen(num)+13), sizeof(char)); 25 | strcpy(ret,"\x1b["); 26 | strcat(ret,num); 27 | strcat(ret,"m"); 28 | strcat(ret,msg); 29 | strcat(ret,"\x1b[0m"); 30 | return ret; 31 | } 32 | 33 | 34 | char* colorize_fn(char* msg, int color){ 35 | return ccolorize(msg, int_to_string(color)); 36 | } 37 | char* colorize_dummy(char* msg, int color){ 38 | char* ret = strdup(msg); 39 | return ret; 40 | } 41 | 42 | typedef char* (*fn_colorize)(char*,int); 43 | fn_colorize colorize_ptr = colorize_fn; 44 | 45 | void colorize_init(){ 46 | if (get_bool("no-color") || !isatty(fileno(stdout)) || !isatty(fileno(stdout))){ 47 | colorize_ptr = colorize_dummy; 48 | } 49 | } 50 | 51 | char* colorize(char* msg, int color){ 52 | return colorize_ptr(msg, color); 53 | } 54 | #else 55 | #include 56 | char* colorize(char* msg, int color){ 57 | char* ret = strdup(msg); 58 | return ret; 59 | } 60 | #endif 61 | -------------------------------------------------------------------------------- /src/operations/utility/run-sandbox.vala: -------------------------------------------------------------------------------- 1 | private static int run_sandbox_main (string[] args) { 2 | if (usr_is_merged ()) { 3 | error_add (_ ("Sandbox operation with usrmerge is not allowed!")); 4 | error (31); 5 | } 6 | sandbox_shared = get_value ("shared"); 7 | sandbox_tmpfs = get_value ("tmpfs"); 8 | sandbox_rootfs = get_destdir (); 9 | sandbox_uid = int.parse (get_value ("uid")); 10 | sandbox_gid = int.parse (get_value ("gid")); 11 | 12 | if (!get_bool ("no-net")) { 13 | sandbox_network = true; 14 | } 15 | info (_ ("Execute sandbox :%s").printf (join (" ", args))); 16 | if(!get_bool("envs")){ 17 | save_env(); 18 | clear_env(); 19 | setenv("PATH", "/sbin:/bin:/usr/sbin:/usr/bin", 1); 20 | } 21 | int status = sandbox ("exec", args); 22 | if(!get_bool("envs")){ 23 | restore_env(); 24 | } 25 | return status / 256; 26 | } 27 | 28 | static void run_sandbox_init () { 29 | operation op = new operation (); 30 | op.help = new helpmsg (); 31 | op.callback.connect (run_sandbox_main); 32 | op.names = {_ ("sandbox"), "sandbox", "sb"}; 33 | op.help.name = _ ("sandbox"); 34 | op.help.minargs=1; 35 | op.help.description = _ ("Start sandbox environment."); 36 | op.help.add_parameter ("--shared", _ ("select shared directory")); 37 | op.help.add_parameter ("--tmpfs", _ ("select tmpfs directory")); 38 | op.help.add_parameter ("--no-net", _ ("block network access")); 39 | op.help.add_parameter ("--envs", _ ("share environmental variables")); 40 | add_operation (op); 41 | } 42 | -------------------------------------------------------------------------------- /src/cli/main.c: -------------------------------------------------------------------------------- 1 | #if no_locale 2 | char* _(char* msg){ 3 | return msg; 4 | } 5 | #else 6 | #include 7 | #include 8 | #endif 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #if musl 15 | extern int fileno(FILE *f); 16 | #endif 17 | 18 | int main(int argc, char** argv, char** envp){ 19 | #ifndef no_locale 20 | setlocale(LC_ALL, ""); 21 | bindtextdomain("ymp", NULL); 22 | textdomain("ymp"); 23 | #define _ gettext 24 | #endif 25 | /* 26 | ██████╗ ██╗ 27 | ╚════██╗███║ 28 | █████╔╝╚██║ 29 | ╚═══██╗ ██║ 30 | ██████╔╝ ██║ 31 | ╚═════╝ ╚═╝ 32 | */ 33 | ymp_init(argv, argc); 34 | if (get_bool("version")){ 35 | write_version(); 36 | exit(0); 37 | }if(argc < 2){ 38 | gchar* c1 = g_strconcat(_ ("No command given."), "\n", NULL); 39 | gchar* c2; 40 | if (isatty(fileno(stdout))){ 41 | c2 = g_strdup_printf ("\x1b[%dm%s\x1b[;0m", 31, _ ("ymp help")); 42 | } else { 43 | c2 = g_strdup_printf ("%s", _ ("ymp help")); 44 | } 45 | gchar* c3 = g_strdup_printf (_ ("Run %s for more information about usage."), c2); 46 | gchar* msg = g_strconcat (c1, c3, NULL); 47 | error_add (msg); 48 | free(msg); 49 | free(c3); 50 | free(c2); 51 | free(c1); 52 | error (31); 53 | }else { 54 | ymp_init (argv, argc); 55 | add_process (argv[1], argv+2, argc-2); 56 | ymp_run (); 57 | } 58 | if(has_error()){ 59 | error(1); 60 | } 61 | exit(0); 62 | } 63 | -------------------------------------------------------------------------------- /src/ccode/signal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #if __GNU_LIBRARY__ 12 | #include 13 | #endif 14 | typedef void (*sighandler_t)(int); 15 | sighandler_t sigint_signal; 16 | 17 | void block_sigint(){ 18 | sigint_signal = signal(SIGINT, SIG_IGN); 19 | } 20 | 21 | void unblock_sigint(){ 22 | signal(SIGINT, sigint_signal); 23 | } 24 | #if __GNU_LIBRARY__ 25 | static void sigsegv_handler(int sig) { 26 | void *array[10]; 27 | size_t size; 28 | char **strings; 29 | size_t i; 30 | 31 | /* Get backtrace */ 32 | size = backtrace(array, 10); 33 | strings = backtrace_symbols(array, size); 34 | 35 | printf("Caught signal %d\n", sig); 36 | printf("Backtrace:\n"); 37 | for (i = 0; i < size; i++) { 38 | printf("%s\n", strings[i]); 39 | } 40 | 41 | /* Free the memory allocated by backtrace_symbols */ 42 | free(strings); 43 | exit(1); 44 | } 45 | static bool sigsegv_trace_enabled = false; 46 | void enable_sigsegv_trace(){ 47 | if(sigsegv_trace_enabled){ 48 | return; 49 | } 50 | sigsegv_trace_enabled = true; 51 | struct sigaction sigact; 52 | sigact.sa_handler = sigsegv_handler; 53 | sigemptyset(&sigact.sa_mask); 54 | sigact.sa_flags = 0; 55 | sigaction(SIGSEGV, &sigact, NULL); 56 | } 57 | #else 58 | void enable_sigsegv_trace(){} 59 | #endif 60 | 61 | 62 | #ifndef kill 63 | int kill(pid_t pid, int sig); 64 | #endif 65 | 66 | int ckill(int pid){ 67 | return kill(pid,9); 68 | } 69 | -------------------------------------------------------------------------------- /tool/mkctx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | > ctx.vala 3 | ### ctx_init variable build 4 | chmod +x -R ./* 5 | for i in $@ ; do 6 | name=$(echo $i | cut -f1 -d=) 7 | value=$(echo $i | cut -f2 -d=) 8 | echo "private string $name;" 9 | done >> ctx.vala 10 | echo "private string[] operation_names;" >> ctx.vala 11 | 12 | function list_operations(){ 13 | find src/operations -type f -exec basename {} \; | sed "s/\..*//g" | sort 14 | } 15 | 16 | function list_build_targets(){ 17 | find src/util/builder_target -type f -exec basename {} \; | sed "s/\..*//g" | sort 18 | } 19 | 20 | function list_txt(){ 21 | find src/shcode -type f -exec basename {} \; | sed "s/\..*//g" | sort 22 | } 23 | ### ctx_init function build 24 | echo "private static void builder_ctx_init(){" >> ctx.vala 25 | for target_name in $(list_build_targets) ; do 26 | echo " build_target_${target_name/-/_}_init();" 27 | done >> ctx.vala 28 | echo "}" >> ctx.vala 29 | echo "private static void ctx_init(){" >> ctx.vala 30 | for i in $@ ; do 31 | name=$(echo $i | cut -f1 -d=) 32 | value=$(echo $i | cut -f2 -d=) 33 | echo " $name = \"$value\";" 34 | done >> ctx.vala 35 | echo -n " operation_names = {" >> ctx.vala 36 | for op_name in $(list_operations) ; do 37 | echo -n "\"${op_name}\", " 38 | done >> ctx.vala 39 | echo "};" >> ctx.vala 40 | for op_name in $(list_operations) ; do 41 | echo " ${op_name/-/_}_init();" 42 | done >> ctx.vala 43 | echo "}" >> ctx.vala 44 | for i in $(list_txt) ; do 45 | echo -e "private string get_$i(){" 46 | echo -e " return \"" 47 | cat src/shcode/$i.sh | sed 's/\\/\\\\/g;s/"/\\"/g' 48 | echo -e "\n\";" 49 | echo -e "}" 50 | done >> ctx.vala 51 | -------------------------------------------------------------------------------- /data/code-runner-gitea-webhook.py: -------------------------------------------------------------------------------- 1 | from http.server import BaseHTTPRequestHandler, HTTPServer 2 | import subprocess 3 | import shutil 4 | import threading 5 | import json 6 | import os 7 | 8 | builddir="/tmp/code-runner" 9 | class WebhookHandler(BaseHTTPRequestHandler): 10 | def _set_headers(self): 11 | self.send_response(200) 12 | self.send_header('Content-type', 'application/json') 13 | self.end_headers() 14 | 15 | 16 | def run_code_runner(self, target, **kwargs): 17 | subprocess.run(["ymp", "code-runner", target+"/build.yaml"]) 18 | 19 | def do_POST(self): 20 | content_length = int(self.headers['Content-Length']) 21 | post_data = self.rfile.read(content_length) 22 | payload = json.loads(post_data.decode('utf-8')) 23 | 24 | repo=payload["repository"]["clone_url"] 25 | target=builddir+"/"+payload["repository"]["full_name"] 26 | if os.path.exists(target): 27 | shutil.rmtree(target) 28 | if not os.path.isdir(os.path.dirname(target)): 29 | os.makedirs(os.path.dirname(target)) 30 | subprocess.run(["git", "clone", repo, target]) 31 | thread = threading.Thread(target=self.run_code_runner, args=(target,)) 32 | thread.start() 33 | 34 | 35 | self._set_headers() 36 | self.wfile.write(json.dumps({'status': 'success'}).encode('utf-8')) 37 | 38 | def run(server_class=HTTPServer, handler_class=WebhookHandler, port=8000): 39 | server_address = ('', port) 40 | httpd = server_class(server_address, handler_class) 41 | print(f'Starting server on port {port}...') 42 | httpd.serve_forever() 43 | 44 | if __name__ == '__main__': 45 | run() 46 | 47 | -------------------------------------------------------------------------------- /src/operations/utility/sysconf.vala: -------------------------------------------------------------------------------- 1 | private static int sysconf_main (string[] args) { 2 | if (!is_root () || get_bool ("no-sysconf")) { 3 | return 0; 4 | } 5 | save_env(); 6 | clear_env(); 7 | print (colorize (_ ("Running sysconf:"), yellow) + " " + get_value ("OPERATION")); 8 | setenv("PATH","/sbin:/bin:/usr/sbin:/usr/bin", 1); 9 | setenv ("OPERATION", get_value ("OPERATION"), 1); 10 | 11 | if (DESTDIR != "/") { 12 | run_args ( {"chroot", get_destdir (), "ldconfig"}); 13 | }else { 14 | run ("ldconfig"); 15 | } 16 | jobs j = new jobs(); 17 | foreach (string hook in find (get_configdir () + "/sysconf.d")) { 18 | j.add((void*)run_sysconf, strdup(hook)); 19 | } 20 | j.run(); 21 | restore_env(); 22 | return 0; 23 | } 24 | 25 | private static void run_sysconf(string fhook){ 26 | string hook = fhook; 27 | if (isfile (hook)) { 28 | info (_ ("Run hook: %s").printf (sbasename (hook))); 29 | create_dir (get_storage () + "/sysconf/" + sbasename (hook)); 30 | if (DESTDIR != "/") { 31 | hook=hook[DESTDIR.length:]; 32 | if (0 != run_args ( {"chroot", get_destdir (), hook})) { 33 | warning (_ ("Failed to run sysconf: %s").printf (sbasename (hook))); 34 | } 35 | }else if (0 != run_args ({hook})) { 36 | warning (_ ("Failed to run sysconf: %s").printf (sbasename (hook))); 37 | } 38 | } 39 | } 40 | 41 | static void sysconf_init () { 42 | operation op = new operation (); 43 | op.help = new helpmsg (); 44 | op.callback.connect (sysconf_main); 45 | op.names = {_ ("sysconf"), "sc", "sysconf"}; 46 | op.help.name = _ ("sysconf"); 47 | op.help.description = _ ("Trigger sysconf operations."); 48 | add_operation (op); 49 | } 50 | -------------------------------------------------------------------------------- /src/operations/shell/chroot.vala: -------------------------------------------------------------------------------- 1 | private static int chroot_main (string[] args) { 2 | if (!is_root ()) { 3 | error_add (_ ("You must be root!")); 4 | return 1; 5 | } 6 | string cmd = ""; 7 | if (args.length > 1) { 8 | cmd = join (" ", args[1:]); 9 | }else { 10 | cmd = "/bin/sh"; 11 | } 12 | if(!get_bool("envs")){ 13 | save_env(); 14 | clear_env(); 15 | setenv("PATH", "/sbin:/bin:/usr/sbin:/usr/bin", 1); 16 | } 17 | print_stderr (colorize (_ ("chroot: =>"), blue) + args[0]); 18 | run_args_silent ( {"mount", "--bind", "/dev", args[0] + "/dev"}); 19 | run_args_silent ( {"mount", "--bind", "/sys", args[0] + "/sys"}); 20 | run_args_silent ( {"mount", "--bind", "/proc", args[0] + "/proc"}); 21 | run_args_silent ( {"mount", "--bind", "/run", args[0] + "/run"}); 22 | int status = run_args ( {"chroot", args[0], "sh", "-c" , cmd}) / 256; 23 | if (status != 0) { 24 | error_add (_ ("Failed to run command: %s").printf (cmd)); 25 | } 26 | print_stderr (_ ("Command %s done.".printf (colorize (cmd, blue)))); 27 | while ( 0 == run_args_silent ( {"umount", "-lf", "-R", args[0] + "/run"})); 28 | while ( 0 == run_args_silent ( {"umount", "-lf", "-R", args[0] + "/proc"})); 29 | while ( 0 == run_args_silent ( {"umount", "-lf", "-R", args[0] + "/sys"})); 30 | while ( 0 == run_args_silent ( {"umount", "-lf", "-R", args[0] + "/dev"})); 31 | if(!get_bool("envs")){ 32 | restore_env(); 33 | } 34 | return status; 35 | } 36 | static void chroot_init () { 37 | operation op = new operation (); 38 | op.help = new helpmsg (); 39 | op.callback.connect (chroot_main); 40 | op.names = {_ ("chroot"), "chroot"}; 41 | op.help.name = _ ("chroot"); 42 | op.help.description = _ ("Execute a command in chroot."); 43 | op.help.minargs=1; 44 | op.help.shell_only = true; 45 | add_operation (op); 46 | } 47 | -------------------------------------------------------------------------------- /src/util/string.vala: -------------------------------------------------------------------------------- 1 | //DOC: ## String functions 2 | //DOC: easy & safe string operation functions. 3 | 4 | //DOC: `public int[] sindex (string f, string[] array)`: 5 | //DOC: Get item index number array in string array. 6 | public int[] sindex (string f, string[] array) { 7 | int[] ret = {}; 8 | for (int i=0;i < array.length;i++) { 9 | if (array[i] == f) { 10 | ret += i; 11 | } 12 | } 13 | return ret; 14 | } 15 | 16 | //DOC: `string[] ssplit (string data, string f):` 17 | //DOC: safe split function. If data null or empty return empty array. 18 | //DOC: if **f** not in data, return single item array. 19 | public string[] ssplit (string data, string f) { 20 | if (data == null || f == null || data.length == 0) { 21 | debug (_ ("empty data")); 22 | return {}; 23 | }else if (!data.contains (f) || f.length == 0) { 24 | return {data}; 25 | } 26 | string[] ret = {}; 27 | foreach (string i in data.split (f)) { 28 | if (i.length > 0 && i != null) { 29 | ret += i; 30 | } 31 | } 32 | return ret; 33 | } 34 | 35 | //DOC: `string sbasename (string path):` 36 | //DOC: safe basename. return filename 37 | public string sbasename (string path) { 38 | debug (_ ("Basename: %s").printf (path)); 39 | string[] f = ssplit (path, "/"); 40 | return f[f.length - 1]; 41 | } 42 | 43 | //DOC: `string sdirname (string path):` 44 | //DOC: safe dirname. return path name 45 | public string sdirname (string path) { 46 | debug (_ ("Dirname: %s").printf (path)); 47 | string[] f = ssplit (path, "/"); 48 | string ret = ""; 49 | if (f.length == 0) { 50 | return ""; 51 | } 52 | foreach (string g in f[:f.length - 1]) { 53 | ret +=g + "/"; 54 | } 55 | if (path[0] == '/') { 56 | ret = "/" + ret; 57 | } 58 | return ret; 59 | } 60 | 61 | public string[] uniq (string[] array) { 62 | string[] ret = {}; 63 | foreach (string item in array) { 64 | if (! (item in ret)) { 65 | ret += item; 66 | } 67 | } 68 | return ret; 69 | } 70 | 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # YMP (Yerli ve Milli Paket sistemi) 2 | ![ymp logo](data/application-x-ymp.svg) 3 | 4 | A package manager for Turkish 5 | 6 | ## Other Pages 7 | * [**ymp source code document**](src/README.md) 8 | * [**Building a ympbuild file**](doc/ympbuild.rst) 9 | * [**Create application with libymp**](doc/libymp.rst) 10 | 11 | 12 | ## Features 13 | * 🇹🇷 Made in Turkiye 🇹🇷 14 | * Binary / Source package support 15 | * Use flag support (for source packages only) 16 | * Built-in httpd 17 | * Sandbox environment support 18 | * Static build support 19 | * Built-in yaml 20 | * Simple package format 21 | * Built-in repository mirror tool 22 | * Shell mode 23 | * Built-in revdep-rebuild 24 | * Built-in code-runner 25 | 26 | ## Dependencies 27 | * libarchive 28 | * libcurl 29 | * glib2.0 30 | * libreadline 31 | 32 | ## Build Dependencies 33 | * meson 34 | * valac 35 | * gcc 36 | 37 | ## Building from source 38 | ### 1. Install dependencies 39 | #### Debian (testing/unstable): 40 | ```bash 41 | # install compilers 42 | apt install meson gcc valac --no-install-recommends -y 43 | # install dependencies 44 | apt install libarchive-dev libreadline-dev libcurl4-openssl-dev libbrotli-dev --no-install-recommends -y 45 | ``` 46 | #### Archlinux: 47 | ```bash 48 | # install compilers 49 | pacman -Sy gcc vala --noconfirm 50 | # install dependencies 51 | pacman -Sy meson curl libarchive readline --noconfirm 52 | ``` 53 | 54 | #### Alpine: 55 | ```bash 56 | # install compilers 57 | apk add gcc vala 58 | # install dependencies 59 | apk add meson musl-dev bash glib-dev readline-dev libarchive-dev libcurl curl-dev 60 | ``` 61 | 62 | ### 2. Build source code 63 | For options please see **meson_options.txt** 64 | ```bash 65 | meson build 66 | ninja -C build 67 | ``` 68 | * For debian: You may need `-Dlibbrotli=false` option. 69 | 70 | ### 3. Remove symbol versions (optional) 71 | If you want to remove symbol versions: 72 | ```bash 73 | bash scripts/remove-symver build/libymp.so build/ymp-cli build/ymp-shell 74 | ``` 75 | * **note**: For only glibc. 76 | 77 | 78 | ### 4. Install source code 79 | ```bash 80 | ninja -C build install 81 | ldconfig 82 | ``` 83 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL=/bin/bash 2 | build: clean 3 | meson setup build --prefix=/usr -Ddoc=true -Ddebug=true -Dscripts=true -Dlibbrotli=false 4 | ninja -C build 5 | bash scripts/remove-symver build/libymp.so build/ymp-cli build/ymp-shell 6 | 7 | minimal: 8 | meson setup build --prefix=/usr -Ddoc=false -Ddebug=false -Dscripts=false -Dlibbrotli=false -Dlibcurl=false -Dlibarchive=false 9 | ninja -C build 10 | bash scripts/remove-symver build/libymp.so build/ymp-cli build/ymp-shell 11 | 12 | 13 | release: clean 14 | meson setup build --prefix=/usr -Ddoc=true -Ddebug=false -Dscripts=true -Dlibbrotli=false 15 | ninja -C build 16 | 17 | static: clean 18 | meson setup build --prefix=/usr -Ddoc=true -Ddebug=true -Dstatic=true -Dscripts=true -Dlibbrotli=false 19 | ninja -C build 20 | 21 | test: test-clean 22 | meson setup build/_test -Dtest=true -Dtools=false -Dscripts=false -Ddebug=true 23 | ln -s ../test build/test 24 | ninja -C build/_test 25 | cd build/_test ; env LD_LIBRARY_PATH="$$(pwd)"/build G_DEBUG=fatal-criticals yes | timeout 30 ./ymp-test --allow-oem --ask 26 | 27 | test2: 28 | valac --pkg ymp test/test2.vala -C --pkg array --pkg jobs \ 29 | --pkg ymp --vapidir=src/vapi -C -X -g3 30 | mv test/test2.c build/test2.c 31 | gcc -o build/test2 build/test2.c `pkgconf --cflags --libs ymp` \ 32 | -Lbuild -Isrc/include -Ibuild -Lbuild -g3 \ 33 | -Wl,--copy-dt-needed-entries -lgobject-2.0 34 | env LD_LIBRARY_PATH="$$(pwd)"/build ./build/test2 --allow-oem 35 | 36 | install: 37 | DESTDIR=$(DESTDIR) ninja -C build install 38 | 39 | test-clean: 40 | rm -rf build/_test ctx.vala build/test .generated 41 | 42 | 43 | clean: 44 | rm -rf build ctx.vala po/*.mo obj-*-linux-gnu .generated 45 | 46 | pot: 47 | xgettext -o po/ymp.pot --from-code="utf-8" `find src -type f -iname "*.vala"` `find src -type f -iname "*.c"` 2>/dev/null 48 | for file in `ls po/*.po`; do \ 49 | msgmerge $$file po/ymp.pot -o $$file.new ; \ 50 | echo POT: $$file; \ 51 | rm -f $$file ; \ 52 | mv $$file.new $$file ; \ 53 | done 54 | sed -f data/fix-turkish.sed -i po/tr.po 55 | 56 | fix: 57 | find src -type f -exec sed -i "s/^ *$$//g;s/ *$$//g" {} \; 58 | -------------------------------------------------------------------------------- /src/operations/utility/debian.vala: -------------------------------------------------------------------------------- 1 | private static int debian_main (string[] args) { 2 | string output = get_value ("output"); 3 | if (output == "") { 4 | output=pwd (); 5 | } 6 | if (get_bool ("extract")) { 7 | foreach (string arg in args) { 8 | deb_extract (arg, output); 9 | } 10 | }else if (get_bool ("create")) { 11 | foreach (string arg in args) { 12 | deb_create (arg, output); 13 | } 14 | } 15 | 16 | if (get_bool ("update-catalog")) { 17 | debian_update_catalog (); 18 | }if (get_bool ("get-pkgname")) { 19 | foreach (string arg in args) { 20 | print (find_debian_pkgname_from_catalog (arg)); 21 | } 22 | } 23 | 24 | if (get_bool ("install")) { 25 | set_bool ("convert", true); 26 | }if (get_bool ("convert")) { 27 | foreach (string arg in args) { 28 | debian_convert (srealpath (arg)); 29 | } 30 | } 31 | return 0; 32 | } 33 | 34 | static void debian_init () { 35 | operation op = new operation (); 36 | op.help = new helpmsg (); 37 | op.callback.connect (debian_main); 38 | op.names = {_ ("debian"), "deb", "debian"}; 39 | op.help.name = _ ("debian"); 40 | op.help.description = _ ("Debian package operations."); 41 | op.help.add_parameter (colorize (_ ("Package options"), magenta), ""); 42 | op.help.add_parameter ("--extract", _ ("extract debian package")); 43 | op.help.add_parameter ("--create", _ ("create debian package")); 44 | op.help.add_parameter ("--convert", _ ("convert debian package to ymp package")); 45 | op.help.add_parameter (colorize (_ ("Install options"), magenta), ""); 46 | op.help.add_parameter ("--install", _ ("install debian package") + colorize (colorize (colorize (" (%s)", red), 5), 1).printf (_ ("Dangerous"))); 47 | op.help.add_parameter (colorize (_ ("Catalog options"), magenta), ""); 48 | op.help.add_parameter ("--update-catalog", _ ("update debian catalog from debian repository")); 49 | op.help.add_parameter ("--get-pkgname", _ ("get source package name from catalog")); 50 | op.help.add_parameter ("--mirror", _ ("debian mirror url")); 51 | add_operation (op); 52 | } 53 | -------------------------------------------------------------------------------- /src/util/builder_target/deb.vala: -------------------------------------------------------------------------------- 1 | private static void build_target_deb_init() { 2 | build_target deb_target = new build_target(); 3 | deb_target.suffix = "deb"; 4 | deb_target.name = "deb"; 5 | deb_target.arch = getDebianArch(); 6 | deb_target.create_source_archive.connect(() => { 7 | return "ignore"; 8 | }); 9 | 10 | deb_target.create_files_info.connect(() => { 11 | return true; 12 | }); 13 | 14 | deb_target.create_metadata_info.connect(() => { 15 | string buildpath = srealpath(deb_target.builder.ymp_build.ympbuild_buildpath); 16 | create_dir(buildpath + "/output/DEBIAN/"); 17 | string control = ""; 18 | string metadata = deb_target.builder.ymp_build.get_ympbuild_metadata(); 19 | var yaml = new yamlfile(); 20 | yaml.data = metadata; 21 | string srcdata = yaml.get("ymp.source"); 22 | string name = yaml.get_value(srcdata, "name"); 23 | string version = yaml.get_value(srcdata, "version"); 24 | string maintainer = yaml.get_value(srcdata, "maintainer"); 25 | string email = yaml.get_value(srcdata, "email"); 26 | control += "Package: %s\n".printf(name); 27 | control += "Version: %s\n".printf(version); 28 | control += "Architecture: %s\n".printf(getDebianArch()); 29 | control += "Installed-Size: 1\n"; 30 | control += "Maintainer: %s <%s>\n".printf(maintainer, email); 31 | control += "Depends: %s\n".printf(join(", ", yaml.get_array(srcdata, "depends"))); 32 | control += "Description: %s\n".printf(yaml.get_value(srcdata, "description")); 33 | control += " Created by YMP/%s\n".printf(VERSION); 34 | writefile(buildpath + "/output/DEBIAN/control", control); 35 | deb_target.builder.output_package_name = name + "_" + version; 36 | return true; 37 | }); 38 | 39 | deb_target.create_data_file.connect(() => { 40 | return; 41 | }); 42 | 43 | deb_target.create_binary_package.connect(() => { 44 | string buildpath = srealpath(deb_target.builder.ymp_build.ympbuild_buildpath); 45 | deb_create(buildpath+"/output", buildpath); 46 | return buildpath+"/output.deb"; 47 | }); 48 | add_build_target(deb_target); 49 | } 50 | -------------------------------------------------------------------------------- /src/operations/package-manager/build.vala: -------------------------------------------------------------------------------- 1 | private bool no_src = false; 2 | private static int build_operation (string[] args) { 3 | string current_directory=pwd (); 4 | string[] new_args = args; 5 | if (new_args.length == 0) { 6 | new_args = {pwd()}; 7 | } 8 | foreach (string arg in new_args) { 9 | info (_ ("Building %s").printf (arg)); 10 | var bd = new builder (); 11 | int r = bd.build_single (arg); 12 | if (r != 0) { 13 | error_add("Build path: %s (%s)".printf(bd.ymp_build.ympbuild_buildpath, arg)); 14 | return r; 15 | } 16 | if(get_bool("install") && !get_bool("no-binary")) { 17 | string[] leftovers = calculate_leftover ({bd.ymp_build.get_ympbuild_value("name")}); 18 | quarantine_import_from_path(bd.ymp_build.ympbuild_buildpath); 19 | quarantine_install (); 20 | quarantine_reset (); 21 | foreach (string file in leftovers) { 22 | remove_file (DESTDIR + "/" + file); 23 | } 24 | } 25 | } 26 | cd (current_directory); 27 | return 0; 28 | } 29 | static void build_init () { 30 | operation op = new operation (); 31 | op.help = new helpmsg (); 32 | op.callback.connect (build_operation); 33 | op.names = {_ ("build"), "build", "bi", "make"}; 34 | op.help.name = _ ("build"); 35 | op.help.description = _ ("Build package from ympbuild file."); 36 | op.help.add_parameter ("--no-source", _ ("do not generate source package")); 37 | op.help.add_parameter ("--no-binary", _ ("do not generate binary package")); 38 | op.help.add_parameter ("--no-build", _ ("do not build package (only test and package)")); 39 | op.help.add_parameter ("--unsafe", _ ("do not check filesystem safety")); 40 | op.help.add_parameter ("--no-package", _ ("do not install package after building")); 41 | op.help.add_parameter ("--ignore-dependency", _ ("disable dependency check")); 42 | op.help.add_parameter ("--no-emerge", _ ("use binary packages")); 43 | op.help.add_parameter ("--builddir", _ ("build directory")); 44 | op.help.add_parameter ("--compress", _ ("compress format")); 45 | op.help.add_parameter ("--install", _ ("install binary package after building")); 46 | add_operation (op); 47 | } 48 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | debian: 2 | image: debian:testing 3 | stage: build 4 | artifacts: 5 | expire_in: 1 week 6 | paths: 7 | - build 8 | script: 9 | - apt update 10 | - apt full-upgrade -y 11 | - apt install meson gcc valac gobject-introspection patchelf --no-install-recommends -y 12 | - apt install libarchive-dev libreadline-dev libcurl4-openssl-dev libbrotli-dev libmagic-dev libidn2-0-dev libpsl-dev --no-install-recommends -y 13 | - meson build -Ddebug=true -Dtools=true -Dlibbrotli=false -Dtest=true 14 | - ninja -C build 15 | - bash scripts/remove-symver build/libymp.so build/ymp-cli build/ymp-shell 16 | - cd build && timeout 30 ./ymp-test || true 17 | - ninja install 18 | 19 | archlinux: 20 | image: archlinux:latest 21 | stage: build 22 | artifacts: 23 | expire_in: 1 week 24 | paths: 25 | - build 26 | script: 27 | - pacman -Syyu --noconfirm 28 | - pacman -Sy gcc vala gobject-introspection patchelf which --noconfirm 29 | - pacman -Sy meson curl libarchive readline file --noconfirm 30 | - meson build -Ddebug=true -Dtools=true -Dtest=true 31 | - ninja -C build 32 | - bash scripts/remove-symver build/libymp.so build/ymp-cli build/ymp-shell 33 | - cd build && timeout 30 ./ymp-test || true 34 | - ninja install 35 | 36 | alpine: 37 | image: alpine:edge 38 | stage: build 39 | artifacts: 40 | expire_in: 1 week 41 | paths: 42 | - build 43 | script: 44 | - apk update 45 | - apk add meson musl-dev gcc bash vala glib-dev readline-dev libarchive-dev libcurl curl-dev upx file-dev libmagic 46 | - apk add libarchive readline glib zlib ncurses acl expat openssl xz-dev zstd lz4 bzip2 curl brotli nghttp2 libidn2-dev libidn2 libpsl-dev libpsl 47 | - meson build -Ddebug=false -Dtools=true -Dtest=true 48 | - ninja -C build 49 | - upx -9 build/* || true 50 | - cd build && timeout 30 ./ymp-test || true 51 | - ninja install 52 | 53 | turkman: 54 | image: registry.gitlab.com/turkman/devel/assets/docker-images 55 | stage: build 56 | artifacts: 57 | expire_in: 1 week 58 | paths: 59 | - build 60 | script: 61 | - ymp repo --update --ignore-gpg 62 | - ymp it meson ninja gcc bash vala binutils flex pkgconf file --no-emerge --upgrade --ignore-quarantine 63 | - meson build -Ddebug=false -Dtools=true -Dtest=true -Dlibbrotli=false 64 | - ninja -C build 65 | - ninja -C build install 66 | -------------------------------------------------------------------------------- /src/ccode/job.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | typedef struct _worker_job { 12 | jobs* j; 13 | int id; 14 | } worker_job; 15 | 16 | extern char* get_value(char* name); 17 | 18 | static void* worker_thread(void* arg) { 19 | worker_job* jb= (worker_job*)arg; 20 | jobs *j = jb->j; 21 | int i; 22 | for (i = jb->id; i < j->total; i+=j->parallel) { 23 | fdebug("Run job: %d\t%d\t\t%d\t%d\n", j->total, j->parallel, i, jb->id); 24 | j->jobs[i].callback((void*)j->jobs[i].ctx, (void*)j->jobs[i].args); 25 | j->finished++; 26 | } 27 | return NULL; 28 | } 29 | 30 | void jobs_unref(jobs *j) { 31 | free(j->jobs); 32 | pthread_cond_destroy(&j->cond); 33 | free(j); 34 | } 35 | 36 | void jobs_add(jobs* j, void (*callback)(void*, ...), void* ctx, void* args, ...) { 37 | if (j->total < j->max) { 38 | job new_job; 39 | new_job.callback = callback; 40 | new_job.args = args; 41 | new_job.ctx = ctx; 42 | new_job.id = j->total; 43 | j->jobs[j->total++] = new_job; 44 | j->current++; 45 | pthread_cond_signal(&j->cond); 46 | fdebug("Add job:%d\t%d\t%d\n", j->total, j->max, j->parallel); 47 | } 48 | } 49 | 50 | void jobs_run(jobs* j) { 51 | pthread_t* threads = (pthread_t*)calloc(j->parallel, sizeof(pthread_t)); 52 | int i; 53 | for (i = 0; i < j->parallel; ++i) { 54 | worker_job *jb = (worker_job*)calloc(1,sizeof(worker_job)); 55 | jb->j = j; 56 | jb->id = i; 57 | pthread_create(&threads[i], NULL, worker_thread, (void*)jb); 58 | } 59 | for (i = 0; i < j->parallel; ++i) { 60 | pthread_join(threads[i], NULL); 61 | } 62 | fdebug("Done jobs:%d\t%d\t%d\n", j->finished, j->max, j->parallel); 63 | free(threads); 64 | } 65 | 66 | jobs* jobs_new() { 67 | jobs* j = (jobs*)malloc(sizeof(jobs)); 68 | j->max = MAX_JOB; 69 | j->current = 0; 70 | j->finished = 0; 71 | j->total = 0; 72 | j->parallel = atoi(get_value("jobs")); 73 | if(j->parallel < 1){ 74 | j->parallel = get_nprocs_conf(); 75 | } 76 | j->jobs = (job*)malloc(j->max * sizeof(job)); 77 | pthread_cond_init(&j->cond, NULL); 78 | fdebug("New jobs"); 79 | return j; 80 | } 81 | -------------------------------------------------------------------------------- /src/operations/package-manager/bootstrap.vala: -------------------------------------------------------------------------------- 1 | private static int bootstrap_main (string[] args) { 2 | if (!is_root ()) { 3 | error_add (_ ("You must be root!")); 4 | } 5 | string repo=get_value ("mirror"); 6 | string rootfs=get_destdir (); 7 | if (repo == "") { 8 | error_add (_ ("Mirror is not defined. Please use --mirror .")); 9 | }if (DESTDIR == "/") { 10 | error_add (_ ("Destdir is not defined. Please use --destdir .")); 11 | } 12 | if (isfile (DESTDIR + "/etc/os-release")) { 13 | error_add (_ ("Target rootfs already exists: %s").printf (DESTDIR)); 14 | } 15 | error (2); 16 | info (colorize (_ ("Creating bootstrap."), blue)); 17 | string[] basedir = {"dev", "sys", "proc", "run"}; 18 | string[] base_packages = {"busybox", "base-files", "glibc"}; 19 | foreach (string dir in basedir) { 20 | create_dir (rootfs + "/" + dir); 21 | } 22 | GLib.FileUtils.chmod (rootfs + "/tmp", 0777); 23 | bool sysconf = get_bool ("no-sysconf"); 24 | set_bool ("no-sysconf", true); 25 | copy_file ("/etc/resolv.conf", rootfs + "/etc/resolv.conf"); 26 | writefile (rootfs + "/" + STORAGEDIR + "/sources.list.d/main", repo + "\n"); 27 | writefile (rootfs + "/" + STORAGEDIR + "/restricted.list", "/data/user\n"); 28 | fetch(repo.replace("$uri", "ymp-index.yaml.asc"), rootfs + "/tmp/main.asc"); 29 | add_gpg_key(rootfs + "/tmp/main.asc", "main"); 30 | remove_file(rootfs + "/tmp/main.asc"); 31 | update_main (args); 32 | install_main (base_packages); 33 | foreach (string package in base_packages) { 34 | string hook = get_configdir () + "/sysconf.d/"; 35 | create_dir (get_destdir () + "/var/lib/ymp/sysconf/" + package); 36 | hook = hook[get_destdir ().length:]; 37 | run_args ( {"chroot", get_destdir (), hook + package}); 38 | } 39 | install_main (args); 40 | set_bool ("no-sysconf", sysconf); 41 | sysconf_main (args); 42 | return 0; 43 | } 44 | 45 | static void bootstrap_init () { 46 | operation op = new operation (); 47 | op.callback.connect (bootstrap_main); 48 | op.names = {_ ("bootstrap"), "bootstrap", "bst"}; 49 | op.help = new helpmsg (); 50 | op.help.name = _ ("bootstrap"); 51 | op.help.description = _ ("Create new rootfs filesystem."); 52 | op.help.add_parameter ("--mirror", _ ("bootstrap mirror uri")); 53 | op.help.add_parameter ("--no-emerge", _ ("use binary packages")); 54 | add_operation (op); 55 | } 56 | -------------------------------------------------------------------------------- /src/operations.vala: -------------------------------------------------------------------------------- 1 | private operation[] ops; 2 | private class operation { 3 | public signal int callback (string[] args); 4 | public string[] names; 5 | public helpmsg help; 6 | } 7 | 8 | private void add_operation (operation op) { 9 | debug (_ ("Add operation: %s").printf (join (":", op.names))); 10 | ops += op; 11 | } 12 | 13 | private static void lock_operation () { 14 | block_sigint (); 15 | if (get_bool ("unblock")) { 16 | unblock_sigint (); 17 | } 18 | } 19 | private static void unlock_operation () { 20 | unblock_sigint (); 21 | } 22 | 23 | private static int operation_main(string type, string[] args){ 24 | if(get_bool("sandbox") && !isfile("/.sandbox")){ 25 | info (_ ("RUN (SANDBOX):") + type + ":" + join (" ", args)); 26 | sandbox_shared = get_value ("shared"); 27 | sandbox_tmpfs = get_value ("tmpfs"); 28 | sandbox_rootfs = get_destdir (); 29 | sandbox_uid = int.parse (get_value ("uid")); 30 | sandbox_gid = int.parse (get_value ("gid")); 31 | return sandbox(type, args); 32 | } 33 | info (_ ("RUN:") + type + ":" + join (" ", args)); 34 | string[] new_args = {}; 35 | bool e = false; 36 | for(int i=0;args[i] != null;i++){ 37 | string arg = args[i]; 38 | if (startswith(arg,"$(") && endswith(arg,")")){ 39 | arg = getoutput(arg[2:-1]).strip(); 40 | }else if (arg.length > 1 && arg[0] == '$') { 41 | arg = get_value (arg[1:]); 42 | } 43 | foreach(string name in get_variable_names()){ 44 | if("${%s}".printf(name) in arg){ 45 | arg = arg.replace("${%s}".printf(name), get_value(name)); 46 | } 47 | } 48 | if(arg == "--"){ 49 | e = true; 50 | continue; 51 | } 52 | if(!e && startswith(arg,"--")){ 53 | continue; 54 | } 55 | new_args += arg; 56 | } 57 | debug (_ ("RUN:") + type + ":" + join (" ", new_args)); 58 | foreach (operation op in ops) { 59 | foreach (string name in op.names) { 60 | if (type == name) { 61 | if (get_bool ("help") || op.help.minargs > new_args.length) { 62 | return help_main ({name}); 63 | } 64 | set_value_readonly ("OPERATION", op.help.name); 65 | return op.callback (new_args); 66 | } 67 | } 68 | } 69 | warning (_ ("Invalid operation name: %s").printf (type)); 70 | return 0; 71 | } 72 | 73 | -------------------------------------------------------------------------------- /src/operations/utility/file.vala: -------------------------------------------------------------------------------- 1 | private static int file_main (string[] args) { 2 | if (get_bool ("remove")) { 3 | return remove_file_main (args); 4 | }else if (get_bool ("copy")) { 5 | return copy_file_main (args); 6 | }else if (get_bool ("move")) { 7 | return move_file_main (args); 8 | }else if (get_bool ("extract")) { 9 | return extract_main (args); 10 | } 11 | return 0; 12 | } 13 | 14 | private static int remove_file_main (string[] args) { 15 | foreach (string arg in args) { 16 | remove_all (arg); 17 | } 18 | return 0; 19 | } 20 | 21 | private static int copy_file_main (string[] args) { 22 | if (args.length < 2) { 23 | error_add (_ ("Source or Target is not defined.")); 24 | error (1); 25 | } 26 | string src = srealpath (args[0]); 27 | string desc = srealpath (args[1]); 28 | if (isfile (src) || issymlink (src)) { 29 | if (isdir (desc)) { 30 | desc += "/" + sbasename (src); 31 | } 32 | copy_file (src, desc); 33 | }else { 34 | foreach (string file in find (src)) { 35 | string target=file[src.length:]; 36 | copy_file (file, desc + "/" + target); 37 | } 38 | } 39 | return 0; 40 | } 41 | 42 | private static int move_file_main (string[] args) { 43 | if (args.length < 2) { 44 | error_add (_ ("Source or Target is not defined.")); 45 | error (1); 46 | } 47 | string src = srealpath (args[0]); 48 | string desc = srealpath (args[1]); 49 | if (isfile (src) || issymlink (src)) { 50 | if (isdir (desc)) { 51 | desc += "/" + sbasename (src); 52 | } 53 | move_file (src, desc); 54 | }else { 55 | foreach (string file in find (src)) { 56 | string target=file[src.length:]; 57 | move_file (file, desc + "/" + target); 58 | } 59 | } 60 | return 0; 61 | } 62 | 63 | static void file_init () { 64 | operation op = new operation (); 65 | op.help = new helpmsg (); 66 | op.callback.connect (file_main); 67 | op.names = {_ ("file"), "f", "file"}; 68 | op.help.name = _ ("file"); 69 | op.help.minargs=1; 70 | op.help.description = _ ("Copy / Move / Remove files or directories."); 71 | op.help.add_parameter ("--remove", _ ("remove file or directories")); 72 | op.help.add_parameter ("--copy", _ ("copy file or directories")); 73 | op.help.add_parameter ("--move", _ ("move file or directories")); 74 | op.help.add_parameter ("--extract", _ ("extract archive file (same as extract operation)")); 75 | add_operation (op); 76 | } 77 | -------------------------------------------------------------------------------- /src/ymp.vala: -------------------------------------------------------------------------------- 1 | private bool ymp_activated = false; 2 | 3 | #ifndef no_locale 4 | private extern void locale_init(); 5 | private extern void enable_sigsegv_trace(); 6 | public const string GETTEXT_PACKAGE="ymp"; 7 | #endif 8 | public void ymp_init (string[] args) { 9 | if(ymp_activated){ 10 | return; 11 | } 12 | enable_sigsegv_trace(); 13 | #ifndef no_locale 14 | locale_init(); 15 | #endif 16 | c_umask (022); 17 | // initial load 18 | parse_args(args); 19 | logger_init(); 20 | settings_init (); 21 | wsl_block (); 22 | ctx_init (); 23 | // override settings 24 | parse_args(args); 25 | #if SHARED 26 | info (_ ("Plugin manager init")); 27 | foreach (string lib in find (DISTRODIR)) { 28 | string libname = sbasename (lib); 29 | if (startswith (libname, "libymp_") && endswith (libname, ".so")) { 30 | info (_ ("Load plugin: %s").printf (libname)); 31 | load_plugin (lib); 32 | } 33 | } 34 | #endif 35 | directories_init (); 36 | #if check_oem 37 | if (is_oem_available ()) { 38 | warning (_ ("OEM detected! Ymp may not working good.")); 39 | #if experimental 40 | if(true) { 41 | #else 42 | if (!get_bool ("ALLOW-OEM") && ! isfile("/.allow-oem")) { 43 | #endif 44 | error_add (_ ("OEM is not allowed! Please use --allow-oem to allow oem.")); 45 | error_add (_ ("If you wish to bypass this error entirely, create /.allow-oem empty file.")); 46 | } 47 | } 48 | if (usr_is_merged ()) { 49 | warning (_ ("UsrMerge detected! Ymp may not working good.")); 50 | } 51 | #endif 52 | if (has_error ()) { 53 | error (31); 54 | } 55 | ymp_activated = true; 56 | } 57 | 58 | private static void directories_init () { 59 | create_dir (get_build_dir ()); 60 | GLib.FileUtils.chmod (get_build_dir (), 0777); 61 | create_dir (get_storage () + "/index/"); 62 | create_dir (get_storage () + "/packages/"); 63 | create_dir (get_storage () + "/metadata/"); 64 | create_dir (get_storage () + "/files/"); 65 | create_dir (get_storage () + "/links/"); 66 | create_dir (get_storage () + "/gpg/"); 67 | create_dir (get_storage () + "/sources.list.d/"); 68 | create_dir (get_storage () + "/quarantine/"); 69 | if (!isfile (get_storage () + "/sources.list")) { 70 | writefile (get_storage () + "/sources.list", ""); 71 | } 72 | #if experimental 73 | if (is_root ()) { 74 | foreach (string path in find (get_storage ())) { 75 | chmod (path, 0755); 76 | chown (path, 0, 0); 77 | } 78 | } 79 | #endif 80 | GLib.FileUtils.chmod (get_storage () + "/gpg/", 0700); 81 | } 82 | -------------------------------------------------------------------------------- /src/util/gpg.vala: -------------------------------------------------------------------------------- 1 | //DOC: # sign & verify file 2 | //DOC: `void sign_file (string path):` 3 | //DOC: sign a file with gpg key 4 | public void sign_file (string path) { 5 | if (!isfile (path)) { 6 | return; 7 | } 8 | run_args ( {"gpg", "--batch", "--yes", "--sign", "-r", get_value ("gpg:repicent"), path}); 9 | } 10 | 11 | //DOC: # sign & verify file 12 | //DOC: `void sign_file (string path):` 13 | //DOC: sign a file with gpg key 14 | public void gpg_export_file (string path) { 15 | if (isfile (path)) { 16 | return; 17 | } 18 | string data = getoutput ("gpg --armor --export '%s'".printf (get_value ("gpg:repicent"))); 19 | writefile (path, data); 20 | } 21 | 22 | //DOC: `bool verify_file (string path):` 23 | //DOC: verify a file with gpg signature 24 | public bool verify_file (string path) { 25 | if (get_bool ("ignore-gpg")) { 26 | return true; 27 | } 28 | if (!isfile (path)) { 29 | return false; 30 | } 31 | string gpgdir = get_storage()+"/gpg/"; 32 | foreach(string file in listdir(gpgdir)) { 33 | if(!endswith(file,".gpg")){ 34 | continue; 35 | } 36 | string[] args = {"gpg","--homedir", gpgdir, "--trust-model", "always", "--no-default-keyring", "--keyring", gpgdir+"%s".printf(file), "--quiet" ,"--verify", path+".gpg"}; 37 | print_array(args); 38 | int status = run_args (args); 39 | if(status == 0){ 40 | return true; 41 | } 42 | 43 | } 44 | return false; 45 | } 46 | 47 | public void add_gpg_key(string path, string name){ 48 | if(endswith(path,".asc")){ 49 | string target = get_storage()+"/gpg/"+sbasename(path); 50 | copy_file(path, target); 51 | run_args({"gpg", "--dearmor", target}); 52 | move_file(target+".gpg",get_storage()+"/gpg/"+name+".gpg"); 53 | remove_file(target); 54 | } 55 | } 56 | 57 | //DOC: `void sign_elf (string path):` 58 | //DOC: create gpg signature and insert into elf binary 59 | public void sign_elf (string path) { 60 | if (!iself (path)) { 61 | return; 62 | } 63 | sign_file (path); 64 | run_args ( {"objcopy", "--add-section", ".gpg=" + path + ".gpg", path}); 65 | remove_file (path + ".gpg"); 66 | } 67 | 68 | //DOC: `bool verify_elf (string path):` 69 | //DOC: dump gpg signature from file and verify elf file 70 | public bool verify_elf (string path) { 71 | if (!iself (path)) { 72 | return false; 73 | } 74 | int status = 0; 75 | status += run_args ( {"objcopy", "-R", ".gpg", path, "/tmp/ymp-elf"}); 76 | status += run_args ( {"objcopy", "--dump-section", ".gpg=/tmp/ymp-elf.gpg", "path"}); 77 | if (!verify_file ("/tmp/ymp-elf")) { 78 | status += 1; 79 | } 80 | remove_file ("/tmp/ymp-elf.gpg"); 81 | remove_file ("/tmp/ymp-elf"); 82 | return status == 0; 83 | } 84 | -------------------------------------------------------------------------------- /src/ymp-work-schema.drawio: -------------------------------------------------------------------------------- 1 | 7V1Lk5s4EP41Po5LIInHMTOTZGu3tiq1c9jNEYNss8HgAM7Y++tXAskGSTPGmJedeA6BBhq79fWn7tYjM/i02X9Ove36zyQg0cwEwX4Gn2emaVg2pP8wyaGUOK5bClZpGPCbToKX8D/ChYBLd2FAstqNeZJEebitC/0kjomf12Remiav9duWSVR/69ZbEUXw4nuRKv07DPI1/xUYnOS/kXC1Fm82AL+y8cTNXJCtvSB5rYjgxxl8SpMkL482+ycSMeMJu5TPfXrj6vGLpSTOmzzw+Ff6YKbrOHtcPvzx7x/x7/khfuBafnjRjv/gmWlFVN9jEP6ghyt2KEQLWbBM6KvpL8sP3FzW910iLjxkRWN+oDcYcLsvH+PXWytCXSnCXSmyulJkd6XI6UqR25EiitKOFBldKTK7UvQWsg+b7YMfhUIfdctSZf01P41YoQ4qqzGMWbO2mSa7OCCMuQC9/LoOc/Ky9Xx29ZV2NFS2zjcRPTNYm4RR9JRESVo8Cy1kW47N26oiXxYfKs/yNPlGKleggSBGx+9R5VRBkCTNyb4i4hz7mSQbkqcHegu/6nK6F/0dP309dR6G6BHWlY7D4jKP91ero+ITpdMDzuoXMLypYfgOjR14xFn6OqNavkMWy16MagLVqpalsSoCfZkVvt9xDtkDDaaoff9/O51ksiWpl4dJnA1BgZdp6Iswl45PfK0PLxyMMOjGh6kz1p0Yjk2N+Dw1kjj4wLIIeraIEv9b3Y51o5N9mP/DjueYn33l97Hj533ltueDOInpDykfAq4hBF+rV08PFme1J7+QNKS2IOlRGHwKmRGe3220LNmlPjmfFuReuiL5+c6FBLUkSoVApYmxpoWFLCUR9b0f9dRL1+z8DV+SsHD3vcT2HGHYkJBT/m7+VDVVkhQZdl2R4UqKSsMoigoUHn92e2Bab3Yu08u4jrRGI156/5E/ixQ4pulx2gUHdsl2S2Lp2S6w3QXoiO0MCYvHMkCV7QyNL0C7L7qzL6I7P/KyLPTfI7z2/GI15Bd4n/yCcF0Rkru4nvnFUZAQxlnusQdvztGgIzmaoTqaDhNmX27mKsZNySahoLsD26KRbSva9v165WIXRsEQcfM4jWDZIzeCWjQOqQ3392BbF41s2wblmss6aZGViDzkay1DOZeV1DKSuY3PJCXtIwLYMCJwJhURQCmnhbBlRADlCpczbERg6OpZk8Hd+LBzpwU725xjsw4Y7M4tsyPwQTws+NAv8L0HPhH1TAV9joo+qz365KyKZkfDou+yMmAT9HWNpPMIMaaFEEsOWdsmyoakCA+MDV0lrssoF7O/mTJUWX500a9VfDqqyEMpetGkdxDowl/cW/yry563SRbmCdfe3vTUxC/8Wd1AJiZOgHQmd8wF7MzkUuUHYtXkA48Pqyk1NeE3Ni3q/syNRGQznrl1M66a9DYZpbq8RQjUcjQK17qu3kIg4e/nR5omFgNJ1KlMNGgceztvEMJAPZyAXwWP33de6sV5GN8jA2DdOMywDNA21R6CAdp7srDheU82p+XJUoiJW3sycOe2oQfbUM7c+RDfdYn03IbVbuQBzAEwz/Ql2nkNgZeti+9kXNfbNM6nrGlhdOzehiLGO1Ru27Ibsre/MJLrokZtbjo9KDV2i351WLMX9NuN4e+Ai8KoXqHflJ4nBn0FSW0r7AjZc8cCx0+dqSFy581KCxe7glQLEQl1v66gptFjuwJ26sUw1gLjuUPTtGPi3mC6Emgbe4PtzqF7+jiW3C+wth3CH0x7AH8QpDEdf3Dh9bM9O/IF5058wWrrCy6e22gw/MtTDvAQ+FerTofNls+TufkcXx6/HL+oCtWqSkC2lGFI7N9DGVu2+Ph1VTh0VeWSjLg9NzeuqgjETYScoVkHCAYtyVlRJMf/PZdUYNu5CTdZr58IehBipbRTrgbqvTNqPe/6jN6B573ABqPL/XFWQ2RVcXUuYxuC56aFVLmghuSose0sGEVR31hsUDGY/hpDLI32aFfdOBo49LfqBulSz19bbFyiqPfVw+XStcDLvdvaJYF6RS7xPqE/11sUNzCf8nZ5UhqguOxF4SpmfQZ1MVZGeGSuFfpe9IFf2IRBwB5+5GksfQ1+nOFnyaHjJCaKL3NhwzVizZ1aWXalSzZ005TkULE7n260bU4ULgpg/WrKStlR4megNqU9aEuqifp0mfdID0+nkIrtfMU2yJrWGlsAHK9Yo9N4CxYAsN3Vqh4slZiRrh6k2y7E6A9nannC5w13dTGIc4KYRiqKQ6baLMQIMLF15nctG3odFYdk80PnOLZ2rgHgOwH4dfYfN41vmmzV0/j+0i1Be2fTLTSxFdhy3bHtxHIsDR4oJYWe0y3UdtHBtMuVRuOF/dNaUHU/uBq8pDQHwK5hy3TtZmxXTAdDVcJjD59bJKPf94a+4N3RUXbyxcvp1biQmOC6MdMbxbkCz7blKiXEstAcuKe/YUHfduLXwDV6Fe0WaoP2MnoT29FeB+SmaxAnBuTRCfvSYX8oFTGg4Uiu0MOwvzB2xTFWYaL4xv2lHNq95bQJR18JH1ZLRFG48FJ/HV69FcxNtIBml5KBW0At7dAW8Hfptbsc3YL5oWYXpIHNr1Y8Vsz+TNku+ynaoGnZqb820FU9plrdvMNxpc52pb1Y0Vtbtx8222w97iDX0LXocbcDN6X5S6PvB44nsettN9vUCn6bSFJiSB2Asm1s06TElOcIy+u9WifU9PT0P46Ut5/+3xb48X8= -------------------------------------------------------------------------------- /src/operations/package-manager/info.vala: -------------------------------------------------------------------------------- 1 | private static int info_main(string[] args) { 2 | foreach(string arg in args) { 3 | if (get_bool("deps")) { 4 | bool ri = get_bool("reinstall"); 5 | set_bool("reinstall", true); 6 | string[] required = resolve_dependencies({arg}); 7 | print(join(" ", required)); 8 | set_bool("reinstall", ri); 9 | } else if (get_bool("revdeps")) { 10 | bool ri = get_bool("reinstall"); 11 | set_bool("reinstall", true); 12 | string[] required = resolve_reverse_dependencies({arg}); 13 | print(join(" ", required)); 14 | set_bool("reinstall", ri); 15 | } else { 16 | package p = get_package(arg); 17 | if (p == null) { 18 | continue; 19 | } 20 | if (get_value("get") != "") { 21 | print("%s: %s".printf(get_value("get"), p.get(get_value("get")))); 22 | } else { 23 | if (p.is_source) { 24 | print("source:"); 25 | } else { 26 | print("package:"); 27 | } 28 | print(" name: %s".printf(p.name)); 29 | print(" version: %s".printf(p.version)); 30 | print(" release: %d".printf(p.release)); 31 | if(p.dependencies.length > 0){ 32 | print(" depends: "); 33 | foreach(string dep in p.dependencies){ 34 | print(" - %s".printf(dep)); 35 | } 36 | } 37 | if(p.gets("use-flags").length > 0){ 38 | print(" use_flags:"); 39 | foreach(string flag in p.gets("use-flags")){ 40 | print(" - %s".printf(flag)); 41 | 42 | } 43 | } 44 | if(p.gets("group").length > 0){ 45 | print(" groups:"); 46 | foreach(string group in p.gets("group")){ 47 | print(" - %s".printf(group)); 48 | 49 | } 50 | } 51 | print(" is_installed: %s".printf(p.is_installed().to_string())); 52 | print(" remote_url: %s".printf(p.get_uri())); 53 | 54 | } 55 | } 56 | } 57 | return 0; 58 | } 59 | 60 | static void info_init() { 61 | operation op = new operation(); 62 | op.help = new helpmsg(); 63 | op.callback.connect(info_main); 64 | op.names = { 65 | _("info"), 66 | "info", 67 | "i" 68 | }; 69 | op.help.name = _("info"); 70 | op.help.minargs = 1; 71 | op.help.description = _("Get informations from package manager databases."); 72 | op.help.add_parameter("--deps", _("list required packages")); 73 | op.help.add_parameter("--revdeps", _("list packages required by package")); 74 | add_operation(op); 75 | } 76 | -------------------------------------------------------------------------------- /test/test.vala: -------------------------------------------------------------------------------- 1 | 2 | string tmp; 3 | void main (string[] args) { 4 | // init ymp 5 | ymp_init (args); 6 | print ("Ymp test"); 7 | 8 | set_destdir ("../test/rootfs"); 9 | add_process ("init", {"hello", "world"}); 10 | ymp_run (); 11 | 12 | //yesno test 13 | print ("Interface test"); 14 | yesno ("Yes or no"); 15 | 16 | // archive test 17 | print ("Archive test"); 18 | var tar = new archive (); 19 | tar.load ("../test/data/main.tar.gz"); 20 | tar.list_files (); 21 | tar.set_target ("./test/"); 22 | tar.extract ("main.c"); 23 | tar.readfile ("main.c"); 24 | tar.extract_all (); 25 | 26 | // file test 27 | print ("File test"); 28 | readfile ("./test/main.c"); 29 | string curdir = GLib.Environment.get_current_dir (); 30 | cd (".."); 31 | 32 | // directory test 33 | create_dir ("test/dir"); 34 | remove_dir ("test/dir"); 35 | cd (curdir); 36 | find ("./test"); 37 | create_dir ("test/dir"); 38 | writefile ("test/dir/test.txt", "ymp"); 39 | remove_all ("test"); 40 | 41 | // logger test 42 | print ("Logging test"); 43 | debug ("debug test"); 44 | 45 | // command test 46 | print ("Command test"); 47 | tmp = getoutput ("../test/hello.py"); 48 | run_silent ("non-command -non-parameter"); 49 | run ("false"); 50 | 51 | // package test 52 | print ("Package test"); 53 | var pkg1 = new package (); 54 | pkg1.load ("../test/data/metadata-binary.yaml"); 55 | 56 | // string test 57 | tmp = join (", ", {"aaa", "bbb"}); 58 | sbasename ("test/dir"); 59 | sdirname ("test/dir"); 60 | 61 | // index test 62 | print ("Repository test"); 63 | get_repos (); 64 | 65 | //array test 66 | print ("Array test"); 67 | var a = new array (); 68 | a.add ("aa"); 69 | a.add ("bb"); 70 | a.add ("cc"); 71 | a.reverse (); 72 | a.pop (0); 73 | a.remove ("aa"); 74 | a.has ("bb"); 75 | a.insert ("dd", 0); 76 | a.set ({"yumusak", "ge"}); 77 | a.get (); 78 | 79 | // Binary test 80 | print ("Binary test"); 81 | iself ("ymp-test"); 82 | is64bit ("libymp.so"); 83 | print (calculate_sha1sum ("ymp-cli")); 84 | 85 | // ttysize test 86 | print ("C functions test"); 87 | tty_size_init (); 88 | get_tty_width (); 89 | get_tty_height (); 90 | 91 | // which test 92 | which ("bash"); 93 | 94 | // users test 95 | get_uid_by_user ("root"); 96 | switch_user ("root"); 97 | 98 | // value test 99 | print ("value test"); 100 | get_value ("interactive"); 101 | set_bool ("shellmode", true); 102 | error_add ("Error test"); 103 | has_error (); 104 | 105 | // brainfuck test 106 | print ("Brainfuck test"); 107 | string bfcode = readfile ("../test/data/hello.bf"); 108 | brainfuck (bfcode, 102400); 109 | print ("\ndone"); 110 | 111 | } 112 | -------------------------------------------------------------------------------- /scripts/ympstrap: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | umask 022 4 | if [[ $UID -ne 0 ]] ; then 5 | echo "You must be root!" 6 | exit 1 7 | fi 8 | repo="$REPO" 9 | if [[ "$repo" == "" ]] ; then 10 | repo='https://gitlab.com/turkmen-linux/packages/binary-repo/-/raw/master/$uri' 11 | fi 12 | export PATH="/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" 13 | output="$1" 14 | if [[ "$output" == "" ]] ; then 15 | echo "Usage: ympstrap (extra packages)" 16 | exit 1 17 | fi 18 | shift 19 | output=$(realpath $output) 20 | basepkgs=(busybox base-files glibc) 21 | ympdep=(acl attr bzip2 curl glib libarchive libcap-ng libffi libidn2 libnghttp2 22 | libpcre2 libpsl libssh libunistring libxml2 lz4 lzo ncurses openssl openssl-1.1 readline 23 | util-linux xz-utils ymp zlib bash file libseccomp gnupg 24 | ) 25 | arch=$(uname -m) 26 | function get_uri(){ 27 | cat "$output"/var/lib/ymp/index/main | grep "uri: .*/$1_.*$arch.ymp" | cut -f2 -d":" | tr -d " " | head -n 1 28 | } 29 | function fetch_pkg(){ 30 | for arg in $@ ; do 31 | uri=$(get_uri $arg) 32 | pkg="$output"/var/lib/ymp/packages/"$(basename $uri)" 33 | mkdir -p "$output"/var/lib/ymp/sysconf/"$arg" 34 | echo "Download: $arg" >/dev/stderr 35 | wget -c ${repo/\$uri/$uri} -O "$pkg" -q 36 | pkginst "$pkg" 37 | chmod 755 -R "$output" 38 | done 39 | } 40 | 41 | function pkginst(){ 42 | mkdir "$output"/tmp/ -p 43 | cd "$output"/tmp/ 44 | unzip "$1" >/dev/null 45 | cd "$output" 46 | tar -xf "$output"/tmp/data.tar.* 47 | rm -rf "$output"/tmp 48 | } 49 | # Stage 1 download repo 50 | mkdir "$output"/var/lib/ymp/{index,packages,sources.list.d,gpg}/ -p 51 | mkdir "$output"/tmp/ -p 52 | chmod 1777 "$output"/tmp/ 53 | echo "$repo" > "$output"/var/lib/ymp/sources.list.d/main 54 | wget -O "$output"/tmp/main.asc "${repo/\$uri/ymp-index.yaml.asc}" 55 | gpg --dearmor "$output"/tmp/main.asc 56 | mv "$output"/tmp/main.asc.gpg "$output"/var/lib/ymp/gpg/main.gpg 57 | rm "$output"/tmp/main.asc 58 | wget -O - ${repo/\$uri/ymp-index.yaml} | grep "uri: " > "$output"/var/lib/ymp/index/main 59 | # Stage 2 install base 60 | fetch_pkg ${basepkgs[@]} 61 | mkdir -p "$output"/var/lib/ymp/sysconf/{glibc,busybox,base-files} 62 | chroot "$output" /etc/sysconf.d/busybox 63 | chroot "$output" /etc/sysconf.d/glibc 64 | chroot "$output" /etc/sysconf.d/base-files 65 | # Stage 3 install ymp 66 | fetch_pkg ${ympdep[@]} 67 | chroot "$output" /sbin/ldconfig 68 | # Stage 4 bind rootfs 69 | mkdir "$output"/{dev,sys,proc,run} -p 70 | mount -t proc proc "$output"/proc 71 | mount -t devtmpfs devtmpfs "$output"/dev 72 | mount -t sysfs sysfs "$output"/sys 73 | cat /etc/resolv.conf > "$output"/etc/resolv.conf 74 | # Stage 5 install ymp from ymp 75 | chroot "$output" ymp repo --update --allow-oem --ignore-gpg 76 | chroot "$output" ymp it ${basepkgs[@]} ${ympdep[@]} $@ --ignore-quarantine --no-emerge --allow-oem 77 | chroot "$output" ymp clean --no-emerge --allow-oem 78 | # Stage 6 unbind 79 | while umount "$output"/{dev,sys,proc} ; do : ; done 80 | -------------------------------------------------------------------------------- /src/ccode/value.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #ifndef _POSIX_C_SOURCE 8 | #define _POSIX_C_SOURCE 9 | #endif 10 | 11 | #ifdef __STRICT_ANSI__ 12 | #define strdup(A) strcpy(calloc(strlen(A) + 1, sizeof(char)), A); 13 | int setenv(const char *name, const char *value, int overwrite); 14 | #endif 15 | 16 | typedef struct _variable { 17 | char* name; 18 | char* value; 19 | bool read_only; 20 | } variable; 21 | 22 | static variable* vars; 23 | static size_t var_count = 0; 24 | 25 | static void set_value_fn(char* name, char* value, bool read_only){ 26 | if(name == NULL || value == NULL){ 27 | return; 28 | } 29 | size_t i=0; 30 | for(i=0;i 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | void brainfuck(char * code, unsigned int size) { 9 | unsigned int ptr = 0; 10 | unsigned int i = 0; 11 | int tmp = 0; 12 | int values[size]; 13 | for(i=0;i < size;i++){ 14 | values[i] = 0; 15 | } 16 | for (i = 0; i < strlen(code); i++) { 17 | if(ptr >=size){ 18 | ferror_add("Failed to run brainfuck code: %s\n","Out of memory"); 19 | return; 20 | } 21 | if (code[i] == '>') { 22 | ptr++; 23 | } else if (code[i] == '<') { 24 | ptr--; 25 | } else if (code[i] == '+') { 26 | values[ptr]++; 27 | } else if (code[i] == '-') { 28 | values[ptr]--; 29 | 30 | }else if (code[i] == '[') { 31 | if (values[ptr] == 0) { 32 | i++; 33 | while (code[i] != ']' || tmp != 0) { 34 | if (code[i] == '[') { 35 | tmp++; 36 | } else if (code[i] == ']') { 37 | tmp--; 38 | } 39 | i++; 40 | } 41 | } 42 | 43 | } else if (code[i] == ']') { 44 | if (values[ptr] != 0) { 45 | i--; 46 | while (code[i] != '[' || tmp > 0) { 47 | if (code[i] == ']') { 48 | tmp++; 49 | } else if (code[i] == '[') { 50 | tmp--; 51 | } 52 | i--; 53 | } 54 | i--; 55 | } 56 | } else if (code[i] == '.') { 57 | putc(values[ptr],stdout); 58 | } else if (code[i] == ',') { 59 | values[ptr] = getc(stdin); 60 | } 61 | } 62 | } 63 | #ifndef popen 64 | FILE *popen(const char *command, const char *type); 65 | int pclose(FILE *stream); 66 | #endif 67 | 68 | void bf_compile(char* code){ 69 | FILE *output; 70 | output = popen ("gcc -x c - $CFLAGS -o /tmp/bf.elf", "w"); 71 | fputs("#include \n",output); 72 | fputs("#include \n",output); 73 | fputs("int ptr = 0;",output); 74 | fputs("unsigned char cell[1024*1024];",output); 75 | fputs("void main(){",output); 76 | int i=0; 77 | for(i=0;code[i];i++){ 78 | switch (code[i]) { 79 | case '<': 80 | fputs("ptr--;",output); 81 | break; 82 | case '>': 83 | fputs("ptr++;",output); 84 | break; 85 | case '+': 86 | fputs("cell[ptr]++;",output); 87 | break; 88 | case '-': 89 | fputs("cell[ptr]--;",output); 90 | break; 91 | case '[': 92 | fputs("while(cell[ptr]){",output); 93 | break; 94 | case ']': 95 | fputs("}",output); 96 | break; 97 | case '.': 98 | fputs("putc(cell[ptr],stdout);",output); 99 | break; 100 | case ',': 101 | fputs("cell[ptr] = getchar();",output); 102 | break; 103 | } 104 | } 105 | fputs("}",output); 106 | pclose(output); 107 | } 108 | 109 | -------------------------------------------------------------------------------- /doc/ympshell.rst: -------------------------------------------------------------------------------- 1 | Ymp Shell 2 | ========= 3 | You can create new ymp shell with **ymp shell** command or **ympsh** command. You can run ymp operations into shell. 4 | 5 | .. code-block:: shell 6 | 7 | ymp shell 8 | -> Ymp >> install git 9 | 10 | Commends 11 | ^^^^^^^^ 12 | You can use **#** symbol or **:** operdation (dummy) 13 | 14 | .. code-block:: shell 15 | 16 | # hello world 17 | : Hello world 18 | 19 | Escape & exclusive characters 20 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 21 | 22 | **$** character used for variables. 23 | 24 | .. code-block:: shell 25 | 26 | set num 13 27 | echo $num 28 | # It is not equal to test13 29 | echo test$num 30 | # It is not equal 13test 31 | echo $numtest 32 | 33 | **\\** character ignore next characters functions 34 | 35 | .. code-block:: shell 36 | 37 | set msg Hello\ World 38 | echo $msg 39 | 40 | **"** and **'** characters define string 41 | 42 | .. code-block:: shell 43 | 44 | set msg "Hello World" 45 | echo $msg 46 | 47 | **`** character execute command and replace output with yourself (for preprocesing) 48 | 49 | .. code-block:: shell 50 | 51 | set dist `uname -a` 52 | echo $dist 53 | 54 | Expressions 55 | ^^^^^^^^^^^ 56 | **$(xxxx)** expression execute command and replace output with yourself. 57 | 58 | .. code-block:: shell 59 | 60 | # get current uid 61 | set uid "$(id -u)" 62 | print $uid 63 | 64 | **--** stop expressioning 65 | 66 | .. code-block:: shell 67 | 68 | # print stuff 69 | print -- $hello $world 70 | 71 | **${xxx}** expression used for variables. 72 | 73 | .. code-block:: shell 74 | 75 | # expr command from shell 76 | set num 2 77 | print "$(expr ${num} + 2)" 78 | 79 | Conditions 80 | ^^^^^^^^^^ 81 | **If** segment used for conditions. If segment must starts with **if** and must ends with **endif** 82 | 83 | .. code-block:: shell 84 | 85 | read var 86 | if eq 12 $var 87 | echo equal to 12 88 | endif 89 | 90 | The keyword **and** compares left and right. Return true if both return true. 91 | 92 | .. code-block:: shell 93 | 94 | if eq 1 1 and eq 2 2 95 | echo equal 96 | endif 97 | 98 | The keyword **or** compares left and right. Return true if anyone returns true. 99 | 100 | .. code-block:: shell 101 | 102 | if eq 1 1 or eq 2 0 103 | echo equal 104 | endif 105 | 106 | The keyword **not** takes the opposite 107 | 108 | .. code-block:: shell 109 | 110 | if not eq 2 0 111 | echo not equal 112 | endif 113 | 114 | 115 | Labels and goto 116 | ^^^^^^^^^^^^^^^ 117 | You can define label and use **goto** word like this 118 | 119 | .. code-block:: shell 120 | 121 | label test 122 | read var 123 | if eq $var 0 124 | exit 125 | endif 126 | echo $var 127 | goto test 128 | 129 | This program can simulate while loop 130 | 131 | ret keyword 132 | ^^^^^^^^^^^^ 133 | If you use **goto** current code point saved. If you use **ret** saved point restored. 134 | 135 | .. code-block:: shell 136 | 137 | if eq 0 1 138 | label hello 139 | echo hello 140 | ret 141 | endif 142 | if eq 0 1 143 | label word 144 | echo world 145 | ret 146 | endif 147 | goto hello 148 | goto world 149 | 150 | This program can simulate functions. 151 | 152 | -------------------------------------------------------------------------------- /src/util/interface.vala: -------------------------------------------------------------------------------- 1 | //DOC: ## Interface functions 2 | //DOC: User interaction functions 3 | //DOC: Example usege: 4 | //DOC: ```vala 5 | //DOC: if (yesno ("Do you want to continue?")) { 6 | //DOC: ... 7 | //DOC: } else { 8 | //DOC: stderr.printf ("Operation canceled."); 9 | //DOC: } 10 | //DOC: ``` 11 | 12 | private bool nostdin_enabled = false; 13 | 14 | //DOC: `bool yesno (string message):` 15 | //DOC: Create a yes/no question. 16 | public bool yesno (string message) { 17 | if (!get_bool ("ask")) { 18 | return true; 19 | } 20 | if (nostdin_enabled) { 21 | return false; 22 | } 23 | #if no_libreadline 24 | print_fn (_ ("%s [y/n]").printf (message), false, true); 25 | var response = stdin.read_line (); 26 | #else 27 | var response = Readline.readline (_ ("%s [y/n]").printf (message)); 28 | #endif 29 | if (response == null || response == "") { 30 | return false; 31 | } 32 | return (response[0] == 'y' || response[0] == 'Y' \ 33 | || response[0] == _("Yy")[0] || response[0] == _("Yy")[1]); 34 | } 35 | 36 | //DOC: `void print_array (string[] array):` 37 | //DOC: print string array to fit terminal size 38 | public void print_array (string[] array) { 39 | int max = get_tty_width (); 40 | int cur = 0; 41 | foreach (string item in array) { 42 | if (cur + item.length + 1 > max) { 43 | cur = 0; 44 | print_fn ("\n", false, false); 45 | } 46 | print_fn (item + " ", false, false); 47 | cur += item.length + 1; 48 | } 49 | print_fn ("\n", false, false); 50 | } 51 | 52 | //DOC: `void shitcat (string data):` 53 | //DOC: print data with shitty random colors. 54 | public void shitcat (string data) { 55 | int cur = 0; 56 | while (cur < data.length) { 57 | print_fn (colorize (data[cur].to_string (), 31 + ( (int)GLib.Random.next_int () % 7)), false, false); 58 | cur++; 59 | } 60 | } 61 | 62 | //DOC: `void print_with_amogus (string data):` 63 | //DOC: print message with cow dialog 64 | public void print_with_amogus (string data) { 65 | int max = 0; 66 | foreach (string line in data.split ("\n")) { 67 | if (line.length > max) { 68 | max = line.length; 69 | } 70 | } 71 | max += 2; 72 | if (max % 2 == 1) { 73 | max += 1; 74 | } 75 | print_fn (" + ", false, false); 76 | for (int i=0;i < max;i++) { 77 | print_fn ("-", false, false); 78 | } 79 | print (" + "); 80 | foreach (string line in data.split ("\n")) { 81 | print_fn ("|", false, false); 82 | int space = max - line.length; 83 | for (int i=0;i < (space / 2);i++) { 84 | print_fn (" ", false, false); 85 | } 86 | print_fn (line, false, false); 87 | for (int i=0;i < (space / 2);i++) { 88 | print_fn (" ", false, false); 89 | } 90 | if (space % 2 == 1) { 91 | print_fn (" ", false, false); 92 | } 93 | print ("|"); 94 | } 95 | print_fn (" + ", false, false); 96 | for (int i=0;i < max;i++) { 97 | print_fn ("-", false, false); 98 | } 99 | print(""); 100 | foreach(string line in ssplit(get_amogus(),"\n")){ 101 | for(int i=0;i < (max / 3);i++){ 102 | print_fn(" ",false,false); 103 | } 104 | print(line); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /doc/coder-runner.rst: -------------------------------------------------------------------------------- 1 | Code-Runner 2 | =========== 3 | Creating a code-runner config 4 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 5 | 6 | To create a code-runner config, you can use the following command: 7 | 8 | .. code-block:: shell 9 | 10 | ymp code-runner --create build.yaml 11 | 12 | This command generates a code-runner config file named build.yaml. 13 | 14 | Execute code-runner 15 | ^^^^^^^^^^^^^^^^^^^ 16 | To execute code-runner with a specific configuration file, use the following command: 17 | 18 | .. code-block:: shell 19 | 20 | ymp code-runner build.yaml 21 | 22 | Replace build.yaml with the path to your code-runner configuration file. 23 | 24 | code-runner configuration file 25 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 26 | Below is an example of a code-runner configuration file (build.yaml): 27 | 28 | .. code-block:: yaml 29 | 30 | name: example 31 | on-fail: fail-job 32 | 33 | steps: 34 | - main 35 | 36 | jobs: 37 | main: 38 | uses: local 39 | directory: /tmp/ymp-build 40 | image: undefined 41 | run: 42 | - echo hello world 43 | 44 | fail-job: 45 | uses: local 46 | image: undefined 47 | directory: /tmp/ymp-build 48 | run: | 49 | echo "Failed" 50 | 51 | 52 | Configuration Sections: 53 | 54 | * **name:** Specifies the name of the code-runner configuration. 55 | 56 | * **on-fail:** Specifies the job that should be executed if any of the previous jobs fail. 57 | 58 | * **steps:** Defines the order in which the jobs are executed. In the provided example, there is a single step named "main." 59 | 60 | * **jobs:** Contains job definitions. Each job has a name ("main" and "fail-job" in this example), uses a certain source (in this case, "local"), specifies a working directory, defines an image, and provides a script to run. 61 | 62 | Job definition: 63 | 64 | * **uses**: Specifies the source for the job. It can be a local source, a remote repository, or any other source. In the example, "some-source" and "another-source" are placeholders for the source of the job. 65 | 66 | * **directory**: Sets the working directory for the job. Commands within the job will be executed relative to this directory. For example, "/path/to/working/directory" and "/path/to/another/directory" are placeholders for the working directories. 67 | 68 | * **image**: Specifies the Docker image to be used for the job. This is optional, and if not provided, the job may run in the host environment. The Docker image can include necessary dependencies for the commands in the job. 69 | 70 | * **run**: Contains the actual commands to be executed in the job. It can be a single command or a list of commands. Commands can be specified as a list (using -) or as a multiline string (using |). In the example, "command1," "command2," and "echo 'Running job2'" are placeholders for the actual commands to be executed. 71 | 72 | 73 | 74 | Create plugins 75 | ^^^^^^^^^^^^^^ 76 | Create new file in ymp source code. under **/lib/code-runner/** directory. 77 | 78 | **example** file content: 79 | 80 | .. code-block:: shell 81 | 82 | #!/bin/bash 83 | set -e 84 | if [[ "$ACTION" == "init" ]] ; then 85 | echo "Init action" 86 | # Environs: 87 | # - DIRECTORY 88 | # - IMAGE 89 | elif [[ "$ACTION" == "run" ]] ; then 90 | echo "Run action" 91 | # Environs: 92 | # - COMMAND 93 | elif [[ "$ACTION" == "clean" ]] ; then 94 | echo "Clean action" 95 | fi 96 | 97 | 98 | **Note:** You may need to save **DIRECTORY** and **IMAGE** environmental variables in init action. 99 | 100 | Then set executable your plugin. 101 | 102 | 103 | -------------------------------------------------------------------------------- /src/ccode/logger.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* functions from vala source */ 9 | bool get_bool(char* val); 10 | void colorize_init(); 11 | 12 | /* string add function*/ 13 | char* str_add(char* s1, char* s2); 14 | 15 | /* string builder */ 16 | char* build_string(char* format, ...); 17 | 18 | 19 | extern char* colorize(char* message, int color); 20 | extern char* gettext(char* message); 21 | 22 | #define yellow 33 23 | #define green 32 24 | #define _(A) gettext(A) 25 | 26 | #include 27 | #include 28 | 29 | /* define function headers */ 30 | void cprint(char* msg); 31 | void cprint_stderr(char* msg); 32 | void cprint_dummy(char* msg); 33 | 34 | 35 | /* function pointer type definitions */ 36 | typedef void (*fn_logger)(char*); 37 | 38 | /* logger function pointer */ 39 | fn_logger print_ptr = cprint; 40 | fn_logger print_stderr_ptr = cprint_stderr; 41 | fn_logger warning_ptr = warning_fn; 42 | fn_logger info_ptr = cprint_dummy; 43 | #ifdef DEBUG 44 | fn_logger debug_ptr = cprint_dummy; 45 | #endif 46 | 47 | /* print functions area */ 48 | void print_fn(char* message, int new_line, int err){ 49 | if(new_line){ 50 | message = str_add(message, "\n"); 51 | } 52 | write(err+1, message, strlen(message)); 53 | } 54 | 55 | void warning_fn (char* message) { 56 | print_stderr (build_string("%s: %s",colorize (_ ("WARNING"), yellow), message)); 57 | } 58 | 59 | void info_fn (char* message) { 60 | print_stderr (build_string("%s: %s",colorize (_ ("INFO"), yellow), message)); 61 | } 62 | 63 | void cprint(char* message){ 64 | message = str_add(message, "\n"); 65 | write(1, message, strlen(message)); 66 | } 67 | 68 | 69 | void set_terminal_title (char* msg) { 70 | #if NOCOLOR 71 | return; 72 | #else 73 | if (!get_bool ("no-color")) { 74 | print_fn (build_string("%s%s%s","\x1b]2;", msg, "\x07"), false, false); 75 | } 76 | #endif 77 | } 78 | 79 | 80 | #ifdef DEBUG 81 | static long last_debug_time = -1; 82 | void debug_fn(char *message) { 83 | if (last_debug_time == -1) { 84 | last_debug_time = time(NULL); 85 | } 86 | 87 | time_t current_time = time(NULL); 88 | int elapsed_time = (int)(current_time - last_debug_time); 89 | 90 | print_stderr (build_string( "[%s:%d]: %s\n", "DEBUG", elapsed_time, message)); 91 | 92 | last_debug_time = current_time; 93 | } 94 | #endif 95 | void cprint_stderr(char* message){ 96 | message = str_add(message, "\n"); 97 | write(2, message, strlen(message)); 98 | } 99 | 100 | void cprint_dummy(char* message){ 101 | (void)message; 102 | } 103 | 104 | 105 | /* logger functions */ 106 | void print(char* msg){ 107 | if(print_ptr){ 108 | print_ptr(msg); 109 | } 110 | } 111 | 112 | void print_stderr(char* msg){ 113 | if(print_stderr_ptr){ 114 | print_stderr_ptr(msg); 115 | } 116 | } 117 | 118 | void warning(char* msg){ 119 | if(warning_ptr){ 120 | warning_ptr(msg); 121 | } 122 | } 123 | 124 | void info(char* msg){ 125 | if(info_ptr){ 126 | info_ptr(msg); 127 | } 128 | } 129 | #ifdef DEBUG 130 | void debug(char* msg){ 131 | if(debug_ptr){ 132 | debug_ptr(msg); 133 | } 134 | } 135 | #endif 136 | 137 | /* init function */ 138 | void logger_init(){ 139 | if(get_bool("quiet")){ 140 | print_ptr = cprint_dummy; 141 | print_stderr_ptr = cprint_dummy; 142 | } 143 | if(get_bool("ignore-warning")){ 144 | warning_ptr = cprint_stderr; 145 | }else if(get_bool("warning-as-error")){ 146 | warning_ptr = error_add; 147 | } 148 | if(get_bool("verbose")){ 149 | info_ptr = info_fn; 150 | } 151 | #ifdef DEBUG 152 | if(get_bool("debug")){ 153 | debug_ptr = debug_fn; 154 | } 155 | #endif 156 | #ifndef NOCOLOR 157 | colorize_init(); 158 | #endif 159 | } 160 | -------------------------------------------------------------------------------- /src/data/code_runner.vala: -------------------------------------------------------------------------------- 1 | private class code_runner_job { 2 | public string name; 3 | public string uses; 4 | public string image; 5 | public string directory; 6 | public string[] commands; 7 | public string[] environs; 8 | } 9 | 10 | public class code_runner_plugin { 11 | public string name; 12 | public string ctx; 13 | public signal void init(string image, string directory); 14 | public signal int run(string command); 15 | public signal void clean(); 16 | } 17 | 18 | private code_runner_plugin[] plugins; 19 | public class code_runner { 20 | private yamlfile yaml; 21 | private array steps; 22 | private code_runner_job[] jobs; 23 | private string fail_job_name; 24 | public void load (string file){ 25 | if (steps == null) { 26 | steps = new array(); 27 | } 28 | if (jobs == null) { 29 | jobs = {}; 30 | } 31 | yaml = new yamlfile(); 32 | yaml.load (file); 33 | steps.adds(yaml.get_array (yaml.data, "steps")); 34 | fail_job_name = yaml.get_value(yaml.data, "on-fail"); 35 | foreach (string import in yaml.get_array (yaml.data, "import")){ 36 | load(import); 37 | } 38 | string jobs_area = yaml.get_area(yaml.data,"jobs"); 39 | foreach (string area_name in yaml.get_area_names (jobs_area)){ 40 | string area = yaml.get_area(jobs_area, area_name); 41 | var job = new code_runner_job (); 42 | job.name = area_name; 43 | job.uses = yaml.get_value(area,"uses"); 44 | job.image = yaml.get_value(area,"image"); 45 | job.directory = sdirname(file); 46 | job.environs = yaml.get_array(area,"environs"); 47 | job.commands = yaml.get_array(area,"run"); 48 | if (job.commands.length == 0) { 49 | job.commands = {yaml.get_value(area,"run")}; 50 | } 51 | if(job.directory == ""){ 52 | job.directory = pwd (); 53 | } 54 | jobs += job; 55 | } 56 | } 57 | public int run(){ 58 | foreach (code_runner_job job in jobs){ 59 | if(! (job.name in steps.get())){ 60 | continue; 61 | } 62 | int status = run_job(job); 63 | if(status != 0){ 64 | foreach (code_runner_job fjob in jobs){ 65 | if(fjob.name == fail_job_name){ 66 | run_job(fjob); 67 | } 68 | } 69 | return status; 70 | } 71 | } 72 | return 0; 73 | } 74 | private int run_job(code_runner_job job){ 75 | print(colorize("Run operation:",blue)+job.name); 76 | foreach(code_runner_plugin p in plugins) { 77 | if(p.name == job.uses){ 78 | save_env(); 79 | clear_env(); 80 | foreach(string env in job.environs){ 81 | string var = ssplit(env,"=")[0]; 82 | string val = env[var.length+1:]; 83 | setenv(var, val, 1); 84 | } 85 | print(colorize("Init plugin:",green)+p.name); 86 | p.init(job.image, job.directory); 87 | print(colorize("Run plugin:",green)+p.name); 88 | foreach(string cmd in job.commands){ 89 | int status = p.run(cmd); 90 | if(status != 0){ 91 | print_stderr(colorize("Failed:",red)+job.name); 92 | print(colorize("Clean plugin:",green)+p.name); 93 | p.clean(); 94 | return status; 95 | }else{ 96 | print_stderr(colorize("Finish:",blue)+job.name); 97 | } 98 | } 99 | print(colorize("Clean plugin:",green)+p.name); 100 | p.clean(); 101 | restore_env(); 102 | } 103 | } 104 | return 0; 105 | } 106 | } 107 | public void add_code_runner_plugin(code_runner_plugin plug){ 108 | if(plugins == null){ 109 | plugins = {}; 110 | } 111 | info(_("Register code-runner plugin: %s").printf(plug.name)); 112 | plugins += plug; 113 | } 114 | 115 | -------------------------------------------------------------------------------- /src/operations/package-manager/remove.vala: -------------------------------------------------------------------------------- 1 | private static int remove_main (string[] args) { 2 | file_cache_reset(); 3 | if (!is_root ()) { 4 | error_add (_ ("You must be root!")); 5 | error (1); 6 | } 7 | single_instance (); 8 | set_value_readonly ("OPERATION", "prerm"); 9 | sysconf_main (args); 10 | string[] pkgs = {}; 11 | if (get_bool ("ignore-dependency")) { 12 | pkgs = args; 13 | }else { 14 | pkgs = resolve_reverse_dependencies (args); 15 | } 16 | if (get_bool("unsafe")){ 17 | foreach (string name in get_unsafe_packages()){ 18 | pkgs += name; 19 | } 20 | } 21 | if ("ymp" in pkgs) { 22 | if (!get_bool ("ignore-safety")) { 23 | error_add (_ ("You cannot remove package manager! If you really want, must use --ignore-safety")); 24 | return 1; 25 | } 26 | } 27 | if (get_bool ("ask")) { 28 | print (_ ("The following additional packages will be removed:")); 29 | print (join (" ", pkgs)); 30 | if (!yesno (colorize (_ ("Do you want to continue?"), red))) { 31 | return 1; 32 | } 33 | }else { 34 | info (_ ("Resolve reverse dependency done: %s").printf (join (" ", pkgs))); 35 | } 36 | jobs j = new jobs(); 37 | foreach (string pkg in pkgs) { 38 | if (is_installed_package (pkg)) { 39 | package *p = get_installed_package (pkg); 40 | //remove_single (p); 41 | j.add((void*)remove_single, (void*)p); 42 | }else { 43 | warning (_ ("Package %s is not installed. Skip removing.").printf (pkg)); 44 | } 45 | } 46 | j.run(); 47 | set_value_readonly ("OPERATION", "postrm"); 48 | sysconf_main (args); 49 | return 0; 50 | } 51 | 52 | private static int remove_single (package *p) { 53 | print (colorize (_ ("Removing: %s"), yellow).printf (p->name)); 54 | if (!get_bool ("without-files")) { 55 | foreach (string file in p->list_links ()) { 56 | if (file.length > 3) { 57 | file=ssplit (file, " ")[0]; 58 | info (_ ("Removing: %s").printf (file)); 59 | remove_file (DESTDIR + "/" + file); 60 | } 61 | } 62 | foreach (string file in p->list_files ()) { 63 | if (file.length > 41) { 64 | file=file[41:]; 65 | info (_ ("Removing: %s").printf (file)); 66 | remove_file (DESTDIR + "/" + file); 67 | } 68 | } 69 | foreach (string file in p->list_links ()) { 70 | if (file.length > 3) { 71 | file=ssplit (file, " ")[0]; 72 | string dir = sdirname (file); 73 | if (is_empty_dir (DESTDIR + "/" + dir)) { 74 | remove_dir (DESTDIR + "/" + dir); 75 | } 76 | } 77 | } 78 | foreach (string file in p->list_files ()) { 79 | if (file.length > 41) { 80 | file=file[41:]; 81 | string dir = sdirname (file); 82 | if (is_empty_dir (DESTDIR + "/" + dir)) { 83 | remove_dir (DESTDIR + "/" + dir); 84 | } 85 | } 86 | } 87 | } 88 | if (!get_bool ("without-metadata")) { 89 | remove_file (get_storage () + "/metadata/" + p->name + ".yaml"); 90 | remove_file (get_storage () + "/files/" + p->name); 91 | remove_file (get_storage () + "/links/" + p->name); 92 | if (isdir (get_storage () + "/sysconf/" + p->name)) { 93 | remove_all (get_storage () + "/sysconf/" + p->name); 94 | } 95 | } 96 | return 0; 97 | } 98 | 99 | static void remove_init () { 100 | operation op = new operation (); 101 | op.help = new helpmsg (); 102 | op.callback.connect (remove_main); 103 | op.names = {_ ("remove"), "remove", "rm"}; 104 | op.help.name = _ ("remove"); 105 | op.help.description = _ ("Remove package from package name."); 106 | op.help.add_parameter ("--ignore-dependency", _ ("disable dependency check")); 107 | op.help.add_parameter ("--without-files", _ ("do not remove files from package database")); 108 | op.help.add_parameter ("--unsafe", _ ("remove all unsafe packages")); 109 | op.help.add_parameter ("--without-metadata", _ ("do not remove metadata from package database")); 110 | add_operation (op); 111 | } 112 | -------------------------------------------------------------------------------- /src/operations/utility/help.vala: -------------------------------------------------------------------------------- 1 | public static int help_main (string[] args) { 2 | if (args.length == 0) { 3 | print (colorize (_ ("Operation list:"), blue)); 4 | foreach (operation op in ops) { 5 | if (!op.help.shell_only) { 6 | print_fn (colorize (op.help.name + " : ", green) + op.help.description + "\n", false, false); 7 | } 8 | } 9 | if (get_bool ("all")) { 10 | print (colorize (_ ("Shell only operation list:"), blue)); 11 | foreach (operation op in ops) { 12 | if (op.help.shell_only) { 13 | print_fn (colorize (op.help.name + " : ", green) + op.help.description + "\n", false, false); 14 | } 15 | } 16 | } 17 | }else { 18 | foreach (string arg in args) { 19 | foreach (operation op in ops) { 20 | if (arg in op.names) { 21 | print (colorize (_ ("Aliases:"), green) + join (" / ", uniq (op.names))); 22 | write_op_help (op); 23 | } 24 | } 25 | } 26 | 27 | } 28 | return 0; 29 | } 30 | 31 | public static void write_version () { 32 | print ("YMP : " + colorize ("Y", red) + "erli ve " + colorize ("M", red) + "illi " + colorize ("P", red) + "ackage manager"); 33 | print (_ ("Version") + " : " + VERSION); 34 | if (!get_bool ("flag")) { 35 | return; 36 | } 37 | print (""); 38 | string flag = get_flag(); 39 | foreach (string line in ssplit (flag, "\n")) { 40 | print (" " + line); 41 | } 42 | print (""); 43 | } 44 | 45 | private static void write_op_help (operation op) { 46 | print_stderr (op.help.build ()); 47 | } 48 | 49 | 50 | static void help_init () { 51 | add_common_parameter ("--", _ ("stop argument parser")); 52 | #if check_oem 53 | add_common_parameter ("--allow-oem", _ ("disable oem check")); 54 | #endif 55 | add_common_parameter ("--quiet", _ ("disable output")); 56 | add_common_parameter ("--ignore-warning", _ ("disable warning messages")); 57 | #if DEBUG 58 | add_common_parameter ("--debug", _ ("enable debug output")); 59 | #endif 60 | add_common_parameter ("--verbose", _ ("show verbose output")); 61 | add_common_parameter ("--ask", _ ("enable questions")); 62 | add_common_parameter ("--no-color", _ ("disable color output")); 63 | add_common_parameter ("--no-sysconf", _ ("disable sysconf triggers")); 64 | add_common_parameter ("--sandbox", _ ("run ymp actions at sandbox environment")); 65 | add_common_parameter ("--help", _ ("write help messages")); 66 | 67 | 68 | operation op = new operation (); 69 | op.help = new helpmsg (); 70 | op.callback.connect (help_main); 71 | op.names = {_ ("help"), "help"}; 72 | op.help.name = _ ("help"); 73 | op.help.description = _ ("Write help message about ymp commands."); 74 | add_operation (op); 75 | 76 | } 77 | 78 | private string[] common_parameters; 79 | private void add_common_parameter (string arg, string desc) { 80 | if (common_parameters == null) { 81 | common_parameters = {}; 82 | } 83 | common_parameters += (colorize (arg, red) + " : " + desc); 84 | } 85 | 86 | private class helpmsg { 87 | public string description=""; 88 | private string[] parameters; 89 | public string name=""; 90 | public string usage=""; 91 | public int minargs = 0; 92 | public bool shell_only = false; 93 | 94 | public void add_parameter (string arg, string desc) { 95 | if (parameters == null) { 96 | parameters = {}; 97 | } 98 | string f = (colorize (arg, red) + " : " + desc); 99 | parameters += f; 100 | } 101 | public string build () { 102 | string ret = ""; 103 | if (usage == "") { 104 | usage = "ymp " + name + _ (" [OPTION]... [ARGS]... "); 105 | } 106 | ret += colorize (_ ("Usage:"), green) + " " + usage + "\n"; 107 | ret += description + "\n"; 108 | if (parameters.length > 0) { 109 | ret += colorize (_ ("Options:") + "\n", green); 110 | foreach (string param in parameters) { 111 | ret += " " + param + "\n"; 112 | } 113 | } 114 | ret += colorize (_ ("Common options:") + "\n", green); 115 | foreach (string param in common_parameters) { 116 | ret += " " + param + "\n"; 117 | } 118 | return ret; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/shcode/ympbuild_header.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export PATH="@buildpath@:/usr/sbin:/sbin:/usr/bin:/bin" 3 | declare -r installdir="@buildpath@/output" 4 | declare -r jobs="-j@jobs@" 5 | export HOME="@buildpath@" 6 | export USER="root" 7 | export PREFIX="/usr" 8 | export DESTDIR="$installdir" 9 | export INSTALL_ROOT="$installdir" 10 | declare -r YMPVER="@VERSION@" 11 | export NOCONFIGURE=1 12 | export NO_COLOR=1 13 | export VERBOSE=1 14 | export FORCE_UNSAFE_CONFIGURE=1 15 | export PYTHONDONTWRITEBYTECODE=1 16 | export SHELL="/bin/bash" 17 | export EDITOR="/bin/false" 18 | export PAGER="/bin/cat" 19 | export CONFIG_SHELL="/bin/bash" 20 | 21 | declare -r TARGET="@BUILD_TARGET@" 22 | declare -r DISTRO="@DISTRO@" 23 | export V=1 24 | 25 | export CFLAGS="-s -DTURKMAN -L@DISTRODIR@ @CFLAGS@" 26 | export CXXFLAGS="-s -DTURKMAN -L@DISTRODIR@ @CXXFLAGS@" 27 | export CC="@CC@" 28 | export LDFLAGS="@LDFLAGS@" 29 | 30 | export ARCH="@ARCH@" 31 | export DEBARCH="@DEBARCH@" 32 | 33 | export GOCACHE="@buildpath@/go-cache/" 34 | export GOMODCACHE="@buildpath@/go/" 35 | export GOTMPDIR="@buildpath@" 36 | 37 | export LANG="C.UTF-8" 38 | 39 | declare -r API_KEY='@APIKEY@' 40 | 41 | exec 0< /dev/null 42 | set -o pipefail 43 | shopt -s expand_aliases 44 | 45 | function meson(){ 46 | if [[ "$1" == "setup" ]] ; then 47 | command meson "$@" \ 48 | -Ddefault_library=both \ 49 | -Dwrap_mode=nodownload \ 50 | -Db_lto=true \ 51 | -Db_pie=true 52 | else 53 | command meson "$@" 54 | fi 55 | } 56 | 57 | function _dump_variables(){ 58 | set -o posix ; set 59 | } 60 | readonly -f _dump_variables 61 | 62 | function ymp_print_metadata(){ 63 | echo "ymp:" 64 | echo " source:" 65 | echo " name: $(echo $name)" 66 | echo " version: $(echo $version)" 67 | echo " release: $(echo $release)" 68 | echo " description: $(echo $description)" 69 | if [[ "${makedepends[@]}" != "" ]] ; then 70 | echo " makedepends:" 71 | for dep in ${makedepends[@]} ; do 72 | echo " - $dep" 73 | done 74 | fi 75 | if [[ "${arch[@]}" != "" ]] ; then 76 | echo " arch:" 77 | for dep in ${arch[@]} ; do 78 | echo " - $dep" 79 | done 80 | fi 81 | if [[ "${depends[@]}" != "" ]] ; then 82 | echo " depends:" 83 | for dep in ${depends[@]} ; do 84 | echo " - $dep" 85 | done 86 | fi 87 | if [[ "${source[@]}" != "" ]] ; then 88 | echo " archive:" 89 | for src in ${source[@]} ; do 90 | echo " - ${src}" 91 | done 92 | fi 93 | if [[ "${group[@]}" != "" ]] ; then 94 | echo " group:" 95 | for grp in ${group[@]} ; do 96 | echo " - ${grp}" 97 | done 98 | fi 99 | if [[ "${provides[@]}" != "" ]] ; then 100 | echo " provides:" 101 | for pro in ${provides[@]} ; do 102 | echo " - $pro" 103 | done 104 | fi 105 | if [[ "${replaces[@]}" != "" ]] ; then 106 | echo " replaces:" 107 | for rep in ${replaces[@]} ; do 108 | echo " - $rep" 109 | done 110 | fi 111 | if [[ "${uses[@]}" != "" || "${uses_extra[@]}" != "" ]] ; then 112 | echo " use-flags:" 113 | for use in ${uses[@]} ; do 114 | echo " - $use" 115 | done 116 | for flag in ${uses[@]} ${uses_extra[@]} `uname -m` "@BUILD_TARGET@"; do 117 | flag_dep="${flag}_depends" 118 | if [[ "$(eval echo \${${flag_dep}[@]})" != "" ]] ; then 119 | echo " ${flag}-depends:" 120 | for dep in $(eval echo \${${flag_dep}[@]}) ; do 121 | echo " - $dep" 122 | done 123 | fi 124 | done 125 | fi 126 | } 127 | readonly -f ymp_print_metadata 128 | 129 | function target(){ 130 | if [[ "$1" == "@BUILD_TARGET@" ]] ; then 131 | return 0 132 | fi 133 | return 1 134 | } 135 | readonly -f target 136 | 137 | function buildtype (){ 138 | if [[ "$1" == "$BUILDTYPE" ]] ; then 139 | return 0 140 | fi 141 | return 1 142 | } 143 | readonly -f buildtype 144 | 145 | function use(){ 146 | if ! echo ${uses[@]} ${uses_extra[@]} ${arch[@]} all extra | grep "$1" >/dev/null; then 147 | echo "Use flag \"$1\" is unknown!" 148 | return 1 149 | fi 150 | if [[ "${use_all}" == "31" ]] ; then 151 | if echo ${uses[@]} | grep "$1" >/dev/null; then 152 | return 0 153 | fi 154 | fi 155 | if [[ "${use_extra}" == "31" ]] ; then 156 | if echo ${uses_extra[@]} | grep "$1" >/dev/null; then 157 | return 0 158 | fi 159 | fi 160 | for use in ${uses[@]} ${uses_extra[@]}; do 161 | if [[ "${use}" == "$1" ]] ; then 162 | flag="use_$1" 163 | [[ "${!flag}" == "31" ]] 164 | return $? 165 | fi 166 | done 167 | } 168 | readonly -f use 169 | 170 | function use_opt(){ 171 | if use "$1" ; then 172 | echo $2 173 | else 174 | echo $3 175 | fi 176 | } 177 | readonly -f use_opt 178 | 179 | function eapply(){ 180 | for aa in $* ; do 181 | patch -Np1 "$aa" 182 | done 183 | } 184 | readonly -f eapply 185 | 186 | -------------------------------------------------------------------------------- /src/interpreter.vala: -------------------------------------------------------------------------------- 1 | public void add_script(string data) { 2 | if (data == null || data == "") { 3 | return; 4 | } 5 | foreach(string line in ssplit(data, "\n")) { 6 | string[] args = split_args(line); 7 | add_process(args[0], args[1: ]); 8 | } 9 | } 10 | 11 | private extern void no_stdin(); 12 | private extern void reset_std(); 13 | 14 | 15 | private class variable_integer { 16 | public string name; 17 | public int value; 18 | } 19 | 20 | public int ymp_run() { 21 | variable_integer[] labels = {}; 22 | bool label_found = false; 23 | int iflevel = 0; 24 | int last_i = -1; 25 | for (int i = 0; i < proc.length; i++) { 26 | debug("Current:%d Last:%d Type:%s".printf(i, last_i, proc[i].type)); 27 | long start_time = get_epoch(); 28 | if (proc[i].type == "label") { 29 | variable_integer l = new variable_integer(); 30 | l.name = proc[i].args[0]; 31 | l.value = i; 32 | if (!(l in labels)) { 33 | labels += l; 34 | } 35 | continue; 36 | } 37 | 38 | if (proc[i].type == "if") { 39 | process op = new process(); 40 | op.type = proc[i].args[0].strip(); 41 | op.args = proc[i].args[1: ]; 42 | if (iflevel == 0) { 43 | lock_operation(); 44 | int status = operation_main(op.type, op.args); 45 | unlock_operation(); 46 | if (status != 0) { 47 | iflevel += 1; 48 | } 49 | } else { 50 | iflevel += 1; 51 | } 52 | continue; 53 | } else if (proc[i].type == "endif") { 54 | iflevel -= 1; 55 | continue; 56 | } 57 | if (iflevel < 0) { 58 | error_add(_("Line %d:").printf(i)+" "+_("Syntax error: Unexceped endif detected.")); 59 | error(2); 60 | } else if (iflevel != 0) { 61 | continue; 62 | } 63 | if (proc[i].type == "goto") { 64 | string name = proc[i].args[0]; 65 | last_i = i; 66 | label_found = false; 67 | foreach(variable_integer l in labels) { 68 | if (l.name == name) { 69 | i = l.value; 70 | iflevel = 0; 71 | label_found = true; 72 | break; 73 | } 74 | } 75 | if(!label_found){ 76 | error_add(_("Line %d:").printf(i)+" "+_("label is not defined: %s").printf(name)); 77 | error(2); 78 | } 79 | continue; 80 | } 81 | if (proc[i].type == "ret") { 82 | if (last_i >= 0) { 83 | i = last_i; 84 | last_i = -1; 85 | } 86 | continue; 87 | } 88 | lock_operation(); 89 | if (get_bool("disable-stdin")) { 90 | no_stdin(); 91 | } 92 | int status = operation_main(proc[i].type, proc[i].args); 93 | reset_std(); 94 | unlock_operation(); 95 | if (status != 0) { 96 | string type = proc[i].type; 97 | error_add(_("Line %d:").printf(i)+" "+_("Process: %s failed. Exited with %d.").printf(type, status)); 98 | error(status); 99 | } 100 | float diff = ((float)(get_epoch() - start_time)) / 1000000; 101 | info(_("Process done in : %f sec").printf(diff)); 102 | } 103 | return 0; 104 | } 105 | 106 | // preprocessor 107 | private static string[] split_args(string line) { 108 | array ret = new array(); 109 | string cur = ""; 110 | char c = '\0'; 111 | char cc = '\0'; 112 | char qc = '\0'; 113 | int type = 0; // 0 = normal 1 = exec 2 = quota 114 | for (int i = 0; i < line.length; i++) { 115 | c = line[i]; 116 | if (c >= 1) { 117 | cc = line[i - 1]; 118 | } 119 | if (c == '\\') { 120 | i += 1; 121 | if (i >= line.length) { 122 | error_add("Unexceped line ending!"); 123 | error(31); 124 | } 125 | cur += line[i].to_string(); 126 | continue; 127 | } 128 | if (c == '`' && cc != '\\') { 129 | if (type != 0) { 130 | type = 1; 131 | ret.add(cur); 132 | cur = ""; 133 | } else { 134 | ret.add(getoutput(cur).strip()); 135 | cur = ""; 136 | type = 0; 137 | } 138 | continue; 139 | } 140 | if ((c == '"' || c == '\'') && cc != '\\') { 141 | if (type == 2 && qc == c) { 142 | type = 0; 143 | qc = '\0'; 144 | } else if (type == 0) { 145 | type = 2; 146 | qc = c; 147 | } 148 | continue; 149 | } 150 | if (c == ' ' && cc != '\\') { 151 | if (type == 0) { 152 | ret.add(cur); 153 | cur = ""; 154 | continue; 155 | } 156 | } 157 | cur += c.to_string(); 158 | } 159 | if (cur != null && cur != "") { 160 | ret.add(cur); 161 | } 162 | return ret.get(); 163 | } 164 | -------------------------------------------------------------------------------- /src/ccode/process.c: -------------------------------------------------------------------------------- 1 | #ifndef _process 2 | #define _process 3 | #define _GNU_SOURCE 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | #ifndef which 20 | char* which(char* path); 21 | #endif 22 | 23 | #ifndef str_add 24 | char* str_add(char* str1, char* str2); 25 | #endif 26 | 27 | 28 | #include 29 | 30 | int locked=0; 31 | void single_instance(){ 32 | if(locked){ 33 | return; 34 | } 35 | int pid_file = open("/run/ymp.pid", O_CREAT | O_RDWR, 0666); 36 | int rc = flock(pid_file, LOCK_EX | LOCK_NB); 37 | locked = 1; 38 | if(rc) { 39 | if(EWOULDBLOCK == errno){ 40 | error_add("Another ymp instance is already running"); 41 | exit(31); 42 | } 43 | } 44 | } 45 | 46 | pid_t child_pid, wait_pid; 47 | int status; 48 | gint run_args(char **command, gint length) { 49 | (void)length; 50 | 51 | child_pid = fork(); 52 | 53 | if (child_pid == -1) { 54 | perror("fork"); 55 | exit(EXIT_FAILURE); 56 | } 57 | 58 | if (child_pid == 0) { 59 | /* This code is executed by the child process */ 60 | execvp(command[0], command); 61 | 62 | /* If execvp fails */ 63 | perror("execvp"); 64 | exit(EXIT_FAILURE); 65 | } else { 66 | /* This code is executed by the parent process */ 67 | wait_pid = waitpid(child_pid, &status, 0); 68 | 69 | if (wait_pid == -1) { 70 | perror("waitpid"); 71 | return EXIT_FAILURE; 72 | } 73 | 74 | if (WIFEXITED(status)) { 75 | /* Child process terminated normally */ 76 | return WEXITSTATUS(status); 77 | } else { 78 | /* Child process did not terminate normally */ 79 | error_add("Child process did not terminate normally.\n"); 80 | return EXIT_FAILURE; 81 | } 82 | } 83 | } 84 | 85 | gint run_args_silent(char **command, gint length) { 86 | 87 | child_pid = fork(); 88 | 89 | if (child_pid == -1) { 90 | perror("fork"); 91 | exit(EXIT_FAILURE); 92 | } 93 | 94 | if (child_pid == 0) { 95 | 96 | /* Redirect standard output and standard error to /dev/null */ 97 | int devnull = open("/dev/null", O_WRONLY); 98 | dup2(devnull, STDOUT_FILENO); 99 | dup2(devnull, STDERR_FILENO); 100 | close(devnull); 101 | 102 | /* This code is executed by the child process */ 103 | execvp(command[0], command); 104 | 105 | /* If execvp fails */ 106 | perror("execvp"); 107 | exit(EXIT_FAILURE); 108 | } else { 109 | /* This code is executed by the parent process */ 110 | wait_pid = waitpid(child_pid, &status, 0); 111 | 112 | if (wait_pid == -1) { 113 | perror("waitpid"); 114 | return EXIT_FAILURE; 115 | } 116 | 117 | if (WIFEXITED(status)) { 118 | /* Child process terminated normally */ 119 | return WEXITSTATUS(status); 120 | } else { 121 | /* Child process did not terminate normally */ 122 | error_add( "Child process did not terminate normally.\n"); 123 | return EXIT_FAILURE; 124 | } 125 | } 126 | } 127 | 128 | gint run(char* command){ 129 | char* cmd[] = {"sh","-c",command, NULL}; 130 | return run_args(cmd, 3); 131 | } 132 | 133 | gint run_printf(char* format, ...){ 134 | char cmd[1024]; 135 | va_list args; 136 | va_start (args, format); 137 | vsnprintf (cmd, 1023, format, args); 138 | va_end (args); 139 | return run(cmd); 140 | 141 | } 142 | 143 | 144 | gint run_silent(char* command){ 145 | char* cmd[] = {"sh","-c",command, NULL}; 146 | return run_args_silent(cmd, 3); 147 | } 148 | 149 | char* getoutput(const char* command) { 150 | FILE *fp = popen(command, "r"); 151 | if (!fp) { 152 | /* Return NULL on failure */ 153 | return NULL; 154 | } 155 | 156 | /* Allocate initial buffer size */ 157 | size_t bufsize = 1024; 158 | char* ret = calloc(bufsize, sizeof(char)); 159 | if (!ret) { 160 | perror("Memory allocation error"); 161 | exit(EXIT_FAILURE); 162 | } 163 | 164 | /* Initialize the string */ 165 | ret[0] = '\0'; 166 | 167 | char buff[1024]; 168 | while (fgets(buff, sizeof(buff), fp) != NULL) { 169 | /* Resize buffer if needed */ 170 | size_t len = strlen(ret) + strlen(buff) + 1; 171 | if (len > bufsize) { 172 | /* Double the buffer size */ 173 | bufsize = len * 2; 174 | ret = realloc(ret, bufsize * sizeof(char)); 175 | if (!ret) { 176 | perror("Memory reallocation error"); 177 | exit(EXIT_FAILURE); 178 | } 179 | } 180 | strcat(ret, buff); 181 | } 182 | 183 | pclose(fp); 184 | 185 | /* Trim the buffer to the actual size needed */ 186 | ret = realloc(ret, (strlen(ret) + 1) * sizeof(char)); 187 | 188 | return ret; 189 | } 190 | 191 | long get_epoch(){ 192 | struct timeval tv; 193 | gettimeofday(&tv, NULL); 194 | return 1000000 * tv.tv_sec + tv.tv_usec; 195 | } 196 | 197 | void freeze(){ 198 | puts("FREEZE"); 199 | while(1); 200 | } 201 | 202 | #endif 203 | -------------------------------------------------------------------------------- /src/operations/package-manager/template.vala: -------------------------------------------------------------------------------- 1 | private static int template_main (string[] args) { 2 | string data="#!/usr/bin/env bash\n"; 3 | data += "name='" + str_or_def ("name", "") + "'\n"; 4 | data += "release=" + "'1'\n"; 5 | data += "version='" + str_or_def ("version", "1.0") + "'\n"; 6 | data += "url='" + str_or_def ("homepage", "https://example.org") + "'\n"; 7 | data += "description='" + str_or_def ("description", "Package description missing") + "'\n"; 8 | data += "email='" + str_or_def ("email", get_gitconfig_variable ("email")) + "'\n"; 9 | data += "maintainer='" + str_or_def ("maintainer", get_gitconfig_variable ("name")) + "'\n"; 10 | data += "license=('" + str_or_def ("license", "GPLv3") + "')\n"; 11 | data += "source=('" + str_or_def ("source", " ") + "')\n"; 12 | data += "depends=(" + str_or_def ("depends", " ") + ")\n"; 13 | data += "makedepends=(" + str_or_def ("makedepends", " ") + ")\n"; 14 | data += "sha256sums=('FIXME')\n"; 15 | data += "group=()\n"; 16 | data += "uses=()\n"; 17 | data += "arch=('" + getArch () + "')\n\n"; 18 | 19 | data += "cd $name-$version\n\n"; 20 | string buildtype = get_value ("build-type"); 21 | if (buildtype == "autotool" || buildtype == "") { 22 | data += "setup () {\n"; 23 | data += " ./configure --prefix=/usr \\\n"; 24 | data += " --libdir=/usr/lib64/\n"; 25 | data += "}\n\n"; 26 | data += "build () {\n"; 27 | data += " make $jobs\n"; 28 | data += "}\n\n"; 29 | data += "package () {\n"; 30 | data += " make install $jobs\n"; 31 | 32 | }else if (buildtype == "cmake") { 33 | data += "setup () {\n"; 34 | data += " mkdir build\n"; 35 | data += " cd build\n"; 36 | data += " cmake -DCMAKE_INSTALL_PREFIX=/usr \\\n"; 37 | data += " -DCMAKE_INSTALL_LIBDIR=/usr/lib64 ..\n"; 38 | data += "}\n\n"; 39 | data += "build () {\n"; 40 | data += " cd build\n"; 41 | data += " make $jobs\n"; 42 | data += "}\n\n"; 43 | data += "package () {\n"; 44 | data += " cd build\n"; 45 | data += " make install $jobs\n"; 46 | 47 | }else if (buildtype == "meson") { 48 | data += "setup () {\n"; 49 | data += " meson setup build --prefix=/usr \\\n"; 50 | data += " --libdir=/usr/lib64/\n"; 51 | data += " -Ddefault_library=both\n"; 52 | data += "}\n\n"; 53 | data += "build () {\n"; 54 | data += " ninja -C build $jobs\n"; 55 | data += "}\n\n"; 56 | data += "package () {\n"; 57 | data += " ninja -C build install $jobs\n"; 58 | 59 | }else { 60 | data += "setup () {\n"; 61 | data += " :\n"; 62 | data += "}\n\n"; 63 | data += "build () {\n"; 64 | data += " :\n"; 65 | data += "}\n\n"; 66 | data += "package () {\n"; 67 | data += " :\n"; 68 | } 69 | data += "}\n\n"; 70 | 71 | if (get_bool ("ask")) { 72 | print (colorize (_ ("Please check ympbuild:"), blue)); 73 | print (data); 74 | if (!yesno (colorize (_ ("Is it OK ?"), red))) { 75 | return 1; 76 | }; 77 | } 78 | string target=srealpath (str_or_def ("output", "")); 79 | error (1); 80 | print (colorize (_ ("Creating template: %s"), yellow).printf (target)); 81 | create_dir (target); 82 | writefile (target + "/ympbuild", data); 83 | return 0; 84 | } 85 | 86 | private string get_gitconfig_variable (string variable) { 87 | string gitconfig = srealpath (GLib.Environment.get_variable ("HOME") + "/.gitconfig"); 88 | if (isfile (gitconfig)) { 89 | info (_ ("Reading gitconfig: %s").printf (gitconfig)); 90 | foreach (string line in readfile (gitconfig).split ("\n")) { 91 | if (variable + " =" in line) { 92 | return ssplit (line, "=")[1].strip (); 93 | } 94 | } 95 | } 96 | return ""; 97 | } 98 | 99 | private string str_or_def (string val, string def) { 100 | string f = get_value (val); 101 | if (f != "") { 102 | return f; 103 | } 104 | if (def == "") { 105 | error_add (_ ("Variable '%s' is not defined. please use --%s").printf (val, val)); 106 | } 107 | return def.strip (); 108 | } 109 | 110 | static void template_init () { 111 | operation op = new operation (); 112 | op.help = new helpmsg (); 113 | op.callback.connect (template_main); 114 | op.names = {_ ("template"), "template", "t"}; 115 | op.help.name = _ ("template"); 116 | op.help.description = _ ("Create ympbuild from template."); 117 | op.help.add_parameter ("--name", _ ("package name")); 118 | op.help.add_parameter ("--version", _ ("package version")); 119 | op.help.add_parameter ("--homepage", _ ("package homepage")); 120 | op.help.add_parameter ("--description", _ ("package description")); 121 | op.help.add_parameter ("--depends", _ ("package dependencies")); 122 | op.help.add_parameter ("--makedepends", _ ("package build dependencies")); 123 | op.help.add_parameter ("--email", _ ("package creator email")); 124 | op.help.add_parameter ("--maintainer", _ ("package maintainer")); 125 | op.help.add_parameter ("--license", _ ("package license")); 126 | op.help.add_parameter ("--source", _ ("package source")); 127 | op.help.add_parameter ("--build-type", _ ("package build-type (autotool cmake meson)")); 128 | op.help.add_parameter ("--output", _ ("ympbuild output directory")); 129 | add_operation (op); 130 | } 131 | -------------------------------------------------------------------------------- /src/settings.vala: -------------------------------------------------------------------------------- 1 | 2 | //DOC: ## Settings functions 3 | //DOC: ymp configuration functions 4 | private string CONFIG; 5 | private string DESTDIR; 6 | private string BUILDDIR; 7 | private string DISTRO; 8 | private yamlfile config_yaml; 9 | private static void settings_init () { 10 | if (DESTDIR == null) { 11 | DESTDIR = "/"; 12 | } 13 | if (BUILDDIR == null) { 14 | BUILDDIR = "/tmp/ymp-build/"; 15 | } 16 | if (CONFIGDIR == null) { 17 | CONFIGDIR = "/etc/"; 18 | } 19 | if (CONFIG == null) { 20 | CONFIG = DESTDIR + "/" + CONFIGDIR + "/ymp.yaml"; 21 | } 22 | if (DISTRO==null){ 23 | string os_release = readfile("/etc/os-release"); 24 | foreach(string line in ssplit(os_release,"\n")){ 25 | if (startswith (line, "NAME=") && line.length > 5){ 26 | DISTRO=line[5:].replace("\"",""); 27 | } 28 | } 29 | if(DISTRO==null){ 30 | DISTRO="Unknown"; 31 | } 32 | } 33 | config_yaml = new yamlfile (); 34 | set_value_readonly ("destdir", DESTDIR); 35 | set_value_readonly ("config", CONFIG); 36 | set_value_readonly ("build:directory", BUILDDIR); 37 | set_value_readonly ("version", VERSION); 38 | string area = ""; 39 | string value = ""; 40 | if (isfile (CONFIG)) { 41 | config_yaml.load (CONFIG); 42 | foreach (string section in config_yaml.get_area_names (config_yaml.data)) { 43 | area = config_yaml.get_area (config_yaml.data, section); 44 | foreach (string variable in config_yaml.get_area_names (area)) { 45 | value = config_yaml.get_value (area, variable); 46 | if (section == "ymp") { 47 | set_value (variable, value); 48 | }else { 49 | set_value (section + ":" + variable, value); 50 | } 51 | } 52 | } 53 | }else { 54 | warning (_ ("Config file does not exists: %s").printf (CONFIG)); 55 | } 56 | if (GLib.Environment.get_variable ("USE") != null) { 57 | set_value ("USE", GLib.Environment.get_variable ("USE")); 58 | }else { 59 | area = config_yaml.get_area (config_yaml.data, "ymp"); 60 | set_value ("USE", config_yaml.get_value (area, "use")); 61 | } 62 | #if DEBUG 63 | if (get_bool ("debug")) { 64 | setenv ("G_MESSAGES_DEBUG", "all", 1); 65 | setenv ("G_ENABLE_DIAGNOSTIC", "1", 1); 66 | setenv ("G_DEBUG", "fatal_warnings", 1); 67 | } 68 | #endif 69 | } 70 | 71 | //DOC: `string get_config (string section, string path):` 72 | //DOC: get config variable from ymp config 73 | public string get_config (string section, string path) { 74 | string fdata = config_yaml.get_area (config_yaml.data, section); 75 | return config_yaml.get_value (fdata, path); 76 | } 77 | 78 | 79 | //DOC: `void set_destdir (string rootfs):` 80 | //DOC: change distdir 81 | public void set_destdir (string rootfs) { 82 | DESTDIR=srealpath (rootfs); 83 | info (_ ("Destination directory has been changed: %s").printf (DESTDIR)); 84 | settings_init (); 85 | } 86 | 87 | //DOC: `void set_builddir (string path):` 88 | //DOC: change builddir 89 | public void set_builddir (string path) { 90 | BUILDDIR=srealpath (path); 91 | info (_ ("Build directory has been changed: %s").printf (BUILDDIR)); 92 | settings_init (); 93 | } 94 | 95 | //DOC: `string get_storage ():` 96 | //DOC: get ymp storage directory. (default: /var/lib/ymp) 97 | public string get_storage () { 98 | return DESTDIR + "/" + STORAGEDIR; 99 | } 100 | 101 | //DOC: `string get_configdir ():` 102 | //DOC: get ymp storage directory. (default: /etc/) 103 | public string get_configdir () { 104 | return DESTDIR + "/" + CONFIGDIR; 105 | } 106 | 107 | public string get_destdir () { 108 | if (DESTDIR == null) { 109 | DESTDIR = "/"; 110 | } 111 | return DESTDIR; 112 | } 113 | 114 | //DOC: `string get_storage ():` 115 | //DOC: get ymp storage directory. (default: /var/lib/ymp) 116 | public string get_build_dir () { 117 | return DESTDIR + get_builddir_priv (); 118 | } 119 | 120 | private static string get_builddir_priv () { 121 | return BUILDDIR; 122 | } 123 | 124 | private static string get_metadata_path (string name) { 125 | return get_storage () + "/metadata/" + name + ".yaml"; 126 | } 127 | 128 | //DOC: `void set_config (string path):` 129 | //DOC: change ymp config file (default /etc/ymp.yaml) 130 | public void set_config (string path) { 131 | CONFIG=srealpath (path); 132 | settings_init (); 133 | } 134 | private static void parse_args (string[] args) { 135 | foreach (string arg in args) { 136 | if (arg == "--") { 137 | return; 138 | } 139 | if (startswith (arg, "--")) { 140 | var argname = arg[2:]; 141 | if (argname == "allow-oem") { 142 | set_value_readonly ("allow-oem", "true"); 143 | }else if (arg.contains ("=")) { 144 | var name = ssplit (argname, "=")[0]; 145 | var value = argname[name.length + 1:]; 146 | if (name == "use") { 147 | set_value (name, value); 148 | }else if (name == "destdir") { 149 | set_destdir (value); 150 | }else if (name == "build:directory") { 151 | set_builddir (value); 152 | }else if (name == "config") { 153 | set_config (value); 154 | }else { 155 | set_value (name, value); 156 | } 157 | }else { 158 | set_bool (argname, true); 159 | } 160 | } 161 | } 162 | if (GLib.Environment.get_variable ("NO_COLOR") != null) { 163 | set_bool ("no-color", true); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/operations/package-manager/search.vala: -------------------------------------------------------------------------------- 1 | private static int search_main (string[] args) { 2 | if (get_bool ("package")) { 3 | return search_pkgrepo_main (args); 4 | }else if (get_bool ("source")) { 5 | return search_srcrepo_main (args); 6 | }else if (get_bool ("file")) { 7 | return search_files_main (args); 8 | }else if (get_bool ("installed")) { 9 | return search_installed_main (args); 10 | }else { 11 | error_add (_ ("No options given. Please use --source or --package or --file or --installed .")); 12 | return 1; 13 | } 14 | } 15 | 16 | private static int search_installed_main (string[] args) { 17 | foreach (string pkg in list_installed_packages ()) { 18 | var p = get_installed_package (pkg); 19 | foreach (string arg in args) { 20 | if (arg in p.get ("description") || arg in p.name) { 21 | print ( (p.name + "\t" + p.get ("description")).replace (arg, colorize (arg, red))); 22 | } 23 | } 24 | } 25 | return 0; 26 | } 27 | 28 | 29 | private static int search_pkgrepo_main (string[] args) { 30 | foreach (repository repo in get_repos ()) { 31 | foreach (string pkg in repo.list_packages ()) { 32 | var p = repo.get_package (pkg); 33 | foreach (string arg in args) { 34 | if (arg in p.get ("description") || arg in p.name ) { 35 | int color = red; 36 | if (is_installed_package (p.name)) { 37 | color = green; 38 | } 39 | print ("%s\t%s".printf (p.name, p.get ("description")).replace (arg, colorize (arg, color))); 40 | } 41 | } 42 | } 43 | } 44 | return 0; 45 | } 46 | 47 | private static int search_srcrepo_main (string[] args) { 48 | foreach (repository repo in get_repos ()) { 49 | foreach (string pkg in repo.list_sources ()) { 50 | var p = repo.get_source (pkg); 51 | foreach (string arg in args) { 52 | if (arg in p.get ("description") || arg in p.name ) { 53 | int color = red; 54 | if (is_installed_package (p.name)) { 55 | color = green; 56 | } 57 | print ("%s\t%s".printf (p.name, p.get ("description")).replace (arg, colorize (arg, color))); 58 | } 59 | } 60 | } 61 | } 62 | return 0; 63 | } 64 | 65 | private static int search_files_main (string[] args) { 66 | foreach(string arg in args){ 67 | if(get_bool("path")){ 68 | foreach(string file in search_path({arg})){ 69 | print("%s => %s".printf(arg, file)); 70 | } 71 | }else { 72 | foreach(string pkg in search_file({arg})){ 73 | print("%s => %s".printf(arg, pkg)); 74 | } 75 | } 76 | } 77 | return 0; 78 | } 79 | 80 | private static string[] search_file (string[] args) { 81 | var pkgs = new array (); 82 | string path = ""; 83 | foreach (string pkg in list_installed_packages ()) { 84 | string files = readfile_cached ("%s/files/%s".printf (get_storage (), pkg)); 85 | foreach (string file in files.split ("\n")) { 86 | if(pkgs.has(pkg)){ 87 | break; 88 | } 89 | if (file.length < 41) { 90 | continue; 91 | } 92 | foreach (string arg in args) { 93 | path = DESTDIR + file[41:]; 94 | if (Regex.match_simple (arg, path)) { 95 | pkgs.add (pkg); 96 | } 97 | } 98 | } 99 | } 100 | return pkgs.get (); 101 | 102 | } 103 | 104 | private static string[] search_elf (string[] args) { 105 | var pkgs = new array (); 106 | string path = ""; 107 | foreach (string pkg in list_installed_packages ()) { 108 | string files = readfile_cached ("%s/files/%s".printf (get_storage (), pkg)); 109 | foreach (string file in files.split ("\n")) { 110 | if(pkgs.has(pkg)){ 111 | break; 112 | } 113 | if (file.length < 41) { 114 | continue; 115 | } 116 | foreach (string arg in args) { 117 | path = file[41:]; 118 | if (Regex.match_simple (arg, path)) { 119 | pkgs.add (pkg); 120 | } 121 | } 122 | } 123 | } 124 | return pkgs.get (); 125 | 126 | } 127 | 128 | private static string[] search_path (string[] args) { 129 | var pkgs = new array (); 130 | string path = ""; 131 | foreach (string pkg in list_installed_packages ()) { 132 | string files = readfile_cached ("%s/files/%s".printf (get_storage (), pkg)); 133 | foreach (string file in files.split ("\n")) { 134 | if (file.length < 41) { 135 | continue; 136 | } 137 | foreach (string arg in args) { 138 | path = DESTDIR + file[41:]; 139 | if (Regex.match_simple (arg, path)) { 140 | pkgs.add (path); 141 | } 142 | } 143 | } 144 | } 145 | return pkgs.get (); 146 | 147 | } 148 | 149 | static void search_init () { 150 | operation op = new operation (); 151 | op.help = new helpmsg (); 152 | op.callback.connect (search_main); 153 | op.names = {_ ("search"), "search", "sr"}; 154 | op.help.name = _ ("search"); 155 | op.help.minargs=1; 156 | op.help.description = _ ("Search packages."); 157 | op.help.add_parameter ("--package", _ ("search package in binary package repository")); 158 | op.help.add_parameter ("--source", _ ("search package in source package repository")); 159 | op.help.add_parameter ("--installed", _ ("search package in installed packages")); 160 | op.help.add_parameter ("--file", _ ("searches for packages by package file")); 161 | add_operation (op); 162 | } 163 | -------------------------------------------------------------------------------- /src/ccode/fetcher_curl.c: -------------------------------------------------------------------------------- 1 | #ifdef libcurl 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | #ifdef __STRICT_ANSI__ 13 | #define strdup(A) strcpy(calloc(strlen(A) + 1, sizeof(char)), A) 14 | #endif 15 | 16 | #ifndef PATH_MAX 17 | #define PATH_MAX 1024 18 | #endif 19 | 20 | static size_t write_data_to_file(void *ptr, size_t size, size_t nmemb, void *stream){ 21 | size_t written = fwrite(ptr, size, nmemb, (FILE *)stream); 22 | return written; 23 | } 24 | 25 | struct string { 26 | char *ptr; 27 | size_t len; 28 | }; 29 | 30 | struct progress { 31 | char *filename; 32 | time_t start_time; 33 | }; 34 | 35 | void init_string(struct string *s) { 36 | s->len = 0; 37 | s->ptr = calloc(1, s->len+1); 38 | if (s->ptr == NULL) { 39 | ferror_add("calloc() failed\n"); 40 | error(1); 41 | } 42 | s->ptr[0] = '\0'; 43 | } 44 | 45 | 46 | static size_t write_data_to_string(void *ptr, size_t size, size_t nmemb, void *stream){ 47 | struct string *s = stream; 48 | size_t new_len = s->len + size*nmemb; 49 | s->ptr = realloc(s->ptr, new_len+1); 50 | if (s->ptr == NULL) { 51 | ferror_add( "realloc() failed\n"); 52 | error(1); 53 | } 54 | memcpy(s->ptr+s->len, ptr, size*nmemb); 55 | s->ptr[new_len] = '\0'; 56 | s->len = new_len; 57 | 58 | return size*nmemb; 59 | } 60 | 61 | 62 | int fetcher_process_to_stderr(void *p, curl_off_t total, curl_off_t current, curl_off_t TotalToUpload, curl_off_t NowUploaded) { 63 | struct progress *data = p; 64 | if (total > 0) { 65 | /* Calculate percentage */ 66 | double percentage = (double)current / total * 100.0; 67 | 68 | /* Calculate elapsed time */ 69 | time_t now = time(NULL); 70 | double elapsed_time = difftime(now, data->start_time); /* in seconds */ 71 | 72 | /* Calculate speed (bytes per second) */ 73 | double speed = (elapsed_time > 0) ? current / elapsed_time : 0; /* bytes per second */ 74 | 75 | /* Calculate ETA (in seconds) */ 76 | double remaining = total - current; 77 | double eta = (speed > 0) ? remaining / speed : 0; /* in seconds */ 78 | 79 | /* Format speed and ETA */ 80 | char speed_str[20]; 81 | char eta_str[20]; 82 | snprintf(speed_str, sizeof(speed_str), "%s/s", g_format_size(speed)); 83 | snprintf(eta_str, sizeof(eta_str), "%.0f s", eta); 84 | 85 | /* Print formatted output */ 86 | fprintf(stderr, "\33[2K\r%6.2f%% %s %s/%s Speed: %s ETA: %s", 87 | percentage, data->filename, g_format_size(current), g_format_size(total), speed_str, eta_str); 88 | fflush(stderr); 89 | } 90 | return 0; 91 | } 92 | 93 | int fetcher_process_to_dummy(void *p, curl_off_t total, curl_off_t current, curl_off_t TotalToUpload, curl_off_t NowUploaded){ 94 | return 0; 95 | } 96 | 97 | void curl_options_common(CURL *curl, char* url){ 98 | struct curl_slist *chunk = NULL; 99 | chunk = curl_slist_append(chunk, "Connection: keep-alive"); 100 | chunk = curl_slist_append(chunk, "DNT: 1"); 101 | chunk = curl_slist_append(chunk, "Sec-GPC: 1"); 102 | chunk = curl_slist_append(chunk, "Ymp: \"NE MUTLU TURKUM DIYENE\""); 103 | if(strcmp(get_value("debug"),"true")==0){ 104 | curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 105 | } 106 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); 107 | curl_easy_setopt(curl, CURLOPT_URL, url); 108 | curl_easy_setopt(curl, CURLOPT_USERAGENT, get_value("useragent")); 109 | curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); 110 | curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); 111 | curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); 112 | curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""); 113 | if (get_bool("progressbar") || getenv("PROGRESSBAR")){ 114 | curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, fetcher_process_to_stderr); 115 | } else { 116 | curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, fetcher_process_to_dummy); 117 | } 118 | if (strcmp(get_value("ignore-ssl"),"true")==0){ 119 | curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); 120 | curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); 121 | } 122 | } 123 | 124 | int fetch(char* url, char* path){ 125 | FILE *fp; 126 | char fetcher_filename[PATH_MAX]; 127 | strcpy(fetcher_filename,path); 128 | CURL* curl=curl_easy_init(); 129 | finfo("Downloading: %s\n",path); 130 | fp = fopen(path,"wb"); 131 | if(fp == NULL) { 132 | ferror_add("Failed to open file for write: %s\n", path); 133 | return 1; 134 | } 135 | curl_options_common(curl, url); 136 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data_to_file); 137 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); 138 | struct progress data; 139 | data.filename = strdup(path); 140 | data.start_time = time(NULL); 141 | curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &data); 142 | CURLcode res; 143 | res = curl_easy_perform(curl); 144 | if(res != CURLE_OK || res == CURLE_HTTP_RETURNED_ERROR){ 145 | ferror_add("curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); 146 | curl_easy_cleanup(curl); 147 | return 0; 148 | } 149 | curl_easy_cleanup(curl); 150 | fclose(fp); 151 | return 1; 152 | } 153 | 154 | 155 | char* fetch_string(char* url){ 156 | CURL* curl=curl_easy_init(); 157 | struct string s; 158 | init_string(&s); 159 | char fetcher_filename[PATH_MAX]; 160 | strcpy(fetcher_filename,""); 161 | curl_options_common(curl, url); 162 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data_to_string); 163 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s); 164 | CURLcode res; 165 | res = curl_easy_perform(curl); 166 | if(res != CURLE_OK){ 167 | ferror_add("curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); 168 | return (char*)(s.ptr); 169 | } 170 | curl_easy_cleanup(curl); 171 | return (char*)(s.ptr); 172 | } 173 | 174 | 175 | #endif 176 | -------------------------------------------------------------------------------- /src/ccode/archive-create.c: -------------------------------------------------------------------------------- 1 | #ifndef _archive 2 | #define _archive 3 | 4 | #define zip 0 5 | #define tar 1 6 | #define p7zip 2 7 | #define cpio 3 8 | #define ar 4 9 | 10 | #define filter_none 0 11 | #define filter_gzip 1 12 | #define filter_xz 2 13 | 14 | #ifndef _XOPEN_SOURCE 15 | #define _XOPEN_SOURCE 700 16 | #endif 17 | 18 | #ifndef no_libarchive 19 | #include 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #ifndef PATH_MAX 40 | #define PATH_MAX 1024 41 | #endif 42 | 43 | #ifdef __STRICT_ANSI__ 44 | /* lstat missing if code is ansi */ 45 | int lstat(const char *pathname, struct stat *statbuf); 46 | #endif 47 | 48 | 49 | #ifndef isexists 50 | int isexists(const char*path); 51 | #endif 52 | 53 | void archive_set_type(archive *data, char* form, char* filt){ 54 | #ifdef debug 55 | debug("Archive type changed"); 56 | debug(form); 57 | debug(filt); 58 | #endif 59 | if(strcmp(form,"zip")==0) 60 | data->aformat=zip; 61 | else if(strcmp(form,"tar")==0) 62 | data->aformat=tar; 63 | else if(strcmp(form,"p7zip")==0) 64 | data->aformat=p7zip; 65 | else if(strcmp(form,"cpio")==0) 66 | data->aformat=cpio; 67 | else if(strcmp(form,"ar")==0) 68 | data->aformat=ar; 69 | 70 | if(strcmp(filt,"none")==0) 71 | data->afilter=filter_none; 72 | else if(strcmp(filt,"gzip")==0) 73 | data->afilter=filter_gzip; 74 | else if(strcmp(filt,"xz")==0) 75 | data->afilter=filter_xz; 76 | } 77 | 78 | void archive_write(archive *data, const char *outname, const char **filename) { 79 | struct archive *a; 80 | struct archive_entry *entry; 81 | struct stat st; 82 | char buff[8192]; 83 | int len; 84 | int fd; 85 | int e; 86 | 87 | a = archive_write_new(); 88 | /* compress format */ 89 | if(data->afilter == filter_gzip){ 90 | archive_write_add_filter_gzip(a); 91 | }else if(data->afilter == filter_xz){ 92 | archive_write_add_filter_xz(a); 93 | }else{ 94 | archive_write_add_filter_none(a); 95 | } 96 | /* archive format */ 97 | if(data->aformat == tar){ 98 | e = (archive_write_set_format_gnutar(a) != ARCHIVE_OK); 99 | }else if (data->aformat == p7zip){ 100 | e = (archive_write_set_format_7zip(a) != ARCHIVE_OK); 101 | }else if (data->aformat == cpio){ 102 | e = (archive_write_set_format_cpio(a) != ARCHIVE_OK); 103 | }else if (data->aformat == ar){ 104 | e = (archive_write_set_format_ar_bsd(a) != ARCHIVE_OK); 105 | }else{ 106 | e = (archive_write_set_format_zip(a) != ARCHIVE_OK); 107 | } 108 | if (e){ 109 | error_add("Libarchive error!"); 110 | return; 111 | } 112 | 113 | archive_write_open_filename(a, outname); 114 | char link[PATH_MAX]; 115 | #ifdef DEBUG 116 | char* type; 117 | #endif 118 | entry = NULL; 119 | while (*filename) { 120 | if(!isexists(*filename)){ 121 | fwarning("Non-existent enty detected: %s\n",*filename); 122 | continue; 123 | } 124 | lstat(*filename, &st); 125 | entry = archive_entry_new(); 126 | archive_entry_set_pathname(entry, *filename); 127 | archive_entry_set_size(entry, st.st_size); 128 | if (S_ISBLK(st.st_mode)) { 129 | /* block device */ 130 | archive_entry_set_filetype(entry, AE_IFBLK); 131 | #ifdef DEBUG 132 | type = "block device"; 133 | #endif 134 | } else if (S_ISCHR(st.st_mode)) { 135 | /* character device */ 136 | #ifdef DEBUG 137 | type = "character device"; 138 | #endif 139 | archive_entry_set_filetype(entry, AE_IFCHR); 140 | } else if (S_ISDIR(st.st_mode)) { 141 | /* directory */ 142 | #ifdef DEBUG 143 | type = "directory"; 144 | #endif 145 | archive_entry_set_filetype(entry, AE_IFDIR); 146 | } else if (S_ISDIR(st.st_mode)) { 147 | /* FIFO/pipe */ 148 | #ifdef DEBUG 149 | type = "fifo"; 150 | #endif 151 | archive_entry_set_filetype(entry, AE_IFIFO); 152 | } else if (S_ISLNK(st.st_mode)) { 153 | /* symlink */ 154 | #ifdef DEBUG 155 | type = "symlink"; 156 | #endif 157 | len = readlink(*filename,link,sizeof(link)); 158 | if(len < 0){ 159 | ferror_add("Broken symlink: %s\n",*filename); 160 | error_add("Failed to create archive"); 161 | break; 162 | } 163 | link[len] = '\0'; 164 | fdebug("Symlink: %s %s\n",*filename, link); 165 | archive_entry_set_filetype(entry, AE_IFLNK); 166 | archive_entry_set_symlink(entry, link); 167 | } else if (S_ISREG(st.st_mode)) { 168 | /* regular file */ 169 | #ifdef DEBUG 170 | type = "file"; 171 | #endif 172 | archive_entry_set_filetype(entry, AE_IFREG); 173 | } else if (S_ISSOCK(st.st_mode)) { 174 | /* socket */ 175 | #ifdef DEBUG 176 | type = "socket"; 177 | #endif 178 | archive_entry_set_filetype(entry, AE_IFSOCK); 179 | } else { 180 | /* unknown */ 181 | #ifdef DEBUG 182 | type = "unknown"; 183 | #endif 184 | archive_entry_set_filetype(entry, AE_IFREG); 185 | ferror_add("Unknown enty detected: %s (%d %d)\n",*filename,st.st_mode,AE_IFREG); 186 | error_add("Failed to create archive"); 187 | } 188 | if(has_error()){ 189 | error(2); 190 | } 191 | #ifdef DEBUG 192 | fdebug("Compress: %s type %s (%d)\n",*filename,type,st.st_mode); 193 | #endif 194 | archive_entry_set_perm(entry, 0644); 195 | archive_write_header(a, entry); 196 | fd = open(*filename, O_RDONLY); 197 | len = read(fd, buff, sizeof(buff)); 198 | while ( len > 0 ) { 199 | archive_write_data(a, buff, len); 200 | len = read(fd, buff, sizeof(buff)); 201 | } 202 | close(fd); 203 | filename++; 204 | } 205 | archive_entry_free(entry); 206 | archive_write_close(a); 207 | archive_write_free(a); 208 | } 209 | #endif 210 | #endif 211 | -------------------------------------------------------------------------------- /src/ccode/string.c: -------------------------------------------------------------------------------- 1 | #ifndef _string 2 | #define _string 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | int iseq(char* str1, char* str2){ 13 | return strcmp(str1,str2) == 0; 14 | } 15 | 16 | size_t sstrlen(const char* str){ 17 | size_t ret = 0; 18 | while(str && str[0] != '\0'){ 19 | str++; 20 | ret++; 21 | } 22 | return ret; 23 | } 24 | 25 | 26 | long count_tab(char* data){ 27 | int cnt = 0; 28 | while (*data == ' ') { 29 | cnt++; 30 | data++; 31 | } 32 | return cnt; 33 | } 34 | 35 | gchar* join(const gchar* f, gchar** array, gint length){ 36 | (void) length; 37 | int i = 0; 38 | int len = 0; 39 | /* find output size */ 40 | while(array[i]){ 41 | len += sstrlen(array[i]) + sstrlen(f); 42 | i++; 43 | } 44 | /* allocate memory */ 45 | char* ret = calloc(len+1, sizeof(char)); 46 | strcpy(ret,""); 47 | /* copy item len and reset value */ 48 | int cnt = i; 49 | i = 0; 50 | /* copy items */ 51 | while(array[i]){ 52 | strcat(ret,array[i]); 53 | if(i= len || str[i] == '\0') { 80 | str[i] = '\0'; 81 | break; 82 | } 83 | str[i] = data[j]; 84 | if(str[i] == '\n'){ 85 | j += cnt; 86 | 87 | } 88 | } 89 | return str; 90 | } 91 | 92 | char* int_to_string(int num){ 93 | char *ret = calloc(((sizeof(num) - 1) / 3 + 2), sizeof(char)); 94 | sprintf(ret, "%d", num); 95 | return ret; 96 | } 97 | 98 | #define isalnum_c(A) \ 99 | (A >= 'A' && A <= 'Z') || \ 100 | (A >= 'a' && A <= 'z') || \ 101 | (A >= '0' && A <= '9') || \ 102 | A == '-' || A == '_' || A == '.' || A == '~' 103 | 104 | /* Function to check if a character is a hexadecimal digit */ 105 | #define isHexDigit(A) \ 106 | (A >= '0' && A <= '9') || \ 107 | (A >= 'A' && A <= 'F') || \ 108 | (A >= 'a' && A <= 'f') 109 | 110 | 111 | /* Function to perform URL decoding */ 112 | char* url_decode(const char *input) { 113 | int cnt = 0; 114 | int i; 115 | for (i = 0; input[i] != '\0'; i++) { 116 | if (input[i] == '%'){ 117 | if (isHexDigit(input[i + 1])){ 118 | if (isHexDigit(input[i + 2])) { 119 | /* Skip '%', and the next two characters (assuming they are valid hexadecimal digits) */ 120 | i += 2; 121 | cnt++; 122 | } 123 | } 124 | } else { 125 | cnt++; 126 | } 127 | } 128 | 129 | /* +1 for null-terminator */ 130 | char *output = (char *)calloc((cnt + 1), sizeof(char)); 131 | 132 | if (output == NULL) { 133 | perror("Memory allocation failed\n"); 134 | return (char*) input; 135 | } 136 | 137 | int j = 0; 138 | for (i = 0; input[i] != '\0'; i++) { 139 | if (input[i] == '%') { 140 | if (isHexDigit(input[i + 1])){ 141 | if (isHexDigit(input[i + 2])) { 142 | char hex[3] = {input[i + 1], input[i + 2], '\0'}; 143 | output[j++] = (char)strtol(hex, NULL, 16); 144 | /* Skip '%', and the next two characters */ 145 | i += 2; 146 | } 147 | } 148 | } else { 149 | output[j++] = input[i]; 150 | } 151 | } 152 | /* Null-terminate the output string */ 153 | output[j] = '\0'; 154 | 155 | return output; 156 | } 157 | 158 | /* Function to perform URL encoding */ 159 | char* url_encode(const char *input) { 160 | int cnt = 0; 161 | int i; 162 | for (i = 0; input[i] != '\0'; i++) { 163 | if (!isalnum_c(input[i])) { 164 | /* Two characters for % and the hexadecimal digit */ 165 | cnt += 2; 166 | } else { 167 | cnt++; 168 | } 169 | } 170 | 171 | /* +1 for null-terminator */ 172 | char *output = (char *)malloc((cnt + 1) * sizeof(char)); 173 | 174 | if (output == NULL) { 175 | perror( "Memory allocation failed\n"); 176 | return (char*) input; 177 | } 178 | 179 | int j = 0; 180 | for (i = 0; input[i] != '\0'; i++) { 181 | if (isalnum_c(input[i])) { 182 | output[j++] = input[i]; 183 | } else { 184 | sprintf(output + j, "%%%02X", (unsigned char)input[i]); 185 | /* Move to the next position in the output string */ 186 | j += 3; 187 | } 188 | } 189 | /* Null-terminate the output string */ 190 | output[j] = '\0'; 191 | 192 | return output; 193 | } 194 | 195 | 196 | int endswith(const char* data, const char* f) { 197 | int i = sstrlen(data); 198 | int j = sstrlen(f); 199 | 200 | if (i < j) { 201 | return 0; 202 | } 203 | 204 | return strcmp(data + i - j, f) == 0; 205 | } 206 | 207 | int startswith(const char* data, const char* f) { 208 | int i = sstrlen(data); 209 | int j = sstrlen(f); 210 | 211 | if (i < j) { 212 | return 0; 213 | } 214 | 215 | return strncmp(data, f, j) == 0; 216 | } 217 | 218 | 219 | char* build_string(char* format, ...) { 220 | va_list args; 221 | va_start(args, format); 222 | 223 | /* Determine the size needed for the string */ 224 | int size = vsnprintf(NULL, 0, format, args) + 1; 225 | va_end(args); 226 | 227 | /* Allocate memory for the string */ 228 | char* result = (char*)malloc(size); 229 | if (result == NULL) { 230 | return ""; 231 | } 232 | 233 | /* Format the string */ 234 | va_start(args, format); 235 | vsnprintf(result, size, format, args); 236 | va_end(args); 237 | 238 | return result; 239 | } 240 | 241 | #endif 242 | -------------------------------------------------------------------------------- /doc/ympbuild.rst: -------------------------------------------------------------------------------- 1 | Building a ympbuild file 2 | ======================== 3 | You must run `ymp build ` command without root. If you want to sandbox environment, you should run command like this: 4 | 5 | .. code-block:: shell 6 | 7 | $ fdir=./repo/stuff-package/ 8 | $ ymp build "$fdir" --sandbox --shared="$fdir" 9 | 10 | Basics of ympbuild 11 | ================== 12 | **ymp** package manager uses **ympbuild** file. **ympbuild** file is simple bash script and call by ymp. You should define variables and functions. Minimal example ympbuild look like this: 13 | 14 | .. code-block:: shell 15 | 16 | #!/usr/bin/env bash 17 | name=example 18 | version=1.0 19 | release=1 20 | url='https://example.org' 21 | description='example package' 22 | email='your-name@example.org' 23 | maintainer='linuxuser' 24 | depends=(foo bar) 25 | source=("https://example.org/source.zip" 26 | "some-stuff.patch" 27 | ) 28 | arch=(x86_64 aarch64) 29 | md5sums=('bb91a17fd6c9032c26d0b2b78b50aff5' 30 | 'SKIP' 31 | ) 32 | license=('GplV3') 33 | prepare(){ 34 | ... 35 | } 36 | setup(){ 37 | ... 38 | } 39 | build(){ 40 | ... 41 | } 42 | package(){ 43 | ... 44 | } 45 | 46 | You can create ympbuild from template. Please see `ymp template --help`. 47 | 48 | variables 49 | ^^^^^^^^^ 50 | * **name** variable is package name. Must be string. 51 | * **version** variable is package version. Could be string or integer. 52 | * **release** variable is package release number. ymp compares this number to select upgraded packages. 53 | * **url** variable is package upstream url. Ymp doesn't use this variable. 54 | * **description** variable is package description. Must be string. 55 | * **email** variable is package maintainer email adress. Must be string. 56 | * **maintainer** variable is package maintairen nickname (or real name). Must be string. 57 | 58 | arrays 59 | ^^^^^^ 60 | * **depends** array is base runtime dependencies. Could be empty. 61 | * **source** array is package source list. ymp downloads or copies this sources into build directory. 62 | * **md5sums** array is package source hash list. ymp checks sources with this hashes. 63 | * **uses** and **uses_extra** arrays are use flag definitions. 64 | * **license** array is package licenses list. 65 | * **arch** array is supported architectures list. 66 | 67 | functions 68 | ^^^^^^^^^ 69 | * **prepare** function is source preparation stage. You can patch or modify source in this stage. 70 | * **setup** function is source configuration stage. You can configure source in this stage. 71 | * **build** function is compile stage. You can compile source. 72 | * **package** function is installation stage. You can install source into packaging directory. 73 | 74 | ympbuild directories 75 | ==================== 76 | Every build has own build directory in **/tmp/ymp-build/**. **build-id** is actually md5sum of **ympbuild** file so if you modify ympbuild, build-id will changed. Build directory defined as **HOME** environmental variable. You can simply use `cd` instead of `cd /tmp/ymp-build/`. 77 | 78 | Source archive extracted into build directory and ympbuild called from build directory. Packaging directory is **/tmp/ymp-build//output**. If you insert a file into this directory, ymp will add this file into package. also packaging directory defined as **installdir** and **DESTDIR** environmental variable. You can use simply `make install` instead of `make install DESTDIR=${installdir}`. 79 | 80 | Note: Generally **/tmp** directory is **tmpfs** so has limited space. If you want more space you must remove **/tmp/ymp-build** and symlink from other location. (location must have read, write and executable permission) 81 | 82 | Use flags 83 | ========= 84 | You can define **uses** and **uses_extra** array for definition use flags. Use flags can be used to customize the build. For example: 85 | 86 | .. code-block:: shell 87 | 88 | ... 89 | uses=(foo bar) 90 | uses_extra=(bazz) 91 | foo_depends=(foo bazz) 92 | ... 93 | setup(){ 94 | ../configure --prefix=/usr \ 95 | $(use_opt foo --with-foo --without-foo) 96 | } 97 | ... 98 | package(){ 99 | ... 100 | if use bar ; then 101 | install stuff ${DESTDIR}/bin/stuff 102 | fi 103 | } 104 | 105 | **use_opt** is option selector. Usage is `use_opt `. 106 | **use** is option checker. If use flag selected return true. 107 | 108 | You can pass use flags with **--use="foo bar"** argument or **USE="foo bar"** environmental variable. For example: 109 | 110 | .. code-block:: shell 111 | 112 | # --use parameter method. 113 | $ ymp build --use="foo bar" ./repo/foo-package/ 114 | # envitormental variable method. 115 | $ USE="foo bar" ymp build ./repo/foo-package/ 116 | # or you can define use flags into /etc/ymp.conf file 117 | 118 | If you add **all** into use flag list. Ymp enable all use flags except uses_extra flags. If you add **extra**, ymp enable all extra use flags. 119 | 120 | Note: If you define **xxx** into use flag list, **xxx_depends** array items are automatically added into **depends** array. 121 | 122 | Note: Use flags is not usable for binary packages. 123 | 124 | Build types 125 | =========== 126 | Ymp can compile a package multiple time in same package. You can define multiple build type with **buildtypes** array 127 | 128 | .. code-block:: shell 129 | 130 | ... 131 | buildtypes=(foo bar bazz) 132 | ... 133 | 134 | You can check buildtype like this in ympbuild file 135 | 136 | .. code-block:: shell 137 | 138 | ... 139 | if buildtype foo ; then 140 | export CFLAGS="..." 141 | fi 142 | # or check BUILDTYPE environment 143 | if [[ "$BUILDTYPE" == "bar" ]] ; then 144 | export CFLAGS="..." 145 | fi 146 | ... 147 | 148 | **Note:** If you didn't define buildtypes default build type name is **main** 149 | 150 | Creating git based package 151 | ========================== 152 | You can create git based package. First use **ymp template** command then create git repository. 153 | 154 | .. code-block:: shell 155 | 156 | $ ymp template --name=example --output=test-package ... 157 | $ cd test-package 158 | $ git init 159 | 160 | Then add remote address and create commit. 161 | 162 | .. code-block:: shell 163 | 164 | $ git remote add origin git@example.org:yourname/test-package.git 165 | $ git commit -m "first commit" 166 | 167 | **Note:** ympbuild file must found root directory of git repository. 168 | 169 | Then push repository to server. 170 | 171 | .. code-block:: shell 172 | 173 | $ git push -u origin master 174 | 175 | You can build and install package like this: 176 | 177 | .. code-block:: shell 178 | 179 | $ ymp build --output=/path/to/output git@example.org:yourname/test-package.git 180 | 181 | ymp will clone repository then build package. 182 | 183 | 184 | --------------------------------------------------------------------------------