From 56db0fcad4b3362d14d20e69a17e45d751c264a5 Mon Sep 17 00:00:00 2001 From: Jeremiah Orians Date: Wed, 17 Oct 2018 16:08:04 -0400 Subject: [PATCH] Breaking change in M2-Planet --- cc_core.c | 31 +-- cc_types.c | 2 +- functions/execve.c | 47 +++++ functions/fork.c | 22 +++ functions/libc-core.M1 | 27 ++- functions/uname.c | 10 +- test/common_x86/x86_defs.M1 | 8 +- test/test.answers | 54 +++--- test/test100/proof.answer | 2 +- test/test23/proof.answer | 2 +- test/test25/.gitignore | 7 + test/test25/cleanup.sh | 6 + test/test25/hello.sh | 39 ++++ test/test25/kaem.c | 369 ++++++++++++++++++++++++++++++++++++ 14 files changed, 571 insertions(+), 55 deletions(-) create mode 100644 functions/execve.c create mode 100644 functions/fork.c create mode 100644 test/test25/.gitignore create mode 100755 test/test25/cleanup.sh create mode 100755 test/test25/hello.sh create mode 100644 test/test25/kaem.c diff --git a/cc_core.c b/cc_core.c index 78abacd..214919f 100644 --- a/cc_core.c +++ b/cc_core.c @@ -37,6 +37,7 @@ char* break_target_num; struct token_list* break_frame; int current_count; struct type* last_type; +int Address_of; /* Imported functions */ char* parse_string(char* string); @@ -44,8 +45,6 @@ int escape_lookup(char* c); char* numerate_number(int a); - - struct token_list* emit(char *s, struct token_list* head) { struct token_list* t = calloc(1, sizeof(struct token_list)); @@ -179,8 +178,8 @@ void variable_load(struct token_list* a) emit_out("LOAD_BASE_ADDRESS_eax %"); emit_out(numerate_number(a->depth)); emit_out("\n"); + if(TRUE == Address_of) return; if(match("=", global_token->s)) return; - if(match("char**", a->type->name)) return; emit_out("LOAD_INTEGER\n"); } @@ -388,7 +387,7 @@ void postfix_expr_arrow() emit_out("\nADD_ebx_to_eax\n"); } - if(!match("=", global_token->s) && !match("char**", current_target->name)) + if((!match("=", global_token->s) && (4 >= i->size))) { emit_out("LOAD_INTEGER\n"); } @@ -553,6 +552,16 @@ void bitwise_expr() void primary_expr() { + if(match("&", global_token->s)) + { + Address_of = TRUE; + global_token = global_token->next; + } + else + { + Address_of = FALSE; + } + if(match("sizeof", global_token->s)) unary_expr_sizeof(); else if('-' == global_token->s[0]) { @@ -608,7 +617,7 @@ void collect_local() struct token_list* a = sym_declare(global_token->s, type_size, function->locals); if(match("main", function->s) && (NULL == function->locals)) { - a->depth = -4; + a->depth = -20; } else if((NULL == function->arguments) && (NULL == function->locals)) { @@ -1004,12 +1013,7 @@ void collect_arguments() { /* deal with foo(int a, char b) */ struct token_list* a = sym_declare(global_token->s, type_size, function->arguments); - if(match("main", function->s)) - { - if(match("argc", a->s)) a->depth = 4; - if(match("argv", a->s)) a->depth = 8; - } - else if(NULL == function->arguments) + if(NULL == function->arguments) { a->depth = -4; } @@ -1047,10 +1051,6 @@ void declare_function() emit_out(":FUNCTION_"); emit_out(function->s); emit_out("\n"); - if(match("main", function->s)) - { - emit_out("COPY_esp_to_ebp\t# Deal with special case\n"); - } statement(); /* Prevent duplicate RETURNS */ @@ -1083,6 +1083,7 @@ struct token_list* program() { out = NULL; function = NULL; + Address_of = FALSE; struct type* type_size; new_type: diff --git a/cc_types.c b/cc_types.c index 981cbf1..eacd3de 100644 --- a/cc_types.c +++ b/cc_types.c @@ -55,7 +55,7 @@ void initialize_types() struct type* d = calloc(1, sizeof(struct type)); d->name = "char**"; d->size = 4; - d->type = c; + d->type = b; d->indirect = d; /*fix up indrects for chars */ diff --git a/functions/execve.c b/functions/execve.c new file mode 100644 index 0000000..a8914f1 --- /dev/null +++ b/functions/execve.c @@ -0,0 +1,47 @@ +## Copyright (C) 2016 Jeremiah Orians +## This file is part of stage0. +## +## stage0 is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## stage0 is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with stage0. If not, see . + +void exit(int value); + +void _exit(int value) +{ + exit(value); +} + +int waitpid (int pid, int* status_ptr, int options) +{ + asm("LOAD_EFFECTIVE_ADDRESS_ebx %12" + "LOAD_INTEGER_ebx" + "LOAD_EFFECTIVE_ADDRESS_ecx %8" + "LOAD_INTEGER_ecx" + "LOAD_EFFECTIVE_ADDRESS_edx %4" + "LOAD_INTEGER_edx" + "LOAD_IMMEDIATE_eax %7" + "INT_80"); +} + + +int execve(char* file_name, char** argv, char** envp) +{ + asm("LOAD_EFFECTIVE_ADDRESS_ebx %12" + "LOAD_INTEGER_ebx" + "LOAD_EFFECTIVE_ADDRESS_ecx %8" + "LOAD_INTEGER_ecx" + "LOAD_EFFECTIVE_ADDRESS_edx %4" + "LOAD_INTEGER_edx" + "LOAD_IMMEDIATE_eax %11" + "INT_80"); +} diff --git a/functions/fork.c b/functions/fork.c new file mode 100644 index 0000000..610aa57 --- /dev/null +++ b/functions/fork.c @@ -0,0 +1,22 @@ +## Copyright (C) 2016 Jeremiah Orians +## This file is part of stage0. +## +## stage0 is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## stage0 is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with stage0. If not, see . + +int fork() +{ + asm("LOAD_IMMEDIATE_eax %2" + "LOAD_IMMEDIATE_ebx %0" + "INT_80"); +} diff --git a/functions/libc-core.M1 b/functions/libc-core.M1 index fd1da63..b6465e8 100644 --- a/functions/libc-core.M1 +++ b/functions/libc-core.M1 @@ -15,7 +15,28 @@ ## along with stage0. If not, see . :_start + + COPY_esp_to_ebp ; Protect esp + + ;; Prepare argv + LOAD_BASE_ADDRESS_eax %4 ; ARGV_address = EBP + 4 + PUSH_eax ; Put argv on the stack + + ;; Prepare envp + COPY_ebp_to_eax ; Address we need to load from + LOAD_INTEGER ; Get ARGC + ADD_IMMEDIATE_to_eax %2 ; OFFSET = ARGC + 2 + SAL_eax_Immediate8 !2 ; OFFSET = OFFSET * WORDSIZE + ADD_ebp_to_eax ; ENVP_address = ESP + OFFSET + PUSH_eax ; Put envp on the stack + + ;; Stack offset + ADD_IMMEDIATE_to_ebp %4 ; Fix ebp + + ;; Perform the main loop CALL_IMMEDIATE %FUNCTION_main - COPY_eax_to_ebx - LOAD_IMMEDIATE_eax %1 - INT_80 + + ;; Exit to kernel + COPY_eax_to_ebx ; Using the return code given by main + LOAD_IMMEDIATE_eax %1 ; Syscall exit + INT_80 ; Exit with that code diff --git a/functions/uname.c b/functions/uname.c index 1a052b0..55e43a3 100644 --- a/functions/uname.c +++ b/functions/uname.c @@ -17,11 +17,11 @@ struct utsname { - char** sysname[65]; /* Operating system name (e.g., "Linux") */ - char** nodename[65]; /* Name within "some implementation-defined network" */ - char** release[65]; /* Operating system release (e.g., "2.6.28") */ - char** version[65]; /* Operating system version */ - char** machine[65]; /* Hardware identifier */ + char sysname[65]; /* Operating system name (e.g., "Linux") */ + char nodename[65]; /* Name within "some implementation-defined network" */ + char release[65]; /* Operating system release (e.g., "2.6.28") */ + char version[65]; /* Operating system version */ + char machine[65]; /* Hardware identifier */ }; int uname(struct utsname* unameData) diff --git a/test/common_x86/x86_defs.M1 b/test/common_x86/x86_defs.M1 index e2d8d62..43af209 100644 --- a/test/common_x86/x86_defs.M1 +++ b/test/common_x86/x86_defs.M1 @@ -14,15 +14,19 @@ ## You should have received a copy of the GNU General Public License ## along with stage0. If not, see . -DEFINE ADD_ebx_to_eax 01D8 +DEFINE ADD_IMMEDIATE_to_eax 81C0 +DEFINE ADD_IMMEDIATE_to_ebp 81C5 DEFINE ADD_eax_to_ebx 01C3 +DEFINE ADD_ebp_to_eax 01E8 +DEFINE ADD_ebx_to_eax 01D8 DEFINE AND_eax_ebx 21D8 DEFINE CALL_IMMEDIATE E8 -DEFINE CALL_eax FFD0 DEFINE CALL_IMMEDIATE E8 +DEFINE CALL_eax FFD0 DEFINE CMP 39C3 DEFINE COPY_eax_to_ebx 89C3 DEFINE COPY_eax_to_ecx 89C1 +DEFINE COPY_ebp_to_eax 89E8 DEFINE COPY_ebx_to_eax 89D8 DEFINE COPY_ebx_to_edx 89DA DEFINE COPY_ecx_to_ebp 89CD diff --git a/test/test.answers b/test/test.answers index e18baa9..6bb78f3 100644 --- a/test/test.answers +++ b/test/test.answers @@ -1,27 +1,27 @@ -12977ab3adfa80dd4e98068e3cf30a660bfbd5fc1c2e5ad4b33fb72ef8cb11a4 test/results/test00-binary -76b75af92dbaba02222ca1a2ae1ec28d8ea075828039821b445c2368ee31d46d test/results/test01-binary -02c8454596a4fddc5d659a547a12386bdde54f1d3e05df2558b0e89d676f2142 test/results/test02-binary -735ce831b4c0f9909977d659fe2b5f83920cfd38606a1d833cab4d89f9619398 test/results/test03-binary -62cafe3e96763862e802b83666b457ceaf4b3e4032b530349253b95c5c1e7bb3 test/results/test04-binary -2cbd9acf2e8069f5d93764e1fe235f0e1606a36e058bad8a976a6d4e97b4b8fe test/results/test05-binary -c921f545c7baebe05e1ce60c777d6d7782ba626fdf7520f576d3ee1b849a8bbf test/results/test06-binary -b45fae655b7f848b28ebdb8eb2e30ae789fbcf7920bc315395d53986bb1adae4 test/results/test07-binary -d511db73158a9544a5b5f828a79751e3de8a04b81c143fd0c146fc22c938aa9f test/results/test08-binary -907e1808f2e2b15ac72ebf13898b15c678e68ebd43d673dcd0f408d907e7962f test/results/test09-binary -ef179cd359ba1d61d45089e314cd4ac2069c8dc4dd7494d7c766344ea3c8cf88 test/results/test10-binary -a6ba14a8d8fe29dccfacdf1723a241ede000d7cee50d82a443f60e73d97e384e test/results/test100-binary -5aaf399fe706d4a8c85c121c75ada29a65c293b57c98e8999961a2ef0bab0d62 test/results/test11-binary -4f8111e73e07255ae203963438c82ea8bcff7474e1594b52b426c58a03cb30eb test/results/test12-binary -dd74dabfdce8657ff440c1eef531cbf67a64854f2020d4d6bcb65c9cc2d199cb test/results/test13-binary -ed0960dc5809d8cda84e7df8bf02bd0cd2aeeba4df8c752d68af434408555f8c test/results/test14-binary -e216869c3fb06de7a41578517c797169e219b20a5697a822ba11eeef0d04f181 test/results/test15-binary -315ae5cc5c9d5bdcae0eddd55371128e53e3e9267a2a7c53832ed0af51693bea test/results/test16-binary -fdce9856f885418a7b2f69fc24a6cc0c85922313b49694d8030c544e4b2ad16f test/results/test17-binary -9a426972b6df90a158aebe3b8f3eb9ef8a63ce317d764afb92be4fce16542743 test/results/test18-binary -91b761d241dd9969230b235c6cb3bc86cc6b0076d9d1a04c4950de32228149f5 test/results/test19-binary -48d845d20fff86183047342641cc8a6174e71c0ca004be882f0195a141bd64ea test/results/test20-binary -65354ea5f760e42ea054785033a6519e0eee30d21b1b69ac7715ef958c5e0e2f test/results/test21-binary -9a79bdfb35c1c17bb0c66357836382bb08d3876ae8c0c77356776d16aa7faa7f test/results/test22-binary -96e1789254675815a3ec5ad93c1cc32c4805d1ad7f029721cef102c4501df8e2 test/results/test23-binary -50215e4b4e2ce22a959ea7bcfc77c4d6ac45464455f5103afcaea0e84f9bf1d1 test/results/test24-binary -0013b8786068520e386a0cf2ce39c5145462439f17c264e62a9eddb1eed0433b test/results/test99-binary +c52562bd0aabb86ce8ca177f22f8d0455769b444df2d4d62894faab63b7151d8 test/results/test00-binary +eae96857f2b6d8e8ba86ac06e72345ea572622b358b23978bb5f2db1baadf41c test/results/test01-binary +8ead336d2f3f72d5874230492e0472edec61d355905e8636e3dfb2731695037c test/results/test02-binary +2313cb3f1a2b9eb6bf15f8d43418e15d6c16f7f1b5c22700fdfc2b38beb59192 test/results/test03-binary +b7ddb37063c541c6a315809c4438aa235d6702f54bb64f4ffc88dbe78617de81 test/results/test04-binary +4d4ec6247a7cc9062a5b3d8adfec7199476715446723a0b882268afe6daad1f3 test/results/test05-binary +663fc6eefe965f237b6bf5a211398c8ae1210f97ff39b59603677e92462c68c7 test/results/test06-binary +a9a3e332d13ded5f80d7431f8717f26527b3722b33ea57760a9a5723dffc099c test/results/test07-binary +f1c01feb865c4d552033186d9ce50dd39468a7e8aebf762886c13ad3e03b5011 test/results/test08-binary +3b39e72f3de90ed690adfaf6145af46157cef2ec5e72867ac577fa27a0229894 test/results/test09-binary +020e86020819cc4963e6185b22e534fcf8306b6cb116f12643f254a24688ff0a test/results/test10-binary +db41db8bc1dc2f94367c41c33d9438634d75994f79a46296bb8907905a64c013 test/results/test100-binary +3fd11bad4a426ce1ff8fd9c6d7d2b943effae9f3f5740b7376e426e9b0555851 test/results/test11-binary +f98ab8e4bb35580e0dde96126d7a56aff66bda208d02c8d89390b40d6cff591c test/results/test12-binary +5051ffca2615144419f8ec1a5d4999486ae81e7781428f59e47e866af97cef92 test/results/test13-binary +a8218958b628066e2fda63d3933f1bf607c358d7bdfe84fc02596393698ea5f6 test/results/test14-binary +3adb4a5f3995583ba711151361728a26c3fbf0140864d13b4b042978ca45d683 test/results/test15-binary +d70e072f4f1f077d10ff65e9216ca8b423b996e35d68d208025db7a78b062f50 test/results/test16-binary +9b4ba350b07cc1cf4e12dc77d0d960ded1511f13b887363b0eb33421e2f626de test/results/test17-binary +8de7384c4633b1d5c60bbbb298d7f4b738e52fbc266ef4ef9a48b3cb995e3176 test/results/test18-binary +b0d7982de3f257d6a5b51ad356c1aa09f24b8a69d862a90f41aef7dc83ec3b2f test/results/test19-binary +365c96fb8368710d620a76facd6bebcdeeb6f6d30ceaf0a6f1567fc3fcbe9b54 test/results/test20-binary +abb4d9272a262c4bf77d9cbb714cbb8ce16841a128c670394f60cb817ebe7727 test/results/test21-binary +24a14bd0641cdbcf49b69a71c80c00fb4f0c42c5ed72f7b44e5119ad1f22d533 test/results/test22-binary +dd9081cb6eb908e8a727b05e2fc65efe01e5c33221eee9a70565808a97c7b294 test/results/test23-binary +6fb0c0db1732038f945172ef05c33c976396baf86571b1169a3af02e850be0d5 test/results/test24-binary +140af7fb3ef89d84b21bd3fe69f0d3260650ec0467c0ffadf9268fad573a397f test/results/test99-binary diff --git a/test/test100/proof.answer b/test/test100/proof.answer index 245687a..3046896 100644 --- a/test/test100/proof.answer +++ b/test/test100/proof.answer @@ -1 +1 @@ -d27357f9db85e403cc09ca59123009dd4193db287b91a3414c09eafb7e28d22e test/test100/proof +b882976ea4fb2ede866851a57fd3be0653ac1918b87e183e4c1cd6cb5c60d2b4 test/test100/proof diff --git a/test/test23/proof.answer b/test/test23/proof.answer index 7ae9651..132300e 100644 --- a/test/test23/proof.answer +++ b/test/test23/proof.answer @@ -1 +1 @@ -736df1e1db39ffd6738be5efa064e14b26cc88fd7530efb6cf663df03c0db721 test/test23/proof +16039cd07d755cff62d61efd6945f214a79cbfa07c32386beea9b9f5b771a976 test/test23/proof diff --git a/test/test25/.gitignore b/test/test25/.gitignore new file mode 100644 index 0000000..0ce0949 --- /dev/null +++ b/test/test25/.gitignore @@ -0,0 +1,7 @@ +# Ignore the files created by script +*.M1 +*.hex2 +proof + +# A place to put a good run for comparison +actual.M1 diff --git a/test/test25/cleanup.sh b/test/test25/cleanup.sh new file mode 100755 index 0000000..b7fe1fe --- /dev/null +++ b/test/test25/cleanup.sh @@ -0,0 +1,6 @@ +#! /bin/sh +rm -f test/test25/kaem.M1 +rm -f test/test25/kaem-footer.M1 +rm -f test/test25/kaem.hex2 +rm -f test/test25/proof +exit 0 diff --git a/test/test25/hello.sh b/test/test25/hello.sh new file mode 100755 index 0000000..5274989 --- /dev/null +++ b/test/test25/hello.sh @@ -0,0 +1,39 @@ +#! /bin/sh +set -x +# Build the test +./bin/M2-Planet -f functions/exit.c \ + -f functions/file.c \ + -f functions/file_print.c \ + -f functions/malloc.c \ + -f functions/calloc.c \ + -f functions/match.c \ + -f functions/numerate_number.c \ + -f functions/fork.c \ + -f functions/execve.c \ + -f test/test25/kaem.c \ + --debug \ + -o test/test25/kaem.M1 || exit 1 + +# Build debug footer +blood-elf -f test/test25/kaem.M1 \ + -o test/test25/kaem-footer.M1 || exit 2 + +# Macro assemble with libc written in M1-Macro +M1 -f test/common_x86/x86_defs.M1 \ + -f functions/libc-core.M1 \ + -f test/test25/kaem.M1 \ + -f test/test25/kaem-footer.M1 \ + --LittleEndian \ + --Architecture 1 \ + -o test/test25/kaem.hex2 || exit 3 + +# Resolve all linkages +hex2 -f test/common_x86/ELF-i386-debug.hex2 \ + -f test/test25/kaem.hex2 \ + --LittleEndian \ + --Architecture 1 \ + --BaseAddress 0x8048000 \ + -o test/results/test25-binary \ + --exec_enable || exit 4 + +exit 0 diff --git a/test/test25/kaem.c b/test/test25/kaem.c new file mode 100644 index 0000000..f2ed363 --- /dev/null +++ b/test/test25/kaem.c @@ -0,0 +1,369 @@ +/* Copyright (C) 2016 Jeremiah Orians + * This file is part of mescc-tools. + * + * mescc-tools is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * mescc-tools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with mescc-tools. If not, see . + */ + +#include +#include +#include +#include + +#define FALSE 0 +//CONSTANT FALSE 0 +#define TRUE 1 +//CONSTANT TRUE 1 +#define max_string 4096 +//CONSTANT max_string 4096 +#define max_args 256 +//CONSTANT max_args 256 + +void file_print(char* s, FILE* f); +char* numerate_number(int a); +int match(char* a, char* b); + +char** tokens; +int command_done; +int VERBOSE; +int STRICT; + +/* Function for purging line comments */ +void collect_comment(FILE* input) +{ + int c; + do + { + c = fgetc(input); + if(-1 == c) + { + file_print("IMPROPERLY TERMINATED LINE COMMENT!\nABORTING HARD\n", stderr); + exit(EXIT_FAILURE); + } + } while('\n' != c); +} + +/* Function for collecting RAW strings and removing the " that goes with them */ +int collect_string(FILE* input, int index, char* target) +{ + int c; + do + { + c = fgetc(input); + if(-1 == c) + { /* We never should hit EOF while collecting a RAW string */ + file_print("IMPROPERLY TERMINATED RAW string!\nABORTING HARD\n", stderr); + exit(EXIT_FAILURE); + } + else if('"' == c) + { /* Made it to the end */ + c = 0; + } + target[index] = c; + index = index + 1; + } while(0 != c); + return index; +} + +/* Function to collect an individual argument or purge a comment */ +char* collect_token(FILE* input) +{ + char* token = calloc(max_string, sizeof(char)); + char c; + int i = 0; + do + { + c = fgetc(input); + if(-1 == c) + { /* Deal with end of file */ + file_print("execution complete\n", stderr); + exit(EXIT_SUCCESS); + } + else if((' ' == c) || ('\t' == c)) + { /* space and tab are token seperators */ + c = 0; + } + else if('\n' == c) + { /* Command terminates at end of line */ + c = 0; + command_done = 1; + } + else if('"' == c) + { /* RAW strings are everything between a pair of "" */ + i = collect_string(input, i, token); + c = 0; + } + else if('#' == c) + { /* Line comments to aid the humans */ + collect_comment(input); + c = 0; + command_done = 1; + } + else if('\\' == c) + { /* Support for end of line escapes, drops the char after */ + fgetc(input); + c = 0; + } + token[i] = c; + i = i + 1; + } while (0 != c); + + if(1 == i) + { /* Nothing worth returning */ + free(token); + return NULL; + } + return token; +} + +char* copy_string(char* target, char* source) +{ + while(0 != source[0]) + { + target[0] = source[0]; + target = target + 1; + source = source + 1; + } + return target; +} + +char* prepend_string(char* add, char* base) +{ + char* ret = calloc(max_string, sizeof(char)); + copy_string(copy_string(ret, add), base); + return ret; +} + +char* find_char(char* string, char a) +{ + if(0 == string[0]) return NULL; + while(a != string[0]) + { + string = string + 1; + if(0 == string[0]) return string; + } + return string; +} + +char* prematch(char* search, char* field) +{ + do + { + if(search[0] != field[0]) return NULL; + search = search + 1; + field = field + 1; + } while(0 != search[0]); + return field; +} + +char* env_lookup(char* token, char** envp) +{ + if(NULL == envp) return NULL; + int i = 0; + char* ret = NULL; + do + { + ret = prematch(token, envp[i]); + if(NULL != ret) return ret; + i = i + 1; + } while(NULL != envp[i]); + return NULL; +} + +char* find_executable(char* name, char* PATH) +{ + if(('.' == name[0]) || ('/' == name[0])) + { /* assume names that start with . or / are relative or absolute */ + return name; + } + + char* next = find_char(PATH, ':'); + char* trial; + FILE* try; + while(NULL != next) + { + next[0] = 0; + trial = prepend_string(PATH, prepend_string("/", name)); + + try = fopen(trial, "r"); + if(NULL != try) + { + fclose(try); + return trial; + } + PATH = next + 1; + next = find_char(PATH, ':'); + free(trial); + } + return NULL; +} + + +/* Function for executing our programs with desired arguments */ +void execute_command(FILE* script, char** envp) +{ + tokens = calloc(max_args, sizeof(char*)); + char* PATH = env_lookup("PATH=", envp); + if(NULL != PATH) + { + PATH = calloc(max_string, sizeof(char)); + copy_string(PATH, env_lookup("PATH=", envp)); + } + + char* USERNAME = env_lookup("LOGNAME=", envp); + if((NULL == PATH) && (NULL == USERNAME)) + { + PATH = calloc(max_string, sizeof(char)); + copy_string(PATH, "/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"); + } + else if(NULL == PATH) + { + PATH = prepend_string("/home/", prepend_string(USERNAME,"/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games")); + } + + int i = 0; + int status = 0; + command_done = 0; + do + { + char* result = collect_token(script); + if(0 != result) + { /* Not a comment string but an actual argument */ + tokens[i] = result; + i = i + 1; + } + } while(0 == command_done); + + if(VERBOSE && (0 < i)) + { + file_print(" +> ", stdout); + int j; + for(j = 0; j < i; j = j + 1) + { + file_print(tokens[j], stdout); + fputc(' ', stdout); + } + file_print("\n", stdout); + } + + if(0 < i) + { /* Not a line comment */ + char* program = find_executable(tokens[0], PATH); + if(NULL == program) + { + file_print(tokens[0], stderr); + file_print("Some weird shit went down with: ", stderr); + file_print("\n", stderr); + exit(EXIT_FAILURE); + } + + int f = fork(); + if (f == -1) + { + file_print("fork() failure", stderr); + exit(EXIT_FAILURE); + } + else if (f == 0) + { /* child */ + /* execve() returns only on error */ + execve(program, tokens, envp); + /* Prevent infinite loops */ + _exit(EXIT_SUCCESS); + } + + /* Otherwise we are the parent */ + /* And we should wait for it to complete */ + waitpid(f, &status, 0); + + if(STRICT && (0 != status)) + { /* Clearly the script hit an issue that should never have happened */ + file_print("Subprocess error ", stderr); + file_print(numerate_number(status), stderr); + file_print("\nABORTING HARD\n", stderr); + /* stop to prevent damage */ + exit(EXIT_FAILURE); + } + /* Then go again */ + } +} + + +int main(int argc, char** argv, char** envp) +{ + VERBOSE = FALSE; + STRICT = FALSE; + char* filename = "kaem.run"; + FILE* script = NULL; + + int i = 1; + while(i <= argc) + { + if(NULL == argv[i]) + { + i = i + 1; + } + else if(match(argv[i], "-h") || match(argv[i], "--help")) + { + file_print("kaem only accepts --help, --version, --verbose or no arguments\n", stdout); + exit(EXIT_SUCCESS); + } + else if(match(argv[i], "-f") || match(argv[i], "--file")) + { + filename = argv[i + 1]; + i = i + 2; + } + else if(match(argv[i], "n") || match(argv[i], "--nightmare-mode")) + { + file_print("Begin nightmare", stdout); + envp = NULL; + i = i + 1; + } + else if(match(argv[i], "-V") || match(argv[i], "--version")) + { + file_print("kaem version 0.1\n", stdout); + exit(EXIT_SUCCESS); + } + else if(match(argv[i], "--verbose")) + { + VERBOSE = TRUE; + i = i + 1; + } + else if(match(argv[i], "--strict")) + { + STRICT = TRUE; + i = i + 1; + } + else + { + file_print("UNKNOWN ARGUMENT\n", stdout); + exit(EXIT_FAILURE); + } + } + + script = fopen(filename, "r"); + + if(NULL == script) + { + file_print("The file: ", stderr); + file_print(filename, stderr); + file_print(" can not be opened!\n", stderr); + exit(EXIT_FAILURE); + } + + while(1) + { + execute_command(script, envp); + } + fclose(script); + return EXIT_SUCCESS; +}