diff --git a/bash-5.1/Cargo.toml b/bash-5.1/Cargo.toml index 48dca7e2264e2c3503fafd3f43eed8fe91c141a2..dbc892ff43d12700937619aba2ab6b9fba2d9257 100644 --- a/bash-5.1/Cargo.toml +++ b/bash-5.1/Cargo.toml @@ -2,15 +2,66 @@ name = "rsbash" version = "0.1.0" edition = "2021" + + [lib] name = "rsbash" crate-type = ["cdylib"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [workspace] -members = ["builtins/command1", "builtins/command2"] + +members=[ + "builtins_rust/jobs", + "builtins_rust/cd", + "builtins_rust/fg_bg", + "builtins_rust/read", + "builtins_rust/fc", + "builtins_rust/getopts", + "builtins_rust/colon", + "builtins_rust/builtin", + "builtins_rust/exit", + "builtins_rust/help", + "builtins_rust/alias", + "builtins_rust/caller", + "builtins_rust/eval", + "builtins_rust/exec", + "builtins_rust/common", + "builtins_rust/cmd", + "builtins_rust/enable", + "builtins_rust/declare", + "builtins_rust/setattr", + "builtins_rust/break_1", + "builtins_rust/type", + "builtins_rust/ulimit" +] [dependencies] -command1 = {path = "./builtins/command1"} -command2 = {path = "./builtins/command2"} +libc = "0.2" read = {path = "./builtins_rust/read"} +#history = {path = "./builtins_rust/history"} +#kill = {path = "./builtins_rust/kill"} +#rlet = {path = "./builtins_rust/rlet"} +#mapfile = {path = "./builtins_rust/mapfile"} +#printf = {path = "./builtins_rust/printf"} +#rreturn = {path = "./builtins_rust/rreturn"} +# shift = {path = "./builtins_rust/shift"} +#times = {path = "./builtins_rust/times"} +#suspend = {path = "./builtins_rust/suspend"} +# test = {path = "./builtins_rust/test"} +#trap = {path = "./builtins_rust/trap"} +#setattr = {path = "./builtins_rust/setattr"} +rcolon = {path = "./builtins_rust/colon"} + builtin = {path = "./builtins_rust/builtin"} + #alias= {path = "./builtins_rust/alias"} + exit = {path = "./builtins_rust/exit"} + rhelp = {path = "./builtins_rust/help"} + rcaller = {path = "./builtins_rust/caller"} + reval = {path = "./builtins_rust/eval"} + rexec = {path = "./builtins_rust/exec"} + rcommon = {path = "./builtins_rust/common"} + rcmd = {path = "builtins_rust/cmd"} + enable = {path = "builtins_rust/enable"} + rbreak = {path = "builtins_rust/break_1"} + rulimit = {path = "builtins_rust/ulimit"} + rtype = {path = "builtins_rust/type"} diff --git a/bash-5.1/Makefile.in b/bash-5.1/Makefile.in index 3d5119a07e9b5f44c74e9837c994ebfe89062f96..08d622a8f3c8181999176932a7188adebcff2f3f 100644 --- a/bash-5.1/Makefile.in +++ b/bash-5.1/Makefile.in @@ -104,10 +104,10 @@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ # The name of this program and some version information. -VERSPROG = bashversion$(EXEEXT) -VERSOBJ = bashversion.$(OBJEXT) +VERSPROG = rashversion$(EXEEXT) +VERSOBJ = rashversion.$(OBJEXT) -Program = bash$(EXEEXT) +Program = rash$(EXEEXT) Version = @BASHVERS@ PatchLevel = `$(BUILD_DIR)/$(VERSPROG) -p` RELSTATUS = @RELSTATUS@ @@ -127,7 +127,7 @@ THIS_SH = $(BUILD_DIR)/$(Program) # with gprof, or nothing (the default). PROFILE_FLAGS= @PROFILE_FLAGS@ -CFLAGS = @CFLAGS@ +CFLAGS = @CFLAGS@ -Wl,--copy-dt-needed-entries CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ @CROSS_COMPILE@ CPPFLAGS = @CPPFLAGS@ CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ @@ -138,7 +138,8 @@ LOCAL_DEFS = @LOCAL_DEFS@ LOCALE_DEFS = -DLOCALEDIR='"$(localedir)"' -DPACKAGE='"$(PACKAGE)"' LOCAL_LIBS = @LOCAL_LIBS@ -LIBS = $(BUILTINS_LIB) $(LIBRARIES) @LIBS@ +LIBS = $(BUILTINS_LIB) $(LIBRARIES) @LIBS@ -lrt -lpthread -L./target/debug -lrjobs -lrread -lrcd -lrfg_bg -lrfc -lrgetopts -lrcolon -lrbuiltin -lrexit -lrhelp -lralias -lrenable -lrdeclare -lrsetattr -lrbreak -lrtype -lrulimit -lrcaller -lreval -lrexec + LIBS_FOR_BUILD = STATIC_LD = @STATIC_LD@ @@ -149,7 +150,7 @@ SYSTEM_FLAGS = -DPROGRAM='"$(Program)"' -DCONF_HOSTTYPE='"$(Machine)"' -DCONF_OS BASE_CCFLAGS = $(SYSTEM_FLAGS) $(LOCAL_DEFS) \ $(DEFS) $(LOCAL_CFLAGS) $(INCLUDES) -CCFLAGS = $(ADDON_CFLAGS) $(BASE_CCFLAGS) ${PROFILE_FLAGS} $(CPPFLAGS) $(CFLAGS) +CCFLAGS = $(ADDON_CFLAGS) $(BASE_CCFLAGS) ${PROFILE_FLAGS} $(CPPFLAGS) $(CFLAGS) -Wl,--copy-dt-needed-entries CCFLAGS_FOR_BUILD = $(BASE_CCFLAGS) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) @@ -572,13 +573,18 @@ OTHER_INSTALLED_DOCS = CHANGES COMPAT NEWS POSIX RBASH README LOADABLES_DIR = ${top_builddir}/examples/loadables +RUST_DIR = $(top_builddir)/builtins_rust +RUST_BUILTINS_DIRS = $(RUST_DIR)/jobs $(RUST_DIR)/read $(RUST_DIR)/cd $(RUST_DIR)/fc $(RUST_DIR)/fg_bg $(RUST_DIR)/getopts $(RUST_DIR)/colon $(RUST_DIR)/builtin $(RUST_DIR)/exit $(RUST_DIR)/help $(RUST_DIR)/alias $(RUST_DIR)/enable $(RUST_DIR)/declare $(RUST_DIR)/setattr $(RUST_DIR)/break_1 $(RUST_DIR)/ulimit $(RUST_DIR)/type $(RUST_DIR)/caller $(RUST_DIR)/eval $(RUST_DIR)/exec +#RUST_TARGET_LIB = $(top_builddir)/target/debug/librjobs.a $(top_builddir)/target/debug/librread.a + + # Keep GNU Make from exporting the entire environment for small machines. .NOEXPORT: -.made: $(Program) bashbug $(SDIR)/man2html$(EXEEXT) +.made: $(Program) rashbug $(SDIR)/man2html$(EXEEXT) @echo "$(Program) last made for a $(Machine) running $(OS)" >.made -$(Program): .build $(OBJECTS) $(BUILTINS_DEP) $(LIBDEP) +$(Program): .build $(OBJECTS) $(BUILTINS_DEP) $(LIBDEP) rust_builtins_lib $(RM) $@ $(PURIFY) $(CC) $(BUILTINS_LDFLAGS) $(LIBRARY_LDFLAGS) $(LDFLAGS) -o $(Program) $(OBJECTS) $(LIBS) ls -l $(Program) @@ -593,10 +599,14 @@ $(Program): .build $(OBJECTS) $(BUILTINS_DEP) $(LIBDEP) @echo " ***********************************************************" @echo -bashbug: $(SDIR)/bashbug.sh $(VERSPROG) +rust_builtins_lib: + @for it in $(RUST_BUILTINS_DIRS); do cd $$it ; cargo build; cd -; done + + +rashbug: $(SDIR)/rashbug.sh $(VERSPROG) @sed -e "s%!PATCHLEVEL!%$(PatchLevel)%" \ - $(SDIR)/bashbug.sh > $@ - @chmod a+rx bashbug + $(SDIR)/rashbug.sh > $@ + @chmod a+rx rashbug strip: $(Program) .made $(STRIP) $(Program) @@ -629,8 +639,8 @@ version.h: $(SOURCES) config.h Makefile patchlevel.h $(SHELL) $(SUPPORT_SRC)mkversion.sh -b -S ${topdir} -s $(RELSTATUS) -d $(Version) -o newversion.h \ && mv newversion.h version.h -bashversion$(EXEEXT): buildversion.o $(SUPPORT_SRC)bashversion.c - $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) ${LDFLAGS_FOR_BUILD} -o $@ $(SUPPORT_SRC)bashversion.c buildversion.o ${LIBS_FOR_BUILD} +rashversion$(EXEEXT): buildversion.o $(SUPPORT_SRC)rashversion.c + $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) ${LDFLAGS_FOR_BUILD} -o $@ $(SUPPORT_SRC)rashversion.c buildversion.o ${LIBS_FOR_BUILD} buildversion.o: $(srcdir)/version.c $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -DBUILDTOOL -c -o $@ $(srcdir)/version.c @@ -823,7 +833,7 @@ installdirs: install: .made installdirs $(INSTALL_PROGRAM) $(INSTALLMODE) $(Program) $(DESTDIR)$(bindir)/$(Program) - $(INSTALL_SCRIPT) $(INSTALLMODE2) bashbug $(DESTDIR)$(bindir)/bashbug + $(INSTALL_SCRIPT) $(INSTALLMODE2) rashbug $(DESTDIR)$(bindir)/rashbug $(INSTALL_DATA) $(OTHER_DOCS) $(DESTDIR)$(docdir) -( cd $(DOCDIR) ; $(MAKE) $(MFLAGS) \ man1dir=$(man1dir) man1ext=$(man1ext) \ @@ -870,7 +880,7 @@ uninstall-headers: -( $(RM) $(DESTDIR)$(pkgconfigdir)/bash.pc ) uninstall: .made - $(RM) $(DESTDIR)$(bindir)/$(Program) $(DESTDIR)$(bindir)/bashbug + $(RM) $(DESTDIR)$(bindir)/$(Program) $(DESTDIR)$(bindir)/rashbug -( cd $(DESTDIR)$(docdir) && ${RM} ${OTHER_INSTALLED_DOCS} ) -( cd $(DOCDIR) ; $(MAKE) $(MFLAGS) \ man1dir=$(man1dir) man1ext=$(man1ext) \ @@ -885,8 +895,9 @@ LIB_SUBDIRS = ${RL_LIBDIR} ${HIST_LIBDIR} ${TERM_LIBDIR} ${GLOB_LIBDIR} \ ${INTL_LIBDIR} ${TILDE_LIBDIR} ${ALLOC_LIBDIR} ${SH_LIBDIR} basic-clean: - $(RM) $(OBJECTS) $(Program) bashbug + $(RM) $(OBJECTS) $(Program) rashbug $(RM) .build .made version.h + cargo clean clean: basic-clean ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ ) @@ -898,6 +909,7 @@ clean: basic-clean -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ ) -( cd $(LOADABLES_DIR) && $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ ) $(RM) $(CREATED_SUPPORT) + cargo clean mostlyclean: basic-clean ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ ) diff --git a/bash-5.1/_distribution b/bash-5.1/_distribution index 76e9e619d633967075525c0a9191d24f652f1c4b..49d59571fbf6e077eece30f8c418b6aad15e20b0 100644 --- a/bash-5.1/_distribution +++ b/bash-5.1/_distribution @@ -1 +1 @@ -5.1.4 +0.1 diff --git a/bash-5.1/build.md b/bash-5.1/build.md new file mode 100644 index 0000000000000000000000000000000000000000..346c8025ef905418d560b2ac70bf60c816dd8236 --- /dev/null +++ b/bash-5.1/build.md @@ -0,0 +1,15 @@ +# 生成rust重写指令的so +cargo build --release + +# 准备依赖库 +sudo mkdir -p /opt/rush/lib/ +sudo cp target/release/deps/*.so /opt/rush/lib/ + +# 配置链接库 +sudo cat > /etc/ld.so.conf.d/rush.conf << EOF +/opt/rush/lib +EOF +sudo ldconfig + +./configure +make diff --git a/bash-5.1/builtins/alias.def b/bash-5.1/builtins/alias.def index 0ab906964687aee01701813c8ba4a01a25ce3472..2d12e8097dd3b6d905b71796329bcd2273b8a44d 100644 --- a/bash-5.1/builtins/alias.def +++ b/bash-5.1/builtins/alias.def @@ -64,19 +64,21 @@ $END #define AL_REUSABLE 0x01 static void print_alias PARAMS((alias_t *, int)); +extern int r_alias_builtin ( register WORD_LIST *list); /* Hack the alias command in a Korn shell way. */ int alias_builtin (list) WORD_LIST *list; { + return r_alias_builtin(list); int any_failed, offset, pflag, dflags; alias_t **alias_list, *t; char *name, *value; dflags = posixly_correct ? 0 : AL_REUSABLE; pflag = 0; - reset_internal_getopt (); + reset_internal_getopt (); /*lhead = lcurrent = loptend = (WORD_LIST *)NULL; sp = 1;*/ while ((offset = internal_getopt (list, "p")) != -1) { switch (offset) @@ -110,7 +112,7 @@ alias_builtin (list) free (alias_list); /* XXX - Do not free the strings. */ if (list == 0) - return (sh_chkwrite (EXECUTION_SUCCESS)); + return (sh_chkwrite (EXECUTION_SUCCESS));//flush } any_failed = 0; @@ -123,8 +125,8 @@ alias_builtin (list) if (offset && name[offset] == '=') { - name[offset] = '\0'; - value = name + offset + 1; + name[offset] = '\0';//need cp to transfrom rust + value = name + offset + 1;//need cp to transfrom rust if (legal_alias_name (name, 0) == 0) { @@ -166,10 +168,12 @@ $END #if defined (ALIAS) /* Remove aliases named in LIST from the aliases database. */ +extern int r_unalias_builtin ( register WORD_LIST *list); int unalias_builtin (list) register WORD_LIST *list; { +return r_unalias_builtin (list); register alias_t *alias; int opt, aflag; diff --git a/bash-5.1/builtins/break.def b/bash-5.1/builtins/break.def index b73ed5e5bdf1097d2427cb05192b02a905847c5f..346b632def2e473aa80c544fb31e73b8e025dd76 100644 --- a/bash-5.1/builtins/break.def +++ b/bash-5.1/builtins/break.def @@ -47,6 +47,7 @@ $END #include "common.h" static int check_loop_level PARAMS((void)); +extern int r_break_builtin PARAMS((WORD_LIST *)); /* The depth of while's and until's. */ int loop_level = 0; @@ -63,6 +64,7 @@ int break_builtin (list) WORD_LIST *list; { + return r_break_builtin(list); intmax_t newbreak; CHECK_HELPOPT (list); @@ -141,3 +143,28 @@ check_loop_level () return (loop_level); } + +extern void set_loop_level(int i) +{ + loop_level = i; +} +extern int get_loop_level(void ) +{ + return loop_level; +} +extern void set_continuing(int i) +{ + continuing = i; +} +extern int get_continuing() +{ + return continuing; +} +extern void set_breaking(int i) +{ + breaking = i ; +} +extern int get_breaking() +{ + return breaking; +} diff --git a/bash-5.1/builtins/builtin.c b/bash-5.1/builtins/builtin.c new file mode 100644 index 0000000000000000000000000000000000000000..eff88dc21ec6f7fc48ae2eab0b629eda6c7bb9c5 --- /dev/null +++ b/bash-5.1/builtins/builtin.c @@ -0,0 +1,57 @@ +/* builtin.c, created from builtin.def. */ +#line 22 "./builtin.def" + +#line 36 "./builtin.def" +#include + +#if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif +# include +#endif + +#include "../shell.h" +#include "../execute_cmd.h" +#include "common.h" +#include "bashgetopt.h" + +extern int r_builtin_builtin ( WORD_LIST *list); + +/* Run the command mentioned in list directly, without going through the + normal alias/function/builtin/filename lookup process. */ +int +builtin_builtin (list) + WORD_LIST *list; +{ +return r_builtin_builtin (list); + sh_builtin_func_t *function; + register char *command; + + if (no_options (list)) + return (EX_USAGE); + list = loptend; /* skip over possible `--' */ + + if (list == 0) + return (EXECUTION_SUCCESS); + + command = list->word->word; +#if defined (DISABLED_BUILTINS) + function = builtin_address (command); +#else /* !DISABLED_BUILTINS */ + function = find_shell_builtin (command); +#endif /* !DISABLED_BUILTINS */ + + if (function == 0) + { + sh_notbuiltin (command); + return (EXECUTION_FAILURE); + } + else + { + this_command_name = command; + this_shell_builtin = function; /* overwrite "builtin" as this builtin */ + list = list->next; + return ((*function) (list)); + } +} diff --git a/bash-5.1/builtins/builtin.def b/bash-5.1/builtins/builtin.def index 74060ee09f00a4108f5fb358c7706d5a1e1083fa..c2c5d13ac5daa90da455b284cd984d39f9186f6d 100644 --- a/bash-5.1/builtins/builtin.def +++ b/bash-5.1/builtins/builtin.def @@ -47,12 +47,15 @@ $END #include "common.h" #include "bashgetopt.h" +extern int r_builtin_builtin ( WORD_LIST *list); + /* Run the command mentioned in list directly, without going through the normal alias/function/builtin/filename lookup process. */ int builtin_builtin (list) WORD_LIST *list; { +return r_builtin_builtin (list); sh_builtin_func_t *function; register char *command; diff --git a/bash-5.1/builtins/caller.def b/bash-5.1/builtins/caller.def index 1000979dd90b60aba6e6ce83dc8962edcb57f881..31a3d589f493461b06fc7049b6718c7e1b570e83 100644 --- a/bash-5.1/builtins/caller.def +++ b/bash-5.1/builtins/caller.def @@ -39,7 +39,7 @@ Returns 0 unless the shell is not executing a shell function or EXPR is invalid. $END -#include +#include #include #include "chartypes.h" #include "bashtypes.h" @@ -68,67 +68,13 @@ $END extern int errno; #endif /* !errno */ +extern int r_caller_builtin(WORD_LIST *); + int caller_builtin (list) WORD_LIST *list; { -#if !defined (ARRAY_VARS) - printf ("1 NULL\n"); - return (EXECUTION_FAILURE); -#else - SHELL_VAR *funcname_v, *bash_source_v, *bash_lineno_v; - ARRAY *funcname_a, *bash_source_a, *bash_lineno_a; - char *funcname_s, *source_s, *lineno_s; - intmax_t num; - - CHECK_HELPOPT (list); - - GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a); - GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a); - GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a); - - if (bash_lineno_a == 0 || array_empty (bash_lineno_a)) - return (EXECUTION_FAILURE); - - if (bash_source_a == 0 || array_empty (bash_source_a)) - return (EXECUTION_FAILURE); - - if (no_options (list)) - return (EX_USAGE); - list = loptend; /* skip over possible `--' */ - - /* If there is no argument list, then give short form: line filename. */ - if (list == 0) - { - lineno_s = array_reference (bash_lineno_a, 0); - source_s = array_reference (bash_source_a, 1); - printf("%s %s\n", lineno_s ? lineno_s : "NULL", source_s ? source_s : "NULL"); - return (EXECUTION_SUCCESS); - } - - if (funcname_a == 0 || array_empty (funcname_a)) - return (EXECUTION_FAILURE); - - if (legal_number (list->word->word, &num)) - { - lineno_s = array_reference (bash_lineno_a, num); - source_s = array_reference (bash_source_a, num+1); - funcname_s = array_reference (funcname_a, num+1); - - if (lineno_s == NULL|| source_s == NULL || funcname_s == NULL) - return (EXECUTION_FAILURE); - - printf("%s %s %s\n", lineno_s, funcname_s, source_s); - } - else - { - sh_invalidnum (list->word->word); - builtin_usage (); - return (EX_USAGE); - } - - return (EXECUTION_SUCCESS); -#endif + r_caller_builtin(list); } #ifdef LOADABLE_BUILTIN diff --git a/bash-5.1/builtins/cd.def b/bash-5.1/builtins/cd.def index 7205608c672239ba4119a5b6b0252212f2130360..b7044bd700045d55a48a55ee76ef0c582e63f6a7 100644 --- a/bash-5.1/builtins/cd.def +++ b/bash-5.1/builtins/cd.def @@ -263,10 +263,13 @@ resetxattr () change the current working directory. It is called by cd_to_string (), so the programming interface is simple, and it handles errors and restrictions properly. */ +extern int r_cd_builtin (WORD_LIST *list); + int cd_builtin (list) WORD_LIST *list; { +return r_cd_builtin(list); char *dirname, *cdpath, *path, *temp; int path_index, no_symlinks, opt, lflag, e; @@ -485,6 +488,7 @@ int pwd_builtin (list) WORD_LIST *list; { +return r_pwd_builtin(list); char *directory; int opt, pflag; diff --git a/bash-5.1/builtins/colon.def b/bash-5.1/builtins/colon.def index 6891b0799f14a74ebb195916f55c617a5632b03c..94d6e85bc339f38d249db0d8d2e982fbebe9865d 100644 --- a/bash-5.1/builtins/colon.def +++ b/bash-5.1/builtins/colon.def @@ -59,11 +59,15 @@ $END #include "../bashansi.h" #include "../shell.h" +extern r_colon_builtin(ignore); +extern r_false_builtin(ignore); /* Return a successful result. */ int colon_builtin (ignore) WORD_LIST *ignore; { + printf("colon builtin\n"); + r_colon_builtin(ignore); return (0); } @@ -72,5 +76,7 @@ int false_builtin (ignore) WORD_LIST *ignore; { + printf("in false builtin\n"); + r_false_builtin(ignore); return (1); } diff --git a/bash-5.1/builtins/enable.def b/bash-5.1/builtins/enable.def index 9d9010b78ddc431f1091334e196f8008bda28946..9767c353a2f3cb101562c3722e43da0b199a1d56 100644 --- a/bash-5.1/builtins/enable.def +++ b/bash-5.1/builtins/enable.def @@ -104,10 +104,12 @@ static int enable_shell_command PARAMS((char *, int)); /* Enable/disable shell commands present in LIST. If list is not specified, then print out a list of shell commands showing which are enabled and which are disabled. */ +extern int r_enable_builtin ( WORD_LIST *list); int enable_builtin (list) WORD_LIST *list; { +return r_enable_builtin(list); int result, flags; int opt, filter; #if defined (HAVE_DLOPEN) && defined (HAVE_DLSYM) @@ -311,6 +313,7 @@ dyn_load_builtin (list, flags, filename) #endif handle = 0; + //没找到 if (absolute_program (filename) == 0) { loadables_path = get_string_value ("BASH_LOADABLES_PATH"); diff --git a/bash-5.1/builtins/eval.def b/bash-5.1/builtins/eval.def index a92b538f26bd8f01bfbbceb369a173dfce3f9c7f..71b3b8f35c4d29e6c6848b741c9395585fc667db 100644 --- a/bash-5.1/builtins/eval.def +++ b/bash-5.1/builtins/eval.def @@ -45,13 +45,12 @@ $END #include "common.h" /* Parse the string that these words make, and execute the command found. */ +extern int r_eval_builtin(WORD_LIST *); + int eval_builtin (list) WORD_LIST *list; { - if (no_options (list)) - return (EX_USAGE); - list = loptend; /* skip over possible `--' */ + r_eval_builtin(list); - return (list ? evalstring (string_list (list), "eval", SEVAL_NOHIST) : EXECUTION_SUCCESS); } diff --git a/bash-5.1/builtins/exec.def b/bash-5.1/builtins/exec.def index cbcb641a68ad2cc847f4244885ceb1cc06ef327e..3713c998df812f9811496548bb45588c35625858 100644 --- a/bash-5.1/builtins/exec.def +++ b/bash-5.1/builtins/exec.def @@ -84,190 +84,12 @@ int no_exit_on_failed_exec; /* If the user wants this to look like a login shell, then prepend a `-' onto NAME and return the new name. */ -static char * -mkdashname (name) - char *name; -{ - char *ret; - ret = (char *)xmalloc (2 + strlen (name)); - ret[0] = '-'; - strcpy (ret + 1, name); - return ret; -} +extern int r_exec_builtin(WORD_LIST *); int exec_builtin (list) WORD_LIST *list; { - int exit_value = EXECUTION_FAILURE; - int cleanenv, login, opt, orig_job_control; - char *argv0, *command, **args, **env, *newname, *com2; - - cleanenv = login = 0; - exec_argv0 = argv0 = (char *)NULL; - - reset_internal_getopt (); - while ((opt = internal_getopt (list, "cla:")) != -1) - { - switch (opt) - { - case 'c': - cleanenv = 1; - break; - case 'l': - login = 1; - break; - case 'a': - argv0 = list_optarg; - break; - CASE_HELPOPT; - default: - builtin_usage (); - return (EX_USAGE); - } - } - list = loptend; - - /* First, let the redirections remain. */ - dispose_redirects (redirection_undo_list); - redirection_undo_list = (REDIRECT *)NULL; - - if (list == 0) - return (EXECUTION_SUCCESS); - -#if defined (RESTRICTED_SHELL) - if (restricted) - { - sh_restricted ((char *)NULL); - return (EXECUTION_FAILURE); - } -#endif /* RESTRICTED_SHELL */ - - args = strvec_from_word_list (list, 1, 0, (int *)NULL); - env = (char **)0; - - /* A command with a slash anywhere in its name is not looked up in $PATH. */ - command = absolute_program (args[0]) ? args[0] : search_for_command (args[0], 1); - - if (command == 0) - { - if (file_isdir (args[0])) - { -#if defined (EISDIR) - builtin_error (_("%s: cannot execute: %s"), args[0], strerror (EISDIR)); -#else - builtin_error (_("%s: cannot execute: %s"), args[0], strerror (errno)); -#endif - exit_value = EX_NOEXEC; - } - else - { - sh_notfound (args[0]); - exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */ - } - goto failed_exec; - } - - com2 = full_pathname (command); - if (com2) - { - if (command != args[0]) - free (command); - command = com2; - } - - if (argv0) - { - free (args[0]); - args[0] = login ? mkdashname (argv0) : savestring (argv0); - exec_argv0 = savestring (args[0]); - } - else if (login) - { - newname = mkdashname (args[0]); - free (args[0]); - args[0] = newname; - } - - /* Decrement SHLVL by 1 so a new shell started here has the same value, - preserving the appearance. After we do that, we need to change the - exported environment to include the new value. If we've already forked - and are in a subshell, we don't want to decrement the shell level, - since we are `increasing' the level */ - - if (cleanenv == 0 && (subshell_environment & SUBSHELL_PAREN) == 0) - adjust_shell_level (-1); - - if (cleanenv) - { - env = strvec_create (1); - env[0] = (char *)0; - } - else - { - maybe_make_export_env (); - env = export_env; - } - -#if defined (HISTORY) - if (interactive_shell && subshell_environment == 0) - maybe_save_shell_history (); -#endif /* HISTORY */ - - restore_original_signals (); - -#if defined (JOB_CONTROL) - orig_job_control = job_control; /* XXX - was also interactive_shell */ - if (subshell_environment == 0) - end_job_control (); - if (interactive || job_control) - default_tty_job_signals (); /* undo initialize_job_signals */ -#endif /* JOB_CONTROL */ - -#if defined (BUFFERED_INPUT) - if (default_buffered_input >= 0) - sync_buffered_stream (default_buffered_input); -#endif - - exit_value = shell_execve (command, args, env); - - /* We have to set this to NULL because shell_execve has called realloc() - to stuff more items at the front of the array, which may have caused - the memory to be freed by realloc(). We don't want to free it twice. */ - args = (char **)NULL; - if (cleanenv == 0) - adjust_shell_level (1); - - if (exit_value == EX_NOTFOUND) /* no duplicate error message */ - goto failed_exec; - else if (executable_file (command) == 0) - { - builtin_error (_("%s: cannot execute: %s"), command, strerror (errno)); - exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */ - } - else - file_error (command); - -failed_exec: - FREE (command); - - if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0)) - exit_shell (exit_value); - - if (args) - strvec_dispose (args); - - if (env && env != export_env) - strvec_dispose (env); - - initialize_traps (); - initialize_signals (1); - -#if defined (JOB_CONTROL) - if (orig_job_control) - restart_job_control (); -#endif /* JOB_CONTROL */ - - return (exit_value); + r_exec_builtin(list); } diff --git a/bash-5.1/builtins/exit.def b/bash-5.1/builtins/exit.def index dc6f3d5b66e1f5f4a104ed0a915fed0bbc2426c7..d79bcd655b3eab11a0c5d70e9cd2b09bb88f1287 100644 --- a/bash-5.1/builtins/exit.def +++ b/bash-5.1/builtins/exit.def @@ -53,10 +53,13 @@ extern int check_jobs_at_exit; static int exit_or_logout PARAMS((WORD_LIST *)); static int sourced_logout; +int r_exit_builtin ( WORD_LIST *list); int exit_builtin (list) WORD_LIST *list; { +printf("exit_builtin\n"); +r_exit_builtin(list); CHECK_HELPOPT (list); if (interactive) @@ -77,11 +80,14 @@ Exits a login shell with exit status N. Returns an error if not executed in a login shell. $END +int r_logout_builtin ( WORD_LIST *list); /* How to logout. */ int logout_builtin (list) WORD_LIST *list; { +printf("LOGOUT_BUILTIN\n"); + r_logout_builtin(list); CHECK_HELPOPT (list); if (login_shell == 0 /* && interactive */) diff --git a/bash-5.1/builtins/fc.def b/bash-5.1/builtins/fc.def index 467dbcbcc33a89b02e228dd442f5c221a02b22bf..3a164ee9e2aca0a2023e4f7e9d2d8cc3a825ed94 100644 --- a/bash-5.1/builtins/fc.def +++ b/bash-5.1/builtins/fc.def @@ -177,11 +177,16 @@ set_verbose_flag () #else # define POSIX_FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-ed}}" #endif +extern int +r_fc_builtin ( + WORD_LIST *list); int fc_builtin (list) WORD_LIST *list; { +return r_fc_builtin (list); + register int i; register char *sep; int numbering, reverse, listing, execute; diff --git a/bash-5.1/builtins/fg_bg.def b/bash-5.1/builtins/fg_bg.def index 0fb53223d447cbc93328337ec5b4e8809c2d4e7d..f50ecd0949acb8b2173f0853a970943ff2cb90a4 100644 --- a/bash-5.1/builtins/fg_bg.def +++ b/bash-5.1/builtins/fg_bg.def @@ -56,9 +56,13 @@ static int fg_bg PARAMS((WORD_LIST *, int)); /* How to bring a job into the foreground. */ int +r_fg_builtin ( + WORD_LIST *list); +int fg_builtin (list) WORD_LIST *list; { +return r_fg_builtin (list); int fg_bit; register WORD_LIST *t; diff --git a/bash-5.1/builtins/getopts.def b/bash-5.1/builtins/getopts.def index 4c39c474cca04c679f93ff143d51fef6eea14300..71ee1b29867dc90ed02728f0db1ab4217c762ad0 100644 --- a/bash-5.1/builtins/getopts.def +++ b/bash-5.1/builtins/getopts.def @@ -311,10 +311,14 @@ dogetopts (argc, argv) } /* The getopts builtin. Build an argv, and call dogetopts with it. */ +extern int +r_getopts_builtin ( + WORD_LIST *list); int getopts_builtin (list) WORD_LIST *list; { + return r_getopts_builtin(list); char **av; int ac, ret; diff --git a/bash-5.1/builtins/help.def b/bash-5.1/builtins/help.def index f33b2b9352189a3cbb7bad692d3fe0929d490826..62469194d05b8d9ab8c9ff46f27e873160bb9ef9 100644 --- a/bash-5.1/builtins/help.def +++ b/bash-5.1/builtins/help.def @@ -88,10 +88,20 @@ static void show_longdoc PARAMS((int)); /* Print out a list of the known functions in the shell, and what they do. If LIST is supplied, print out the list which matches for each pattern specified. */ +extern int r_help_builtin ( WORD_LIST *list); +extern int r_help_null_builtin ( WORD_LIST *list); int help_builtin (list) WORD_LIST *list; { + if (list) + { + return r_help_builtin(list); + } + else + { + return r_help_null_builtin(list); + } register int i; char *pattern, *name; int plen, match_found, sflag, dflag, mflag, m, pass, this_found; diff --git a/bash-5.1/builtins/jobs.def b/bash-5.1/builtins/jobs.def index 1ce098d08be2b1a72b1f89284bcad48021778df0..0d9fe03d44e3cb99f8eb6258c9b7f439a5050737 100644 --- a/bash-5.1/builtins/jobs.def +++ b/bash-5.1/builtins/jobs.def @@ -78,10 +78,12 @@ static int execute_list_with_replacements PARAMS((WORD_LIST *)); replace all job specs with the pid of the appropriate process group leader and execute the command. The -r and -s options mean to print info about running and stopped jobs only, respectively. */ +extern int r_jobs_builtin(list); int jobs_builtin (list) WORD_LIST *list; { + return r_jobs_builtin(list); int form, execute, state, opt, any_failed, job; sigset_t set, oset; diff --git a/bash-5.1/builtins/read.def b/bash-5.1/builtins/read.def index 6e1f53751118c92ec8349a7c0648f46fdcb61bfd..b28ed06f60a416864445ca94643617a18b9cce69 100644 --- a/bash-5.1/builtins/read.def +++ b/bash-5.1/builtins/read.def @@ -1,3 +1,23 @@ +This file is read.def, from which is created read.c. +It implements the builtin "read" in Bash. + +Copyright (C) 1987-2020 Free Software Foundation, Inc. + +This file is part of GNU Bash, the Bourne Again SHell. + +Bash 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. + +Bash 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 Bash. If not, see . + $PRODUCES read.c $BUILTIN read @@ -92,11 +112,59 @@ $END extern int errno; #endif -extern int r_read_builtin (WORD_LIST *); +struct ttsave +{ + int fd; + TTYSTRUCT attrs; +}; +#if defined (READLINE) +static void reset_attempted_completion_function PARAMS((char *)); +static int set_itext PARAMS((void)); +static char *edit_line PARAMS((char *, char *)); +static void set_eol_delim PARAMS((int)); +static void reset_eol_delim PARAMS((char *)); +#endif +static SHELL_VAR *bind_read_variable PARAMS((char *, char *)); +#if defined (HANDLE_MULTIBYTE) +static int read_mbchar PARAMS((int, char *, int, int, int)); +#endif +static void ttyrestore PARAMS((struct ttsave *)); + +static sighandler sigalrm PARAMS((int)); +static void reset_alarm PARAMS((void)); + +/* Try this to see what the rest of the shell can do with the information. */ procenv_t alrmbuf; int sigalrm_seen; +static int reading, tty_modified; +static SigHandler *old_alrm; +static unsigned char delim; + +static struct ttsave termsave; + +/* In all cases, SIGALRM just sets a flag that we check periodically. This + avoids problems with the semi-tricky stuff we do with the xfree of + input_string at the top of the unwind-protect list (see below). */ + +/* Set a flag that CHECK_ALRM can check. This relies on zread or read_builtin + calling trap.c:check_signals(), which knows about sigalrm_seen and alrmbuf. */ +static sighandler +sigalrm (s) + int s; +{ + sigalrm_seen = 1; +} + +static void +reset_alarm () +{ + /* Cancel alarm before restoring signal handler. */ + falarm (0, 0); + set_signal_handler (SIGALRM, old_alrm); +} + /* Read the value of the shell variables whose names follow. The reading is done from the current input stream, whatever that may be. Successive words of the input line are assigned @@ -107,18 +175,1022 @@ int read_builtin (list) WORD_LIST *list; { - r_read_builtin(list); + return r_read_builtin(list); +} +int +__read_builtin (list) + WORD_LIST *list; +{ + register char *varname; + int size, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2, nflag; + volatile int i; + int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul; + int raw, edit, nchars, silent, have_timeout, ignore_delim, fd; + int lastsig, t_errno; + int mb_cur_max; + unsigned int tmsec, tmusec; + long ival, uval; + intmax_t intval; + char c; + char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname; + char *e, *t, *t1, *ps2, *tofree; + struct stat tsb; + SHELL_VAR *var; + TTYSTRUCT ttattrs, ttset; +#if defined (ARRAY_VARS) + WORD_LIST *alist; + int vflags; +#endif +#if defined (READLINE) + char *rlbuf, *itext; + int rlind; + FILE *save_instream; +#endif + + USE_VAR(size); + USE_VAR(i); + USE_VAR(pass_next); + USE_VAR(print_ps2); + USE_VAR(saw_escape); + USE_VAR(input_is_pipe); +/* USE_VAR(raw); */ + USE_VAR(edit); + USE_VAR(tmsec); + USE_VAR(tmusec); + USE_VAR(nchars); + USE_VAR(silent); + USE_VAR(ifs_chars); + USE_VAR(prompt); + USE_VAR(arrayname); +#if defined (READLINE) + USE_VAR(rlbuf); + USE_VAR(rlind); + USE_VAR(itext); +#endif + USE_VAR(list); + USE_VAR(ps2); + USE_VAR(lastsig); + + sigalrm_seen = reading = tty_modified = 0; + + i = 0; /* Index into the string that we are reading. */ + raw = edit = 0; /* Not reading raw input by default. */ + silent = 0; + arrayname = prompt = (char *)NULL; + fd = 0; /* file descriptor to read from */ + +#if defined (READLINE) + rlbuf = itext = (char *)0; + rlind = 0; +#endif + + mb_cur_max = MB_CUR_MAX; + tmsec = tmusec = 0; /* no timeout */ + nr = nchars = input_is_tty = input_is_pipe = unbuffered_read = have_timeout = 0; + delim = '\n'; /* read until newline */ + ignore_delim = nflag = 0; + + reset_internal_getopt (); + while ((opt = internal_getopt (list, "ersa:d:i:n:p:t:u:N:")) != -1) + { + switch (opt) + { + case 'r': + raw = 1; + break; + case 'p': + prompt = list_optarg; + break; + case 's': + silent = 1; + break; + case 'e': +#if defined (READLINE) + edit = 1; +#endif + break; + case 'i': +#if defined (READLINE) + itext = list_optarg; +#endif + break; +#if defined (ARRAY_VARS) + case 'a': + arrayname = list_optarg; + break; +#endif + case 't': + code = uconvert (list_optarg, &ival, &uval, (char **)NULL); + if (code == 0 || ival < 0 || uval < 0) + { + builtin_error (_("%s: invalid timeout specification"), list_optarg); + return (EXECUTION_FAILURE); + } + else + { + have_timeout = 1; + tmsec = ival; + tmusec = uval; + } + break; + case 'N': + ignore_delim = 1; + delim = -1; + case 'n': + nflag = 1; + code = legal_number (list_optarg, &intval); + if (code == 0 || intval < 0 || intval != (int)intval) + { + sh_invalidnum (list_optarg); + return (EXECUTION_FAILURE); + } + else + nchars = intval; + break; + case 'u': + code = legal_number (list_optarg, &intval); + if (code == 0 || intval < 0 || intval != (int)intval) + { + builtin_error (_("%s: invalid file descriptor specification"), list_optarg); + return (EXECUTION_FAILURE); + } + else + fd = intval; + if (sh_validfd (fd) == 0) + { + builtin_error (_("%d: invalid file descriptor: %s"), fd, strerror (errno)); + return (EXECUTION_FAILURE); + } + break; + case 'd': + delim = *list_optarg; + break; + CASE_HELPOPT; + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + + /* `read -t 0 var' tests whether input is available with select/FIONREAD, + and fails if those are unavailable */ + if (have_timeout && tmsec == 0 && tmusec == 0) +#if 0 + return (EXECUTION_FAILURE); +#else + return (input_avail (fd) ? EXECUTION_SUCCESS : EXECUTION_FAILURE); +#endif + + /* Convenience: check early whether or not the first of possibly several + variable names is a valid identifier, and bail early if so. */ +#if defined (ARRAY_VARS) + vflags = assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0; + if (list && legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word, vflags) == 0) +#else + if (list && legal_identifier (list->word->word) == 0) +#endif + { + sh_invalidid (list->word->word); + return (EXECUTION_FAILURE); + } + + /* If we're asked to ignore the delimiter, make sure we do. */ + if (ignore_delim) + delim = -1; + + /* IF IFS is unset, we use the default of " \t\n". */ + ifs_chars = getifs (); + if (ifs_chars == 0) /* XXX - shouldn't happen */ + ifs_chars = ""; + /* If we want to read exactly NCHARS chars, don't split on IFS */ + if (ignore_delim) + ifs_chars = ""; + for (skip_ctlesc = skip_ctlnul = 0, e = ifs_chars; *e; e++) + skip_ctlesc |= *e == CTLESC, skip_ctlnul |= *e == CTLNUL; + + input_string = (char *)xmalloc (size = 112); /* XXX was 128 */ + input_string[0] = '\0'; + + /* More input and options validation */ + if (nflag == 1 && nchars == 0) + { + retval = read (fd, &c, 0); + retval = (retval >= 0) ? EXECUTION_SUCCESS : EXECUTION_FAILURE; + goto assign_vars; /* bail early if asked to read 0 chars */ + } + + /* $TMOUT, if set, is the default timeout for read. */ + if (have_timeout == 0 && (e = get_string_value ("TMOUT"))) + { + code = uconvert (e, &ival, &uval, (char **)NULL); + if (code == 0 || ival < 0 || uval < 0) + tmsec = tmusec = 0; + else + { + tmsec = ival; + tmusec = uval; + } + } + + begin_unwind_frame ("read_builtin"); + +#if defined (BUFFERED_INPUT) + if (interactive == 0 && default_buffered_input >= 0 && fd_is_bash_input (fd)) + sync_buffered_stream (default_buffered_input); +#endif + +#if 1 + input_is_tty = isatty (fd); +#else + input_is_tty = 1; +#endif + if (input_is_tty == 0) +#ifndef __CYGWIN__ + input_is_pipe = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE); +#else + input_is_pipe = 1; +#endif + + /* If the -p, -e or -s flags were given, but input is not coming from the + terminal, turn them off. */ + if ((prompt || edit || silent) && input_is_tty == 0) + { + prompt = (char *)NULL; +#if defined (READLINE) + itext = (char *)NULL; +#endif + edit = silent = 0; + } + +#if defined (READLINE) + if (edit) + add_unwind_protect (xfree, rlbuf); +#endif + + pass_next = 0; /* Non-zero signifies last char was backslash. */ + saw_escape = 0; /* Non-zero signifies that we saw an escape char */ + + if (tmsec > 0 || tmusec > 0) + { + /* Turn off the timeout if stdin is a regular file (e.g. from + input redirection). */ + if ((fstat (fd, &tsb) < 0) || S_ISREG (tsb.st_mode)) + tmsec = tmusec = 0; + } + + if (tmsec > 0 || tmusec > 0) + { + code = setjmp_nosigs (alrmbuf); + if (code) + { + sigalrm_seen = 0; + /* Tricky. The top of the unwind-protect stack is the free of + input_string. We want to run all the rest and use input_string, + so we have to save input_string temporarily, run the unwind- + protects, then restore input_string so we can use it later */ + orig_input_string = 0; + input_string[i] = '\0'; /* make sure it's terminated */ + if (i == 0) + { + t = (char *)xmalloc (1); + t[0] = 0; + } + else + t = savestring (input_string); + + run_unwind_frame ("read_builtin"); + input_string = t; + retval = 128+SIGALRM; + goto assign_vars; + } + if (interactive_shell == 0) + initialize_terminating_signals (); + old_alrm = set_signal_handler (SIGALRM, sigalrm); + add_unwind_protect (reset_alarm, (char *)NULL); +#if defined (READLINE) + if (edit) + { + add_unwind_protect (reset_attempted_completion_function, (char *)NULL); + add_unwind_protect (bashline_reset_event_hook, (char *)NULL); + } +#endif + falarm (tmsec, tmusec); + } + + /* If we've been asked to read only NCHARS chars, or we're using some + character other than newline to terminate the line, do the right + thing to readline or the tty. */ + if (nchars > 0 || delim != '\n') + { +#if defined (READLINE) + if (edit) + { + if (nchars > 0) + { + unwind_protect_int (rl_num_chars_to_read); + rl_num_chars_to_read = nchars; + } + if (delim != '\n') + { + set_eol_delim (delim); + add_unwind_protect (reset_eol_delim, (char *)NULL); + } + } + else +#endif + if (input_is_tty) + { + /* ttsave() */ + termsave.fd = fd; + ttgetattr (fd, &ttattrs); + termsave.attrs = ttattrs; + + ttset = ttattrs; + i = silent ? ttfd_cbreak (fd, &ttset) : ttfd_onechar (fd, &ttset); + if (i < 0) + sh_ttyerror (1); + tty_modified = 1; + add_unwind_protect ((Function *)ttyrestore, (char *)&termsave); + if (interactive_shell == 0) + initialize_terminating_signals (); + } + } + else if (silent) /* turn off echo but leave term in canonical mode */ + { + /* ttsave (); */ + termsave.fd = fd; + ttgetattr (fd, &ttattrs); + termsave.attrs = ttattrs; + + ttset = ttattrs; + i = ttfd_noecho (fd, &ttset); /* ttnoecho (); */ + if (i < 0) + sh_ttyerror (1); + + tty_modified = 1; + add_unwind_protect ((Function *)ttyrestore, (char *)&termsave); + if (interactive_shell == 0) + initialize_terminating_signals (); + } + +#if defined (READLINE) + save_instream = 0; + if (edit && fd != 0) + { + if (bash_readline_initialized == 0) + initialize_readline (); + + unwind_protect_var (rl_instream); + save_instream = rl_instream; + rl_instream = fdopen (fd, "r"); + } +#endif + + /* This *must* be the top unwind-protect on the stack, so the manipulation + of the unwind-protect stack after the realloc() works right. */ + add_unwind_protect (xfree, input_string); + + CHECK_ALRM; + if ((nchars > 0) && (input_is_tty == 0) && ignore_delim) /* read -N */ + unbuffered_read = 2; + else if ((nchars > 0) || (delim != '\n') || input_is_pipe) + unbuffered_read = 1; + + if (prompt && edit == 0) + { + fprintf (stderr, "%s", prompt); + fflush (stderr); + } + +#if defined (__CYGWIN__) && defined (O_TEXT) + setmode (0, O_TEXT); +#endif + + ps2 = 0; + for (print_ps2 = eof = retval = 0;;) + { + CHECK_ALRM; + +#if defined (READLINE) + if (edit) + { + /* If we have a null delimiter, don't treat NULL as ending the line */ + if (rlbuf && rlbuf[rlind] == '\0' && delim != '\0') + { + free (rlbuf); + rlbuf = (char *)0; + } + if (rlbuf == 0) + { + reading = 1; + rlbuf = edit_line (prompt ? prompt : "", itext); + reading = 0; + rlind = 0; + } + if (rlbuf == 0) + { + eof = 1; + break; + } + c = rlbuf[rlind++]; + } + else + { +#endif + + if (print_ps2) + { + if (ps2 == 0) + ps2 = get_string_value ("PS2"); + fprintf (stderr, "%s", ps2 ? ps2 : ""); + fflush (stderr); + print_ps2 = 0; + } + + reading = 1; + CHECK_ALRM; + errno = 0; + if (unbuffered_read == 2) + retval = posixly_correct ? zreadintr (fd, &c, 1) : zreadn (fd, &c, nchars - nr); + else if (unbuffered_read) + retval = posixly_correct ? zreadintr (fd, &c, 1) : zread (fd, &c, 1); + else + retval = posixly_correct ? zreadcintr (fd, &c) : zreadc (fd, &c); + reading = 0; + + if (retval <= 0) + { + int t; + + t = errno; + if (retval < 0 && errno == EINTR) + { + check_signals (); /* in case we didn't call zread via zreadc */ + lastsig = LASTSIG(); + if (lastsig == 0) + lastsig = trapped_signal_received; +#if 0 + run_pending_traps (); /* because interrupt_immediately is not set */ +#endif + } + else + lastsig = 0; + if (terminating_signal && tty_modified) + ttyrestore (&termsave); /* fix terminal before exiting */ + CHECK_TERMSIG; + eof = 1; + errno = t; /* preserve it for the error message below */ + break; + } + + QUIT; /* in case we didn't call check_signals() */ +#if defined (READLINE) + } +#endif + + if (retval <= 0) /* XXX shouldn't happen */ + CHECK_ALRM; + + /* XXX -- use i + mb_cur_max (at least 4) for multibyte/read_mbchar */ + if (i + (mb_cur_max > 4 ? mb_cur_max : 4) >= size) + { + char *t; + t = (char *)xrealloc (input_string, size += 128); + + /* Only need to change unwind-protect if input_string changes */ + if (t != input_string) + { + input_string = t; + remove_unwind_protect (); + add_unwind_protect (xfree, input_string); + } + } + + /* If the next character is to be accepted verbatim, a backslash + newline pair still disappears from the input. */ + if (pass_next) + { + pass_next = 0; + if (c == '\n') + { + if (skip_ctlesc == 0 && i > 0) + i--; /* back up over the CTLESC */ + if (interactive && input_is_tty && raw == 0) + print_ps2 = 1; + } + else + goto add_char; + continue; + } + + /* This may cause problems if IFS contains CTLESC */ + if (c == '\\' && raw == 0) + { + pass_next++; + if (skip_ctlesc == 0) + { + saw_escape++; + input_string[i++] = CTLESC; + } + continue; + } + + if (ignore_delim == 0 && (unsigned char)c == delim) + break; + + if (c == '\0' && delim != '\0') + continue; /* skip NUL bytes in input */ + + if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL)) + { + saw_escape++; + input_string[i++] = CTLESC; + } + +add_char: + input_string[i++] = c; + CHECK_ALRM; + +#if defined (HANDLE_MULTIBYTE) + /* XXX - what if C == 127? Can DEL introduce a multibyte sequence? */ + if (mb_cur_max > 1 && is_basic (c) == 0) + { + input_string[i] = '\0'; /* for simplicity and debugging */ + /* If we got input from readline, grab the next multibyte char from + rlbuf. */ +# if defined (READLINE) + if (edit) + { + size_t clen; + clen = mbrlen (rlbuf + rlind - 1, mb_cur_max, (mbstate_t *)NULL); + /* We only deal with valid multibyte sequences longer than one + byte. If we get anything else, we leave the one character + copied and move on to the next. */ + if ((int)clen > 1) + { + memcpy (input_string+i, rlbuf+rlind, clen-1); + i += clen - 1; + rlind += clen - 1; + } + } + else +# endif + if (locale_utf8locale == 0 || ((c & 0x80) != 0)) + i += read_mbchar (fd, input_string, i, c, unbuffered_read); + } +#endif + + nr++; + + if (nchars > 0 && nr >= nchars) + break; + } + input_string[i] = '\0'; + CHECK_ALRM; + +#if defined (READLINE) + if (edit) + free (rlbuf); +#endif + + if (retval < 0) + { + t_errno = errno; + if (errno != EINTR) + builtin_error (_("read error: %d: %s"), fd, strerror (errno)); + run_unwind_frame ("read_builtin"); + return ((t_errno != EINTR) ? EXECUTION_FAILURE : 128+lastsig); + } + + if (tmsec > 0 || tmusec > 0) + reset_alarm (); + + if (nchars > 0 || delim != '\n') + { +#if defined (READLINE) + if (edit) + { + if (nchars > 0) + rl_num_chars_to_read = 0; + if (delim != '\n') + reset_eol_delim ((char *)NULL); + } + else +#endif + if (input_is_tty) + ttyrestore (&termsave); + } + else if (silent) + ttyrestore (&termsave); + + if (unbuffered_read == 0) + zsyncfd (fd); + +#if defined (READLINE) + if (save_instream) + rl_instream = save_instream; /* can't portably free it */ +#endif + + discard_unwind_frame ("read_builtin"); + + retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS; + +assign_vars: + +#if defined (ARRAY_VARS) + /* If -a was given, take the string read, break it into a list of words, + an assign them to `arrayname' in turn. */ + if (arrayname) + { + if (legal_identifier (arrayname) == 0) + { + sh_invalidid (arrayname); + free (input_string); + return (EXECUTION_FAILURE); + } + + var = find_or_make_array_variable (arrayname, 1); + if (var == 0) + { + free (input_string); + return EXECUTION_FAILURE; /* readonly or noassign */ + } + if (assoc_p (var)) + { + builtin_error (_("%s: cannot convert associative to indexed array"), arrayname); + free (input_string); + return EXECUTION_FAILURE; /* existing associative array */ + } + else if (invisible_p (var)) + VUNSETATTR (var, att_invisible); + array_flush (array_cell (var)); + + alist = list_string (input_string, ifs_chars, 0); + if (alist) + { + if (saw_escape) + dequote_list (alist); + else + word_list_remove_quoted_nulls (alist); + assign_array_var_from_word_list (var, alist, 0); + dispose_words (alist); + } + free (input_string); + return (retval); + } +#endif /* ARRAY_VARS */ + + /* If there are no variables, save the text of the line read to the + variable $REPLY. ksh93 strips leading and trailing IFS whitespace, + so that `read x ; echo "$x"' and `read ; echo "$REPLY"' behave the + same way, but I believe that the difference in behaviors is useful + enough to not do it. Without the bash behavior, there is no way + to read a line completely without interpretation or modification + unless you mess with $IFS (e.g., setting it to the empty string). + If you disagree, change the occurrences of `#if 0' to `#if 1' below. */ + if (list == 0) + { +#if 0 + orig_input_string = input_string; + for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++) + ; + input_string = t; + input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape); +#endif + + if (saw_escape) + { + t = dequote_string (input_string); + var = bind_variable ("REPLY", t, 0); + free (t); + } + else + var = bind_variable ("REPLY", input_string, 0); + if (var == 0 || readonly_p (var) || noassign_p (var)) + retval = EXECUTION_FAILURE; + else + VUNSETATTR (var, att_invisible); + + free (input_string); + return (retval); + } + + /* This code implements the Posix.2 spec for splitting the words + read and assigning them to variables. */ + orig_input_string = input_string; + + /* Remove IFS white space at the beginning of the input string. If + $IFS is null, no field splitting is performed. */ + for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++) + ; + input_string = t; + for (; list->next; list = list->next) + { + varname = list->word->word; +#if defined (ARRAY_VARS) + if (legal_identifier (varname) == 0 && valid_array_reference (varname, vflags) == 0) +#else + if (legal_identifier (varname) == 0) +#endif + { + sh_invalidid (varname); + free (orig_input_string); + return (EXECUTION_FAILURE); + } + + /* If there are more variables than words read from the input, + the remaining variables are set to the empty string. */ + if (*input_string) + { + /* This call updates INPUT_STRING. */ + t = get_word_from_string (&input_string, ifs_chars, &e); + if (t) + *e = '\0'; + /* Don't bother to remove the CTLESC unless we added one + somewhere while reading the string. */ + if (t && saw_escape) + { + t1 = dequote_string (t); + var = bind_read_variable (varname, t1); + free (t1); + } + else + var = bind_read_variable (varname, t ? t : ""); + } + else + { + t = (char *)0; + var = bind_read_variable (varname, ""); + } + + FREE (t); + if (var == 0) + { + free (orig_input_string); + return (EXECUTION_FAILURE); + } + + stupidly_hack_special_variables (varname); + VUNSETATTR (var, att_invisible); + } + + /* Now assign the rest of the line to the last variable argument. */ +#if defined (ARRAY_VARS) + if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word, vflags) == 0) +#else + if (legal_identifier (list->word->word) == 0) +#endif + { + sh_invalidid (list->word->word); + free (orig_input_string); + return (EXECUTION_FAILURE); + } + +#if 0 + /* This has to be done this way rather than using string_list + and list_string because Posix.2 says that the last variable gets the + remaining words and their intervening separators. */ + input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape); +#else + /* Check whether or not the number of fields is exactly the same as the + number of variables. */ + tofree = NULL; + if (*input_string) + { + t1 = input_string; + t = get_word_from_string (&input_string, ifs_chars, &e); + if (*input_string == 0) + tofree = input_string = t; + else + { + input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape); + tofree = t; + } + } +#endif + + if (saw_escape && input_string && *input_string) + { + t = dequote_string (input_string); + var = bind_read_variable (list->word->word, t); + free (t); + } + else + var = bind_read_variable (list->word->word, input_string ? input_string : ""); + + if (var) + { + stupidly_hack_special_variables (list->word->word); + VUNSETATTR (var, att_invisible); + } + else + retval = EXECUTION_FAILURE; + + FREE (tofree); + free (orig_input_string); + + return (retval); +} + +static SHELL_VAR * +bind_read_variable (name, value) + char *name, *value; +{ + SHELL_VAR *v; + + v = builtin_bind_variable (name, value, 0); + return (v == 0 ? v + : ((readonly_p (v) || noassign_p (v)) ? (SHELL_VAR *)NULL : v)); +} + +#if defined (HANDLE_MULTIBYTE) +static int +read_mbchar (fd, string, ind, ch, unbuffered) + int fd; + char *string; + int ind, ch, unbuffered; +{ + char mbchar[MB_LEN_MAX + 1]; + int i, n, r; + char c; + size_t ret; + mbstate_t ps, ps_back; + wchar_t wc; + + memset (&ps, '\0', sizeof (mbstate_t)); + memset (&ps_back, '\0', sizeof (mbstate_t)); + + mbchar[0] = ch; + i = 1; + for (n = 0; n <= MB_LEN_MAX; n++) + { + ps_back = ps; + ret = mbrtowc (&wc, mbchar, i, &ps); + if (ret == (size_t)-2) + { + ps = ps_back; + + /* We don't want to be interrupted during a multibyte char read */ + if (unbuffered == 2) + r = zreadn (fd, &c, 1); + else if (unbuffered) + r = zread (fd, &c, 1); + else + r = zreadc (fd, &c); + if (r <= 0) + goto mbchar_return; + mbchar[i++] = c; + continue; + } + else if (ret == (size_t)-1 || ret == (size_t)0 || ret > (size_t)0) + break; + } + +mbchar_return: + if (i > 1) /* read a multibyte char */ + /* mbchar[0] is already string[ind-1] */ + for (r = 1; r < i; r++) + string[ind+r-1] = mbchar[r]; + return i - 1; +} +#endif + + +static void +ttyrestore (ttp) + struct ttsave *ttp; +{ + ttsetattr (ttp->fd, &(ttp->attrs)); + tty_modified = 0; } void -read_tty_cleanup () +__read_tty_cleanup () { - ; + if (tty_modified) + ttyrestore (&termsave); } int -read_tty_modified () +__read_tty_modified () +{ + return (tty_modified); +} + +#if defined (READLINE) +static rl_completion_func_t *old_attempted_completion_function = 0; +static rl_hook_func_t *old_startup_hook; +static char *deftext; + +static void +reset_attempted_completion_function (cp) + char *cp; +{ + if (rl_attempted_completion_function == 0 && old_attempted_completion_function) + rl_attempted_completion_function = old_attempted_completion_function; +} + +static int +set_itext () +{ + int r1, r2; + + r1 = r2 = 0; + if (old_startup_hook) + r1 = (*old_startup_hook) (); + if (deftext) + { + r2 = rl_insert_text (deftext); + deftext = (char *)NULL; + rl_startup_hook = old_startup_hook; + old_startup_hook = (rl_hook_func_t *)NULL; + } + return (r1 || r2); +} + +static char * +edit_line (p, itext) + char *p; + char *itext; +{ + char *ret; + int len; + + if (bash_readline_initialized == 0) + initialize_readline (); + + old_attempted_completion_function = rl_attempted_completion_function; + rl_attempted_completion_function = (rl_completion_func_t *)NULL; + bashline_set_event_hook (); + if (itext) + { + old_startup_hook = rl_startup_hook; + rl_startup_hook = set_itext; + deftext = itext; + } + + ret = readline (p); + + rl_attempted_completion_function = old_attempted_completion_function; + old_attempted_completion_function = (rl_completion_func_t *)NULL; + bashline_reset_event_hook (); + + if (ret == 0) + return ret; + len = strlen (ret); + ret = (char *)xrealloc (ret, len + 2); + ret[len++] = delim; + ret[len] = '\0'; + return ret; +} + +static int old_delim_ctype; +static rl_command_func_t *old_delim_func; +static int old_newline_ctype; +static rl_command_func_t *old_newline_func; + +static unsigned char delim_char; + +static void +set_eol_delim (c) + int c; { - return 0; + Keymap cmap; + + if (bash_readline_initialized == 0) + initialize_readline (); + cmap = rl_get_keymap (); + + /* Save the old delimiter char binding */ + old_newline_ctype = cmap[RETURN].type; + old_newline_func = cmap[RETURN].function; + old_delim_ctype = cmap[c].type; + old_delim_func = cmap[c].function; + + /* Change newline to self-insert */ + cmap[RETURN].type = ISFUNC; + cmap[RETURN].function = rl_insert; + + /* Bind the delimiter character to accept-line. */ + cmap[c].type = ISFUNC; + cmap[c].function = rl_newline; + + delim_char = c; } +static void +reset_eol_delim (cp) + char *cp; +{ + Keymap cmap; + + cmap = rl_get_keymap (); + + cmap[RETURN].type = old_newline_ctype; + cmap[RETURN].function = old_newline_func; + + cmap[delim_char].type = old_delim_ctype; + cmap[delim_char].function = old_delim_func; +} +#endif diff --git a/bash-5.1/builtins/setattr.def b/bash-5.1/builtins/setattr.def index 33bef4c38f8123eae07ac4922f34b2501b78bd63..f83dbeedd235804372ce8012955f0ff9fbdd8ec3 100644 --- a/bash-5.1/builtins/setattr.def +++ b/bash-5.1/builtins/setattr.def @@ -76,6 +76,7 @@ int export_builtin (list) register WORD_LIST *list; { + return r_export_builtin(list); return (set_or_show_attributes (list, att_exported, 0)); } @@ -107,6 +108,7 @@ int readonly_builtin (list) register WORD_LIST *list; { + return r_readonly_builtin(list); return (set_or_show_attributes (list, att_readonly, 0)); } @@ -120,7 +122,7 @@ readonly_builtin (list) ATTRIBUTE. An arg of `-n' says to remove the attribute from the the remaining names in LIST (doesn't work for readonly). */ int -set_or_show_attributes (list, attribute, nodefs) +__set_or_show_attributes (list, attribute, nodefs) register WORD_LIST *list; int attribute, nodefs; { @@ -350,7 +352,7 @@ set_or_show_attributes (list, attribute, nodefs) /* Show all variable variables (v == 1) or functions (v == 0) with attributes. */ int -show_all_var_attributes (v, nodefs) +__show_all_var_attributes (v, nodefs) int v, nodefs; { SHELL_VAR **variable_list, *var; @@ -374,7 +376,7 @@ show_all_var_attributes (v, nodefs) /* Show all local variable variables with their attributes. This shows unset local variables (all_local_variables called with 0 argment). */ int -show_local_var_attributes (v, nodefs) +__show_local_var_attributes (v, nodefs) int v, nodefs; { SHELL_VAR **variable_list, *var; @@ -396,7 +398,7 @@ show_local_var_attributes (v, nodefs) } int -var_attribute_string (var, pattr, flags) +__var_attribute_string (var, pattr, flags) SHELL_VAR *var; int pattr; char *flags; /* filled in with attributes */ @@ -468,7 +470,7 @@ var_attribute_string (var, pattr, flags) or `readonly') instead of `declare', and doesn't print function defs when called by `export' or `readonly'. */ int -show_var_attributes (var, pattr, nodefs) +__show_var_attributes (var, pattr, nodefs) SHELL_VAR *var; int pattr, nodefs; { @@ -522,7 +524,7 @@ show_var_attributes (var, pattr, nodefs) } int -show_name_attributes (name, nodefs) +__show_name_attributes (name, nodefs) char *name; int nodefs; { @@ -540,7 +542,7 @@ show_name_attributes (name, nodefs) } int -show_localname_attributes (name, nodefs) +__show_localname_attributes (name, nodefs) char *name; int nodefs; { @@ -558,7 +560,7 @@ show_localname_attributes (name, nodefs) } int -show_func_attributes (name, nodefs) +__show_func_attributes (name, nodefs) char *name; int nodefs; { @@ -576,7 +578,7 @@ show_func_attributes (name, nodefs) } void -set_var_attribute (name, attribute, undo) +__set_var_attribute (name, attribute, undo) char *name; int attribute, undo; { diff --git a/bash-5.1/builtins/type.def b/bash-5.1/builtins/type.def index a8e47c0ac44dbffe102bc3dccee0d65298173f8c..d26801f4d9640cd2e893e1bca984bb65f0da2f2c 100644 --- a/bash-5.1/builtins/type.def +++ b/bash-5.1/builtins/type.def @@ -77,7 +77,7 @@ $END #include "bashgetopt.h" extern int find_reserved_word PARAMS((char *)); - +extern int r_type_builtin PARAMS((WORD_LIST *)); /* For each word in LIST, find out what the shell is going to do with it as a simple command. i.e., which file would this shell use to execve, or if it is a builtin command, or an alias. Possible flag @@ -110,6 +110,7 @@ int type_builtin (list) WORD_LIST *list; { + return r_type_builtin(list); int dflags, any_failed, opt; WORD_LIST *this; diff --git a/bash-5.1/builtins/ulimit.def b/bash-5.1/builtins/ulimit.def index a895c5e26de00a737a23a5b9173d83a8e5d08ca9..6029913a8716f16cf43ba0d758f0037451051b47 100644 --- a/bash-5.1/builtins/ulimit.def +++ b/bash-5.1/builtins/ulimit.def @@ -220,6 +220,7 @@ static int filesize PARAMS((RLIMTYPE *)); static int pipesize PARAMS((RLIMTYPE *)); static int getmaxuprc PARAMS((RLIMTYPE *)); static int getmaxvm PARAMS((RLIMTYPE *, RLIMTYPE *)); +extern int r_ulimit_builtin PARAMS((WORD_LIST *)); typedef struct { int option; /* The ulimit option for this limit. */ @@ -332,6 +333,7 @@ int ulimit_builtin (list) register WORD_LIST *list; { + return r_ulimit_builtin(list); register char *s; int c, limind, mode, opt, all_limits; diff --git a/bash-5.1/builtins_rust/alias/Cargo.toml b/bash-5.1/builtins_rust/alias/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..bd102dd8fe0a3cd840d0d0c24fd0a1d0cf7dfd12 --- /dev/null +++ b/bash-5.1/builtins_rust/alias/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "alias" +version = "0.1.0" +edition = "2018" +authors = ["liutong"] + + +[lib] +name = "ralias" +crate-type = ["staticlib"] + +[dependencies] +libc = "0.2" +rcmd = {path="../cmd"} +# nix = "0.23" diff --git a/bash-5.1/builtins_rust/alias/src/lib.rs b/bash-5.1/builtins_rust/alias/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..1dcbe59b15f67a9a1eb2e525c3f9eda1bd9e1e44 --- /dev/null +++ b/bash-5.1/builtins_rust/alias/src/lib.rs @@ -0,0 +1,231 @@ +use std::ffi::CStr; +extern "C" { + fn free(__ptr: *mut libc::c_void); + fn dcgettext( + __domainname: *const libc::c_char, + __msgid: *const libc::c_char, + __category: libc::c_int, + ) -> *mut libc::c_char; + fn printf(_: *const libc::c_char, _: ...) -> libc::c_int; + fn legal_alias_name(_: *const libc::c_char, _: libc::c_int) -> libc::c_int; + fn sh_single_quote(_: *const libc::c_char) -> *mut libc::c_char; + static mut posixly_correct: libc::c_int; + static mut aliases: *mut HASH_TABLE; + fn find_alias(_: *mut libc::c_char) -> *mut alias_t; + fn add_alias(_: *mut libc::c_char, _: *mut libc::c_char); + fn remove_alias(_: *mut libc::c_char) -> libc::c_int; + fn delete_all_aliases(); + fn all_aliases() -> *mut *mut alias_t; + fn builtin_error(_: *const libc::c_char, _: ...); + fn builtin_usage(); + fn sh_notfound(_: *mut libc::c_char); + fn sh_chkwrite(_: libc::c_int) -> libc::c_int; + fn builtin_help(); + static mut loptend: *mut WORD_LIST; + fn internal_getopt(_: *mut WORD_LIST, _: *mut libc::c_char) -> libc::c_int; + fn reset_internal_getopt(); +} +pub type size_t = libc::c_ulong; + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct word_desc { + pub word: *mut libc::c_char, + pub flags: libc::c_int, +} +pub type WORD_DESC = word_desc; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct bucket_contents { + pub next: *mut bucket_contents, + pub key: *mut libc::c_char, + pub data: *mut libc::c_void, + pub khash: libc::c_uint, + pub times_found: libc::c_int, +} +pub type BUCKET_CONTENTS = bucket_contents; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct hash_table { + pub bucket_array: *mut *mut BUCKET_CONTENTS, + pub nbuckets: libc::c_int, + pub nentries: libc::c_int, +} +pub type HASH_TABLE = hash_table; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct alias { + pub name: *mut libc::c_char, + pub value: *mut libc::c_char, + pub flags: libc::c_char, +} +pub type alias_t = alias; +#[no_mangle] +pub unsafe extern "C" fn r_alias_builtin(mut list: *mut WORD_LIST) -> libc::c_int { + println!("alias_builtin run!"); + let mut any_failed: libc::c_int = 0; + let mut offset: libc::c_int = 0; + let mut pflag: libc::c_int = 0; + let mut dflags: libc::c_int = 0; + let mut alias_list: *mut *mut alias_t = 0 as *mut *mut alias_t; + let mut t: *mut alias_t = 0 as *mut alias_t; + let mut name: *mut libc::c_char = 0 as *mut libc::c_char; + let mut value: *mut libc::c_char = 0 as *mut libc::c_char; + dflags = if posixly_correct != 0 { 0 as libc::c_int } else { 0x1 as libc::c_int }; + pflag = 0 as libc::c_int; + reset_internal_getopt(); + loop { + offset = internal_getopt( + list, + b"p\0" as *const u8 as *const libc::c_char as *mut libc::c_char, + ); + if !(offset != -(1 as libc::c_int)) { + break; + } + match offset as u8 { + b'p' => { + pflag = 1 as libc::c_int; + dflags |= 0x1 as libc::c_int; + } + _ => { + builtin_usage(); + return 258 as libc::c_int; + } + } + } + list = loptend; + if list.is_null() || pflag != 0 { + if aliases.is_null() { + return 0 as libc::c_int; + } + alias_list = all_aliases(); + if alias_list.is_null() { + return 0 as libc::c_int; + } + offset = 0 as libc::c_int; + while !(*alias_list.offset(offset as isize)).is_null() { + print_alias(*alias_list.offset(offset as isize), dflags); + offset += 1; + } + free(alias_list as *mut libc::c_void); + if list.is_null() { + return sh_chkwrite(0 as libc::c_int); + } + } + any_failed = 0 as libc::c_int; + while !list.is_null() { + name = (*(*list).word).word; + offset = 0 as libc::c_int; + while *name.offset(offset as isize) as libc::c_int != 0 + && *name.offset(offset as isize) as libc::c_int != '=' as i32 + { + offset += 1; + } + if offset != 0 && *name.offset(offset as isize) as libc::c_int == '=' as i32 { + *name.offset(offset as isize) = '\u{0}' as i32 as libc::c_char; + value = name.offset(offset as isize).offset(1 as libc::c_int as isize); + if legal_alias_name(name, 0 as libc::c_int) == 0 as libc::c_int { + builtin_error( + dcgettext( + 0 as *const libc::c_char, + b"`%s': invalid alias name\0" as *const u8 + as *const libc::c_char, + 5 as libc::c_int, + ), + name, + ); + any_failed += 1; + } else { + add_alias(name, value); + } + } else { + t = find_alias(name); + if !t.is_null() { + print_alias(t, dflags); + } else { + sh_notfound(name); + any_failed += 1; + } + } + list = (*list).next; + } + return if any_failed != 0 { 1 as libc::c_int } else { 0 as libc::c_int }; +} +#[no_mangle] +pub unsafe extern "C" fn r_unalias_builtin(mut list: *mut WORD_LIST) -> libc::c_int { + let mut alias: *mut alias_t = 0 as *mut alias_t; + let mut opt: libc::c_int = 0; + let mut aflag: libc::c_int = 0; + aflag = 0 as libc::c_int; + reset_internal_getopt(); + loop { + opt = internal_getopt( + list, + b"a\0" as *const u8 as *const libc::c_char as *mut libc::c_char, + ); + if !(opt != -(1 as libc::c_int)) { + break; + } + match opt { + 97 => { + aflag = 1 as libc::c_int; + } + -99 => { + builtin_help(); + return 258 as libc::c_int; + } + _ => { + builtin_usage(); + return 258 as libc::c_int; + } + } + } + list = loptend; + if aflag != 0 { + delete_all_aliases(); + return 0 as libc::c_int; + } + if list.is_null() { + builtin_usage(); + return 258 as libc::c_int; + } + aflag = 0 as libc::c_int; + while !list.is_null() { + alias = find_alias((*(*list).word).word); + if !alias.is_null() { + remove_alias((*alias).name); + } else { + sh_notfound((*(*list).word).word); + aflag += 1; + } + list = (*list).next; + } + return if aflag != 0 { 1 as libc::c_int } else { 0 as libc::c_int }; +} +unsafe extern "C" fn print_alias(mut alias: *mut alias_t, mut flags: libc::c_int) { + let mut value: *mut libc::c_char = 0 as *mut libc::c_char; + value = sh_single_quote((*alias).value); + if flags & 0x1 as libc::c_int != 0 { + printf( + b"alias %s\0" as *const u8 as *const libc::c_char, + if !((*alias).name).is_null() + && *((*alias).name).offset(0 as libc::c_int as isize) as libc::c_int + == '-' as i32 + { + b"-- \0" as *const u8 as *const libc::c_char + } else { + b"\0" as *const u8 as *const libc::c_char + }, + ); + } + + println!("{}={}", CStr::from_ptr((*alias).name).to_string_lossy().into_owned(), CStr::from_ptr(value).to_string_lossy().into_owned()); + free(value as *mut libc::c_void); +} diff --git a/bash-5.1/builtins_rust/bind/.gitignore b/bash-5.1/builtins_rust/bind/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4fffb2f89cbd8f2169ce9914bd16bd43785bb368 --- /dev/null +++ b/bash-5.1/builtins_rust/bind/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/bash-5.1/builtins_rust/bind/Cargo.toml b/bash-5.1/builtins_rust/bind/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..359fde33dcde645bde068df06ddf1f6e74872689 --- /dev/null +++ b/bash-5.1/builtins_rust/bind/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "rbind" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +nix = "0.24.1" + +[lib] +crate-type = ["cdylib"] +name = "rbind" diff --git a/bash-5.1/builtins_rust/bind/src/lib.rs b/bash-5.1/builtins_rust/bind/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..7a6dcf566ee373dd6f4e9fb040be059909f63327 --- /dev/null +++ b/bash-5.1/builtins_rust/bind/src/lib.rs @@ -0,0 +1,568 @@ +extern crate libc; +extern crate nix; +use libc::{c_char,c_int,strerror,free, c_void, strlen, size_t,}; +use std::{ffi::{CString,CStr}}; +use std::fs::File; +use nix::errno::errno; + +//struct +#[repr (C)] +pub struct WORD_DESC{ + pub word:*mut c_char, + pub flags:c_int, +} + +#[repr (C)] +// #[derive(Copy,Clone)] +pub struct WORD_LIST{ + pub next:*mut WORD_LIST, + pub word:*mut WORD_DESC, +} +#[repr (C)] +pub struct _keymap_entry{ + pub Type:c_char, + pub function:rl_command_func_t, +} +type KEYMAP_ENTRY = _keymap_entry; +type Keymap = *mut KEYMAP_ENTRY; +type rl_command_func_t = extern fn(c_int,c_int)->c_int; +//emun + + + +//macro +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {0} +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => { 1 }; +} + +#[macro_export] +macro_rules! EX_USAGE { + () => { 258 } +} + +#[macro_export] +macro_rules! LFLAG { + () => { 0x0001 } +} +#[macro_export] +macro_rules! PFLAG { + () => { 0x0002 } +} +#[macro_export] +macro_rules! FFLAG { + () => { 0x0004 } +} +#[macro_export] +macro_rules! VFLAG { + () => { 0x0008 } +} +#[macro_export] +macro_rules! QFLAG { + () => { 0x0010 } +} +#[macro_export] +macro_rules! MFLAG { + () => { 0x0020 } +} +#[macro_export] +macro_rules! RFLAG { + () => { 0x0040 } +} +#[macro_export] +macro_rules! PPFLAG { + () => { 0x0080 } +} +#[macro_export] +macro_rules! VVFLAG { + () => { 0x0100 } +} +#[macro_export] +macro_rules! SFLAG { + () => { 0x0200 } +} +#[macro_export] +macro_rules! SSFLAG { + () => { 0x0400 } +} +#[macro_export] +macro_rules! UFLAG { + () => { 0x0800 } +} +#[macro_export] +macro_rules! XFLAG { + () => { 0x1000 } +} +#[macro_export] +macro_rules! XXFLAG { + () => { 0x2000 } +} + +#[macro_export] +macro_rules! ISKMAP { + () => { 1 } +} + +#[macro_export] +macro_rules! KEYMAP_SIZE{ + () => { 257 } +} + +#[macro_export] +macro_rules! ANYOTHERKEY{ + () => { KEYMAP_SIZE!() - 1} +} + +// #[macro_export] +// macro_rules! unwind_protect_var { +// ($X:expr) => { + +// unwind_protect_mem($X as *mut c_char,std::intrinsics::size_of(File)); +// // std::mem::size_of::<& REPL>() +// }; +// } + +//extern "C" +extern "C"{ + static no_line_editing:i32; + static bash_readline_initialized:i32; + static mut rl_outstream:*mut File; + static stdout:*mut File; + static list_optarg:*mut c_char; + static loptend:*mut WORD_LIST; + + fn builtin_warning(format:*const c_char,...); + fn initialize_readline(); + fn begin_unwind_frame(tar:*mut c_char); + fn run_unwind_frame(tag:*mut c_char); + fn unwind_protect_mem(var:*mut c_char,size:i32); + fn reset_internal_getopt(); + fn internal_getopt(list:*mut WORD_LIST,opts:*mut c_char)->i32; + fn builtin_usage(); + fn rl_set_keymap(map:Keymap); + fn sh_chkwrite(s:i32)->i32; + fn builtin_error(format:*const c_char,...); + fn rl_named_function(string:*const c_char)->*mut rl_command_func_t; + fn rl_invoking_keyseqs(function:*mut rl_command_func_t)->*mut *mut c_char; + fn strvec_dispose(array:*mut *mut c_char); + fn rl_unbind_function_in_map(func:*mut rl_command_func_t,map:Keymap)->i32; + fn rl_get_keymap()->Keymap; + fn unbind_unix_command(kseq:*mut c_char)->i32; + fn bash_execute_unix_command(count:i32,key:i32)->i32; + fn rl_bind_keyseq(keyseq:*const c_char,function:*mut rl_command_func_t)->i32; + fn rl_function_of_keyseq_len(keyseq:*const c_char,len:size_t,map:Keymap,Type:*mut i32)->*mut rl_command_func_t; + fn rl_translate_keyseq(seq:*const c_char,array:*mut c_char,len:*mut i32)->i32; + fn xmalloc(n:size_t)->*mut c_void; + fn rl_get_keymap_by_name(name:*const c_char)->Keymap; + fn rl_list_funmap_names(); + fn rl_function_dumper(print_readably:i32); + fn rl_macro_dumper(print_readably:i32); + fn rl_variable_dumper(print_readably:i32); + fn rl_read_init_file(filename:*const c_char)->i32; + fn printable_filename(Fn:*mut c_char,flags:i32)->*mut c_char; + // fn query_bindings(name:*mut c_char)->i32; + // fn unbind_command(name:*mut c_char)->i32; + // fn unbind_keyseq(seq:*mut c_char)->i32; + fn bind_keyseq_to_unix_command(line:*mut c_char)->i32; + fn print_unix_command_map()->i32; + fn strvec_len(array:*mut *mut c_char)->i32; + fn rl_parse_and_bind(string:*mut c_char)->i32; + fn strvec_search(array:*mut *mut c_char,name:*mut c_char)->i32; +} + + +#[no_mangle] +pub extern "C" fn r_bind_builtin(mut list:*mut WORD_LIST)->i32{ + let mut return_code:i32; + let mut kmap:Keymap; + let mut saved_keymap:Keymap; + let mut flags:i32; + let mut opt:i32; + let mut initfile:*mut c_char; + let mut map_name:*mut c_char; + let mut fun_name:*mut c_char; + let mut unbind_name:*mut c_char; + let mut remove_seq:*mut c_char; + let mut cmd_seq:*mut c_char; + let mut t:*mut c_char; + + println!("r_bind_builtin"); + + unsafe{ + if no_line_editing != 0{ + let s_str = String::from("line editing not enabled"); + let s_ptr = s_str.as_ptr() as *const c_char; + builtin_warning(s_ptr); + } + + kmap = std::ptr::null_mut(); + saved_keymap = std::ptr::null_mut(); + flags = 0; + initfile = std::ptr::null_mut(); + map_name = std::ptr::null_mut(); + fun_name = std::ptr::null_mut(); + unbind_name = std::ptr::null_mut(); + remove_seq = std::ptr::null_mut(); + cmd_seq = std::ptr::null_mut(); + + return_code = EXECUTION_SUCCESS!(); + + if bash_readline_initialized == 0{ + initialize_readline(); + } + let bind_str = String::from("bind_builtin"); + let bind_ptr = bind_str.as_ptr() as *mut c_char; + begin_unwind_frame(bind_ptr); + //这里是瞎写的!!!!! + // unwind_protect_var!(rl_outstream); + // unwind_protect_mem(rl_outstream as *mut c_char,8); + unwind_protect_mem(std::mem::transmute(rl_outstream), std::mem::size_of_val(&rl_outstream) as c_int); + + + rl_outstream = stdout; + reset_internal_getopt(); + + let c_str = CString::new("lvpVPsSXf:q:u:m:r:x:").unwrap(); + let c_ptr = c_str.as_ptr() as *mut c_char; + opt = internal_getopt(list,c_ptr); + while opt != -1{ + let optu8 = opt as u8; + let opt_char = char::from(optu8); + match opt_char{ + 'l' => flags |= LFLAG!(), + 'v' => flags |= VFLAG!(), + 'p' => flags |= PFLAG!(), + 'f' => { + flags |= FFLAG!(); + initfile = list_optarg; + } + 'm' => { + flags |= MFLAG!(); + map_name = list_optarg; + } + 'q' => { + flags |= QFLAG!(); + fun_name = list_optarg; + } + 'u' => { + flags |= UFLAG!(); + unbind_name = list_optarg; + } + 'r' => { + flags |= RFLAG!(); + remove_seq = list_optarg; + } + 'V' => flags |= VVFLAG!(), + 'P' => flags |= PPFLAG!(), + 's' => flags |= SFLAG!(), + 'S' => flags |= SSFLAG!(), + 'x' => { + flags |= XFLAG!(); + cmd_seq = list_optarg; + } + 'X' => flags |= XXFLAG!(), + _ => { + builtin_usage(); + // BIND_RETURN!(EX_USAGE!()); + return_code = EX_USAGE!(); + if !saved_keymap.is_null(){ + rl_set_keymap(saved_keymap); + } + run_unwind_frame(bind_ptr ); + if return_code < 0 { + return_code = EXECUTION_FAILURE!(); + } + return sh_chkwrite(return_code); + } + } + opt = internal_getopt(list,c_ptr); + } + + list = loptend; + + /* First, see if we need to install a special keymap for this + command. Then start on the arguments. */ + + if (flags & MFLAG!()) != 0 && !map_name.is_null(){ + kmap = rl_get_keymap_by_name(map_name); + if kmap.is_null(){ + let c_ptr = CString::new("%s:invalid keymap name").unwrap().as_ptr(); //%s在c中为`%s': + builtin_error(c_ptr,map_name); + return_code = EXECUTION_FAILURE!(); + if !saved_keymap.is_null(){ + rl_set_keymap(saved_keymap); + } + run_unwind_frame(bind_ptr ); + if return_code < 0 { + return_code = EXECUTION_FAILURE!(); + } + return sh_chkwrite(return_code); + } + } + + if !kmap.is_null(){ + saved_keymap = rl_get_keymap(); + rl_set_keymap(kmap); + } + + /* XXX - we need to add exclusive use tests here. It doesn't make sense + to use some of these options together. */ + /* Now hack the option arguments */ + if flags & LFLAG!() != 0{ + rl_list_funmap_names(); + } + if flags & PFLAG!() != 0{ + rl_function_dumper(1); + } + if flags & PPFLAG!() != 0{ + rl_function_dumper(0); + } + if flags & SFLAG!() != 0{ + rl_macro_dumper(1); + } + if flags & SSFLAG!() != 0{ + rl_macro_dumper(0); + } + if flags & VFLAG!() != 0{ + rl_variable_dumper(1); + } + if flags & VVFLAG!() != 0{ + rl_variable_dumper(0); + } + + if (flags & FFLAG!()) != 0 && !initfile.is_null(){ + if rl_read_init_file(initfile) != 0{ + t = printable_filename(initfile,0); + let c_ptr = CString::new("%s: cannot read: %s").unwrap().as_ptr(); + builtin_error(c_ptr,t,strerror(errno())); + if t != initfile{ + free(t as *mut c_void); + } + return_code = EXECUTION_FAILURE!(); + if !saved_keymap.is_null(){ + rl_set_keymap(saved_keymap); + } + run_unwind_frame(bind_ptr ); + if return_code < 0 { + return_code = EXECUTION_FAILURE!(); + } + return sh_chkwrite(return_code); + } + } + + if (flags & QFLAG!()) != 0 && !fun_name.is_null(){ + return_code = r_query_bindings(fun_name); + } + + if (flags & UFLAG!()) != 0 && !unbind_name.is_null(){ + return_code = r_unbind_command(unbind_name); + } + + if (flags & RFLAG!()) != 0 && !remove_seq.is_null(){ + opt = r_unbind_keyseq(remove_seq); + return_code = opt; + if !saved_keymap.is_null(){ + rl_set_keymap(saved_keymap); + } + run_unwind_frame(bind_ptr ); + if return_code < 0 { + return_code = EXECUTION_FAILURE!(); + } + return sh_chkwrite(return_code); + } + + if flags & XFLAG!() != 0{ + return_code = bind_keyseq_to_unix_command (cmd_seq); + } + + if flags & XXFLAG!() != 0{ + return_code = print_unix_command_map(); + } + + /* Process the rest of the arguments as binding specifications. */ + while !list.is_null(){ + let mut olen:i32; + let mut nlen:i32; + let mut d:i32; + let mut i:i32; + let mut obindings:*mut *mut c_char; + let mut nbindings:*mut *mut c_char; + + obindings = rl_invoking_keyseqs(bash_execute_unix_command as *mut rl_command_func_t); + if !obindings.is_null(){ + olen = strvec_len(obindings); + } + else{ + olen = 0; + } + + rl_parse_and_bind((*(*list).word).word); + + nbindings = rl_invoking_keyseqs(bash_execute_unix_command as *mut rl_command_func_t); + if !nbindings.is_null(){ + nlen = strvec_len(nbindings); + } + else{ + nlen = 0; + } + + if nlen< olen{ + d = olen - nlen; + i = 0; + let mut t:*mut c_char; + while i0 { + t = *((obindings as usize + (i*8) as usize) as *mut *mut c_char) as *mut c_char; + if nlen == 0 || strvec_search(nbindings,t) >= 0{ + unbind_unix_command(t); + d = d-1; + } + i += 1; + } + } + + strvec_dispose(obindings); + strvec_dispose(nbindings); + + list = (*list).next; + } + + if !saved_keymap.is_null(){ + rl_set_keymap(saved_keymap); + } + run_unwind_frame(bind_ptr); + + if return_code < 0{ + return_code = EXECUTION_FAILURE!(); + } + + return sh_chkwrite(return_code); + + }//unsafe +} + +#[no_mangle] +extern "C" fn r_query_bindings(name:*mut c_char)->i32{ + let mut function:*mut rl_command_func_t; + let mut keyseqs:*mut *mut c_char; + let mut j:i32; + let mut name_str:String; + + unsafe{ + let name_str = CStr::from_ptr(name).to_str().unwrap().to_owned(); + + function = rl_named_function(name); + if function.is_null(){ + let c_str = CString::new("%s: unknow function name").unwrap().as_ptr(); + builtin_error(c_str,name); + return EXECUTION_FAILURE!(); + } + + keyseqs = rl_invoking_keyseqs(function); + + if keyseqs.is_null(){ + println!("{} is not bound to any keys.",name_str); + return EXECUTION_FAILURE!(); + } + + print!("{} can be invoked via ",name_str); + j = 0; + let mut t:*mut c_char; + t = *keyseqs; + while j<5 && !t.is_null(){ + let c:String; + if !(*((keyseqs as usize + ((j+1)*8) as usize) as *mut *mut c_char) as *mut c_char).is_null(){ + c = String::from(","); + } + else{ + c = String::from(".\n"); + } + let c_cstr = CStr::from_ptr(t); + let c_str = c_cstr.to_str().unwrap(); + print!("\"{}\"{}",c_str,c); + j += 1; + t = *((keyseqs as usize + (j*8) as usize) as *mut *mut c_char) as *mut c_char; + } + if !(*((keyseqs as usize + (j*8) as usize) as *mut *mut c_char) as *mut c_char).is_null(){ + print!("...\n"); + } + strvec_dispose(keyseqs); + return EXECUTION_SUCCESS!(); + } +} + +#[no_mangle] +extern "C" fn r_unbind_command(name:*mut c_char)->i32{ + let mut function:*mut rl_command_func_t; + + unsafe{ + function = rl_named_function(name); + if function.is_null(){ + let c_str = CString::new("`%s':unknown function name").unwrap().as_ptr(); + builtin_error(c_str,name); + return EXECUTION_FAILURE!(); + } + + rl_unbind_function_in_map(function,rl_get_keymap()); + return EXECUTION_SUCCESS!(); + } +} + +#[no_mangle] +extern "C" fn r_unbind_keyseq(seq:*mut c_char)->i32{ + let mut kseq:*mut c_char; + let mut kslen:i32 = 0; + let mut Type:i32 = 0; + let mut f:*mut rl_command_func_t; + unsafe{ + kseq = xmalloc((2 * strlen(seq)) + 1) as *mut c_char; + if rl_translate_keyseq(seq,kseq,&mut kslen) != 0{ + free(kseq as *mut c_void); + let c_ptr = CString::new("`%s': cannot unbind").unwrap().as_ptr(); + builtin_error(c_ptr, seq); + return EXECUTION_FAILURE!(); + } + //可能存在错误 + f = rl_function_of_keyseq_len(kseq,kslen as usize,0 as Keymap,&mut Type); + if f.is_null(){ + free(kseq as *mut c_void); + return EXECUTION_SUCCESS!(); + } + + if Type == ISKMAP!(){ + //不清楚这个条件是如何触发的,所以下面语句可能存在问题 + f = (*(f as Keymap).offset(ANYOTHERKEY!() as isize)).function as *mut rl_command_func_t; + } + + /* I wish this didn't have to translate the key sequence again, but readline + doesn't have a binding function that takes a translated key sequence as + an argument. */ + if rl_bind_keyseq(seq,std::ptr::null_mut() as *mut rl_command_func_t) != 0{ + free(kseq as *mut c_void); + let c_ptr = CString::new("`%s': cannot unbind").unwrap().as_ptr(); + builtin_error(c_ptr, seq); + return EXECUTION_FAILURE!(); + } + + if f == bash_execute_unix_command as *mut rl_command_func_t{ + unbind_unix_command(seq); + } + free(kseq as *mut c_void); + return EXECUTION_SUCCESS!(); + } +} + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/break_1/Cargo.toml b/bash-5.1/builtins_rust/break_1/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..098083f1281a3be1e23471569ca0248259cd699d --- /dev/null +++ b/bash-5.1/builtins_rust/break_1/Cargo.toml @@ -0,0 +1,15 @@ +[package] +authors = ["zhanghuanhuan"] +name = "rbreak" +version = "0.0.1" +edition = "2021" +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +nix = "0.23.0" + +[lib] +crate-type = ["staticlib"] +name = "rbreak" + diff --git a/bash-5.1/builtins_rust/break_1/src/lib.rs b/bash-5.1/builtins_rust/break_1/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..7bf45e0ee5b5cf2c8618817d332b4fcc614244ea --- /dev/null +++ b/bash-5.1/builtins_rust/break_1/src/lib.rs @@ -0,0 +1,133 @@ +#[macro_use] +#[warn(temporary_cstring_as_ptr)] +extern crate libc; +extern crate nix; + +use std::ffi::CString; +use libc::c_long; +#[repr(C)] +pub struct WORD_DESC { + pub word: *mut libc::c_char, + pub flags: libc::c_int +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct WORD_LIST { + next: *mut WORD_LIST, + word: *mut WORD_DESC +} + +// 屏蔽警告。 +#[allow(non_camel_case_types)] +type intmax_t = c_long; + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {0} +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => {1} +} + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! ISHELP { + ($s:expr) => { + libc::strcmp($s as *const libc::c_char,CString::new("--help").unwrap().as_ptr()) + } +} + +#[macro_export] +macro_rules! CHECK_HELPOPT { + ($l:expr) => { + if $l !=std::ptr::null_mut() && (*$l).word !=std::ptr::null_mut() && ISHELP!((*(*$l).word).word) == 0 { + builtin_help (); + return EX_USAGE!(); + } + } +} + +extern "C" { + fn get_numeric_arg(list :*mut WORD_LIST, i: i32 , intmax :*mut intmax_t) -> i32; + fn builtin_help (); + fn get_loop_level() -> i32; + fn set_continuing(cont : i32); + fn set_breaking(breaking : i32); + fn sh_erange (s:* mut libc::c_char, desc:* mut libc::c_char); + //pub static fn check_loop_level () -> i64; + /* Non-zero when a "break" instruction is encountered. */ + pub static posixly_correct :i32; +} + +#[no_mangle] +pub extern "C" fn r_break_builtin(mut list :*mut WORD_LIST) -> i32 { + //println!("enter r_break_builtin"); + let mut newbreak : intmax_t = 1 as intmax_t; + unsafe { + CHECK_HELPOPT! (list); + if check_loop_level() == 0 { + return (EXECUTION_SUCCESS!()); + } + get_numeric_arg(list, 1, &mut newbreak as *mut intmax_t); + + if newbreak <= 0{ + #[warn(temporary_cstring_as_ptr)] + sh_erange ((*(*list).word).word, CString::new("loop count ").unwrap().as_ptr() as * mut libc::c_char); + set_breaking (get_loop_level()); + return (EXECUTION_FAILURE!()); + } + + if newbreak > get_loop_level() as libc::c_long{ + newbreak = get_loop_level() as i64; + } + + set_breaking(newbreak as i32); + } + return (EXECUTION_SUCCESS!()); +} + +fn continue_builtin (list :*mut WORD_LIST) -> i32 { + let mut newcont : intmax_t = 0 as intmax_t; + unsafe { + CHECK_HELPOPT! (list); + } + if check_loop_level() == 0 { + return (EXECUTION_SUCCESS!()); + } + unsafe { + get_numeric_arg(list, 1, newcont as *mut intmax_t); + } + unsafe { + if newcont <= 0{ + #[warn(temporary_cstring_as_ptr)] + sh_erange ((*(*list).word).word, CString::new("loop count ").unwrap().as_ptr() as * mut libc::c_char); + set_breaking(get_loop_level()); + return (EXECUTION_FAILURE!()); + } + if newcont > get_loop_level().into(){ + newcont = get_loop_level() as i64; + } + set_continuing(newcont as i32); + + } + return (EXECUTION_SUCCESS!()); +} + +#[no_mangle] +pub extern "C" fn check_loop_level () -> i32 { +unsafe { + if get_loop_level()== 0 && posixly_correct == 0 { + println! ("only meaningful in a `for`, `while`, or until `loop` "); + return 0; + } + return (get_loop_level()); +} +} + diff --git a/bash-5.1/builtins_rust/build.rs b/bash-5.1/builtins_rust/build.rs index 5b5544932086123d93bad082cc9783b5d85fd090..f062a48ed003e1a0ba67a7b6713460a7db048766 100644 --- a/bash-5.1/builtins_rust/build.rs +++ b/bash-5.1/builtins_rust/build.rs @@ -5,179 +5,17 @@ fn main() { let library_dir = "/opt/rsbash/builtins"; + let libsh_dir = "./lib/sh/"; + let exe_dir = "/opt/rsbash/"; - println!("cargo:rustc-link-search=native={}", env::join_paths(&[library_dir]).unwrap().to_str().unwrap()); + println!("cargo:rustc-link-search=native={}", env::join_paths(&[library_dir ]).unwrap().to_str().unwrap()); + println!("cargo:rustc-link-search=native={}", env::join_paths(&[ exe_dir]).unwrap().to_str().unwrap()); + println!("cargo:rustc-link-search=native={}", env::join_paths(&[ libsh_dir]).unwrap().to_str().unwrap()); - println!("cargo:rustc-flags=-l dylib=jobs"); - println!("cargo:rustc-flags=-l dylib=trap"); - println!("cargo:rustc-flags=-l dylib=execute_cmd"); - println!("cargo:rustc-flags=-l dylib=unwind_prot"); - println!("cargo:rustc-flags=-l dylib=flags"); - println!("cargo:rustc-flags=-l dylib=variables"); - println!("cargo:rustc-flags=-l dylib=builtins_break"); - println!("cargo:rustc-flags=-l dylib=builtins_common"); - println!("cargo:rustc-flags=-l dylib=sig"); - println!("cargo:rustc-flags=-l dylib=builtins_wait"); - println!("cargo:rustc-flags=-l dylib=shell"); - println!("cargo:rustc-flags=-l dylib=input"); - println!("cargo:rustc-flags=-l dylib=xmalloc"); - println!("cargo:rustc-flags=-l dylib=version"); - println!("cargo:rustc-flags=-l dylib=error"); - println!("cargo:rustc-flags=-l dylib=subst"); - println!("cargo:rustc-flags=-l dylib=lib_sh_winsize"); - println!("cargo:rustc-flags=-l dylib=dispose_cmd"); - println!("cargo:rustc-flags=-l dylib=lib_readline_readline"); - println!("cargo:rustc-flags=-l dylib=general"); - println!("cargo:rustc-flags=-l dylib=lib_sh_oslib"); - println!("cargo:rustc-flags=-l dylib=list"); - println!("cargo:rustc-flags=-l dylib=builtins_evalstring"); - println!("cargo:rustc-flags=-l dylib=y.tab"); - println!("cargo:rustc-flags=-l dylib=builtins_evalfile"); - println!("cargo:rustc-flags=-l dylib=lib_sh_casemod"); - println!("cargo:rustc-flags=-l dylib=lib_sh_fmtulong"); - println!("cargo:rustc-flags=-l dylib=builtins_set"); - println!("cargo:rustc-flags=-l dylib=lib_readline_history"); - println!("cargo:rustc-flags=-l dylib=mailcheck"); - println!("cargo:rustc-flags=-l dylib=bashhist"); - println!("cargo:rustc-flags=-l dylib=bashline"); - println!("cargo:rustc-flags=-l dylib=assoc"); - println!("cargo:rustc-flags=-l dylib=builtins_shopt"); - println!("cargo:rustc-flags=-l dylib=lib_readline_histfile"); - println!("cargo:rustc-flags=-l dylib=hashlib"); - println!("cargo:rustc-flags=-l dylib=print_cmd"); - println!("cargo:rustc-flags=-l dylib=copy_cmd"); - println!("cargo:rustc-flags=-l dylib=hashcmd"); - println!("cargo:rustc-flags=-l dylib=pathexp"); - println!("cargo:rustc-flags=-l dylib=lib_sh_random"); - println!("cargo:rustc-flags=-l dylib=findcmd"); - println!("cargo:rustc-flags=-l dylib=arrayfunc"); - println!("cargo:rustc-flags=-l dylib=lib_readline_terminal"); - println!("cargo:rustc-flags=-l dylib=array"); - println!("cargo:rustc-flags=-l dylib=lib_readline_complete"); - println!("cargo:rustc-flags=-l dylib=alias"); - println!("cargo:rustc-flags=-l dylib=builtins_getopt"); - println!("cargo:rustc-flags=-l dylib=locale"); - println!("cargo:rustc-flags=-l dylib=lib_readline_shell"); - println!("cargo:rustc-flags=-l dylib=lib_sh_stringvec"); - println!("cargo:rustc-flags=-l dylib=lib_sh_itos"); - println!("cargo:rustc-flags=-l dylib=pcomplete"); - println!("cargo:rustc-flags=-l dylib=lib_sh_strtrans"); - println!("cargo:rustc-flags=-l dylib=lib_readline_histexpand"); - println!("cargo:rustc-flags=-l dylib=lib_sh_shquote"); - println!("cargo:rustc-flags=-l dylib=builtins_pushd"); - println!("cargo:rustc-flags=-l dylib=redir"); - println!("cargo:rustc-flags=-l dylib=lib_sh_pathcanon"); - println!("cargo:rustc-flags=-l dylib=builtins_getopts"); - println!("cargo:rustc-flags=-l dylib=lib_readline_colors"); - println!("cargo:rustc-flags=-l dylib=lib_readline_mbutil"); - println!("cargo:rustc-flags=-l dylib=lib_readline_signals"); - println!("cargo:rustc-flags=-l dylib=lib_readline_text"); - println!("cargo:rustc-flags=-l dylib=lib_readline_parse-colors"); - println!("cargo:rustc-flags=-l dylib=lib_readline_display"); - println!("cargo:rustc-flags=-l dylib=lib_readline_util"); - println!("cargo:rustc-flags=-l dylib=lib_glob_xmbsrtowcs"); - println!("cargo:rustc-flags=-l dylib=lib_glob_gmisc"); - println!("cargo:rustc-flags=-l dylib=lib_sh_shmbchar"); - println!("cargo:rustc-flags=-l dylib=make_cmd"); - println!("cargo:rustc-flags=-l dylib=syntax"); - println!("cargo:rustc-flags=-l dylib=lib_glob_strmatch"); - println!("cargo:rustc-flags=-l dylib=lib_glob_glob"); - println!("cargo:rustc-flags=-l dylib=builtins_declare"); - println!("cargo:rustc-flags=-l dylib=stringlib"); - println!("cargo:rustc-flags=-l dylib=builtins_setattr"); - println!("cargo:rustc-flags=-l dylib=braces"); - println!("cargo:rustc-flags=-l dylib=lib_readline_misc"); - println!("cargo:rustc-flags=-l dylib=lib_readline_rltty"); - println!("cargo:rustc-flags=-l dylib=lib_readline_keymaps"); - println!("cargo:rustc-flags=-l dylib=lib_readline_kill"); - println!("cargo:rustc-flags=-l dylib=lib_readline_input"); - println!("cargo:rustc-flags=-l dylib=lib_readline_vi_mode"); - println!("cargo:rustc-flags=-l dylib=lib_readline_macro"); - println!("cargo:rustc-flags=-l dylib=lib_readline_bind"); - println!("cargo:rustc-flags=-l dylib=lib_readline_undo"); - println!("cargo:rustc-flags=-l dylib=lib_readline_funmap"); - println!("cargo:rustc-flags=-l dylib=lib_readline_nls"); - println!("cargo:rustc-flags=-l dylib=builtins_read"); - println!("cargo:rustc-flags=-l dylib=eval"); - println!("cargo:rustc-flags=-l dylib=lib_sh_setlinebuf"); - println!("cargo:rustc-flags=-l dylib=lib_sh_netconn"); - println!("cargo:rustc-flags=-l dylib=lib_sh_input_avail"); - println!("cargo:rustc-flags=-l dylib=lib_sh_shtty"); - println!("cargo:rustc-flags=-l dylib=lib_sh_zread"); - println!("cargo:rustc-flags=-l dylib=lib_sh_ufuncs"); - println!("cargo:rustc-flags=-l dylib=lib_sh_uconvert"); - println!("cargo:rustc-flags=-l dylib=pcomplib"); - println!("cargo:rustc-flags=-l dylib=bracecomp"); - println!("cargo:rustc-flags=-l dylib=lib_sh_spell"); - println!("cargo:rustc-flags=-l dylib=lib_sh_fnxform"); - println!("cargo:rustc-flags=-l dylib=lib_termcap_termcap"); - println!("cargo:rustc-flags=-l dylib=lib_termcap_tparam"); - println!("cargo:rustc-flags=-l dylib=builtins_bashgetopt"); - println!("cargo:rustc-flags=-l dylib=builtins_source"); - println!("cargo:rustc-flags=-l dylib=lib_sh_shmatch"); - println!("cargo:rustc-flags=-l dylib=test"); - println!("cargo:rustc-flags=-l dylib=builtins_return"); - println!("cargo:rustc-flags=-l dylib=builtins_exec"); - println!("cargo:rustc-flags=-l dylib=builtins_command"); - println!("cargo:rustc-flags=-l dylib=lib_sh_mbschr"); - println!("cargo:rustc-flags=-l dylib=expr"); - println!("cargo:rustc-flags=-l dylib=lib_sh_timeval"); - println!("cargo:rustc-flags=-l dylib=lib_sh_fpurge"); - println!("cargo:rustc-flags=-l dylib=builtins_fc"); - println!("cargo:rustc-flags=-l dylib=builtins_mapfile"); - println!("cargo:rustc-flags=-l dylib=builtins_eval"); - println!("cargo:rustc-flags=-l dylib=builtins_jobs"); - println!("cargo:rustc-flags=-l dylib=builtins_cd"); - println!("cargo:rustc-flags=-l dylib=builtins_shopt"); - println!("cargo:rustc-flags=-l dylib=builtins_echo"); - println!("cargo:rustc-flags=-l dylib=lib_glob_smatch"); - println!("cargo:rustc-flags=-l dylib=lib_sh_utf8"); - println!("cargo:rustc-flags=-l dylib=lib_readline_search"); - println!("cargo:rustc-flags=-l dylib=lib_readline_isearch"); - println!("cargo:rustc-flags=-l dylib=lib_sh_stringlist"); - println!("cargo:rustc-flags=-l dylib=builtins_complete"); - println!("cargo:rustc-flags=-l dylib=builtins_exit"); - println!("cargo:rustc-flags=-l dylib=lib_sh_tmpfile"); - println!("cargo:rustc-flags=-l dylib=lib_sh_netopen"); - println!("cargo:rustc-flags=-l dylib=lib_sh_eaccess"); - println!("cargo:rustc-flags=-l dylib=lib_readline_histsearch"); - println!("cargo:rustc-flags=-l dylib=lib_tilde_tilde"); - println!("cargo:rustc-flags=-l dylib=lib_sh_makepath"); - println!("cargo:rustc-flags=-l dylib=builtins_shift"); - println!("cargo:rustc-flags=-l dylib=lib_readline_parens"); - println!("cargo:rustc-flags=-l dylib=builtins_type"); - println!("cargo:rustc-flags=-l dylib=lib_sh_zmapfd"); - println!("cargo:rustc-flags=-l dylib=lib_sh_mailstat"); - println!("cargo:rustc-flags=-l dylib=builtins_builtins"); - println!("cargo:rustc-flags=-l dylib=builtins_kill"); - println!("cargo:rustc-flags=-l dylib=builtins_times"); - println!("cargo:rustc-flags=-l dylib=builtins_printf"); - println!("cargo:rustc-flags=-l dylib=builtins_umask"); - println!("cargo:rustc-flags=-l dylib=builtins_let"); - println!("cargo:rustc-flags=-l dylib=builtins_suspend"); - println!("cargo:rustc-flags=-l dylib=builtins_history"); - println!("cargo:rustc-flags=-l dylib=builtins_bind"); - println!("cargo:rustc-flags=-l dylib=builtins_fg_bg"); - println!("cargo:rustc-flags=-l dylib=builtins_builtin"); - println!("cargo:rustc-flags=-l dylib=builtins_alias"); - println!("cargo:rustc-flags=-l dylib=builtins_hash"); - println!("cargo:rustc-flags=-l dylib=builtins_enable"); - println!("cargo:rustc-flags=-l dylib=builtins_help"); - println!("cargo:rustc-flags=-l dylib=builtins_trap"); - println!("cargo:rustc-flags=-l dylib=builtins_caller"); - println!("cargo:rustc-flags=-l dylib=builtins_colon"); - println!("cargo:rustc-flags=-l dylib=builtins_ulimit"); - println!("cargo:rustc-flags=-l dylib=builtins_test"); - println!("cargo:rustc-flags=-l dylib=lib_sh_wcsnwidth"); - println!("cargo:rustc-flags=-l dylib=lib_readline_callback"); - println!("cargo:rustc-flags=-l dylib=lib_sh_zcatfd"); - println!("cargo:rustc-flags=-l dylib=lib_sh_zwrite"); - println!("cargo:rustc-flags=-l dylib=lib_sh_unicode"); - println!("cargo:rustc-flags=-l dylib=lib_sh_zgetline"); - println!("cargo:rustc-flags=-l dylib=lib_malloc_malloc"); - println!("cargo:rustc-flags=-l dylib=lib_sh_pathphys"); - println!("cargo:rustc-flags=-l dylib=lib_sh_fmtumax"); + println!("cargo:rustc-link-args=-Wl,--copy-dt-needed-entries -fpic"); + println!("cargo:rustc-flags=-l static=sh"); + println!("cargo:rustc-flags=-l dylib=rt"); } diff --git a/bash-5.1/builtins_rust/builtin/Cargo.toml b/bash-5.1/builtins_rust/builtin/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..7ee7ace7d057593b7109f08e4c7934075f34ff6d --- /dev/null +++ b/bash-5.1/builtins_rust/builtin/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "builtin" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +name = "rbuiltin" +crate-type = ["staticlib"] + +[dependencies] +libc = "0.2" +rcmd = {path="../cmd"} + diff --git a/bash-5.1/builtins_rust/builtin/src/builtin.rs b/bash-5.1/builtins_rust/builtin/src/builtin.rs new file mode 100644 index 0000000000000000000000000000000000000000..95d714721e68866706e0e47fccd038c223674d02 --- /dev/null +++ b/bash-5.1/builtins_rust/builtin/src/builtin.rs @@ -0,0 +1,4 @@ + +#[no_mangle] +pub unsafe extern "C" fn builtin_builtin(mut list: *mut WORD_LIST) -> libc::c_int { + diff --git a/bash-5.1/builtins_rust/builtin/src/intercdep.rs b/bash-5.1/builtins_rust/builtin/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..3d716d2290a13861733896872eb09b981e23c04b --- /dev/null +++ b/bash-5.1/builtins_rust/builtin/src/intercdep.rs @@ -0,0 +1,45 @@ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +/* +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} +*/ +pub const EX_USAGE: c_int = 258; +pub const EXECUTION_SUCCESS :c_int = 0; + +/* +pub const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +*/ +//typedef int sh_builtin_func_t PARAMS((WORD_LIST *)); /* sh_wlist_func_t */ +extern "C" { + static mut loption :*mut WORD_LIST; + pub fn no_options(list: *mut WORD_LIST) -> c_int; + pub fn builtin_address(command: *const c_char) -> extern "C" fn(w:*mut WORD_LIST) ->i32; + + static mut this_command_name: *mut libc::c_char; + + fn sh_notbuiltin(_: *mut libc::c_char); + fn find_shell_builtin(_: *mut libc::c_char) -> Option::; + static mut this_shell_builtin: Option::; + static mut loptend: *mut WORD_LIST; +} + +pub type sh_builtin_func_t = unsafe extern "C" fn(*mut WORD_LIST) -> i32; diff --git a/bash-5.1/builtins_rust/builtin/src/lib.rs b/bash-5.1/builtins_rust/builtin/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..3d546691d75c61889b9379072b5517e2e2621158 --- /dev/null +++ b/bash-5.1/builtins_rust/builtin/src/lib.rs @@ -0,0 +1,31 @@ +use libc::{c_int, c_char}; + +include!(concat!("intercdep.rs")); + +#[no_mangle] +pub extern "C" fn r_builtin_builtin(mut list: *mut WORD_LIST) -> i32 { + unsafe{ + let mut function: Option:: = None; + let mut command: *mut libc::c_char = 0 as *mut libc::c_char; + if no_options(list) != 0 { + return 258 as libc::c_int; + } + list = loptend; + if list.is_null() { + return 0 as libc::c_int; + } + command = (*(*list).word).word; + function = find_shell_builtin(command); + if function.is_none() { + sh_notbuiltin(command); + return 1 as libc::c_int; + } else { + this_command_name = command; + this_shell_builtin = function; + list = (*list).next; + return (Some(function.expect("non-null function pointer"))) + .expect("non-null function pointer")(list); + }; + } +} + diff --git a/bash-5.1/builtins_rust/caller/Cargo.toml b/bash-5.1/builtins_rust/caller/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..de77b46477196c4c31af0c2f43f20a390a7fc0a9 --- /dev/null +++ b/bash-5.1/builtins_rust/caller/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "rcaller" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +read = {path="../read"} + +[lib] +crate-type = ["staticlib","lib"] +name = "rcaller" diff --git a/bash-5.1/builtins_rust/caller/src/lib.rs b/bash-5.1/builtins_rust/caller/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..ac7d633670b5825f8efe4356ad1f5b661e458d90 --- /dev/null +++ b/bash-5.1/builtins_rust/caller/src/lib.rs @@ -0,0 +1,293 @@ +extern crate libc; +extern crate rread; + +use libc::{c_char,c_int,PT_NULL,c_long,printf,}; +use std::{ffi::{CStr,CString}, sync::Arc}; + +use rread::{SHELL_VAR,ARRAY,intmax_t,}; + +//struct +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + + +//enum + +//macro +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => { + 0 + } +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => { + 1 + } +} + + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! att_array { + () => { + 0x0000004 /* value is an array */ + } +} + +#[macro_export] +macro_rules! att_cell { + ($var:expr) => { + return (*($var).value) as *mut ARRAY; + } +} + +// #[macro_export] +// macro_rules! array_empty { +// ($a:expr) => { +// if (*($a)).num_elements == 0{ +// return true; +// } +// else{ +// return false ; +// } +// } +// } + +#[macro_export] +macro_rules! array_cell { + ($var:expr) => { + (*($var)).value as *mut ARRAY + + }; +} + +#[macro_export] +macro_rules! GET_ARRAY_FROM_VAR { + ($n:expr,$v:expr,$a:expr) => { + $v = find_variable($n); + if ($v) != std::ptr::null_mut() && array_p($v) != 0{ + $a = array_cell!($v); + } + else{ + $a = 0 as *mut ARRAY; + } + } +} + + + +#[macro_export] +macro_rules! CHECK_HELPOPT { + ($l:expr) => { + if $l != std::ptr::null_mut() && (*($l)).word != std::ptr::null_mut() && ISHELP((*(*($l)).word).word) == true{ + builtin_help(); + return EX_USAGE!(); + } + }; +} + +// #[macro_export] +// macro_rules! ISHELP { +// ($s:expr) => { +// let s_str = CString::new("--help").unwrap().as_ptr(); +// STREQ( ($s),s_str); +// }; +// } + + + +type arrayind_t = intmax_t; +//extern c +extern "C" { + static loptend:*mut WORD_LIST; + + fn builtin_help(); + fn find_variable(str:*const c_char)->*mut SHELL_VAR; + fn array_reference(a:*mut ARRAY,i:arrayind_t)->*mut c_char; + fn builtin_usage(); + fn no_options(list:*mut WORD_LIST)->i32; + fn legal_number(string:*mut c_char,result:*mut c_long)->i32; + fn sh_invalidnum(s:*mut c_char); +} + + +unsafe fn STREQ(a:*const c_char,b:*const c_char)->bool{ + return *a == *b && libc::strcmp(a,b) == 0; +} +unsafe fn ISHELP(s:*const c_char)->bool{ + // let s_str = CString::new("--help").unwrap().as_ptr(); + return STREQ( s,CString::new("--help").unwrap().as_ptr()); +} +unsafe fn array_p(var:*mut SHELL_VAR) ->i32 { + return (*var).attributes & att_array!(); +} +unsafe fn array_empty(a:*mut ARRAY)->bool{ + + if (*a).num_elements == 0{ + return true; + } + else{ + return false ; + } + +} + +//rust +#[no_mangle] +pub extern "C" fn r_caller_builtin(mut list:*mut WORD_LIST)->i32{ + let mut funcname_v:*mut SHELL_VAR = std::ptr::null_mut(); + let bash_source_v:*mut SHELL_VAR; + let bash_lineno_v:*mut SHELL_VAR; + let mut funcname_a:*mut ARRAY= std::ptr::null_mut(); + let mut bash_source_a:*mut ARRAY= std::ptr::null_mut(); + let mut bash_lineno_a:*mut ARRAY= std::ptr::null_mut(); + let funcname_s:*mut c_char; + let mut source_s:*mut c_char; + let mut lineno_s:*mut c_char; + let mut num:intmax_t = 0; + + println!("r_caller_builtin"); + + unsafe{ + CHECK_HELPOPT!(list); + + // let str= CString::new("FUNCNAME").unwrap().as_ptr(); + GET_ARRAY_FROM_VAR!(CString::new("FUNCNAME").unwrap().as_ptr(),funcname_v,funcname_a); + + // let str = { + // let tmp = CString::new("BASH_SOURCE"); + // let tmp2 = tmp.unwrap(); + // let tmp2.as_ptr() + // } + // let str= CString::new("BASH_SOURCE").unwrap().as_ptr(); + // let str_ptr = str.as_ptr(); + GET_ARRAY_FROM_VAR!(CString::new("BASH_SOURCE").unwrap().as_ptr(),bash_source_v,bash_source_a); + + // let str= CString::new("BASH_LINENO").unwrap().as_ptr(); + GET_ARRAY_FROM_VAR!(CString::new("BASH_LINENO").unwrap().as_ptr(),bash_lineno_v,bash_lineno_a); + + if bash_lineno_a.is_null() || array_empty(bash_lineno_a){ + return EXECUTION_FAILURE!(); + } + + if bash_source_a.is_null() || array_empty(bash_source_a){ + return EXECUTION_FAILURE!(); + } + + if no_options(list) != 0{ + return EX_USAGE!(); + } + + list = loptend; /* skip over possible `--' */ + /* If there is no argument list, then give short form: line filename. */ + if list.is_null(){ + lineno_s = array_reference(bash_lineno_a,0); + source_s = array_reference(bash_source_a,1); + + if !lineno_s.is_null(){ + lineno_s = lineno_s; + } + else{ + lineno_s = CString::new("NULL").unwrap().as_ptr() as *mut c_char; + } + + if !source_s.is_null(){ + source_s = source_s; + } + else{ + source_s = CString::new("NULL").unwrap().as_ptr() as *mut c_char; + } + let lineno_s_str = CStr::from_ptr(lineno_s).to_str().unwrap().to_owned(); + let source_s_str = CStr::from_ptr(source_s).to_str().unwrap().to_owned(); + println!("{} {}",lineno_s_str,source_s_str); + + return EXECUTION_SUCCESS!(); + } + + if funcname_a.is_null() || array_empty(funcname_a) { + return EXECUTION_FAILURE!(); + } + if legal_number((*(*list).word).word,&mut num) != 0{ + lineno_s = array_reference(bash_lineno_a,num); + source_s = array_reference(bash_source_a,num+1); + funcname_s = array_reference(funcname_a,num+1); + + if lineno_s == PT_NULL as *mut c_char || source_s == PT_NULL as *mut c_char || funcname_s == PT_NULL as *mut c_char{ + return EXECUTION_FAILURE!(); + } + let lineno_s_str = CStr::from_ptr(lineno_s).to_str().unwrap().to_owned(); + let funcname_s_str = CStr::from_ptr(funcname_s).to_str().unwrap().to_owned(); + let source_s_str = CStr::from_ptr(source_s).to_str().unwrap().to_owned(); + println!("{} {} {}",lineno_s_str,funcname_s_str,source_s_str); + } + else{ + sh_invalidnum((*(*list).word).word); + builtin_usage(); + return EX_USAGE!(); + } + + return EXECUTION_SUCCESS!(); + } +} + + + +/* +#ifdef LOADABLE_BUILTIN +static char *caller_doc[] = { +N_("Returns the context of the current subroutine call.\n\ + \n\ + Without EXPR, returns \"$line $filename\". With EXPR, returns\n\ + \"$line $subroutine $filename\"; this extra information can be used to\n\ + provide a stack trace.\n\ + \n\ + The value of EXPR indicates how many call frames to go back before the\n\ + current one; the top frame is frame 0."), + (char *)NULL +}; + +struct builtin caller_struct = { + "caller", + caller_builtin, + BUILTIN_ENABLED, + caller_doc, + "caller [EXPR]", + 0 +}; + +*/ + + + + + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/cd/Cargo.toml b/bash-5.1/builtins_rust/cd/Cargo.toml index 6c92c52d39437ba0815f490509217580c267f9d6..11db0d4add631a53e15a0dac8e6f11509d92e63c 100644 --- a/bash-5.1/builtins_rust/cd/Cargo.toml +++ b/bash-5.1/builtins_rust/cd/Cargo.toml @@ -3,7 +3,7 @@ authors = ["huzhengming"] name = "rcd" version = "0.0.1" build = "../build.rs" -edition = "2021" +edition = "2018" [dependencies] @@ -12,5 +12,5 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["cdylib"] +crate-type = ["staticlib"] name = "rcd" diff --git a/bash-5.1/builtins_rust/cd/src/lib.rs b/bash-5.1/builtins_rust/cd/src/lib.rs index bb10f8c86fbd5f00ae066e241575ed58af6a9ca5..adde5faf8195cccebda2dc7b0b533b806862e134 100644 --- a/bash-5.1/builtins_rust/cd/src/lib.rs +++ b/bash-5.1/builtins_rust/cd/src/lib.rs @@ -2,7 +2,7 @@ extern crate libc; extern crate nix; use libc::{c_char, c_long, c_void}; -use std::{ffi::CString}; +use std::{ffi::{CString, CStr}}; #[repr(C)] pub struct WORD_DESC { @@ -492,7 +492,7 @@ pub extern "C" fn r_resetxattr () { } #[no_mangle] -pub extern "C" fn r_cd_builtin (list:*mut WORD_LIST)->i32 { +pub extern "C" fn r_cd_builtin (mut list:*mut WORD_LIST)->i32 { let mut dirname:*mut c_char=std::ptr::null_mut(); let cdpath:*mut c_char; let mut path:*mut c_char; @@ -502,159 +502,168 @@ pub extern "C" fn r_cd_builtin (list:*mut WORD_LIST)->i32 { let mut opt:i32; let mut lflag:i32; let e:i32; + unsafe { - if restricted !=0 { - sh_restricted (0 as * mut c_char); - return EXECUTION_FAILURE!(); - } + if restricted !=0 { + sh_restricted (0 as * mut c_char); + return EXECUTION_FAILURE!(); + } - eflag = 0; - no_symlinks = no_symbolic_links; - xattrflag = 0; - reset_internal_getopt (); - let c_str_elp = CString::new("eLP").unwrap(); // from a &str, creates a new allocation - opt = internal_getopt (list, c_str_elp.as_ptr() as * mut c_char); - while opt != -1 { - let optu8:u8= opt as u8; - let optChar:char=char::from(optu8); - match optChar { - 'P'=>{no_symlinks = 1;} - 'L'=>{no_symlinks = 0;} - 'e'=>{eflag = 1;} - _=>{ - builtin_usage (); - return EX_USAGE!(); - } - } - opt =internal_getopt (list, c_str_elp.as_ptr() as * mut c_char); - } + eflag = 0; + no_symlinks = no_symbolic_links; + xattrflag = 0; + reset_internal_getopt (); + + let c_str_elp = CString::new("eLP").unwrap(); // from a &str, creates a new allocation + opt = internal_getopt (list, c_str_elp.as_ptr() as * mut c_char); + while opt != -1 { + let optu8:u8= opt as u8; + let optChar:char=char::from(optu8); + match optChar { + 'P'=>{no_symlinks = 1;} + 'L'=>{no_symlinks = 0;} + 'e'=>{eflag = 1;} + _=>{ + builtin_usage (); + return EX_USAGE!(); + } + } + opt =internal_getopt (list, c_str_elp.as_ptr() as * mut c_char); + } - if cdable_vars != 0 { - lflag=LCD_DOVARS!(); - } else { - lflag=0; - } + // list = loptend; //后加的 - if interactive !=0 && cdspelling !=0 { - lflag=lflag | LCD_DOSPELL!(); - } else { - lflag=lflag | 0; - } + if cdable_vars != 0 { + lflag=LCD_DOVARS!(); + } else { + lflag=0; + } - if eflag !=0 && no_symlinks == 0{ - eflag = 0; - } + if interactive !=0 && cdspelling !=0 { + lflag=lflag | LCD_DOSPELL!(); + } else { + lflag=lflag | 0; + } - if loptend == std::ptr::null_mut() { + if eflag !=0 && no_symlinks == 0{ + eflag = 0; + } + + if loptend == std::ptr::null_mut() { /* `cd' without arguments is equivalent to `cd $HOME' */ dirname = get_string_value (CString::new("HOME").unwrap().as_ptr()); if dirname == std::ptr::null_mut() { builtin_error (CString::new("HOME not set").unwrap().as_ptr()); return EXECUTION_FAILURE!(); - } + } lflag = 0; - }else if (*loptend).next != std::ptr::null_mut() { - builtin_error (CString::new("too many arguments").unwrap().as_ptr()); - return EXECUTION_FAILURE!(); - }else if char::from((*(*(*loptend).word).word) as u8) == '-' && char::from(*((((*(*loptend).word).word) as usize +4) as *mut c_char) as u8) == '\0' { - /* This is `cd -', equivalent to `cd $OLDPWD' */ - dirname = get_string_value (CString::new("OLDPWD").unwrap().as_ptr()); - - if dirname == std::ptr::null_mut() { - builtin_error (CString::new("OLDPWD not set").unwrap().as_ptr()); - return EXECUTION_FAILURE!(); - } - lflag = LCD_PRINTPATH!(); /* According to SUSv3 */ - } else if absolute_pathname ((*(*loptend).word).word) !=0 { - dirname = (*(*loptend).word).word; - } else if privileged_mode == 0 { - cdpath = get_string_value (CString::new("CDPATH").unwrap().as_ptr() ); - if cdpath !=std::ptr::null_mut() { - dirname = (*(*loptend).word).word; - /* Find directory in $CDPATH. */ - path_index = 0; - path = extract_colon_unit (cdpath, & mut path_index); - while path != std::ptr::null_mut() { + } + else if (*loptend).next != std::ptr::null_mut() { + builtin_error (CString::new("too many arguments").unwrap().as_ptr()); + return EXECUTION_FAILURE!(); + } + else if char::from((*(*(*loptend).word).word) as u8) == '-' && char::from(*((((*(*loptend).word).word) as usize +4) as *mut c_char) as u8) == '\0' { + /* This is `cd -', equivalent to `cd $OLDPWD' */ + dirname = get_string_value (CString::new("OLDPWD").unwrap().as_ptr()); + if dirname == std::ptr::null_mut() { + builtin_error (CString::new("OLDPWD not set").unwrap().as_ptr()); + return EXECUTION_FAILURE!(); + } + lflag = LCD_PRINTPATH!(); /* According to SUSv3 */ + } + else if absolute_pathname ((*(*loptend).word).word) !=0 { + dirname = (*(*loptend).word).word; + } + else if privileged_mode == 0 && get_string_value (CString::new("CDPATH").unwrap().as_ptr() ) != std::ptr::null_mut(){ + cdpath = get_string_value (CString::new("CDPATH").unwrap().as_ptr() ); + dirname = (*(*loptend).word).word; + + /* Find directory in $CDPATH. */ + path_index = 0; + path = extract_colon_unit (cdpath, & mut path_index); + + while path != std::ptr::null_mut() { /* OPT is 1 if the path element is non-empty */ opt = (char::from(*path as u8 )!= '\0') as i32 ; temp = sh_makepath (path, dirname, MP_DOTILDE!()); libc::free (path as * mut c_void); - if r_change_to_directory (temp, no_symlinks, xattrflag) !=0 { - /* POSIX.2 says that if a nonempty directory from CDPATH - is used to find the directory to change to, the new - directory name is echoed to stdout, whether or not - the shell is interactive. */ - if opt !=0 { - if no_symlinks !=0 { - path=temp; - } else { - path=the_current_working_directory; - } - - if path !=std::ptr::null_mut() { - libc::printf(CString::new("%s\n").unwrap().as_ptr() as * const c_char,path); - } - } - - libc::free (temp as * mut c_void); - return r_bindpwd (no_symlinks); - - } else { - libc::free (temp as * mut c_void); + if r_change_to_directory (temp, no_symlinks, xattrflag) !=0 { + /* POSIX.2 says that if a nonempty directory from CDPATH + is used to find the directory to change to, the new + directory name is echoed to stdout, whether or not + the shell is interactive. */ + if opt !=0 { + if no_symlinks !=0 { + path=temp; + } + else { + path=the_current_working_directory; + } + + if path !=std::ptr::null_mut() { + libc::printf(CString::new("%s\n").unwrap().as_ptr() as * const c_char,path); + } + } + + libc::free (temp as * mut c_void); + return r_bindpwd (no_symlinks); + } + else { + libc::free (temp as * mut c_void); + } + + path = extract_colon_unit (cdpath, &mut path_index); } - - path = extract_colon_unit (cdpath, &mut path_index); - } + } + else{ + dirname = (*(*loptend).word).word; } - } else{ - dirname = (*(*loptend).word).word; - } - /* When we get here, DIRNAME is the directory to change to. If we - chdir successfully, just return. */ - if 0 != r_change_to_directory (dirname, no_symlinks, xattrflag) { - if (lflag & LCD_PRINTPATH!()) !=0 { - libc::printf(CString::new("%s\n").unwrap().as_ptr() as * const c_char,dirname); + /* When we get here, DIRNAME is the directory to change to. If we + chdir successfully, just return. */ + if 0 != r_change_to_directory (dirname, no_symlinks, xattrflag) { + if (lflag & LCD_PRINTPATH!()) !=0 { + libc::printf(CString::new("%s\n").unwrap().as_ptr() as * const c_char,dirname); + } + return r_bindpwd (no_symlinks); } - return r_bindpwd (no_symlinks); - } - /* If the user requests it, then perhaps this is the name of - a shell variable, whose value contains the directory to - change to. */ - if (lflag & LCD_DOVARS!()) !=0 { + /* If the user requests it, then perhaps this is the name of + a shell variable, whose value contains the directory to + change to. */ + if (lflag & LCD_DOVARS!()) !=0 { temp = get_string_value (dirname); if temp != std::ptr::null_mut() && r_change_to_directory (temp, no_symlinks, xattrflag) !=0 { libc::printf(CString::new("%s\n").unwrap().as_ptr() as * const c_char,temp); return r_bindpwd (no_symlinks); } - } + } - /* If the user requests it, try to find a directory name similar in - spelling to the one requested, in case the user made a simple - typo. This is similar to the UNIX 8th and 9th Edition shells. */ - if (lflag & LCD_DOSPELL!()) !=0 { - temp = dirspell (dirname); - if temp !=std::ptr::null_mut() && r_change_to_directory (temp, no_symlinks, xattrflag) !=0 { - println!("{:?}", temp); - libc::free (temp as * mut c_void); - return r_bindpwd (no_symlinks); - } else { - libc::free (temp as * mut c_void); - } - } + /* If the user requests it, try to find a directory name similar in + spelling to the one requested, in case the user made a simple + typo. This is similar to the UNIX 8th and 9th Edition shells. */ + if (lflag & LCD_DOSPELL!()) !=0 { + temp = dirspell (dirname); + if temp !=std::ptr::null_mut() && r_change_to_directory (temp, no_symlinks, xattrflag) !=0 { + println!("{:?}", temp); + libc::free (temp as * mut c_void); + return r_bindpwd (no_symlinks); + } else { + libc::free (temp as * mut c_void); + } + } - e =errno!(); - temp = printable_filename (dirname, 0); - builtin_error (CString::new("%s: %s").unwrap().as_ptr(), temp, libc::strerror (e)); + e =errno!(); + temp = printable_filename (dirname, 0); + builtin_error (CString::new("%s: %s").unwrap().as_ptr(), temp, libc::strerror (e)); - if temp != dirname { - libc::free (temp as * mut c_void); - } - return EXECUTION_FAILURE!(); + if temp != dirname { + libc::free (temp as * mut c_void); + } + return EXECUTION_FAILURE!(); } } @@ -841,12 +850,13 @@ pub extern "C" fn r_change_to_directory (newdir:* mut c_char, nolinks:i32, xattr } } +/* #[no_mangle] pub extern "C" fn cmd_name() ->*const u8 { return b"cd" as *const u8; } - #[no_mangle] pub extern "C" fn run(list : *mut WORD_LIST)->i32 { return r_cd_builtin(list); -} \ No newline at end of file +} +*/ diff --git a/bash-5.1/builtins_rust/cmd/Cargo.toml b/bash-5.1/builtins_rust/cmd/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..880021d5177038bf50bba7bb901a93faeba2ef83 --- /dev/null +++ b/bash-5.1/builtins_rust/cmd/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "rcmd" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +lazy_static = "1.4.0" + +[lib] +crate-type = ["staticlib", "rlib"] +name = "rcmd" diff --git a/bash-5.1/builtins_rust/cmd/src/lib.rs b/bash-5.1/builtins_rust/cmd/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..53b51454b06c7c116735f0492eb8ea36767c6bf3 --- /dev/null +++ b/bash-5.1/builtins_rust/cmd/src/lib.rs @@ -0,0 +1,72 @@ +use std::collections::HashMap; +use std::sync::Mutex; + +#[macro_use] +extern crate lazy_static; + +pub struct Cmd { + name:String, + enable:bool, +} +impl Cmd { +pub fn build_cmd(name:String, enable:bool) -> Cmd { + Cmd { + name, + enable, + } +} + +pub fn set_enable(&mut self, is_enable:bool) -> &Cmd { + self.enable = is_enable; + self +} +pub fn get_enable(&self) -> bool { + return self.enable +} +} + +lazy_static! { +static ref CMD: Mutex>> = Mutex::new(HashMap::new()); +} +fn init_cmd_table() { +} + +pub fn insert_empty_cmd(cmd:String) -> bool { + let it = Cmd::build_cmd(String::from(&cmd[..]),true); + let mut cmd_table = CMD.lock().unwrap(); + cmd_table.insert(String::from(&cmd[..]), Box::new(it)); + return true; +} +pub fn insert_cmd(cmd:&str, item: Box) -> Option>{ + let mut cmd_table = CMD.lock().unwrap(); + cmd_table.insert(String::from(cmd), item) +} + +pub fn get_cmd_enable(cmd:String) -> Result{ + let mut cmd_table = CMD.lock().unwrap(); + let item = cmd_table.get(&cmd); + match item { + Some(c) => { + println!("name:{}, is {}!", cmd, c.enable); + + return Ok(c.enable); + } + None => { + return Err(cmd+" not found"); + } + } +} + +pub fn set_cmd_enable(cmd :String, is_enable:bool)->bool { + let mut a = CMD.lock().unwrap(); + let v = a.get_mut(&cmd); + match v { + Some(c) => { + c.enable = is_enable; + } + None => { + return false; + } + } + return true; +} diff --git a/bash-5.1/builtins_rust/colon/Cargo.toml b/bash-5.1/builtins_rust/colon/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..e55c8c3b3eaa2fc7cb8011ede5f6e97d60acc75a --- /dev/null +++ b/bash-5.1/builtins_rust/colon/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "rcolon" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["staticlib"] +name = "rcolon" + +[dependencies] +libc = "0.2" diff --git a/bash-5.1/builtins_rust/colon/src/lib.rs b/bash-5.1/builtins_rust/colon/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..ed63b7367475bd7856c24a76e785c40d63c6a9f1 --- /dev/null +++ b/bash-5.1/builtins_rust/colon/src/lib.rs @@ -0,0 +1,39 @@ +use std::{ffi::CString}; +use libc::{size_t, c_int, c_uint, c_char, c_long, c_void, PT_NULL, c_ulong, strchr}; + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +#[no_mangle] +pub extern "C" fn r_colon_builtin(ignore:WORD_LIST)->i32 { + println!("in r_colon_builtin"); + 0 +} + +#[no_mangle] +pub extern "C" fn r_false_builtin(ignore: WORD_LIST) -> i32 { + println!("in r_false_builtin"); + 1 +} diff --git a/bash-5.1/builtins_rust/common/Cargo.toml b/bash-5.1/builtins_rust/common/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..fd6f6441f5faa6259719c9bd2bbe899b5e73d479 --- /dev/null +++ b/bash-5.1/builtins_rust/common/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "rcommon" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +nix = "0.24" + + +[lib] +crate-type = ["staticlib"] +name = "rcommon" \ No newline at end of file diff --git a/bash-5.1/builtins_rust/common/src/lib.rs b/bash-5.1/builtins_rust/common/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..14da9d5152a38c6719531b5c439220964d13bde1 --- /dev/null +++ b/bash-5.1/builtins_rust/common/src/lib.rs @@ -0,0 +1,1710 @@ +extern crate libc; + +use libc::{c_char,c_int, c_void, FILE, size_t, intmax_t,c_long, strcmp}; +use libc::{isdigit,strerror, __errno_location, fflush, ferror,clearerr, free,strcpy,strlen,strncmp,atoi,qsort}; +use std::ffi::{CStr, CString}; +use std::intrinsics::transmute; +use std::io::stderr; +use std::mem::size_of; +use std::ptr::read_volatile; +use nix::errno::errno; + + +//struct +#[repr (C)] +#[derive(Copy,Clone)] +pub struct WORD_DESC{ + pub word:*mut c_char, + pub flags:c_int, +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct WORD_LIST{ + pub next:*mut WORD_LIST, + pub word:*mut WORD_DESC, +} + +#[repr (C)] +pub struct builtin{ + pub name:*mut c_char, + pub function:*mut sh_builtin_func_t, + pub flags:i32, + pub long_doc: *const *mut c_char , + pub short_doc:*const c_char, + pub handle:*mut c_char, +} + +#[repr (C)] +pub struct g_list{ + pub next:*mut g_list, +} +type GENERIC_LIST = g_list; + +#[repr (C)] +pub struct process{ + pub next:*mut process, + pub pid:pid_t, + pub status:WAIT, + pub running:i32, + pub command:*mut c_char, +} +type WAIT = i32; +type pid_t = c_int; +type PROCESS = process; + +#[repr(C)] +pub struct JOB { + wd: *mut c_char, + pipe: *mut PROCESS, + pgrp:i32, + state:JOB_STATE, + flags:i32, + deferred:*mut COMMAND, + j_cleanup:*mut fn(), + cleanarg:* mut fn() +} + +#[repr(C)] +pub struct COMMAND { + type_c:command_type, + flags:i32, + line:i32, + redirects:*mut REDIRECT, + value:VALUE_COMMAND, +} +#[repr(C)] +#[derive(Copy,Clone)] +pub union REDIRECTEE { + dest:libc::c_int, /* Place to redirect REDIRECTOR to, or ... */ + filename:* mut WORD_DESC /* filename to redirect to. */ +} + +#[repr(u8)] +#[derive(Copy,Clone)] +enum r_instruction { + r_output_direction, r_input_direction, r_inputa_direction, + r_appending_to, r_reading_until, r_reading_string, + r_duplicating_input, r_duplicating_output, r_deblank_reading_until, + r_close_this, r_err_and_out, r_input_output, r_output_force, + r_duplicating_input_word, r_duplicating_output_word, + r_move_input, r_move_output, r_move_input_word, r_move_output_word, + r_append_err_and_out +} + +#[repr(C)] +pub union REDIRECT { + next:*mut REDIRECT, /* Next element, or NULL. */ + redirector:REDIRECTEE, /* Descriptor or varname to be redirected. */ + rflags:libc::c_int, /* Private flags for this redirection */ + flags:libc::c_int, /* Flag value for `open'. */ + instruction:r_instruction, /* What to do with the information. */ + redirectee:REDIRECTEE, /* File descriptor or filename */ + here_doc_eof:*mut c_char /* The word that appeared in <*mut SHELL_VAR, /* Function called to return a `dynamic' + value for a variable, like $SECONDS + or $RANDOM. */ + assign_func:* mut fn(v:* mut SHELL_VAR,str1:* mut c_char,t:c_long,str2:* mut c_char)->*mut SHELL_VAR, /* Function called when this `special + variable' is assigned a value in + bind_variable. */ + attributes:i32, /* export, readonly, array, invisible... */ + context:i32 /* Which context this variable belongs to. */ +} + +//macro +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => { + 1 + }; +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => { + 0 + }; +} + +#[macro_export] +macro_rules! DISCARD { + () => { + 2 + }; +} + +#[macro_export] +macro_rules! GETOPT_HELP { + () => { + -99 + }; +} + +#[macro_export] +macro_rules! ARGS_INVOC { + () => { + 0x01 + }; +} + +#[macro_export] +macro_rules! ARGS_FUNC { + () => { + 0x02 + }; +} + +#[macro_export] +macro_rules! ARGS_SETBLTIN { + () => { + 0x04 + }; +} + +#[macro_export] +macro_rules! EX_BADUSAGE { + () => { + 2 + }; +} + +#[macro_export] +macro_rules! DEBUG_TRAP { + () => { + NSIG!() + }; +} + +#[macro_export] +macro_rules! NSIG { + () => { + 64 + }; +} + +#[macro_export] +macro_rules! NO_JOB { + () => { + -1 + }; +} + +#[macro_export] +macro_rules! DUP_JOB { + () => { + -2 + }; +} + +#[macro_export] +macro_rules! JM_SUBSTRING { + () => { + 0x02 + }; +} + +#[macro_export] +macro_rules! JM_EXACT { + () => { + 0x04 + }; +} + +#[macro_export] +macro_rules! JM_STOPPED { + () => { + 0x08 + }; +} + +#[macro_export] +macro_rules! JM_FIRSTMATCH { + () => { + 0x10 + }; +} + +#[macro_export] +macro_rules! VA_NOEXPAND { + () => { + 0x001 + }; +} + +#[macro_export] +macro_rules! VA_ONEWORD { + () => { + 0x002 + }; +} + +#[macro_export] +macro_rules! ASS_NOEXPAND { + () => { + 0x0080 + }; +} + +#[macro_export] +macro_rules! att_readonly { + () => { + 0x0000002 + }; +} + +#[macro_export] +macro_rules! att_invisible { + () => { + 0x0001000 + }; +} + +#[macro_export] +macro_rules! att_nounset { + () => { + 0x0002000 + }; +} + +#[macro_export] +macro_rules! att_noassign { + () => { + 0x0004000 + }; +} + +#[macro_export] +macro_rules! SPECIAL_BUILTIN { + () => { + 0x08 + }; +} + +#[macro_export] +macro_rules! BUILTIN_ENABLED { + () => { + 0x01 + }; +} + +#[macro_export] +macro_rules! BUILTIN_DELETED { + () => { + 0x02 + }; +} + +#[macro_export] +macro_rules! DSIG_SIGPREFIX { + () => { + 0x01 + }; +} + +#[macro_export] +macro_rules! DSIG_NOCASE { + () => { + 0x02 + }; +} + +#[macro_export] +macro_rules! NO_SIG { + () => { + -1 + }; +} + +#[macro_export] +macro_rules! readonly_p { + ($var:expr) => { + (*$var).attributes & att_readonly!() + }; +} + +#[macro_export] +macro_rules! noassign_p { + ($var:expr) => { + (*$var).attributes & att_noassign!() + }; +} + +#[macro_export] +macro_rules! non_unsettable_p { + ($var:expr) => { + (*$var).attributes & att_nounset!() + }; +} + +#[macro_export] +macro_rules! VUNSETATTR { + ($var:expr,$attr:expr) => { + (*$var).attributes &= !($attr) + }; +} + + + +#[macro_export] +macro_rules! ISOCTAL { + ($c:expr) => { + ($c) >= b'0' as i8 && ($c) <= b'7' as i8 + }; +} + +#[macro_export] +macro_rules! DIGIT { + ($c:expr) => { + ($c) >= b'0' as i8 && ($c) <= b'9' as i8 + }; +} + +#[macro_export] +macro_rules! QUIT { + () => { + if read_volatile(&terminating_signal as *const i32) != 0{ + termsig_handler(read_volatile(&terminating_signal as *const i32)); + } + if interrupt_state != 0{ + throw_to_top_level(); + } + }; +} + +#[macro_export] +macro_rules! savestring { + ($x:expr) => { + strcpy(xmalloc(1 + strlen($x)) as *mut c_char,$x) as *mut c_char + } +} + +#[macro_export] +macro_rules! FREE { + ($s:expr) => { + if ($s) != std::ptr::null_mut(){ + free($s); + } + } +} + +#[macro_export] +macro_rules! STREQN { + ($a:expr,$b:expr,$n:expr) => { + if $n == 0 { + 1 + } + else{ + (*$a == *$b && strncmp($a,$b,$n) == 0) as i32 + } + } +} + +#[macro_export] +macro_rules! get_job_by_jid { + ($ind:expr) => { + (*((jobs as usize + ($ind*8) as usize ) as *mut*mut JOB) as *mut JOB) + } +} + +#[macro_export] +macro_rules! J_JOBSTATE { + ($j:expr) => { + (*$j).state + } +} + +//enum +#[repr(i8)] +#[derive(PartialEq)] +pub enum JOB_STATE { + JNONE = -1, + JRUNNING = 1, + JSTOPPED = 2, + JDEAD = 4, + JMIXED = 8 +} + +//type +pub type sh_builtin_func_t = fn (*mut WORD_LIST)->i32; +pub type QSFUNC = unsafe extern "C" fn(*const c_void,*const c_void)->i32; + +//extern C +extern "C"{ + static interactive_shell:i32; + static this_command_name:*mut c_char; + static mut current_builtin:*mut builtin; + static terminating_signal:c_int; + static interrupt_state:c_int; + static stdout:*mut FILE; + static mut posparam_count:i32; + static mut dollar_vars:[*mut c_char;10]; + static mut rest_of_args:*mut WORD_LIST; + static test_of_args:*mut WORD_LIST; + static variable_context:i32; + static running_trap:i32; + static trap_saved_exit_value:i32; + static last_command_exit_value:i32; + static no_symbolic_links:i32; + static bsah_getcwd_errstr:*const c_char; + static js:jobstats; + static jobs:*mut*mut JOB; + static assoc_expand_once:i32; + static shell_builtins:*mut builtin; + static mut num_shell_builtins:i32; + static posixly_correct:i32; + + + fn get_name_for_error()->*mut c_char; + fn executing_line_number()->i32; + fn top_level_cleanup(); + fn jump_to_top_level(value:i32); + fn internal_getopt(list:*mut WORD_LIST,opts:*mut c_char)->i32; + fn reset_internal_getopt(); + fn termsig_handler(sig:i32); + fn throw_to_top_level(); + fn fpurge(stream:*mut FILE) ->i32; + fn strvec_from_word_list(list:WORD_LIST,alloc:i32,starting_index:i32,ip:*mut i32)->*mut *mut c_char; + fn xmalloc(n:size_t)->*mut c_void; + fn dispose_words(list:*mut WORD_LIST); + fn copy_word_list(list:*mut WORD_LIST)->*mut WORD_LIST; + fn list_length(list:*mut GENERIC_LIST)->i32; + fn invalidate_cached_quoted_dollar_at(); + fn set_builtin(list:*mut WORD_LIST)->i32; + fn legal_number(string:*mut c_char,result:*mut c_long)->i32; + fn return_builtin(list:*mut WORD_LIST)->i32; + fn getcwd(buf:*mut c_char,size:size_t)->*mut c_char; + fn internal_error(format:*const c_char,...); + fn strcasestr(s1:*const c_char,s2:*const c_char)->*mut c_char; + fn all_digits(string:*const c_char)->i32; + fn valid_array_reference(name:*const c_char,flags:i32)->i32; + fn bind_variable (name:* const c_char,value:* mut c_char,flags:i32)->* mut SHELL_VAR; + fn assign_array_element(name:*mut c_char,value:*mut c_char,flags:i32)->*mut SHELL_VAR; + fn find_variable(_:*const c_char)->*mut SHELL_VAR; + fn unbind_variable(name:*const c_char)->i32; + fn signal_name(sig:i32)->*mut c_char; + fn kill_builtin(list:*mut WORD_LIST)->i32; + fn decode_signal(string:*mut c_char,flags:i32)->i32; + fn builtin_help(); + + fn builtin_error(format:*const c_char,...); +} + +unsafe fn ISOPTION(s:* const c_char, c:c_char)->bool +{ + // return *s == '-' as c_char && *((s as usize + 1)as * mut c_char) == c && *((s as usize + 8)as * mut c_char) != 0; + return *s == '-' as c_char && *s.offset(1) == c && *s.offset(2) != 0; +} + + + + +/* Used by some builtins and the mainline code. */ +pub static mut last_shell_builtin:*mut sh_builtin_func_t = std::ptr::null_mut(); +pub static mut this_shell_builtin:*mut sh_builtin_func_t = std::ptr::null_mut(); + +/* **************************************************************** */ +/* */ +/* Error reporting, usage, and option processing */ +/* */ +/* **************************************************************** */ + +/* This is a lot like report_error (), but it is for shell builtins + instead of shell control structures, and it won't ever exit the + shell. */ + +#[no_mangle] +fn r_builitin_error_prolog(){ + let mut name:*mut c_char; + + unsafe{ + name = get_name_for_error(); + eprint!("{}: ",CStr::from_ptr(name).to_str().unwrap()); + + if interactive_shell == 0{ + eprint!("line {}: ",executing_line_number()) + } + + if !this_command_name.is_null() && *this_command_name!=0{ + eprint!("{}:",CStr::from_ptr(name).to_str().unwrap()); + } + } +} + +//builtin_error builtin_waring是可变参函数,先跳过 + + +/* Print a usage summary for the currently-executing builtin command. */ +#[no_mangle] +pub extern "C" fn r_builtin_usage(){ + unsafe{ + if !this_command_name.is_null() && *this_command_name != 0{ + eprint!("{}: usage: ",CStr::from_ptr(this_command_name).to_str().unwrap()); + eprintln!("{}",CStr::from_ptr((*current_builtin).short_doc).to_str().unwrap() ); + // stderr().flush(); + } + } + +} + +/* Return if LIST is NULL else barf and jump to top_level. Used by some + builtins that do not accept arguments. */ +#[no_mangle] +pub extern "C" fn r_no_args(list:*mut WORD_LIST){ + unsafe{ + let c_str = CString::new("too many arguments").unwrap().as_ptr(); + builtin_error(c_str); + top_level_cleanup(); + jump_to_top_level(DISCARD!()); + } +} + +/* Check that no options were given to the currently-executing builtin, + and return 0 if there were options. */ +#[no_mangle] +pub extern "C" fn r_no_options(list:*mut WORD_LIST)->i32{ + let mut opt:i32; + + unsafe{ + reset_internal_getopt(); + + opt = internal_getopt(list,std::ptr::null_mut()); + if opt != -1{ + if opt == GETOPT_HELP!(){ + builtin_help(); + return 2; + } + r_builtin_usage(); + return 1; + } + return 0; + } +} + +#[no_mangle] +pub extern "C" fn r_sh_needarg(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: option requires an argument").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_neednumarg(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: numeric argument requited").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + + +#[no_mangle] +pub extern "C" fn r_sh_notfound(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: not found").unwrap().as_ptr(); + builtin_error(c_str,s); + } + +} + +/* Function called when one of the builtin commands detects an invalid + option. */ +#[no_mangle] +pub extern "C" fn r_sh_invalidop(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: invalid option").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_invalidoptname(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: invalid option name").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_invalidid(s:*mut c_char){ + unsafe{ + let c_str = CString::new("`%s': not a valid identifier").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_invalidnum(s:*mut c_char){ + unsafe{ + let msg:*mut c_char; + + if *s == b'0' as i8 && isdigit(*s.offset(1) as c_int) != 0{ + msg = CString::new("invalid octal number").unwrap().as_ptr() as *mut c_char; + } + else if *s == b'0' as i8 && *s.offset(1) == b'x' as i8{ + msg = CString::new("invalid hex number").unwrap().as_ptr() as *mut c_char; + } + else { + msg = CString::new("invalid number").unwrap().as_ptr() as *mut c_char; + } + + let c_str = CString::new("%s: %s").unwrap().as_ptr(); + builtin_error(c_str,s,msg); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_invalidsig(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: invalid signal specification").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_badpid(s:*mut c_char){ + unsafe{ + let c_str = CString::new("`%s': not a pid or valid job spec").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_readonly(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: readonly variable").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_erange(s:*mut c_char,desc:*mut c_char){ + unsafe{ + if !s.is_null(){ + let c_str = CString::new("%s: %s out of range").unwrap().as_ptr(); + if !desc.is_null(){ + builtin_error(c_str, s,desc); + } + else{ + let desc_str = CString::new("argument").unwrap().as_ptr(); + builtin_error(c_str, s,desc_str); + } + } + else{ + let c_str = CString::new("%s out of range").unwrap().as_ptr(); + let desc_str = CString::new("argument").unwrap().as_ptr(); + builtin_error(c_str,desc_str) + } + } +} + +#[no_mangle] +pub extern "C" fn r_sh_badjob(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: no job control").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_nojobs(s:*mut c_char){ + unsafe{ + if !s.is_null(){ + let c_str = CString::new("%s: no job control").unwrap().as_ptr(); + builtin_error(c_str,s); + } + else{ + let c_str = CString::new("no job control").unwrap().as_ptr(); + builtin_error(c_str); + } + } +} + +#[no_mangle] +pub extern "C" fn r_sh_restricted(s:*mut c_char){ + unsafe{ + if !s.is_null(){ + let c_str = CString::new("%s: restricted").unwrap().as_ptr(); + builtin_error(c_str,s); + } + else{ + let c_str = CString::new("restricted").unwrap().as_ptr(); + builtin_error(c_str); + } + } +} + +#[no_mangle] +pub extern "C" fn r_sh_notbuiltin(s:*mut c_char){ + unsafe{ + let c_str = CString::new("%s: not a shell builtin").unwrap().as_ptr(); + builtin_error(c_str,s); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_wrerror(){ + unsafe{ + let c_str = CString::new("write error: %s").unwrap().as_ptr(); + builtin_error(c_str,strerror(*__errno_location())); + } +} + +#[no_mangle] +pub extern "C" fn r_sh_ttyerror(set:i32){ + unsafe{ + if set != 0{ + let c_str = CString::new("error setting terminal attributes: %s").unwrap(); + let c_str_ptr = c_str.as_ptr(); + builtin_error(c_str_ptr,strerror(*__errno_location())); + } + else{ + let c_str = CString::new("error getting terminal attributes: %s").unwrap(); + let c_str_ptr = c_str.as_ptr(); + builtin_error(c_str_ptr,strerror(*__errno_location())); + } + } +} + +#[no_mangle] +pub extern "C" fn r_sh_chkwrite(s:i32)->i32{ + unsafe{ + QUIT!(); + fflush(stdout); + QUIT!(); + + if ferror(stdout) != 0{ + r_sh_wrerror(); + fpurge(stdout); + clearerr(stdout); + return EXECUTION_FAILURE!(); + } + return s; + } +} + +/* **************************************************************** */ +/* */ +/* Shell positional parameter manipulation */ +/* */ +/* **************************************************************** */ + +/* Convert a WORD_LIST into a C-style argv. Return the number of elements + in the list in *IP, if IP is non-null. A convenience function for + loadable builtins; also used by `test'. */ +#[no_mangle] +pub extern "C" fn r_make_builtin_argv(list:WORD_LIST,ip:*mut i32)->*mut *mut c_char{ + let argv:*mut *mut c_char; + unsafe{ + argv = strvec_from_word_list(list,0,1,ip); + *argv.offset(0) = this_command_name; + return argv; + } +} + +/* Remember LIST in $1 ... $9, and REST_OF_ARGS. If DESTRUCTIVE is + non-zero, then discard whatever the existing arguments are, else + only discard the ones that are to be replaced. Set POSPARAM_COUNT + to the number of args assigned (length of LIST). */ +#[no_mangle] +pub extern "C" fn r_remember_args(mut list:*mut WORD_LIST,destructive:i32){ + let mut i:i32; + + unsafe{ + posparam_count = 0; + i = 1; + while i<10{ + if (destructive !=0 || list != std::ptr::null_mut()) && *dollar_vars.as_ptr().offset(i as isize) != std::ptr::null_mut(){ + free(*dollar_vars.as_ptr().offset(i as isize) as *mut c_void); + *dollar_vars.as_mut_ptr().offset(i as isize) = std::ptr::null_mut(); + } + + if !list.is_null(){ + posparam_count = i; + *dollar_vars.as_mut_ptr().offset(posparam_count as isize) = savestring!((*(*list).word).word); + list = (*list).next; + } + i += 1; + } + + /* If arguments remain, assign them to REST_OF_ARGS. + Note that copy_word_list (NULL) returns NULL, and + that dispose_words (NULL) does nothing. */ + if destructive !=0 || !list.is_null(){ + dispose_words(rest_of_args); + rest_of_args = copy_word_list(list); + posparam_count += list_length(list as *mut GENERIC_LIST);//there is may be problems + } + + if destructive != 0{ + r_set_dollar_vars_changed(); + } + invalidate_cached_quoted_dollar_at(); + } +} + +#[no_mangle] +pub extern "C" fn r_shift_args(mut times:i32){ + let mut temp:*mut WORD_LIST; + // let mut count:i32; + + unsafe{ + if times <= 0{ + return; + } + + times -= 1; //可能存在问题 + while times > 0 { + if *dollar_vars.as_ptr().offset(1) != std::ptr::null_mut(){ + free(*dollar_vars.as_ptr().offset(1) as *mut c_void); + } + + for count in 1..9{ + *dollar_vars.as_mut_ptr().offset(count) = *dollar_vars.as_ptr().offset(count+1) + } + + if !rest_of_args.is_null(){ + temp = rest_of_args; + *dollar_vars.as_mut_ptr().offset(9) = savestring!((*(*temp).word).word); + rest_of_args = (*test_of_args).next; + (*temp).next = std::ptr::null_mut(); + dispose_words(temp); + } + else{ + *dollar_vars.as_mut_ptr().offset(9) = std::ptr::null_mut(); + } + + posparam_count -= 1; + + times -= 1; + } + } +} + +#[no_mangle] +pub extern "C" fn r_number_of_args()->i32{ + unsafe{ + return posparam_count; + } +} + +static mut changed_dollar_vars:i32 = 0; + +/* Have the dollar variables been reset to new values since we last + checked? */ + +#[no_mangle] +pub extern "C" fn r_dollar_vars_changed()->i32{ + unsafe{ + return changed_dollar_vars; + } +} + +#[no_mangle] +pub extern "C" fn r_set_dollar_vars_unchanged(){ + unsafe{ + changed_dollar_vars = 0; + } +} + +#[no_mangle] +pub extern "C" fn r_set_dollar_vars_changed(){ + unsafe{ + if variable_context != 0{ + changed_dollar_vars |= ARGS_FUNC!(); + } + else if this_shell_builtin == set_builtin as *mut sh_builtin_func_t{ //there may be problems + changed_dollar_vars |= ARGS_SETBLTIN!(); + } + else{ + changed_dollar_vars |= ARGS_INVOC!(); + } + } +} + + +/* **************************************************************** */ +/* */ +/* Validating numeric input and arguments */ +/* */ +/* **************************************************************** */ + +/* Read a numeric arg for this_command_name, the name of the shell builtin + that wants it. LIST is the word list that the arg is to come from. + Accept only the numeric argument; report an error if other arguments + follow. If FATAL is 1, call throw_to_top_level, which exits the + shell; if it's 2, call jump_to_top_level (DISCARD), which aborts the + current command; if FATAL is 0, return an indication of an invalid + number by setting *NUMOK == 0 and return -1. */ +#[no_mangle] +pub extern "C" fn r_get_numeric_arg(mut list:*mut WORD_LIST,fatal:i32,count:*mut intmax_t)->i32{ + let arg:*mut c_char; + unsafe{ + if !count.is_null(){ + *count = 1; + } + + if !list.is_null() && !(*list).word.is_null() && ISOPTION((*(*list).word).word,b'-' as i8){ + list = (*list).next; + } + + if !list.is_null(){ + arg = (*(*list).word).word; + if !arg.is_null() || legal_number(arg,count) == 0{ + if !(*(*list).word).word.is_null(){ + r_sh_neednumarg((*(*list).word).word); + } + else { + r_sh_neednumarg(String::from("`'").as_ptr() as *mut i8); + } + + if fatal == 0{ + return 0; + } + else if fatal == 1{ /* fatal == 1; abort */ + throw_to_top_level(); + } + else{ /* fatal == 2; discard current command */ + top_level_cleanup(); + jump_to_top_level(DISCARD!()); + } + } + + r_no_args((*list).next); + } + return 1; + } +} + +/* Get an eight-bit status value from LIST */ +#[no_mangle] +pub extern "C" fn r_get_exitstat(mut list:*mut WORD_LIST)->i32{ + let mut status:i32; + let mut sval:intmax_t = 0; + let mut arg:*mut c_char; + + unsafe{ + if !list.is_null() && !(*list).word.is_null() && ISOPTION((*(*list).word).word,b'-' as i8){ + list = (*list).next; + } + + if list.is_null(){ + /* If we're not running the DEBUG trap, the return builtin, when not + given any arguments, uses the value of $? before the trap ran. If + given an argument, return uses it. This means that the trap can't + change $?. The DEBUG trap gets to change $?, though, since that is + part of its reason for existing, and because the extended debug mode + does things with the return value. */ + if this_shell_builtin == return_builtin as *mut sh_builtin_func_t && running_trap > 0 && running_trap != DEBUG_TRAP!()+1{ + return trap_saved_exit_value; + } + return last_command_exit_value; + } + + arg = (*(*list).word).word; + if arg.is_null() || legal_number(arg,&mut sval) == 0{ + if !(*(*list).word).word.is_null(){ + r_sh_neednumarg((*(*list).word).word); + } + else { + r_sh_neednumarg(String::from("`'").as_ptr() as *mut i8); + } + + return EX_BADUSAGE!(); + } + + r_no_args((*list).next); + + status = (sval & 255) as i32; + return status; + } +} + +/* Return the octal number parsed from STRING, or -1 to indicate + that the string contained a bad number. */ +#[no_mangle] +pub extern "C" fn r_read_octal(mut string:*mut c_char)->i32{ + let mut result:i32 = 0; + let mut digits:i32 = 0; + + unsafe{ + while *string!=0 && ISOCTAL!(*string){ + digits += 1; + result = (result * 8) + (*string - b'0' as i8) as i32; + string = (string as usize + 1 ) as *mut c_char; + if result > 0o7777{ + return -1; + } + } + + if digits == 0 || *string != 0{ + result = -1; + } + + return result; + } +} + + +/* **************************************************************** */ +/* */ +/* Manipulating the current working directory */ +/* */ +/* **************************************************************** */ + +/* Return a consed string which is the current working directory. + FOR_WHOM is the name of the caller for error printing. */ + +pub static mut the_current_working_directory:*mut c_char = std::ptr::null_mut(); + +#[no_mangle] +pub extern "C" fn r_get_working_directory(for_whom:*mut c_char)->*mut c_char{ + unsafe{ + if no_symbolic_links != 0{ + FREE!(the_current_working_directory as *mut c_void); + the_current_working_directory = std::ptr::null_mut(); + } + + if the_current_working_directory.is_null(){ + the_current_working_directory = getcwd(0 as *mut c_char,0); + + if the_current_working_directory.is_null(){ + let strerror_str = CStr::from_ptr(strerror(errno())); + let strerror_string = strerror_str.to_str().unwrap().to_owned(); + let bash_getcwd_errstr = String::from("getcwd: cannot access parent directories"); + if !for_whom.is_null() && *for_whom!=0{ + let for_whom_str = CStr::from_ptr(for_whom); + let for_whom_string = for_whom_str.to_str().unwrap().to_owned(); + eprintln!("{}: error retrieving current directory: {}: {}",for_whom_string,bash_getcwd_errstr,strerror_string); + } + else{ + let for_whom_str = CStr::from_ptr(get_name_for_error()); + let for_whom_string = for_whom_str.to_str().unwrap().to_owned(); + eprintln!("{}: error retrieving current directory: {}: {}",for_whom_string,bash_getcwd_errstr,strerror_string); + } + return std::ptr::null_mut(); + } + } + return savestring!(the_current_working_directory); + } +} + +#[no_mangle] +pub extern "C" fn r_set_working_dierctory(name:*mut c_char){ + unsafe{ + FREE!(the_current_working_directory as *mut c_void); + the_current_working_directory = savestring!(name); + } +} + +/* **************************************************************** */ +/* */ +/* Job control support functions */ +/* */ +/* **************************************************************** */ +#[no_mangle] +pub extern "C" fn r_get_job_by_name(name:*const c_char,flags:i32)->i32{ + let mut i:i32; + let mut wl:i32; + let mut cl:i32; + let mut match_0:i32; + let mut job:i32; + let mut p:*mut PROCESS; + let mut j:*mut JOB; + + unsafe{ + job = NO_JOB!(); + wl = strlen(name) as i32; + + i = js.j_jobslots - 1; + while i >= 0{ + j = get_job_by_jid!(i); + if j.is_null() || ( flags & JM_STOPPED!() != 0 && J_JOBSTATE!(j) != JOB_STATE::JSTOPPED){ + continue; + } + + p = (*j).pipe; + + loop{ + if (flags & JM_EXACT!()) != 0{ + cl = strlen((*p).command) as i32; + match_0 = STREQN!((*p).command,name,cl as usize); + } + else if (flags & JM_SUBSTRING!()) != 0{ + match_0 = (strcasestr((*p).command,name) != 0 as *mut c_char) as i32; + } + else{ + match_0 = STREQN!((*p).command,name,wl as usize); + } + + if match_0 == 0{ + p = (*p).next; + continue; + } + else if flags & JM_FIRSTMATCH!() != 0{ + return i; + } + else if job != NO_JOB!(){ + if !this_shell_builtin.is_null(){ + let c_str = CString::new("%s: ambiguous job spece").unwrap(); + let c_str_ptr = c_str.as_ptr(); + builtin_error(c_str_ptr,name); + } + else{ + let c_str = CString::new("%s: ambiguous job spece").unwrap(); + let c_str_ptr = c_str.as_ptr(); + internal_error(c_str_ptr,name) + } + return DUP_JOB!(); + } + else{ + job = i; + } + + if p == (*j).pipe{ + break; + } + } + + i -= 1; + } + return job; + } +} + +/* Return the job spec found in LIST. */ +#[no_mangle] +pub extern "C" fn r_get_job_spec(list:*mut WORD_LIST)->i32{ + let mut word:*mut c_char; + let mut job:i32; + let mut jflags:i32; + + unsafe{ + if list.is_null(){ + return js.j_current; + } + + word = (*(*list).word).word; + + if *word.offset(0) == '\0' as i8 { + return NO_JOB!(); + } + + if *word.offset(0) == '%' as i8 { + word = word.offset(1); + } + + if DIGIT!(*word) && all_digits(word) != 0{ + job = atoi(word); + if job<0 || job>js.j_jobslots{ + return NO_JOB!(); + } + else{ + return job -1; + } + } + + jflags = 0; + let opt = word.offset(0) as u8; + let opt_char = char::from(opt); + match opt_char{ + '\0'|'%' | '+' => return js.j_current, + '-' => return js.j_previous, + '?' => { + jflags |= JM_SUBSTRING!(); + word = word.offset(1); + } + _ => {}, + } + return r_get_job_by_name(word, jflags); + } +} + +/* + * NOTE: `kill' calls this function with forcecols == 0 + */ +pub extern "C" fn r_display_signal_list(mut list:*mut WORD_LIST,forcecols:i32)->i32{ + let mut i:i32; + let mut column:i32; + let mut name:*mut c_char; + let mut result:i32; + let mut signum:i32; + let mut dflags:i32; + let mut lsignum:intmax_t = 0; + + unsafe{ + result = EXECUTION_SUCCESS!(); + if list.is_null(){ + column = 0; + for i in 1..NSIG!() { + name = signal_name(i); + if STREQN!(name,String::from("SIGJUNK").as_ptr() as *mut c_char,7) != 0|| + STREQN!(name,String::from("Unknown").as_ptr() as *mut c_char,7) != 0 { + continue; + } + + if posixly_correct != 0 && forcecols != 0{ + /* This is for the kill builtin. POSIX.2 says the signal names + are displayed without the `SIG' prefix. */ + if STREQN!(name,String::from("SIG").as_ptr() as *mut c_char,3) != 0{ + name = name.offset(3); + if i == NSIG!() - 1{ + print!("{}",CStr::from_ptr(name).to_str().unwrap().to_owned()); + } + else { + print!("{} ",CStr::from_ptr(name).to_str().unwrap().to_owned()); + } + } + } + else{ + print!("{:02} {}",i,CStr::from_ptr(name).to_str().unwrap().to_owned()); + + column += 1; + if column < 5{ + print!{"\t"}; + } + else{ + print!("\n"); + column = 0; + } + } + } + + if posixly_correct != 0 && forcecols != 0 || column != 0{ + print!("\n"); + } + return result; + } //if list.is_null() + + /* List individual signal names or numbers. */ + while !list.is_null(){ + if legal_number((*(*list).word).word,&mut lsignum) != 0{ + /* This is specified by Posix.2 so that exit statuses can be + mapped into signal numbers. */ + if lsignum > 128{ + lsignum -= 128; + } + if lsignum<0 || lsignum >= NSIG!(){ + r_sh_invalidsig((*(*list).word).word); + result = EXECUTION_FAILURE!(); + list = (*list).next; + continue; + } + + signum = lsignum as i32; + name = signal_name(signum); + if STREQN!(name,String::from("SIGJUNK").as_ptr() as *mut c_char,7) != 0|| + STREQN!(name,String::from("Unknow").as_ptr() as *mut c_char,7) != 0{ + list = (*list).next; + continue; + } + /* POSIX.2 says that `kill -l signum' prints the signal name without + the `SIG' prefix. */ + if this_shell_builtin == kill_builtin as *mut sh_builtin_func_t && signum > 0{ + // name = name.offset(3); + println!("{}",CStr::from_ptr(name.offset(3)).to_str().unwrap().to_owned()); + } + else { + println!("{}",CStr::from_ptr(name).to_str().unwrap().to_owned()); + } + } + else{ + dflags = DSIG_NOCASE!(); + if posixly_correct == 0 || this_shell_builtin != kill_builtin as *mut sh_builtin_func_t{ + dflags |= DSIG_SIGPREFIX!(); + } + signum = decode_signal((*(*list).word).word,dflags); + if signum == NO_SIG!(){ + r_sh_invalidsig((*(*list).word).word); + result = EXECUTION_FAILURE!(); + list = (*list).next; + continue; + } + println!("{}",signum); + } + list = (*list).next; + }//while + return result; + } +} + + +/* **************************************************************** */ +/* */ +/* Finding builtin commands and their functions */ +/* */ +/* **************************************************************** */ + +/* Perform a binary search and return the address of the builtin function + whose name is NAME. If the function couldn't be found, or the builtin + is disabled or has no function associated with it, return NULL. + Return the address of the builtin. + DISABLED_OKAY means find it even if the builtin is disabled. */ + +extern "C" fn r_builtin_address_internal(name:*mut c_char,disabled_okay:i32)->*mut builtin{ + let mut hi:i32; + let mut lo:i32; + let mut mid:i32 = 0; + let mut j:i32; + + unsafe{ + hi = num_shell_builtins -1; + lo = 0; + + while lo <= hi { + mid = (lo + hi) / 2; + + j = (*((*shell_builtins.offset(mid as isize)).name).offset(0) - *name.offset(0)) as i32; + + if j==0{ + j = strcmp((*shell_builtins.offset(mid as isize)).name,name); + } + + if j==0{ + /* It must have a function pointer. It must be enabled, or we + must have explicitly allowed disabled functions to be found, + and it must not have been deleted. */ + if !(*shell_builtins.offset(mid as isize)).function.is_null() && + (*shell_builtins.offset(mid as isize)).flags & BUILTIN_DELETED!() == 0 && + (*shell_builtins.offset(mid as isize)).flags & BUILTIN_ENABLED!() != 1 || + disabled_okay != 0{ + return &mut *shell_builtins.offset(mid as isize); + } + else { + return 0 as *mut builtin; + } + } + + if j > 0{ + hi = mid -1; + } + else{ + lo = mid + 1; + } + } + + return 0 as *mut builtin; + } +} + +/* Return the pointer to the function implementing builtin command NAME. */ +pub extern "C" fn r_find_shell_builtin(name:*mut c_char)->*mut sh_builtin_func_t{ + unsafe{ + current_builtin = r_builtin_address_internal(name,0); + if !current_builtin.is_null(){ + return (*current_builtin).function; + } + else{ + return 0 as *mut sh_builtin_func_t; + } + } +} + +/* Return the address of builtin with NAME, whether it is enabled or not. */ +pub extern "C" fn r_builtin_address(name:*mut c_char)->*mut sh_builtin_func_t{ + unsafe{ + current_builtin = r_builtin_address_internal(name,1); + if !current_builtin.is_null(){ + return (*current_builtin).function; + } + else{ + return 0 as *mut sh_builtin_func_t; + } + } +} + +/* Return the function implementing the builtin NAME, but only if it is a + POSIX.2 special builtin. */ +#[no_mangle] +pub extern "C" fn r_find_special_builtin(name:*mut c_char)->*mut sh_builtin_func_t{ + unsafe{ + current_builtin = r_builtin_address_internal(name,0); + + if !current_builtin.is_null() && (*current_builtin).flags & SPECIAL_BUILTIN!() != 0{ + return (*current_builtin).function; + } + else { + return 0 as *mut sh_builtin_func_t; + } + } +} + +#[no_mangle] +extern "C" fn r_shell_builtin_compare(sbp1:*mut builtin,sbp2:*mut builtin)->i32{ + let mut result:i32; + + unsafe{ + result = (*((*sbp1).name).offset(0) - *((*sbp2).name).offset(0)) as i32; + if result == 0{ + result = strcmp((*sbp1).name, (*sbp2).name); + } + return result; + } +} + +/* Sort the table of shell builtins so that the binary search will work + in find_shell_builtin. */ +#[no_mangle] +pub extern "C" fn initialize_shell_builtins(){ + unsafe{ + qsort(shell_builtins as *mut c_void, + num_shell_builtins as usize, + size_of::(), + std::mem::transmute::< + Option:: libc::c_int>, + Option:: + >( + Some( + std::mem::transmute::< + unsafe extern "C" fn(*mut builtin, *mut builtin) -> c_int, + unsafe extern "C" fn() -> c_int, + >(r_shell_builtin_compare), + ), + ), + ); + } +} + + +/* **************************************************************** */ +/* */ +/* Variable assignments during builtin commands */ +/* */ +/* **************************************************************** */ +#[no_mangle] +pub extern "C" fn r_builtin_bind_variablel(name:*mut c_char,value:*mut c_char,flags:i32)->*mut SHELL_VAR{ + let mut v:*mut SHELL_VAR; + + unsafe{ + let mut opt:i32; + if assoc_expand_once != 0{ + opt = VA_NOEXPAND!() | VA_ONEWORD!(); + } + else{ + opt = 0; + } + + if valid_array_reference(name,opt) == 0{ + v = bind_variable(name,value,flags); + } + else{ + v = assign_array_element( + name, + value, + flags + | (if assoc_expand_once != 0{ + ASS_NOEXPAND!() + } else{ + 0 + }), + ); + } + + if !v.is_null() && readonly_p!(v)==0 && noassign_p!(v) ==0 { + VUNSETATTR!(v,att_invisible!()); + } + return v; + } +} + +/* Like check_unbind_variable, but for use by builtins (only matters for + error messages). */ +pub extern "C" fn r_builtin_unbind_variable(vname:*const c_char)->i32{ + let mut v:*mut SHELL_VAR; + + unsafe{ + v = find_variable(vname); + if !v.is_null() && readonly_p!(v) != 0{ + let c_str = CString::new("%s: cannot unset: readonly %s").unwrap(); + let c_str_ptr = c_str.as_ptr(); + builtin_error(c_str_ptr,vname,"variable"); + return -2; + } + + else if !v.is_null() && non_unsettable_p!(v) != 0{ + let c_str = CString::new("%s: cannot unset").unwrap(); + let c_str_ptr = c_str.as_ptr(); + builtin_error(c_str_ptr,vname); + return -2 + } + + return unbind_variable(vname); + } +} + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/complete/Cargo.toml b/bash-5.1/builtins_rust/complete/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..0bb6fe90b1adecf93b2e07ce124e6129478808a6 --- /dev/null +++ b/bash-5.1/builtins_rust/complete/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["huzhengming"] +name = "rcomplete" +version = "0.0.1" +##build = "../build.rs" +edition = "2018" + + +[dependencies] +lazy_static = "1.4.0" +libc = "0.2" +nix = "0.23.0" + +[lib] +crate-type = ["cdylib"] +name = "rcomplete" diff --git a/bash-5.1/builtins_rust/complete/src/lib.rs b/bash-5.1/builtins_rust/complete/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..d00afdf7de2705ac7a918839b467f67c998f7bc9 --- /dev/null +++ b/bash-5.1/builtins_rust/complete/src/lib.rs @@ -0,0 +1,1414 @@ +extern crate libc; +extern crate nix; + +use libc::{c_char, c_int, c_ulong, c_void}; +use std::{ffi::CString}; + +#[repr(C)] +pub struct WORD_DESC { + pub word: *mut c_char, + pub flags:c_int +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub struct WORD_LIST { + next: *mut WORD_LIST, + word: *mut WORD_DESC +} + +#[repr(u8)] +enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select, + cm_connection, cm_function_def, cm_until, cm_group, + cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc +} + +#[repr(u8)] +#[derive(Copy,Clone)] +enum r_instruction { + r_output_direction, r_input_direction, r_inputa_direction, + r_appending_to, r_reading_until, r_reading_string, + r_duplicating_input, r_duplicating_output, r_deblank_reading_until, + r_close_this, r_err_and_out, r_input_output, r_output_force, + r_duplicating_input_word, r_duplicating_output_word, + r_move_input, r_move_output, r_move_input_word, r_move_output_word, + r_append_err_and_out +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub union REDIRECTEE { + dest:c_int, + filename:* mut WORD_DESC +} + +#[repr(C)] +pub union REDIRECT { + next:*mut REDIRECT, + redirector:REDIRECTEE, + rflags:c_int, + flags:c_int, + instruction:r_instruction, + redirectee:REDIRECTEE, + here_doc_eof:*mut c_char +} + +/* FOR command. */ +#[repr(C)] +pub struct for_com { + flags:c_int, + line:c_int, + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct PATTERN_LIST { + next:* mut PATTERN_LIST, + patterns:* mut WORD_LIST, + action:*mut COMMAND, + flags:c_int +} + +#[repr(C)] +pub struct case_com { + flags:c_int, + line:c_int, + word:*mut WORD_DESC, + clauses:*mut PATTERN_LIST +} + +#[repr(C)] +pub struct while_com { + flags:c_int, + test:*mut COMMAND, + action:*mut COMMAND +} + +#[repr(C)] +pub struct if_com { + flags:c_int, + test:*mut COMMAND, + true_case:*mut COMMAND, + false_case:*mut COMMAND +} + +#[repr(C)] +pub struct connection { + ignore:c_int, + first:*mut COMMAND, + second:*mut COMMAND, + connector:c_int +} + +#[repr(C)] +pub struct simple_com { + flags:c_int, + line:c_int, + words:*mut WORD_LIST, + redirects:*mut REDIRECT +} + +#[repr(C)] +pub struct function_def { + flags:c_int, + line:c_int, + name:*mut WORD_DESC, + command:*mut COMMAND, + source_file:*mut c_char +} + +#[repr(C)] +pub struct group_com { + ignore:libc::c_int, + command:*mut COMMAND, + source_file:*mut c_char +} + +#[repr(C)] +pub struct select_com { + flags:c_int, + line:c_int, + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct arith_com { + flags:c_int, + line:c_int, + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct cond_com { + flags:c_int, + line:c_int, + type_c:c_int, + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct arith_for_com { + flags:c_int, + line:c_int, + init:*mut WORD_LIST, + test:*mut WORD_LIST, + step:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct subshell_com { + flags:i32, + line:i32, + command:*mut COMMAND +} + +#[repr(C)] +pub struct coproc_com { + flags:i32, + name:*mut c_char, + command:*mut COMMAND +} + +#[repr(C)] +pub union VALUE_COMMAND { + For:*mut for_com, + Case:*mut case_com, + While:*mut while_com, + If:*mut if_com, + Connection:*mut connection, + Simple:*mut simple_com, + Function_def:*mut function_def, + Group:*mut group_com, + Select:*mut select_com, + Arith:*mut arith_com, + Cond:*mut cond_com, + ArithFor:*mut arith_for_com, + Subshell:*mut subshell_com, + Coproc:*mut coproc_com +} + +#[repr(C)] +pub struct COMMAND { + type_c:command_type, + flags:i32, + line:i32, + redirects:*mut REDIRECT, + value:VALUE_COMMAND +} + +/* Structure containing all the non-action (binary) options; filled in by + build_actions(). */ +#[repr(C)] +#[derive(Copy,Clone)] +pub struct _optflags { + pflag:c_int, + rflag:c_int, + Dflag:c_int, + Eflag:c_int, + Iflag:c_int +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub struct _compacts { + actname:* const c_char, + actflag:libc::c_ulong, + actopt:c_int, +} + +pub struct CompactsArray { + compactsArr:[_compacts;25usize] +} + +impl CompactsArray { + pub fn new()->CompactsArray { + CompactsArray{ + compactsArr:[ + _compacts{ actname:"alias\0".as_ptr() as *const c_char, actflag: CA_ALIAS!(),actopt: 'a' as c_int }, + _compacts{ actname:"arrayvar\0".as_ptr() as *const c_char, actflag: CA_ARRAYVAR!(),actopt: 0 as c_int }, + _compacts{ actname:"binding\0".as_ptr() as *const c_char, actflag: CA_BINDING!(),actopt: 0 as c_int }, + _compacts{ actname:"builtin\0".as_ptr() as *const c_char, actflag: CA_BUILTIN!(),actopt: 'b' as c_int }, + _compacts{ actname:"command\0".as_ptr() as *const c_char, actflag: CA_COMMAND!(),actopt: 'c' as c_int }, + _compacts{ actname:"directory\0".as_ptr() as *const c_char, actflag: CA_DIRECTORY!(),actopt: 'd' as c_int }, + _compacts{ actname:"disabled\0".as_ptr() as *const c_char, actflag: CA_DISABLED!(),actopt: 0 as c_int }, + _compacts{ actname:"enabled\0".as_ptr() as *const c_char, actflag: CA_ENABLED!(),actopt: 0 as c_int }, + _compacts{ actname:"export\0".as_ptr() as *const c_char, actflag: CA_EXPORT!(),actopt: 'e' as c_int }, + _compacts{ actname:"file\0".as_ptr() as *const c_char, actflag: CA_FILE!(),actopt: 'f' as c_int }, + _compacts{ actname:"function\0".as_ptr() as *const c_char, actflag: CA_FUNCTION!(),actopt: 0 as c_int }, + _compacts{ actname:"helptopic\0".as_ptr() as *const c_char, actflag: CA_HELPTOPIC!(),actopt: 0 as c_int }, + _compacts{ actname:"hostname\0".as_ptr() as *const c_char, actflag: CA_HOSTNAME!(),actopt: 0 as c_int }, + _compacts{ actname:"group\0".as_ptr() as *const c_char, actflag: CA_GROUP!(),actopt: 'g' as c_int }, + _compacts{ actname:"job\0".as_ptr() as *const c_char, actflag: CA_JOB!(),actopt: 'j' as c_int }, + _compacts{ actname:"keyword\0".as_ptr() as *const c_char, actflag: CA_KEYWORD!(),actopt: 'k' as c_int }, + _compacts{ actname:"running\0".as_ptr() as *const c_char, actflag: CA_RUNNING!(),actopt: 0 as c_int }, + _compacts{ actname:"service\0".as_ptr() as *const c_char, actflag: CA_SERVICE!(),actopt: 's' as c_int }, + _compacts{ actname:"setopt\0".as_ptr() as *const c_char, actflag: CA_SETOPT!(),actopt: 0 as c_int }, + _compacts{ actname:"shopt\0".as_ptr() as *const c_char, actflag: CA_SHOPT!(),actopt: 0 as c_int }, + _compacts{ actname:"signal\0".as_ptr() as *const c_char, actflag: CA_SIGNAL!(),actopt: 0 as c_int }, + _compacts{ actname:"stopped\0".as_ptr() as *const c_char, actflag: CA_STOPPED!(),actopt: 0 as c_int }, + _compacts{ actname:"user\0".as_ptr() as *const c_char, actflag: CA_USER!(),actopt: 'u' as c_int }, + _compacts{ actname:"variable\0".as_ptr() as *const c_char, actflag: CA_VARIABLE!(),actopt: 'v' as c_int }, + _compacts{ actname:std::ptr::null_mut(), actflag: 0,actopt: 0 as c_int }, + ] + } + } +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub struct _compopt { + optname:* const c_char, + optflag:libc::c_ulong, +} + +pub struct CompoptArray { + compoptArr:[_compopt;9usize] +} + +impl CompoptArray { + pub fn new()->CompoptArray{ + CompoptArray{ + compoptArr:[ + _compopt{ optname:"bashdefault\0".as_ptr() as *const c_char, optflag:COPT_BASHDEFAULT!() }, + _compopt{ optname:"default\0".as_ptr() as *const c_char, optflag:COPT_DEFAULT!() }, + _compopt{ optname:"dirnames\0".as_ptr() as *const c_char, optflag:COPT_DIRNAMES!() }, + _compopt{ optname:"filenames\0".as_ptr() as *const c_char,optflag:COPT_FILENAMES!()}, + _compopt{ optname:"noquote\0".as_ptr() as *const c_char, optflag:COPT_NOQUOTE!() }, + _compopt{ optname:"nosort\0".as_ptr() as *const c_char, optflag:COPT_NOSORT!() }, + _compopt{ optname:"nospace\0".as_ptr() as *const c_char, optflag:COPT_NOSPACE!() }, + _compopt{ optname:"plusdirs\0".as_ptr() as *const c_char, optflag:COPT_PLUSDIRS!() }, + _compopt{ optname:std::ptr::null_mut(), optflag:0 }, + ] + } + } +} + + +#[repr(C)] +pub struct COMPSPEC { + refcount:c_int, + actions:c_ulong, + options:c_ulong, + globpat:* mut c_char, + words:* mut c_char, + prefix: * mut c_char, + suffix: * mut c_char, + funcname: * mut c_char, + command:* mut c_char, + lcommand:* mut c_char, + filterpat:* mut c_char, +} +#[repr(C)] +pub struct BUCKET_CONTENTS { + next:* mut BUCKET_CONTENTS, /* Link to next hashed key in this bucket. */ + key:* mut c_char, /* What we look up. */ + data:* mut libc::c_void, /* What we really want. */ + khash:libc::c_uint, /* What key hashes to */ + times_found:i32, /* Number of times this item has been found. */ +} + +#[repr(C)] +pub struct STRINGLIST { + list:* mut * mut c_char, + list_size:c_int, + list_len:c_int, +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => {1} +} + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => { + 0 + } +} + +#[macro_export] +macro_rules! CA_ALIAS { + () => { + 1<<0 + } +} + +#[macro_export] +macro_rules! CA_ARRAYVAR { + () => { + 1<<1 + } +} + +#[macro_export] +macro_rules! CA_BINDING { + () => { + 1<<2 + } +} + +#[macro_export] +macro_rules! CA_BUILTIN { + () => { + 1<<3 + } +} + +#[macro_export] +macro_rules! CA_COMMAND { + () => { + 1<<4 + } +} + +#[macro_export] +macro_rules! CA_DIRECTORY { + () => { + 1<<5 + } +} + +#[macro_export] +macro_rules! CA_DISABLED { + () => { + 1<<6 + } +} + +#[macro_export] +macro_rules! CA_ENABLED { + () => { + 1<<7 + } +} + +#[macro_export] +macro_rules! CA_EXPORT { + () => { + 1<<8 + } +} + +#[macro_export] +macro_rules! CA_FILE { + () => { + 1<<9 + } +} + +#[macro_export] +macro_rules! CA_FUNCTION { + () => { + 1<<10 + } +} + +#[macro_export] +macro_rules! CA_GROUP { + () => { + 1<<11 + } +} + +#[macro_export] +macro_rules! CA_HELPTOPIC { + () => { + 1<<12 + } +} + +#[macro_export] +macro_rules! CA_HOSTNAME { + () => { + 1<<13 + } +} + +#[macro_export] +macro_rules! CA_JOB { + () => { + 1<<14 + } +} + +#[macro_export] +macro_rules! CA_KEYWORD { + () => { + 1<<15 + } +} + +#[macro_export] +macro_rules! CA_RUNNING { + () => { + 1<<16 + } +} + +#[macro_export] +macro_rules! CA_SERVICE { + () => { + 1<<17 + } +} + +#[macro_export] +macro_rules! CA_SETOPT { + () => { + 1<<18 + } +} + +#[macro_export] +macro_rules! CA_SHOPT { + () => { + 1<<19 + } +} + +#[macro_export] +macro_rules! CA_SIGNAL { + () => { + 1<<20 + } +} + +#[macro_export] +macro_rules! CA_STOPPED { + () => { + 1<<21 + } +} + +#[macro_export] +macro_rules! CA_USER { + () => { + 1<<22 + } +} + +#[macro_export] +macro_rules! CA_VARIABLE { + () => { + 1<<23 + } +} + +#[macro_export] +macro_rules! COPT_RESERVED { + () => { + 1<<0 + } +} + +#[macro_export] +macro_rules! COPT_DEFAULT { + () => { + 1<<1 + } +} + +#[macro_export] +macro_rules! COPT_FILENAMES { + () => { + 1<<2 + } +} + +#[macro_export] +macro_rules! COPT_DIRNAMES { + () => { + 1<<3 + } +} + +#[macro_export] +macro_rules! COPT_NOQUOTE { + () => { + 1<<4 + } +} + +#[macro_export] +macro_rules! COPT_NOSPACE { + () => { + 1<<5 + } +} + +#[macro_export] +macro_rules! COPT_BASHDEFAULT { + () => { + 1<<6 + } +} + +#[macro_export] +macro_rules! COPT_PLUSDIRS { + () => { + 1<<7 + } +} + +#[macro_export] +macro_rules! COPT_NOSORT { + () => { + 1<<8 + } +} + +#[macro_export] +macro_rules! RL_STATE_COMPLETING { + () => { + 0x0004000 /* doing completion */ + } +} + +extern "C" { + fn reset_internal_getopt(); + fn internal_getopt (list:*mut WORD_LIST , opts:*mut c_char)->i32; + fn sh_invalidopt (value:* mut c_char); + fn sh_invalidid (value:* mut c_char); + fn sh_invalidoptname (value:* mut c_char); + fn builtin_usage(); + static list_optarg:* mut c_char; + fn builtin_error(err:*const c_char,...); + fn check_identifier (w:* mut WORD_DESC, f:i32)->i32; + static mut posixly_correct:i32; + static mut loptend:*mut WORD_LIST; + fn make_word_list (w:* mut WORD_DESC, list:*mut WORD_LIST)->*mut WORD_LIST; + fn make_bare_word (w:*const c_char)->* mut WORD_DESC; + fn dispose_words (list:*mut WORD_LIST); + fn progcomp_flush (); + fn compspec_create ()->* mut COMPSPEC; + fn progcomp_insert (str:* mut c_char, c:* mut COMPSPEC)->i32; + fn progcomp_remove (str:* mut c_char)->i32; + fn sh_single_quote (str:* mut c_char)->* mut c_char; + fn progcomp_walk (func: unsafe extern "C" fn (item:* mut BUCKET_CONTENTS)->i32); + fn sh_chkwrite (i:i32)->i32; + fn progcomp_search (w:*const c_char)->* mut COMPSPEC; + static mut pcomp_line:* mut c_char; + static mut pcomp_ind:c_int; + fn gen_compspec_completions (cs:* mut COMPSPEC, cmd:*const c_char, word:*const c_char, start:i32, end:i32, foundp:* mut i32)->* mut STRINGLIST; + fn bash_default_completion (text:* const c_char, start:i32, end:i32, qc:i32, compflags:i32)->* mut * mut c_char; + fn rl_filename_completion_function (text:* const c_char, state:i32)-> * mut c_char; + fn rl_completion_matches (text:* const c_char, entry_function:unsafe extern "C" fn (text:* const c_char, state:i32)-> * mut c_char)->* mut * mut c_char; + fn completions_to_stringlist (matches:* mut * mut c_char)->* mut STRINGLIST; + fn strvec_dispose (matches:* mut * mut c_char); + fn strlist_dispose (strlist:* mut STRINGLIST); + fn strlist_print (strlist:* mut STRINGLIST, text:* mut c_char); + fn compspec_dispose (com:* mut COMPSPEC); + static mut list_opttype:i32; + static mut rl_readline_state:c_ulong; + static mut pcomp_curcs:* mut COMPSPEC; + static pcomp_curcmd:* mut c_char; + fn pcomp_set_compspec_options (cs:* mut COMPSPEC, flags:i32, set_or_unset:i32); + fn pcomp_set_readline_variables (flags:i32, nval:i32); +} + +pub static mut Garg:* mut c_char=std::ptr::null_mut(); +pub static mut Warg:* mut c_char=std::ptr::null_mut(); +pub static mut Parg:* mut c_char=std::ptr::null_mut(); +pub static mut Sarg:* mut c_char=std::ptr::null_mut(); +pub static mut Xarg:* mut c_char=std::ptr::null_mut(); +pub static mut Farg:* mut c_char=std::ptr::null_mut(); +pub static mut Carg:* mut c_char=std::ptr::null_mut(); + +unsafe fn savestring(x:* const c_char)->* mut c_char +{ + let str1:* mut c_char=libc::malloc(1 + libc::strlen (x )) as * mut c_char; + return libc::strcpy(str1,x ); +} + +unsafe fn STRDUP(x:* const c_char)->* mut c_char +{ + if x !=std::ptr::null_mut() { + return savestring (x); + } else { + return std::ptr::null_mut(); + } +} + +unsafe fn STREQ( a:* const c_char, b:* const c_char)->bool +{ + return *a ==*b && libc::strcmp(a, b) == 0; +} + +unsafe fn shell_break_chars()->* const c_char +{ + return "()<>;&| \t\n\0".as_ptr() as *const c_char; +} + +unsafe fn EMPTYCMD()->* const c_char +{ + return "_EmptycmD_\0".as_ptr() as *const c_char; +} + +unsafe fn DEFAULTCMD()->* const c_char +{ + return "_DefaultCmD_\0".as_ptr() as *const c_char; +} + +unsafe fn INITIALWORD()->* const c_char +{ + return "_InitialWorD_\0".as_ptr() as *const c_char; +} + +unsafe fn RL_ISSTATE(x:c_ulong)->c_ulong +{ + return rl_readline_state & x; +} + +#[no_mangle] +pub extern "C" fn r_find_compact (name:* mut c_char)->i32 +{ + let mut i:i32=0; + unsafe { + let compacts:CompactsArray=CompactsArray::new(); + while compacts.compactsArr[i as usize].actname != std::ptr::null_mut() { + if STREQ (name, compacts.compactsArr[i as usize].actname) { + return i; + } + i+=1; + } + return -1; + } +} + +#[no_mangle] +pub extern "C" fn r_find_compopt (name:* mut c_char)->i32 +{ + let mut i:i32=0; + let compopts:CompoptArray=CompoptArray::new(); + unsafe { + while compopts.compoptArr[i as usize].optname != std::ptr::null_mut() { + if STREQ (name, compopts.compoptArr[i as usize].optname) { + return i; + } + i+=1; + } + return -1; + } +} + +#[no_mangle] +pub extern "C" fn r_build_actions (list : *mut WORD_LIST, flagp:* mut _optflags, actp:* mut c_ulong, optp:* mut c_ulong)->i32 +{ + let mut opt:i32; + let mut ind:i32; + let mut opt_given:i32=0; + let mut acts:c_ulong=0; + let mut copts:c_ulong=0; + let mut w:WORD_DESC=WORD_DESC{word:std::ptr::null_mut(),flags:0}; + + unsafe { + reset_internal_getopt (); + opt = internal_getopt(list, CString::new("abcdefgjko:prsuvA:G:W:P:S:X:F:C:DEI").unwrap().as_ptr() as * mut c_char); + while opt != -1 { + opt_given = 1; + let optu8:u8= opt as u8; + let optChar:char=char::from(optu8); + match optChar{ + 'r'=>{ + if flagp !=std::ptr::null_mut() { + (*flagp).rflag = 1; + } else { + sh_invalidopt (CString::new("-r").unwrap().as_ptr() as * mut c_char); + builtin_usage (); + return EX_USAGE!(); + } + } + 'p'=>{ + if flagp !=std::ptr::null_mut() { + (*flagp).pflag = 1; + } else { + sh_invalidopt (CString::new("-p").unwrap().as_ptr() as * mut c_char); + builtin_usage (); + return EX_USAGE!(); + } + } + 'a'=>{ + acts |= CA_ALIAS!(); + } + 'b'=>{ + acts |= CA_BUILTIN!(); + } + 'c'=>{ + acts |= CA_COMMAND!(); + } + 'd'=>{ + acts |= CA_DIRECTORY!(); + } + 'e'=>{ + acts |= CA_EXPORT!(); + } + 'f'=>{ + acts |= CA_FILE!(); + } + 'g'=>{ + acts |= CA_GROUP!(); + } + 'j'=>{ + acts |= CA_GROUP!(); + } + 'k'=>{ + acts |= CA_KEYWORD!(); + } + 's'=>{ + acts |= CA_SERVICE!(); + } + 'u'=>{ + acts |= CA_USER!(); + } + 'v'=>{ + acts |= CA_VARIABLE!(); + } + 'o'=>{ + ind = r_find_compopt (list_optarg); + if ind < 0 { + sh_invalidoptname (list_optarg); + return EX_USAGE!(); + } + let compopts:CompoptArray=CompoptArray::new(); + copts |= compopts.compoptArr[ind as usize].optflag; + } + 'A'=>{ + ind = r_find_compact (list_optarg); + if ind < 0 { + builtin_error (CString::new("%s: invalid action name").unwrap().as_ptr(), list_optarg); + return EX_USAGE!(); + } + let compacts:CompactsArray=CompactsArray::new(); + acts |= compacts.compactsArr[ind as usize].actflag; + } + 'C'=>{ + Carg = list_optarg; + } + 'D'=>{ + if flagp !=std::ptr::null_mut() { + (*flagp).Dflag = 1; + } else { + sh_invalidopt (CString::new("-D").unwrap().as_ptr() as * mut c_char); + builtin_usage (); + return EX_USAGE!(); + } + } + 'E'=>{ + if flagp !=std::ptr::null_mut() { + (*flagp).Eflag = 1; + } else { + sh_invalidopt (CString::new("-E").unwrap().as_ptr() as * mut c_char); + builtin_usage (); + return EX_USAGE!(); + } + } + 'I'=>{ + if flagp !=std::ptr::null_mut() { + (*flagp).Iflag = 1; + } else { + sh_invalidopt (CString::new("-I").unwrap().as_ptr() as * mut c_char); + builtin_usage (); + return EX_USAGE!(); + } + } + 'F'=>{ + w.word = list_optarg; + Farg = list_optarg; + w.flags = 0; + if check_identifier (&mut w, posixly_correct) == 0 || libc::strpbrk (Farg, shell_break_chars()) != std::ptr::null_mut() { + sh_invalidid (Farg); + return EX_USAGE!(); + } + } + 'G'=>{ + Garg = list_optarg; + } + 'P'=>{ + Parg = list_optarg; + } + 'S'=>{ + Sarg = list_optarg; + } + 'W'=>{ + Warg = list_optarg; + } + 'X'=>{ + Xarg = list_optarg; + } + 'X'=>{ + Xarg = list_optarg; + } + _=>{ + builtin_usage (); + return EX_USAGE!(); + } + } + opt=internal_getopt(list, CString::new("abcdefgjko:prsuvA:G:W:P:S:X:F:C:DEI").unwrap().as_ptr() as * mut c_char); + } + *actp = acts; + *optp = copts; + if opt_given !=0 { + return EXECUTION_SUCCESS!(); + } else { + return EXECUTION_FAILURE!(); + } + } +} + +/* Add, remove, and display completion specifiers. */ +#[no_mangle] +pub extern "C" fn r_complete_builtin (listt: *mut WORD_LIST)->i32 +{ + let mut opt_given:i32=0; + let mut rval:i32; + let mut acts:c_ulong=0; + let mut copts:c_ulong=0; + let mut cs:* mut COMPSPEC; + let mut oflags:_optflags=_optflags{pflag:0,rflag:0,Dflag:0,Eflag:0,Iflag:0}; + let mut l: *mut WORD_LIST; + let mut wl: *mut WORD_LIST; + + unsafe { + let mut list:* mut WORD_LIST=listt.clone(); + if list == std::ptr::null_mut() { + r_print_all_completions (); + return EXECUTION_SUCCESS!(); + } + + oflags.pflag=0; + oflags.rflag=0; + oflags.Dflag=0; + oflags.Eflag=0; + oflags.Iflag=0; + + Garg=std::ptr::null_mut(); + Warg=std::ptr::null_mut(); + Parg=std::ptr::null_mut(); + Sarg=std::ptr::null_mut(); + Xarg=std::ptr::null_mut(); + Farg=std::ptr::null_mut(); + Carg=std::ptr::null_mut(); + + cs=std::ptr::null_mut(); + + /* Build the actions from the arguments. Also sets the [A-Z]arg variables + as a side effect if they are supplied as options. */ + rval = r_build_actions (list, &mut oflags, &mut acts, &mut copts); + if rval == EX_USAGE!() { + return rval; + } + + opt_given = (rval != EXECUTION_FAILURE!()) as i32; + + list = loptend.clone(); + + if oflags.Dflag !=0 { + wl = make_word_list (make_bare_word (DEFAULTCMD()), std::ptr::null_mut()); + } else if oflags.Eflag !=0 { + wl = make_word_list (make_bare_word (EMPTYCMD()), std::ptr::null_mut()); + } else if oflags.Iflag !=0 { + wl = make_word_list (make_bare_word (INITIALWORD()), std::ptr::null_mut()); + } else { + wl = std::ptr::null_mut(); + } + + /* -p overrides everything else */ + if oflags.pflag !=0 || (list == std::ptr::null_mut() && opt_given == 0) { + if wl != std::ptr::null_mut() { + rval = r_print_cmd_completions (wl); + dispose_words (wl); + return rval; + } else if list == std::ptr::null_mut() { + r_print_all_completions (); + return EXECUTION_SUCCESS!(); + } + return r_print_cmd_completions (list); + } + + /* next, -r overrides everything else. */ + if oflags.rflag !=0 { + if wl != std::ptr::null_mut() { + rval = r_remove_cmd_completions (wl); + dispose_words (wl); + return rval; + } else if list == std::ptr::null_mut() { + progcomp_flush (); + return EXECUTION_SUCCESS!(); + } + return r_remove_cmd_completions (list); + } + + if wl == std::ptr::null_mut() && list == std::ptr::null_mut() && opt_given !=0 { + builtin_usage (); + return EX_USAGE!(); + } + + /* If we get here, we need to build a compspec and add it for each + remaining argument. */ + cs = compspec_create (); + (*cs).actions = acts; + (*cs).options = copts; + + (*cs).globpat = STRDUP (Garg); + (*cs).words = STRDUP (Warg); + (*cs).prefix = STRDUP (Parg); + (*cs).suffix = STRDUP (Sarg); + (*cs).funcname = STRDUP (Farg); + (*cs).command = STRDUP (Carg); + (*cs).filterpat = STRDUP (Xarg); + + rval = EXECUTION_SUCCESS!(); + + if wl != std::ptr::null_mut() { + l= wl.clone(); + } else { + l= list.clone(); + } + + while l != std::ptr::null_mut() { + /* Add CS as the compspec for the specified commands. */ + if progcomp_insert ((*(*l).word).word, cs) == 0 { + rval = EXECUTION_FAILURE!(); + } + l = (*l).next; + } + + dispose_words (wl); + return rval; + } +} + +#[no_mangle] +pub extern "C" fn r_remove_cmd_completions (list: * mut WORD_LIST)->i32 +{ + let mut l:* mut WORD_LIST; + let mut ret:i32; + unsafe { + ret = EXECUTION_SUCCESS!(); + l = list.clone(); + while l!=std::ptr::null_mut() { + if progcomp_remove ((*(*l).word).word) == 0 { + builtin_error (CString::new("%s: no completion specification").unwrap().as_ptr(), (*(*l).word).word); + ret = EXECUTION_FAILURE!(); + } + l = (*l).next; + } + return ret; + } +} + +#[no_mangle] +pub extern "C" fn r_print_compoptions (copts:c_ulong, full:i32) +{ + unsafe { + let compopts:CompoptArray=CompoptArray::new(); + for i in 0..compopts.compoptArr.len() { + if (copts & compopts.compoptArr[i].optflag) !=0 { + libc::printf (CString::new("-o %s ").unwrap().as_ptr(), compopts.compoptArr[i].optname); + } else if full !=0 { + libc::printf (CString::new("+o %s ").unwrap().as_ptr(), compopts.compoptArr[i].optname); + } + } + } +} + +#[no_mangle] +pub extern "C" fn r_print_compactions (acts:c_ulong) +{ + unsafe { + let compacts:CompactsArray=CompactsArray::new(); + for i in 0..compacts.compactsArr.len() { + if compacts.compactsArr[i].actopt !=0 && (acts & compacts.compactsArr[i].actflag) !=0 { + libc::printf (CString::new("-%c ").unwrap().as_ptr(), compacts.compactsArr[i].actopt); + } + } + + for i in 0..compacts.compactsArr.len() { + if compacts.compactsArr[i].actopt ==0 && (acts & compacts.compactsArr[i].actflag) !=0 { + libc::printf (CString::new("-A %s ").unwrap().as_ptr(), compacts.compactsArr[i].actname); + } + } + } +} + +#[no_mangle] +pub extern "C" fn r_print_arg (arg:* const c_char, flag:* const c_char, quote:i32) +{ + let x:* mut c_char; + unsafe { + if arg != std::ptr::null_mut() { + if quote !=0 { + x = sh_single_quote (arg as * mut c_char); + } else { + x= arg as * mut c_char; + } + libc::printf (CString::new("%s %s ").unwrap().as_ptr(), flag, x); + if x != arg as * mut c_char { + libc::free (x as * mut c_void); + } + } + } +} + +#[no_mangle] +pub extern "C" fn r_print_cmd_name (cmd:* const c_char) +{ + unsafe { + if STREQ (cmd, DEFAULTCMD()) { + libc::printf (CString::new("-D").unwrap().as_ptr()); + } else if STREQ (cmd, EMPTYCMD()) { + libc::printf (CString::new("-E").unwrap().as_ptr()); + } else if STREQ (cmd, INITIALWORD()) { + libc::printf (CString::new("-I").unwrap().as_ptr()); + } else if *cmd == 0 { /* XXX - can this happen? */ + libc::printf (CString::new("''").unwrap().as_ptr()); + } else { + libc::printf (CString::new("%s").unwrap().as_ptr(),cmd); + } + } +} + +#[no_mangle] +pub extern "C" fn r_print_one_completion (cmd: * mut c_char, cs:* mut COMPSPEC)->i32 +{ + unsafe { + libc::printf (CString::new("complete ").unwrap().as_ptr()); + + r_print_compoptions ((*cs).options, 0); + r_print_compactions ((*cs).actions); + + /* now the rest of the arguments */ + + /* arguments that require quoting */ + r_print_arg ((*cs).globpat, CString::new("-G").unwrap().as_ptr(), 1); + r_print_arg ((*cs).words, CString::new("-W").unwrap().as_ptr(), 1); + r_print_arg ((*cs).prefix, CString::new("-P").unwrap().as_ptr(), 1); + r_print_arg ((*cs).suffix, CString::new("-S").unwrap().as_ptr(), 1); + r_print_arg ((*cs).filterpat, CString::new("-X").unwrap().as_ptr(), 1); + + r_print_arg ((*cs).command, CString::new("-C").unwrap().as_ptr(), 1); + + /* simple arguments that don't require quoting */ + r_print_arg ((*cs).funcname, CString::new("-F").unwrap().as_ptr(), 0); + + r_print_cmd_name (cmd); + libc::printf (CString::new("\n").unwrap().as_ptr()); + + return 0; + } +} + +#[no_mangle] +pub extern "C" fn r_print_compopts (cmd:* mut c_char, cs:* mut COMPSPEC, full:i32) +{ + unsafe { + libc::printf (CString::new("compopt ").unwrap().as_ptr()); + + r_print_compoptions ((*cs).options, full); + r_print_cmd_name (cmd); + + libc::printf (CString::new("\n").unwrap().as_ptr()); + } +} + +#[no_mangle] +pub extern "C" fn r_print_compitem (item:* mut BUCKET_CONTENTS)->i32 +{ + let cs:* mut COMPSPEC; + let cmd:* mut c_char; + unsafe { + cmd = (*item).key; + cs = (*item).data as * mut COMPSPEC; + } + + return r_print_one_completion (cmd, cs); +} + +#[no_mangle] +pub extern "C" fn r_print_all_completions () +{ + unsafe { + progcomp_walk (r_print_compitem); + } +} + +#[no_mangle] +pub extern "C" fn r_print_cmd_completions (list:* mut WORD_LIST)->i32 +{ + let mut l:* mut WORD_LIST; + let mut cs:* mut COMPSPEC; + let mut ret:i32; + + unsafe { + ret = EXECUTION_SUCCESS!(); + l = list.clone(); + while l != std::ptr::null_mut() { + cs = progcomp_search ((*(*l).word).word); + if cs != std::ptr::null_mut() { + r_print_one_completion ((*(*l).word).word, cs); + } else { + builtin_error (CString::new("%s: no completion specification").unwrap().as_ptr(),(*(*l).word).word); + ret = EXECUTION_FAILURE!(); + } + l = (*l).next; + } + return sh_chkwrite (ret); + } +} + +#[no_mangle] +pub extern "C" fn r_compgen_builtin (listt:* mut WORD_LIST)->i32 +{ + let mut rval:i32; + let mut acts:c_ulong=0; + let mut copts:c_ulong=0; + let mut cs: * mut COMPSPEC; + let mut sl:* mut STRINGLIST; + let word:* mut c_char; + let mut matches:* mut * mut c_char; + let old_line:* mut c_char; + let old_ind:i32; + unsafe { + let mut list:* mut WORD_LIST=listt.clone(); + if list == std::ptr::null_mut() { + return EXECUTION_SUCCESS!(); + } + + Garg=std::ptr::null_mut(); + Warg=std::ptr::null_mut(); + Parg=std::ptr::null_mut(); + Sarg=std::ptr::null_mut(); + Xarg=std::ptr::null_mut(); + Farg=std::ptr::null_mut(); + Carg=std::ptr::null_mut(); + + cs = std::ptr::null_mut(); + + /* Build the actions from the arguments. Also sets the [A-Z]arg variables + as a side effect if they are supplied as options. */ + rval = r_build_actions (list, std::ptr::null_mut(), &mut acts, &mut copts); + if rval == EX_USAGE!() { + return rval; + } + + if rval == EXECUTION_FAILURE!() { + return EXECUTION_SUCCESS!(); + } + + list = loptend.clone(); + + if list !=std::ptr::null_mut() && (*list).word != std::ptr::null_mut() { + word = (*((*list).word)).word; + } else { + word=CString::new("").unwrap().as_ptr() as * mut c_char; + } + + if Farg != std::ptr::null_mut() { + builtin_error (CString::new("warning: -F option may not work as you expect").unwrap().as_ptr()); + } + + if Carg != std::ptr::null_mut() { + builtin_error (CString::new("warning: -C option may not work as you expect").unwrap().as_ptr()); + } + + /* If we get here, we need to build a compspec and evaluate it. */ + cs = compspec_create (); + (*cs).actions = acts; + (*cs).options = copts; + (*cs).refcount = 1; + + (*cs).globpat = STRDUP (Garg); + (*cs).words = STRDUP (Warg); + (*cs).prefix = STRDUP (Parg); + (*cs).suffix = STRDUP (Sarg); + (*cs).funcname = STRDUP (Farg); + (*cs).command = STRDUP (Carg); + (*cs).filterpat = STRDUP (Xarg); + + rval = EXECUTION_FAILURE!(); + + /* probably don't have to save these, just being safe */ + old_line = pcomp_line; + old_ind = pcomp_ind; + pcomp_line = std::ptr::null_mut(); + pcomp_ind = 0; + sl = gen_compspec_completions (cs, CString::new("compgen").unwrap().as_ptr(), word, 0, 0, std::ptr::null_mut()); + pcomp_line = old_line; + pcomp_ind = old_ind; + + /* If the compspec wants the bash default completions, temporarily + turn off programmable completion and call the bash completion code. */ + if (sl == std::ptr::null_mut() || (*sl).list_len == 0) && (copts & COPT_BASHDEFAULT!()) !=0 { + matches = bash_default_completion (word, 0, 0, 0, 0); + sl = completions_to_stringlist (matches); + strvec_dispose (matches); + } + + /* This isn't perfect, but it's the best we can do, given what readline + exports from its set of completion utility functions. */ + if (sl == std::ptr::null_mut() || (*sl).list_len == 0) && (copts & COPT_DEFAULT!()) !=0 { + matches = rl_completion_matches (word, rl_filename_completion_function); + strlist_dispose (sl); + sl = completions_to_stringlist (matches); + strvec_dispose (matches); + } + + if sl != std::ptr::null_mut() { + if (*sl).list != std::ptr::null_mut() && (*sl).list_len !=0 { + rval = EXECUTION_SUCCESS!(); + strlist_print (sl, std::ptr::null_mut()); + } + strlist_dispose (sl); + } + + compspec_dispose (cs); + return rval; + } +} + +#[no_mangle] +pub extern "C" fn r_compopt_builtin (listt:* mut WORD_LIST)->i32 +{ + let mut opts_on:i32=0; + let mut opts_off:i32=0; + let mut opts:* mut i32; + let mut opt:i32; + let mut oind:i32; + let mut ret:i32; + let mut Dflag:i32=0; + let mut Eflag:i32=0; + let mut Iflag:i32=0; + let mut l:* mut WORD_LIST; + let mut wl:* mut WORD_LIST; + let mut cs:* mut COMPSPEC; + + ret = EXECUTION_SUCCESS!(); + unsafe { + let mut list:* mut WORD_LIST=listt.clone(); + reset_internal_getopt (); + + opt = internal_getopt (list, CString::new("+o:DEI").unwrap().as_ptr() as * mut c_char); + + while opt != -1 { + if list_opttype == '-' as i32 { + opts = &mut opts_on; + } else { + opts = &mut opts_off; + } + + let optu8:u8= opt as u8; + let optChar:char=char::from(optu8); + + match optChar { + 'o'=>{ + oind = r_find_compopt (list_optarg); + if oind < 0 { + sh_invalidoptname (list_optarg); + return EX_USAGE!(); + } + let compopts:CompoptArray=CompoptArray::new(); + *opts |= compopts.compoptArr[oind as usize].optflag as i32; + } + 'D'=>{ + Dflag = 1; + } + 'E'=>{ + Eflag = 1; + } + 'I'=>{ + Iflag = 1; + } + _=>{ + builtin_usage (); + return EX_USAGE!(); + } + } + opt = internal_getopt (list, CString::new("+o:DEI").unwrap().as_ptr() as * mut c_char); + } + + list = loptend.clone(); + + if Dflag != 0 { + wl = make_word_list (make_bare_word (DEFAULTCMD()), std::ptr::null_mut()); + } else if Eflag !=0 { + wl = make_word_list (make_bare_word (EMPTYCMD()), std::ptr::null_mut()); + } else if Iflag !=0 { + wl = make_word_list (make_bare_word (INITIALWORD()), std::ptr::null_mut()); + } else { + wl = std::ptr::null_mut(); + } + + if list == std::ptr::null_mut() && wl == std::ptr::null_mut() { + if RL_ISSTATE (RL_STATE_COMPLETING!()) == 0 || pcomp_curcs == std::ptr::null_mut() { + builtin_error (CString::new("not currently executing completion function").unwrap().as_ptr()); + return EXECUTION_FAILURE!(); + } + cs = pcomp_curcs.clone(); + + if opts_on == 0 && opts_off == 0 { + r_print_compopts (pcomp_curcmd, cs, 1); + return sh_chkwrite (ret); + } + + /* Set the compspec options */ + pcomp_set_compspec_options (cs, opts_on, 1); + pcomp_set_compspec_options (cs, opts_off, 0); + + /* And change the readline variables the options control */ + pcomp_set_readline_variables (opts_on, 1); + pcomp_set_readline_variables (opts_off, 0); + + return ret; + } + + if wl != std::ptr::null_mut() { + l = wl.clone(); + } else { + l=list.clone(); + } + + while l != std::ptr::null_mut() { + cs = progcomp_search ((*((*list).word)).word); + if cs == std::ptr::null_mut() { + builtin_error (CString::new("%s: no completion specification").unwrap().as_ptr(), (*((*list).word)).word); + ret = EXECUTION_FAILURE!(); + continue; + } + if opts_on == 0 && opts_off == 0 { + r_print_compopts ((*((*list).word)).word, cs, 1); + continue; /* XXX -- fill in later */ + } + + /* Set the compspec options */ + pcomp_set_compspec_options (cs, opts_on, 1); + pcomp_set_compspec_options (cs, opts_off, 0); + l = (*l).next; + } + + if wl != std::ptr::null_mut() { + dispose_words (wl); + } + + return ret; + } +} + +#[no_mangle] +pub extern "C" fn cmd_name() ->*const u8 { + return b"complete" as *const u8; +} + +#[no_mangle] +pub extern "C" fn run(list : *mut WORD_LIST)->i32 { + return r_complete_builtin(list); +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/declare/Cargo.toml b/bash-5.1/builtins_rust/declare/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..a4e33ac1f0211fc0aa528c053f55757ca0e3bb11 --- /dev/null +++ b/bash-5.1/builtins_rust/declare/Cargo.toml @@ -0,0 +1,17 @@ +[package] +authors = ["huzhengming"] +name = "rdeclare" +version = "0.0.1" +#build = "../build.rs" +edition = "2018" + + +[dependencies] +lazy_static = "1.4.0" +libc = "0.2" +nix = "0.23.0" + +[lib] +#crate-type = ["cdylib"] +crate-type = ["staticlib"] +name = "rdeclare" diff --git a/bash-5.1/builtins_rust/declare/src/lib.rs b/bash-5.1/builtins_rust/declare/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..ca36790378977b0647e9a6b79477bcdfa703830a --- /dev/null +++ b/bash-5.1/builtins_rust/declare/src/lib.rs @@ -0,0 +1,1552 @@ +extern crate libc; +extern crate nix; + +use libc::{c_char, c_long, c_void}; +use std::{ffi::CString}; + +#[repr(C)] +pub struct WORD_DESC { + pub word: *mut libc::c_char, + pub flags:libc::c_int +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub struct WORD_LIST { + next: *mut WORD_LIST, + word: *mut WORD_DESC +} + +#[repr(u8)] +enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select, + cm_connection, cm_function_def, cm_until, cm_group, + cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc +} + +#[repr(u8)] +#[derive(Copy,Clone)] +enum r_instruction { + r_output_direction, r_input_direction, r_inputa_direction, + r_appending_to, r_reading_until, r_reading_string, + r_duplicating_input, r_duplicating_output, r_deblank_reading_until, + r_close_this, r_err_and_out, r_input_output, r_output_force, + r_duplicating_input_word, r_duplicating_output_word, + r_move_input, r_move_output, r_move_input_word, r_move_output_word, + r_append_err_and_out +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub union REDIRECTEE { + dest:libc::c_int, + filename:* mut WORD_DESC +} + +#[repr(C)] +pub union REDIRECT { + next:*mut REDIRECT, + redirector:REDIRECTEE, + rflags:libc::c_int, + flags:libc::c_int, + instruction:r_instruction, + redirectee:REDIRECTEE, + here_doc_eof:*mut c_char +} + +/* FOR command. */ +#[repr(C)] +pub struct for_com { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct PATTERN_LIST { + next:* mut PATTERN_LIST, + patterns:* mut WORD_LIST, + action:*mut COMMAND, + flags:libc::c_int +} + +#[repr(C)] +pub struct case_com { + flags:libc::c_int, + line:libc::c_int, + word:*mut WORD_DESC, + clauses:*mut PATTERN_LIST +} + +#[repr(C)] +pub struct while_com { + flags:libc::c_int, + test:*mut COMMAND, + action:*mut COMMAND +} + +#[repr(C)] +pub struct if_com { + flags:libc::c_int, + test:*mut COMMAND, + true_case:*mut COMMAND, + false_case:*mut COMMAND +} + +#[repr(C)] +pub struct connection { + ignore:libc::c_int, + first:*mut COMMAND, + second:*mut COMMAND, + connector:libc::c_int +} + +#[repr(C)] +pub struct simple_com { + flags:libc::c_int, + line:libc::c_int, + words:*mut WORD_LIST, + redirects:*mut REDIRECT +} + +#[repr(C)] +pub struct function_def { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + command:*mut COMMAND, + source_file:*mut c_char +} + +#[repr(C)] +pub struct group_com { + ignore:libc::c_int, + command:*mut COMMAND, + source_file:*mut c_char +} + +#[repr(C)] +pub struct select_com { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct arith_com { + flags:libc::c_int, + line:libc::c_int, + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct cond_com { + flags:libc::c_int, + line:libc::c_int, + type_c:libc::c_int, + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct arith_for_com { + flags:libc::c_int, + line:libc::c_int, + init:*mut WORD_LIST, + test:*mut WORD_LIST, + step:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct subshell_com { + flags:i32, + line:i32, + command:*mut COMMAND +} + +#[repr(C)] +pub struct coproc_com { + flags:i32, + name:*mut c_char, + command:*mut COMMAND +} + +#[repr(C)] +pub union VALUE_COMMAND { + For:*mut for_com, + Case:*mut case_com, + While:*mut while_com, + If:*mut if_com, + Connection:*mut connection, + Simple:*mut simple_com, + Function_def:*mut function_def, + Group:*mut group_com, + Select:*mut select_com, + Arith:*mut arith_com, + Cond:*mut cond_com, + ArithFor:*mut arith_for_com, + Subshell:*mut subshell_com, + Coproc:*mut coproc_com +} + +#[repr(C)] +pub struct COMMAND { + type_c:command_type, + flags:i32, + line:i32, + redirects:*mut REDIRECT, + value:VALUE_COMMAND +} + +#[repr(C)] +pub struct SHELL_VAR { + name:*mut c_char, /* Symbol that the user types. */ + value:*mut c_char, /* Value that is returned. */ + exportstr:*mut c_char, /* String for the environment. */ + dynamic_value:*mut fn(v:* mut SHELL_VAR)->*mut SHELL_VAR, /* Function called to return a `dynamic' + value for a variable, like $SECONDS + or $RANDOM. */ + assign_func:* mut fn(v:* mut SHELL_VAR,str1:* mut c_char,t:c_long,str2:* mut c_char)->*mut SHELL_VAR, /* Function called when this `special + variable' is assigned a value in + bind_variable. */ + attributes:i32, /* export, readonly, array, invisible... */ + context:i32 /* Which context this variable belongs to. */ +} + +#[repr(C)] +pub struct BUCKET_CONTENTS { + next:* mut BUCKET_CONTENTS, /* Link to next hashed key in this bucket. */ + key:* mut c_char, /* What we look up. */ + data:* mut c_void, /* What we really want. */ + khash:u32, /* What key hashes to */ + times_found:i32 /* Number of times this item has been found. */ +} + +#[repr(C)] +pub struct HASH_TABLE { + bucket_array:*mut * mut BUCKET_CONTENTS, /* Where the data is kept. */ + nbuckets:i32, /* How many buckets does this table have. */ + nentries:i32 /* How many entries does this table have. */ +} + +#[repr(C)] +pub struct VAR_CONTEXT { + name:* mut c_char,/* empty or NULL means global context */ + scope:i32, /* 0 means global context */ + flags:i32, + up:* mut VAR_CONTEXT, /* previous function calls */ + down:* mut VAR_CONTEXT, /* down towards global context */ + table:* mut HASH_TABLE /* variables at this scope */ +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => {1} +} + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! ARGS_SETBLTIN { + () => { + 0x04 + } +} + +#[macro_export] +macro_rules! EXITPROG { + () => { + 3 + } +} + +#[macro_export] +macro_rules! att_local { + () => { + 0x0000020 + } +} + +#[macro_export] +macro_rules! att_array { + () => { + 0x0000004 /* value is an array */ + } +} + +#[macro_export] +macro_rules! att_assoc { + () => { + 0x0000040 /* variable is an associative array */ + } +} + +#[macro_export] +macro_rules! att_function { + () => { + 0x0000008 /* value is a function */ + } +} + +#[macro_export] +macro_rules! att_integer { + () => { + 0x0000010 /* internal representation is int */ + } +} + +#[macro_export] +macro_rules! att_nameref { + () => { + 0x0000800 /* word is a name reference */ + } +} + +#[macro_export] +macro_rules! att_readonly { + () => { + 0x0000002 /* cannot change */ + } +} + +#[macro_export] +macro_rules! att_trace { + () => { + 0x0000080 /* function is traced with DEBUG trap */ + } +} + +#[macro_export] +macro_rules! att_exported { + () => { + 0x0000001 /* export to environment */ + } +} + +#[macro_export] +macro_rules! att_capcase { + () => { + 0x0000400 /* word capitalized on assignment */ + } +} + +#[macro_export] +macro_rules! att_uppercase { + () => { + 0x0000100 /* word converted to uppercase on assignment */ + } +} + +#[macro_export] +macro_rules! att_lowercase { + () => { + 0x0000200 /* word converted to lowercase on assignment */ + } +} + +#[macro_export] +macro_rules! MKLOC_INHERIT { + () => { + 0x04 + } +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => { + 0 + } +} + +#[macro_export] +macro_rules! ASS_APPEND { + () => { + 0x0001 + } +} + +#[macro_export] +macro_rules! ASS_MKLOCAL { + () => { + 0x0002 + } +} + +#[macro_export] +macro_rules! MKLOC_ARRAYOK { + () => { + 0x02 + } +} + +#[macro_export] +macro_rules! MKLOC_ASSOCOK { + () => { + 0x01 + } +} + +#[macro_export] +macro_rules! FUNC_MULTILINE { + () => { + 0x01 + } +} + +#[macro_export] +macro_rules! FUNC_EXTERNAL { + () => { + 0x02 + } +} + +#[macro_export] +macro_rules! ASS_FORCE { + () => { + 0x0020 /* force assignment even to readonly variable */ + } +} + +#[macro_export] +macro_rules! W_COMPASSIGN { + () => { + 1 << 15 /* Compound assignment */ + } +} + +#[macro_export] +macro_rules! ASS_NOEXPAND { + () => { + 0x0080 /* don't expand associative array subscripts */ + } +} + +#[macro_export] +macro_rules! EX_BADASSIGN { + () => { + 260 /* variable assignment error */ + } +} + +#[macro_export] +macro_rules! att_tempvar { + () => { + 0x0100000 /* variable came from the temp environment */ + } +} + +#[macro_export] +macro_rules! att_propagate { + () => { + 0x0200000 /* propagate to previous scope */ + } +} + +#[macro_export] +macro_rules! ASS_NAMEREF { + () => { + 0x0010 /* assigning to nameref variable */ + } +} + +#[macro_export] +macro_rules! att_invisible { + () => { + 0x0001000 /* cannot see */ + } +} + +#[macro_export] +macro_rules! att_noassign { + () => { + 0x0004000 /* assignment not allowed */ + } +} + +pub union Functions { + f_xfree:unsafe extern "C" fn(str1:* mut c_void), + f_maybe_pop_dollar_vars: unsafe extern "C" fn(), + f_maybe_set_debug_trap:unsafe extern "C" fn(* mut c_char) +} + +extern "C" { + fn builtin_help (); + static variable_context:i32; + fn builtin_error(err:*const c_char,...); + fn builtin_warning(err:*const c_char,...); + fn find_variable (str:*const c_char)->* mut SHELL_VAR; + fn find_global_variable (str:*const c_char)->* mut SHELL_VAR; + fn reset_internal_getopt(); + fn internal_getopt (list:*mut WORD_LIST , opts:*mut c_char)->i32; + static mut list_opttype:i32; + static mut array_needs_making:i32; + fn builtin_usage(); + static mut loptend:*mut WORD_LIST; + fn show_local_var_attributes (v:i32, nodefs:i32)->i32; + fn show_all_var_attributes (v:i32, nodefs:i32)->i32; + fn set_builtin (list:*mut WORD_LIST)->i32; + fn set_or_show_attributes (list:*mut WORD_LIST, attribute:i32, nodefs:i32)->i32; + fn sh_chkwrite (ret:i32)->i32; + fn show_func_attributes (name:* mut c_char, nodefs:i32)->i32; + fn show_localname_attributes (name:* mut c_char, nodefs:i32)->i32; + fn show_name_attributes (name:* mut c_char, nodefs:i32)->i32; + fn sh_notfound (name:* mut c_char); + static assoc_expand_once:i32; + fn assignment (str1:* const c_char, flags:i32)->i32; + fn make_local_variable (name:* const c_char, flags:i32)->* mut SHELL_VAR; + fn get_current_options ()->* mut c_char; + fn valid_array_reference (name:* const c_char, flags:i32)->i32; + fn check_selfref (name:* const c_char, value:* mut c_char, flags:i32)->i32; + fn valid_nameref_value (name:* const c_char, flags:i32)->i32; + fn sh_invalidid (value:* mut c_char); + static mut posixly_correct:i32; + fn nameref_transform_name (name:* mut c_char, flags:i32)->* mut c_char; + fn find_variable_last_nameref (name:* const c_char, flags:i32)->* mut SHELL_VAR; + fn make_local_assoc_variable (value:* mut c_char, flags:i32)->* mut SHELL_VAR; + fn make_local_array_variable (value:* mut c_char, flags:i32)->* mut SHELL_VAR; + fn find_global_variable_last_nameref (value:* const c_char, flags:i32)->* mut SHELL_VAR; + fn find_global_variable_noref (value:* const c_char)->* mut SHELL_VAR; + fn find_variable_noref (value:* const c_char)->* mut SHELL_VAR; + fn sh_readonly (name:* const c_char); + fn sh_invalidopt (value:* mut c_char); + static mut debugging_mode:i32; + fn find_function_def (name:* const c_char)->* mut function_def; + fn named_function_string (name:* mut c_char, cmd:* mut COMMAND, i:i32)->* mut c_char; + fn make_new_assoc_variable (name:* mut c_char)->* mut SHELL_VAR; + fn make_new_array_variable (name:* mut c_char)->* mut SHELL_VAR; + fn bind_global_variable (name:* const c_char,value:* mut c_char,flags:i32)->* mut SHELL_VAR; + fn bind_variable (name:* const c_char,value:* mut c_char,flags:i32)->* mut SHELL_VAR; + static mut shell_compatibility_level:i32; + fn internal_warning (format:* const c_char, ...); + fn assign_array_element (name:* mut c_char, value:* mut c_char, flags:i32)->* mut SHELL_VAR; + fn bind_assoc_variable (var:* mut SHELL_VAR, name:* mut c_char, key:* mut c_char, value:* mut c_char, flags:i32)->* mut SHELL_VAR; + fn bind_array_variable (name:* mut c_char, s:libc::c_long, value:* mut c_char, flags:i32)->* mut SHELL_VAR; + fn bind_variable_value (var:* mut SHELL_VAR, name:* mut c_char, flags:i32)->* mut SHELL_VAR; + fn delete_var (name:* const c_char, varc:* mut VAR_CONTEXT)->i32; + static global_variables:* mut VAR_CONTEXT; + static shell_variables:* mut VAR_CONTEXT; + fn find_tempenv_variable (format:* const c_char)->* mut SHELL_VAR; + fn stupidly_hack_special_variables (name:* mut c_char); + fn assign_array_var_from_string (var:* mut SHELL_VAR, value:* mut c_char, flags:i32)->* mut SHELL_VAR; + fn convert_var_to_array (var:* mut SHELL_VAR)->* mut SHELL_VAR; + fn convert_var_to_assoc (var:* mut SHELL_VAR)->* mut SHELL_VAR; + fn find_function (name:* const c_char)->* mut SHELL_VAR; + fn legal_identifier (name:* const c_char)->i32; +} + +#[no_mangle] +pub extern "C" fn r_declare_builtin (list:* mut WORD_LIST)->i32 +{ + return r_declare_internal (list, 0); +} + +unsafe fn STREQ( a:* const c_char, b:* const c_char)->bool { + return *a ==*b && libc::strcmp(a, b) == 0; +} + +#[no_mangle] +pub extern "C" fn r_local_builtin (list:* mut WORD_LIST)->i32 +{ + unsafe { + /* Catch a straight `local --help' before checking function context */ + if list !=std::ptr::null_mut() && (*list).word != std::ptr::null_mut() && STREQ ((*(*list).word).word, CString::new("--help").unwrap().as_ptr()) { + builtin_help (); + return EX_USAGE!(); + } + + if variable_context !=0 { + return r_declare_internal (list, 1); + } else { + builtin_error (CString::new("can only be used in a function").unwrap().as_ptr()); + return EXECUTION_FAILURE!(); + } + } + +} + +unsafe fn local_p( varr:* mut SHELL_VAR)->i32 { + return (*varr).attributes & att_local!(); +} + +#[no_mangle] +pub extern "C" fn r_declare_find_variable (name:* const c_char, mkglobal:i32, chklocal:i32)->* mut SHELL_VAR +{ + let varr: * mut SHELL_VAR; + unsafe { + if mkglobal == 0 { + return find_variable (name); + } else if chklocal !=0 { + varr = find_variable (name); + if varr != std::ptr::null_mut() && local_p (varr) !=0 && (*varr).context == variable_context { + return varr; + } + + return find_global_variable (name); + } else { + return find_global_variable (name); + } + } +} + +unsafe fn DECLARE_OPTS()->* const c_char +{ + return CString::new("+acfgilnprtuxAFGI").unwrap().as_ptr(); +} + +unsafe fn savestring(x:* const c_char)->* mut c_char +{ + let str1:* mut c_char=libc::malloc(1 + libc::strlen (x )) as * mut c_char; + return libc::strcpy(str1,x ); +} + +unsafe fn value_cell(var:*mut SHELL_VAR)->* mut c_char +{ + return (*var).value; +} + +unsafe fn var_setvalue(var:*mut SHELL_VAR,str1:* mut c_char) +{ + (*var).value=str1; +} + +unsafe fn VSETATTR(var:*mut SHELL_VAR, attr:i32) { + (*var).attributes=attr; +} + +unsafe fn readonly_p(var:*mut SHELL_VAR) ->i32 { + return (*var).attributes & att_readonly!(); +} + +unsafe fn nameref_p(var:*mut SHELL_VAR) ->i32 { + return (*var).attributes & att_nameref!(); +} + +unsafe fn nameref_cell(var:*mut SHELL_VAR) ->* mut c_char { + return (*var).value;/* so it can change later */ +} + +unsafe fn function_cell(var:*mut SHELL_VAR) ->* mut COMMAND { + return (*var).value as * mut COMMAND; +} + +unsafe fn VUNSETATTR(var:*mut SHELL_VAR,attr:i32) ->i32 { + return (*var).attributes & !attr; +} + +unsafe fn array_p(var:*mut SHELL_VAR) ->i32 { + return (*var).attributes & att_array!(); +} + +unsafe fn assoc_p(var:*mut SHELL_VAR) ->i32 { + return (*var).attributes & att_assoc!(); +} + +unsafe fn var_isset(var:*mut SHELL_VAR) ->bool { + return (*var).value !=std::ptr::null_mut(); +} + +unsafe fn tempvar_p(var:*mut SHELL_VAR) ->i32 { + return (*var).attributes & att_tempvar!(); +} + +unsafe fn noassign_p(var:*mut SHELL_VAR) ->i32 { + return (*var).attributes & att_noassign!(); +} + +#[no_mangle] +pub extern "C" fn r_declare_internal (list:* mut WORD_LIST, local_var:i32)->i32 +{ + let mut flags_on:i32=0; + let mut flags_off:i32=0; + let mut flags:* mut i32; + let mut any_failed:i32=0; + let mut assign_error:i32=0; + let mut pflag:i32=0; + let mut nodefs:i32=0; + let opt:i32; + let mut onref:i32; + let mut offref:i32; + let mut mkglobal:i32=0; + let mut chklocal:i32=0; + let mut inherit_flag:i32=0; + + let mut t: *mut c_char; + let mut subscript_start: *mut c_char; + let mut var:*mut SHELL_VAR; + let mut refvar:*mut SHELL_VAR; + let mut v:*mut SHELL_VAR; + + let mut shell_fn:*mut function_def; + + refvar = std::ptr::null_mut(); + + unsafe { + reset_internal_getopt (); + opt = internal_getopt (list, DECLARE_OPTS() as * mut c_char); + while opt != -1 { + if list_opttype == '+' as i32 { + flags= &mut flags_off; + } else { + flags= &mut flags_on; + } + + let optu8:u8= opt as u8; + let optChar:char=char::from(optu8); + + /* If you add options here, see whether or not they need to be added to + the loop in subst.c:shell_expand_word_list() */ + match optChar { + 'a'=>{ *flags |= att_array!();} + 'A'=>{ *flags |= att_assoc!();} + 'p'=>{ pflag+=1;} + 'F'=>{ nodefs+=1; + *flags |= att_function!(); + } + 'f'=>{ *flags |= att_function!();} + 'G'=>{ + if flags == &mut flags_on { + chklocal = 1; + } + } + 'g'=>{ + if flags == &mut flags_on { + mkglobal = 1; + } + } + 'i'=>{ *flags |= att_integer!();} + 'n'=>{ *flags |= att_nameref!();} + 'r'=>{ *flags |= att_readonly!();} + 't'=>{ *flags |= att_trace!();} + 'x'=>{ *flags |= att_exported!(); + array_needs_making = 1; + } + 'c'=>{ *flags |= att_capcase!(); + if flags == &mut flags_on { + flags_off |= att_uppercase!() | att_lowercase!(); + } + } + 'l'=>{ *flags |= att_lowercase!(); + if flags == &mut flags_on { + flags_off |= att_capcase!()| att_uppercase!(); + } + } + 'u'=>{ *flags |= att_uppercase!(); + if flags == &mut flags_on { + flags_off |= att_capcase!()| att_lowercase!(); + } + } + 'I'=>{ inherit_flag = MKLOC_INHERIT!();} + _=>{ builtin_usage (); + return EX_USAGE!(); + } + } + internal_getopt (list, DECLARE_OPTS() as * mut c_char); + } + + let mut llist:* mut WORD_LIST = loptend.clone(); + + /* If there are no more arguments left, then we just want to show + some variables. */ + if llist == std::ptr::null_mut() { /* declare -[aAfFirtx] */ + /* Show local variables defined at this context level if this is + the `local' builtin. */ + if local_var != 0 { + show_local_var_attributes (0, nodefs); /* XXX - fix up args later */ + } else if pflag != 0 && (flags_on == 0 || flags_on == att_function!()) { + let mut ret=0; + if flags_on == 0 { + ret=1; + } + show_all_var_attributes (ret, nodefs); + } else if flags_on == 0 { + return set_builtin (std::ptr::null_mut()); + } else { + set_or_show_attributes (std::ptr::null_mut(), flags_on, nodefs); + } + return sh_chkwrite (EXECUTION_SUCCESS!()); + } + + if pflag !=0 { /* declare -p [-aAfFirtx] name [name...] */ + any_failed=0; + while llist != std::ptr::null_mut() { + if (flags_on & att_function!()) != 0 { + pflag = show_func_attributes ((*(*llist).word).word, nodefs); + } else if local_var !=0 { + pflag = show_localname_attributes ((*(*llist).word).word, nodefs); + } else { + pflag = show_name_attributes ((*(*llist).word).word, nodefs); + } + + if pflag !=0 { + sh_notfound ((*(*llist).word).word); + any_failed+=1; + } + llist = (*llist).next; + } + + if any_failed !=0 { + return EXECUTION_FAILURE!(); + } else { + return EXECUTION_SUCCESS!(); + } + } + + /* There are arguments left, so we are making variables. */ + while llist !=std::ptr::null_mut() { /* declare [-aAfFirx] name [name ...] */ + + let mut value:* mut c_char; + let mut name:* mut c_char; + let mut oldname:* mut c_char; + let mut offset:i32; + let mut aflags:i32; + let wflags:i32; + let mut created_var:i32; + let mut namelen:i32; + let assoc_noexpand:i32; + + let mut making_array_special:i32; + let mut compound_array_assign:i32; + let mut simple_array_assign:i32; + let mut var_exists:i32; + let mut array_exists:i32; + let mut creating_array:i32; + let mut array_subscript_assignment:i32; + + name = savestring ((*(*llist).word).word); + wflags = (*(*llist).word).flags; + + assoc_noexpand = (assoc_expand_once !=0 && (wflags & (1 << 2)) !=0) as i32; + if assoc_noexpand !=0 { + offset = assignment (name, 2); + } else { + offset = assignment (name, 0); + } + + aflags = 0; + created_var = 0; + + if local_var !=0 && variable_context !=0 && STREQ (name, CString::new("-").unwrap().as_ptr()) { + var = make_local_variable (CString::new("-").unwrap().as_ptr(), 0); + libc::free (value_cell (var) as * mut c_void); /* just in case */ + value = get_current_options (); + var_setvalue (var, value); + VSETATTR (var, att_invisible!()); + libc::free (name as * mut c_void); + llist = (*llist).next; + continue; + } + + if offset !=0 { /* declare [-aAfFirx] name=value */ + *((name as usize + offset as usize) as * mut c_char) = '\0' as c_char; + value = (name as usize + (offset + 1) as usize) as * mut c_char; + if *((name as usize + (offset - 1) as usize) as * mut c_char) == '+' as c_char { + aflags |= ASS_APPEND!(); + *((name as usize + (offset - 1) as usize) as * mut c_char) = '\0' as c_char; + } + } else { + value = CString::new("").unwrap().as_ptr() as * mut c_char; + } + + /* Do some lexical error checking on the LHS and RHS of the assignment + that is specific to nameref variables. */ + if (flags_on & att_nameref!()) !=0 { + if valid_array_reference (name, 0) !=0 { + builtin_error (CString::new("%s: reference variable cannot be an array").unwrap().as_ptr(), name); + assign_error+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + continue; + } else if check_selfref (name, value, 0) !=0 {/* disallow self references at global scope, warn at function scope */ + if variable_context == 0 { + builtin_error (CString::new("%s: nameref variable self references not allowed").unwrap().as_ptr(), name); + assign_error+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + continue; + } else { + builtin_warning (CString::new("%s: circular name reference").unwrap().as_ptr(), name); + } + } + + if value != std::ptr::null_mut() && (*value) !=0 && (aflags & ASS_APPEND!()) == 0 && valid_nameref_value (value, 1) == 0 { + builtin_error (CString::new("`nvalid %s': ivariable name for name reference").unwrap().as_ptr(), value); + assign_error+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + continue; + } + } + +//restart_new_var_name: + loop { + + var_exists = 0; + array_exists = 0; + creating_array = 0; + compound_array_assign = 0; + simple_array_assign = 0; + array_subscript_assignment = 0; + subscript_start = std::ptr::null_mut(); + t = libc::strchr (name, '[' as libc::c_int); + if t !=std::ptr::null_mut() && (flags_on & att_function!()) == 0 {/* ] */ + /* If offset != 0 we have already validated any array reference + because assignment() calls skipsubscript() */ + if offset == 0 && valid_array_reference (name, 0) == 0 { + sh_invalidid (name); + assign_error+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + + subscript_start = t; + *t = '\0' as c_char; + making_array_special = 1; /* XXX - should this check offset? */ + array_subscript_assignment = (offset != 0) as i32; + } else { + making_array_special = 0; + } + /* If we're in posix mode or not looking for a shell function (since + shell function names don't have to be valid identifiers when the + shell's not in posix mode), check whether or not the argument is a + valid, well-formed shell identifier. */ + if (posixly_correct !=0 || (flags_on & att_function!()) == 0) && legal_identifier (name) == 0 { + sh_invalidid (name); + assign_error+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + /* If VARIABLE_CONTEXT has a non-zero value, then we are executing + inside of a function. This means we should make local variables, + not global ones. */ + + /* XXX - this has consequences when we're making a local copy of a + variable that was in the temporary environment. Watch out + for this. */ + refvar = std::ptr::null_mut(); + if variable_context !=0 && mkglobal == 0 && ((flags_on & att_function!()) == 0) { + let newname: * mut c_char; + + /* check name for validity here? */ + var = find_variable (name); + if var == std::ptr::null_mut() { + newname = nameref_transform_name (name, ASS_MKLOCAL!()); + } else if (flags_on & att_nameref!()) == 0 && (flags_off & att_nameref!()) == 0 { + /* Ok, we're following namerefs here, so let's make sure that if + we followed one, it was at the same context (see below for + more details). */ + refvar = find_variable_last_nameref (name, 1); + if refvar != std::ptr::null_mut() && (*refvar).context != variable_context { + newname = name ; + } else { + newname = (*var).name; + } + refvar = std::ptr::null_mut(); + } else { + newname = name; /* dealing with nameref attribute */ + } + + /* Pass 1 as second argument to make_local_{assoc,array}_variable + return an existing {array,assoc} variable to be flagged as an + error below. */ + if (flags_on & att_assoc!()) !=0 { + var = make_local_assoc_variable (newname, MKLOC_ARRAYOK!()|inherit_flag); + } else if (flags_on & att_array!()) !=0 || making_array_special !=0 { + var = make_local_array_variable (newname, MKLOC_ASSOCOK!()|inherit_flag); + } else if offset == 0 && (flags_on & att_nameref!()) !=0 { + /* First look for refvar at current scope */ + refvar = find_variable_last_nameref (name, 1); + /* VARIABLE_CONTEXT != 0, so we are attempting to create or modify + the attributes for a local variable at the same scope. If we've + used a reference from a previous context to resolve VAR, we + want to throw REFVAR and VAR away and create a new local var. */ + if refvar != std::ptr::null_mut() && (*refvar).context != variable_context { + refvar = std::ptr::null_mut(); + var = make_local_variable (name, inherit_flag); + } else if refvar != std::ptr::null_mut() && (*refvar).context == variable_context { + var = refvar; + } else if var == std::ptr::null_mut() || (*refvar).context != variable_context {/* Maybe we just want to create a new local variable */ + var = make_local_variable (name, inherit_flag); + } + /* otherwise we have a var at the right context */ + } else { + /* XXX - check name for validity here with valid_nameref_value */ + if flags_on & att_nameref!() !=0 { + var = make_local_variable ( name , inherit_flag); + } else { + var = make_local_variable ( newname, inherit_flag); /* sets att_invisible for new vars */ + } + } + + if var == std::ptr::null_mut() { + any_failed+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + + if var != std::ptr::null_mut() && nameref_p (var) !=0 && readonly_p (var) != 0 && nameref_cell (var) != std::ptr::null_mut() && (flags_off & att_nameref!()) !=0 { + sh_readonly (name); + any_failed+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + } else { + var = std::ptr::null_mut(); + } + /* If we are declaring a function, then complain about it in some way. + We don't let people make functions by saying `typeset -f foo=bar'. */ + + /* There should be a way, however, to let people look at a particular + function definition by saying `typeset -f foo'. */ + + if (flags_on & att_function!()) !=0 { + if offset !=0 { /* declare -f [-rix] foo=bar */ + builtin_error (CString::new("cannot use `-f' to make functions").unwrap().as_ptr()); + libc::free (name as * mut c_void); + return EXECUTION_FAILURE!(); + } else {/* declare -f [-rx] name [name...] */ + var = find_function (name); + if var != std::ptr::null_mut() { + if readonly_p (var) !=0 && (flags_off & att_readonly!()) !=0 { + builtin_error (CString::new("%s: readonly function").unwrap().as_ptr(), name); + any_failed+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } else if (flags_on & (att_array!()|att_assoc!())) !=0 { + if (flags_on & att_array!()) !=0 { + sh_invalidopt (CString::new("-a").unwrap().as_ptr() as * mut c_char); + } else { + sh_invalidopt (CString::new("-A").unwrap().as_ptr() as * mut c_char); + } + + any_failed+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + /* declare -[Ff] name [name...] */ + if flags_on == att_function!() && flags_off == 0 { + if nodefs !=0 && debugging_mode !=0 { + shell_fn = find_function_def ((*var).name); + if shell_fn !=std::ptr::null_mut() { + libc::printf (CString::new("%s %d %s\n").unwrap().as_ptr(), (*var).name, (*shell_fn).line, (*shell_fn).source_file); + } else { + libc::printf (CString::new("%s\n").unwrap().as_ptr(), (*var).name); + } + } else { + if nodefs !=0 { + t=(*var).name; + } else { + named_function_string (name, function_cell (var), FUNC_MULTILINE!()|FUNC_EXTERNAL!()); + } + libc::printf (CString::new("%s\n").unwrap().as_ptr(), t); + any_failed = sh_chkwrite (any_failed); + } + } else { /* declare -[fF] -[rx] name [name...] */ + VSETATTR (var, flags_on); + flags_off &= ! att_function!(); /* makes no sense */ + VUNSETATTR (var, flags_off); + } + } else { + any_failed+=1; + } + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + } else { /* declare -[aAinrx] name [name...] */ + /* Non-null if we just created or fetched a local variable. */ + + /* Here's what ksh93 seems to do as of the 2012 version: if we are + using declare -n to modify the value of an existing nameref + variable, don't follow the nameref chain at all and just search + for a nameref at the current context. If we have a nameref, + modify its value (changing which variable #define ASS_NAMEREF 0x0010 /* assigning to nameref variable */it references). */ + if var == std::ptr::null_mut() && (flags_on & att_nameref!()) !=0 { + /* See if we are trying to modify an existing nameref variable, + but don't follow the nameref chain. */ + if mkglobal !=0 { + var = find_global_variable_noref (name); + } else { + var = find_variable_noref (name); + } + + if var != std::ptr::null_mut() && nameref_p (var) == 0 { + var = std::ptr::null_mut(); + } + } else if var == std::ptr::null_mut() && (flags_off & att_nameref!()) !=0 { + /* However, if we're turning off the nameref attribute on an existing + nameref variable, we first follow the nameref chain to the end, + modify the value of the variable this nameref variable references + if there is an assignment statement argument, + *CHANGING ITS VALUE AS A SIDE EFFECT*, then turn off the nameref + flag *LEAVING THE NAMEREF VARIABLE'S VALUE UNCHANGED* */ + /* See if we are trying to modify an existing nameref variable */ + if mkglobal !=0 { + refvar=find_global_variable_last_nameref (name, 0); + } else { + refvar=find_variable_last_nameref (name, 0); + } + + if refvar != std::ptr::null_mut() && nameref_p (refvar) == 0 { + refvar = std::ptr::null_mut(); + } + /* If the nameref is readonly but doesn't have a value, ksh93 + allows the nameref attribute to be removed. If it's readonly + and has a value, even if the value doesn't reference an + existing variable, we disallow the modification */ + if refvar != std::ptr::null_mut() && nameref_cell (refvar) != std::ptr::null_mut() && readonly_p (refvar) != 0 { + sh_readonly (name); + any_failed+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + /* If all we're doing is turning off the nameref attribute, don't + bother with VAR at all, whether it exists or not. Just turn it + off and go on. */ + if refvar != std::ptr::null_mut() && flags_on == 0 && offset == 0 && (flags_off & !att_nameref!()) == 0 { + VUNSETATTR (refvar, att_nameref!()); + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + + if refvar !=std::ptr::null_mut() { + /* XXX - use declare_find_variable here? */ + if mkglobal !=0 { + var = find_global_variable (nameref_cell (refvar)); + } else { + var =find_variable (nameref_cell (refvar)); + } + } + } else if var == std::ptr::null_mut() && offset !=0 && array_subscript_assignment !=0 { + /* If we have an array assignment to a nameref, remove the nameref + attribute and go on. */ + if mkglobal !=0 { + var = find_global_variable_noref (name); + } else { + var = find_variable_noref (name); + } + + if var !=std::ptr::null_mut() && nameref_p (var) !=0 { + internal_warning (CString::new("%s: removing nameref attribute").unwrap().as_ptr(), name); + libc::free (value_cell (var) as * mut c_void); /* XXX - bash-4.3 compat */ + var_setvalue (var, std::ptr::null_mut()); + VUNSETATTR (var, att_nameref!()); + } + } + + /* See if we are trying to set flags or value (or create) for an + existing nameref that points to a non-existent variable: e.g., + declare -n foo=bar + unset foo # unsets bar + declare -i foo + foo=4+4 + declare -p foo */ + if var == std::ptr::null_mut() && (mkglobal !=0 || flags_on !=0 || flags_off !=0 || offset !=0) { + if mkglobal !=0 { + refvar = find_global_variable_last_nameref (name, 0); + } else { + refvar = find_variable_last_nameref (name, 0); + } + + if refvar != std::ptr::null_mut() && nameref_p (refvar) == 0 { + refvar = std::ptr::null_mut(); + } + + if refvar !=std::ptr::null_mut() { + /* XXX - use declare_find_variable here? */ + if mkglobal !=0 { + var = find_global_variable (nameref_cell (refvar)) ; + } else { + var = find_variable (nameref_cell (refvar)); + } + } + + if refvar !=std::ptr::null_mut() && var == std::ptr::null_mut() { + oldname = name; /* need to free this */ + namelen = libc::strlen (nameref_cell (refvar)) as i32; + + if subscript_start != std::ptr::null_mut() { + *subscript_start = '[' as c_char; /*]*/ + namelen += libc::strlen (subscript_start) as i32; + } + + name = libc::malloc (namelen as libc::size_t + 2 + libc::strlen (value) + 1 ) as * mut c_char ; + libc::strcpy (name, nameref_cell (refvar)); + + if subscript_start != std::ptr::null_mut() { + libc::strcpy ((name as usize + (libc::strlen (nameref_cell (refvar))) as usize) as * mut c_char, subscript_start); + } + + /* We are committed to using the new name, so reset */ + if offset !=0 { + /* Rebuild assignment and restore offset and value */ + if (aflags & ASS_APPEND!()) !=0 { + *((name as usize + namelen as usize) as * mut c_char) = '+' as c_char; + namelen+=1; + } + + *((name as usize + namelen as usize) as * mut c_char) = '=' as c_char; + namelen+=1; + + if value != std::ptr::null_mut() && (*value) !=0 { + libc::strcpy ((name as usize + namelen as usize) as * mut c_char, value); + } else { + *((name as usize + namelen as usize) as * mut c_char) = '\0' as c_char; + } + + offset = assignment (name, 0); + /* if offset was valid previously, but the substituting + of the nameref value results in an invalid assignment, + throw an invalid identifier error */ + if offset == 0 { + libc::free (oldname as * mut c_void); + sh_invalidid (name); + assign_error+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + *((name as usize + offset as usize) as * mut c_char) = '\0' as c_char; + value = (name as usize + namelen as usize) as * mut c_char; + } + libc::free (oldname as * mut c_void); + + /* OK, let's turn off the nameref attribute. + Now everything else applies to VAR. */ + if (flags_off & att_nameref!()) !=0 { + VUNSETATTR (refvar, att_nameref!()); + } + + //goto restart_new_var_name; + continue; + /* NOTREACHED */ + } + } + if var == std::ptr::null_mut() { + var = r_declare_find_variable (name, mkglobal, chklocal); + } + + var_exists = (var != std::ptr::null_mut()) as i32; + array_exists = (var != std::ptr::null_mut() && (array_p (var) !=0 || assoc_p (var) !=0 )) as i32; + creating_array = flags_on & (att_array!()|att_assoc!()); + + if var == std::ptr::null_mut() { + if (flags_on & att_assoc!()) !=0 { + var = make_new_assoc_variable (name); + if var != std::ptr::null_mut() && offset == 0 { + VSETATTR (var, att_invisible!()); + } + } else if (flags_on & att_array!()) !=0 || making_array_special !=0 { + var = make_new_array_variable (name); + if var != std::ptr::null_mut() && offset == 0 { + VSETATTR (var, att_invisible!()); + } + } else { + if mkglobal !=0 { + var=bind_global_variable (name, std::ptr::null_mut(), ASS_FORCE!()); + } else { + var= bind_variable (name, std::ptr::null_mut(), ASS_FORCE!()); + } + if var != std::ptr::null_mut() && offset == 0 { + VSETATTR (var, att_invisible!()); + } + } + + if var == std::ptr::null_mut() { + /* Has to appear in brackets */ + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + created_var = 1; + } else if (array_p (var) !=0 || assoc_p (var) !=0 ) && (flags_on & att_nameref!()) !=0 { + /* Can't take an existing array variable and make it a nameref */ + builtin_error (CString::new("%s: reference variable cannot be an array").unwrap().as_ptr(), name); + assign_error+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } else if nameref_p (var) !=0 && (flags_on & att_nameref!()) == 0 && (flags_off & att_nameref!()) == 0 && offset !=0 && valid_nameref_value (value, 1) == 0 { + builtin_error (CString::new("`%s': invalid variable name for name reference").unwrap().as_ptr(), value); + any_failed+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } else if (flags_on & att_nameref!()) !=0 { + /* Check of offset is to allow an assignment to a nameref var as + part of the declare word to override existing value */ + if nameref_p (var) == 0 && var_isset (var) && offset == 0 && valid_nameref_value (value_cell (var), 0) == 0 { + builtin_error (CString::new("`%s': invalid variable name for name reference").unwrap().as_ptr(), value_cell (var)); + any_failed+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + + if readonly_p (var) !=0 { + sh_readonly (name); + any_failed+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + /* ksh93 compat: turning on nameref attribute turns off -ilu */ + VUNSETATTR (var, att_integer!()|att_uppercase!()|att_lowercase!()|att_capcase!()); + } + + /* Cannot use declare +r to turn off readonly attribute. */ + if readonly_p (var) !=0 && (flags_off & att_readonly!()) !=0 { + sh_readonly ((*var).name); + any_failed+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + + /* Cannot use declare to assign value to readonly or noassign + variable. */ + if (readonly_p (var) !=0 || noassign_p (var)!=0 ) && offset !=0 { + if readonly_p (var) !=0 { + sh_readonly (name); + } + assign_error+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + + /* make declare a[2]=foo as similar to a[2]=foo as possible if + a is already an array or assoc variable. */ + if array_subscript_assignment !=0 && array_exists !=0 && creating_array == 0 { + simple_array_assign = 1; + } else if (making_array_special !=0 || creating_array !=0 || array_exists !=0) && offset!=0 { + let mut vlen:i32; + vlen = libc::strlen (value) as i32; + /*itrace("declare_builtin: name = %s value = %s flags = %d", name, value, wflags);*/ + if shell_compatibility_level > 43 && (wflags & W_COMPASSIGN!()) == 0 && *value == '(' as c_char && *((value as usize + (vlen-1) as usize) as * mut c_char) == ')' as c_char { + /* The warning is only printed when using compound assignment + to an array variable that doesn't already exist. We use + creating_array to allow things like + declare -a foo$bar='(abc)' to work. */ + if array_exists == 0 && creating_array == 0 { + internal_warning (CString::new("%s: quoted compound array assignment deprecated").unwrap().as_ptr(), (*(*llist).word).word); + } + compound_array_assign = (array_exists !=0 || creating_array !=0) as i32; + simple_array_assign = making_array_special; + } else if *value == '(' as c_char && *((value as usize + (vlen-1) as usize) as * mut c_char) == ')' as c_char && (shell_compatibility_level < 44 || (wflags & W_COMPASSIGN!()) !=0 ) { + compound_array_assign = 1; + } else { + simple_array_assign = 1; + } + } + + /* Cannot use declare +a name or declare +A name to remove an + array variable. */ + if ((flags_off & att_array!()) !=0 && array_p (var) !=0) || ((flags_off & att_assoc!()) !=0 && assoc_p (var) !=0) { + builtin_error (CString::new("%s: cannot destroy array variables in this way").unwrap().as_ptr(), name); + any_failed+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + + if (flags_on & att_array!()) !=0 && assoc_p (var) !=0 { + builtin_error (CString::new("%s: cannot convert associative to indexed array").unwrap().as_ptr(), name); + any_failed+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + + if (flags_on & att_assoc!()) !=0 && array_p (var) !=0 { + builtin_error (CString::new("%s: cannot convert indexed to associative array").unwrap().as_ptr(), name); + any_failed+=1; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + + /* declare -A name[[n]] makes name an associative array variable. */ + if (flags_on & att_assoc!()) !=0 { + if assoc_p (var) == 0 { + var = convert_var_to_assoc (var); + } + } else if (making_array_special !=0 || (flags_on & att_array!()) !=0 ) && array_p (var) == 0 && assoc_p (var) == 0 { + /* declare -a name[[n]] or declare name[n] makes name an indexed + array variable. */ + var = convert_var_to_array (var); + } + + /* XXX - we note that we are turning on nameref attribute and defer + setting it until the assignment has been made so we don't do an + inadvertent nameref lookup. Might have to do the same thing for + flags_off&att_nameref. */ + /* XXX - ksh93 makes it an error to set a readonly nameref variable + using a single typeset command. */ + onref = flags_on & att_nameref!(); + flags_on &= !att_nameref!(); + + if array_p (var) !=0 || assoc_p (var) !=0 || (offset !=0 && compound_array_assign !=0) || simple_array_assign !=0 { + onref = 0; /* array variables may not be namerefs */ + } + /* ksh93 seems to do this */ + offref = flags_off & att_nameref!(); + flags_off &= !att_nameref!(); + + VSETATTR (var, flags_on); + VUNSETATTR (var, flags_off); + + if offset !=0 && compound_array_assign !=0 { + assign_array_var_from_string (var, value, aflags|ASS_FORCE!()); + } else if simple_array_assign !=0 && subscript_start !=std::ptr::null_mut() { + let mut local_aflags:i32; + /* declare [-aA] name[N]=value */ + *subscript_start = '[' as c_char; /* ] */ + /* XXX - problem here with appending */ + local_aflags = aflags&ASS_APPEND!(); + if assoc_noexpand !=0 { + local_aflags |= ASS_NOEXPAND!(); + } else { + local_aflags |= 0; + } + + var = assign_array_element (name, value, local_aflags); /* XXX - not aflags */ + *subscript_start = '\0' as c_char; + if var == std::ptr::null_mut() {/* some kind of assignment error */ + assign_error+=1; + flags_on |= onref; + flags_off |= offref; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + } else if simple_array_assign !=0 { + /* let bind_{array,assoc}_variable take care of this. */ + if assoc_p (var) !=0 { + bind_assoc_variable (var, name, savestring (CString::new("0").unwrap().as_ptr()), value, aflags|ASS_FORCE!()); + } else { + bind_array_variable (name, 0, value, aflags|ASS_FORCE!()); + } + } else if offset !=0 { + /* XXX - no ASS_FORCE here */ + /* bind_variable_value duplicates the essential internals of bind_variable() */ + if onref !=0 || nameref_p (var) !=0 { + aflags |= ASS_NAMEREF!(); + } + + v = bind_variable_value (var, value, aflags); + if v == std::ptr::null_mut() && (onref !=0 || nameref_p (var) !=0) { + if valid_nameref_value (value, 1) == 0 { + sh_invalidid (value); + } + + assign_error+=1; + /* XXX - unset this variable? or leave it as normal var? */ + if created_var !=0 { + if mkglobal !=0 { + delete_var ( (*var).name, global_variables); + } else { + delete_var ( (*var).name, shell_variables); + } + } + + flags_on |= onref;/* undo change from above */ + flags_off |= offref; + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + } + + /* If we found this variable in the temporary environment, as with + `var=value declare -x var', make sure it is treated identically + to `var=value export var'. Do the same for `declare -r' and + `readonly'. Preserve the attributes, except for att_tempvar. */ + /* XXX -- should this create a variable in the global scope, or + modify the local variable flags? ksh93 has it modify the + global scope. + Need to handle case like in set_var_attribute where a temporary + variable is in the same table as the function local vars. */ + if (flags_on & (att_exported!()|att_readonly!()) !=0 ) && tempvar_p (var) !=0 { + let mut tv:* mut SHELL_VAR; + let tvalue:* mut c_char=std::ptr::null_mut(); + + tv = find_tempenv_variable ((*var).name); + if tv != std::ptr::null_mut() { + if var_isset(var) { + savestring (value_cell (var)); + } else { + savestring (CString::new("").unwrap().as_ptr()); + } + tv = bind_variable ((*var).name, tvalue, 0); + + if tv != std::ptr::null_mut() { + (*tv).attributes |= (*var).attributes & !att_tempvar!(); + if (*tv).context > 0 { + VSETATTR (tv, att_propagate!()); + } + } + libc::free (tvalue as * mut c_void); + } + VSETATTR (var, att_propagate!()); + } + } + + /* Turn on nameref attribute we deferred above. */ + /* XXX - should we turn on the noassign attribute for consistency with + ksh93 when we turn on the nameref attribute? */ + VSETATTR (var, onref); + flags_on |= onref; + VUNSETATTR (var, offref); + flags_off |= offref; + /* Yuck. ksh93 compatibility. XXX - need to investigate more but + definitely happens when turning off nameref attribute on nameref + (see comments above). Under no circumstances allow this to turn + off readonly attribute on readonly nameref variable. */ + if refvar !=std::ptr::null_mut() { + if (flags_off & att_readonly!()) !=0 { + flags_off &= !att_readonly!(); + } + VUNSETATTR (refvar, flags_off); + } + + stupidly_hack_special_variables (name); + libc::free (name as * mut c_void); + llist = (*llist).next; + break; + } + } + if assign_error !=0 { + return EX_BADASSIGN!(); + } else { + if any_failed == 0 { + return EXECUTION_SUCCESS!(); + } else { + return EXECUTION_FAILURE!(); + } + } +} +} + +#[no_mangle] +pub extern "C" fn cmd_name() ->*const u8 { + return b"declare" as *const u8; +} + +#[no_mangle] +pub extern "C" fn run(list : *mut WORD_LIST)->i32 { + return r_declare_builtin(list); +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/echo/.gitignore b/bash-5.1/builtins_rust/echo/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4fffb2f89cbd8f2169ce9914bd16bd43785bb368 --- /dev/null +++ b/bash-5.1/builtins_rust/echo/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/bash-5.1/builtins_rust/echo/Cargo.toml b/bash-5.1/builtins_rust/echo/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..a2d9ac725adea985387f86a958adb45837f65592 --- /dev/null +++ b/bash-5.1/builtins_rust/echo/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "recho" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" + +[lib] +crate-type = ["cdylib"] +name = "recho" diff --git a/bash-5.1/builtins_rust/echo/src/lib.rs b/bash-5.1/builtins_rust/echo/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..aa704d09071c9c74a80627b974f5e7e5759648ce --- /dev/null +++ b/bash-5.1/builtins_rust/echo/src/lib.rs @@ -0,0 +1,233 @@ +extern crate libc; + +use libc::{c_char,c_int, strchr, putchar,clearerr,strlen,free,FILE, fprintf, c_void}; +use std::ffi::{CString,CStr,}; +use std::ops::Index; +// use std::io::{stdout, Write}; +use std::ptr::read_volatile; + +//结构体 +#[repr (C)] +pub struct WORD_DESC{ + pub word:*mut c_char, + pub flags:c_int, +} + +#[repr (C)] +// #[derive(Copy,Clone)] +pub struct WORD_LIST{ + pub next:*mut WORD_LIST, + pub word:*mut WORD_DESC, +} + + +//枚举 + +//宏 +#[macro_export] +macro_rules! VALID_ECHO_OPTIONS { + () => { + CString::new("neE").unwrap().as_ptr() + }; +} + + +#[macro_export] +macro_rules! QUIT { + () => { + if read_volatile(&terminating_signal as *const i32) != 0{ + termsig_handler(read_volatile(&terminating_signal as *const i32)); + } + if interrupt_state != 0{ + throw_to_top_level(); + } + }; +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {0} +} + + + +unsafe fn STRLEN (s:*const c_char) -> i32{ + + if s!=std::ptr::null_mut(){ + let s_cstr = CStr::from_ptr(s); + let s_str = s_cstr.to_str().unwrap(); + let s_string = s_str.to_owned(); + + let len = s_string.len(); + return len as i32; + } + else{ + return 0; + } + +} + + +// +extern "C"{ + static terminating_signal:c_int; + static interrupt_state:c_int; + static stdout:*mut FILE; + + fn termsig_handler(sig:i32); + fn throw_to_top_level(); + fn ansicstr(string:*mut c_char,len:i32,flags:i32,sawc:*mut c_int,rlen:*mut c_int)->*mut c_char; + fn sh_chkwrite(s:i32)->i32; +} + +/* System V machines already have a /bin/sh with a v9 behaviour. We + give Bash the identical behaviour for these machines so that the + existing system shells won't barf. Regrettably, the SUS v2 has + standardized the Sys V echo behavior. This variable is external + so that we can have a `shopt' variable to control it at runtime. */ + +pub static mut xpg_echo:i32 = 0; // 也有可能是1 + +/* Print the words in LIST to standard output. If the first word is + `-n', then don't print a trailing newline. We also support the + echo syntax from Version 9 Unix systems. */ + +#[no_mangle] +pub extern "C" fn r_echo_builtin(mut list:*mut WORD_LIST)->i32{ + println!("r_echo_builtin"); + let mut display_return:i32; + let mut do_v9:i32; + let mut i:i32; + let mut len:i32; + let mut temp:*mut c_char=std::ptr::null_mut(); + let mut s:*mut c_char; + + unsafe{ + do_v9 = xpg_echo; + display_return = 1; + + // if posixly_correct!=0 && xpg_echo!=0{ //xpg_echo=0,所以这个可能不用翻译 + + // } + if (*(*list).word).word != std::ptr::null_mut(){ + temp = (*(*list).word).word; + } + while !list.is_null() && *temp=='-' as c_char{ + /* If it appears that we are handling options, then make sure that + all of the options specified are actually valid. Otherwise, the + string should just be echoed. */ + + temp = (temp as usize +1) as *mut c_char; + let mut t = temp; + i = 0; + + while *temp as i32 != 0{ + let s = *temp as i32; + let su8 = s as u8; + let s_opt = char::from(su8); + + if strchr(VALID_ECHO_OPTIONS!(), s_opt as c_int).is_null(){ + break; + } + + temp = (temp as usize + 1) as *mut c_char; + i += 1; + } + // + /* echo - and echo - both mean to just echo the arguments. */ + if *t==0 || *((t as usize + i as usize) as *mut c_char) != 0{ + break; + } + + /* All of the options in TEMP are valid options to ECHO. + Handle them. */ + while !t.is_null(){ + let optu8 = *t as u8; + let opt_char = char::from(optu8); + + match opt_char{ + 'n' => { + display_return = 0; + } + 'e' => { + do_v9 = 1; + } + 'E' => { + do_v9 = 0; + } + _ => break, + } + t = (t as usize +1) as *mut c_char; + } + + list = (*list).next; + if !(*(*list).word).word.is_null(){ + temp = (*(*list).word).word; + } + } + + clearerr(stdout); /* clear error before writing and testing success */ + + while list != std::ptr::null_mut(){ + i = 0; + len =0; + + if do_v9 !=0{ + temp = ansicstr((*(*list).word).word,STRLEN((*(*list).word).word), 1,&mut i,&mut len); + } + else{ + temp = (*(*list).word).word; + } + + if temp != std::ptr::null_mut(){ + if do_v9 != 0{ + s = temp; + + for t in 0..len{ + putchar(*s as c_int ); + s = (s as usize + 1) as *mut c_char; + } + } + else { + fprintf(stdout, temp); + } + } + + QUIT!(); + if do_v9 !=0 && temp != std::ptr::null_mut(){ + free(temp as *mut c_void); + } + + list = (*list).next; + if i != 0{ + display_return = 0; + break; + } + + if list!=std::ptr::null_mut(){ + putchar(' ' as i32); + QUIT!(); + } + }//while + + if display_return != 0{ + putchar('\n' as i32); + } + + return sh_chkwrite(EXECUTION_SUCCESS!()); + + }//unsafe + +} + + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/enable/Cargo.toml b/bash-5.1/builtins_rust/enable/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..baac0a058fc239631bc46ba15ab75491316d792f --- /dev/null +++ b/bash-5.1/builtins_rust/enable/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "enable" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +name = "renable" +crate-type = ["staticlib"] + +[dependencies] +libc = "0.2" +libloading = "0.7" +rcmd = {path="../cmd"} diff --git a/bash-5.1/builtins_rust/enable/src/enable.rs b/bash-5.1/builtins_rust/enable/src/enable.rs new file mode 100644 index 0000000000000000000000000000000000000000..f70b002703774fa7f37611e88202289a19a2a435 --- /dev/null +++ b/bash-5.1/builtins_rust/enable/src/enable.rs @@ -0,0 +1,3 @@ +#[no_mangle] +pub extern "C" fn enable_builtin(list: WORD_LIST) { +} diff --git a/bash-5.1/builtins_rust/enable/src/lib.rs b/bash-5.1/builtins_rust/enable/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..1d61f3c4d8113466ae2dfdfb7cadb2b7bd7fe939 --- /dev/null +++ b/bash-5.1/builtins_rust/enable/src/lib.rs @@ -0,0 +1,686 @@ +use std::ffi::{CString,CStr}; +extern crate rcmd; +use libc::c_char; +use std::path::Path; +use libloading::Library; +use rcmd::*; +/* +#define ENABLED 1 +#define DISABLED 2 +#define SPECIAL 4 + +#define AFLAG 0x01 +#define DFLAG 0x02 +#define FFLAG 0x04 +#define NFLAG 0x08 +#define PFLAG 0x10 +#define SFLAG 0x20 + */ +pub const ENABLED: i32 = 1; +pub const DISABLED: i32 = 2; +pub const SPECIAL: i32 = 4; + +pub const AFLAG: i32 = 0x01; +pub const DFLAG: i32 = 0x02; +pub const FFLAG: i32 = 0x04; +pub const NFLAG: i32 = 0x08; +pub const PFLAG: i32 = 0x10; +pub const SFLAG: i32 = 0x20; + +pub const EX_USAGE: i32 = 258; +pub const EXECUTION_FAILURE:i32 = 1; + +// Flags describing various things about a builtin. +//#define BUILTIN_ENABLED 0x01 /* This builtin is enabled. */ +//#define BUILTIN_DELETED 0x02 /* This has been deleted with enable -d. */ +//#define STATIC_BUILTIN 0x04 /* This builtin is not dynamically loaded. */ +//#define SPECIAL_BUILTIN 0x08 /* This is a Posix `special' builtin. */ +//#define ASSIGNMENT_BUILTIN 0x10 /* This builtin takes assignment statements. */ +//#define POSIX_BUILTIN 0x20 /* This builtins is special in the Posix command search order. */ +//#define LOCALVAR_BUILTIN 0x40 /* This builtin creates local variables */ +//#define REQUIRES_BUILTIN 0x80 /* This builtin requires other files. */ +//#define BASE_INDENT 4 + +pub const BUILTIN_ENABLED :i32 = 0x01; +pub const BUILTIN_DELETED :i32 = 0x02; +pub const STATIC_BUILTIN :i32 = 0x04; +pub const SPECIAL_BUILTIN :i32 = 0x08; +pub const ASSIGNMENT_BUILTIN :i32 = 0x10; +pub const POSIX_BUILTIN :i32 = 0x20; +pub const LOCALVAR_BUILTIN :i32 = 0x40; +pub const REQUIRES_BUILTIN :i32 = 0x80; + +/* +#define EXECUTION_FAILURE 1 +#define EXECUTION_SUCCESS 0 + */ +//pub const EXECUTION_FAILURE :i32 = 1; +pub const EXECUTION_SUCCESS :i32 = 0; + +/* The MODE argument to `dlopen' contains one of the following: */ +// #define RTLD_LAZY 0x00001 /* Lazy function call binding. */ +// #define RTLD_NOW 0x00002 /* Immediate function call binding. */ +// #define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */ +// #define RTLD_NOLOAD 0x00004 /* Do not load the object. */ +// #define RTLD_DEEPBIND 0x00008 /* Use deep binding. */ + +/* If the following bit is set in the MODE argument to `dlopen', + the symbols of the loaded object and its dependencies are made + visible as if the object were linked directly into the program. */ +// #define RTLD_GLOBAL 0x00100 + +pub const RTLD_LAZY :i32 = 0x00001; +pub const RTLD_NOW :i32 = 0x00002; +pub const RTLD_BINDING_MASK :i32 = 0x3; +pub const RTLD_NOLOAD :i32 = 0x00004; +pub const RTLD_DEEPBIND :i32 = 0x00008; +pub const RTLD_GLOBAL :i32 = 0x00100; + +pub const FS_NODIRS :i32 = 0x20; +pub const FS_EXEC_PREFERRED :i32 = 0x4; + +extern "C" { + fn printf(_: *const libc::c_char, _: ...) -> libc::c_int; + fn strlen(_: *const libc::c_char) -> libc::c_ulong; + fn strcpy(_: *mut libc::c_char, _: *const libc::c_char) -> *mut libc::c_char; + fn free(__ptr: *mut libc::c_void); + fn dcgettext( + __domainname: *const libc::c_char, + __msgid: *const libc::c_char, + __category: libc::c_int, + ) -> *mut libc::c_char; + fn xmalloc(_: size_t) -> *mut libc::c_void; + fn xrealloc(_: *mut libc::c_void, _: size_t) -> *mut libc::c_void; + fn absolute_program(_: *const libc::c_char) -> libc::c_int; + fn printable_filename(_: *mut libc::c_char, _: libc::c_int) -> *mut libc::c_char; + fn get_string_value(_: *const libc::c_char) -> *mut libc::c_char; + static mut num_shell_builtins: libc::c_int; + static mut static_shell_builtins: [builtin; 0]; + static mut shell_builtins: *mut builtin; + static mut restricted: libc::c_int; + fn builtin_error(_: *const libc::c_char, _: ...); + fn builtin_warning(_: *const libc::c_char, _: ...); + fn builtin_usage(); + fn sh_restricted(_: *mut libc::c_char); + fn sh_notbuiltin(_: *mut libc::c_char); + fn builtin_address_internal(_: *mut libc::c_char, _: libc::c_int) -> *mut builtin; + fn initialize_shell_builtins(); + fn builtin_help(); + static mut list_optarg: *mut libc::c_char; + static mut loptend: *mut WORD_LIST; + fn internal_getopt(_: *const WORD_LIST, _: *const libc::c_char) -> i32; + fn reset_internal_getopt(); + fn find_in_path( + _: *const libc::c_char, + _: *mut libc::c_char, + _: libc::c_int, + ) -> *mut libc::c_char; + static mut it_builtins: ITEMLIST; + static mut it_disabled: ITEMLIST; + static mut it_enabled: ITEMLIST; + fn set_itemlist_dirty(_: *mut ITEMLIST); + fn dlopen(__file: *const libc::c_char, __mode: libc::c_int) -> *mut libc::c_void; + fn dlclose(__handle: *mut libc::c_void) -> libc::c_int; + fn dlsym( + __handle: *mut libc::c_void, + __name: *const libc::c_char, + ) -> *mut libc::c_void; + fn dlerror() -> *mut libc::c_char; +} +pub type size_t = libc::c_ulong; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct word_desc { + pub word: *mut libc::c_char, + pub flags: libc::c_int, +} +pub type WORD_DESC = word_desc; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; +pub type sh_load_func_t = unsafe extern "C" fn(*mut libc::c_char) -> libc::c_int; +pub type sh_unload_func_t = unsafe extern "C" fn(*mut libc::c_char) -> (); +pub type sh_builtin_func_t = unsafe extern "C" fn(*mut WORD_LIST) -> libc::c_int; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _list_of_strings { + pub list: *mut *mut libc::c_char, + pub list_size: libc::c_int, + pub list_len: libc::c_int, +} +pub type STRINGLIST = _list_of_strings; +#[derive(Copy, Clone)] +#[repr(C)] +pub struct builtin { + pub name: *mut libc::c_char, + pub function: Option::, + pub flags: libc::c_int, + pub long_doc: *const *mut libc::c_char, + pub short_doc: *const libc::c_char, + pub handle: *mut libc::c_char, +} +#[derive(Copy, Clone)] +#[repr(C)] +pub struct _list_of_items { + pub flags: libc::c_int, + pub list_getter: Option:: libc::c_int>, + pub slist: *mut STRINGLIST, + pub genlist: *mut STRINGLIST, + pub genindex: libc::c_int, +} +pub type ITEMLIST = _list_of_items; +#[no_mangle] +pub unsafe extern "C" fn r_enable_builtin(mut list: *mut WORD_LIST) -> i32 { + let mut result: i32 = 0; + let mut flags: i32 = 0; + let mut opt: i32 = 0; + let mut filter: i32 = 0; + let mut filename: *mut libc::c_char = 0 as *mut libc::c_char; + reset_internal_getopt(); + let adnpsf = CString::new("adnpsf").expect("CString::new failed");; + loop { + opt = internal_getopt(list, adnpsf.as_ptr() ); + if !(opt != -1) { + break; + } + let opt_char = opt as u8 as char; + match opt_char { + 'a' => { + flags |= AFLAG; + } + 'n' => { + flags |= NFLAG; + } + 'p' => { + flags |= PFLAG; + } + 's' => { + flags |= SFLAG; + } + 'f' => { + flags |= FFLAG; + filename = list_optarg; + } + 'd' => { + flags |= DFLAG; + } + _ => { + if opt ==-99 { + builtin_help(); + return EX_USAGE; + } + builtin_usage(); + return EX_USAGE; + } + } + } + list = loptend; + // 如果是严格模式,就直接返回EXECUTION_FAILURE,命令结束。 + if restricted != 0 && flags & (FFLAG|DFLAG) != 0 { + sh_restricted (0 as *mut c_char); + return EXECUTION_FAILURE; + } + + // 配置filter,通过flag和PFLAG,后者表示打印, + // 如果命令传入不带选项,或者带-P + // 则打印enable和disable的集合; + // 否则判断是否带-N + // 带则打印DISABLED的,不带—N则打印ENABLED的 + if list.is_null() || flags & PFLAG != 0 { + filter = if flags & AFLAG != 0 { ENABLED | DISABLED } + else if flags & NFLAG != 0 { + DISABLED + } else { + ENABLED + }; + + if flags & SFLAG != 0 { + filter |= SPECIAL; + } + + list_some_builtins(filter); + + } else if flags & FFLAG != 0 { + // 如果不带-N或者参数不为空,那么判断-F.(bash源文件中判断HAVE_DLSYM,HAVE_DLOPEN两个宏存在) + // -F后面需要加文件名,载入so,作为内建命令 + + //判断是ENABLED还是DISABLED + filter = if flags & NFLAG != 0 { + DISABLED + } else { + ENABLED + }; + + // 判断是否设置SPECIAL标志位 + if flags & SFLAG != 0 { + filter |= SPECIAL; + } + + //载入so + result = dyn_load_builtin(list, filter, filename); + + // 设置完成,bash源代码中判断PROGRAMMABLE_COMPLETION + set_itemlist_dirty(&mut it_builtins); + + } else if flags & DFLAG != 0 { + // 否则判断-D,-D含义是删除以 -f 选项加载的内建 + while !list.is_null() { + opt = dyn_unload_builtin((*(*list).word).word); + if opt == EXECUTION_FAILURE { + result = EXECUTION_FAILURE; + } + list = (*list).next; + } + set_itemlist_dirty(&mut it_builtins); + + } else { + // 不带-N -F -D,且选项不为空的其他 + while !list.is_null() { + opt = enable_shell_command((*(*list).word).word, flags & NFLAG); + if opt == EXECUTION_FAILURE { + sh_notbuiltin((*(*list).word).word); + result = EXECUTION_FAILURE; + } + list = (*list).next; + } + } + return result; +} + +//仅仅-p的时候会调用,打印,filter决定是enable,disable +unsafe extern "C" fn list_some_builtins(mut filter: libc::c_int) { + let mut i: i32 = 0; + + while i < num_shell_builtins { + let tmpIter =*shell_builtins.offset(i as isize); + if !(tmpIter.function.is_none()||tmpIter.flags & BUILTIN_DELETED != 0) + { + if !(filter & SPECIAL != 0 + && (*shell_builtins.offset(i as isize)).flags & SPECIAL_BUILTIN + == 0) + { + if filter & ENABLED != 0 + && (*shell_builtins.offset(i as isize)).flags & BUILTIN_ENABLED + != 0 + { + let name= unsafe{CStr::from_ptr((*shell_builtins.offset(i as isize)).name)}; + println!("==enable {}", name.to_str().expect("name cannot trans")); + } else if filter & DISABLED != 0 + && (*shell_builtins.offset(i as isize)).flags + & BUILTIN_ENABLED == 0 as libc::c_int + { + let name= unsafe{CStr::from_ptr((*shell_builtins.offset(i as isize)).name)}; + println!("!!enable -n {}", name.to_str().expect("name cannot trans")); + + } + } + } + i += 1; + } +} +unsafe extern "C" fn enable_shell_command( + mut name: *mut libc::c_char, + mut disable_p: libc::c_int, +) -> libc::c_int { + let mut b: *mut builtin = 0 as *mut builtin; + b = builtin_address_internal(name, 1); + if b.is_null() { + return EXECUTION_FAILURE; + } + if disable_p != 0 { + (*b).flags &= !(BUILTIN_ENABLED); + if !set_cmd_enable(CStr::from_ptr(name).to_string_lossy().into_owned(), false) { + insert_empty_cmd(CStr::from_ptr(name).to_string_lossy().into_owned()); + set_cmd_enable(CStr::from_ptr(name).to_string_lossy().into_owned(), false); + get_cmd_enable(CStr::from_ptr(name).to_string_lossy().into_owned()); + } + } else if restricted != 0 && (*b).flags & BUILTIN_ENABLED == 0 { + sh_restricted(0 as *mut libc::c_void as *mut libc::c_char); + return EXECUTION_FAILURE; + } else { + (*b).flags |= BUILTIN_ENABLED; + if !set_cmd_enable(CStr::from_ptr(name).to_string_lossy().into_owned(), true) { + insert_empty_cmd(CStr::from_ptr(name).to_string_lossy().into_owned()); + set_cmd_enable(CStr::from_ptr(name).to_string_lossy().into_owned(), true); + } + } + set_itemlist_dirty(&mut it_enabled); + set_itemlist_dirty(&mut it_disabled); + return EXECUTION_SUCCESS; +} +unsafe extern "C" fn dyn_load_builtin( + mut list: *mut WORD_LIST, + mut flags: libc::c_int, + mut filename: *mut libc::c_char, +) -> libc::c_int { + let mut l: *mut WORD_LIST = 0 as *mut WORD_LIST; + let mut handle: *mut libc::c_void = 0 as *mut libc::c_void; + let mut total: libc::c_int = 0; + let mut size: libc::c_int = 0; + let mut new: libc::c_int = 0; + let mut replaced: libc::c_int = 0; + let mut r: libc::c_int = 0; + let mut struct_name: *mut libc::c_char = 0 as *mut libc::c_char; + let mut name: *mut libc::c_char = 0 as *mut libc::c_char; + let mut funcname: *mut libc::c_char = 0 as *mut libc::c_char; + let mut loadfunc: Option:: = None; + let mut new_builtins: *mut *mut builtin = 0 as *mut *mut builtin; + let mut b: *mut builtin = 0 as *mut builtin; + let mut new_shell_builtins: *mut builtin = 0 as *mut builtin; + let mut old_builtin: *mut builtin = 0 as *mut builtin; + let mut loadables_path: *mut libc::c_char = 0 as *mut libc::c_char; + let mut load_path: *mut libc::c_char = 0 as *mut libc::c_char; + if list.is_null() { + return 1 as libc::c_int; + } + handle = 0 as *mut libc::c_void; + if absolute_program(filename) == 0 as libc::c_int { + loadables_path = get_string_value( + b"BASH_LOADABLES_PATH\0" as *const u8 as *const libc::c_char, + ); + if !loadables_path.is_null() { + load_path = find_in_path( + filename, + loadables_path, + 0x20 as libc::c_int | 0x4 as libc::c_int, + ); + if !load_path.is_null() { + handle = dlopen(load_path, 0x1 as libc::c_int); + free(load_path as *mut libc::c_void); + } + } + } + if handle.is_null() { + handle = dlopen(filename, 0x1 as libc::c_int); + } + if handle.is_null() { + name = printable_filename(filename, 0 as libc::c_int); + builtin_error( + dcgettext( + 0 as *const libc::c_char, + b"cannot open shared object %s: %s\0" as *const u8 + as *const libc::c_char, + 5 as libc::c_int, + ), + name, + dlerror(), + ); + if name != filename { + free(name as *mut libc::c_void); + } + return 1 as libc::c_int; + } + new = 0 as libc::c_int; + l = list; + while !l.is_null() { + l = (*l).next; + new += 1; + } + new_builtins = xmalloc( + (new as libc::c_ulong) + .wrapping_mul(::std::mem::size_of::<*mut builtin>() as libc::c_ulong), + ) as *mut *mut builtin; + let mut current_block_57: u64; + new = 0 as libc::c_int; + replaced = new; + while !list.is_null() { + name = (*(*list).word).word; + size = strlen(name) as libc::c_int; + struct_name = xmalloc((size + 8 as libc::c_int) as size_t) as *mut libc::c_char; + strcpy(struct_name, name); + strcpy( + struct_name.offset(size as isize), + b"_struct\0" as *const u8 as *const libc::c_char, + ); + old_builtin = builtin_address_internal(name, 1 as libc::c_int); + b = dlsym(handle, struct_name) as *mut builtin; + if b.is_null() { + name = printable_filename(filename, 0 as libc::c_int); + builtin_error( + dcgettext( + 0 as *const libc::c_char, + b"cannot find %s in shared object %s: %s\0" as *const u8 + as *const libc::c_char, + 5 as libc::c_int, + ), + struct_name, + name, + dlerror(), + ); + if name != filename { + free(name as *mut libc::c_void); + } + free(struct_name as *mut libc::c_void); + } else { + funcname = xrealloc( + struct_name as *mut libc::c_void, + (size as libc::c_ulong) + .wrapping_add( + ::std::mem::size_of::<[libc::c_char; 14]>() as libc::c_ulong, + ) + .wrapping_add(1 as libc::c_int as libc::c_ulong), + ) as *mut libc::c_char; + strcpy(funcname, name); + strcpy( + funcname.offset(size as isize), + b"_builtin_load\0" as *const u8 as *const libc::c_char, + ); + loadfunc = ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(dlsym(handle, funcname)); + if loadfunc.is_some() { + if !old_builtin.is_null() + && (*old_builtin).flags & 0x4 as libc::c_int == 0 as libc::c_int + { + builtin_warning( + dcgettext( + 0 as *const libc::c_char, + b"%s: dynamic builtin already loaded\0" as *const u8 + as *const libc::c_char, + 5 as libc::c_int, + ), + name, + ); + } + r = (Some(loadfunc.expect("non-null function pointer"))) + .expect("non-null function pointer")(name); + if r == 0 as libc::c_int { + builtin_error( + dcgettext( + 0 as *const libc::c_char, + b"load function for %s returns failure (%d): not loaded\0" + as *const u8 as *const libc::c_char, + 5 as libc::c_int, + ), + name, + r, + ); + free(funcname as *mut libc::c_void); + current_block_57 = 15345278821338558188; + } else { + current_block_57 = 7990025728955927862; + } + } else { + current_block_57 = 7990025728955927862; + } + match current_block_57 { + 15345278821338558188 => {} + _ => { + free(funcname as *mut libc::c_void); + (*b).flags &= !(0x4 as libc::c_int); + if flags & 4 as libc::c_int != 0 { + (*b).flags |= 0x8 as libc::c_int; + } + let ref mut fresh0 = (*b).handle; + *fresh0 = handle as *mut libc::c_char; + if !old_builtin.is_null() { + replaced += 1; + libc::memcpy( + old_builtin as *mut libc::c_char as *mut libc::c_void, + b as *mut libc::c_char as *const libc::c_void, + ::std::mem::size_of::() as libc::c_ulong + as libc::size_t, + ); + } else { + let fresh1 = new; + new = new + 1; + let ref mut fresh2 = *new_builtins.offset(fresh1 as isize); + *fresh2 = b; + } + } + } + } + list = (*list).next; + } + if replaced == 0 as libc::c_int && new == 0 as libc::c_int { + free(new_builtins as *mut libc::c_void); + dlclose(handle); + return 1 as libc::c_int; + } + if new != 0 { + total = num_shell_builtins + new; + size = ((total + 1 as libc::c_int) as libc::c_ulong) + .wrapping_mul(::std::mem::size_of::() as libc::c_ulong) + as libc::c_int; + new_shell_builtins = xmalloc(size as size_t) as *mut builtin; + libc::memcpy( + new_shell_builtins as *mut libc::c_char as *mut libc::c_void, + shell_builtins as *mut libc::c_char as *const libc::c_void, + (num_shell_builtins as libc::c_ulong) + .wrapping_mul(::std::mem::size_of::() as libc::c_ulong) + as libc::size_t, + ); + replaced = 0 as libc::c_int; + while replaced < new { + libc::memcpy( + &mut *new_shell_builtins.offset((num_shell_builtins + replaced) as isize) + as *mut builtin as *mut libc::c_char as *mut libc::c_void, + *new_builtins.offset(replaced as isize) as *mut libc::c_char + as *const libc::c_void, + ::std::mem::size_of::() as libc::c_ulong as libc::size_t, + ); + replaced += 1; + } + let ref mut fresh3 = (*new_shell_builtins.offset(total as isize)).name; + *fresh3 = 0 as *mut libc::c_char; + let ref mut fresh4 = (*new_shell_builtins.offset(total as isize)).function; + *fresh4 = None; + (*new_shell_builtins.offset(total as isize)).flags = 0 as libc::c_int; + if shell_builtins != static_shell_builtins.as_mut_ptr() { + free(shell_builtins as *mut libc::c_void); + } + shell_builtins = new_shell_builtins; + num_shell_builtins = total; + initialize_shell_builtins(); + } + free(new_builtins as *mut libc::c_void); + return 0 as libc::c_int; +} +unsafe extern "C" fn delete_builtin(mut b: *mut builtin) { + let mut ind: libc::c_int = 0; + let mut size: libc::c_int = 0; + let mut new_shell_builtins: *mut builtin = 0 as *mut builtin; + ind = b.offset_from(shell_builtins) as libc::c_long as libc::c_int; + size = (num_shell_builtins as libc::c_ulong) + .wrapping_mul(::std::mem::size_of::() as libc::c_ulong) as libc::c_int; + new_shell_builtins = xmalloc(size as size_t) as *mut builtin; + if ind != 0 { + libc::memcpy( + new_shell_builtins as *mut libc::c_char as *mut libc::c_void, + shell_builtins as *mut libc::c_char as *const libc::c_void, + (ind as libc::c_ulong) + .wrapping_mul(::std::mem::size_of::() as libc::c_ulong) + as libc::size_t, + ); + } + libc::memcpy( + &mut *new_shell_builtins.offset(ind as isize) as *mut builtin + as *mut libc::c_char as *mut libc::c_void, + &mut *shell_builtins.offset((ind + 1 as libc::c_int) as isize) as *mut builtin + as *mut libc::c_char as *const libc::c_void, + ((num_shell_builtins - ind) as libc::c_ulong) + .wrapping_mul(::std::mem::size_of::() as libc::c_ulong) + as libc::size_t, + ); + if shell_builtins != static_shell_builtins.as_mut_ptr() { + free(shell_builtins as *mut libc::c_void); + } + num_shell_builtins -= 1; + shell_builtins = new_shell_builtins; +} +unsafe extern "C" fn local_dlclose(mut handle: *mut libc::c_void) -> libc::c_int { + return dlclose(handle); +} +unsafe extern "C" fn dyn_unload_builtin(mut name: *mut libc::c_char) -> libc::c_int { + let mut b: *mut builtin = 0 as *mut builtin; + let mut handle: *mut libc::c_void = 0 as *mut libc::c_void; + let mut funcname: *mut libc::c_char = 0 as *mut libc::c_char; + let mut unloadfunc: Option:: = None; + let mut ref_0: libc::c_int = 0; + let mut i: libc::c_int = 0; + let mut size: libc::c_int = 0; + b = builtin_address_internal(name, 1 as libc::c_int); + if b.is_null() { + sh_notbuiltin(name); + return 1 as libc::c_int; + } + if (*b).flags & 0x4 as libc::c_int != 0 { + builtin_error( + dcgettext( + 0 as *const libc::c_char, + b"%s: not dynamically loaded\0" as *const u8 as *const libc::c_char, + 5 as libc::c_int, + ), + name, + ); + return 1 as libc::c_int; + } + handle = (*b).handle as *mut libc::c_void; + i = 0 as libc::c_int; + ref_0 = i; + while i < num_shell_builtins { + if (*shell_builtins.offset(i as isize)).handle == (*b).handle { + ref_0 += 1; + } + i += 1; + } + size = strlen(name) as libc::c_int; + funcname = xmalloc( + (size as libc::c_ulong) + .wrapping_add(::std::mem::size_of::<[libc::c_char; 16]>() as libc::c_ulong) + .wrapping_add(1 as libc::c_int as libc::c_ulong), + ) as *mut libc::c_char; + strcpy(funcname, name); + strcpy( + funcname.offset(size as isize), + b"_builtin_unload\0" as *const u8 as *const libc::c_char, + ); + unloadfunc = ::std::mem::transmute::< + *mut libc::c_void, + Option::, + >(dlsym(handle, funcname)); + if unloadfunc.is_some() { + (Some(unloadfunc.expect("non-null function pointer"))) + .expect("no-null function pointer")(name); + } + free(funcname as *mut libc::c_void); + if ref_0 == 1 as libc::c_int && local_dlclose(handle) != 0 as libc::c_int { + builtin_error( + dcgettext( + 0 as *const libc::c_char, + b"%s: cannot delete: %s\0" as *const u8 as *const libc::c_char, + 5 as libc::c_int, + ), + name, + dlerror(), + ); + return 1 as libc::c_int; + } + delete_builtin(b); + return 0 as libc::c_int; +} diff --git a/bash-5.1/builtins_rust/eval/Cargo.toml b/bash-5.1/builtins_rust/eval/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..92934d245aa12b393148139e8352fd212d4b0dd7 --- /dev/null +++ b/bash-5.1/builtins_rust/eval/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "reval" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" + +[lib] +crate-type = ["staticlib"] +name = "reval" diff --git a/bash-5.1/builtins_rust/eval/src/lib.rs b/bash-5.1/builtins_rust/eval/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..8f2ba18733022767b9f5da47c38be9a94b4e88ae --- /dev/null +++ b/bash-5.1/builtins_rust/eval/src/lib.rs @@ -0,0 +1,84 @@ +extern crate libc; +use libc::{c_char,c_int}; +use std::ffi::{CStr, CString}; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! SEVAL_NOHIST { + () => {0x004} +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => { + 0 + } +} + + +extern "C" { + static loptend:*mut WORD_LIST; + + fn no_options(list:*mut WORD_LIST)->i32; + fn evalstring(string:*mut c_char,from_file:*const c_char,flag:i32)->i32; + fn string_list(list:*mut WORD_LIST)->*mut c_char; +} + +#[no_mangle] +pub extern "C" fn r_eval_builtin(mut list:*mut WORD_LIST)->i32{ + println!("r_eval_builtin"); + + unsafe{ + if no_options(list) != 0{ + return EX_USAGE!(); + } + + list = loptend; + + if !list.is_null() { + return evalstring(string_list(list),CString::new("eval").unwrap().as_ptr(),SEVAL_NOHIST!()); + } + else{ + return EXECUTION_SUCCESS!(); + } + } + +} + + + + + + + + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/exec/Cargo.toml b/bash-5.1/builtins_rust/exec/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..23f0b7e540cb5da729fe9c11a08d325dcefd11dc --- /dev/null +++ b/bash-5.1/builtins_rust/exec/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "rexec" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +nix = "0.24.1" + +[lib] +crate-type = ["staticlib"] +name = "rexec" diff --git a/bash-5.1/builtins_rust/exec/src/lib.rs b/bash-5.1/builtins_rust/exec/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..4d3e2074015ec3c8ace4956a6ec14d0d2b2675a7 --- /dev/null +++ b/bash-5.1/builtins_rust/exec/src/lib.rs @@ -0,0 +1,420 @@ +extern crate libc; +extern crate nix; + +use libc::{c_char,c_int, strlen, strcpy, size_t, c_void, free}; +use std::ffi::{CString,CStr}; +use nix::errno::errno; + + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct WORD_DESC{ + pub word:*mut c_char, + pub flags:c_int, +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct WORD_LIST{ + pub next:*mut WORD_LIST, + pub word:*mut WORD_DESC, +} + +#[repr (C)] +struct redirect{ + next:*mut redirect, + redirector:REDIRECTEE, + rflags:i32, + flags:i32, + insturction:r_instruction, + redirectee:REDIRECTEE, + here_doc_eof:*mut c_char, +} +type REDIRECT = redirect; + +#[repr (C)] +union REDIRECTEE { + dest:i32, + filename:*mut WORD_DESC, +} + +#[repr(i8)] //i8 or C ??????? +enum r_instruction { + r_output_direction, + r_input_direction, + r_inputa_direction, + + r_appending_to, + r_reading_until, + r_reading_string, + + r_duplicating_input, + r_duplicating_output, + r_deblank_reading_until, + + r_close_this, + r_err_and_out, + r_input_output, + r_output_force, + + r_duplicating_input_word, + r_duplicating_output_word, + + r_move_input, + r_move_output, + r_move_input_word, + r_move_output_word, + + r_append_err_and_out +} + + + +//macro +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {0} +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => { 1 }; +} + +#[macro_export] +macro_rules! EX_USAGE { + () => { 258 } +} + +#[macro_export] +macro_rules! EX_NOEXEC { + () => { 126 } +} + +#[macro_export] +macro_rules! EX_NOTFOUND { + () => { 127 } +} + +#[macro_export] +macro_rules! SUBSHELL_PAREN { + () => { 0x02 } +} + + +#[macro_export] +macro_rules! savestring { + ($x:expr) => { + strcpy(xmalloc(1 + strlen($x)) as *mut c_char,$x) as *mut c_char + } +} + +#[macro_export] +macro_rules! FREE { + ($s:expr) => { + if ($s) != std::ptr::null_mut(){ + free($s); + } + } +} + + +extern "C" { + // static errno:i32; + static mut exec_argv0:*mut c_char; + static list_optarg:*mut c_char; + static loptend:*mut WORD_LIST; + static mut redirection_undo_list:*mut REDIRECT; + static restricted:i32; + static comsub_ignore_return:i32; + static export_env:*mut *mut c_char; + static interactive_shell:i32; + static subshell_environment:i32; + static job_control:i32; + static interactive:i32; + static default_buffered_input:i32; + // static no_exit_on_failed_exec:i32; + + fn xmalloc(n:size_t)->*mut c_void; + fn reset_internal_getopt(); + fn internal_getopt(list:*mut WORD_LIST,opts:*mut c_char)->i32; + fn builtin_usage(); + fn dispose_redirects(list:*mut REDIRECT); + fn sh_restricted(s:*mut c_char); + fn strvec_from_word_list(list:*mut WORD_LIST,alloc:i32,starting_index:i32,ip:*mut i32)->*mut *mut c_char; + fn absolute_program(string:*const c_char)->i32; + fn search_for_command(pathname:*const c_char,flags:i32)->*mut c_char; + fn file_isdir(f:*const c_char)->i32; + fn builtin_error(format:*const c_char,...); + fn strerror(e:i32)->*mut c_char; + fn sh_notfound(s:*mut c_char); + fn full_pathname(file:*mut c_char)->*mut c_char; + fn adjust_shell_level(change:i32); + fn strvec_create(n:i32)->*mut *mut c_char; + fn maybe_make_export_env(); + fn maybe_save_shell_history()->i32; + fn restore_original_signals(); + fn end_job_control(); + fn default_tty_job_signals(); + fn sync_buffered_stream(bfd:i32)->i32; + fn shell_execve(command:*mut c_char,args:*mut *mut c_char,env:*mut *mut c_char)->i32; + fn executable_file(file:*const c_char)->i32; + fn file_error(filename:*mut c_char); + fn exit_shell(s:i32); + fn strvec_dispose(array:*mut *mut c_char); + fn initialize_traps(); + fn initialize_signals(reinit:i32); + fn restart_job_control(); +} + + +pub static no_exit_on_failed_exec:i32 = 0; + + +/* If the user wants this to look like a login shell, then + prepend a `-' onto NAME and return the new name. */ +#[no_mangle] +extern "C" fn r_mkdashname(name:*mut c_char)->*mut c_char{ + let mut ret:*mut c_char; + + unsafe{ + ret = xmalloc(2 + strlen(name)) as *mut c_char; + *ret.offset(0) = '-' as i8; + strcpy(ret.offset(1), name); + return ret; + } + +} + + +#[no_mangle] +pub extern "C" fn r_exec_builtin(mut list:*mut WORD_LIST)->i32{ + let mut exit_value = EXECUTION_FAILURE!(); + let mut cleanenv:i32 = 0; + let mut login:i32 = 0; + let mut opt:i32; + let mut orig_job_control:i32 = 0; + let mut argv0:*mut c_char = std::ptr::null_mut() as *mut c_char; + let mut command:*mut c_char; + let mut args:*mut *mut c_char; + let mut env:*mut *mut c_char; + let mut newname:*mut c_char; + let mut com2:*mut c_char; + + println!("r_exec_builtin"); + + unsafe{ + loop{ + + exec_argv0 = std::ptr::null_mut() as *mut c_char; + + reset_internal_getopt(); + + let c_str = CString::new("cla:").unwrap(); + let c_ptr = c_str.as_ptr() as *mut c_char; + opt = internal_getopt(list,c_ptr); + while opt != -1{ + let optu8 = opt as u8; + let opt_char = char::from(optu8); + match opt_char{ + 'c' => cleanenv = 1, + 'l' => login = 1, + 'a' => argv0 = list_optarg, + _ => { + builtin_usage(); + return EX_USAGE!(); + } + } + + opt = internal_getopt(list,c_ptr); + } + + list = loptend; + + /* First, let the redirections remain. */ + dispose_redirects(redirection_undo_list); + redirection_undo_list = std::ptr::null_mut() as *mut REDIRECT; + + if list.is_null(){ + return EXECUTION_SUCCESS!(); + } + + if restricted != 0{ //限制性shell + sh_restricted(std::ptr::null_mut() as *mut c_char); + return EXECUTION_FAILURE!(); + } + + args = strvec_from_word_list(list,1,0,0 as *mut c_int); //这个指针这样写不清楚可不可以 + env = 0 as *mut *mut c_char; + // println!("11111"); + + /* A command with a slash anywhere in its name is not looked up in $PATH. */ + if absolute_program(*args.offset(0)) != 0{ //命令给的绝对路径,或者执行脚本 + command = (*args).offset(0); + // println!("command:{}",CStr::from_ptr(command).to_str().unwrap()); + } + else { //exec后直接给命令 + command = search_for_command(*args.offset(0),1); + println!("command:{}",CStr::from_ptr(command).to_str().unwrap()); + } + + if command.is_null(){ + if file_isdir(*args.offset(0)) != 0{ + let c_str = CString::new("%s: cannot execute: %s").unwrap(); + let c_ptr = c_str.as_ptr(); + builtin_error(c_ptr,*args.offset(0),strerror(errno())); + exit_value = EX_NOEXEC!(); + } + else{ + sh_notfound(*args.offset(0)); + exit_value = EX_NOTFOUND!(); + } + //goto failed_exec; + break; + } + + com2 = full_pathname(command); + if !com2.is_null(){ + // println!("command:{}",CStr::from_ptr(command).to_str().unwrap()); + // println!("args[0]:{}",CStr::from_ptr(*args.offset(0)).to_str().unwrap()); + if command != *args.offset(0){ + free(command as *mut c_void); + } + // println!("command:{}",CStr::from_ptr(command).to_str().unwrap()); + println!("com2:{}",CStr::from_ptr(com2).to_str().unwrap()); + command = com2; + } + + if !argv0.is_null(){ //exec有-a参数 + free(*args.offset(0) as *mut c_void); + if login != 0{ + *args.offset(0) = r_mkdashname(argv0); + println!("args[0]:{}",CStr::from_ptr(*args.offset(0)).to_str().unwrap()); + } + else { + *args.offset(0) = savestring!(argv0); + println!("args[0]:{}",CStr::from_ptr(*args.offset(0)).to_str().unwrap()); + println!("args[1]:{}",CStr::from_ptr(*args.offset(1)).to_str().unwrap()); + println!("args[2]:{}",CStr::from_ptr(*args.offset(2)).to_str().unwrap()); + } + exec_argv0 = savestring!(*args.offset(0)); + println!("exec_argv0:{}",CStr::from_ptr(exec_argv0).to_str().unwrap()); + } + else if login != 0{ + newname = r_mkdashname(*args.offset(0)); + free(*args.offset(0) as *mut c_void); + *args.offset(0) = newname; + } + + /* Decrement SHLVL by 1 so a new shell started here has the same value, + preserving the appearance. After we do that, we need to change the + exported environment to include the new value. If we've already forked + and are in a subshell, we don't want to decrement the shell level, + since we are `increasing' the level */ + + if cleanenv == 0 && (subshell_environment & SUBSHELL_PAREN!() == 0){ + adjust_shell_level(-1); + } + + if cleanenv != 0{ + env = strvec_create(1); + *env.offset(0) = 0 as *mut c_char; + } + else{ + maybe_make_export_env(); + env = export_env; + } + + if interactive_shell !=0 && subshell_environment == 0{ + maybe_save_shell_history(); + } + + restore_original_signals(); + + orig_job_control = job_control; + if subshell_environment == 0{ + end_job_control(); + } + if interactive != 0 || job_control != 0{ + default_tty_job_signals(); + } + + if default_buffered_input >= 0{ + sync_buffered_stream(default_buffered_input); + } + + exit_value = shell_execve(command,args,env); + + /* We have to set this to NULL because shell_execve has called realloc() + to stuff more items at the front of the array, which may have caused + the memory to be freed by realloc(). We don't want to free it twice. */ + + args = std::ptr::null_mut() as *mut *mut c_char; + + if cleanenv == 0 { + adjust_shell_level(1); + } + + if exit_value == EX_NOTFOUND!(){ + //goto failed_exec; + break; + } + else if executable_file(command) == 0{ + let c_str = CString::new("%s: cannot execute: %s").unwrap(); + let c_ptr = c_str.as_ptr(); + builtin_error(c_ptr,command,strerror(errno())); + exit_value = EX_NOEXEC!(); + } + else{ + file_error(command); + } + + //跳出loop循环,只执行一次loop + break; + } + + + //fialed_exec + FREE!(command as *mut c_void); + + if subshell_environment != 0 || interactive == 0 && no_exit_on_failed_exec ==0{ + exit_shell(exit_value); + } + + if !args.is_null(){ + strvec_dispose(args); + } + + if !env.is_null() && env != export_env{ + strvec_dispose(env); + } + + initialize_traps(); + initialize_signals(1); + + if orig_job_control != 0{ + restart_job_control(); + } + + return exit_value; + } +} + + + + + + + + + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/exit/Cargo.toml b/bash-5.1/builtins_rust/exit/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..5b879602bf0c3f371611361c3731737435fa0303 --- /dev/null +++ b/bash-5.1/builtins_rust/exit/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "exit" +version = "0.1.0" +edition = "2021" +#build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +nix = "0.23.0" +rjobs = {path="../jobs"} + + +[lib] +crate-type = ["staticlib"] +name = "rexit" diff --git a/bash-5.1/builtins_rust/exit/src/lib.rs b/bash-5.1/builtins_rust/exit/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..63574ef66f334bdc05437cb8b38e753e1babdeb3 --- /dev/null +++ b/bash-5.1/builtins_rust/exit/src/lib.rs @@ -0,0 +1,275 @@ +extern crate libc; +extern crate rjobs; +extern crate nix; + +use libc::c_char; +use std::ffi::CString; + +use rjobs::{PROCESS, COMMAND, r_jobs_builtin, JLIST_STANDARD, WORD_LIST}; + +#[repr(C)] +pub struct JOB { + wd: *mut c_char, + pipe: *mut PROCESS, + pgrp:i32, + state:JOB_STATE, + flags:i32, + deferred:*mut COMMAND, + j_cleanup:*mut fn(), + cleanarg:* mut fn() +} + +#[repr(C)] +pub struct jobstats { + /* limits */ + c_childmax:libc::c_long, + /* child process statistics */ + c_living:libc::c_int, /* running or stopped child processes */ + c_reaped:libc::c_int, /* exited child processes still in jobs list */ + c_injobs:libc::c_int, /* total number of child processes in jobs list */ + /* child process totals */ + c_totforked:libc::c_int, /* total number of children this shell has forked */ + c_totreaped:libc::c_int, /* total number of children this shell has reaped */ + /* job counters and indices */ + j_jobslots:libc::c_int,/* total size of jobs array */ + j_lastj:libc::c_int, /* last (newest) job allocated */ + j_firstj:libc::c_int, /* first (oldest) job allocated */ + j_njobs:libc::c_int, /* number of non-NULL jobs in jobs array */ + j_ndead:libc::c_int, /* number of JDEAD jobs in jobs array */ + /* */ + j_current:libc::c_int, /* current job */ + j_previous:libc::c_int, /* previous job */ + /* */ + j_lastmade:* mut JOB, /* last job allocated by stop_pipeline */ + j_lastasync:* mut JOB /* last async job allocated by stop_pipeline */ +} + + +//枚举 +#[repr(i8)] +#[derive(PartialEq)] +pub enum JOB_STATE { + JNONE = -1, + JRUNNING = 1, + JSTOPPED = 2, + JDEAD = 4, + JMIXED = 8 +} + +//宏 +#[macro_export] +macro_rules! EX_USAGE { + () => { 258 } +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => { 0 } +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE{ + () => { 1 } +} + +#[macro_export] +macro_rules! get_job_by_jid { + ($ind:expr) => { + (*((jobs as usize + ($ind*8) as usize ) as *mut*mut JOB) as *mut JOB) + } +} + +#[macro_export] +macro_rules! STOPPED { + ($j:expr) => { + (*get_job_by_jid!($j)).state == JOB_STATE::JSTOPPED + } +} + +#[macro_export] +macro_rules! RUNNING{ + ($j:expr) => { + (*get_job_by_jid!($j)).state == JOB_STATE::JRUNNING + } +} + +#[macro_export] +macro_rules! EXITPROG{ + () => { 3 } +} + +#[macro_export] +macro_rules! SYS_BASH_LOGOOUT { + () => { + CString::new(" \"/etc/bash.bash_logout\" ").unwrap().as_ptr() + } +} + +//C库 +extern "C"{ + static mut interactive:i32; + static mut login_shell:i32; + // static mut last_shell_builtin:*mut fn(v:*mut WORD_LIST)->i32; + static mut last_shell_builtin:extern fn(v:*mut WORD_LIST)->i32; + // static mut this_shell_builtin:*mut fn(v:*mut WORD_LIST)->i32; + static mut this_shell_builtin:extern fn(v:*mut WORD_LIST)->i32; + static js:jobstats ; + static mut check_jobs_at_exit:i32; + static mut jobs:*mut*mut JOB; + static mut running_trap:i32; + static mut trap_saved_exit_value:i32; + static mut last_command_exit_value:i32; + static subshell_environment:i32; + + fn builtin_help(); + fn builtin_error(err:*const c_char,...); + fn list_all_jobs(form:i32); + fn get_exitstat(list:*mut WORD_LIST) -> i32; + fn jump_to_top_level(level:i32); + fn maybe_execute_file(fname:*const c_char,force_noninteractive:i32)->i32; +} + +unsafe fn STREQ(a:*const c_char,b:*const c_char)->bool{ + return *a == *b && libc::strcmp(a,b) == 0; +} + +// unsafe fn printToStderr(str:*mut c_char) -> std::io::Result<()>{ +// let stderr = std::io::stderr(); +// let mut handle = stderr.lock(); +// handle.write_all(std::ffi::CStr::from_ptr(str).to_bytes())?; +// Ok(()) +// } + +// +static mut sourced_logout:i32 = 0; + +#[no_mangle] +pub extern "C" fn r_exit_builtin(list:*mut WORD_LIST) -> i32{ + println!("r_exit_builtin"); + unsafe{ + if list != std::ptr::null_mut() && (*list).word != std::ptr::null_mut() && + STREQ((*(*list).word).word, CString::new("--help").unwrap().as_ptr()){ + builtin_help(); + return EX_USAGE!(); + } + + if interactive != 0 { + if login_shell != 0 { + // let str:*mut c_char = CString::new("logout\n").unwrap().into_raw(); + // printToStderr(str); + eprintln!("logout"); + }else{ + // let str:*mut c_char = CString::new("exit\n").unwrap().into_raw(); + // printToStderr(str); + eprintln!("exit"); + // libc::fprintf(stderr,CString::new("exit\n").unwrap().as_ptr()); + } + + } + // libc::fflush(stderr); + return r_exit_or_logout(list); + } +} + +#[no_mangle] +pub extern "C" fn r_logout_builtin(list:*mut WORD_LIST)->i32{ + unsafe{ + if list != std::ptr::null_mut() && (*list).word != std::ptr::null_mut() && + STREQ((*(*list).word).word, CString::new("--help").unwrap().as_ptr()){ + builtin_help(); + return EX_USAGE!(); + } + + if login_shell == 0{ + builtin_error(CString::new("not login shell: use `exit'").unwrap().as_ptr()); + return EXECUTION_FAILURE!(); + }else{ + return r_exit_or_logout(list) + } + } +} + +#[no_mangle] +pub extern "C" fn r_exit_or_logout(list:*mut WORD_LIST)->i32{ + // let stream:*mut libc::FILE; + let exit_value:i32; + let exit_immediate_okay:i32; + let mut stopmsg:i32; + + unsafe{ + exit_immediate_okay = (interactive == 0 || + last_shell_builtin == r_exit_builtin || + last_shell_builtin == r_logout_builtin || + last_shell_builtin == r_jobs_builtin ) as i32; + + /* Check for stopped jobs if thw user wants to.*/ + if exit_immediate_okay == 0 { + stopmsg = 0; + for i in 0..js.j_jobslots { + if get_job_by_jid!(i) != std::ptr::null_mut() && STOPPED!(i){ + stopmsg = JOB_STATE::JSTOPPED as i32; + } + else if (check_jobs_at_exit != 0) && (stopmsg ==0) && get_job_by_jid!(i) != std::ptr::null_mut() && RUNNING!(i) { + stopmsg = JOB_STATE::JRUNNING as i32; + } + } + + if stopmsg == JOB_STATE::JSTOPPED as i32 { + // libc::fprintf(stream,CString::new("There are stopped jobs. \n").unwrap().as_ptr()); + eprintln!("There are stopped jobs. "); + } + else if stopmsg == JOB_STATE::JRUNNING as i32{ + // libc::fprintf(stream,CString::new("There are runing jobs.\n").unwrap().as_ptr()); + eprintln!("There are runing jobs."); + } + + if stopmsg == check_jobs_at_exit{ + list_all_jobs(JLIST_STANDARD!()) + } + + if stopmsg != 0 { + last_shell_builtin = r_exit_builtin ; + this_shell_builtin = last_shell_builtin ; + return EXECUTION_FAILURE!(); + } + } + + if (running_trap ==1) && (list == std::ptr::null_mut()) + { + exit_value = trap_saved_exit_value; + }else{ + exit_value = get_exitstat(list); + } + + r_bash_logout(); + last_command_exit_value = exit_value; + + jump_to_top_level(EXITPROG!()); + + 0 + } +} + +#[no_mangle] +pub extern "C" fn r_bash_logout(){ + unsafe{ + if login_shell != 0 && sourced_logout == 0 && subshell_environment == 0 { + sourced_logout = sourced_logout + 1; + maybe_execute_file(CString::new("~/.bash_logout").unwrap().as_ptr(),1); + maybe_execute_file(SYS_BASH_LOGOOUT!(),1); + } + } + +} + + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/fc/Cargo.toml b/bash-5.1/builtins_rust/fc/Cargo.toml index 8101733906766f4c560c672944a7a4f6dce8aa2e..28e5aebdaa8980007e3e900952a9df548035ddf0 100644 --- a/bash-5.1/builtins_rust/fc/Cargo.toml +++ b/bash-5.1/builtins_rust/fc/Cargo.toml @@ -3,7 +3,7 @@ authors = ["huzhengming"] name = "rfc" version = "0.0.1" build = "../build.rs" -edition = "2021" +edition = "2018" [dependencies] @@ -12,5 +12,5 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["cdylib"] +crate-type = ["staticlib"] name = "rfc" diff --git a/bash-5.1/builtins_rust/fc/src/lib.rs b/bash-5.1/builtins_rust/fc/src/lib.rs index b359375266eeef5476bfdae6bc9953a8ac65e7ea..409dbe2667c9dc34db6647cfe5b43f4b86bde1a4 100644 --- a/bash-5.1/builtins_rust/fc/src/lib.rs +++ b/bash-5.1/builtins_rust/fc/src/lib.rs @@ -488,14 +488,14 @@ unsafe fn QUIT () } unsafe fn DIGIT ( c: c_char)->bool { - char::from(c as u8) >= '0' && char::from(c as u8) <= '9' + char::from(c as u8) >= '0' && char::from(c as u8) <= '9' } unsafe fn STREQN ( a:* const c_char, b:* const c_char, n:i32)->bool { if n==0 { return true; } else { - return *((a as usize +4) as * const c_char) ==*((b as usize +4) as * const c_char) && libc::strncmp(a, b, n as libc::size_t) == 0 + return *a == *b && libc::strncmp(a, b, n as libc::size_t) == 0 } } @@ -647,7 +647,7 @@ pub extern "C" fn r_fc_builtin (list:* mut WORD_LIST)->i32 return EXECUTION_SUCCESS!(); } i=0; - while *((hlist as usize +(4*i) as usize) as * mut * mut HIST_ENTRY) != std::ptr::null_mut() { + while *((hlist as usize +(8*i) as usize) as * mut * mut HIST_ENTRY) != std::ptr::null_mut() { i+=1; } @@ -655,13 +655,13 @@ pub extern "C" fn r_fc_builtin (list:* mut WORD_LIST)->i32 last_hist = i - rh - hist_last_line_added; real_last = i; - while *((hlist as usize +(4*real_last) as usize ) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() && real_last > 0 + while *((hlist as usize +(8*real_last) as usize ) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() && real_last > 0 { real_last-=1; } - if i == last_hist && *((hlist as usize + (4*last_hist) as usize) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() { - while last_hist >= 0 && *((hlist as usize + (4*last_hist) as usize) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() + if i == last_hist && *((hlist as usize + (8*last_hist) as usize) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() { + while last_hist >= 0 && *((hlist as usize + (8*last_hist) as usize) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() { last_hist-=1; } @@ -725,13 +725,13 @@ pub extern "C" fn r_fc_builtin (list:* mut WORD_LIST)->i32 if listing == 0 && hist_last_line_added !=0 { bash_delete_last_history (); - if histbeg == histend && histend == last_hist && *((hlist as usize + (4*last_hist) as usize) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() { + if histbeg == histend && histend == last_hist && *((hlist as usize + (8*last_hist) as usize) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() { histend-=1; last_hist = histend; histbeg = histend; } - if *((hlist as usize + (4*last_hist) as usize) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() { + if *((hlist as usize + (8*last_hist) as usize) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() { last_hist-=1; } @@ -820,7 +820,7 @@ pub extern "C" fn r_fc_builtin (list:* mut WORD_LIST)->i32 } } else { let mut ch:char; - if (**((hlist as usize + i as usize) as *mut*mut HIST_ENTRY)).data != std::ptr::null_mut() { + if (**((hlist as usize + (8*i) as usize) as *mut*mut HIST_ENTRY)).data != std::ptr::null_mut() { ch='*'; } else { ch=' '; @@ -838,9 +838,9 @@ pub extern "C" fn r_fc_builtin (list:* mut WORD_LIST)->i32 } if stream != std::ptr::null_mut() { - libc::fprintf (stream, CString::new ("%s\n").unwrap().as_ptr(), (**((hlist as usize + (i*4) as usize) as *mut*mut HIST_ENTRY)).line); + libc::fprintf (stream, CString::new ("%s\n").unwrap().as_ptr(), (**((hlist as usize + (i*8) as usize) as *mut*mut HIST_ENTRY)).line); }else { - printToStdout((**((hlist as usize + (i*4) as usize) as *mut*mut HIST_ENTRY)).line); + printToStdout((**((hlist as usize + (i*8) as usize) as *mut*mut HIST_ENTRY)).line); } ret=reverse !=0; @@ -944,7 +944,7 @@ pub extern "C" fn r_fc_gethist (command:* mut c_char, hlist:* mut * mut HIST_ENT i = r_fc_gethnum (command, hlist, mode); unsafe { if i >= 0 { - return savestring ((*(*((hlist as usize + (4*i) as usize) as * mut * mut HIST_ENTRY))).line ); + return savestring ((*(*((hlist as usize + (8*i) as usize) as * mut * mut HIST_ENTRY))).line ); } else { return std::ptr::null_mut(); } @@ -970,7 +970,7 @@ pub extern "C" fn r_fc_gethnum (command:* mut c_char, hlist:* mut * mut HIST_ENT listing = mode & HN_LISTING!(); sign = 1; /* Count history elements. */ - while *((hlist as usize + (4*i) as usize ) as * mut * mut HIST_ENTRY) != std::ptr::null_mut() { + while *((hlist as usize + (8*i) as usize ) as * mut * mut HIST_ENTRY) != std::ptr::null_mut() { i+=1; } @@ -989,8 +989,8 @@ pub extern "C" fn r_fc_gethnum (command:* mut c_char, hlist:* mut * mut HIST_ENT rh = (remember_on_history !=0 || ((subshell_environment & SUBSHELL_COMSUB!()) !=0 && enable_history_list !=0)) as i32; last_hist = i - rh - hist_last_line_added; - if i == last_hist && *((hlist as usize + (4*last_hist) as usize ) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() { - while last_hist >= 0 && *((hlist as usize + (4*last_hist) as usize ) as * mut * mut HIST_ENTRY) == std::ptr::null_mut(){ + if i == last_hist && *((hlist as usize + (8*last_hist) as usize ) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() { + while last_hist >= 0 && *((hlist as usize + (8*last_hist) as usize ) as * mut * mut HIST_ENTRY) == std::ptr::null_mut(){ last_hist-=1; } } @@ -1008,7 +1008,7 @@ pub extern "C" fn r_fc_gethnum (command:* mut c_char, hlist:* mut * mut HIST_ENT } /* back up from the end to the last non-null history entry */ - while *((hlist as usize + (4*real_last) as usize ) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() && real_last > 0 { + while *((hlist as usize + (8*real_last) as usize ) as * mut * mut HIST_ENTRY) == std::ptr::null_mut() && real_last > 0 { real_last-=1; } @@ -1019,7 +1019,7 @@ pub extern "C" fn r_fc_gethnum (command:* mut c_char, hlist:* mut * mut HIST_ENT /* Handle possible leading minus sign. */ if s != std::ptr::null_mut() && ( char::from(*s as u8) != '-') { sign = -1; - s = (s as usize +1) as * mut c_char; + s = (s as usize +4) as * mut c_char; } if s != std::ptr::null_mut() && DIGIT( *s ) { @@ -1076,7 +1076,7 @@ pub extern "C" fn r_fc_gethnum (command:* mut c_char, hlist:* mut * mut HIST_ENT clen = libc::strlen (command as * const c_char) as i32; j = i; while j >= 0 { - if STREQN (command, (*(*((hlist as usize + (4*j) as usize ) as * mut * mut HIST_ENTRY))).line, clen) { + if STREQN (command, (*(*((hlist as usize + (8*j) as usize ) as * mut * mut HIST_ENTRY))).line, clen) { return j; } j-=1; @@ -1195,12 +1195,13 @@ pub extern "C" fn fc_readline (stream:* mut libc::FILE)->* mut c_char } } +/* #[no_mangle] pub extern "C" fn cmd_name() ->*const u8 { return b"fc" as *const u8; } - #[no_mangle] pub extern "C" fn run(list : *mut WORD_LIST)->i32 { return r_fc_builtin(list); -} \ No newline at end of file +} +*/ diff --git a/bash-5.1/builtins_rust/fg_bg/Cargo.toml b/bash-5.1/builtins_rust/fg_bg/Cargo.toml index 74b94d65e035b5d70545dcb69093062ca56cfb68..7f80416633410a60464ce3e6447ab6ebfc5d3d01 100644 --- a/bash-5.1/builtins_rust/fg_bg/Cargo.toml +++ b/bash-5.1/builtins_rust/fg_bg/Cargo.toml @@ -3,7 +3,7 @@ authors = ["huzhengming"] name = "rfg_bg" version = "0.0.1" build = "../build.rs" -edition = "2021" +edition = "2018" [dependencies] @@ -12,5 +12,5 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["cdylib"] +crate-type = ["staticlib"] name = "rfg_bg" diff --git a/bash-5.1/builtins_rust/fg_bg/src/lib.rs b/bash-5.1/builtins_rust/fg_bg/src/lib.rs index b1d9d35a05c984430655e6d972075e1cfa25b6de..224272aff2c6d3d729a95cccaec95494b7f12ae1 100644 --- a/bash-5.1/builtins_rust/fg_bg/src/lib.rs +++ b/bash-5.1/builtins_rust/fg_bg/src/lib.rs @@ -310,7 +310,7 @@ macro_rules! DUP_JOB { #[macro_export] macro_rules! get_job_by_jid { ($ind:expr) => { - (*(((jobs as usize) + ($ind*32) as usize ) as *mut*mut JOB) as *mut JOB) + (*(((jobs as usize) + ($ind*8) as usize ) as *mut*mut JOB) as *mut JOB) } } @@ -509,12 +509,13 @@ pub extern "C" fn r_fg_bg (list:*mut WORD_LIST, foreground:i32)->i32{ } } +/* #[no_mangle] pub extern "C" fn cmd_name() ->*const u8 { return b"fg" as *const u8; } - #[no_mangle] pub extern "C" fn run(list : *mut WORD_LIST)->i32 { return r_fg_builtin(list); -} \ No newline at end of file +} +*/ diff --git a/bash-5.1/builtins_rust/getopts/Cargo.toml b/bash-5.1/builtins_rust/getopts/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..1e96f4e536e696f40479800502132964e1dad2ef --- /dev/null +++ b/bash-5.1/builtins_rust/getopts/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["huzhengming"] +name = "rgetopts" +version = "0.0.1" +build = "../build.rs" +edition = "2021" + + +[dependencies] +lazy_static = "1.4.0" +libc = "0.2" +nix = "0.23.0" + +[lib] +crate-type = ["staticlib"] +name = "rgetopts" diff --git a/bash-5.1/builtins_rust/getopts/src/lib.rs b/bash-5.1/builtins_rust/getopts/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..9b66e828acbfe0486b1d2800ada63ac20f32e238 --- /dev/null +++ b/bash-5.1/builtins_rust/getopts/src/lib.rs @@ -0,0 +1,558 @@ +extern crate libc; +extern crate nix; + +use libc::{c_char, c_long, c_void}; +use std::{ffi::CString}; + +#[repr(C)] +pub struct WORD_DESC { + pub word: *mut libc::c_char, + pub flags:libc::c_int +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub struct WORD_LIST { + next: *mut WORD_LIST, + word: *mut WORD_DESC +} + +#[repr(u8)] +enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select, + cm_connection, cm_function_def, cm_until, cm_group, + cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc +} + +#[repr(u8)] +#[derive(Copy,Clone)] +enum r_instruction { + r_output_direction, r_input_direction, r_inputa_direction, + r_appending_to, r_reading_until, r_reading_string, + r_duplicating_input, r_duplicating_output, r_deblank_reading_until, + r_close_this, r_err_and_out, r_input_output, r_output_force, + r_duplicating_input_word, r_duplicating_output_word, + r_move_input, r_move_output, r_move_input_word, r_move_output_word, + r_append_err_and_out +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub union REDIRECTEE { + dest:libc::c_int, + filename:* mut WORD_DESC +} + +#[repr(C)] +pub union REDIRECT { + next:*mut REDIRECT, + redirector:REDIRECTEE, + rflags:libc::c_int, + flags:libc::c_int, + instruction:r_instruction, + redirectee:REDIRECTEE, + here_doc_eof:*mut c_char +} + +/* FOR command. */ +#[repr(C)] +pub struct for_com { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct PATTERN_LIST { + next:* mut PATTERN_LIST, + patterns:* mut WORD_LIST, + action:*mut COMMAND, + flags:libc::c_int +} + +#[repr(C)] +pub struct case_com { + flags:libc::c_int, + line:libc::c_int, + word:*mut WORD_DESC, + clauses:*mut PATTERN_LIST +} + +#[repr(C)] +pub struct while_com { + flags:libc::c_int, + test:*mut COMMAND, + action:*mut COMMAND +} + +#[repr(C)] +pub struct if_com { + flags:libc::c_int, + test:*mut COMMAND, + true_case:*mut COMMAND, + false_case:*mut COMMAND +} + +#[repr(C)] +pub struct connection { + ignore:libc::c_int, + first:*mut COMMAND, + second:*mut COMMAND, + connector:libc::c_int +} + +#[repr(C)] +pub struct simple_com { + flags:libc::c_int, + line:libc::c_int, + words:*mut WORD_LIST, + redirects:*mut REDIRECT +} + +#[repr(C)] +pub struct function_def { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + command:*mut COMMAND, + source_file:*mut c_char +} + +#[repr(C)] +pub struct group_com { + ignore:libc::c_int, + command:*mut COMMAND, + source_file:*mut c_char +} + +#[repr(C)] +pub struct select_com { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct arith_com { + flags:libc::c_int, + line:libc::c_int, + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct cond_com { + flags:libc::c_int, + line:libc::c_int, + type_c:libc::c_int, + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct arith_for_com { + flags:libc::c_int, + line:libc::c_int, + init:*mut WORD_LIST, + test:*mut WORD_LIST, + step:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct subshell_com { + flags:i32, + line:i32, + command:*mut COMMAND +} + +#[repr(C)] +pub struct coproc_com { + flags:i32, + name:*mut c_char, + command:*mut COMMAND +} + +#[repr(C)] +pub union VALUE_COMMAND { + For:*mut for_com, + Case:*mut case_com, + While:*mut while_com, + If:*mut if_com, + Connection:*mut connection, + Simple:*mut simple_com, + Function_def:*mut function_def, + Group:*mut group_com, + Select:*mut select_com, + Arith:*mut arith_com, + Cond:*mut cond_com, + ArithFor:*mut arith_for_com, + Subshell:*mut subshell_com, + Coproc:*mut coproc_com +} + +#[repr(C)] +pub struct COMMAND { + type_c:command_type, + flags:i32, + line:i32, + redirects:*mut REDIRECT, + value:VALUE_COMMAND +} + +#[repr(C)] +pub struct SHELL_VAR { + name:*mut c_char, + value:*mut c_char, + exportstr:*mut c_char, + dynamic_value:*mut fn(v:* mut SHELL_VAR)->*mut SHELL_VAR, + assign_func:* mut fn(v:* mut SHELL_VAR,str1:* mut c_char,t:c_long,str2:* mut c_char)->*mut SHELL_VAR, + attributes:i32, + context:i32 +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => {1} +} + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {0} +} + +#[macro_export] +macro_rules! EX_MISCERROR { + () => {2} +} + +#[macro_export] +macro_rules! att_readonly { + () => { + 0x0000002 /* cannot change */ + } +} + +#[macro_export] +macro_rules! att_noassign { + () => { + 0x0004000 /* assignment not allowed */ + } +} + +#[macro_export] +macro_rules! G_EOF { + () => { + -1 + } +} + +#[macro_export] +macro_rules! G_INVALID_OPT { + () => { + -2 + } +} + +#[macro_export] +macro_rules! G_ARG_MISSING { + () => { + -3 + } +} + +#[macro_export] +macro_rules! GETOPT_HELP { + () => { + -99 + } +} + +extern "C" { + fn unbind_variable_noref (name: * const c_char)->i32; + static mut sh_optind:i32; + static mut sh_badopt:i32; + fn legal_identifier (name: * const c_char)->i32; + fn bind_variable (name: * const c_char, value: * mut c_char, flags:i32)->* mut SHELL_VAR; + fn sh_invalidid(name:* mut c_char); + fn builtin_usage(); + static mut sh_opterr:i32; + fn sh_getopt_restore_state (argv:*mut*mut c_char); + static dollar_vars:[* mut c_char;10]; + fn sh_getopt (argc:i32, argv: * const*mut c_char, optstring: * const c_char)->i32; + static rest_of_args:* mut WORD_LIST; + fn number_of_args ()->i32; + fn strvec_create (i:i32)->*mut*mut c_char; + static sh_optarg:* mut c_char; + static sh_optopt:i32; + fn reset_internal_getopt(); + fn internal_getopt (list:*mut WORD_LIST , opts:*mut c_char)->i32; + fn builtin_help (); + static mut loptend:*mut WORD_LIST; + fn make_builtin_argv (list:* mut WORD_LIST, ac:* mut i32)->*mut*mut c_char; +} + +/* getopts_reset is magic code for when OPTIND is reset. N is the + value that has just been assigned to OPTIND. */ +#[no_mangle] +pub extern "C" fn r_getopts_reset (newind:i32){ + unsafe { + sh_optind = newind; + sh_badopt = 0; + } +} + +#[no_mangle] +pub extern "C" fn r_getopts_unbind_variable (name:* mut c_char)->i32 { + unsafe { + return unbind_variable_noref (name); + } +} + +fn readonly_p(va:* mut SHELL_VAR)->i32 +{ + unsafe { + return (*va).attributes & att_readonly!(); + } +} + +fn noassign_p(va:* mut SHELL_VAR)->i32 +{ + unsafe { + return (*va).attributes & att_noassign!(); + } +} + +#[no_mangle] +pub extern "C" fn r_getopts_bind_variable(name:* mut c_char, value:* mut c_char)->i32 +{ + let v:* mut SHELL_VAR; + unsafe { + if legal_identifier(name) !=0 { + v = bind_variable(name, value, 0); + if v != std::ptr::null_mut() && (readonly_p(v) != 0 || noassign_p(v) != 0) { + return EX_MISCERROR!(); + } + + if v != std::ptr::null_mut() { + return EXECUTION_SUCCESS!(); + } else { + return EXECUTION_FAILURE!(); + } + + } else { + sh_invalidid(name); + return EXECUTION_FAILURE!(); + } + } +} + +#[no_mangle] +pub extern "C" fn r_dogetopts(argc:i32, argv:*mut*mut c_char)->i32 +{ + let mut ret:i32; + let special_error:i32; + let mut old_opterr:i32=0; + let mut i:i32; + let n:i32; + + let mut strval:[c_char;2]=[0;2]; + let mut numval:[c_char;16]=[0;16]; + let mut optstr: * mut c_char; /* list of options */ + let name: * mut c_char; /* variable to get flag val */ + let t:* mut c_char; + unsafe { + let mut argcc:i32=argc; + let mut argvv:*mut*mut c_char=argv; + if argcc < 3 { + builtin_usage(); + return EX_USAGE!(); + } + + /* argv[0] is "getopts". */ + optstr = *((argvv as usize +8) as *mut*mut c_char); + name = *((argvv as usize +16) as *mut*mut c_char); + argcc -= 2; + argvv = (argvv as usize +16) as *mut*mut c_char; + + if *optstr == ':' as c_char { + special_error = 1; + } else { + special_error = 0; + } + + if special_error != 0 { + old_opterr = sh_opterr; + optstr=(optstr as usize + 4) as * mut c_char; + sh_opterr = 0; /* suppress diagnostic messages */ + } + + if argcc > 1 { + sh_getopt_restore_state(&mut(*argvv)); + t = *argvv; + *argvv = dollar_vars[0]; + ret = sh_getopt(argcc, argvv, optstr); + *argvv = t; + } else if rest_of_args == std::ptr::null_mut() { + i=0; + while i < 10 && dollar_vars[i as usize] != std::ptr::null_mut() { + i+=1; + } + + sh_getopt_restore_state(&mut (dollar_vars[0] as * mut c_char)); + ret = sh_getopt(i, &dollar_vars[0], optstr); + } else { + let mut words: * mut WORD_LIST; + let v:*mut*mut c_char; + + i = number_of_args() + 1; /* +1 for $0 */ + v = strvec_create(i + 1); + i=0; + while i < 10 && dollar_vars[i as usize] !=std::ptr::null_mut() { + *((v as usize +8*i as usize) as *mut*mut c_char) = dollar_vars[i as usize]; + i+=1; + } + + words = rest_of_args; + while words != std::ptr::null_mut() { + *((v as usize +8*i as usize) as *mut*mut c_char) = (*(*words).word).word; + words = (*words).next; + i+=1; + } + + *((v as usize +8*i as usize) as *mut*mut c_char) = std::ptr::null_mut(); + sh_getopt_restore_state(&mut(*v)); + ret = sh_getopt(i, v, optstr); + libc::free(v as * mut c_void); + } + + if special_error !=0 { + sh_opterr = old_opterr.clone(); + } + + /* Set the OPTIND variable in any case, to handle "--" skipping. It's + highly unlikely that 14 digits will be too few. */ + if sh_optind < 10 { + numval[14] = sh_optind as c_char+ '0' as c_char; + numval[15] = '\0' as c_char; + i = 14; + } else { + i=15; + numval[15] = '\0' as c_char; + n = sh_optind; + + i-=1; + numval[i as usize] = (n % 10) as c_char + '0' as c_char; + while n / 10 != 0 { + i-=1; + numval[i as usize] = (n % 10) as c_char + '0' as c_char; + } + } + + bind_variable(CString::new ("OPTIND").unwrap().as_ptr(), & mut numval[i as usize], 0); + + /* If an error occurred, decide which one it is and set the return + code appropriately. In all cases, the option character in error + is in OPTOPT. If an invalid option was encountered, OPTARG is + NULL. If a required option argument was missing, OPTARG points + to a NULL string (that is, sh_optarg[0] == 0). */ + if ret == '?' as i32 { + if sh_optarg == std::ptr::null_mut() { + ret = G_INVALID_OPT!(); + } else if *sh_optarg == '\0' as c_char{ + ret = G_ARG_MISSING!(); + } + } + + if ret == G_EOF!() { + r_getopts_unbind_variable(CString::new ("OPTARG").unwrap().as_ptr()as * mut c_char); + r_getopts_bind_variable(name, CString::new ("?").unwrap().as_ptr() as * mut c_char); + return EXECUTION_FAILURE!(); + } + + if ret == G_INVALID_OPT!() { + /* Invalid option encountered. */ + ret = r_getopts_bind_variable(name, CString::new ("?").unwrap().as_ptr() as * mut c_char); + + if special_error !=0 { + strval[0] = sh_optopt as c_char; + strval[1] = '\0' as c_char; + bind_variable(CString::new ("OPTARG").unwrap().as_ptr() as * mut c_char, &mut strval[0], 0); + } else { + r_getopts_unbind_variable(CString::new ("OPTARG").unwrap().as_ptr() as * mut c_char); + } + + return ret; + } + + if ret == G_ARG_MISSING!() { + /* Required argument missing. */ + if special_error !=0 { + ret = r_getopts_bind_variable(name, CString::new (":").unwrap().as_ptr() as * mut c_char); + + strval[0] = sh_optopt as c_char; + strval[1] = '\0' as c_char; + bind_variable(CString::new ("OPTARG").unwrap().as_ptr() as * mut c_char, &mut strval[1], 0); + } else { + ret = r_getopts_bind_variable(name, CString::new ("?").unwrap().as_ptr() as * mut c_char); + r_getopts_unbind_variable(CString::new ("OPTARG").unwrap().as_ptr() as * mut c_char); + } + return ret; + } + + bind_variable(CString::new ("OPTARG").unwrap().as_ptr() as * mut c_char, sh_optarg, 0); + + strval[0] = ret as c_char; + strval[1] = '\0' as c_char; + return r_getopts_bind_variable(name, &mut strval[0]); + } +} + +#[no_mangle] +pub extern "C" fn r_getopts_builtin(list: * mut WORD_LIST)->i32 +{ + unsafe { + let av:*mut*mut c_char; + let mut ac:i32=0; + let mut ret:i32; + + if list == std::ptr::null_mut() { + builtin_usage(); + return EX_USAGE!(); + } + + reset_internal_getopt(); + ret = internal_getopt(list, CString::new ("").unwrap().as_ptr() as * mut c_char); + if ret != -1 { + if ret == GETOPT_HELP!() { + builtin_help(); + } else { + builtin_usage(); + } + + return EX_USAGE!(); + } + let llist: * mut WORD_LIST=loptend.clone(); + av = make_builtin_argv(llist, &mut ac); + ret = r_dogetopts(ac, av); + libc::free(av as * mut c_void); + + return ret; + } +} + +/* +#[no_mangle] +pub extern "C" fn cmd_name() ->*const u8 { + return b"getopts" as *const u8; +} +#[no_mangle] +pub extern "C" fn run(list : *mut WORD_LIST)->i32 { + return r_getopts_builtin(list); +}*/ diff --git a/bash-5.1/builtins_rust/hash/.gitignore b/bash-5.1/builtins_rust/hash/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4fffb2f89cbd8f2169ce9914bd16bd43785bb368 --- /dev/null +++ b/bash-5.1/builtins_rust/hash/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/bash-5.1/builtins_rust/hash/Cargo.toml b/bash-5.1/builtins_rust/hash/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..39d577a796716cc1176817ac9666d818195f6066 --- /dev/null +++ b/bash-5.1/builtins_rust/hash/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "rhash" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +read = {path = "../read"} + +[lib] +crate-type = ["staticlib"] +name = "rhash" diff --git a/bash-5.1/builtins_rust/hash/src/lib.rs b/bash-5.1/builtins_rust/hash/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..9b41a21e27ce1cc0b0a1b895174ae46060d3cf95 --- /dev/null +++ b/bash-5.1/builtins_rust/hash/src/lib.rs @@ -0,0 +1,419 @@ +extern crate libc; +extern crate rread; + + +use libc::{c_char,c_int, strchr,free,c_void,strerror,EISDIR}; +use std::ffi::{CStr,CString}; +use std::io::{stdout, Write}; +use rread::{SHELL_VAR}; + +//struct +//结构体 +#[repr (C)] +pub struct WORD_DESC{ + pub word:*mut c_char, + pub flags:c_int, +} + +#[repr (C)] +// #[derive(Copy,Clone)] +pub struct WORD_LIST{ + pub next:*mut WORD_LIST, + pub word:*mut WORD_DESC, +} + +type PTR_T=c_void; +#[repr (C)] +pub struct bucket_contents{ + pub next:*mut bucket_contents, + pub key:*mut c_char, + pub data:*mut PTR_T, //void * or char * + pub khash:u32, + pub times_found:i32, +} +type BUCKET_CONTENTS=bucket_contents; + +#[repr (C)] +pub struct hash_table{ + pub bucket_array:*mut *mut BUCKET_CONTENTS, + pub nbucjets:i32, + pub nentries:i32, +} +type HASH_TABLE = hash_table; + +#[repr (C)] +pub struct _pathdata{ + pub path:*mut c_char, + pub flags:i32, +} +type PATH_DATA = _pathdata; +//enum + +//macro +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => { 0 } +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE{ + () => { 1 } +} + +#[macro_export] +macro_rules! EX_USAGE { + () => { 258 } +} + +#[macro_export] +macro_rules! PARAMS { + ($protos:expr) => { + $protos + }; +} + +#[macro_export] +macro_rules! HASH_ENTRIES { + ($ht:expr) => { + if ($ht) != std::ptr::null_mut(){ + return (*$ht).nentries; + } + else{ + return 0; + } + }; +} + +#[macro_export] +macro_rules! pathdata { + ($x:expr) => { + (*$x).data as *mut PATH_DATA + }; +} + +#[macro_export] +macro_rules! FREE { + ($s:expr) => { + if $s != std::ptr::null_mut(){ + free($s as *mut c_void); + } + }; +} + +// type i32 hash_efunc PARAMS(*mut BUCKET_CONTENTS); +type hash_wfunc = extern fn(*mut BUCKET_CONTENTS)->i32; +type sh_builtin_func_t = extern fn (*mut WORD_LIST)->i32; + +//extern c +extern "C"{ + static loptend:*mut WORD_LIST; + static hashing_enabled:i32; + static list_optarg:*mut c_char; + static this_command_name:*mut c_char; + static posixly_correct:i32; + static restricted:i32; + static shell_compatibility_level:i32; + static hashed_filenames:*mut HASH_TABLE; + static dot_found_in_search:i32; + + fn builtin_error(format:*const c_char,...); + fn reset_internal_getopt(); + fn internal_getopt(list:*mut WORD_LIST,opts:*mut c_char)->i32; + fn builtin_usage(); + fn sh_needarg(s:*mut c_char); + fn phash_flush(); + fn sh_restricted(s:*mut c_char); + fn absolute_program(string:*const c_char)->i32; + fn find_user_command(name:*const c_char)->*mut c_char; + fn executable_file(file:*const c_char)->i32; + fn sh_notfound(s:*mut c_char); + fn is_directory(file:*const c_char)->i32; + fn phash_insert(filename:*mut c_char,full_path:*mut c_char,check_dot:i32,found:i32); + fn phash_remove(filename:*const c_char)->i32; + fn find_function(name:*const c_char)->*mut SHELL_VAR; + fn find_shell_builtin(name:*mut c_char)->*mut sh_builtin_func_t; + fn hash_walk(table:*mut HASH_TABLE,func:*mut hash_wfunc); + fn phash_search(filename:*const c_char)->*mut c_char; + fn printable_filename(f:*mut c_char,flage:i32)->*mut c_char; +} + +//rust +/* Print statistics on the current state of hashed commands. If LIST is + not empty, then rehash (or hash in the first place) the specified + commands. */ +#[no_mangle] +pub extern "C" fn r_hash_builtin(mut list:*mut WORD_LIST)->i32{ + let mut expunge_hash_table:i32; + let mut list_targets:i32; + let mut list_portably:i32; + let mut delete:i32; + let mut opt:i32; + let mut w:*mut c_char; + let mut pathname:*mut c_char; + + unsafe{ + if hashing_enabled == 0{ + let c_str = CString::new("hashing disabled").unwrap(); + let c_str_ptr = c_str.as_ptr(); + + builtin_error(c_str_ptr); + return EXECUTION_FAILURE!(); + } + expunge_hash_table = 0; + list_targets = 0; + list_portably = 0; + delete = 0; + pathname = std::ptr::null_mut(); + + reset_internal_getopt(); + let opts = CString::new("dlp:rt").unwrap(); + opt = internal_getopt(list,opts.as_ptr() as *mut c_char); + while opt != -1{ + let optu8 = opt as u8; + let opt_char = char::from(optu8); + match opt_char{ + 'd' => delete = 1, + 'l' => list_portably = 1, + 'p' => pathname = list_optarg, + 'r' => expunge_hash_table = 1, + 't' => list_targets = 1, + _ => { + builtin_usage(); + return EX_USAGE!(); + } + + } + + opt = internal_getopt(list,opts.as_ptr() as *mut c_char); + } + + list = loptend; + + /* hash -t requires at least one argument. */ + if list == std::ptr::null_mut() && (delete != 0 || list_targets != 0) { + let mut temp:*mut c_char; + if delete != 0{ + temp = CString::new("-d").unwrap().as_ptr() as *mut c_char; + } + else{ + temp = CString::new("-t").unwrap().as_ptr() as *mut c_char; + } + sh_needarg(temp); + return EXECUTION_FAILURE!(); + } + + /* We want hash -r to be silent, but hash -- to print hashing info, so + we test expunge_hash_table. */ + if list==std::ptr::null_mut() && expunge_hash_table == 0{ + opt = r_print_hashed_commands(list_portably); + if opt==0 && posixly_correct==0 && (list_portably==0 || shell_compatibility_level<=50){ + let s_cstr = CStr::from_ptr(this_command_name); + let s_str = s_cstr.to_str().unwrap(); + let s_string = s_str.to_owned(); + println!("{}:hash table empty",s_string); + } + return EXECUTION_SUCCESS!(); + } + + if expunge_hash_table != 0{ + phash_flush(); + } + + /* If someone runs `hash -r -t xyz' he will be disappointed. */ + if list_targets != 0{ + return r_list_hashed_filename_targets(list,list_portably); + } + + if restricted != 0 && pathname != std::ptr::null_mut(){ + if strchr(pathname,'/' as c_int) != std::ptr::null_mut(){ + sh_restricted(pathname); + return EXECUTION_FAILURE!(); + } + + /* If we are changing the hash table in a restricted shell, make sure the + target pathname can be found using a $PATH search. */ + w = find_user_command(pathname); + if w==std::ptr::null_mut() || *w==0 || executable_file(w)==0{ + sh_notfound(pathname); + free(w as *mut c_void); + return EXECUTION_FAILURE!(); + } + free(w as *mut c_void); + } + + opt = EXECUTION_SUCCESS!(); + while list != std::ptr::null_mut(){ + /* Add, remove or rehash the specified commands. */ + w = (*(*list).word).word; + if absolute_program(w as *const c_char) != 0{ + continue; + } + else if pathname != std::ptr::null_mut(){ + if is_directory(pathname) != 0{ + let c_err = CString::new("%s:%s").unwrap().as_ptr(); + builtin_error(c_err,pathname,strerror(EISDIR)); + opt = EXECUTION_SUCCESS!(); + } + else{ + phash_insert(w,pathname,0,0); + } + } + else if delete != 0{ + if phash_remove(w) != 0{ + sh_notfound(w); + opt = EXECUTION_FAILURE!(); + } + } + else if r_add_hashed_command(w,0) != 0{ + opt = EXECUTION_FAILURE!(); + } + list = (*list).next; + } + + stdout().flush(); + return opt; + }//unsafe +} + +#[no_mangle] +extern "C" fn r_add_hashed_command(w:*mut c_char,quiet:i32)->i32{ + let mut rv:i32; + let full_path:*mut c_char; + + rv = 0; + + unsafe{ + // if find_function(w) == std::ptr::null_mut() && find_shell_builtin(w) == std::ptr::null_mut(){ + if find_function(w).is_null() && find_shell_builtin(w).is_null(){ + phash_remove(w); + full_path = find_user_command(w); + if full_path != std::ptr::null_mut() && executable_file(full_path) != 0{ + phash_insert(w,full_path,dot_found_in_search,0) + } + else{ + if quiet == 0{ + sh_notfound(w); + } + rv += 1; + } + FREE!(full_path); + } + + return rv; + + }//unsafe +} + +#[no_mangle] +extern "C" fn r_print_hash_info(item:*mut BUCKET_CONTENTS)->i32{ + + unsafe{ + println!("{:04}\t{}",(*item).times_found,*(*pathdata!(item)).path); + }//unsafe + 0 +} + +#[no_mangle] +extern "C" fn r_print_portable_hash_info(item:*mut BUCKET_CONTENTS)->i32{ + let fp:*mut c_char; + let f:*mut c_char; + + unsafe{ + fp = printable_filename((*pathdata!(item)).path,1); + f = printable_filename((*item).key,1); + println!("builtin hash -p {} {}",*fp,*f); + + if fp != (*pathdata!(item)).path{ + free(fp as *mut c_void); + } + if f != (*item).key{ + free(f as *mut c_void); + } + return 0; + }//unsafe +} + +#[no_mangle] +extern "C" fn r_print_hashed_commands(fmt:i32)->i32{ + unsafe{ + if hashed_filenames.is_null() || HASH_ENTRIES!(hashed_filenames){ + return 0; + } + if fmt == 0{ + println!("hits\tcommand"); + } + let fmt_t:hash_wfunc; + if fmt != 0{ + fmt_t = r_print_portable_hash_info; + } + else{ + fmt_t = r_print_hash_info; + } + hash_walk(hashed_filenames,fmt_t as *mut hash_wfunc); + return 1; + } +} + +#[no_mangle] +extern "C" fn r_list_hashed_filename_targets(list:*mut WORD_LIST,fmt:i32)->i32{ + let mut all_found:i32; + let multiple:i32; + let mut target:*mut c_char; + let mut l:*mut WORD_LIST; + + all_found = 1; + + unsafe{ + if !(*list).next.is_null(){ + multiple = 1; + } + else{ + multiple = 0; + } + + l = list; + while !l.is_null(){ + target = phash_search((*(*l).word).word); + if target.is_null(){ + all_found = 0; + sh_notfound((*(*l).word).word); + continue; + } + if fmt != 0{ + println!("builtin hash -p {} {}",*target,*(*(*l).word).word) + } + else{ + if multiple != 0{ + print!("{}\t",*((*(*l).word).word)); + } + println!("{}",*target); + } + free(target as *mut c_void); + l = (*l).next; + } + + if all_found != 0{ + return EXECUTION_SUCCESS!(); + } + else{ + return EXECUTION_FAILURE!(); + } + } + +} + + + + + + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/help/Cargo.toml b/bash-5.1/builtins_rust/help/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..efb75c0b4dd7d4448aeba4cec3cfcae79031e56b --- /dev/null +++ b/bash-5.1/builtins_rust/help/Cargo.toml @@ -0,0 +1,15 @@ +[package] +authors = ["zhanghuanhuan"] +name = "rhelp" +version = "0.0.1" +build = "../build.rs" +edition = "2018" +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +nix = "0.24.1" + +[lib] +crate-type = ["staticlib"] +name = "rhelp" diff --git a/bash-5.1/builtins_rust/help/src/lib.rs b/bash-5.1/builtins_rust/help/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..40847e94828c263589f0dba2297a83e08d3f3346 --- /dev/null +++ b/bash-5.1/builtins_rust/help/src/lib.rs @@ -0,0 +1,673 @@ +extern crate libc; +extern crate nix; +extern crate std; +use libc::{c_char, c_void ,putchar, free}; +use std::{ffi::{CString,CStr}, i32, io::{Read, stdout, Write}, mem, string, u32}; + +pub enum Option { + None, + Some(T), +} + +#[repr(C)] +pub struct WORD_DESC { + pub word: *mut libc::c_char, + pub flags:libc::c_int +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct WORD_LIST { + next: *mut WORD_LIST, + word: *mut WORD_DESC +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct builtin { + name : *mut libc::c_char, + function :*mut sh_builtin_func_t, + flags : bool, + long_doc :*mut *mut c_char, + short_doc :*mut libc::c_char, + handle :*mut libc::c_char +} +type sh_builtin_func_t = fn(WORD_LIST) -> i32; + +#[repr(C)] +struct FieldStruct { + name : *mut c_char, +} + + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {0} +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE{ + () => {-1} +} + +#[macro_export] +macro_rules! FNMATCH_EXTFLAG { + () => {0} +} + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! MB_CUR_MAX { + () => {6} + } + +#[macro_export] +macro_rules! BASE_INDENT{ + () => {4} +} + +#[macro_export] +macro_rules! BUILTIN_ENABLED{ + () => {1} +} + +#[macro_export] +macro_rules! FNM_NOMATCH{ + () => {1} +} + +#[macro_export] +macro_rules! BUILTIN_SIZEOF{ + () => {48} +} + +#[macro_export] +macro_rules! EXIT_FAILURE{ + () => {1} +} + +extern "C"{ + fn reset_internal_getopt(); + fn internal_getopt (list:*mut WORD_LIST , opts:*mut c_char)->i32; + //fn builtin_error(err:*const c_char,...); + fn builtin_usage(); + fn show_shell_version(ver:i32); + fn glob_pattern_p(pattern:*const c_char) -> i32; + fn zcatfd(fd : i32 ,id : i32, nn :*mut c_char) -> i32; + fn zmapfd(fd : i32, name :*mut *mut libc::c_char, nn: *mut libc::c_char) -> i32; + fn sh_builtin_func_t(list :*mut WORD_LIST) -> i32; + fn builtin_address_internal(comand_name:*mut c_char, i:i32) -> *mut builtin; + fn termsig_handler (sig:i32); + fn throw_to_top_level(); + fn default_columns() -> usize; + fn wcsnwidth (chaa : * mut libc::wchar_t, size :i32, i: i32) -> i32; + fn xstrmatch (string1 : * mut libc::c_char, string2 : * mut libc::c_char, i : i8) -> i8; + fn open(pathname : *const libc::c_char, oflag : i32) -> i32; + fn wcwidth( c :libc::wchar_t) -> i32; + static mut loptend:*mut WORD_LIST; + static bash_copyright : *const c_char; + static bash_license : *const c_char; + static mut terminating_signal:i32; + static this_command_name:*mut libc::c_char; + static mut interrupt_state:i32; + static mut num_shell_builtins : i32; + static mut static_shell_builtin : [builtin ; 100]; + static shell_builtins:*mut builtin; + static mut current_builtin :*mut builtin; +} + +#[no_mangle] +pub extern "C" fn r_help_builtin(mut list:*mut WORD_LIST)->i32 { + + // let mut i:i32; + let mut plen:usize; + let mut match_found:i32; + let mut sflag :i32 = 0; + let mut dflag : i32 = 0; + let mut mflag : i32 = 0; + let mut m: bool; + let pass:i32 = 0; + let mut this_found:i32; + let mut pattern:*mut c_char; + let mut name:*mut c_char; + let l:*mut WORD_LIST= list; + let mut i : i32; + unsafe { + reset_internal_getopt(); + } + let c_str_dms = CString::new("dms").unwrap(); // from a &str, creates a new allocation + unsafe { + i = internal_getopt (list, c_str_dms.as_ptr() as * mut c_char); + } + while i != -1 { + let optu8:u8= i as u8; + let optChar:char=char::from(optu8); + match optChar{ + 'd'=> {dflag = 1; break;} + 'm'=> {mflag = 1; break;} + 's'=> {sflag = 1; break;} + _=>{ + unsafe { + builtin_usage (); + return EX_USAGE!(); + } + } + } + } + unsafe { + let pattern = glob_pattern_p ((*(*list).word).word); + if (pattern == 1){ + println!("Shell commands matching keyword, Shell commands matching keyword"); + if (*list).next !=std::ptr::null_mut() { + println!("Shell commands matching keywords"); + } + else { + println!("Shell commands matching keyword"); + } + println!("{:?} ,",list); + } + let mut loptendt=*list; + let mut match_found = 0; + let mut pattern:*mut c_char = 0 as *mut libc::c_char; + while list !=std::ptr::null_mut() { + pattern = (*(*list).word).word; + plen = libc::strlen (pattern); + let mut this_found = 0; + let mut v : Vec<*mut libc::c_char> = Vec::new(); + for val in 0..=75 { + //let nname = &shell_builtins[val].name; + let builtin1 = unsafe{&(*((shell_builtins as usize + (val*BUILTIN_SIZEOF!()) as usize) as *mut builtin))}; + if builtin1.name != std::ptr::null_mut(){ + v.push(builtin1.name); + } + } + for val in 1..3 { + //for &mut namee in &mut v { + for i in 0..v.len(){ + QUIT(); + /* First val: look for exact string or pattern matches. + Second val: look for prefix matches like bash-4.2 */ + if val == 1{ + m = (libc::strcmp (pattern,v[i]) == 0)|| + (strmatch (pattern,v[i], FNMATCH_EXTFLAG!()) != FNM_NOMATCH!()); + } + else{ + m = libc::strncmp (pattern, v[i], plen) == 0; + } + if m { + + this_found = 1; + match_found = match_found +1 ; + if dflag == 1{ + + show_desc (v[i], i as i32); + //continue; + } + else if mflag ==1{ + + show_manpage (v[i], i as i32); + continue; + } + unsafe { + let builtin1 = &(*((shell_builtins as usize + (i*BUILTIN_SIZEOF!()) as usize) as *mut builtin)); + + println! ("{:?}: {:?}\n", CStr::from_ptr(v[i]), CStr::from_ptr(builtin1.short_doc)); + } + if sflag == 0{ + + show_longdoc (i as i32); + } + } + } + if val == 1 && this_found == 1{ + + break; + } + } + + if (*list).next != std::ptr::null_mut(){ + list = (*list).next; + + } + else { + + break; + } + } + if match_found == 0{ + println! ("no help topics match {:?} .Try 'help help' or 'man -k {:?}' or info {:?}", pattern , pattern, pattern); + return EXECUTION_FAILURE!(); + } + } + unsafe { + std::io::stdout().flush(); + } + return EXECUTION_SUCCESS!(); +} + + +#[no_mangle] +pub extern "C" fn r_help_null_builtin (mut list:*mut WORD_LIST) -> i32{ + unsafe { + show_shell_version(0); + } + show_builtin_command_help (); + return EXECUTION_SUCCESS!(); +} + +unsafe fn QUIT () +{ + if terminating_signal !=0 { + termsig_handler (terminating_signal); + } + + if interrupt_state !=0{ + throw_to_top_level(); + } +} + + +#[no_mangle] +pub extern "C" fn r_builtin_help (){ + let mut ind: i32 = 5; + let d: i32; + unsafe { + current_builtin = builtin_address_internal(this_command_name, 0); + if current_builtin == 0 as *mut builtin{ + return ; + } + + d = (current_builtin as usize - shell_builtins as usize) as i32; + } + ind = d ; + /* + #if defined (__STDC__) + ind = (int)d; + #else + ind = (int)d / sizeof (struct builtin); + #endif + */ + unsafe { + let builtin1 = &(*((shell_builtins as usize + (ind*BUILTIN_SIZEOF!()) as usize) as *mut builtin)); + println!("{:?} : {:?}",this_command_name, CStr::from_ptr(builtin1.short_doc)); + } + show_longdoc (ind); +} + +fn open_helpfile(name :*mut c_char) -> i32{ + + let mut fd : i32; + unsafe { + fd = open (name, 0); + + } + if fd == -1 { + return -1; + } + else { + fd + } +} + +fn show_longdoc(i : i32){ + let mut j : i32; + let mut doc :*mut (*mut c_char); + let mut fd : i32; + let mut usefile : bool ; + let builtin1 = unsafe{&(*((shell_builtins as usize + (i*BUILTIN_SIZEOF!()) as usize) as *mut builtin))}; + unsafe { + doc = builtin1.long_doc; + usefile = doc!= std::ptr::null_mut() && (doc as usize + 8 as usize) as * mut c_char != std::ptr::null_mut(); + usefile = usefile && char::from(unsafe {*((*doc as usize) as * mut c_char) as u8 })== '/'; + // usefile = usefile && unsafe{*((doc as usize + 8 as usize)as *mut *mut libc::c_char) as *mut libc::c_char} == std::ptr::null_mut(); + //usefile = usefile && ((doc as usize + 8 as usize) as * mut c_char) == std::ptr::null_mut(); + //usefile = usefile && (*(doc as usize + 8 as usize) as *mut libc::c_char )as char== '/' as char ; + //usefile = doc!= std::ptr::null_mut() && *((doc as usize + ) as * mut c_char)== '/' as i8 && (doc as usize +4)as * mut c_char == std::ptr::null_mut() as * mut c_char; + } + // let usefile = (doc!= std::ptr::null_mut() && char::from(unsafe {*((doc + 4*8) as usize ) as * mut c_char) as u8 })== '/'); + if usefile { + unsafe { + fd = open_helpfile (*builtin1.long_doc); + } + if (fd < 0){ + //无返回值 + return (); + } + unsafe { + zcatfd (fd, 1, *doc); + libc::close (fd); + } + /* XXX - handle errors if zmapfd returns < 0 */ + } + else if doc!= std::ptr::null_mut() { + let mut j = 0 ; + unsafe { + println!("{:?}",CStr::from_ptr(*doc)); + } + } + // while unsafe {*((doc as usize+(8*j) as usize)as * mut * mut c_char) as *mut c_char }!= std::ptr::null_mut(){ + // unsafe { + // println! ("{:?}{:?} {:?}", BASE_INDENT!()," ", CStr::from_ptr(*((doc as usize+(8*j) as usize)as * mut * mut c_char) as *mut c_char)); + // j += 1; + // } + // } + // } +} + +fn show_desc (name : *mut c_char, i :i32){ + + let mut j :i32; + let r :i32; + let mut doc : *mut *mut libc::c_char; + let mut line : *mut i8 = 0 as *mut i8 ; + let mut fd : i32; + let mut usefile : bool; + + let builtin1 = unsafe{&(*((shell_builtins as usize + (i*BUILTIN_SIZEOF!()) as usize) as *mut builtin))}; + unsafe { + doc = builtin1.long_doc; + } + // usefile = (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL); + usefile = doc!= std::ptr::null_mut() && unsafe {*doc as *mut i8} != std::ptr::null_mut(); + usefile = usefile && unsafe {**doc as i8 } == '/' as i8; + //usefile = usefile && unsafe {*(doc as usize + 8 as usize) as *mut i8} != std::ptr::null_mut(); + if usefile { + + fd = open_helpfile (unsafe {*doc as *mut i8 }); + if (fd < 0){ + //无返回值 + return (); + } + unsafe { + r = zmapfd (fd, *(line as *mut i8) as *mut *mut i8 ,(doc as *mut i8)); + libc::close (fd); + } + /* XXX - handle errors if zmapfd returns < 0 */ + } + else + { + if doc!= std::ptr::null_mut() { + unsafe { + line = *doc as *mut i8; + } + } + else{ + + line = std::ptr::null_mut(); + } + } + + unsafe { + println!("{:?}",CStr::from_ptr(name)); + } + let mut j = 0 ; + while ((line as usize + (8*j)) as * mut c_char)!= std::ptr::null_mut() { + unsafe { + libc::putchar (*((line as usize + (8*j))as * mut c_char) as i32); + if char::from(*((line as usize + (8*j))as * mut c_char) as u8)== '\n'{ + break; + } + } + j += 1; + } + unsafe { + std::io::stdout().flush(); + } + if usefile{ + unsafe { + libc::free (line as * mut c_void); + } + } +} +fn show_manpage (name : *mut c_char, i : i32){ + + let mut j :i32; + let mut doc :*mut *mut libc::c_char; + let mut line :*mut libc::c_char = 0 as *mut libc::c_char;; + let mut fd: i32; + let mut usefile : bool; + let builtin1 = unsafe{&(*((shell_builtins as usize + (i*BUILTIN_SIZEOF!()) as usize) as *mut builtin))}; + unsafe { + + doc = builtin1.long_doc; + } + //*doc = (*((shell_builtins as usize + i as usize) as *mut builtin).long_doc as *mut libc::c_char); + usefile = doc!= std::ptr::null_mut() && unsafe {*doc as *mut i8} != std::ptr::null_mut(); + usefile = usefile && unsafe {**doc as i8 } == '/' as i8; + + if usefile{ + + unsafe { + fd = open_helpfile (*doc); + } + if fd < 0 { + //无返回值 + return (); + } + unsafe{ + zmapfd (fd, line as *mut *mut libc::c_char, *doc); + libc::close (fd); + } + } + else { + + if doc!= std::ptr::null_mut(){ + unsafe { + line = *doc as *mut i8; + } + } + else{ + line = std::ptr::null_mut(); + } + } + /* NAME */ + println! ("NAME\n"); + unsafe { + println! (" - {:?} ", CStr::from_ptr(name)); + } + let mut j = 0 ; + unsafe { + while (*((doc as usize + (8*j))as *mut *mut c_char)as *mut c_char) != std::ptr::null_mut() { + libc::putchar (*((line as usize + (8*j)) as * mut c_char) as i32); + if char::from(*((line as usize + (8*j))as * mut c_char) as u8) == '\n'{ + break; + } + j += 1; + } + } + + println! ("\n"); + + /* SYNOPSIS */ + println! ("SYNOPSIS\n"); + unsafe { + println! (" {:?}\n", CStr::from_ptr(builtin1.short_doc)); + } + /* DESCRIPTION */ + println! ("DESCRIPTION\n"); + if !usefile{ + let mut j = 0 ; + unsafe { + while (*((doc as usize + (8*j))as *mut *mut c_char)as *mut c_char) != std::ptr::null_mut() { + println! (" {:?}\n", unsafe{CStr::from_ptr(*((doc as usize + (8*j))as *mut *mut c_char)as *mut c_char)}); + j += 1; + } + } + } + else{ + while doc != std::ptr::null_mut() && (((doc as usize + (8*j)))as * mut c_char) != std::ptr::null_mut() { + unsafe { + libc::putchar (*((doc as usize + (8*j))as * mut c_char)as i32); + } + println! (" "); + } + j += 1; + } + unsafe { + libc::putchar ('\n' as i32); + } + /* SEE ALSO */ + + println! ("SEE ALSO\n"); + println! (" rash(1) {} \n\n"," "); + + /* IMPLEMENTATION */ + println! ("IMPLEMENTATION\n"); + println! (" "); + unsafe { + show_shell_version (0); + } + println! (" "); + unsafe { + println! ("{:?}", CStr::from_ptr(bash_copyright)); + } + println! (" "); + unsafe { + println! ("{:?}", CStr::from_ptr(bash_license)); + } + //fflush (stdout); + if usefile { + unsafe { + libc::free (line as * mut c_void); + } + } +} + +#[no_mangle] +pub extern "C" fn dispcolumn (i : i32, buf : *mut c_char, bufsize :libc::c_int, width : usize, height : i32){ + let mut j : i32; + let mut dispcols : usize; + let mut helpdoc :*mut libc::c_char; + /* first column */ + let mut builtin1 = unsafe{&(*((shell_builtins as usize + (i*BUILTIN_SIZEOF!()) as usize) as *mut builtin))}; + helpdoc = builtin1.short_doc; + unsafe { + libc::strncpy (((buf as usize + 4 as usize ) as * mut c_char), helpdoc, width - 2); + *((buf as usize + (width - 2) as usize) as * mut c_char)='>' as c_char; + *((buf as usize+(width - 1) as usize) as * mut c_char)='\0' as c_char; + } + /* indicate truncation */ + println! ("{:?}", buf); + unsafe { + if ((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins){ + println! ("\n"); + return; + } + } + dispcols = unsafe {libc::strlen(buf)}; + /* two spaces */ + for j in dispcols .. width{ + std::io::stdout().write(b" "); + } + /* second column */ + builtin1 = unsafe{&(*((shell_builtins as usize + (((i+height)*BUILTIN_SIZEOF!()) as usize)) as *mut builtin))}; + helpdoc = builtin1.short_doc as *mut libc::c_char; + unsafe { + if builtin1.flags && BUILTIN_ENABLED!()==1 { + *((buf as usize) as * mut c_char)=' ' as c_char; + } + else{ + *((buf as usize) as * mut c_char)='*' as c_char; + } + libc::strncpy (((buf as usize + 4 as usize ) as * mut c_char), helpdoc, width - 3); + *((buf as usize + (width - 3) as usize) as * mut c_char)='>' as c_char; + *((buf as usize+(width - 2) as usize) as * mut c_char)='\0' as c_char; + } + println! ("{:?}\n", buf); +} + +pub fn wdispcolumn (i : i32, buf :*mut c_char, bufsize : i32, width : i32, height : i32){ + let mut j : i32; + let mut dispcols : i32 = 0; + let mut dispchars : i32 = 0; + let mut helpdoc :*mut c_char; + let mut wcstr:*mut libc::wchar_t; + let mut slen : i32 = 0; + let mut n :i32 = 0; + let mut builtin1 = unsafe{&(*((shell_builtins as usize + (i*BUILTIN_SIZEOF!()) as usize) as *mut builtin))}; + helpdoc = builtin1.short_doc; + unsafe { + println! ("{:?}", CStr::from_ptr(helpdoc)); + } + +} + +fn show_builtin_command_help (){ + let mut i : i32; + let mut j : i32; + let height : i32 = 76; + let mut width : usize; + let mut t :*mut libc::c_char; + let mut blurb:[i8;128] = ['0' as i8;128]; + println!("help command edit by huanhuan."); + println!("{}",("These shell commands are defined internally. Type `help' to see this list.\n Type `help name' to find out more about the function `name'.\n Use `info bash' to find out more about the shell in general.\n Use `man -k' or `info' to find out more about commands not in this list.\n A star (*) next to a name means that the command is disabled.\n")); + + let ref2: &mut i8= &mut blurb[0]; + + unsafe { + width = default_columns(); + } + width /= 2; + if width > (std::mem::size_of::()*128) { + width = std::mem::size_of::()*128; + } + if width <= 3{ + width = 40; + } + // unsafe { + // height = (num_shell_builtins + 1) / 2; /* number of rows */ + // } + for i in 0..height{ + unsafe { + QUIT(); + } + if MB_CUR_MAX!() > 1 { + let ptr2: *mut i8 = ref2 as *mut i8; + wdispcolumn (i, ptr2,128, width as i32, height); + } +} +} +//#endif /* HELP_BUILTIN */ +fn strmatch (pattern : *mut libc::c_char, string : *mut libc::c_char, flags : i8) -> i8 +{ + if ((string as usize)as * mut c_char != std::ptr::null_mut()) || ((pattern as usize)as * mut c_char != std::ptr::null_mut()){ + return FNM_NOMATCH!(); + } + return unsafe {xstrmatch (pattern, string, flags)}; +} + +struct Thing { + pointer_to_self: *mut Thing, +} + +fn xmalloc (size:usize) ->*mut c_void { + let ret: *mut c_void; +unsafe { + ret = libc::malloc(size); +} +// if (ret == 0) { +// println!("man2html: out of memory"); +// // fprintf(stderr, "man2html: out of memory"); +// (1) +// } + ret +} + +// fn wcswidth(pwcs : *mut libc::wchar_t , n : i32) -> i32{ +// let mut wc : libc::wchar_t; +// let mut len : i32 = 0; +// let mut l : i32; + +// while n-1 > 0 && *(pwcs as usize + 1 as usize) != '\0' as libc::wchar_t{ +// wc = *(pwcs += 1); +// if wcwidth(wc) < 0 { +// return -1; +// } +// len += l; +// } +// len +// } diff --git a/bash-5.1/builtins_rust/history/Cargo.toml b/bash-5.1/builtins_rust/history/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..03dc57ee8e53c5fb8bc54049d4ad114c742382c2 --- /dev/null +++ b/bash-5.1/builtins_rust/history/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "history" +version = "0.1.0" +edition = "2018" +authors = ["lvgenggeng"] +#build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "rhistory" +crate-type = ["staticlib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/history/src/intercdep.rs b/bash-5.1/builtins_rust/history/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..92f11d521b1b375536fe9b9420dd1f749a07f856 --- /dev/null +++ b/bash-5.1/builtins_rust/history/src/intercdep.rs @@ -0,0 +1,92 @@ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +pub const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_USAGE: c_int = 258; + + +pub type histdata_t = *mut libc::c_void; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct _hist_entry { + pub line: *mut c_char, + pub timestamp: *mut c_char, + pub data: histdata_t, +} +pub type HIST_ENTRY = _hist_entry; + +extern "C" { + pub fn reset_internal_getopt(); + pub fn internal_getopt(list: *mut WORD_LIST, opts: *mut c_char) -> c_int; + pub fn builtin_usage(); + pub fn builtin_error(format: *const c_char, ...); + + pub fn bash_clear_history(); + pub fn bash_delete_last_history() -> c_int; + pub fn bash_delete_history_range (first: c_int, last: c_int) -> c_int; + pub fn bash_delete_histent(i: c_int) -> c_int; + + pub fn check_add_history (line: *mut c_char, force: c_int) -> c_int; + pub fn history_expand (hstring: *mut c_char, output: *mut *mut c_char) -> c_int; + pub fn history_get_time(hist: *mut HIST_ENTRY) -> libc::time_t; + pub fn history_list() -> *mut *mut HIST_ENTRY; + pub fn where_history() -> c_int; + pub fn history_set_pos(pos: c_int) -> c_int; + pub fn using_history(); + pub fn maybe_append_history(filename: *mut c_char) -> c_int; + pub fn write_history(filename: *const c_char) -> c_int; + pub fn read_history(filename: *const c_char) -> c_int; + pub fn read_history_range(filename: *const c_char, from: c_int, to: c_int) -> c_int; + pub fn strftime(s: *mut c_char, maxsize:size_t, format: *const c_char, timeptr: *const libc::tm) -> size_t; + pub fn get_numeric_arg(list: *mut WORD_LIST, fatal: c_int, count: *mut c_long) -> c_int; + + pub fn string_list(list: *mut WORD_LIST) -> *mut c_char; + + pub fn sh_chkwrite(s: c_int) -> c_int; + pub fn get_string_value(var_name: *const c_char) -> *mut c_char; + + pub fn termsig_handler(sig: c_int) -> c_int; + pub fn throw_to_top_level() -> c_void; + + pub fn legal_number (str1:*const c_char,result:* mut c_long) -> i32; + + pub fn sh_erange(s: *mut c_char, desc: *mut c_char); + pub fn sh_restricted(s: *mut c_char) -> c_void; + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + + pub static mut remember_on_history: c_int; + pub static mut hist_last_line_pushed: c_int; + pub static mut hist_last_line_added: c_int; + pub static mut current_command_line_count: c_int; + pub static mut current_command_first_line_saved: c_int; + pub static mut command_oriented_history: c_int; + + pub static mut terminating_signal: c_int; + pub static mut interrupt_state: c_int; + + pub static mut history_base: c_int; + pub static mut history_length: c_int; + pub static mut history_lines_in_file: c_int; + pub static mut history_lines_read_from_file: c_int; + pub static mut force_append_history: c_int; + pub static mut history_lines_this_session: c_int; + + pub static mut restricted: c_int; +} diff --git a/bash-5.1/builtins_rust/history/src/lib.rs b/bash-5.1/builtins_rust/history/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..1529c0dcf7a5d7b66dc63e077d8f9146d0f99aaf --- /dev/null +++ b/bash-5.1/builtins_rust/history/src/lib.rs @@ -0,0 +1,332 @@ +use std::{ffi::{CString, CStr}, io::Write}; + +use libc::{size_t, c_int, c_char, c_long, c_void, PT_NULL}; + +include!(concat!("intercdep.rs")); + +pub const AFLAG: c_int = 0x01; +pub const RFLAG: c_int = 0x02; +pub const WFLAG: c_int = 0x04; +pub const NFLAG: c_int = 0x08; +pub const SFLAG: c_int = 0x10; +pub const PFLAG: c_int = 0x20; +pub const CFLAG: c_int = 0x40; +pub const DFLAG: c_int = 0x80; + +#[no_mangle] +pub extern "C" fn r_history_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_history_builtin call"); + + let mut flags: c_int = 0; + let mut opt: c_int; + let mut result: c_int; + + let mut filename: *mut c_char; + let mut delete_arg: *mut c_char = PT_NULL as *mut c_char; + let mut range: *mut c_char; + + let mut delete_offset: c_long = 0; + +unsafe { + reset_internal_getopt(); + let opt_str = CString::new("acd:npsrw").unwrap(); + opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + while opt != -1 { + let opt_char:char=char::from(opt as u8); + match opt_char { + 'a' => flags |= AFLAG, + 'c' => flags |= CFLAG, + 'n' => flags |= NFLAG, + 'r' => flags |= RFLAG, + 'w' => flags |= WFLAG, + 's' => flags |= SFLAG, + 'd' => { + flags |= DFLAG; + delete_arg = list_optarg; + } + 'p' => flags |= PFLAG, + _ => { + builtin_usage (); + return EX_USAGE; + } + } + opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + } + list = loptend; + + let c_tmp = if *delete_arg == b'-' as c_char {(delete_arg as usize + 1) as *mut c_char} else {delete_arg}; + range = libc::strchr(c_tmp, b'-' as c_int); + + opt = flags & (AFLAG | RFLAG | WFLAG | NFLAG); + if opt != 0 && opt != AFLAG && opt != RFLAG && opt != WFLAG && opt != NFLAG { + let c_err = CString::new("cannot use more than one of -anrw").unwrap(); + builtin_error( c_err.as_ptr()); + return EXECUTION_FAILURE; + } + + if (flags & CFLAG) != 0 { + bash_clear_history(); + if list.is_null() { + return EXECUTION_SUCCESS; + } + } + + if (flags & SFLAG) != 0 { + if !list.is_null() { + push_history(list); + } + return EXECUTION_SUCCESS; + } else if (flags & PFLAG) != 0 { + if !list.is_null() { + return expand_and_print_history(list); + } + return sh_chkwrite(EXECUTION_SUCCESS); + } else if (flags & PFLAG) != 0 { + if !list.is_null() { + return expand_and_print_history(list); + } + return sh_chkwrite(EXECUTION_SUCCESS); + } else if (flags & DFLAG) != 0 && !range.is_null() { + let mut delete_start: c_long = 0; + let mut delete_end: c_long = 0; + + *range = b'\0' as c_char; + range = (range as usize + 1) as *mut c_char; + if legal_number(delete_arg, std::mem::transmute(&delete_start)) == 0 || + legal_number(range, std::mem::transmute(&delete_end)) == 0 { + *((range as usize - 1) as *mut c_char) = b'-' as c_char; + sh_erange(delete_arg, "history position\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + if *delete_arg == b'-' as c_char && delete_start < 0 { + delete_start += history_length as c_long; + if delete_start < history_base as c_long { + sh_erange(delete_arg, "history position\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + } else if delete_start > 0 { + delete_start -= history_base as c_long; + } + if delete_start < 0 || delete_start >= history_length as c_long { + sh_erange(delete_arg, "history position\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + if *range == b'-' as c_char && delete_end < 0 { + delete_end += history_length as c_long; + if delete_end < history_base as c_long { + sh_erange(range, "history position\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + } else if delete_end > 0 { + delete_end -= history_base as c_long; + } + + if delete_end < 0 || delete_end >= history_length as c_long { + sh_erange(range, "history position\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + result = bash_delete_history_range(delete_start as c_int, delete_end as c_int); + if where_history() > history_length { + history_set_pos(history_length); + } + return if result != 0 {EXECUTION_SUCCESS} else {EXECUTION_FAILURE}; + } else if (flags & DFLAG) != 0 { + if legal_number(delete_arg, std::mem::transmute(&delete_offset)) == 0 { + sh_erange(delete_arg, "history position\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + + if *delete_arg == b'-' as c_char && delete_offset < 0 { + let ind = history_length + delete_offset as c_int; + if ind < history_base { + sh_erange(range, "history position\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + opt = ind + history_base; + } else if delete_offset < history_base as c_long || + (delete_offset >= (history_base + history_length) as c_long) { + sh_erange(range, "history position\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } else { + opt = delete_offset as c_int; + } + + result = bash_delete_histent(opt - history_base); + if where_history() > history_length { + history_set_pos(history_length); + } + return if result != 0 {EXECUTION_FAILURE} else {EXECUTION_SUCCESS}; + } else if (flags & (AFLAG | RFLAG | NFLAG | WFLAG | CFLAG)) == 0 { + result = display_history(list); + return sh_chkwrite(result); + } + + filename = if !list.is_null() {(*((*list).word)).word} else {get_string_value("HISTFILE\0".as_ptr() as *mut c_char)}; + result = EXECUTION_SUCCESS; + + if restricted != 0 && !(libc::strchr(filename, b'/' as c_int).is_null()) { + sh_restricted(filename); + return EXECUTION_FAILURE; + } + + if (flags & AFLAG) != 0 { + result = maybe_append_history(filename); + } else if (flags & WFLAG) != 0 { + result = write_history(filename); + } else if (flags & RFLAG) != 0{ + result = read_history(filename); + history_lines_in_file = history_lines_read_from_file; + } else if (flags & NFLAG) != 0{ + let old_history_lines = history_lines_in_file; + let obase = history_base; + + using_history(); + result = read_history_range(filename, history_lines_in_file, -1); + using_history(); + + history_lines_in_file = history_lines_read_from_file; + if force_append_history == 0 { + history_lines_this_session += + history_lines_in_file - old_history_lines + history_base - obase; + } + } +} + + return if result != 0 {EXECUTION_FAILURE} else {EXECUTION_SUCCESS}; +} + +fn histtime(hlist: *mut HIST_ENTRY, histtimefmt: *const c_char) -> *mut c_char +{ +unsafe { + static mut timestr: [c_char;128] = [0;128]; + + let mut t = history_get_time(hlist); + let tm = if t != 0 {libc::localtime(&t)} else {PT_NULL as *mut libc::tm}; + if t != 0 && !tm.is_null() { + strftime(std::mem::transmute(×tr), + std::mem::size_of_val(×tr), + histtimefmt, + tm); + } else if !(*hlist).timestamp.is_null() && (*(*hlist).timestamp) != 0 { + let c_str = CString::new("%s: invalid timestamp").unwrap(); + libc::snprintf(std::mem::transmute(×tr), + std::mem::size_of_val(×tr), c_str.as_ptr(), + if *((*hlist).timestamp) == b'#' as c_char {((*hlist).timestamp as usize + 1) as *mut c_char} else {(*hlist).timestamp}); + } else { + libc::strcpy(std::mem::transmute(×tr), b"??\0".as_ptr() as *const c_char); + } + + return timestr.as_mut_ptr(); +} +} + +unsafe fn quit() +{ + if terminating_signal != 0 { + termsig_handler(terminating_signal); + } + if interrupt_state != 0 { + throw_to_top_level(); + } +} + +unsafe fn display_history(list: *mut WORD_LIST) -> c_int +{ + let mut limit:c_long = 0; + let mut histtimefmt: *mut c_char; + let mut timestr: *mut c_char; + + if !list.is_null() { + if get_numeric_arg(list, 0, std::mem::transmute(&limit)) == 0 { + return EXECUTION_FAILURE; + } + if limit < 0 { + limit = -limit; + } + } else { + limit = -1; + } + + let hlist = history_list(); + + if !hlist.is_null() { + let mut i: c_long = 0; + while !((hlist as usize + (i * 8) as usize) as *mut HIST_ENTRY).is_null() { + i += 1; + } + + i = if 0 <= limit && limit < i {i - limit} else {0}; + + histtimefmt = get_string_value("HISTTIMEFORMAT\0".as_ptr() as *const c_char); + + while !((hlist as usize + (i * 8) as usize) as *mut HIST_ENTRY).is_null(){ + quit(); + + if !histtimefmt.is_null() && *histtimefmt != 0 { + timestr = histtime((hlist as usize + (i * 8) as usize) as *mut HIST_ENTRY, histtimefmt); + } else { + timestr = PT_NULL as *mut c_char; + } + + let data = (*((hlist as usize + (i * 8) as usize) as *mut HIST_ENTRY)).data; + let line = (*((hlist as usize + (i * 8) as usize) as *mut HIST_ENTRY)).line; + let s_timestr = CString::from_raw(timestr).into_string().unwrap(); + println!("{:>5}{} {}{}", + i as c_int + history_base, + if !data.is_null() {"*"} else {" "}, + if !timestr.is_null() && *timestr != 0 {s_timestr} else {"".to_owned()}, + CString::from_raw(line).into_string().unwrap() + ); + i += 1; + } + } + + return EXECUTION_SUCCESS; +} + +fn push_history(list: *mut WORD_LIST) { +unsafe { + if remember_on_history != 0 && hist_last_line_pushed == 0 && + (hist_last_line_added != 0 || (current_command_line_count > 0 && current_command_first_line_saved != 0 && command_oriented_history != 0)) && + bash_delete_last_history() == 0 { + return; + } + + let s = string_list(list); + check_add_history(s, 1); + + hist_last_line_pushed = 1; + libc::free(s as *mut c_void); +} +} + +fn expand_and_print_history(mut list: *mut WORD_LIST) -> c_int +{ +unsafe { + + let mut s: *mut c_char = PT_NULL as *mut c_char; + let mut result: c_int; + + if hist_last_line_pushed == 0 && hist_last_line_added != 0 && bash_delete_last_history() == 0 { + return EXECUTION_FAILURE; + } + result = EXECUTION_SUCCESS; + while !list.is_null() { + let r = history_expand((*((*list).word)).word, std::mem::transmute(&s)); + if r < 0 { + let c_err = CString::new("%s: history expansion failed").unwrap(); + builtin_error( c_err.as_ptr(), (*((*list).word)).word); + result = EXECUTION_FAILURE; + } else { + std::io::stdout().lock().write_all(CStr::from_ptr(s).to_bytes()).unwrap(); + libc::putchar(b'\n' as c_int); + } + if !s.is_null() { + libc::free(s as *mut c_void); + } + list = (*list).next; + } + std::io::stdout().lock().flush().unwrap(); + return result; +} +} diff --git a/bash-5.1/builtins_rust/jobs/Cargo.toml b/bash-5.1/builtins_rust/jobs/Cargo.toml index fa26bda57da3806ceeaf60eaea69d5f32799d1aa..d2db00b52e255907ed401c5bab43592d67e06601 100644 --- a/bash-5.1/builtins_rust/jobs/Cargo.toml +++ b/bash-5.1/builtins_rust/jobs/Cargo.toml @@ -2,8 +2,7 @@ authors = ["huzhengming"] name = "rjobs" version = "0.0.1" -build = "../build.rs" -edition = "2021" +edition = "2018" [dependencies] @@ -12,5 +11,5 @@ libc = "0.2" nix = "0.23.0" [lib] -crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] name = "rjobs" diff --git a/bash-5.1/builtins_rust/jobs/src/lib.rs b/bash-5.1/builtins_rust/jobs/src/lib.rs index 5c0162713f275a4eccc43184e6ab56284ccba124..3f74083e469d43a71406a83c2588880510886fe4 100644 --- a/bash-5.1/builtins_rust/jobs/src/lib.rs +++ b/bash-5.1/builtins_rust/jobs/src/lib.rs @@ -13,8 +13,8 @@ pub struct WORD_DESC { #[repr(C)] #[derive(Copy,Clone)] pub struct WORD_LIST { - next: *mut WORD_LIST, - word: *mut WORD_DESC + pub next: *mut WORD_LIST, + pub word: *mut WORD_DESC } #[repr(i8)] @@ -31,6 +31,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select, cm_connection, cm_function_def, cm_until, cm_group, cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc } + #[repr(u8)] #[derive(Copy,Clone)] enum r_instruction { @@ -41,7 +42,8 @@ enum r_instruction { r_duplicating_input_word, r_duplicating_output_word, r_move_input, r_move_output, r_move_input_word, r_move_output_word, r_append_err_and_out - } +} + #[repr(C)] pub struct PROCESS { next: *mut PROCESS, @@ -69,7 +71,6 @@ pub union REDIRECT { here_doc_eof:*mut c_char /* The word that appeared in < {3} } + #[macro_export] macro_rules! EXECUTION_FAILURE { () => {1} } + #[macro_export] macro_rules! JSTATE_RUNNING { () => {0x1} } + #[macro_export] macro_rules! JSTATE_STOPPED { () => {0x2} } + #[macro_export] macro_rules! EX_USAGE { () => {258} } + #[macro_export] macro_rules! EXECUTION_SUCCESS { () => {0} } + #[macro_export] macro_rules! BLOCK_SIGNAL { - ($sig:expr, $nvar:expr, $ovar:expr) => { + ($sig:expr, $nvar:expr, $ovar:expr) => { $nvar.unwrap().clear(); $nvar.unwrap().add($sig); $nvar.unwrap().clear(); - nix::sys::signal::sigprocmask(nix::sys::signal::SigmaskHow::SIG_BLOCK, $nvar, $ovar); + nix::sys::signal::sigprocmask(nix::sys::signal::SigmaskHow::SIG_BLOCK, $nvar, $ovar); } } @@ -317,17 +322,18 @@ macro_rules! UNBLOCK_SIGNAL { nix::sys::signal::sigprocmask(nix::sys::signal::SigmaskHow::SIG_SETMASK, $ovar, None) } } + #[macro_export] macro_rules! UNBLOCK_CHILD { ($ovar:expr) => { - UNBLOCK_SIGNAL!($ovar); + UNBLOCK_SIGNAL!($ovar); } } #[macro_export] macro_rules! BLOCK_CHILD { ($nvar:expr,$ovar:expr) => { - BLOCK_SIGNAL!(nix::sys::signal::SIGCHLD, $nvar, $ovar); + BLOCK_SIGNAL!(nix::sys::signal::SIGCHLD, $nvar, $ovar); } } @@ -340,6 +346,7 @@ macro_rules! NO_JOB { macro_rules! DUP_JOB { () => {-2} } + #[macro_export] macro_rules! CMD_INHIBIT_EXPANSION {/* Do not expand the command words. */ () => {0x20} @@ -348,14 +355,14 @@ macro_rules! CMD_INHIBIT_EXPANSION {/* Do not expand the command words. */ #[macro_export] macro_rules! get_job_by_jid { ($ind:expr) => { - (*(((jobs as i32) + $ind*8 ) as *mut*mut JOB) as *mut JOB) + (*((jobs as usize + ($ind*8) as usize ) as *mut*mut JOB) as *mut JOB) } } #[macro_export] macro_rules! INVALID_JOB { ($j:expr) => { - $j <0 || $j >= js.j_jobslots || get_job_by_jid !($j) as u8 == 0 + $j <0 || $j >= js.j_jobslots || get_job_by_jid !($j) == std::ptr::null_mut() } } @@ -365,15 +372,14 @@ extern "C" { fn internal_getopt (list:*mut WORD_LIST , opts:*mut c_char)->i32; fn builtin_error(err:*const c_char,...); fn builtin_usage(); - static mut loptend:*mut WORD_LIST; + static mut loptend:*mut WORD_LIST; fn list_all_jobs(form:i32); fn list_stopped_jobs(form:i32); - fn list_one_job (jjob:*mut JOB, format:i32, ignore:i32, job_index:i32); + fn list_one_job (jjob:*mut JOB, format:i32, ignore:i32, job_index:i32); fn get_job_spec (list:*mut WORD_LIST)->i32; fn sh_badjob (str:*mut c_char); static jobs:*mut*mut JOB; - fn discard_unwind_frame (str: * mut c_char); - + fn discard_unwind_frame (str: * mut c_char); fn begin_unwind_frame (str: * mut c_char); fn execute_command (command:* mut COMMAND)->i32; fn dispose_command (command:* mut COMMAND); @@ -388,34 +394,32 @@ extern "C" { fn nohup_all_jobs (running_only:i32); fn delete_all_jobs(running_only:i32); } + #[no_mangle] pub extern "C" fn r_execute_list_with_replacements (list:*mut WORD_LIST)->i32{ - println!("r_execute_list_with_replacements"); + //println!("r_execute_list_with_replacements"); unsafe{ - let mut l:WORD_LIST=*list; + let mut l:*mut WORD_LIST=list; let mut job:i32; let result:i32; let command:*mut COMMAND; - /* First do the replacement of job specifications with pids. */ - - while l.next as u8 !=0 { - let lchar:char=char::from((*(*l.word).word) as u8); + /* First do the replacement of job specifications with pids. */ + while l !=std::ptr::null_mut() { + let lchar:char=char::from((*(*(*l).word).word) as u8); if lchar== '%' /* we have a winner */ { - job = get_job_spec (&mut l); - + job = get_job_spec ( l); /* A bad job spec is not really a job spec! Pass it through. */ if INVALID_JOB!(job){ continue; } - libc::free((*l.word).word as * mut libc::c_void); - (*(*l.word).word) = (*get_job_by_jid! (job)).pgrp as i8; - } - l=*(l.next); - } - - + libc::free((*(*l).word).word as * mut libc::c_void); + (*(*(*l).word).word) = (*get_job_by_jid! (job)).pgrp as i8; + } + l=(*l).next; + } + let mut c_str_jobs_builtin = CString::new("jobs_builtin").unwrap(); /* Next make a new simple command and execute it. */ begin_unwind_frame (c_str_jobs_builtin.as_ptr() as * mut c_char); @@ -429,14 +433,13 @@ extern "C" { add_unwind_protect(dispose_command, command); result = execute_command (command); dispose_command (command); - discard_unwind_frame (c_str_jobs_builtin.as_ptr() as * mut c_char); return result; } } #[no_mangle] -pub extern "C" fn r_jobs_builtin(list:*mut WORD_LIST)->i32{ +pub extern "C" fn r_jobs_builtin(list:*mut WORD_LIST)->i32 { println!("r_jobs_builtin"); let mut form:i32; let mut execute:i32=0; @@ -452,44 +455,41 @@ pub extern "C" fn r_jobs_builtin(list:*mut WORD_LIST)->i32{ state = JSTATE_ANY!(); unsafe { - reset_internal_getopt(); - - let mut c_str_lpnxrs = CString::new("lpnxrs").unwrap(); // from a &str, creates a new allocation - - opt = internal_getopt (list, c_str_lpnxrs.as_ptr() as * mut c_char); - while opt != -1{ - let optu8:u8= opt as u8; - let optChar:char=char::from(optu8); - match optChar{ - 'l'=>{form = JLIST_LONG!();} - 'p'=>{form = JLIST_PID_ONLY!();} - 'n'=>{form = JLIST_CHANGED_ONLY!();} - 'x'=>{ - if form != JLIST_STANDARD!() { - let mut c_str_err = CString::new("no other options allowed with `-x'").unwrap(); // from a &str, creates a new allocation - builtin_error (c_str_err.as_ptr()); - return EXECUTION_FAILURE!(); - } - execute+=1; + reset_internal_getopt(); + + let mut c_str_lpnxrs = CString::new("lpnxrs").unwrap(); // from a &str, creates a new allocation + + opt = internal_getopt (list, c_str_lpnxrs.as_ptr() as * mut c_char); + while opt != -1 { + let optu8:u8= opt as u8; + let optChar:char=char::from(optu8); + match optChar{ + 'l'=>{form = JLIST_LONG!();} + 'p'=>{form = JLIST_PID_ONLY!();} + 'n'=>{form = JLIST_CHANGED_ONLY!();} + 'x'=>{ + if form != JLIST_STANDARD!() { + let mut c_str_err = CString::new("no other options allowed with `-x'").unwrap(); // from a &str, creates a new allocation + builtin_error (c_str_err.as_ptr()); + return EXECUTION_FAILURE!(); } - 'r'=>{state = JSTATE_RUNNING!();} - 's'=>{state = JSTATE_STOPPED!();} - - _=>{ - builtin_usage (); - return EX_USAGE!(); + execute+=1; } - - } - opt = internal_getopt (list, c_str_lpnxrs.as_ptr() as * mut c_char); + 'r'=>{state = JSTATE_RUNNING!();} + 's'=>{state = JSTATE_STOPPED!();} + _=>{ + builtin_usage (); + return EX_USAGE!(); + } } + opt = internal_getopt (list, c_str_lpnxrs.as_ptr() as * mut c_char); + } - - if execute != 0 { + if execute != 0 { return r_execute_list_with_replacements (loptend); - } - - if loptend as u8 ==0 { + } + + if loptend ==std::ptr::null_mut() { if state == JSTATE_ANY!() { list_all_jobs (form); } else if state == JSTATE_RUNNING!() { @@ -499,16 +499,16 @@ pub extern "C" fn r_jobs_builtin(list:*mut WORD_LIST)->i32{ } return EXECUTION_SUCCESS!(); } - + let mut loptendt=*loptend; - while loptendt.next as u8 !=0 { + while loptendt.next !=std::ptr::null_mut() { BLOCK_CHILD !(Some(&mut set), Some(&mut oset)); job = get_job_spec (&mut loptendt); - if (job == NO_JOB!()) || jobs as u8 == 0 || get_job_by_jid !(job) as u8 == 0 { - sh_badjob ((*loptendt.word).word); + if (job == NO_JOB!()) || jobs == std::ptr::null_mut() || get_job_by_jid !(job) == std::ptr::null_mut() { + sh_badjob ((*loptendt.word).word); any_failed+=1; - } else if (job != DUP_JOB!()){ + } else if (job != DUP_JOB!()) { list_one_job (0 as * mut JOB, form, 0, job); } @@ -517,13 +517,14 @@ pub extern "C" fn r_jobs_builtin(list:*mut WORD_LIST)->i32{ } if any_failed !=0 { return EXECUTION_FAILURE!(); - }else { + } else { return EXECUTION_SUCCESS!(); } } } + #[no_mangle] -pub extern "C" fn r_disown_builtin (list:* mut WORD_LIST)->libc::c_int{ +pub extern "C" fn r_disown_builtin (list:* mut WORD_LIST)->libc::c_int { let opt:i32; let mut job:i32=0; let mut retval:i32; @@ -534,88 +535,91 @@ pub extern "C" fn r_disown_builtin (list:* mut WORD_LIST)->libc::c_int{ let mut set:nix::sys::signal::SigSet=nix::sys::signal::SigSet::empty(); let mut oset:nix::sys::signal::SigSet =nix::sys::signal::SigSet::empty(); let mut pid_value:c_long=0; - println!("r_disown_builtin"); + //println!("r_disown_builtin"); unsafe { reset_internal_getopt (); let mut c_str_ahr = CString::new("ahr").unwrap(); // from a &str, creates a new allocation - opt = internal_getopt (list, c_str_ahr.as_ptr() as * mut c_char); - while opt != -1{ + while opt != -1 { let optu8:u8= opt as u8; let optChar:char=char::from(optu8); match optChar{ - 'a'=>{all_jobs = 1;} - 'h'=>{nohup_only = 1;} - 'r'=>{running_jobs = 1;} - _=>{ - builtin_usage (); - return EX_USAGE!(); - } - + 'a'=>{all_jobs = 1;} + 'h'=>{nohup_only = 1;} + 'r'=>{running_jobs = 1;} + _=>{ + builtin_usage (); + return EX_USAGE!(); + } } - } - + } + retval = EXECUTION_SUCCESS!(); /* `disown -a' or `disown -r' */ - if loptend as u8 == 0 && (all_jobs !=0 || running_jobs != 0) { + if loptend == std::ptr::null_mut() && (all_jobs !=0 || running_jobs != 0) { if nohup_only!=0{ nohup_all_jobs (running_jobs); - } else{ + } else { delete_all_jobs (running_jobs); } - - return EXECUTION_SUCCESS!(); - } + return EXECUTION_SUCCESS!(); + } - BLOCK_CHILD !(Some(&mut set), Some(&mut oset)); - if (loptend as u8 !=0 && legal_number ((*(*loptend).word).word, &mut pid_value) !=0 && pid_value == pid_value) { - job=get_job_by_pid ( pid_value as i32, 0, 0 as *mut*mut PROCESS); - }else { - get_job_spec (loptend); - - } - if job == NO_JOB!() || jobs as u8 !=0 || INVALID_JOB!(job){ - if loptend as u8 !=0 { + BLOCK_CHILD !(Some(&mut set), Some(&mut oset)); + if (loptend !=std::ptr::null_mut() && legal_number ((*(*loptend).word).word, &mut pid_value) !=0 && pid_value == pid_value) { + job=get_job_by_pid ( pid_value as i32, 0, 0 as *mut*mut PROCESS); + }else { + get_job_spec (loptend); + } + if job == NO_JOB!() || jobs !=std::ptr::null_mut() || INVALID_JOB!(job) { + if loptend !=std::ptr::null_mut() { sh_badjob ((*(*loptend).word).word); - }else { + } else { sh_badjob (CString::new("current").unwrap().as_ptr() as * mut c_char); - } - retval = EXECUTION_FAILURE!(); - } else if nohup_only !=0{ + } + retval = EXECUTION_FAILURE!(); + } else if nohup_only !=0{ nohup_job (job); } else { delete_job (job, 1); } - - UNBLOCK_CHILD !(Some(&oset)); - - - if loptend as u8 !=0 { + + UNBLOCK_CHILD !(Some(&oset)); + + if loptend != std::ptr::null_mut() { let mut loptendt=*loptend; - while loptendt.next as u8 !=0 { + while loptendt.next !=std::ptr::null_mut() { loptendt = *loptendt.next; BLOCK_CHILD !(Some(&mut set), Some(&mut oset)); if legal_number ((*loptendt.word).word, &mut pid_value) !=0 && pid_value == pid_value { job=get_job_by_pid ( pid_value as i32, 0, 0 as *mut*mut PROCESS); - }else { + } else { get_job_spec (&mut loptendt); - } - if job == NO_JOB!() || jobs as u8 !=0 || INVALID_JOB!(job){ - - sh_badjob ((*loptendt.word).word); - + if job == NO_JOB!() || jobs !=std::ptr::null_mut() || INVALID_JOB!(job) { + sh_badjob ((*loptendt.word).word); retval = EXECUTION_FAILURE!(); } else if nohup_only !=0{ nohup_job (job); } else { delete_job (job, 1); } - UNBLOCK_CHILD !(Some(&oset)); } } return retval; } -} \ No newline at end of file +} + +#[no_mangle] +pub extern "C" fn cmd_name() ->*const u8 { + return b"jobs" as *const u8; +} +/* +#[no_mangle] + +pub extern "C" fn run(list : *mut WORD_LIST)->i32 { + return r_jobs_builtin(list); +} +*/ diff --git a/bash-5.1/builtins_rust/kill/Cargo.toml b/bash-5.1/builtins_rust/kill/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..806a44fcf164c7de4b434dc7e109d3c2637f4ee5 --- /dev/null +++ b/bash-5.1/builtins_rust/kill/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "kill" +version = "0.1.0" +edition = "2018" +authors = ["lvgenggeng"] +#build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "rkill" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/kill/src/intercdep.rs b/bash-5.1/builtins_rust/kill/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..388884675ed0644797e5fc8f0b08358966a0b3b8 --- /dev/null +++ b/bash-5.1/builtins_rust/kill/src/intercdep.rs @@ -0,0 +1,323 @@ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +pub const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_USAGE: c_int = 258; + +pub const EINVAL: c_int = 22; +pub const NO_SIG: c_int = -1; + +pub const DSIG_SIGPREFIX: c_int = 0x01; +pub const DSIG_NOCASE: c_int = 0x02; + +pub const DUP_JOB: c_int = -2; + +pub const J_JOBCONTROL: c_int = 0x04; + +pub type pid_t = c_int; +pub type WAIT = c_int; +pub type sh_vptrfunc_t = *mut fn(); +pub type JOB_STATE = c_int; + +pub type command_type = c_uint; +#[repr(C)] +#[derive(Copy, Clone)] +pub union REDIRECTEE { + pub dest: c_int, + pub filename: *mut WORD_DESC, +} + +pub type r_instruction = c_uint; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct redirect { + pub next: *mut redirect, + pub redirector: REDIRECTEE, + pub rflags: c_int, + pub flags: c_int, + pub instruction: r_instruction, + pub redirectee: REDIRECTEE, + pub here_doc_eof: *mut c_char, +} + +pub type REDIRECT = redirect; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct command { + pub type_: command_type, + pub flags: c_int, + pub line: c_int, + pub redirects: *mut REDIRECT, + pub value: command__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union command__bindgen_ty_1 { + pub For: *mut for_com, + pub Case: *mut case_com, + pub While: *mut while_com, + pub If: *mut if_com, + pub Connection: *mut connection, + pub Simple: *mut simple_com, + pub Function_def: *mut function_def, + pub Group: *mut group_com, + pub Select: *mut select_com, + pub Arith: *mut arith_com, + pub Cond: *mut cond_com, + pub ArithFor: *mut arith_for_com, + pub Subshell: *mut subshell_com, + pub Coproc: *mut coproc_com, +} + +pub type COMMAND = command; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct pattern_list { + pub next: *mut pattern_list, + pub patterns: *mut WORD_LIST, + pub action: *mut COMMAND, + pub flags: c_int, +} + +pub type PATTERN_LIST = pattern_list; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct case_com { + pub flags: c_int, + pub line: c_int, + pub word: *mut WORD_DESC, + pub clauses: *mut PATTERN_LIST, +} + +pub type CASE_COM = case_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct for_com { + pub flags: c_int, + pub line: c_int, + pub name: *mut WORD_DESC, + pub map_list: *mut WORD_LIST, + pub action: *mut COMMAND, +} + +pub type FOR_COM = for_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct arith_for_com { + pub flags: c_int, + pub line: c_int, + pub init: *mut WORD_LIST, + pub test: *mut WORD_LIST, + pub step: *mut WORD_LIST, + pub action: *mut COMMAND, +} + +pub type ARITH_FOR_COM = arith_for_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct select_com { + pub flags: c_int, + pub line: c_int, + pub name: *mut WORD_DESC, + pub map_list: *mut WORD_LIST, + pub action: *mut COMMAND, +} + +pub type SELECT_COM = select_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct if_com { + pub flags: c_int, + pub test: *mut COMMAND, + pub true_case: *mut COMMAND, + pub false_case: *mut COMMAND, +} + +pub type IF_COM = if_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct while_com { + pub flags: c_int, + pub test: *mut COMMAND, + pub action: *mut COMMAND, +} + +pub type WHILE_COM = while_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct arith_com { + pub flags: c_int, + pub line: c_int, + pub exp: *mut WORD_LIST, +} + +pub type ARITH_COM = arith_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct cond_com { + pub flags: c_int, + pub line: c_int, + pub type_: c_int, + pub op: *mut WORD_DESC, + pub left: *mut cond_com, + pub right: *mut cond_com, +} + +pub type COND_COM = cond_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct simple_com { + pub flags: c_int, + pub line: c_int, + pub words: *mut WORD_LIST, + pub redirects: *mut REDIRECT, +} + +pub type SIMPLE_COM = simple_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct function_def { + pub flags: c_int, + pub line: c_int, + pub name: *mut WORD_DESC, + pub command: *mut COMMAND, + pub source_file: *mut c_char, +} + +pub type FUNCTION_DEF = function_def; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct group_com { + pub ignore: c_int, + pub command: *mut COMMAND, +} + +pub type GROUP_COM = group_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct subshell_com { + pub flags: c_int, + pub line: c_int, + pub command: *mut COMMAND, +} + +pub type SUBSHELL_COM = subshell_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct coproc { + pub c_name: *mut c_char, + pub c_pid: pid_t, + pub c_rfd: c_int, + pub c_wfd: c_int, + pub c_rsave: c_int, + pub c_wsave: c_int, + pub c_flags: c_int, + pub c_status: c_int, + pub c_lock: c_int, +} + +pub type Coproc = coproc; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct coproc_com { + pub flags: c_int, + pub name: *mut c_char, + pub command: *mut COMMAND, +} + +pub type COPROC_COM = coproc_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct process { + pub next: *mut process, + pub pid: pid_t, + pub status: WAIT, + pub running: c_int, + pub command: *mut c_char, +} + +pub type PROCESS = process; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct job { + pub wd: *mut c_char, + pub pipe: *mut PROCESS, + pub pgrp: pid_t, + pub state: JOB_STATE, + pub flags: c_int, + pub deferred: *mut COMMAND, + pub j_cleanup: sh_vptrfunc_t, + pub cleanarg: *mut c_void, +} + +pub type JOB = job; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct connection { + pub _address: u8, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct jobstats { + pub c_childmax: c_long, + pub c_living: c_int, + pub c_reaped: c_int, + pub c_injobs: c_int, + pub c_totforked: c_int, + pub c_totreaped: c_int, + pub j_jobslots: c_int, + pub j_lastj: c_int, + pub j_firstj: c_int, + pub j_njobs: c_int, + pub j_ndead: c_int, + pub j_current: c_int, + pub j_previous: c_int, + pub j_lastmade: *mut JOB, + pub j_lastasync: *mut JOB, +} + +extern "C" { + pub fn reset_internal_getopt(); + pub fn internal_getopt(list: *mut WORD_LIST, opts: *mut c_char) -> c_int; + + pub fn get_job_spec(list: *mut WORD_LIST) -> c_int; + + pub fn builtin_usage(); + pub fn builtin_help(); + pub fn builtin_error(format: *const c_char, ...); + + pub fn legal_number(string: *mut c_char, result: c_long) -> c_int; + pub fn display_signal_list (list: *mut WORD_LIST, forcecols: c_int) -> c_int; + pub fn decode_signal (string: *mut c_char, flags: c_int) -> c_int; + + pub fn sh_needarg(s: *mut c_char) -> c_void; + pub fn sh_invalidsig(s: *mut c_char) -> c_void; + pub fn sh_badpid(s: *mut c_char) -> c_void; + pub fn sh_badjob(s: *mut c_char) -> c_void; + + pub fn kill_pid(pid: libc::pid_t, sig: c_int, group: c_int) -> c_int; + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + + pub static posixly_correct: c_int; + + pub static mut js: jobstats; + pub static mut jobs: *mut *mut JOB; +} diff --git a/bash-5.1/builtins_rust/kill/src/lib.rs b/bash-5.1/builtins_rust/kill/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..5f294f17be414ca3eef80d1ffecb4c2e66d96352 --- /dev/null +++ b/bash-5.1/builtins_rust/kill/src/lib.rs @@ -0,0 +1,206 @@ +use std::{ffi::{CString, CStr}}; +use libc::{c_int, c_uint, c_char, c_long, c_void, PT_NULL}; + +include!(concat!("intercdep.rs")); + + +#[no_mangle] +pub extern "C" fn r_kill_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_kill_builtin call"); + +unsafe { + let mut word: *mut c_char; + let mut pid:libc::pid_t; + let mut pid_value: c_long = 0; + + if list.is_null() { + builtin_usage(); + return EX_USAGE; + } + + if !list.is_null() && !(*list).word.is_null() && + libc::strcmp((*((*list).word)).word, "--help\0".as_ptr() as *const c_char) == 0 { + builtin_help (); + return EX_USAGE; + } + + let mut any_succeeded: c_int = 0; + let mut listing: c_int = 0; + let mut saw_signal: c_int = 0; + let mut sig = libc::SIGTERM; + let mut sigspec = "TERM\0".as_ptr() as *mut c_char; + + let dflags = DSIG_NOCASE | if posixly_correct == 0 {DSIG_SIGPREFIX} else {0}; + while !list.is_null() { + word = (*((*list).word)).word; + + if is_option(word, b'l') || is_option(word, b'L') { + listing += 1; + list = (*list).next; + } else if is_option(word, b's') || is_option(word, b'n') { + list = (*list).next; + if !list.is_null() { + sigspec = (*((*list).word)).word; + if *sigspec == b'0' as c_char && + *((sigspec as usize + 1) as *mut c_char) == b'\0' as c_char { + sig = 0; + } else { + sig = decode_signal(sigspec, dflags); + } + list = (*list).next; + saw_signal += 1; + } else { + sh_needarg(word); + return EXECUTION_FAILURE; + } + } else if *word == b'-' as c_char && + *((word as usize + 1) as *mut c_char) == b's' as c_char && + libc::isalpha(*((word as usize + 2) as *mut c_char) as c_int) != 0 { + sigspec = (word as usize + 2) as *mut c_char; + if *sigspec == b'0' as c_char && + *((sigspec as usize + 1) as *mut c_char) == b'\0' as c_char { + sig = 0; + } else { + sig = decode_signal(sigspec, dflags); + } + list = (*list).next; + saw_signal += 1; + } else if *word == b'-' as c_char && + *((word as usize + 1) as *mut c_char) == b'n' as c_char && + libc::isdigit(*((word as usize + 2) as *mut c_char) as c_int) != 0 { + sigspec = (word as usize + 2) as *mut c_char; + if *sigspec == b'0' as c_char && + *((sigspec as usize + 1) as *mut c_char) == b'\0' as c_char { + sig = 0; + } else { + sig = decode_signal(sigspec, dflags); + } + list = (*list).next; + saw_signal += 1; + } else if is_option(word, b'-') { + list = (*list).next; + break; + } else if is_option(word, b'?') { + builtin_usage(); + return EX_USAGE; + } else if *word == b'-' as c_char && saw_signal == 0 { + sigspec = (word as usize + 1) as *mut c_char; + sig = decode_signal(sigspec, dflags); + saw_signal += 1; + list = (*list).next; + } else { + break; + } + } + + if listing != 0 { + return display_signal_list(list, 0); + } + + if sig == NO_SIG { + sh_invalidsig(sigspec); + return EXECUTION_FAILURE; + } + + if list.is_null() { + builtin_usage(); + return EX_USAGE; + } + + while !list.is_null() { + word = (*((*list).word)).word; + + if *word == b'-' as c_char { + word = (word as usize + 1) as *mut c_char; + } + + if *word != 0 && legal_number((*((*list).word)).word, std::mem::transmute(&pid_value)) != 0 + && (pid_value == (pid_value as c_int) as c_long) { + pid = pid_value as libc::pid_t; + + if kill_pid(pid, sig, (pid < -1) as c_int) < 0 { + if *(libc::__errno_location()) == EINVAL { + sh_invalidsig(sigspec); + } else { + kill_error(pid, *(libc::__errno_location())); + } + list = (*list).next; + continue; + } else { + any_succeeded += 1; + } + } + else if *((*((*list).word)).word) != 0 && *((*((*list).word)).word) != b'%' as c_char { + let c_err = CString::new("%s: arguments must be process or job IDs").unwrap(); + builtin_error(c_err.as_ptr(), (*((*list).word)).word); + list = (*list).next; + continue; + } else if *word != 0 { + let set: libc::sigset_t = std::mem::zeroed(); + let oset: libc::sigset_t = std::mem::zeroed(); + let j: *mut JOB; + + libc::sigemptyset(std::mem::transmute(&set)); + libc::sigaddset(std::mem::transmute(&set), libc::SIGCHLD); + libc::sigemptyset(std::mem::transmute(&oset)); + libc::sigprocmask(libc::SIG_BLOCK, std::mem::transmute(&set), std::mem::transmute(&oset)); + + let job = get_job_spec(list); + + if job < 0 || job > js.j_jobslots || ((jobs as usize + job as usize * 8) as *mut JOB).is_null() { + if job != DUP_JOB { + sh_badjob((*((*list).word)).word); + } + libc::sigprocmask(libc::SIG_SETMASK, std::mem::transmute(&oset), PT_NULL as *mut libc::sigset_t); + list = (*list).next; + continue; + } + + j = (jobs as usize + job as usize * 8) as *mut JOB; + if (*j).flags & J_JOBCONTROL != 0 { + pid = (*j).pgrp; + } else { + pid = (*((*j).pipe)).pid; + } + + libc::sigprocmask(libc::SIG_SETMASK, std::mem::transmute(&oset), PT_NULL as *mut libc::sigset_t); + + if kill_pid(pid, sig, 1) < 0 { + if *(libc::__errno_location()) == EINVAL { + sh_invalidsig(sigspec); + } else { + kill_error(pid, *(libc::__errno_location())); + } + list = (*list).next; + continue; + } else { + any_succeeded += 1; + } + } + else { + sh_badpid((*((*list).word)).word); + list = (*list).next; + continue; + } + list = (*list).next; + } + + return if any_succeeded != 0 {EXECUTION_SUCCESS} else {EXECUTION_FAILURE}; +} +} + +unsafe fn is_option(s: *mut c_char, c: u8) -> bool +{ + let str = CStr::from_ptr(s).to_bytes_with_nul(); + return str[0] == b'-' && str[1] == c && str[2] != 0 +} + +unsafe fn kill_error(pid: libc::pid_t, e: c_int) +{ + let mut x = libc::strerror(e); + if x.is_null() { + x = "Unknown error".as_ptr() as *mut c_char; + } + + builtin_error("(%ld) - %s".as_ptr() as *const c_char, pid, x); +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/mapfile/Cargo.toml b/bash-5.1/builtins_rust/mapfile/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..ab558a553852e193b82ddd71bcda4d35d562fe45 --- /dev/null +++ b/bash-5.1/builtins_rust/mapfile/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "mapfile" +version = "0.1.0" +edition = "2018" +authors = ["lvgenggeng"] +#build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "rmapfile" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/mapfile/src/intercdep.rs b/bash-5.1/builtins_rust/mapfile/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..f4de2e9c91124fd305a5547ddcaa3c7adbd0e02e --- /dev/null +++ b/bash-5.1/builtins_rust/mapfile/src/intercdep.rs @@ -0,0 +1,114 @@ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +pub type arrayind_t = c_long; + +pub type sh_var_value_func_t = + ::std::option::Option *mut variable>; + + pub type sh_var_assign_func_t = ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut variable, + arg2: *mut c_char, + arg3: arrayind_t, + arg4: *mut c_char, + ) -> *mut variable, +>; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct variable { + pub name: *mut c_char, + pub value: *mut c_char, + pub exportstr: *mut c_char, + pub dynamic_value: sh_var_value_func_t, + pub assign_func: sh_var_assign_func_t, + pub attributes: c_int, + pub context: c_int, +} +pub type SHELL_VAR = variable; + +pub const atype_array_indexed: atype = 0; +pub const atype_array_assoc: atype = 1; +pub type atype = c_uint; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct array { + pub type_: atype, + pub max_index: arrayind_t, + pub num_elements: c_int, + pub head: *mut array_element, + pub lastref: *mut array_element, +} +pub type ARRAY = array; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct array_element { + pub ind: arrayind_t, + pub value: *mut c_char, + pub next: *mut array_element, + pub prev: *mut array_element, +} +pub type ARRAY_ELEMENT = array_element; + +pub const ESPIPE: c_int = 29; +pub const SEEK_CUR: c_int = 1; + +pub const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_USAGE: c_int = 258; + +pub const SEVAL_NOHIST: c_int = 0x004; + +pub const att_readonly: c_int = 0x0000002; +pub const att_array: c_int = 0x0000004; +pub const att_invisible: c_int = 0x0001000; +pub const att_noassign: c_int = 0x0004000; + +extern "C" { + pub fn reset_internal_getopt(); + pub fn internal_getopt(list: *mut WORD_LIST, opts: *mut c_char) -> c_int; + pub fn builtin_usage(); + pub fn builtin_error(format: *const c_char, ...); + + pub fn legal_identifier(arg1: *const c_char) -> c_int; + pub fn legal_number (str1:*const c_char,result:* mut c_long) -> i32; + pub fn sh_invalidid(arg1: *mut c_char); + pub fn sh_validfd(arg1: c_int) -> c_int; + + pub fn sh_single_quote(s: *mut c_char) -> *mut c_char; + + pub fn evalstring(string: *mut c_char, from_file: *const c_char, flags: c_int) -> c_int; + + pub fn find_or_make_array_variable(name: *mut c_char, flags: c_int) -> *mut SHELL_VAR; + + pub fn bind_array_element(entry: *mut SHELL_VAR, ind: c_long, value: *mut c_char, flags: c_int) -> *mut SHELL_VAR; + + pub fn array_flush(a: *mut ARRAY); + + pub fn err_readonly(s: *const c_char) -> c_void; + + pub fn zreset() -> c_void; + pub fn zsyncfd(fd: c_int) -> c_void; + pub fn zgetline (fd: c_int, lineptr: *mut *mut c_char, n: *mut size_t, delim: c_int, unbuffered_read: c_int) -> ssize_t; + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + +} diff --git a/bash-5.1/builtins_rust/mapfile/src/lib.rs b/bash-5.1/builtins_rust/mapfile/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..b5f8ba8471085ecc0a0982c81c3aa51de2c6396f --- /dev/null +++ b/bash-5.1/builtins_rust/mapfile/src/lib.rs @@ -0,0 +1,220 @@ +use std::{ffi::CString}; + +use libc::{size_t, ssize_t, c_int, c_uint, c_char, c_uchar, c_long, c_void, PT_NULL}; + +include!(concat!("intercdep.rs")); + +pub const DEFAULT_QUANTUM: c_long = 5000; +pub const MAPF_CLEARARRAY: c_int = 0x01; +pub const MAPF_CHOP: c_int = 0x02; + +static mut delim: c_int = 0; + +#[no_mangle] +pub extern "C" fn r_mapfile_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_mapfile_builtin call"); + + let mut opt: c_int; + let mut code: c_int; + let mut fd: c_int = 0; + let mut flags: c_int = MAPF_CLEARARRAY; + let intval: c_long = 0; + let mut lines: c_long = 0; + let mut origin: c_long = 0; + let mut nskip: c_long = 0; + let mut callback_quantum: c_long = DEFAULT_QUANTUM; + + let array_name: *mut c_char; + let mut callback: *mut c_char = PT_NULL as *mut c_char; + +unsafe { + + delim = b'\n' as c_int; + + reset_internal_getopt(); + let opt_str = CString::new("d:u:n:O:tC:c:s:").unwrap(); + opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + while opt != -1 { + let opt_char:char=char::from(opt as u8); + match opt_char { + 'd' => delim = *list_optarg as c_int, + 'u' => { + code = legal_number(list_optarg, std::mem::transmute(&intval)); + if code == 0 || intval < 0 || intval != (intval as c_int) as c_long{ + builtin_error("%s: invalid file descriptor specification\0".as_ptr() as *const c_char, list_optarg); + return EXECUTION_FAILURE; + } else { + fd = intval as c_int; + } + if sh_validfd(fd) == 0 { + builtin_error("%d: invalid file descriptor: %s\0".as_ptr() as *const c_char, + fd, libc::strerror(*libc::__errno_location())); + return EXECUTION_FAILURE; + } + } + 'n' => { + code = legal_number(list_optarg, std::mem::transmute(&intval)); + if code == 0 || intval < 0 || intval != (intval as c_uint) as c_long { + builtin_error("%s: invalid line count\0".as_ptr() as *const c_char, list_optarg); + return EXECUTION_FAILURE; + } else { + lines = intval; + } + } + 'O' => { + code = legal_number(list_optarg, std::mem::transmute(&intval)); + if code == 0 || intval < 0 || intval != (intval as c_uint) as c_long { + builtin_error("%s: invalid array origin\0".as_ptr() as *const c_char, + list_optarg); + return EXECUTION_FAILURE; + } else { + origin = intval; + } + flags &= (MAPF_CLEARARRAY as c_uint ^ 0xffffffff) as c_int; + } + 't' => flags |= MAPF_CHOP, + 'C' => callback = list_optarg, + 'c' => { + code = legal_number(list_optarg, std::mem::transmute(&intval)); + if code == 0 || intval < 0 || intval != (intval as c_uint) as c_long { + builtin_error("%s: invalid callback quantum\0".as_ptr() as *const c_char, list_optarg); + return EXECUTION_FAILURE; + } else { + callback_quantum = intval; + } + } + 's' => { + code = legal_number(list_optarg, std::mem::transmute(&intval)); + if code == 0 || intval < 0 || intval != (intval as c_uint) as c_long { + builtin_error("%s: invalid line count\0".as_ptr() as *const c_char, list_optarg); + return EXECUTION_FAILURE; + } else { + nskip = intval; + } + } + _ => { + builtin_usage (); + return EX_USAGE; + } + } + opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + } + list = loptend; + + if list.is_null() { + array_name = "MAPFILE".as_ptr() as *mut c_char; + } else if (*list).word.is_null() || (*(*list).word).word.is_null() { + builtin_error("internal error: getting variable name\0".as_ptr() as *const c_char); + return EXECUTION_FAILURE; + } else if *(*(*list).word).word == b'\0' as c_char { + builtin_error("empty array variable name\0".as_ptr() as *const c_char); + return EX_USAGE; + } else { + array_name = (*(*list).word).word; + } + if legal_identifier(array_name) == 0 { + sh_invalidid(array_name); + return EXECUTION_FAILURE; + } + + return mapfile(fd, lines, origin, nskip, callback_quantum, callback, + array_name, delim, flags); +} +} + +unsafe fn run_callback(callback: *const c_char, curindex: c_uint, curline: *mut c_char) -> c_int +{ + let qline = sh_single_quote(curline); + let execlen = libc::strlen(callback) + libc::strlen(qline) + 10 + 3; + let execstr = libc::malloc(execlen); + + let flags = SEVAL_NOHIST; + + libc::snprintf(execstr as *mut c_char, execlen, "%s %d %s\0".as_ptr() as *const c_char, + callback, curindex, qline); + libc::free(qline as *mut c_void); + return evalstring(execstr as *mut c_char, PT_NULL as *const c_char, flags); +} + +unsafe fn do_chop(line: *mut c_char, d: c_uchar) +{ + let length = libc::strlen(line); + if length != 0 && *((line as usize + length - 1) as *mut c_char) == d as c_char { + *((line as usize + length - 1) as *mut c_char) = b'\0' as c_char; + } +} + +unsafe fn mapfile(fd: c_int, line_count_goal: c_long, origin: c_long, nskip: c_long, callback_quantum: c_long, + callback: *mut c_char, array_name: *mut c_char, dlm: c_int, flags: c_int) -> c_int +{ + let mut line: *mut c_char = PT_NULL as *mut c_char; + let mut line_length: size_t = 0; + let mut unbuffered_read: c_int; + + let entry = find_or_make_array_variable(array_name, 1); + if entry.is_null() || ((*entry).attributes & att_readonly) != 0 || ((*entry).attributes & att_noassign) != 0 { + if !entry.is_null() && ((*entry).attributes & att_readonly) != 0 { + err_readonly(array_name); + } + + return EXECUTION_FAILURE; + } else if ((*entry).attributes & att_array) == 0 { + builtin_error("%s: not an indexed array\0".as_ptr() as *const c_char, array_name); + return EXECUTION_FAILURE; + } else if ((*entry).attributes & att_array) != 0 { + (*entry).attributes &= (att_invisible as c_uint ^ 0xffffffff) as c_int; + } + + if (flags & MAPF_CLEARARRAY) != 0 { + array_flush(std::mem::transmute((*entry).value)); + } + unbuffered_read = ((libc::lseek(fd, 0, SEEK_CUR) < 0) && (*libc::__errno_location() == ESPIPE)) as c_int; + + if dlm != b'\n' as c_int { + unbuffered_read = 1; + } + zreset(); + + let mut line_count: c_uint = 0; + while (line_count as c_long) < nskip { + if zgetline(fd, std::mem::transmute(&line), std::mem::transmute(&line_length), dlm, unbuffered_read) < 0 { + break; + } + line_count += 1; + } + + line = PT_NULL as *mut c_char; + line_length = 0; + let mut array_index: c_uint = origin as c_uint; + line_count = 1; + while zgetline(fd, std::mem::transmute(&line), std::mem::transmute(&line_length), dlm, unbuffered_read) != -1 { + if (flags & MAPF_CHOP) != 0 { + do_chop(line, dlm as c_uchar); + } + + if !callback.is_null() && line_count != 0 && (line_count as c_long % callback_quantum) == 0 { + run_callback(callback, array_index, line); + + if unbuffered_read == 0 { + zsyncfd(fd); + } + } + + bind_array_element(entry, array_index as c_long, line, 0); + + line_count += 1; + if line_count_goal != 0 && (line_count as c_long) > line_count_goal { + break; + } + + array_index += 1; + } + + libc::free(line as *mut c_void); + + if unbuffered_read == 0 { + zsyncfd(fd); + } + + return EXECUTION_SUCCESS; +} diff --git a/bash-5.1/builtins_rust/printf/Cargo.toml b/bash-5.1/builtins_rust/printf/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..a87e0bc568ef7bfc70718998c62845c56bca21da --- /dev/null +++ b/bash-5.1/builtins_rust/printf/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "printf" +version = "0.1.0" +edition = "2018" +authors = ["lvgenggeng"] +#build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "rprintf" +crate-type = ["staticlib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/printf/src/intercdep.rs b/bash-5.1/builtins_rust/printf/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..f782774a5aab422678fbb6df1e9381cf04d1bd3e --- /dev/null +++ b/bash-5.1/builtins_rust/printf/src/intercdep.rs @@ -0,0 +1,117 @@ +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +pub type SHELL_VAR = variable; + +pub type __intmax_t = c_long; +pub type intmax_t = __intmax_t; +pub type arrayind_t = intmax_t; +pub type sh_var_value_func_t = + ::std::option::Option *mut variable>; + + pub type sh_var_assign_func_t = ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut variable, + arg2: *mut c_char, + arg3: arrayind_t, + arg4: *mut c_char, + ) -> *mut variable, +>; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct variable { + pub name: *mut c_char, + pub value: *mut c_char, + pub exportstr: *mut c_char, + pub dynamic_value: sh_var_value_func_t, + pub assign_func: sh_var_assign_func_t, + pub attributes: c_int, + pub context: c_int, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub union __mbstate_t__bindgen_ty_1 { + pub __wch: c_uint, + pub __wchb: [c_char; 4], +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct __mbstate_t { + pub __count: c_int, + pub __value: __mbstate_t__bindgen_ty_1, +} +pub type mbstate_t = __mbstate_t; + +pub const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_USAGE: c_int = 258; + +pub const VA_NOEXPAND: c_int = 0x001; +pub const VA_ONEWORD: c_int = 0x002; + +pub const att_readonly: c_int = 0x0000002; +pub const att_noassign: c_int = 0x0004000; + +extern "C" { + pub fn reset_internal_getopt(); + pub fn internal_getopt(list: *mut WORD_LIST, opts: *mut c_char) -> c_int; + pub fn builtin_usage(); + pub fn builtin_error(format: *const c_char, ...); + pub fn builtin_warning(format: *const c_char, ...); + pub fn builtin_bind_variable(name: *mut c_char, value: *mut c_char, flags: c_int) -> *mut SHELL_VAR; + pub fn stupidly_hack_special_variables(name: *const c_char) -> c_void; + pub fn legal_identifier(arg1: *const c_char) -> c_int; + pub fn legal_number (str1:*const c_char,result:* mut c_long) -> i32; + pub fn sh_invalidid(arg1: *mut c_char); + + pub fn valid_array_reference (name: *const c_char, flags: c_int) -> c_int; + pub fn bind_var_to_int(var: *mut c_char, val: c_long) -> *mut SHELL_VAR; + + pub fn mbtowc(pwc: *mut libc::wchar_t, s: *const c_char, n: size_t) -> size_t; + + pub fn sh_invalidnum(s: *mut c_char) -> c_void; + + pub fn xmalloc(bytes: size_t) -> *mut c_void; + pub fn xrealloc(p: *mut c_void, bytes: size_t) -> *mut c_void; + pub fn savestring(s: *const c_char) -> *mut c_char; + pub fn ansic_shouldquote(s: *const c_char) -> c_int; + pub fn ansic_quote(str: *mut c_char, flags: c_int, rlen: *mut c_int) -> *mut c_char; + pub fn sh_backslash_quote(string: *mut c_char, table: *mut c_char, flags: c_int) -> *mut c_char; + + pub fn u32cconv(c: c_ulong, s: *mut c_char) -> c_int; + + pub fn termsig_handler(arg1: c_int) -> c_void; + pub fn throw_to_top_level() -> c_void; + + pub fn sv_tz(name: *mut c_char) -> c_void; + pub fn strftime(s: *mut c_char, maxsize: size_t, format: *const c_char, timeptr: *const libc::tm) -> size_t; + + pub fn sh_wrerror() -> c_void; + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + pub static mut assoc_expand_once: c_int; + + pub static terminating_signal : c_int; + pub static interrupt_state : c_int; + + pub static stdout: *mut libc::FILE; + + pub static shell_start_time: libc::time_t; +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/printf/src/lib.rs b/bash-5.1/builtins_rust/printf/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..eae577919eb6b8c1ff4b31d58424ad28c73e87b0 --- /dev/null +++ b/bash-5.1/builtins_rust/printf/src/lib.rs @@ -0,0 +1,1214 @@ +use std::{ffi::CString}; +use libc::{size_t, c_int, c_uint, c_char, c_long, c_void, PT_NULL, c_ulong, strchr}; + +include!(concat!("intercdep.rs")); + +macro_rules! IS_DIGITAL { + ($x: expr) => { + $x >= b'0' as c_char && $x <= b'9' as c_char + }; +} + +unsafe fn QUIT() +{ + if terminating_signal != 0 { + termsig_handler(terminating_signal); + } + + if interrupt_state != 0 { + throw_to_top_level(); + } +} + +unsafe fn PC(c: u8) +{ + let mut b: [c_char; 2] = [0; 2]; + tw += 1; + b[0] = c as c_char; + if vflag != 0 { + vbadd(b.as_ptr() as *mut c_char, 1); + } else { + libc::putchar(c as c_int ); + } + QUIT(); +} + +static mut conversion_error: c_int = 0; +static mut conv_buf: *mut c_char = PT_NULL as *mut c_char; +static mut conv_bufsize: size_t = 0; + +static mut vbuf: *mut c_char = PT_NULL as *mut c_char; +static mut vname: *mut c_char = PT_NULL as *mut c_char; +static mut vflag: c_int = 0; +static mut vbsize: size_t = 0; +static mut vblen: c_int = 0; + +static mut retval: c_int = 0; +static mut tw: c_long = 0; + +static mut garglist: *mut WORD_LIST = PT_NULL as *mut WORD_LIST; +static mut orig_arglist: *mut WORD_LIST = PT_NULL as *mut WORD_LIST; + +#[no_mangle] +pub extern "C" fn r_printf_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_printf_builtin call"); + + let mut ch: c_int; + let mut fieldwidth: c_int; + let mut have_fieldwidth: c_int; + let mut precision: c_int; + let mut have_precision: c_int; + let mut arrayflags: c_int; + + let mut fmt; + let mut start; + let mut modstart; + let mut convch; + let mut thisch; + let mut nextch; +unsafe { + + let PRETURN = |out_val: c_int| { + QUIT(); + if vflag != 0 { + let v = builtin_bind_variable(vname, vbuf, 0); + stupidly_hack_special_variables(vname); + if v.is_null() || ((*v).attributes & att_readonly) != 0 || ((*v).attributes & att_noassign) != 0 { + return EXECUTION_FAILURE; + } + } + if conv_bufsize > 4096 { + libc::free(conv_buf as *mut c_void); + conv_bufsize = 0; + conv_buf = PT_NULL as *mut c_char; + } + + if vbsize > 4096 { + libc::free(vbuf as *mut c_void); + vbsize = 0; + vbuf = PT_NULL as *mut c_char; + } else if !vbuf.is_null() { + *vbuf = 0; + } + + if libc::ferror(stdout) == 0 { + libc::fflush(stdout); + } + QUIT(); + if libc::ferror(stdout) != 0 { + sh_wrerror(); + libc::clearerr(stdout); + return EXECUTION_FAILURE; + } + + return out_val; + }; + + vflag = 0; + reset_internal_getopt(); + let opt_str = CString::new("v:").unwrap(); + let mut opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + while opt != -1 { + let opt_char:char=char::from(opt as u8); + match opt_char { + 'v' => { + vname = list_optarg; + arrayflags = if assoc_expand_once != 0 {VA_NOEXPAND | VA_ONEWORD} else {0}; + if legal_identifier(vname) != 0 || valid_array_reference(vname, arrayflags) != 0 { + vflag = 1; + if vbsize == 0 { + vbsize = 16; + vbuf = xmalloc(16) as *mut c_char; + } + vblen = 0; + if !vbuf.is_null() { + *vbuf = 0; + } + } else { + sh_invalidid(vname); + return EX_USAGE; + } + } + _ => { + builtin_usage (); + return EX_USAGE; + } + } + opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + } + list = loptend; + + if list.is_null() { + builtin_usage(); + return EX_USAGE; + } + + if vflag != 0 && !((*(*list).word).word.is_null()) && *(*(*list).word).word == b'\0' as c_char { + let v = builtin_bind_variable(vname, "\0".as_ptr() as *mut c_char, 0); + stupidly_hack_special_variables(vname); + return if v.is_null() || ((*v).attributes & att_readonly) != 0 || ((*v).attributes & att_noassign) != 0 {EXECUTION_FAILURE} else {EXECUTION_SUCCESS}; + } + + if (*(*list).word).word.is_null() || *(*(*list).word).word == b'\0' as c_char { + return EXECUTION_SUCCESS; + } + + let format = (*(*list).word).word; + tw = 0; + + garglist = (*list).next; + orig_arglist = (*list).next; + + if format.is_null() || *format == 0 { + return EXECUTION_SUCCESS; + } + + 'outer: loop { + tw = 0; + fmt = format; + while *fmt != 0 { + precision = 0; + fieldwidth = 0; + have_fieldwidth = 0; + have_precision = 0; + + if *fmt == b'\\' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + let mut mbch: [i8;25] = [0; 25]; + let mut mblen: c_int = 0; + fmt = (fmt as usize + tescape(fmt, mbch.as_ptr() as *mut c_char, std::mem::transmute(&mblen), PT_NULL as *mut c_int) as usize) as *mut c_char; + let mut mbind = 0; + while mbind < mblen { + PC(mbch[mbind as usize] as u8); + } + fmt = (fmt as usize - 1) as *mut c_char; + continue; + } + + if *fmt != b'%' as c_char { + PC(*fmt as u8); + continue; + } + + start = fmt; + fmt = (fmt as usize + 1) as *mut c_char; + if *fmt == b'%' as c_char { + PC(b'%'); + continue; + } + + while *fmt != 0 && !(strchr("#'-+ 0\0".as_ptr() as *const c_char, *fmt as c_int).is_null()) { + fmt = (fmt as usize + 1) as *mut c_char; + } + + if *fmt == b'*' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + have_fieldwidth = 1; + fieldwidth = getint(); + } else { + while IS_DIGITAL!(*fmt) { + fmt = (fmt as usize + 1) as *mut c_char; + } + } + + if *fmt == b'.' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + if *fmt == b'*' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + have_precision = 1; + precision = getint(); + } else { + if *fmt == b'-' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + } + while IS_DIGITAL!(*fmt) { + fmt = (fmt as usize + 1) as *mut c_char; + } + } + } + + modstart = fmt; + while *fmt != 0 && !(strchr("hjlLtz\0".as_ptr() as *const c_char, *fmt as c_int).is_null()) { + fmt = (fmt as usize + 1) as *mut c_char; + } + + if *fmt == 0 { + builtin_error("`%s': missing format character\0".as_ptr() as *const c_char, start); + return PRETURN(EXECUTION_FAILURE); + } + + convch = *fmt; + thisch = *modstart; + nextch = *((modstart as usize + 1) as *mut c_char); + *modstart = convch; + *((modstart as usize + 1) as *mut c_char) = b'\0' as c_char; + + QUIT(); + let format_type = convch as u8; + match format_type { + b'c' => { + let p = getchr(); + let f = start; + libc::clearerr(stdout); + let PF = || { + let nw: c_int; + if vflag == 0 { + if have_fieldwidth != 0 && have_precision != 0 { + nw = libc::printf(f, fieldwidth, precision, p); + } else if have_fieldwidth != 0 { + nw = libc::printf(f, fieldwidth, p); + } else if have_precision != 0 { + nw = libc::printf(f, precision, p); + } else { + nw = libc::printf(f, p); + } + } else { + let vbsnprintf2 = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf1 = |x: c_int| { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + if have_fieldwidth != 0 && have_precision != 0 { + nw = vbsnprintf2(); + } else if have_fieldwidth != 0 { + nw = vbsnprintf1(fieldwidth); + } else if have_precision != 0 { + nw = vbsnprintf1(precision); + } else { + nw = vbsnprintf(); + } + } + tw += nw as c_long; + }; + PF(); + QUIT(); + if libc::ferror(stdout) != 0 { + sh_wrerror(); + libc::clearerr(stdout); + return EXECUTION_FAILURE; + } + } + b's' => { + let p = getstr(); + let f = start; + libc::clearerr(stdout); + let PF = || { + let nw: c_int; + if vflag == 0 { + if have_fieldwidth != 0 && have_precision != 0 { + nw = libc::printf(f, fieldwidth, precision, p); + } else if have_fieldwidth != 0 { + nw = libc::printf(f, fieldwidth, p); + } else if have_precision != 0 { + nw = libc::printf(f, precision, p); + } else { + nw = libc::printf(f, p); + } + } else { + let vbsnprintf2 = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf1 = |x: c_int| { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + if have_fieldwidth != 0 && have_precision != 0 { + nw = vbsnprintf2(); + } else if have_fieldwidth != 0 { + nw = vbsnprintf1(fieldwidth); + } else if have_precision != 0 { + nw = vbsnprintf1(precision); + } else { + nw = vbsnprintf(); + } + } + tw += nw as c_long; + }; + PF(); + QUIT(); + if libc::ferror(stdout) != 0 { + sh_wrerror(); + libc::clearerr(stdout); + return EXECUTION_FAILURE; + } + } + b'(' => { + *((modstart as usize + 1) as *mut c_char) = nextch; + let timefmt = xmalloc(libc::strlen(fmt) + 3) as *mut c_char; + fmt = (fmt as usize + 1) as *mut c_char; + let mut t = timefmt; + let mut n = 1; + while *fmt != 0 { + if *fmt == b'(' as c_char { + n += 1; + } else if *fmt == b')' as c_char { + n -= 1; + } + if n == 0 { + break; + } + *t = *fmt; + t = (t as usize + 1) as *mut c_char; + fmt = (fmt as usize + 1) as *mut c_char; + } + *t = b'\0' as c_char; + fmt = (fmt as usize + 1) as *mut c_char; + if *fmt != b'T' as c_char { + builtin_warning("`%c': invalid time format specification\0".as_ptr() as *const c_char, *fmt as c_int); + fmt = start; + libc::free(timefmt as *mut c_void); + PC(*fmt as u8); + continue; + } + if *timefmt == b'\0' as c_char { + *timefmt = b'%' as c_char; + *((timefmt as usize + 1) as *mut c_char) = b'X' as c_char; + *((timefmt as usize + 2) as *mut c_char) = b'\0' as c_char; + } + + let arg = if !garglist.is_null() {getintmax()} else {-1}; + let mut secs: libc::time_t; + if arg == -1 { + secs = libc::time(0 as *mut libc::time_t); + } else if arg == -2 { + secs = shell_start_time; + } else { + secs = arg; + } + + sv_tz("TZ\0".as_ptr() as *mut c_char); + let mut tm = libc::localtime(std::mem::transmute(&secs)); + if tm.is_null() { + secs = 0; + tm = libc::localtime(std::mem::transmute(&secs)); + } + let mut timebuf:[c_char; 128] = [0; 128]; + let mut n: c_int = if !tm.is_null() {strftime(timebuf.as_ptr() as *mut c_char, 128, timefmt, tm) as c_int} else {0}; + libc::free(timefmt as *mut c_void); + if n == 0 { + timebuf[0] = b'\0' as c_char; + } else { + timebuf[127] = b'\0' as c_char; + } + + *modstart = b's' as c_char; + *((modstart as usize + 1) as *mut c_char) = b'\0' as c_char; + n = printstr(start, timebuf.as_ptr() as *mut c_char, libc::strlen(timebuf.as_ptr()) as c_int, fieldwidth, precision); + if n < 0 { + if libc::ferror(stdout) == 0 { + sh_wrerror(); + libc::clearerr(stdout); + } + return PRETURN(EXECUTION_FAILURE); + } + } + b'n' => { + let var = getstr(); + if !var.is_null() && *var != 0 { + if legal_identifier(var) != 0 { + bind_var_to_int(var, tw); + } else { + sh_invalidid(var); + return PRETURN(EXECUTION_FAILURE); + } + } + } + b'b' => { + let mut rlen: c_int = 0; + let mut r: c_int = 0; + ch = 0; + let p = getstr(); + let xp = bexpand(p, libc::strlen(p) as c_int, std::mem::transmute(&ch), std::mem::transmute(&rlen)); + if !xp.is_null() { + r = printstr(start, xp, rlen, fieldwidth, precision); + if r < 0 { + if libc::ferror(stdout) == 0 { + sh_wrerror(); + libc::clearerr(stdout); + } + retval = EXECUTION_FAILURE; + } + libc::free(xp as *mut c_void); + } + if ch != 0 || r < 0 { + return PRETURN(retval); + } + } + b'q' => { + let mut r: c_int = 0; + let xp: *mut c_char; + let p = getstr(); + if !p.is_null() && *p == 0 { + xp = savestring(b"''\0".as_ptr() as *const c_char); + } else if ansic_shouldquote(p) != 0 { + xp = ansic_quote(p, 0, PT_NULL as *mut c_int); + } else { + xp = sh_backslash_quote(p, PT_NULL as *mut c_char, 3); + } + if !xp.is_null() { + r = printstr(start, xp, libc::strlen(xp) as c_int, fieldwidth, precision); + if r < 0 { + if libc::ferror(stdout) == 0 { + sh_wrerror(); + libc::clearerr(stdout); + } + libc::free(xp as *mut c_void); + } + } + if r < 0 { + return PRETURN(EXECUTION_FAILURE); + } + } + b'd' | b'i' => { + let f = mklong(start, "l\0".as_ptr() as *mut c_char, 1); + let p = getintmax(); + libc::clearerr(stdout); + let PF = || { + let nw: c_int; + if vflag == 0 { + if have_fieldwidth != 0 && have_precision != 0 { + nw = libc::printf(f, fieldwidth, precision, p); + } else if have_fieldwidth != 0 { + nw = libc::printf(f, fieldwidth, p); + } else if have_precision != 0 { + nw = libc::printf(f, precision, p); + } else { + nw = libc::printf(f, p); + } + } else { + let vbsnprintf2 = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf1 = |x: c_int| { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + if have_fieldwidth != 0 && have_precision != 0 { + nw = vbsnprintf2(); + } else if have_fieldwidth != 0 { + nw = vbsnprintf1(fieldwidth); + } else if have_precision != 0 { + nw = vbsnprintf1(precision); + } else { + nw = vbsnprintf(); + } + } + tw += nw as c_long; + }; + PF(); + QUIT(); + if libc::ferror(stdout) != 0 { + sh_wrerror(); + libc::clearerr(stdout); + return EXECUTION_FAILURE; + } + } + b'o' | b'u' | b'x' | b'X' => { + let f = mklong(start, "l\0".as_ptr() as *mut c_char, 1); + let p = getuintmax(); + libc::clearerr(stdout); + let PF = || { + let nw: c_int; + if vflag == 0 { + if have_fieldwidth != 0 && have_precision != 0 { + nw = libc::printf(f, fieldwidth, precision, p); + } else if have_fieldwidth != 0 { + nw = libc::printf(f, fieldwidth, p); + } else if have_precision != 0 { + nw = libc::printf(f, precision, p); + } else { + nw = libc::printf(f, p); + } + } else { + let vbsnprintf2 = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf1 = |x: c_int| { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + if have_fieldwidth != 0 && have_precision != 0 { + nw = vbsnprintf2(); + } else if have_fieldwidth != 0 { + nw = vbsnprintf1(fieldwidth); + } else if have_precision != 0 { + nw = vbsnprintf1(precision); + } else { + nw = vbsnprintf(); + } + } + tw += nw as c_long; + }; + PF(); + QUIT(); + if libc::ferror(stdout) != 0 { + sh_wrerror(); + libc::clearerr(stdout); + return EXECUTION_FAILURE; + } + } + b'e' | b'E' | b'f' | b'F' | b'g' | b'G' | b'a' | b'A' => { + let p = getfloatmax(); + let f = mklong(start, "L\0".as_ptr() as *mut c_char, 1); + libc::clearerr(stdout); + let PF = || { + let nw: c_int; + if vflag == 0 { + if have_fieldwidth != 0 && have_precision != 0 { + nw = libc::printf(f, fieldwidth, precision, p); + } else if have_fieldwidth != 0 { + nw = libc::printf(f, fieldwidth, p); + } else if have_precision != 0 { + nw = libc::printf(f, precision, p); + } else { + nw = libc::printf(f, p); + } + } else { + let vbsnprintf2 = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, have_fieldwidth, have_precision, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf1 = |x: c_int| { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, x, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + let vbsnprintf = || { + let mut blen: c_int; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen > vbsize { + vbsize = ((nlen as size_t + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + blen = libc::snprintf((vbuf as usize + vblen as usize) as *mut c_char, vbsize - vblen as usize, f, p); + } + vblen += blen; + *((vbuf as usize + vblen as usize) as *mut c_char) = b'0' as c_char; + blen + }; + if have_fieldwidth != 0 && have_precision != 0 { + nw = vbsnprintf2(); + } else if have_fieldwidth != 0 { + nw = vbsnprintf1(fieldwidth); + } else if have_precision != 0 { + nw = vbsnprintf1(precision); + } else { + nw = vbsnprintf(); + } + } + tw += nw as c_long; + }; + PF(); + QUIT(); + if libc::ferror(stdout) != 0 { + sh_wrerror(); + libc::clearerr(stdout); + return EXECUTION_FAILURE; + } + } + _ => { + builtin_error("`%c': invalid format character\0".as_ptr() as *const c_char, convch as c_int); + return PRETURN(EXECUTION_FAILURE); + } + } + + *modstart = thisch; + *((modstart as usize + 1) as *mut c_char) = nextch; + + fmt = (fmt as usize + 1) as *mut c_char; + } + + if libc::ferror(stdout) != 0 { + return PRETURN(EXECUTION_FAILURE); + } + + if !garglist.is_null() && garglist != (*list).next { + continue 'outer; + } else { + break 'outer; + } + } + + if conversion_error != 0 { + retval = EXECUTION_FAILURE; + } + + return PRETURN(retval); +} +} + +fn hexvalue(c: u8) -> c_int +{ + return ( + if (c) >= b'a' && (c) <= b'f' { + (c) - b'a' + 10 + } else if (c) >= b'A' && (c) <= b'F' { + (c) - b'A' + 10 + } else { + (c) - b'0' + }) as i32 +} + +unsafe fn printstr(mut fmt: *mut c_char, mut string: *mut c_char, len: c_int, fieldwidth: c_int, precision: c_int) -> c_int +{ + if string.is_null() { + string = "\0".as_ptr() as *mut c_char; + } + + if *fmt == b'%' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + } + + let mut ljust: c_int = 0; + let mut fw: c_int = 0; + let mut mfw: c_long = 0; + let mut pr: c_int = -1; + let mut mpr: c_long = -1; + + while !(strchr("#'-+ 0\0".as_ptr() as *const c_char, *fmt as c_int).is_null()) { + if *fmt == b'-' as c_char { + ljust = 1; + } + fmt = (fmt as usize + 1) as *mut c_char; + } + + if *fmt == b'*' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + fw = fieldwidth; + if fw < 0 { + fw = -fw; + ljust = 1; + } + } else if IS_DIGITAL!(*fmt) { + mfw = (*fmt - b'0' as c_char) as c_long; + fmt = (fmt as usize + 1) as *mut c_char; + while IS_DIGITAL!(*fmt) { + mfw = mfw * 10 + (*fmt - b'0' as c_char) as c_long; + fmt = (fmt as usize + 1) as *mut c_char; + } + fw = if mfw < 0 || mfw > (libc::INT_MAX as c_long) {libc::INT_MAX} else {mfw as c_int}; + } + + if *fmt == b'.' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + if *fmt == b'*' as c_char { + fmt = (fmt as usize + 1) as *mut c_char; + pr = precision; + } else if IS_DIGITAL!(*fmt) { + mpr = (*fmt - b'0' as c_char) as c_long; + fmt = (fmt as usize + 1) as *mut c_char; + while IS_DIGITAL!(*fmt) { + mpr = mpr * 10 + (*fmt - b'0' as c_char) as c_long; + fmt = (fmt as usize + 1) as *mut c_char; + } + pr = if mpr < 0 || mpr > (libc::INT_MAX as c_long) {libc::INT_MAX} else {mpr as c_int}; + } else { + pr = 0; + } + } + + let nc = if pr >= 0 && pr <= len {pr} else {len}; + let mut padlen = fw - nc; + if padlen < 0 { + padlen = 0; + } + if ljust != 0 { + padlen = -padlen; + } + + while padlen > 0 { + PC(b' '); + padlen -= 1; + } + + for i in 0..nc { + PC(*((string as usize + i as usize) as *mut c_char) as u8); + } + + return 0; +} + +unsafe fn tescape(estart: *mut c_char, cp:*mut c_char, lenp: *mut c_int, sawc: *mut c_int) -> c_int +{ + + let mut p: *mut c_char = estart; + let mut evalue: c_int; + let mut temp: c_int; + let mut uvalue: c_ulong; + if !lenp.is_null() { + *lenp = 1; + } + + let c = *p as u8; + p = (p as usize + 1) as *mut c_char; + match c { + b'a' => *cp = 7, + b'b' => *cp = 8, + b'e' | b'E' => *cp = 27, + b'f' => *cp = 12, + b'n' => *cp = 10, + b'r' => *cp = 13, + b't' => *cp = 9, + b'v' => *cp = 11, + b'0'..=b'7' => { + evalue = (c - b'0') as c_int; + temp = 2 + (evalue == 0 && !sawc.is_null()) as c_int; + while *p >= b'0' as c_char && *p <= b'7' as c_char && temp != 0 { + temp -= 1; + evalue = (evalue * 8) + (*p - b'0' as c_char) as c_int; + p = (p as usize + 1) as *mut c_char; + } + + *cp = (evalue & 0xff) as c_char; + } + b'x' => { + temp = 2; + evalue = 0; + while libc::isdigit(*p as c_int) != 0 && temp != 0 { + temp -= 1; + evalue = (evalue * 16) + hexvalue(*p as u8); + p = (p as usize + 1) as *mut c_char; + } + + if p as usize == (estart as usize + 1) { + builtin_error("missing hex digit for \\x\0".as_ptr() as *const c_char); + *cp = b'\\' as c_char; + return 0; + } + *cp = (evalue & 0xff) as c_char; + } + b'u' | b'U' => { + temp = if c == b'u' {4} else {8}; + uvalue = 0; + while libc::isdigit(*p as c_int) != 0 && temp != 0 { + temp -= 1; + uvalue = (uvalue * 16) + hexvalue(*p as u8) as c_ulong; + p = (p as usize + 1) as *mut c_char; + } + + if p as usize == (estart as usize + 1) { + builtin_error("missing unicode digit for \\%c\0".as_ptr() as *const c_char, c as c_int); + *cp = b'\\' as c_char; + return 0; + } + if uvalue <= 0x7f { + *cp = uvalue as c_char; + } else { + temp = u32cconv(uvalue, cp); + *((cp as usize + temp as usize) as *mut c_char) = b'\0' as c_char; + if !lenp.is_null() { + *lenp = temp; + } + } + } + b'\\' => *cp = c as c_char, + b'\'' | b'"' | b'?' => { + if sawc.is_null() { + *cp = c as c_char; + } else { + *cp = b'\\' as c_char; + return 0; + } + } + b'c' => { + if sawc.is_null() { + *sawc = 1; + } else { + *cp = b'\\' as c_char; + return 0; + } + } + _ => { + *cp = b'\\' as c_char; + return 0; + } + } + return (p as usize - estart as usize) as c_int; +} + +unsafe fn bexpand(string: *mut c_char, len: c_int, sawc: *mut c_int, lenp: *mut c_int) -> *mut c_char +{ + let mut mbch:[c_char; 25]; + let mut mblen: c_int = 0; + + let mut ret: *mut c_char; + let mut r: *mut c_char; + let mut s: *mut c_char; + let mut c: c_char; + + if string.is_null() || len == 0 { + if !sawc.is_null() { + *sawc = 0; + } + if !lenp.is_null() { + *lenp = 0; + } + ret = xmalloc(1) as *mut c_char; + *ret = b'\0' as c_char; + return ret; + } + + ret = xmalloc(len as size_t + 1) as *mut c_char; + r = ret; + s = string; + while !s.is_null() && *s != 0 { + c = *s as c_char; + s = (s as usize + 1) as *mut c_char; + if c != b'\\' as c_char || *s == b'\0' as c_char { + *r = c; + r = (r as usize + 1) as *mut c_char; + continue; + } + + let mut temp: c_int = 0; + mbch = [0; 25]; + let n = tescape(s, mbch.as_mut_ptr() as *mut c_char, + std::mem::transmute(&mblen), std::mem::transmute(&temp)); + s = (s as usize + n as size_t) as *mut c_char; + + if temp != 0 { + if !sawc.is_null() { + *sawc = 1; + } + break; + } + + for mbind in 0..mblen { + *r = mbch[mbind as usize]; + r = (r as usize + 1) as *mut c_char; + } + } + + *r = b'\0' as c_char; + if !lenp.is_null() { + *lenp = (r as usize - ret as usize) as c_int; + } + + return ret; +} + +unsafe fn vbadd(buf: *mut c_char, blen: c_int) -> *mut c_char +{ + let nlen: size_t = vblen as size_t + blen as size_t + 1; + if nlen >= vbsize { + vbsize = ((nlen + 63) >> 6) << 6; + vbuf = xrealloc(vbuf as *mut c_void, vbsize) as *mut c_char; + } + + if blen == 1 { + *((vbuf as usize + vblen as usize) as *mut c_char) = *buf; + vblen += 1; + } else if blen > 1 { + libc::memcpy((vbuf as usize + vblen as usize) as *mut c_void, + buf as *mut c_void, blen as size_t); + vblen += blen; + } + *((vbuf as usize + vblen as usize) as *mut c_char) = b'\0' as c_char; + + return vbuf; +} + +unsafe fn printf_erange(s: *mut c_char) +{ + builtin_error("warning: %s: %s\0".as_ptr() as *const c_char, s, libc::strerror(libc::ERANGE)); +} + +unsafe fn mklong(str: *mut c_char, modifiers: *mut c_char, mlen: size_t) -> *mut c_char +{ + let slen = libc::strlen(str); + let len = slen + mlen + 1; + + if len > conv_bufsize { + conv_bufsize = ((len + 1023) >> 10) << 10; + conv_buf = libc::realloc(conv_buf as *mut c_void, conv_bufsize) as *mut c_char; + } + + libc::memcpy(conv_buf as *mut c_void, str as *mut c_void, slen - 1); + libc::memcpy((conv_buf as usize + slen - 1) as *mut c_void, modifiers as *mut c_void, mlen); + + *((conv_buf as usize + len - 2) as *mut c_char) = *((str as usize + slen - 1) as *mut c_char); + *((conv_buf as usize + len - 1) as *mut c_char) = b'\0' as c_char; + + return conv_buf; +} + +unsafe fn getchr() -> c_int +{ + if garglist.is_null() { + return b'\0' as c_int; + } + + let ret = *(*(*garglist).word).word as c_int; + garglist = (*garglist).next; + return ret; +} + +unsafe fn getstr() -> *mut c_char +{ + if garglist.is_null() { + return "\0".as_ptr() as *mut c_char; + } + + let ret = (*(*garglist).word).word; + garglist = (*garglist).next; + return ret; +} + +unsafe fn getint() -> c_int +{ + let mut ret = getintmax(); + + if garglist.is_null() { + return ret as c_int; + } + + if ret > libc::INT_MAX as c_long{ + printf_erange((*(*garglist).word).word); + ret = libc::INT_MAX as c_long; + } else if ret < libc::INT_MIN as c_long{ + printf_erange((*(*garglist).word).word); + ret = libc::INT_MIN as c_long; + } + + return ret as c_int; +} + +unsafe fn getintmax() -> c_long +{ + if garglist.is_null() { + return 0; + } + + if *(*(*garglist).word).word == b'\'' as c_char || + *(*(*garglist).word).word == b'"' as c_char { + return asciicode(); + } + + let mut ep: *mut c_char = PT_NULL as *mut c_char; + *libc::__errno_location() = 0; + let ret = libc::strtol((*(*garglist).word).word, std::mem::transmute(&ep), 0); + if *ep != 0 { + sh_invalidnum((*(*garglist).word).word); + conversion_error = 1; + } else if *libc::__errno_location() == libc::ERANGE { + printf_erange((*(*garglist).word).word); + } + garglist = (*garglist).next; + return ret; +} + +unsafe fn getuintmax() -> c_ulong +{ + if garglist.is_null() { + return 0; + } + + if *(*(*garglist).word).word == b'\'' as c_char || + *(*(*garglist).word).word == b'"' as c_char { + return asciicode() as c_ulong; + } + + *libc::__errno_location() = 0; + let mut ep: *mut c_char = PT_NULL as *mut c_char; + let ret = libc::strtoul((*(*garglist).word).word, std::mem::transmute(&ep), 0); + if *ep != 0 { + sh_invalidnum((*(*garglist).word).word); + conversion_error = 1; + } else if *libc::__errno_location() == libc::ERANGE { + printf_erange((*(*garglist).word).word); + } + garglist = (*garglist).next; + return ret; +} + +unsafe fn getfloatmax() -> f64 +{ + let ep: *mut c_char = PT_NULL as *mut c_char; + + if garglist.is_null() { + return 0.0; + } + + if *(*(*garglist).word).word == b'\'' as c_char || + *(*(*garglist).word).word == b'\"' as c_char { + return asciicode() as f64; + } + + *libc::__errno_location() = 0; + let ret = libc::strtod((*(*garglist).word).word, std::mem::transmute(&ep)); + if *ep != 0 { + sh_invalidnum((*(*garglist).word).word); + conversion_error = 1; + } else if *libc::__errno_location() == libc::ERANGE { + printf_erange((*(*garglist).word).word); + } + + garglist = (*garglist).next; + + return ret; +} + +unsafe fn asciicode() -> c_long +{ + let ch: c_long; + //let state: mbstate_t = std::mem::zeroed(); + let slen = libc::strlen((*(*garglist).word).word); + let wc: libc::wchar_t = 0; + let mblength = mbtowc(std::mem::transmute(&wc), ((*(*garglist).word).word as usize + 1) as *mut c_char, slen); + if mblength > 0 { + ch = wc as c_long; + } else { + ch = *(((*(*garglist).word).word as usize + 1) as *mut c_char) as c_long; + } + + garglist = (*garglist).next; + + return ch; +} diff --git a/bash-5.1/builtins_rust/pushd/Cargo.toml b/bash-5.1/builtins_rust/pushd/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..79419da6071e7120a818c3f1a7f6df14a17913e4 --- /dev/null +++ b/bash-5.1/builtins_rust/pushd/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["huzhengming"] +name = "rpushd" +version = "0.0.1" +#build = "../build.rs" +edition = "2018" + + +[dependencies] +lazy_static = "1.4.0" +libc = "0.2" +nix = "0.23.0" + +[lib] +crate-type = ["cdylib"] +name = "rpushd" diff --git a/bash-5.1/builtins_rust/pushd/src/lib.rs b/bash-5.1/builtins_rust/pushd/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..bd0783c7e3aeac783f7bbd15f41694604185f1e3 --- /dev/null +++ b/bash-5.1/builtins_rust/pushd/src/lib.rs @@ -0,0 +1,972 @@ +extern crate libc; +extern crate nix; + +use libc::{c_char, c_long, c_void}; +use std::{ffi::CString}; + +#[repr(C)] +pub struct WORD_DESC { + pub word: *mut libc::c_char, + pub flags:libc::c_int +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub struct WORD_LIST { + next: *mut WORD_LIST, + word: *mut WORD_DESC +} + +#[repr(u8)] +enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select, + cm_connection, cm_function_def, cm_until, cm_group, + cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc +} + +#[repr(u8)] +#[derive(Copy,Clone)] +enum r_instruction { + r_output_direction, r_input_direction, r_inputa_direction, + r_appending_to, r_reading_until, r_reading_string, + r_duplicating_input, r_duplicating_output, r_deblank_reading_until, + r_close_this, r_err_and_out, r_input_output, r_output_force, + r_duplicating_input_word, r_duplicating_output_word, + r_move_input, r_move_output, r_move_input_word, r_move_output_word, + r_append_err_and_out +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub union REDIRECTEE { + dest:libc::c_int, + filename:* mut WORD_DESC +} + +#[repr(C)] +pub union REDIRECT { + next:*mut REDIRECT, + redirector:REDIRECTEE, + rflags:libc::c_int, + flags:libc::c_int, + instruction:r_instruction, + redirectee:REDIRECTEE, + here_doc_eof:*mut c_char +} + +/* FOR command. */ +#[repr(C)] +pub struct for_com { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct PATTERN_LIST { + next:* mut PATTERN_LIST, + patterns:* mut WORD_LIST, + action:*mut COMMAND, + flags:libc::c_int +} + +#[repr(C)] +pub struct case_com { + flags:libc::c_int, + line:libc::c_int, + word:*mut WORD_DESC, + clauses:*mut PATTERN_LIST +} + +#[repr(C)] +pub struct while_com { + flags:libc::c_int, + test:*mut COMMAND, + action:*mut COMMAND +} + +#[repr(C)] +pub struct if_com { + flags:libc::c_int, + test:*mut COMMAND, + true_case:*mut COMMAND, + false_case:*mut COMMAND +} + +#[repr(C)] +pub struct connection { + ignore:libc::c_int, + first:*mut COMMAND, + second:*mut COMMAND, + connector:libc::c_int +} + +#[repr(C)] +pub struct simple_com { + flags:libc::c_int, + line:libc::c_int, + words:*mut WORD_LIST, + redirects:*mut REDIRECT +} + +#[repr(C)] +pub struct function_def { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + command:*mut COMMAND, + source_file:*mut c_char +} + +#[repr(C)] +pub struct group_com { + ignore:libc::c_int, + command:*mut COMMAND, + source_file:*mut c_char +} + +#[repr(C)] +pub struct select_com { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct arith_com { + flags:libc::c_int, + line:libc::c_int, + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct cond_com { + flags:libc::c_int, + line:libc::c_int, + type_c:libc::c_int, + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct arith_for_com { + flags:libc::c_int, + line:libc::c_int, + init:*mut WORD_LIST, + test:*mut WORD_LIST, + step:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct subshell_com { + flags:i32, + line:i32, + command:*mut COMMAND +} + +#[repr(C)] +pub struct coproc_com { + flags:i32, + name:*mut c_char, + command:*mut COMMAND +} + +#[repr(C)] +pub union VALUE_COMMAND { + For:*mut for_com, + Case:*mut case_com, + While:*mut while_com, + If:*mut if_com, + Connection:*mut connection, + Simple:*mut simple_com, + Function_def:*mut function_def, + Group:*mut group_com, + Select:*mut select_com, + Arith:*mut arith_com, + Cond:*mut cond_com, + ArithFor:*mut arith_for_com, + Subshell:*mut subshell_com, + Coproc:*mut coproc_com +} + +#[repr(C)] +pub struct COMMAND { + type_c:command_type, + flags:i32, + line:i32, + redirects:*mut REDIRECT, + value:VALUE_COMMAND +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => {1} +} + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => { + 0 + } +} + +#[macro_export] +macro_rules! NOCD { + () => { + 0x01 + } +} + +#[macro_export] +macro_rules! ROTATE { + () => { + 0x02 + } +} + +#[macro_export] +macro_rules! LONGFORM { + () => { + 0x04 + } +} + +#[macro_export] +macro_rules! CLEARSTAK { + () => { + 0x08 + } +} + +extern "C" { + fn builtin_help (); + fn builtin_error(err:*const c_char,...); + fn get_working_directory (path:* mut c_char)-> * mut c_char; + fn sh_invalidopt (value:* mut c_char); + fn builtin_usage(); + fn sh_invalidnum (value:* mut c_char); + fn legal_number (str1:* const c_char, num:* mut libc::c_long)->i32; + fn cd_builtin (list:*mut WORD_LIST)->i32; + fn polite_directory_format (path:* mut c_char)->* mut c_char; + fn sh_erange (str1:* mut c_char, str2:* mut c_char); + fn make_word_list (w: * mut WORD_DESC , l: * mut WORD_LIST)->* mut WORD_LIST; + fn make_word (w:*const c_char)->* mut WORD_DESC; + fn dispose_words (l: * mut WORD_LIST); + fn strvec_resize (c:* mut * mut c_char, s:i32)->* mut * mut c_char; + fn get_string_value (w:*const c_char)-> * mut c_char; + fn sh_chkwrite (i:i32)->i32; +} +pub static mut pushd_directory_list:* mut * mut c_char=std::ptr::null_mut(); +pub static mut directory_list_offset:i32=0; +pub static mut directory_list_size:i32=0; + +unsafe fn STREQ( a:* const c_char, b:* const c_char)->bool +{ + return *a ==*b && libc::strcmp(a, b) == 0; +} + +unsafe fn ISHELP(s:* const c_char)->bool +{ + return STREQ (s, CString::new("--help").unwrap().as_ptr()); +} + +unsafe fn ISOPTION(s:* const c_char, c:c_char)->bool +{ + return *s == '-' as c_char && *((s as usize + 1)as * mut c_char) == c && *((s as usize + 8)as * mut c_char) != 0; +} + +unsafe fn savestring(x:* const c_char)->* mut c_char +{ + let str1:* mut c_char=libc::malloc(1 + libc::strlen (x )) as * mut c_char; + return libc::strcpy(str1,x ); +} + +#[no_mangle] +pub extern "C" fn r_pushd_builtin (listt:* mut WORD_LIST)->i32 +{ + let orig_list:* mut WORD_LIST; + let mut temp:* mut c_char; + let current_directory:* mut c_char; + let mut top:* mut c_char; + let mut j:i32; + let mut flags:i32; + let skipopt:i32; + let mut num:libc::c_long=0; + let mut direction:c_char; + + unsafe { + let mut list:* mut WORD_LIST=listt.clone(); + orig_list = list.clone(); + + if list != std::ptr::null_mut() && (*list).word != std::ptr::null_mut() && ISHELP((*((*list).word)).word) { + builtin_help (); + return EX_USAGE!(); + } + + if list != std::ptr::null_mut() && (*list).word != std::ptr::null_mut() && ISOPTION ((*((*list).word)).word, '-' as c_char) { + list = (*list).next; + skipopt = 1; + } else { + skipopt = 0; + } + + /* If there is no argument list then switch current and + top of list. */ + if list == std::ptr::null_mut() { + if directory_list_offset == 0 { + builtin_error (CString::new("no other directory").unwrap().as_ptr()); + return EXECUTION_FAILURE!(); + } + + current_directory = get_working_directory (CString::new("pushd").unwrap().as_ptr() as * mut c_char); + if current_directory == std::ptr::null_mut() { + return EXECUTION_FAILURE!(); + } + + j = directory_list_offset - 1; + temp = *((pushd_directory_list as usize + (j*8) as usize) as * mut *mut c_char); + *((pushd_directory_list as usize + (j*8) as usize) as * mut *mut c_char) = current_directory; + j = r_change_to_temp (temp); + libc::free (temp as * mut c_void); + return j; + } + + flags = 0; + + while skipopt == 0 && list !=std::ptr::null_mut() { + if ISOPTION ((*((*list).word)).word, 'n' as c_char) { + flags |= NOCD!(); + } else if ISOPTION ((*((*list).word)).word, '-' as c_char) { + list = (*list).next; + break; + } else if *((*((*list).word)).word) == '-' as c_char && *(((*((*list).word)).word as usize +1) as * mut c_char) == '\0' as c_char { + /* Let `pushd -' work like it used to. */ + break; + } else { + direction = *((*((*list).word)).word); + if direction == '+' as c_char || direction == '-' as c_char { + if legal_number (((*((*list).word)).word as usize +1) as * mut c_char, &mut num) == 0 { + sh_invalidnum ((*((*list).word)).word); + builtin_usage (); + return EX_USAGE!(); + } + + if direction == '-' as c_char { + num = directory_list_offset as libc::c_long - num; + } + + if num > directory_list_offset as libc::c_long || num < 0 { + r_pushd_error (directory_list_offset, (*((*list).word)).word); + return EXECUTION_FAILURE!(); + } + flags |= ROTATE!(); + } else if *((*((*list).word)).word)== '-' as c_char { + sh_invalidopt ((*((*list).word)).word); + builtin_usage (); + return EX_USAGE!(); + } else { + break; + } + } + list = (*list).next; + } + + if (flags & ROTATE!()) != 0 { + /* Rotate the stack num times. Remember, the current + directory acts like it is part of the stack. */ + temp = get_working_directory (CString::new("pushd").unwrap().as_ptr() as * mut c_char); + + if num == 0 { + if (flags & NOCD!()) == 0 { + j=r_change_to_temp (temp); + } else { + j=EXECUTION_SUCCESS!(); + } + + libc::free (temp as * mut c_void); + return j; + } + + { + top = *((pushd_directory_list as usize + ((directory_list_offset - 1)*8) as usize ) as * mut * mut c_char); + j = directory_list_offset - 2; + + while j > -1 { + *((pushd_directory_list as usize + ((j +1)*8) as usize ) as * mut * mut c_char) =*((pushd_directory_list as usize + (j*8) as usize ) as * mut * mut c_char); + j-=1; + } + + *((pushd_directory_list as usize + ((j +1)*8) as usize ) as * mut * mut c_char)=temp; + + temp = top; + num-=1; + } + + while num != 0 { + top = *((pushd_directory_list as usize + ((directory_list_offset - 1)*8) as usize ) as * mut * mut c_char); + j = directory_list_offset - 2; + + while j > -1 { + *((pushd_directory_list as usize + ((j +1)*8) as usize ) as * mut * mut c_char) =*((pushd_directory_list as usize + (j*8) as usize ) as * mut * mut c_char); + j-=1; + } + + *((pushd_directory_list as usize + ((j +1)*8) as usize ) as * mut * mut c_char)=temp; + + temp = top; + num-=1; + } + + if (flags & NOCD!()) == 0 { + j=r_change_to_temp (temp); + } else { + j=EXECUTION_SUCCESS!(); + } + + libc::free (temp as * mut c_void); + return j; + } + + if list == std::ptr::null_mut() { + return EXECUTION_SUCCESS!(); + } + + /* Change to the directory in list->word->word. Save the current + directory on the top of the stack. */ + current_directory = get_working_directory (CString::new("pushd").unwrap().as_ptr() as * mut c_char); + if current_directory == std::ptr::null_mut() { + return EXECUTION_FAILURE!(); + } + + if (flags & NOCD!()) == 0 { + if skipopt !=0 { + j=cd_builtin(orig_list); + } else { + j=cd_builtin(list); + } + } else { + j=EXECUTION_SUCCESS!(); + } + + if j == EXECUTION_SUCCESS!() { + if (flags & NOCD!()) !=0 { + r_add_dirstack_element(savestring ((*((*list).word)).word)); + } else { + r_add_dirstack_element(current_directory); + } + + r_dirs_builtin (std::ptr::null_mut()); + if (flags & NOCD!()) != 0 { + libc::free (current_directory as * mut c_void); + } + return EXECUTION_SUCCESS!(); + } else { + libc::free (current_directory as * mut c_void); + return EXECUTION_FAILURE!(); + } + } +} + +/* Pop the directory stack, and then change to the new top of the stack. + If LIST is non-null it should consist of a word +N or -N, which says + what element to delete from the stack. The default is the top one. */ +#[no_mangle] +pub extern "C" fn r_popd_builtin (listt:* mut WORD_LIST)->i32 { +let mut i:i32; +let mut which:libc::c_long; +let mut flags:i32; +let mut direction:c_char; +let mut which_word:* mut c_char; + +unsafe { +let mut list:* mut WORD_LIST=listt.clone(); +if list != std::ptr::null_mut() && (*list).word != std::ptr::null_mut() && ISHELP((*((*list).word)).word) { + builtin_help (); + return EX_USAGE!(); +} + +which_word = std::ptr::null_mut(); +flags = 0; +which = 0; +direction = '+' as c_char; +while list != std::ptr::null_mut() { + if ISOPTION ((*((*list).word)).word, 'n' as c_char){ + flags |= NOCD!(); + } else if ISOPTION ((*((*list).word)).word, '-' as c_char) { + list = (*list).next; + break; + } else { + direction = *((*((*list).word)).word); + if direction == '+' as c_char || direction == '-' as c_char { + + if legal_number ((((*((*list).word)).word as usize + 1) as * mut c_char), & mut which) == 0 { + sh_invalidnum ((*((*list).word)).word); + builtin_usage (); + return EX_USAGE!(); + } + which_word = (*((*list).word)).word; + } else if *((*((*list).word)).word) == '-' as c_char { + sh_invalidopt ((*((*list).word)).word); + builtin_usage (); + return EX_USAGE!(); + } else if (*((*list).word)).word != std::ptr::null_mut() { + builtin_error (CString::new("%s: invalid argument").unwrap().as_ptr() as * mut c_char, (*((*list).word)).word); + builtin_usage (); + return EX_USAGE!(); + } else { + break; + } + } + list = (*list).next; +} + +if which > directory_list_offset as libc::c_long || (which < -directory_list_offset as libc::c_long) || (directory_list_offset == 0 && which == 0) { + if which_word !=std::ptr::null_mut() { + r_pushd_error (directory_list_offset, which_word); + } else { + r_pushd_error (directory_list_offset, CString::new("").unwrap().as_ptr() as * mut c_char); + } + return EXECUTION_FAILURE!(); +} + +/* Handle case of no specification, or top of stack specification. */ +if (direction == '+' as c_char && which == 0) || + (direction == '-' as c_char && which == directory_list_offset as libc::c_long) { + if (flags & NOCD!()) == 0 { + i=r_cd_to_string (*((pushd_directory_list as usize + ((directory_list_offset - 1)*8) as usize) as *mut *mut c_char)); + } else { + i=EXECUTION_SUCCESS!(); + } + + if i != EXECUTION_SUCCESS!() { + return i; + } + + directory_list_offset-=1; + + libc::free ((*((pushd_directory_list as usize + (directory_list_offset *8) as usize) as *mut *mut c_char)) as * mut c_void); + } else { + /* Since an offset other than the top directory was specified, + remove that directory from the list and shift the remainder + of the list into place. */ + if direction == '+' as c_char{ + i= directory_list_offset - which as i32; + } else { + i=which as i32; + } + + if i < 0 || i > directory_list_offset { + if which_word !=std::ptr::null_mut() { + r_pushd_error (directory_list_offset, which_word); + } else { + r_pushd_error (directory_list_offset, CString::new("").unwrap().as_ptr() as * mut c_char); + } + + return EXECUTION_FAILURE!(); + } + libc::free ((*((pushd_directory_list as usize + (i*8) as usize) as * mut * mut c_char)) as * mut c_void); + directory_list_offset-=1; + + /* Shift the remainder of the list into place. */ + while i < directory_list_offset { + *((pushd_directory_list as usize +(i*8) as usize) as * mut * mut c_char)=*((pushd_directory_list as usize +((i+1)*8) as usize) as * mut * mut c_char); + i+=1; + } + } + + r_dirs_builtin (std::ptr::null_mut()); + return EXECUTION_SUCCESS!(); +} +} + +/* Print the current list of directories on the directory stack. */ +#[no_mangle] +pub extern "C" fn r_dirs_builtin (listt:* mut WORD_LIST)->i32 +{ + let mut flags:i32=0; + let mut desired_index:i32=-1; + let mut index_flag:i32=0; + let mut vflag:i32=0; + let mut i:libc::c_long=0; + let mut temp:*mut c_char; + let mut w:* mut c_char=CString::new("").unwrap().as_ptr() as * mut c_char; + + unsafe { + let mut list:* mut WORD_LIST=listt.clone(); + if list != std::ptr::null_mut() && (*list).word != std::ptr::null_mut() && ISHELP((*((*list).word)).word) { + builtin_help (); + return EX_USAGE!(); + } + + while list != std::ptr::null_mut() { + if ISOPTION ((*((*list).word)).word, 'l' as c_char) { + flags |= LONGFORM!(); + } else if ISOPTION ((*((*list).word)).word, 'c' as c_char) { + flags |= CLEARSTAK!(); + } else if ISOPTION ((*((*list).word)).word, 'v' as c_char) { + vflag |= 2; + } else if ISOPTION ((*((*list).word)).word, 'p' as c_char) { + vflag |= 1; + } else if ISOPTION ((*((*list).word)).word, '-' as c_char) { + list = (*list).next; + break; + } else if *((*((*list).word)).word) == '+' as c_char || *((*((*list).word)).word) == '-' as c_char { + let sign:i32; + w = ((*((*list).word)).word as usize +1) as * mut c_char; + if legal_number (w, &mut i) == 0 { + sh_invalidnum ((*((*list).word)).word); + builtin_usage (); + return EX_USAGE!(); + } + + if *((*((*list).word)).word) == '+' as c_char { + sign = -1; + } else { + sign = -1; + } + + desired_index = r_get_dirstack_index (i, sign, &mut index_flag); + } else { + sh_invalidopt ((*((*list).word)).word); + builtin_usage (); + return EX_USAGE!(); + } + list=(*list).next + } + + if (flags & CLEARSTAK!()) !=0 { + r_clear_directory_stack (); + return EXECUTION_SUCCESS!(); + } + + if index_flag !=0 && (desired_index < 0 || desired_index > directory_list_offset) { + r_pushd_error (directory_list_offset, w); + return EXECUTION_FAILURE!(); + } + + /* The first directory printed is always the current working directory. */ + if index_flag == 0 || (index_flag == 1 && desired_index == 0) { + temp = get_working_directory (CString::new("dirs").unwrap().as_ptr() as * mut c_char); + if temp == std::ptr::null_mut() { + temp = savestring (CString::new("").unwrap().as_ptr() as * mut c_char); + } + + if (vflag & 2) !=0 { + if (flags & LONGFORM!()) !=0 { + libc::printf (CString::new("%2d %s").unwrap().as_ptr(), 0, temp); + } else { + libc::printf (CString::new("%2d %s").unwrap().as_ptr(), 0, polite_directory_format (temp)); + } + } else { + if (flags & LONGFORM!()) !=0 { + libc::printf (CString::new("%s").unwrap().as_ptr(), temp); + } else { + libc::printf (CString::new("%s").unwrap().as_ptr(), polite_directory_format (temp)); + } + } + + libc::free (temp as * mut c_void); + if index_flag !=0 { + libc::putchar ('\n' as libc::c_int); + return sh_chkwrite (EXECUTION_SUCCESS!()); + } + } + + /* Now print the requested directory stack entries. */ + if index_flag !=0 { + if (vflag & 2) !=0 { + if (flags & LONGFORM!()) !=0 { + libc::printf (CString::new("%2d %s").unwrap().as_ptr(), directory_list_offset - desired_index, + *((pushd_directory_list as usize + (desired_index*8) as usize) as * mut * mut c_char) ); + } else { + libc::printf (CString::new("%2d %s").unwrap().as_ptr(), directory_list_offset - desired_index, + polite_directory_format (*((pushd_directory_list as usize + (desired_index*8) as usize) as * mut * mut c_char))); + } + } else { + if (flags & LONGFORM!()) !=0 { + libc::printf (CString::new("%s").unwrap().as_ptr(), *((pushd_directory_list as usize + (desired_index*8) as usize) as * mut * mut c_char) ); + } else { + libc::printf (CString::new("%s").unwrap().as_ptr(), polite_directory_format (*((pushd_directory_list as usize + (desired_index*8) as usize) as * mut * mut c_char))); + } + } + } else { + i = (directory_list_offset - 1) as libc::c_long; + while i >= 0 { + if vflag >= 2 { + if (flags & LONGFORM!()) !=0 { + libc::printf (CString::new("\n%2d %s").unwrap().as_ptr(), directory_list_offset - i as i32 ,*((pushd_directory_list as usize + (i*8) as usize) as * mut * mut c_char) ); + } else { + libc::printf (CString::new("\n%2d %s").unwrap().as_ptr(),directory_list_offset - i as i32 ,polite_directory_format (*((pushd_directory_list as usize + (i*8) as usize) as * mut * mut c_char))); + } + } else { + if (flags & LONGFORM!()) !=0 { + if (vflag & 1) !=0 { + libc::printf (CString::new("%s%s").unwrap().as_ptr(),CString::new("\n").unwrap().as_ptr() as * mut c_char,*((pushd_directory_list as usize + (i*8) as usize) as * mut * mut c_char) ); + } else { + libc::printf (CString::new("%s%s").unwrap().as_ptr() , CString::new(" ").unwrap().as_ptr() as * mut c_char,*((pushd_directory_list as usize + (i*8) as usize) as * mut * mut c_char) ); + } + + } else { + if (vflag & 1) !=0 { + libc::printf (CString::new("%s%s").unwrap().as_ptr(), CString::new("\n").unwrap().as_ptr() as * mut c_char,polite_directory_format (*((pushd_directory_list as usize + (i*8) as usize) as * mut * mut c_char))); + } else { + libc::printf (CString::new("%s%s").unwrap().as_ptr() , CString::new(" ").unwrap().as_ptr() as * mut c_char,polite_directory_format (*((pushd_directory_list as usize + (i*8) as usize) as * mut * mut c_char))); + } + } + + } + i-=1; + } + } + + libc::putchar ('\n' as libc::c_int); + return sh_chkwrite (EXECUTION_SUCCESS!()); + } +} + +#[no_mangle] +pub extern "C" fn r_pushd_error (offset:i32, arg:* mut c_char) +{ + unsafe { + if offset == 0 { + builtin_error (CString::new("directory stack empty").unwrap().as_ptr()); + } else{ + sh_erange (arg, CString::new("directory stack index").unwrap().as_ptr() as * mut c_char); + } + } +} + +#[no_mangle] +pub extern "C" fn r_clear_directory_stack () +{ + let mut i:i32=0; + unsafe { + while i < directory_list_offset { + libc::free (*((pushd_directory_list as usize + (i*8) as usize) as * mut * mut c_char) as * mut c_void); + i+=1; + } + + directory_list_offset = 0; + } +} + +/* Switch to the directory in NAME. This uses the cd_builtin to do the work, + so if the result is EXECUTION_FAILURE then an error message has already + been printed. */ +#[no_mangle] +pub extern "C" fn r_cd_to_string (name:* mut c_char)->i32 +{ + unsafe { + let tlist:* mut WORD_LIST; + let dir:* mut WORD_LIST; + let result:i32; + + dir = make_word_list (make_word (name), std::ptr::null_mut()); + tlist = make_word_list (make_word (CString::new("--").unwrap().as_ptr()), dir); + result = cd_builtin (tlist); + dispose_words (tlist); + return result; + } +} + +#[no_mangle] +pub extern "C" fn r_change_to_temp (temp: * mut c_char)->i32 +{ + let tt:i32; + + if temp !=std::ptr::null_mut() { + tt = r_cd_to_string (temp); + } else { + tt= EXECUTION_FAILURE!(); + } + + if tt == EXECUTION_SUCCESS!() { + r_dirs_builtin (std::ptr::null_mut()); + } + + return tt; +} + +#[no_mangle] +pub extern "C" fn r_add_dirstack_element (dir:* mut c_char) +{ + unsafe { + if directory_list_offset == directory_list_size { + directory_list_size += 10; + pushd_directory_list = strvec_resize (pushd_directory_list, directory_list_size); + } + + *((pushd_directory_list as usize + (directory_list_offset*8) as usize ) as * mut * mut c_char) = dir; + directory_list_offset+=1; + } +} + +#[no_mangle] +pub extern "C" fn r_get_dirstack_index (ind:libc::c_long, sign:i32, indexp:* mut i32)->i32 +{ + unsafe { + if indexp !=std::ptr::null_mut(){ + if sign > 0 { + *indexp=1; + } else { + *indexp=0; + } + } + /* dirs +0 prints the current working directory. */ + /* dirs -0 prints last element in directory stack */ + if ind == 0 && sign > 0 { + return 0; + } else if ind == directory_list_offset as libc::c_long { + if indexp !=std::ptr::null_mut() { + if sign > 0 { + *indexp = 2; + } else { + *indexp = 1; + } + } + return 0; + } else if ind >= 0 && ind <= directory_list_offset as libc::c_long { + if sign > 0 { + return directory_list_offset - ind as i32; + } else { + return ind as i32; + } + } else { + return -1; + } + } +} + +/* Used by the tilde expansion code. */ +#[no_mangle] +pub extern "C" fn r_get_dirstack_from_string (strt:* mut c_char)-> * mut c_char +{ + let ind:i32; + let mut sign:i32; + let mut index_flag:i32; + let mut i:libc::c_long=0; + + sign = 1; + let mut str1=strt.clone(); + unsafe { + + if *str1 == '-' as c_char || *str1 == '+' as c_char { + if *str1 == '-' as c_char { + sign=-1; + } else { + sign=1; + } + str1=(str1 as usize + 1 ) as * mut c_char; + } + + if legal_number (str1, &mut i) == 0 { + return std::ptr::null_mut(); + } + + index_flag = 0; + ind = r_get_dirstack_index (i, sign, &mut index_flag); + if index_flag !=0 && (ind < 0 || ind > directory_list_offset) { + return std::ptr::null_mut(); + } + + if index_flag == 0 || (index_flag == 1 && ind == 0) { + return get_string_value (CString::new("PWD").unwrap().as_ptr()); + } else { + return *((pushd_directory_list as usize + (ind*8) as usize) as * mut * mut c_char); + } + } +} + +#[no_mangle] +pub extern "C" fn r_get_dirstack_element (ind:libc::c_long, sign:i32)-> * mut c_char +{ + let mut i:i32; + unsafe { + i = r_get_dirstack_index (ind, sign, std::ptr::null_mut()); + if i < 0 || i > directory_list_offset { + return std::ptr::null_mut(); + } else { + return *((pushd_directory_list as usize + (i*8) as usize) as * mut * mut c_char); + } + } +} + +#[no_mangle] +pub extern "C" fn r_set_dirstack_element (ind:libc::c_long, sign:i32, value:* mut c_char) +{ + let i:i32; + unsafe { + i = r_get_dirstack_index (ind, sign, std::ptr::null_mut()); + if ind == 0 || i < 0 || i > directory_list_offset { + return; + } + libc::free ((*((pushd_directory_list as usize + (i*8) as usize) as * mut * mut c_char)) as * mut c_void); + *((pushd_directory_list as usize + (i*8) as usize) as * mut * mut c_char) = savestring (value); + } +} + +#[no_mangle] +pub extern "C" fn r_get_directory_stack (flags:i32)->* mut WORD_LIST +{ + let mut i:i32; + let mut ret:* mut WORD_LIST; + let mut d:* mut c_char; + let t:* mut c_char; + unsafe { + ret = std::ptr::null_mut(); + i = 0; + while i < directory_list_offset { + if (flags&1) !=0 { + d=polite_directory_format (*((pushd_directory_list as usize + (i*8) as usize) as * mut * mut c_char)); + } else { + d=*((pushd_directory_list as usize + (i*8) as usize) as * mut * mut c_char) + } + ret = make_word_list (make_word (d), ret); + i+=1; + } + /* Now the current directory. */ + d = get_working_directory (CString::new("dirstack").unwrap().as_ptr() as * mut c_char); + i = 0; /* sentinel to decide whether or not to free d */ + if d == std::ptr::null_mut() { + d = CString::new(".").unwrap().as_ptr() as * mut c_char; + } else { + if (flags&1) !=0 { + t=polite_directory_format(d); + } else { + t=d; + } + /* polite_directory_format sometimes returns its argument unchanged. + If it does not, we can free d right away. If it does, we need to + mark d to be deleted later. */ + if t != d { + libc::free (d as * mut c_void); + d = t; + } else { /* t == d, so d is what we want */ + i = 1; + } + } + ret = make_word_list (make_word (d), ret); + if i !=0 { + libc::free (d as * mut c_void); + } + return ret; /* was (REVERSE_LIST (ret, (WORD_LIST *)); */ + } +} + +#[no_mangle] +pub extern "C" fn cmd_name() ->*const u8 { + return b"pushd" as *const u8; +} + +#[no_mangle] +pub extern "C" fn run(list : *mut WORD_LIST)->i32 { + return r_pushd_builtin(list); +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/read/Cargo.toml b/bash-5.1/builtins_rust/read/Cargo.toml index 79188cea38680aae347fe57d76492ca2d78524ef..3a5551fc696c98a3d17bd1a655dbd7c70efe5eb5 100644 --- a/bash-5.1/builtins_rust/read/Cargo.toml +++ b/bash-5.1/builtins_rust/read/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "read" version = "0.1.0" -edition = "2021" +edition = "2018" authors = ["lvgenggeng"] build = "../build.rs" @@ -9,7 +9,8 @@ build = "../build.rs" [lib] name = "rread" -crate-type = ["cdylib"] +#crate-type = ["cdylib"] +crate-type = ["staticlib","rlib"] [dependencies] libc = "0.2" diff --git a/bash-5.1/builtins_rust/read/src/intercdep.rs b/bash-5.1/builtins_rust/read/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..61985e931645181fcd38c714e40f2ab80e12901d --- /dev/null +++ b/bash-5.1/builtins_rust/read/src/intercdep.rs @@ -0,0 +1,320 @@ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +pub type SHELL_VAR = variable; + +pub type __intmax_t = c_long; +pub type intmax_t = __intmax_t; +pub type arrayind_t = intmax_t; +pub type sh_var_value_func_t = + ::std::option::Option *mut variable>; + + pub type sh_var_assign_func_t = ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut variable, + arg2: *mut c_char, + arg3: arrayind_t, + arg4: *mut c_char, + ) -> *mut variable, +>; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct variable { + pub name: *mut c_char, + pub value: *mut c_char, + pub exportstr: *mut c_char, + pub dynamic_value: sh_var_value_func_t, + pub assign_func: sh_var_assign_func_t, + pub attributes: c_int, + pub context: c_int, +} + +pub type __jmp_buf = [c_long; 8usize]; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct __sigset_t { + pub __val: [c_ulong; 16usize], +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct __jmp_buf_tag { + pub __jmpbuf: __jmp_buf, + pub __mask_was_saved: c_int, + pub __saved_mask: __sigset_t, +} + +pub type sigjmp_buf = [__jmp_buf_tag; 1usize]; + +pub type rl_hook_func_t = fn() -> c_int; +pub type rl_completion_func_t = fn(args1 : *const c_char, args2 : c_int) -> *mut *mut c_char; + +#[repr(C)] +#[derive(Copy, Clone)] +pub union __mbstate_t__bindgen_ty_1 { + pub __wch: c_uint, + pub __wchb: [c_char; 4], +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct __mbstate_t { + pub __count: c_int, + pub __value: __mbstate_t__bindgen_ty_1, +} +pub type mbstate_t = __mbstate_t; + +pub const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EINTR : c_int = 4; +pub const EX_USAGE : c_int = 258; + +pub const VA_NOEXPAND : c_int = 0x001; +pub const VA_ONEWORD : c_int = 0x002; + +pub const ISFUNC: c_int = 0; + +pub const MB_LEN_MAX: c_int = 16; + +pub const CTLESC: c_char = b'\x01' as c_char; +pub const CTLNUL: c_char = b'\x4f' as c_char; + +pub const __S_IFMT: u32 = 0o0170000; +pub const __S_IFREG: u32 = 0o0100000; + +extern "C" { + pub fn reset_internal_getopt(); + + pub fn internal_getopt( + arg1: *mut WORD_LIST, + arg2: *mut c_char, + ) -> c_int; + + pub fn list_string(s: *mut c_char, t: *mut c_char, i: c_int) -> *mut WORD_LIST; + pub fn dequote_string(s: *mut c_char) -> *mut c_char; + pub fn dequote_list(s: *mut WORD_LIST) -> *mut WORD_LIST; + pub fn word_list_remove_quoted_nulls(s: *mut WORD_LIST); + pub fn dispose_words(s: *mut WORD_LIST); + pub fn assign_array_var_from_word_list(var: *mut SHELL_VAR, list: *mut WORD_LIST, flags: c_int) -> *mut SHELL_VAR; + + pub fn builtin_usage(); + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + pub static mut assoc_expand_once : c_int; + pub static mut interactive_shell : c_int; + + pub static mut rl_num_chars_to_read: c_int; + pub static mut rl_attempted_completion_function : rl_completion_func_t; + + pub static mut bash_readline_initialized : c_int; + pub static mut rl_startup_hook: *mut rl_hook_func_t; + + pub static interrupt_state : c_int; + pub static terminating_signal : c_int; + pub static trapped_signal_received : c_int; + + pub static mut alrmbuf: sigjmp_buf; + + pub static mut rl_instream: *mut libc::FILE; + + pub static posixly_correct: c_int; + + pub static locale_utf8locale: c_int; + + pub static mut ifs_cmap: [u8; 256]; + + pub fn uconvert( + s: *mut c_char, + ip: *mut c_long, + up: *mut c_long, + ep: *mut *mut c_char, + ) -> c_int; + + pub fn builtin_error(arg1: *const c_char, ...); + + pub fn legal_number( + arg1: *const c_char, + arg2: *mut std::os::raw::c_long, + ) -> c_int; + + pub fn sh_invalidnum(arg1: *mut c_char); + + pub fn sh_validfd(arg1: c_int) -> c_int; + + pub fn input_avail(arg1: c_int) -> c_int; + + pub fn legal_identifier(arg1: *const c_char) -> c_int; + + pub fn valid_array_reference( + arg1: *const c_char, + arg2: c_int, + ) -> c_int; + + pub fn sh_invalidid(arg1: *mut c_char); + + pub fn getifs() -> *mut c_char; + + pub fn xmalloc(arg1: libc::size_t) -> *mut c_void; + + pub fn xfree(arg1: *mut c_void); + + pub fn xrealloc(arg1: *mut c_void, arg2: libc::size_t) + -> *mut c_void; + + pub fn get_string_value(arg1: *const c_char) -> *mut c_char; + + pub fn begin_unwind_frame(arg1: *mut c_char); + pub fn run_unwind_frame(arg1: *mut c_char); + pub fn discard_unwind_frame(arg1: *mut c_char); + + pub fn fd_is_bash_input(arg1: c_int) -> c_int; + + pub fn sync_buffered_stream(arg1: c_int) -> c_int; + + pub fn initialize_readline() -> c_void; + pub fn readline(p : *const c_char) -> *mut c_char; + pub fn rl_insert_text(p : *const c_char) -> c_int; + + pub fn bashline_set_event_hook() -> c_void; + pub fn bashline_reset_event_hook() -> c_void; + + pub fn zreadintr(arg1: c_int, arg2: *mut c_char, arg3: size_t) -> libc::ssize_t; + pub fn zreadcintr(arg1: c_int, arg2: *mut c_char) -> libc::ssize_t; + + pub fn zread(arg1: c_int, arg2: *mut c_char, arg3: size_t) -> libc::ssize_t; + pub fn zreadn(arg1: c_int, arg2: *mut c_char, arg3: size_t) -> libc::ssize_t; + pub fn zreadc(arg1: c_int, arg2: *mut c_char) -> libc::ssize_t; + + pub fn zsyncfd(fd: c_int) -> c_void; + + pub fn check_signals(); + pub fn termsig_handler(arg1: c_int) -> c_void; + pub fn throw_to_top_level() -> c_void; + + pub fn builtin_bind_variable(name: *mut c_char, value: *mut c_char, flags: c_int) -> *mut SHELL_VAR; + pub fn bind_variable(name: *const c_char, value: *mut c_char, flags: c_int) -> *mut SHELL_VAR; + pub fn find_or_make_array_variable(name: *mut c_char, flags: c_int) -> *mut SHELL_VAR; + + pub fn array_flush(a: *mut ARRAY); + + pub fn get_word_from_string(stringp: *mut *mut c_char, separators: *mut c_char, endptr: *mut *mut c_char) -> *mut c_char; + + pub fn stupidly_hack_special_variables(name: *mut c_char); + pub fn strip_trailing_ifs_whitespace(s: *mut c_char, sep: *mut c_char, es: c_int) -> *mut c_char; +} + +extern "C" { + pub fn initialize_terminating_signals(); +} + +pub type SigHandler = unsafe extern "C" fn(arg1: c_int); +extern "C" { + pub fn set_signal_handler(arg1: c_int, arg2: *mut SigHandler) -> *mut SigHandler; +} + +extern "C" { + // todo: more f type + pub fn add_unwind_protect(f : *mut c_void,...); + pub fn unwind_protect_mem(var : *mut c_int, size : c_int); + pub fn remove_unwind_protect() -> c_void; +} + +extern "C" { + pub fn falarm( + arg1: c_uint, + arg2: c_uint, + ) -> c_uint; +} + +extern "C" { + pub fn __sigsetjmp( + __env: *mut __jmp_buf_tag, + __savemask: c_int, + ) -> c_int; + + pub fn siglongjmp(__env: *mut __jmp_buf_tag, __val: c_int); + +} + +extern "C" { + pub fn ttgetattr(arg1: c_int, arg2: *mut libc::termios) -> c_int; + pub fn ttsetattr(arg1: c_int, arg2: *mut libc::termios) -> c_int; + + pub fn ttfd_noecho( + arg1: c_int, + arg2: *mut libc::termios, + ) -> c_int; + +} + +extern "C" { + pub fn sh_ttyerror(arg1: c_int); + pub fn ttfd_cbreak(fd: c_int, ttp: *mut libc::termios) -> c_int; + pub fn ttfd_onechar(fd: c_int, ttp: *mut libc::termios) -> c_int; +} + + +pub type rl_command_func_t = unsafe extern "C" fn(c_int, c_int) -> c_int; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct _keymap_entry { + pub tp: c_char, + pub function: rl_command_func_t, +} +pub type KEYMAP_ENTRY = _keymap_entry; +pub type Keymap = *mut KEYMAP_ENTRY; + +extern "C" { + pub fn rl_get_keymap() -> Keymap; + pub fn rl_insert(count: c_int, key: c_int) -> c_int; + pub fn rl_newline(count: c_int, key: c_int) -> c_int; + +} + +extern "C" { + pub fn mbrtowc(pwc: *mut libc::wchar_t, s: *mut c_char, n: libc::size_t, ps: *mut mbstate_t) -> libc::size_t; + pub fn mbrlen(mbstr: *const c_char, count: size_t, mbstate: *mut mbstate_t) -> c_int; +} + +pub const atype_array_indexed: atype = 0; +pub const atype_array_assoc: atype = 1; +pub type atype = c_uint; + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct array { + pub type_: atype, + pub max_index: arrayind_t, + pub num_elements: c_int, + pub head: *mut array_element, + pub lastref: *mut array_element, +} +pub type ARRAY = array; + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct array_element { + pub ind: arrayind_t, + pub value: *mut c_char, + pub next: *mut array_element, + pub prev: *mut array_element, +} +pub type ARRAY_ELEMENT = array_element; diff --git a/bash-5.1/builtins_rust/read/src/lib.rs b/bash-5.1/builtins_rust/read/src/lib.rs index 3c47a31b6e18d7599265e43ca381506b18a42308..8015ec1bdb1e8a163b80b63470ef4306b9fbb214 100644 --- a/bash-5.1/builtins_rust/read/src/lib.rs +++ b/bash-5.1/builtins_rust/read/src/lib.rs @@ -1,35 +1,1008 @@ +use libc::{c_int, c_char, c_long, c_ulong, c_uint, size_t, c_void, PT_NULL, ssize_t}; +use nix::errno::errno; +use std::{ffi::{CString, CStr}, ptr::null_mut}; -use libc::{F_UNLCK, c_char, c_long}; -use std::ffi::CString; +include!(concat!("intercdep.rs")); -#[repr(C)] -pub struct WORD_DESC { - pub word: *mut libc::c_char, - pub flags:libc::c_int +static mut old_alrm : *mut SigHandler = PT_NULL as *mut SigHandler; + +static mut sigalrm_seen : c_int = 0; +static mut reading : c_int = 0; +static mut tty_modified : c_int = 0; + +static mut delim : c_char= b'\n' as c_char; +#[derive(Clone, Copy)] +pub struct tty_save { + fd: i32, + attrs: libc::termios, } -#[repr(C)] -#[derive(Copy,Clone)] -pub struct WORD_LIST { - next: *mut WORD_LIST, - word: *mut WORD_DESC +static mut termsave : Option = None; +static mut ptermsave: *mut c_void = PT_NULL as *mut c_void; + +static mut interactive : c_int = 0; +static mut default_buffered_input : c_int = -1; + +#[no_mangle] +pub extern "C" fn r_read_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_read_builtin call"); + + let mut varname :*mut c_char = libc::PT_NULL as *mut c_char; + let mut size : c_int = 0; + let mut nr : c_int = 0; + let mut pass_next : c_int = 0; + let mut saw_escape : c_int = 0; + let mut eof : c_int; + let mut opt : c_int; + let mut retval : c_int; + let mut code : c_int; + let mut print_ps2 : c_int; + let mut nflag : c_int = 0; + + let mut i : c_int = 0; + + let mut input_is_tty : c_int = 0; + let mut input_is_pipe : c_int = 0; + let mut unbuffered_read : c_int = 0; + let mut skip_ctlesc : c_int; + let mut skip_ctlnul : c_int; + + let mut raw : c_int = 0; + let mut edit : c_int = 0; + let mut nchars : c_int = 0; + let mut silent : c_int = 0; + let mut have_timeout : c_int = 0; + let mut ignore_delim : c_int = 0; + let mut fd : c_int = 0; + + let mut lastsig : c_int = 0; + let mut t_errno : c_int; + + let mut mb_cur_max : c_int; + + let mut tmsec : c_uint = 0; + let mut tmusec : c_uint = 0; + + let mut ival : c_long = 0; + let mut uval : c_long = 0; + let mut intval : c_long = 0; + + let mut c : c_char = 0; + + let mut input_string : *mut c_char; + let mut orig_input_string : *mut c_char; + let ifs_chars_null = CString::new("").unwrap(); + let mut ifs_chars : *mut c_char; + let mut prompt : *mut c_char = PT_NULL as *mut c_char; + let mut arrayname : *mut c_char = PT_NULL as *mut c_char; + + let mut e : *mut c_char; + let t : *mut c_char; + let t1 : *mut c_char; + let mut ps2 : *mut c_char; + let mut tofree : *mut c_char; + + let mut tsb : libc::stat; + + let mut var : *mut SHELL_VAR = PT_NULL as *mut SHELL_VAR; + + let mut ttattrs : libc::termios; + let mut ttset : libc::termios; + unsafe { + ttattrs = std::mem::zeroed(); + ttset = std::mem::zeroed(); + } + + let mut alist : *mut WORD_LIST; + + let mut vflags : c_int; + let mut rlbuf : *mut c_char = null_mut(); + let mut itext : *mut c_char = null_mut(); + + let mut rlind : c_int = 0; + + + let mut save_instream : *mut libc::FILE; + + let mut mb_cur_max : c_int = 1; + +unsafe { + + if termsave.is_none() { + let tmp: tty_save = std::mem::zeroed(); + termsave = Some(tmp); + } + ptermsave = std::mem::transmute(&termsave.unwrap()); + + reset_internal_getopt(); + let opt_str = CString::new("ersa:d:i:n:p:t:u:N:").unwrap(); + opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + while opt != -1 { + let opt_char:char=char::from(opt as u8); + match opt_char { + 'r' => raw = 1, + 'p' => prompt = list_optarg, + 's' => silent = 1, + 'e' => edit = 1, + 'i' => itext = list_optarg, + 'a' => arrayname = list_optarg, + 't' => { + code = uconvert(list_optarg, &mut ival, &mut uval, PT_NULL as *mut *mut c_char); + if code == 0 || ival < 0 || uval < 0 { + let c_err = CString::new("%s: invalid timeout specification").unwrap(); + builtin_error( c_err.as_ptr(), list_optarg); + return EXECUTION_FAILURE; + } else { + have_timeout = 1; + tmsec = ival as c_uint; + tmusec = uval as c_uint; + } + } + 'N' => { + ignore_delim = 1; + delim = -1; + } + 'n' => { + nflag = 1; + code = legal_number(list_optarg, &mut intval); + if code == 0 || intval < 0 || intval != (intval as c_int) as c_long { + sh_invalidnum(list_optarg); + return EXECUTION_FAILURE; + } else { + nchars = intval as c_int; + } + } + 'u' => { + code = legal_number(list_optarg, &mut intval); + if code == 0 || intval < 0 || intval != (intval as c_int) as c_long { + let c_err = CString::new("%s: invalid file descriptor specification").unwrap(); + builtin_error(c_err.as_ptr(), list_optarg); + return EXECUTION_FAILURE; + } else { + fd = intval as c_int; + } + if sh_validfd(fd) == 0 { + let c_err = CString::new("%d: invalid file descriptor: %s").unwrap(); + builtin_error(c_err.as_ptr(), fd, libc::strerror(nix::errno::errno())); + return EXECUTION_FAILURE; + } + } + 'd' => delim = *list_optarg, + _ => { + builtin_usage (); + return EX_USAGE; + } + } + opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + } + + list = loptend; + + if have_timeout == 1 && tmsec == 0 && tmusec == 0 { + return if input_avail(fd) != 0 {EXECUTION_SUCCESS} else {EXECUTION_FAILURE}; + } + + vflags = if assoc_expand_once != 0 {(VA_NOEXPAND | VA_ONEWORD) as c_int} else {0}; + + if !list.is_null() && + legal_identifier((*(*list).word).word) == 0 && + valid_array_reference((*(*list).word).word, vflags) == 0 { + sh_invalidid((*(*list).word).word); + return EXECUTION_FAILURE; + } + + ifs_chars = getifs(); + if ifs_chars.is_null() { + ifs_chars = ifs_chars_null.as_ptr() as *mut c_char; + } + + if ignore_delim != 0 { + delim = -1; + ifs_chars = ifs_chars_null.as_ptr() as *mut c_char; + } + + skip_ctlesc = 0; + skip_ctlnul = 0; + e = ifs_chars; + loop { + if *e == 0 { + break; + } + skip_ctlesc |= (*e == 1) as c_int; + skip_ctlnul |= (*e == 117) as c_int; + e = ((e as usize) + 1) as *mut c_char; + } + + input_string = xmalloc(112) as *mut c_char; + *input_string = b'\0' as c_char; + +'out_assig_vars: loop { + if nflag == 1 && nchars == 0 { + let mut gc : c_int = 0; + retval = libc::read(fd, &mut gc as *mut i32 as *mut c_void, 0) as c_int; + retval = if retval >= 0 {EXECUTION_SUCCESS} else {EXECUTION_FAILURE}; + + break 'out_assig_vars; + } + + let str_val = CString::new("TMOUT").unwrap(); + e = get_string_value(str_val.as_ptr()); + if have_timeout == 0 && !e.is_null() { + code = uconvert(e, &mut ival, &mut uval, 0 as *mut *mut c_char); + if code == 0 || ival < 0 || uval < 0 { + tmsec = 0; + tmusec = 0; + } else { + tmsec = ival as c_uint; + tmusec = uval as c_uint; + } + } + + let frame_name = CString::new("read_builtin").unwrap(); + begin_unwind_frame(frame_name.as_ptr() as *mut c_char); + + if interactive == 0 && default_buffered_input >= 0 && fd_is_bash_input(fd) != 0 { + sync_buffered_stream(default_buffered_input); + } + + input_is_tty = libc::isatty(fd); + if input_is_tty == 0 { + input_is_pipe = (libc::lseek(fd, 0, libc::SEEK_CUR) < 0 && (errno() == libc::ESPIPE)) as c_int; + } + + if (!prompt.is_null() || edit != 0 || silent != 0) && input_is_tty == 0 { + itext = PT_NULL as *mut c_char; + edit = 0; + silent = 0; + } + + if edit != 0 { + add_unwind_protect(xfree as *mut c_void, rlbuf); + } + + tsb = std::mem::zeroed(); + if tmsec > 0 || tmusec > 0 { + if (libc::fstat(fd, &mut tsb as *mut libc::stat) < 0) || + ((tsb.st_mode & __S_IFMT) == __S_IFREG) { + tmsec = 0; + tmusec = 0; + } + } + + if tmsec > 0 || tmusec > 0 { + code = __sigsetjmp(&mut alrmbuf as *mut __jmp_buf_tag, 0); + if code != 0 { + sigalrm_seen = 0; + orig_input_string = PT_NULL as *mut c_char; + if i == 0 { + t = libc::malloc(1) as *mut c_char; + *t = b'\0' as c_char; + } else { + t = libc::strcpy( xmalloc( + (libc::strlen(input_string) + 1) as size_t) as *mut c_char, input_string); + } + + run_unwind_frame(frame_name.as_ptr() as *mut c_char); + input_string = t; + retval = 128 + libc::SIGALRM; + break 'out_assig_vars; + } + + if interactive_shell == 0 { + initialize_terminating_signals(); + } + + old_alrm = set_signal_handler(libc::SIGALRM, sigalrm as *mut SigHandler); + add_unwind_protect(reset_alarm as *mut c_void, PT_NULL as *mut c_char); + + if edit != 0 { + add_unwind_protect(reset_attempted_completion_function as *mut c_void, + PT_NULL as *mut c_char); + add_unwind_protect(bashline_reset_event_hook as *mut c_void, + PT_NULL as *mut c_char); + } + + falarm(tmsec, tmusec); + } + + if nchars > 0 || delim != b'\n' as c_char { + if edit != 0 { + if nchars > 0 { + unwind_protect_mem(&mut rl_num_chars_to_read as *mut c_int, std::mem::size_of_val(&rl_num_chars_to_read) as c_int); + rl_num_chars_to_read = nchars; + } + + if delim != b'\n' as c_char { + set_eol_delim(delim as c_int); + add_unwind_protect(reset_eol_delim as *mut c_void, PT_NULL as *mut c_char); + } + } else if input_is_tty != 0 { + termsave.unwrap().fd = fd; + ttgetattr(fd, &mut ttattrs as *mut libc::termios); + termsave.unwrap().attrs = ttattrs; + ttset = ttattrs; + if silent != 0 { + i = ttfd_cbreak(fd, std::mem::transmute(&ttset)); + } else { + i = ttfd_onechar(fd, std::mem::transmute(&ttset)); + } + + if i < 0 { + sh_ttyerror(1); + } + tty_modified = 1; + add_unwind_protect(ttyrestore as *mut c_void, ptermsave); + if interactive_shell == 0 { + initialize_terminating_signals(); + } + + } + } else if silent != 0 { + termsave.unwrap().fd = fd; + ttgetattr(fd, &mut ttattrs as *mut libc::termios); + termsave.unwrap().attrs = ttattrs; + + ttset = ttattrs; + i = ttfd_noecho(fd, std::mem::transmute(&ttset)); + if i < 0 { + sh_ttyerror(1); + } + + tty_modified = 1; + add_unwind_protect(ttyrestore as *mut c_void, ptermsave); + if interactive_shell == 0 { + initialize_terminating_signals(); + } + } + + save_instream = std::mem::zeroed(); + if edit != 0 && fd != 0 { + if bash_readline_initialized == 0 { + initialize_readline(); + } + + unwind_protect_mem(std::mem::transmute(rl_instream), std::mem::size_of_val(&rl_instream) as c_int); + save_instream = rl_instream; + rl_instream = libc::fdopen(fd, "r".as_ptr() as *const c_char); + + } + + add_unwind_protect(xfree as *mut c_void, input_string); + check_alrm(); + if nchars > 0 && input_is_tty == 0 && ignore_delim != 0 { + unbuffered_read = 2; + } else if nchars > 0 || delim != b'\n' as c_char || input_is_pipe != 0 { + unbuffered_read = 1; + } + + if !prompt.is_null() && edit == 0 { + eprintln!("{}", CStr::from_ptr(prompt).to_str().unwrap()); + + } + + ps2 = PT_NULL as *mut c_char; + print_ps2 = 0; + eof = 0; + retval = 0; + 'get_input_string: loop { + if sigalrm_seen != 0 { + siglongjmp (std::mem::transmute(&alrmbuf), 1); + } + + if edit != 0 { + if !rlbuf.is_null() && + *((rlbuf as usize + rlind as usize) as *mut c_char) == 0 && + delim != 0 { + libc::free(rlbuf as *mut c_void); + rlbuf = PT_NULL as *mut c_char; + } + if rlbuf.is_null() { + reading = 1; + rlbuf = if prompt.is_null() {edit_line("".as_ptr() as *mut c_char, itext)} + else {edit_line(prompt, itext)}; + reading = 0; + rlind = 0; + } + if rlbuf.is_null() { + eof = 1; + break 'get_input_string; + } + c = *((rlbuf as usize + rlind as usize) as *mut c_char); + rlind += 1; + } else { + if print_ps2 != 0 { + if ps2.is_null() { + ps2 = get_string_value("PS2".as_ptr() as *const c_char); + } + eprintln!("{}", CStr::from_ptr(prompt).to_str().unwrap()); + print_ps2 = 0; + } + + reading = 1; + check_alrm(); + *(libc::__errno_location()) = 0; + if unbuffered_read == 2 { + retval = if posixly_correct != 0 {zreadintr(fd, &mut c as *mut c_char, 1) as c_int} + else {zreadn(fd, &mut c as *mut c_char, (nchars - nr) as usize) as c_int}; + } else if unbuffered_read != 0 { + retval = if posixly_correct != 0 {zreadintr(fd, &mut c as *mut c_char, 1) as c_int} + else {zreadn(fd, &mut c as *mut c_char, 1) as c_int}; + } else { + retval = if posixly_correct != 0 {zreadcintr(fd, &mut c as *mut c_char) as c_int} + else {zreadc(fd, &mut c as *mut c_char) as c_int}; + } + + reading = 0; + + if retval <= 0 { + let t = *libc::__errno_location(); + if retval < 0 && *libc::__errno_location() == libc::EINTR { + check_signals(); + //lastsig = LASTSIG(); + if terminating_signal != 0 { + lastsig = terminating_signal; + } else { + lastsig = if interrupt_state != 0 {libc::SIGINT} else { 0 }; + } + + if lastsig == 0 { + lastsig = trapped_signal_received; + } + } else { + lastsig = 0; + } + + if terminating_signal != 0 && tty_modified != 0 { + ttyrestore(); + } + check_alrm(); + eof = 1; + *libc::__errno_location() = t; + break 'get_input_string; + } + + quit(); + } + + if retval <= 0 { + check_alrm(); + } + + if mb_cur_max <= 4 { + mb_cur_max = 4; + } + if i + mb_cur_max >= size { + size += 128; + let t: *mut c_char= xrealloc(input_string as *mut c_void, size as usize) as *mut c_char; + if t != input_string { + input_string = t; + remove_unwind_protect(); + add_unwind_protect(xfree as *mut c_void, input_string); + } + } +'out_add_char: loop { + if pass_next != 0 { + pass_next = 0; + if c == b'\n' as c_char { + if skip_ctlesc == 0 && i > 0 {i -= 1;} + if interactive != 0 && input_is_tty != 0 && raw == 0 {print_ps2 = 1;} + } else { + break 'out_add_char; + } + continue 'get_input_string; + } + + if c == b'\\' as c_char && raw == 0 { + pass_next += 1; + if skip_ctlesc == 0 { + saw_escape += 1; + *((input_string as usize + i as usize) as *mut c_char) = CTLESC; + i += 1; + } + continue 'get_input_string; + } + + if ignore_delim == 0 && c == delim { + break 'get_input_string; + } + + if c == b'\0' as c_char && delim != b'\0' as c_char { + continue 'get_input_string; + } + + if (skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL) { + saw_escape += 1; + *((input_string as usize + i as usize) as *mut c_char) = CTLESC; + i += 1; + } + break 'out_add_char; + } + *((input_string as usize + i as usize) as *mut c_char) = c; + i += 1; + check_alrm(); + + if mb_cur_max > 1 && is_basic(c) == 0 { + *((input_string as usize + i as usize) as *mut c_char) = b'\0' as c_char; + + if edit != 0 { + let clen = mbrlen((rlbuf as usize + rlind as usize - 1) as *const c_char, + mb_cur_max as usize, + std::mem::transmute(&PT_NULL)); + if clen > 1 { + libc::memcpy( (input_string as usize + i as usize) as *mut c_void, + (rlbuf as usize + rlind as usize) as *mut c_void, (clen - 1) as size_t); + i += clen - 1; + rlind += clen - 1; + } + } else if locale_utf8locale == 0 || ((c as u8 & 0x80) != 0) { + i += read_mbchar(fd, input_string, i, c as c_int, unbuffered_read); + } + + nr += 1; + if nchars > 0 && nr >= nchars { + break 'get_input_string; + } + } + } + + *((input_string as usize + i as usize) as *mut c_char) = b'\0' as c_char; + check_alrm(); + + if edit != 0 { + libc::free(rlbuf as *mut c_void); + } + + if retval < 0 { + t_errno = *libc::__errno_location(); + if *libc::__errno_location() != EINTR { + let c_err = CString::new("read error: %d: %s").unwrap(); + builtin_error( c_err.as_ptr(), fd, libc::strerror(*libc::__errno_location())); + } + + run_unwind_frame(frame_name.as_ptr() as *mut c_char); + return if t_errno != EINTR {EXECUTION_FAILURE} else { 128 + lastsig}; + } + + if tmsec > 0 || tmusec > 0 { + reset_alarm(); + } + + if nchars > 0 || delim != b'\n' as c_char { + if edit != 0 { + + } else if input_is_tty != 0 { + ttyrestore(); + } + } else if silent != 0 { + ttyrestore(); + } + + if unbuffered_read != 0 { + zsyncfd(fd); + } + + if !save_instream.is_null() { + rl_instream = save_instream; + } + + discard_unwind_frame(frame_name.as_ptr() as *mut c_char); + + retval = if eof != 0 {EXECUTION_FAILURE} else {EXECUTION_SUCCESS}; + + break 'out_assig_vars; +} + + if !arrayname.is_null() { + if legal_identifier(arrayname) == 0 { + sh_invalidid(arrayname); + libc::free(input_string as *mut c_void); + return EXECUTION_FAILURE; + } + + var = find_or_make_array_variable(arrayname, 1); + if var.is_null() { + libc::free(input_string as *mut c_void); + return EXECUTION_FAILURE; /* readonly or noassign */ + } + if ((*var).attributes & 0x0000040) != 0 { + let c_err = CString::new("%s: cannot convert associative to indexed array").unwrap(); + builtin_error(c_err.as_ptr(), arrayname); + libc::free(input_string as *mut c_void); + return EXECUTION_FAILURE; /* existing associative array */ + } else if ((*var).attributes & 0x0001000) != 0 { + (*var).attributes &= ((*var).attributes as u32 ^ 0xffffffff as u32) as i32; + } + + array_flush(std::mem::transmute((*var).value)); + + alist = list_string(input_string, ifs_chars, 0); + if !alist.is_null() { + if saw_escape != 0 { + dequote_list(alist); + } else { + word_list_remove_quoted_nulls(alist); + } + assign_array_var_from_word_list(var, alist, 0); + dispose_words(alist); + } + + libc::free(input_string as *mut c_void); + return retval; + } + + if list.is_null() { + if saw_escape != 0 { + let t = dequote_string(input_string); + var = bind_variable("REPLY".as_ptr() as *const c_char, t, 0); + libc::free(t as *mut c_void); + } else { + var = bind_variable("REPLY".as_ptr() as *const c_char, input_string, 0); + } + let cond = var.is_null() || ((*var).attributes & 0x0000002) != 0 || ((*var).attributes & 0x0004000) != 0; + if cond { + retval = EXECUTION_FAILURE; + } else { + (*var).attributes &= ((*var).attributes as u32 ^ 0xffffffff as u32) as i32; + } + + libc::free(input_string as *mut c_void); + return retval; + } + + orig_input_string = input_string; + + let mut t = input_string; + while !ifs_chars.is_null() && *ifs_chars != 0 && + (*t == b' ' as c_char|| *t == b'\t' as c_char || *t == b'\n' as c_char) && + (ifs_cmap[*t as usize] != 0) { + t = (t as usize + 1) as *mut c_char; + } + input_string = t; + + while !(*list).next.is_null() { + varname = (*((*list).word)).word; + + if legal_identifier(varname) == 0 && + valid_array_reference(varname, vflags) == 0 { + sh_invalidid(varname); + libc::free(orig_input_string as *mut c_void); + return EXECUTION_FAILURE; + } + + if *input_string != 0 { + t = get_word_from_string(std::mem::transmute(&input_string), ifs_chars, std::mem::transmute(&e)); + if !t.is_null() { *e = b'\0' as c_char;} + + if !t.is_null() && saw_escape != 0 { + let t1 = dequote_string(t); + var = bind_read_variable(varname, t1); + libc::free(t1 as *mut c_void); + } else { + var = bind_read_variable(varname, if !t.is_null() {t} else {"".as_ptr() as *mut c_char}); + } + } else { + t = PT_NULL as *mut c_char; + var = bind_read_variable(varname, "".as_ptr() as *mut c_char); + } + + if !t.is_null() { + libc::free(t as *mut c_void); + } + + if var.is_null() { + libc::free(orig_input_string as *mut c_void); + return EXECUTION_FAILURE; + } + + stupidly_hack_special_variables(varname); + (*var).attributes &= ((*var).attributes as u32 ^ 0xffffffff as u32) as i32; + + list = (*list).next; + } + + if legal_identifier((*((*list).word)).word) == 0 && + valid_array_reference((*((*list).word)).word, vflags) == 0 { + sh_invalidid((*((*list).word)).word); + libc::free(orig_input_string as *mut c_void); + return EXECUTION_FAILURE; + } + + tofree = PT_NULL as *mut c_char; + if *input_string != 0 { + t1 = input_string; + t = get_word_from_string(std::mem::transmute(&input_string), ifs_chars, std::mem::transmute(&e)); + if *input_string == 0 { + input_string = t; + tofree = input_string; + } else { + input_string = strip_trailing_ifs_whitespace(t1, ifs_chars, saw_escape); + tofree = t; + } + } + + if saw_escape != 0 && !input_string.is_null() && *input_string != 0 { + t = dequote_string(input_string); + var = bind_read_variable((*((*list).word)).word, t); + libc::free(t as *mut c_void); + } else { + var = bind_read_variable((*((*list).word)).word, if !input_string.is_null() {input_string} else {"".as_ptr() as *mut c_char}); + } + + if !var.is_null() { + stupidly_hack_special_variables((*((*list).word)).word); + (*var).attributes &= ((*var).attributes as u32 ^ 0xffffffff as u32) as i32; + } else { + retval = EXECUTION_FAILURE; + } + + if !tofree.is_null() { + libc::free(tofree as *mut c_void); + } + libc::free(orig_input_string as *mut c_void); + return retval; +} +} + +/* ---------------------------------------------------------------------------------- */ + +pub fn is_basic(c: i8) -> u32 { + let is_basic_table :[c_uint; 8] = [ 0x00001a00, 0xffffffef, 0xfffffffe, 0x7ffffffe, 0,0,0,0]; + + let index = (c >> 5) as usize; + return (is_basic_table[index] >> (c & 31) ) & 1; } -/* -Read a line from the standard input and split it into fields. +pub fn bind_read_variable(name: *mut c_char, value: *mut c_char) -> * mut SHELL_VAR { + let v: *mut SHELL_VAR; +unsafe { + v = builtin_bind_variable(name, value, 0); -Reads a single line from the standard input, or from file descriptor FD -if the -u option is supplied. The line is split into fields as with word -splitting, and the first word is assigned to the first NAME, the second -word to the second NAME, and so on, with any leftover words assigned to -the last NAME. Only the characters found in $IFS are recognized as word -delimiters. + if v.is_null() { + return v; + } else { + if ((*v).attributes & 0x0000002) != 0 || ((*v).attributes & 0x0004000) != 0 { + return PT_NULL as *mut SHELL_VAR; + } else { + return v; + } + } +} +} + +fn read_mbchar(fd: c_int, string: *mut c_char, ind: c_int, ch: c_int, unbuffered: c_int) -> c_int { + let mut i: size_t = 1; + let mut r: ssize_t; + let mut c: c_char = 0; + let mut ret: ssize_t; -If no NAMEs are supplied, the line read is stored in the REPLY variable. -*/ +unsafe { + let mut mbchar: [c_char; MB_LEN_MAX as usize + 1] = std::mem::zeroed(); + let mut ps: mbstate_t = std::mem::zeroed(); + let mut ps_back: mbstate_t = std::mem::zeroed(); + let mut wc: libc::wchar_t = std::mem::zeroed(); + +'out: loop { + mbchar[0] = ch as c_char; + for n in 0..= MB_LEN_MAX { + ps_back = ps; + ret = mbrtowc(std::mem::transmute(&wc), std::mem::transmute(&mbchar), i, std::mem::transmute(&ps)) as ssize_t; + if ret == -2 { + ps = ps_back; + + /* We don't want to be interrupted during a multibyte char read */ + if unbuffered == 2 { + r = zreadn(fd, std::mem::transmute(&c), 1); + } else if unbuffered != 0 { + r = zread(fd, std::mem::transmute(&c), 1); + } else { + r = zreadc(fd, std::mem::transmute(&c)); + } + if r <= 0 { + break 'out; + } + mbchar[i] = c; + i += 1; + continue; + } else if ret == -1 || ret == 0 || ret > 0 { + break; + } + } + break 'out; +} + if i > 1 { + r = 1; + while r < i as isize { + *((string as usize + ind as usize + r as usize -1) as *mut c_char) = mbchar[r as size_t]; + + r += 1; + } + } + return (i - 1) as c_int; +} +} + +fn quit() { +unsafe { + if terminating_signal != 0 { + termsig_handler(terminating_signal); + } + + if interrupt_state != 0 { + throw_to_top_level(); + } +} +} + +fn check_alrm() { + unsafe { + if sigalrm_seen != 0 { + siglongjmp (std::mem::transmute(&alrmbuf), 1); + } + } +} + +static mut old_attempted_completion_function: usize = 0; + +pub fn reset_attempted_completion_function(cp: *mut c_char) +{ +unsafe { + if rl_attempted_completion_function as usize == 0 && + old_attempted_completion_function as usize != 0 { + rl_attempted_completion_function = std::mem::transmute(old_attempted_completion_function); + } +} +} + +static mut old_startup_hook: usize = 0; +static mut deftext: *mut c_char = PT_NULL as *mut c_char; + +fn set_itext() -> c_int +{ + let mut r1 = 0; + let mut r2 = 0; + +unsafe { + if old_startup_hook != 0 { + let fp: rl_hook_func_t = std::mem::transmute(old_startup_hook); + r1 = fp(); + } + if !deftext.is_null() { + r2 = rl_insert_text(deftext as *const c_char); + deftext = PT_NULL as *mut c_char; + rl_startup_hook = std::mem::transmute(old_startup_hook); + old_startup_hook = std::mem::transmute(0 as usize); + } +} + return (r1 != 0 || r2 != 0) as c_int; +} + +fn edit_line(p : *mut c_char, itext : *mut c_char) -> *mut c_char { +unsafe { + if bash_readline_initialized == 0 { + initialize_readline(); + } + + old_attempted_completion_function = std::mem::transmute(rl_attempted_completion_function); + rl_attempted_completion_function = std::mem::transmute(0 as usize); + bashline_set_event_hook(); + if !itext.is_null() { + old_startup_hook = std::mem::transmute(rl_startup_hook); + rl_startup_hook = std::mem::transmute(set_itext as usize); + deftext = itext; + } + + let mut ret = readline(p); + + rl_attempted_completion_function = std::mem::transmute(old_attempted_completion_function); + old_attempted_completion_function = std::mem::transmute(0 as usize); + bashline_reset_event_hook(); + + if ret.is_null() { + return ret; + } + + let len = libc::strlen(ret); + ret = xrealloc(ret as *mut c_void, len + 2) as *mut c_char; + *ret = delim; + *((ret as usize + 1) as *mut c_char) = b'\0' as c_char; + return ret; +} +} + +fn sigalrm(s : c_int) { +unsafe { + sigalrm_seen = 1; +} +} + +fn reset_alarm() +{ +unsafe { + falarm(0, 0); + set_signal_handler(libc::SIGALRM, old_alrm); +} +} + +fn ttyrestore() +{ +unsafe { + if termsave.is_none() { + let tmp: tty_save = std::mem::zeroed(); + termsave = Some(tmp); + } + + let ter = termsave.unwrap(); + ttsetattr(ter.fd, std::mem::transmute(&(ter.attrs))); + tty_modified = 0; +} +} #[no_mangle] -pub extern "C" fn r_read_builtin(list: *mut WORD_LIST) -> i32 { - println!("r_read_builtin call"); - 0 -} \ No newline at end of file +pub extern "C" fn read_tty_cleanup() +{ +unsafe { + if tty_modified != 0 { + ttyrestore(); + } +} +} + +#[no_mangle] +pub extern "C" fn read_tty_modified() -> c_int +{ +unsafe { + return tty_modified; + } +} + +static mut old_delim_ctype: c_int = 0; +static mut old_delim_func: usize = 0; +static mut old_newline_ctype: c_int = 0; +static mut old_newline_func: usize = 0; + +static mut delim_char: u8 = 0; +fn set_eol_delim(c: c_int) +{ +unsafe { + if bash_readline_initialized == 0 { + initialize_readline(); + } + + let cmap = rl_get_keymap(); + let n = std::mem::size_of_val(&*cmap); + let ret_pos = (b'M' & 0x1f) as usize * n; + let c_pos = (c & 0x1f) as usize * n; + + /* Save the old delimiter char binding */ + old_newline_ctype = (*((cmap as usize + ret_pos) as Keymap)).tp as c_int; + old_newline_func = (*((cmap as usize + ret_pos) as Keymap)).function as usize; + old_delim_ctype = (*((cmap as usize + c_pos) as Keymap)).tp as c_int; + old_delim_func = (*((cmap as usize + c_pos) as Keymap)).function as usize; + + /* Change newline to self-insert */ + (*((cmap as usize + ret_pos) as Keymap)).tp = ISFUNC as c_char; + (*((cmap as usize + ret_pos) as Keymap)).function = rl_insert; + + /* Bind the delimiter character to accept-line. */ + (*((cmap as usize + c_pos) as Keymap)).tp = ISFUNC as c_char; + (*((cmap as usize + c_pos) as Keymap)).function = rl_newline; + + delim_char = c as u8; +} +} + +fn reset_eol_delim(cp: *mut c_char) +{ +unsafe { + let cmap = rl_get_keymap(); + let n = std::mem::size_of_val(&*cmap); + let ret_pos = (b'M' & 0x1f) as usize * n; + let delim_pos = (delim_char & 0x1f) as usize * n; + + (*((cmap as usize + ret_pos) as Keymap)).tp = old_newline_ctype as c_char; + (*((cmap as usize + ret_pos) as Keymap)).function = std::mem::transmute(old_newline_func); + + (*((cmap as usize + delim_pos) as Keymap)).tp = old_delim_ctype as c_char; + (*((cmap as usize + delim_pos) as Keymap)).function = std::mem::transmute(old_delim_func); +} +} diff --git a/bash-5.1/builtins_rust/rlet/Cargo.toml b/bash-5.1/builtins_rust/rlet/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..cf22e7174a9587d9c610a9596cedbe132987df32 --- /dev/null +++ b/bash-5.1/builtins_rust/rlet/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rlet" +version = "0.1.0" +edition = "2018" +authors = ["lvgenggeng"] +#build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "rlet" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/rlet/src/intercdep.rs b/bash-5.1/builtins_rust/rlet/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..d2246f94d4f21090d6d6a2aaee70c126f7bd358c --- /dev/null +++ b/bash-5.1/builtins_rust/rlet/src/intercdep.rs @@ -0,0 +1,46 @@ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +pub const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_USAGE: c_int = 258; + +pub const EXP_EXPANDED: c_int = 0x01; + +pub type histdata_t = *mut libc::c_void; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct _hist_entry { + pub line: *mut c_char, + pub timestamp: *mut c_char, + pub data: histdata_t, +} +pub type HIST_ENTRY = _hist_entry; + +extern "C" { + pub fn string_list(list: *mut WORD_LIST) -> *mut c_char; + + pub fn builtin_usage(); + pub fn builtin_help(); + pub fn builtin_error(format: *const c_char, ...); + + pub fn evalexp (expr: *mut c_char, flags: c_int, validp: *mut c_int) -> c_long; + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + +} diff --git a/bash-5.1/builtins_rust/rlet/src/lib.rs b/bash-5.1/builtins_rust/rlet/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..7fe5af59585a4c068c134779322d1daa71b3d4d5 --- /dev/null +++ b/bash-5.1/builtins_rust/rlet/src/lib.rs @@ -0,0 +1,63 @@ +use std::ffi::CStr; +use libc::{c_int, c_char, c_long, c_void}; + +include!(concat!("intercdep.rs")); + +#[no_mangle] +pub extern "C" fn r_let_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_let_builtin call"); +unsafe { + let mut ret: c_long = 0; + let mut expok: c_int = 0; + + if !list.is_null() && !(*list).word.is_null() && + libc::strcmp((*((*list).word)).word, "--help\0".as_ptr() as *const c_char) == 0 { + builtin_help (); + return EX_USAGE; + } + + if !list.is_null() && !(*list).word.is_null() && is_option((*((*list).word)).word, b'-') { + list = (*list).next; + } + + if list.is_null() { + builtin_error("expression expected\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + + while !list.is_null() { + ret = evalexp((*((*list).word)).word, EXP_EXPANDED, std::mem::transmute(&expok)); + if expok == 0 { + return EXECUTION_FAILURE; + } + list = (*list).next; + } + + return if ret == 0 {EXECUTION_FAILURE} else {EXECUTION_SUCCESS}; +} +} + +#[no_mangle] +pub extern "C" fn r_exp_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_exp_builtin call"); + +unsafe { + let mut expok: c_int = 0; + + if list.is_null() { + builtin_error("expression expected\0".as_ptr() as *const c_char); + return EXECUTION_FAILURE; + } + + let exp = string_list(list); + let ret = evalexp(exp, EXP_EXPANDED, std::mem::transmute(&expok)); + libc::free(exp as *mut c_void); + return if ret == 0 || expok == 0 {EXECUTION_FAILURE} else {EXECUTION_SUCCESS}; +} +} + +unsafe fn is_option(s: *mut c_char, c: u8) -> bool +{ + let str = CStr::from_ptr(s).to_bytes_with_nul(); + return str[0] == b'-' && str[1] == c && str[2] != 0 +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/rreturn/Cargo.toml b/bash-5.1/builtins_rust/rreturn/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..bc74aa79175748bd2e51e8948f0ece4c12edb403 --- /dev/null +++ b/bash-5.1/builtins_rust/rreturn/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rreturn" +version = "0.1.0" +edition = "2018" +authors = ["lvgenggeng"] +#build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "rreturn" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/rreturn/src/intercdep.rs b/bash-5.1/builtins_rust/rreturn/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..7e97641724dbc85e35cd772d4bfca6c3e61d94a7 --- /dev/null +++ b/bash-5.1/builtins_rust/rreturn/src/intercdep.rs @@ -0,0 +1,54 @@ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +pub const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_USAGE: c_int = 258; + +pub type __jmp_buf = [c_long; 8usize]; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct __sigset_t { + pub __val: [c_ulong; 16usize], +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct __jmp_buf_tag { + pub __jmpbuf: __jmp_buf, + pub __mask_was_saved: c_int, + pub __saved_mask: __sigset_t, +} +pub type sigjmp_buf = [__jmp_buf_tag; 1usize]; + +extern "C" { + pub fn builtin_usage(); + pub fn builtin_help(); + pub fn builtin_error(format: *const c_char, ...); + + pub fn get_exitstat(list: *mut WORD_LIST) -> c_int; + + pub fn siglongjmp(__env: *mut __jmp_buf_tag, __val: c_int); + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + + pub static mut return_catch_value: c_int; + pub static return_catch_flag: c_int; + pub static return_catch: sigjmp_buf; +} diff --git a/bash-5.1/builtins_rust/rreturn/src/lib.rs b/bash-5.1/builtins_rust/rreturn/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..277faa26a22c2718d7f0d79ffcd54f033765f095 --- /dev/null +++ b/bash-5.1/builtins_rust/rreturn/src/lib.rs @@ -0,0 +1,25 @@ +use libc::{c_int, c_char, c_long, c_ulong}; + +include!(concat!("intercdep.rs")); + +#[no_mangle] +pub extern "C" fn r_return_builtin(list: *mut WORD_LIST) -> i32 { + println!("r_return_builtin call"); + +unsafe { + if !list.is_null() && !(*list).word.is_null() && + libc::strcmp((*((*list).word)).word, "--help\0".as_ptr() as *const c_char) == 0 { + builtin_help (); + return EX_USAGE; + } + + return_catch_value = get_exitstat(list); + if return_catch_flag != 0 { + siglongjmp(std::mem::transmute(&return_catch), 1); + } else { + builtin_error("can only `return' from a function or sourced script\0".as_ptr() as *const c_char); + return EX_USAGE; + } +} + return EXECUTION_SUCCESS; +} diff --git a/bash-5.1/builtins_rust/setattr/Cargo.toml b/bash-5.1/builtins_rust/setattr/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..6999ba9091df1fa6a3a5867ca8acc190ae5c6e22 --- /dev/null +++ b/bash-5.1/builtins_rust/setattr/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "setattr" +version = "0.1.0" +edition = "2018" +authors = ["lvgenggeng"] +build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "rsetattr" +#crate-type = ["cdylib"] +crate-type = ["staticlib"] + +[build-dependencies] +rdeclare = {path = "../declare"} + +[dependencies] +libc = "0.2" +nix = "0.23" +rdeclare = {path = "../declare"} diff --git a/bash-5.1/builtins_rust/setattr/src/intercdep.rs b/bash-5.1/builtins_rust/setattr/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..cea139dece18b8fd848a145b3f38be78287acdfd --- /dev/null +++ b/bash-5.1/builtins_rust/setattr/src/intercdep.rs @@ -0,0 +1,390 @@ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +pub type __intmax_t = c_long; +pub type intmax_t = __intmax_t; +pub type arrayind_t = intmax_t; +pub type sh_var_value_func_t = + ::std::option::Option *mut variable>; + + pub type sh_var_assign_func_t = ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut variable, + arg2: *mut c_char, + arg3: arrayind_t, + arg4: *mut c_char, + ) -> *mut variable, +>; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct variable { + pub name: *mut c_char, + pub value: *mut c_char, + pub exportstr: *mut c_char, + pub dynamic_value: sh_var_value_func_t, + pub assign_func: sh_var_assign_func_t, + pub attributes: c_int, + pub context: c_int, +} +pub type SHELL_VAR = variable; + +pub type pid_t = c_int; +pub type WAIT = c_int; +pub type sh_vptrfunc_t = *mut fn(); +pub type JOB_STATE = c_int; + +pub type command_type = c_uint; +#[repr(C)] +#[derive(Copy, Clone)] +pub union REDIRECTEE { + pub dest: c_int, + pub filename: *mut WORD_DESC, +} + +pub type r_instruction = c_uint; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct redirect { + pub next: *mut redirect, + pub redirector: REDIRECTEE, + pub rflags: c_int, + pub flags: c_int, + pub instruction: r_instruction, + pub redirectee: REDIRECTEE, + pub here_doc_eof: *mut c_char, +} + +pub type REDIRECT = redirect; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct command { + pub type_: command_type, + pub flags: c_int, + pub line: c_int, + pub redirects: *mut REDIRECT, + pub value: command__bindgen_ty_1, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub union command__bindgen_ty_1 { + pub For: *mut for_com, + pub Case: *mut case_com, + pub While: *mut while_com, + pub If: *mut if_com, + pub Connection: *mut connection, + pub Simple: *mut simple_com, + pub Function_def: *mut function_def, + pub Group: *mut group_com, + pub Select: *mut select_com, + pub Arith: *mut arith_com, + pub Cond: *mut cond_com, + pub ArithFor: *mut arith_for_com, + pub Subshell: *mut subshell_com, + pub Coproc: *mut coproc_com, +} + +pub type COMMAND = command; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct pattern_list { + pub next: *mut pattern_list, + pub patterns: *mut WORD_LIST, + pub action: *mut COMMAND, + pub flags: c_int, +} + +pub type PATTERN_LIST = pattern_list; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct case_com { + pub flags: c_int, + pub line: c_int, + pub word: *mut WORD_DESC, + pub clauses: *mut PATTERN_LIST, +} + +pub type CASE_COM = case_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct for_com { + pub flags: c_int, + pub line: c_int, + pub name: *mut WORD_DESC, + pub map_list: *mut WORD_LIST, + pub action: *mut COMMAND, +} + +pub type FOR_COM = for_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct arith_for_com { + pub flags: c_int, + pub line: c_int, + pub init: *mut WORD_LIST, + pub test: *mut WORD_LIST, + pub step: *mut WORD_LIST, + pub action: *mut COMMAND, +} + +pub type ARITH_FOR_COM = arith_for_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct select_com { + pub flags: c_int, + pub line: c_int, + pub name: *mut WORD_DESC, + pub map_list: *mut WORD_LIST, + pub action: *mut COMMAND, +} + +pub type SELECT_COM = select_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct if_com { + pub flags: c_int, + pub test: *mut COMMAND, + pub true_case: *mut COMMAND, + pub false_case: *mut COMMAND, +} + +pub type IF_COM = if_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct while_com { + pub flags: c_int, + pub test: *mut COMMAND, + pub action: *mut COMMAND, +} + +pub type WHILE_COM = while_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct arith_com { + pub flags: c_int, + pub line: c_int, + pub exp: *mut WORD_LIST, +} + +pub type ARITH_COM = arith_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct cond_com { + pub flags: c_int, + pub line: c_int, + pub type_: c_int, + pub op: *mut WORD_DESC, + pub left: *mut cond_com, + pub right: *mut cond_com, +} + +pub type COND_COM = cond_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct simple_com { + pub flags: c_int, + pub line: c_int, + pub words: *mut WORD_LIST, + pub redirects: *mut REDIRECT, +} + +pub type SIMPLE_COM = simple_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct function_def { + pub flags: c_int, + pub line: c_int, + pub name: *mut WORD_DESC, + pub command: *mut COMMAND, + pub source_file: *mut c_char, +} + +pub type FUNCTION_DEF = function_def; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct group_com { + pub ignore: c_int, + pub command: *mut COMMAND, +} + +pub type GROUP_COM = group_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct subshell_com { + pub flags: c_int, + pub line: c_int, + pub command: *mut COMMAND, +} + +pub type SUBSHELL_COM = subshell_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct coproc { + pub c_name: *mut c_char, + pub c_pid: pid_t, + pub c_rfd: c_int, + pub c_wfd: c_int, + pub c_rsave: c_int, + pub c_wsave: c_int, + pub c_flags: c_int, + pub c_status: c_int, + pub c_lock: c_int, +} + +pub type Coproc = coproc; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct coproc_com { + pub flags: c_int, + pub name: *mut c_char, + pub command: *mut COMMAND, +} + +pub type COPROC_COM = coproc_com; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct process { + pub next: *mut process, + pub pid: pid_t, + pub status: WAIT, + pub running: c_int, + pub command: *mut c_char, +} + +pub type PROCESS = process; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct job { + pub wd: *mut c_char, + pub pipe: *mut PROCESS, + pub pgrp: pid_t, + pub state: JOB_STATE, + pub flags: c_int, + pub deferred: *mut COMMAND, + pub j_cleanup: sh_vptrfunc_t, + pub cleanarg: *mut c_void, +} + +pub type JOB = job; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct connection { + pub _address: u8, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct jobstats { + pub c_childmax: c_long, + pub c_living: c_int, + pub c_reaped: c_int, + pub c_injobs: c_int, + pub c_totforked: c_int, + pub c_totreaped: c_int, + pub j_jobslots: c_int, + pub j_lastj: c_int, + pub j_firstj: c_int, + pub j_njobs: c_int, + pub j_ndead: c_int, + pub j_current: c_int, + pub j_previous: c_int, + pub j_lastmade: *mut JOB, + pub j_lastasync: *mut JOB, +} + +pub type sh_builtin_func_t = + unsafe extern "C" fn(arg1: *mut WORD_LIST) -> c_int; + +pub const att_exported: c_int = 0x0000001; +pub const att_readonly: c_int = 0x0000002; +pub const att_array: c_int = 0x0000004; +pub const att_function: c_int = 0x0000008; +pub const att_integer: c_int = 0x0000010; +pub const att_local: c_int = 0x0000020; +pub const att_assoc: c_int = 0x0000040; +pub const att_trace: c_int = 0x0000080; +pub const att_uppercase: c_int = 0x0000100; +pub const att_lowercase: c_int = 0x0000200; +pub const att_capcase: c_int = 0x0000400; +pub const att_nameref: c_int = 0x0000800; + +pub const att_invisible: c_int = 0x0001000; +pub const att_imported: c_int = 0x0008000; + +pub const att_tempvar: c_int = 0x0100000; +pub const att_propagate: c_int = 0x0200000; + +pub const EX_USAGE: c_int = 258; +pub const EX_BADASSIGN: c_int = 260; + +pub const EXECUTION_SUCCESS: c_int = 0; +pub const EXECUTION_FAILURE: c_int = 1; + +pub const ASS_APPEND: c_int = 0x0001; + +pub const FUNC_MULTILINE: c_int = 0x01; +pub const FUNC_EXTERNAL: c_int = 0x02; + +extern "C" { + pub static mut loptend : *mut WORD_LIST; + pub static mut array_needs_making: c_int; + pub static mut this_shell_builtin: sh_builtin_func_t; + pub static mut posixly_correct: c_int; + pub static mut this_command_name: *mut c_char; + pub static mut variable_context: c_int; + pub static mut shell_compatibility_level: c_int; + pub static mut nameref_invalid_value: SHELL_VAR; + + pub fn reset_internal_getopt(); + pub fn internal_getopt(list: *mut WORD_LIST, opts: *mut c_char) -> c_int; + pub fn builtin_usage(); + pub fn builtin_error(arg1: *const c_char, ...); + pub fn find_function(name: *const c_char) -> *mut SHELL_VAR; + pub fn exportable_function_name(string: *const c_char) -> c_int; + pub fn assignment(string: *const c_char, flags: c_int) -> c_int; + pub fn legal_identifier(arg1: *const c_char) -> c_int; + pub fn sh_invalidid(s: *mut c_char); + pub fn make_word(string: *const c_char) -> *mut WORD_DESC; + pub fn make_word_list(word: *mut WORD_DESC, wlink: *mut WORD_LIST) -> *mut WORD_LIST; + pub fn declare_builtin(list:* mut WORD_LIST) -> c_int; + pub fn dispose_word(w: *mut WORD_DESC); + pub fn do_assignment_no_expand(string: *mut c_char) -> c_int; + + pub fn all_shell_functions() -> *mut *mut SHELL_VAR; + pub fn all_shell_variables() -> *mut *mut SHELL_VAR; + pub fn all_local_variables(visible_only: c_int) -> *mut *mut SHELL_VAR; + + pub fn sh_chkwrite(s: c_int) -> c_int; + pub fn sh_double_quote(string: *const c_char) -> *mut c_char; + + pub fn named_function_string (name: *mut c_char, command: *mut COMMAND, flags: c_int) -> *mut c_char; + + pub fn print_array_assignment (var: *mut SHELL_VAR, quoted: c_int); + pub fn print_assoc_assignment (var: *mut SHELL_VAR, quoted: c_int); + + pub fn find_variable_noref(name: *const c_char) -> *mut SHELL_VAR; + pub fn find_variable(name: *const c_char) -> *mut SHELL_VAR; + pub fn find_global_variable(name: *const c_char) -> *mut SHELL_VAR; + pub fn find_tempenv_variable(name: *const c_char) -> *mut SHELL_VAR; + pub fn find_variable_notempenv(name: *const c_char) -> *mut SHELL_VAR; + pub fn find_variable_nameref_for_create(name: *const c_char, flags: c_int) -> *mut SHELL_VAR; + pub fn bind_variable(name: *const c_char, value: *mut c_char, flags: c_int) -> *mut SHELL_VAR; + + pub fn stupidly_hack_special_variables(name: *mut c_char); + +} diff --git a/bash-5.1/builtins_rust/setattr/src/lib.rs b/bash-5.1/builtins_rust/setattr/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..bbe8547bffdfa40a760cef10bb9e8e798a1b5c26 --- /dev/null +++ b/bash-5.1/builtins_rust/setattr/src/lib.rs @@ -0,0 +1,533 @@ +use libc::{c_int, c_uint, c_char, c_long, PT_NULL, c_void}; + +include!(concat!("intercdep.rs")); + +#[no_mangle] +pub extern "C" fn r_export_builtin(list: *mut WORD_LIST) -> c_int { + println!("r_export_builtin call"); + return set_or_show_attributes(list, att_exported, 0); +} + +#[no_mangle] +pub extern "C" fn r_readonly_builtin(list: *mut WORD_LIST) -> c_int { + println!("r_readonly_builtin call"); + return set_or_show_attributes(list, att_readonly, 0); +} + +#[no_mangle] +pub extern "C" fn set_or_show_attributes(mut list: *mut WORD_LIST, mut attribute: c_int, nodefs: c_int) -> c_int { + let mut assign_error: c_int = 0; + let mut any_failed: c_int = 0; + let mut undo: c_int = 0; + let mut functions_only: bool = false; + let mut arrays_only: c_int = 0; + let mut assoc_only: c_int = 0; + let mut name: *mut c_char; + let mut var: *mut SHELL_VAR; + let mut assign: c_int; + let mut aflags: c_int; + let mut tlist: *mut WORD_LIST; + let mut nlist: *mut WORD_LIST; + let mut w: *mut WORD_DESC; +unsafe { + reset_internal_getopt(); + let opt_str = std::ffi::CString::new("aAfnp").unwrap(); + let mut opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + while opt != -1 { + let opt_char:char=char::from(opt as u8); + match opt_char { + 'n' => undo = 1, + 'f' => functions_only = true, + 'a' => arrays_only = 1, + 'A' => assoc_only = 1, + _ => { + builtin_usage (); + return EX_USAGE; + } + } + opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + } + + list = loptend; + + if !list.is_null() { + if attribute & att_exported != 0 { + array_needs_making = 1; + } + if undo != 0 && (attribute & att_readonly) != 0 { + attribute &= !att_readonly; + } + while !list.is_null() { + name = (*(*list).word).word; + + if functions_only { + var = find_function(name); + if var.is_null() { + builtin_error("%s: not a function\0".as_ptr() as *const c_char, name); + any_failed += 1; + } else if (attribute & att_exported) != 0 && undo == 0 && + exportable_function_name(name) == 0 { + builtin_error("%s: cannot export\0".as_ptr() as *const c_char, name); + any_failed += 1; + } else { + if undo == 0 { + (*var).attributes |= attribute; + } else { + (*var).attributes &= !attribute; + } + } + list = (*list).next; + continue; + } + + assign = assignment(name, 0); + aflags = 0; + if assign != 0 { + *((name as usize + assign as usize) as *mut c_char) = b'\0' as c_char; + if *((name as usize + assign as usize - 1) as *mut c_char) == b'+' as c_char { + aflags |= ASS_APPEND; + *((name as usize + assign as usize - 1) as *mut c_char) = b'\0' as c_char; + } + } + + if legal_identifier(name) == 0 { + sh_invalidid(name); + if assign != 0 { + assign_error += 1; + } else { + any_failed += 1; + } + list = (*list).next; + continue; + } + + if assign != 0 { + *((name as usize + assign as usize) as *mut c_char) = b'=' as c_char; + if (aflags & ASS_APPEND) != 0 { + *((name as usize + assign as usize - 1) as *mut c_char) = b'+' as c_char; + } + + if arrays_only != 0 || assoc_only != 0 { + tlist = (*list).next; + (*list).next = PT_NULL as *mut WORD_LIST; + + let mut optw: [u8;8] = [0;8]; + optw[0] = b'-'; + optw[1] = b'g'; + let mut opti = 2; + if (attribute & att_readonly) != 0 { + optw[opti] = b'r'; + opti += 1; + } + if (attribute & att_exported) != 0 { + optw[opti] = b'x'; + opti += 1; + } + if (attribute & arrays_only) != 0 { + optw[opti] = b'a'; + opti += 1; + } else { + optw[opti] = b'A'; + opti += 1; + } + + w = make_word(optw.as_ptr() as *const c_char); + nlist = make_word_list(w, list); + + opt = declare_builtin(nlist); + if opt != EXECUTION_SUCCESS { + assign_error += 1; + } + (*list).next = tlist; + dispose_word(w); + libc::free(nlist as *mut c_void); + } else if do_assignment_no_expand(name) == 0 { + assign_error += 1; + } + *((name as usize + assign as usize) as *mut c_char) = b'\0' as c_char; + if (aflags & ASS_APPEND) != 0 { + *((name as usize + assign as usize - 1) as *mut c_char) = b'\0' as c_char; + } + } + + set_var_attribute(name, attribute, undo); + if assign != 0 { + *((name as usize + assign as usize) as *mut c_char) = b'=' as c_char; + if (aflags & ASS_APPEND) != 0 { + *((name as usize + assign as usize - 1) as *mut c_char) = b'+' as c_char; + } + } + list = (*list).next; + } + } else { + let mut variable_list: *mut *mut SHELL_VAR; + if (attribute & att_function) != 0 || functions_only { + variable_list = all_shell_functions(); + if attribute != att_function { + attribute &= !att_function; + } + } else { + variable_list = all_shell_variables(); + } + + if (attribute & att_array) != 0 { + arrays_only += 1; + if attribute != att_array { + attribute &= !att_array; + } + } else if (attribute & att_assoc) != 0 { + assoc_only += 1; + if attribute != att_assoc { + attribute &= !att_assoc; + } + } + + if !variable_list.is_null() { + let mut i = 0; + loop { + var = (variable_list as usize + 8 * i) as *mut SHELL_VAR; + if var.is_null() { + break; + } + + if arrays_only != 0 && ((*var).attributes & att_array) != 0 { + continue; + } else if assoc_only != 0 && ((*var).attributes & assoc_only) != 0 { + continue; + } + + if ((*var).attributes & (att_invisible | att_exported)) == (att_invisible | att_exported) { + continue; + } + + if ((*var).attributes & attribute) != 0 { + let pattr = (this_shell_builtin as usize == r_readonly_builtin as usize) || + (this_shell_builtin as usize == r_export_builtin as usize); + show_var_attributes(var, pattr as c_int, nodefs); + any_failed = sh_chkwrite(any_failed); + if any_failed != 0 { + break; + } + } + i += 1; + } + libc::free(variable_list as *mut c_void); + } + } +} + return if assign_error != 0 {EX_BADASSIGN} else if any_failed == 0 {EXECUTION_SUCCESS} else {EXECUTION_FAILURE}; +} + +#[no_mangle] +pub extern "C" fn show_all_var_attributes(list: *mut WORD_LIST, v: c_int, nodefs: c_int) -> c_int { + let mut i = 0; + let mut any_failed = 0; + let mut var: *mut SHELL_VAR; + let mut variable_list: *mut *mut SHELL_VAR; +unsafe { + variable_list = if v != 0 {all_shell_variables()} else {all_shell_functions()}; + if variable_list.is_null() { + return EXECUTION_SUCCESS; + } + + loop { + var = (variable_list as usize + 8 * i) as *mut SHELL_VAR; + if var.is_null() { + break; + } + + let pattr = (this_shell_builtin as usize == r_readonly_builtin as usize) || + (this_shell_builtin as usize == r_export_builtin as usize); + show_var_attributes(var, pattr as c_int, nodefs); + any_failed = sh_chkwrite(any_failed); + if any_failed != 0 { + break; + } + + i += 1; + } + + libc::free(variable_list as *mut c_void); +} + return if any_failed == 0 {EXECUTION_SUCCESS} else {EXECUTION_FAILURE}; +} + +#[no_mangle] +pub extern "C" fn show_local_var_attributes(v: c_int, nodefs: c_int) -> c_int { + let mut i = 0; + let mut any_failed = 0; + let mut var: *mut SHELL_VAR; + let mut variable_list: *mut *mut SHELL_VAR; +unsafe { + variable_list = all_local_variables(0); + if variable_list.is_null() { + return EXECUTION_SUCCESS; + } + + loop { + var = (variable_list as usize + 8 * i) as *mut SHELL_VAR; + if var.is_null() { + break; + } + + let pattr = (this_shell_builtin as usize == r_readonly_builtin as usize) || + (this_shell_builtin as usize == r_export_builtin as usize); + show_var_attributes(var, pattr as c_int, nodefs); + any_failed = sh_chkwrite(any_failed); + if any_failed != 0 { + break; + } + + i += 1; + } + + libc::free(variable_list as *mut c_void); +} + return if any_failed == 0 {EXECUTION_SUCCESS} else {EXECUTION_FAILURE}; +} + +#[no_mangle] +pub extern "C" fn show_var_attributes(var: *mut SHELL_VAR, pattr: c_int, mut nodefs: c_int) -> c_int { + + let mut flags = [0;16]; + +unsafe { + let i = var_attribute_string(var, pattr, flags.as_mut_ptr()); + + if ((*var).attributes & att_function) != 0 && nodefs == 0 && + (pattr == 0 || posixly_correct == 0) { + libc::printf("%s\n\0".as_ptr() as *const c_char, + named_function_string((*var).name, (*var).value as *mut COMMAND, FUNC_MULTILINE | FUNC_EXTERNAL)); + + nodefs += 1; + if pattr == 0 && i == 1 && flags[0] == b'f' as c_char { + return 0; + } + } + + if pattr == 0 || posixly_correct == 0 { + libc::printf("declare -%s \0".as_ptr() as *const c_char, if i != 0 {flags.as_ptr()} else {"-\0".as_ptr() as *const c_char}); + } else if i != 0 { + libc::printf("%s -%s \0".as_ptr() as *const c_char, this_command_name, flags.as_ptr()); + } else { + libc::printf("%s \0".as_ptr() as *const c_char, this_command_name); + } + + if ((*var).attributes & att_invisible) != 0 && + ((*var).attributes & att_array) != 0 && + ((*var).attributes & att_assoc) != 0 { + libc::printf("%s\n\0".as_ptr() as *const c_char, (*var).name); + } else if ((*var).attributes & att_array) != 0 { + print_array_assignment(var, 0); + } else if ((*var).attributes & att_assoc) != 0 { + print_assoc_assignment(var, 0); + } else if nodefs != 0 || + (((*var).attributes & att_function) != 0 && pattr != 0 && posixly_correct != 0) { + libc::printf("%s\n\0".as_ptr() as *const c_char, (*var).name); + } else if ((*var).attributes & att_function) != 0 { + libc::printf("%s\n\0".as_ptr() as *const c_char, + named_function_string((*var).name, (*var).value as *mut COMMAND, FUNC_MULTILINE | FUNC_EXTERNAL)); + } else if ((*var).attributes & att_invisible) != 0 && (*var).value.is_null() { + libc::printf("%s\n\0".as_ptr() as *const c_char, (*var).name); + } else { + let x = sh_double_quote((*var).value); + libc::printf("%s=%s\n\0".as_ptr() as *const c_char, (*var).name, x); + libc::free(x as *mut c_void); + } +} + return 0; +} + +#[no_mangle] +pub extern "C" fn show_name_attributes(name: *mut c_char, nodefs: c_int) -> c_int { +unsafe { + let var = find_variable_noref(name); + if !var.is_null() { + let pattr = (this_shell_builtin as usize == r_readonly_builtin as usize) || + (this_shell_builtin as usize == r_export_builtin as usize); + show_var_attributes(var, pattr as c_int, nodefs); + return 0; + } else { + return 1; + } +} +} + +#[no_mangle] +pub extern "C" fn show_localname_attributes(name: *mut c_char, nodefs: c_int) -> c_int { +unsafe { + let var = find_variable_noref(name); + let cond = var.is_null() && ((*var).attributes & att_local) != 0 && (*var).context == variable_context; + if cond { + let pattr = (this_shell_builtin as usize == r_readonly_builtin as usize) || + (this_shell_builtin as usize == r_export_builtin as usize); + show_var_attributes(var, pattr as c_int, nodefs); + return 0; + } else { + return 1; + } +} +} + +#[no_mangle] +pub extern "C" fn show_func_attributes(name: *mut c_char, nodefs: c_int) -> c_int { + unsafe { + let var = find_function(name); + if !var.is_null() { + let pattr = (this_shell_builtin as usize == r_readonly_builtin as usize) || + (this_shell_builtin as usize == r_export_builtin as usize); + show_var_attributes(var, pattr as c_int, nodefs); + return 0; + } else { + return 1; + } + } +} + +#[no_mangle] +pub extern "C" fn set_var_attribute(name: *mut c_char, attribute: c_int, undo: c_int) { + let mut var: *mut SHELL_VAR; + let mut tvalue: *mut c_char; +unsafe { + if undo != 0 { + var = find_variable(name); + } else { + let tv = find_tempenv_variable(name); + if !tv.is_null() && ((*tv).attributes & att_tempvar) != 0 { + tvalue = if !(*tv).value.is_null() { + libc::strdup((*tv).value) + } else {"\0".as_ptr() as *mut c_char}; + + var = bind_variable((*tv).name, tvalue, 0); + if var.is_null() { + libc::free(tvalue as *mut c_void); + return; + } + (*var).attributes |= (*tv).attributes & (!att_tempvar); + if posixly_correct != 0 || shell_compatibility_level <= 44 { + if (*var).context == 0 && (attribute & att_readonly) != 0 { + let v = find_global_variable((*tv).name); + if v as usize != var as usize { + (*tv).attributes |= att_propagate; + } + } else { + (*tv).attributes |= att_propagate; + } + + if (*var).context != 0 { + (*var).attributes |= att_propagate; + } + } + if undo == 0 { + (*tv).attributes |= attribute; + } else { + (*tv).attributes &= !attribute; + } + + stupidly_hack_special_variables((*tv).name); + libc::free(tvalue as *mut c_void); + } else { + var = find_variable_notempenv(name); + if var.is_null() { + let refvar = find_variable_nameref_for_create(name, 0); + if cmp_two(std::mem::transmute(refvar),std::mem::transmute(&nameref_invalid_value)) { + return; + } + } + if var.is_null() { + var = bind_variable(name, PT_NULL as *mut c_char, 0); + if !var.is_null() { + (*var).attributes |= att_invisible; + } + } else if (*var).context != 0 { + (*var).attributes |= att_propagate; + } + } + } + + if !var.is_null() { + if undo == 0 { + (*var).attributes |= attribute; + } else { + (*var).attributes &= !attribute; + } + } + + if !var.is_null() && (((*var).attributes & att_exported) != 0 || (attribute & att_exported) != 0) { + array_needs_making += 1; + } +} +} + +#[no_mangle] +pub extern "C" fn var_attribute_string(var: *mut SHELL_VAR, pattr: c_int, flags: *mut c_char) -> c_int { + let mut i = 0; +unsafe { + if pattr == 0 || posixly_correct == 0 { + if ((*var).attributes & att_array) != 0 { + *((flags as usize + i) as *mut c_char) = b'a' as c_char; + i += 1; + } + if ((*var).attributes & att_assoc) != 0 { + *((flags as usize + i) as *mut c_char) = b'A' as c_char; + i += 1; + } + if ((*var).attributes & att_function) != 0 { + *((flags as usize + i) as *mut c_char) = b'f' as c_char; + i += 1; + } + if ((*var).attributes & att_integer) != 0 { + *((flags as usize + i) as *mut c_char) = b'i' as c_char; + i += 1; + } + if ((*var).attributes & att_nameref) != 0 { + *((flags as usize + i) as *mut c_char) = b'n' as c_char; + i += 1; + } + if ((*var).attributes & att_readonly) != 0 { + *((flags as usize + i) as *mut c_char) = b'r' as c_char; + i += 1; + } + if ((*var).attributes & att_trace) != 0 { + *((flags as usize + i) as *mut c_char) = b't' as c_char; + i += 1; + } + if ((*var).attributes & att_exported) != 0 { + *((flags as usize + i) as *mut c_char) = b'x' as c_char; + i += 1; + } + if ((*var).attributes & att_capcase) != 0 { + *((flags as usize + i) as *mut c_char) = b'c' as c_char; + i += 1; + } + if ((*var).attributes & att_lowercase) != 0 { + *((flags as usize + i) as *mut c_char) = b'l' as c_char; + i += 1; + } + if ((*var).attributes & att_uppercase) != 0 { + *((flags as usize + i) as *mut c_char) = b'u' as c_char; + i += 1; + } + } else { + if ((*var).attributes & att_array) != 0 { + *((flags as usize + i) as *mut c_char) = b'a' as c_char; + i += 1; + } + if ((*var).attributes & att_assoc) != 0 { + *((flags as usize + i) as *mut c_char) = b'A' as c_char; + i += 1; + } + if ((*var).attributes & att_function) != 0 { + *((flags as usize + i) as *mut c_char) = b'f' as c_char; + i += 1; + } + } + + *((flags as usize + i) as *mut c_char) = b'\0' as c_char; +} + return i as c_int; +} + +unsafe fn cmp_two(a: usize, b: usize) -> bool { + return a == b; +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/shift/Cargo.toml b/bash-5.1/builtins_rust/shift/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..7ac783fbf767a9b4b648c03fe0a0dcd42c9c43a8 --- /dev/null +++ b/bash-5.1/builtins_rust/shift/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "shift" +version = "0.1.0" +edition = "2018" +authors = ["lvgenggeng"] +build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "rshift" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/shift/src/intercdep.rs b/bash-5.1/builtins_rust/shift/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..24ce4a1bc3165a754e27ea6796fb3c135f38641a --- /dev/null +++ b/bash-5.1/builtins_rust/shift/src/intercdep.rs @@ -0,0 +1,36 @@ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +pub const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_USAGE: c_int = 258; + +extern "C" { + pub fn builtin_usage(); + pub fn builtin_help(); + pub fn builtin_error(format: *const c_char, ...); + + pub fn get_numeric_arg(list: *mut WORD_LIST, fatal: c_int, count: c_long) -> c_int; + pub fn number_of_args() -> c_int; + pub fn sh_erange(s: *mut c_char, desc: *mut c_char); + pub fn clear_dollar_vars(); + pub fn shift_args(times: c_int); + pub fn invalidate_cached_quoted_dollar_at(); + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; +} diff --git a/bash-5.1/builtins_rust/shift/src/lib.rs b/bash-5.1/builtins_rust/shift/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..00fb8f8749d606b5da65d76ac0365cef366abbf3 --- /dev/null +++ b/bash-5.1/builtins_rust/shift/src/lib.rs @@ -0,0 +1,47 @@ +use libc::{c_int, c_char, c_long, PT_NULL}; + +include!(concat!("intercdep.rs")); + +pub static print_shift_error: c_int = 0; + +#[no_mangle] +pub extern "C" fn r_shift_builtin(list: *mut WORD_LIST) -> i32 { + println!("r_shift_builtin call"); + +unsafe { + if !list.is_null() && !(*list).word.is_null() && + libc::strcmp((*((*list).word)).word, "--help\0".as_ptr() as *const c_char) == 0 { + builtin_help (); + return EX_USAGE; + } + + let mut times: c_int = 0; + if get_numeric_arg(list, 0, std::mem::transmute(×)) == 0 { + return EXECUTION_FAILURE; + } + + if times == 0 { + return EXECUTION_SUCCESS; + } else if times < 0 { + let s = if list.is_null() {PT_NULL as *mut c_char} else {(*(*list).word).word}; + sh_erange(s,"shift count\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + + let nargs = number_of_args(); + if times > nargs { + if print_shift_error != 0 { + let s = if list.is_null() {PT_NULL as *mut c_char} else {(*(*list).word).word}; + sh_erange(s,"shift count\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + } else if times == nargs { + clear_dollar_vars(); + } else { + shift_args(times); + } + + invalidate_cached_quoted_dollar_at(); +} + return EXECUTION_SUCCESS; +} diff --git a/bash-5.1/builtins_rust/source/Cargo.toml b/bash-5.1/builtins_rust/source/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..ba9e39c0236ff93eeec980c6e4b4be74a3fe1a83 --- /dev/null +++ b/bash-5.1/builtins_rust/source/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["huzhengming"] +name = "rsource" +version = "0.0.1" +#build = "../build.rs" +edition = "2018" + + +[dependencies] +lazy_static = "1.4.0" +libc = "0.2" +nix = "0.23.0" + +[lib] +crate-type = ["cdylib"] +name = "rsource" diff --git a/bash-5.1/builtins_rust/source/src/lib.rs b/bash-5.1/builtins_rust/source/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..f3e3d5e03a0207b9fab991c51bcd3e14502c3e24 --- /dev/null +++ b/bash-5.1/builtins_rust/source/src/lib.rs @@ -0,0 +1,416 @@ +extern crate libc; +extern crate nix; + +use libc::{c_char, c_long, c_void}; +use std::{ffi::CString}; + +#[repr(C)] +pub struct WORD_DESC { + pub word: *mut libc::c_char, + pub flags:libc::c_int +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub struct WORD_LIST { + next: *mut WORD_LIST, + word: *mut WORD_DESC +} + +#[repr(u8)] +enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select, + cm_connection, cm_function_def, cm_until, cm_group, + cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc +} + +#[repr(u8)] +#[derive(Copy,Clone)] +enum r_instruction { + r_output_direction, r_input_direction, r_inputa_direction, + r_appending_to, r_reading_until, r_reading_string, + r_duplicating_input, r_duplicating_output, r_deblank_reading_until, + r_close_this, r_err_and_out, r_input_output, r_output_force, + r_duplicating_input_word, r_duplicating_output_word, + r_move_input, r_move_output, r_move_input_word, r_move_output_word, + r_append_err_and_out +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub union REDIRECTEE { + dest:libc::c_int, + filename:* mut WORD_DESC +} + +#[repr(C)] +pub union REDIRECT { + next:*mut REDIRECT, + redirector:REDIRECTEE, + rflags:libc::c_int, + flags:libc::c_int, + instruction:r_instruction, + redirectee:REDIRECTEE, + here_doc_eof:*mut c_char +} + +/* FOR command. */ +#[repr(C)] +pub struct for_com { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct PATTERN_LIST { + next:* mut PATTERN_LIST, + patterns:* mut WORD_LIST, + action:*mut COMMAND, + flags:libc::c_int +} + +#[repr(C)] +pub struct case_com { + flags:libc::c_int, + line:libc::c_int, + word:*mut WORD_DESC, + clauses:*mut PATTERN_LIST +} + +#[repr(C)] +pub struct while_com { + flags:libc::c_int, + test:*mut COMMAND, + action:*mut COMMAND +} + +#[repr(C)] +pub struct if_com { + flags:libc::c_int, + test:*mut COMMAND, + true_case:*mut COMMAND, + false_case:*mut COMMAND +} + +#[repr(C)] +pub struct connection { + ignore:libc::c_int, + first:*mut COMMAND, + second:*mut COMMAND, + connector:libc::c_int +} + +#[repr(C)] +pub struct simple_com { + flags:libc::c_int, + line:libc::c_int, + words:*mut WORD_LIST, + redirects:*mut REDIRECT +} + +#[repr(C)] +pub struct function_def { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + command:*mut COMMAND, + source_file:*mut c_char +} + +#[repr(C)] +pub struct group_com { + ignore:libc::c_int, + command:*mut COMMAND, + source_file:*mut c_char +} + +#[repr(C)] +pub struct select_com { + flags:libc::c_int, + line:libc::c_int, + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct arith_com { + flags:libc::c_int, + line:libc::c_int, + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct cond_com { + flags:libc::c_int, + line:libc::c_int, + type_c:libc::c_int, + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct arith_for_com { + flags:libc::c_int, + line:libc::c_int, + init:*mut WORD_LIST, + test:*mut WORD_LIST, + step:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct subshell_com { + flags:i32, + line:i32, + command:*mut COMMAND +} + +#[repr(C)] +pub struct coproc_com { + flags:i32, + name:*mut c_char, + command:*mut COMMAND +} + +#[repr(C)] +pub union VALUE_COMMAND { + For:*mut for_com, + Case:*mut case_com, + While:*mut while_com, + If:*mut if_com, + Connection:*mut connection, + Simple:*mut simple_com, + Function_def:*mut function_def, + Group:*mut group_com, + Select:*mut select_com, + Arith:*mut arith_com, + Cond:*mut cond_com, + ArithFor:*mut arith_for_com, + Subshell:*mut subshell_com, + Coproc:*mut coproc_com +} + +#[repr(C)] +pub struct COMMAND { + type_c:command_type, + flags:i32, + line:i32, + redirects:*mut REDIRECT, + value:VALUE_COMMAND +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => {1} +} + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! ARGS_SETBLTIN { + () => { + 0x04 + } +} + +#[macro_export] +macro_rules! EXITPROG { + () => { + 3 + } +} +pub union Functions { + f_xfree:unsafe extern "C" fn(str1:* mut c_void), + f_maybe_pop_dollar_vars: unsafe extern "C" fn(), + f_maybe_set_debug_trap:unsafe extern "C" fn(* mut c_char) +} + +extern "C" { + static variable_context:i32; + fn dollar_vars_changed ()->i32; + fn dispose_saved_dollar_vars (); + fn pop_dollar_vars (); + static mut debugging_mode:i32; + fn pop_args (); + fn set_dollar_vars_unchanged (); + fn invalidate_cached_quoted_dollar_at (); + fn no_options (list:* mut WORD_LIST)->i32; + static mut loptend:*mut WORD_LIST; + fn builtin_usage(); + fn builtin_error(err:*const c_char,...); + static mut restricted:i32; + fn sh_restricted (word:* mut c_char); + static mut posixly_correct:i32; + static mut source_searches_cwd:i32; + fn printable_filename (path:* mut c_char, tab:i32)->* mut c_char; + fn absolute_pathname (path:* const c_char)->i32; + static source_uses_path:i32; + fn find_path_file (path:* const c_char)->* mut c_char; + static mut interactive_shell:i32; + static mut executing_command_builtin:i32; + static mut last_command_exit_value:i32; + fn jump_to_top_level(level:i32); + fn begin_unwind_frame (str: * mut c_char); + fn add_unwind_protect(f:Functions,args:* mut c_char); + fn maybe_set_debug_trap (str: * mut c_char); + fn xfree(str1:* mut c_void); + fn push_dollar_vars (); + static shell_compatibility_level:i32; + fn init_bash_argv(); + fn remember_args (list:* mut WORD_LIST, argc:i32); + fn push_args (list:* mut WORD_LIST); + static mut function_trace_mode:i32; + fn signal_is_trapped (sig:i32)->i32; + fn signal_is_ignored (sig:i32)->i32; + static trap_list:[* mut c_char;68]; + fn restore_default_signal (sig:i32); + fn source_file (name:* const c_char, sflags:i32)->i32; + fn run_unwind_frame (filename:* mut c_char); +} + +#[no_mangle] +pub extern "C" fn r_maybe_pop_dollar_vars () +{ + unsafe { + if variable_context == 0 && (dollar_vars_changed () & ARGS_SETBLTIN!()) !=0 { + dispose_saved_dollar_vars (); + } else { + pop_dollar_vars (); + } + if debugging_mode !=0 { + pop_args (); /* restore BASH_ARGC and BASH_ARGV */ + } + + set_dollar_vars_unchanged (); + invalidate_cached_quoted_dollar_at (); /* just invalidate to be safe */ + } +} + +unsafe fn savestring(x:* mut c_char)->* mut c_char +{ + let str1:* mut c_char=libc::malloc(1 + libc::strlen (x as * const c_char)) as * mut c_char; + return libc::strcpy(str1,x as * const c_char); +} + +unsafe fn TRAP_STRING(s:i32)->* mut c_char { + if signal_is_trapped (s) !=0 && signal_is_ignored (s) == 0 { + return trap_list[s as usize]; + } else { + return std::ptr::null_mut(); + } +} + +unsafe fn DEBUG_TRAP()->i32 +{ + return libc::SIGRTMAX() +1; +} + +#[no_mangle] +pub extern "C" fn r_source_builtin (list:* mut WORD_LIST)->i32 +{ + let mut result:i32; + let mut filename:*mut c_char; + let mut debug_trap:* mut c_char; + let x:* mut c_char; + unsafe { + if no_options (list) !=0{ + return EX_USAGE!(); + } + + let mut llist:* mut WORD_LIST = loptend.clone(); + + if list == std::ptr::null_mut() { + builtin_error (CString::new("filename argument required").unwrap().as_ptr()); + builtin_usage (); + return EX_USAGE!(); + } + + if restricted !=0 && libc::strchr ((*(*llist).word).word, '/' as libc::c_int) != std::ptr::null_mut() { + sh_restricted ((*(*llist).word).word); + return EXECUTION_FAILURE!(); + } + + filename = std::ptr::null_mut(); + /* XXX -- should this be absolute_pathname? */ + if posixly_correct !=0 && libc::strchr ((*(*llist).word).word, '/' as libc::c_int) != std::ptr::null_mut() { + filename = savestring ((*(*llist).word).word); + } else if absolute_pathname ((*(*llist).word).word) !=0 { + filename = savestring ((*(*llist).word).word); + } else if source_uses_path !=0 { + filename = find_path_file ((*(*llist).word).word); + } + + if filename == std::ptr::null_mut() { + if source_searches_cwd == 0 { + x = printable_filename ((*(*llist).word).word, 0); + builtin_error (CString::new("%s: file not found").unwrap().as_ptr(), x); + if x != (*(*llist).word).word { + libc::free (x as * mut c_void); + } + + if posixly_correct !=0 && interactive_shell == 0 && executing_command_builtin == 0 { + last_command_exit_value = EXECUTION_FAILURE!(); + jump_to_top_level (EXITPROG!()); + } + return EXECUTION_FAILURE!(); + } else { + filename = savestring ((*(*llist).word).word); + } + } + + begin_unwind_frame (CString::new("source").unwrap().as_ptr() as * mut c_char); + let xf:Functions=Functions{f_xfree :xfree}; + add_unwind_protect (xf, filename); + + if (*list).next != std::ptr::null_mut() { + push_dollar_vars (); + let xvars:Functions=Functions{f_maybe_pop_dollar_vars:r_maybe_pop_dollar_vars}; + add_unwind_protect (xvars, std::ptr::null_mut()); + if debugging_mode !=0 || shell_compatibility_level <= 44 { + init_bash_argv (); /* Initialize BASH_ARGV and BASH_ARGC */ + } + + remember_args ((*list).next, 1); + if debugging_mode !=0 { + push_args ((*list).next); /* Update BASH_ARGV and BASH_ARGC */ + } + + } + set_dollar_vars_unchanged (); + + /* Don't inherit the DEBUG trap unless function_trace_mode (overloaded) + is set. XXX - should sourced files inherit the RETURN trap? Functions + don't. */ + debug_trap = TRAP_STRING (DEBUG_TRAP()); + if debug_trap != std::ptr::null_mut() && function_trace_mode == 0 { + debug_trap = savestring (debug_trap); + let xf1:Functions=Functions{f_xfree :xfree}; + add_unwind_protect (xf1, debug_trap); + + let xfmaybe_set_debug_trap:Functions=Functions{f_maybe_set_debug_trap :maybe_set_debug_trap}; + add_unwind_protect (xfmaybe_set_debug_trap, debug_trap); + restore_default_signal (DEBUG_TRAP()); + } + + result = source_file (filename, (list !=std::ptr::null_mut() && (*list).next !=std::ptr::null_mut()) as i32); + + run_unwind_frame (CString::new("source").unwrap().as_ptr() as * mut c_char); + + return result; + } +} + +#[no_mangle] +pub extern "C" fn cmd_name() ->*const u8 { + return b"source" as *const u8; +} + +#[no_mangle] +pub extern "C" fn run(list : *mut WORD_LIST)->i32 { + return r_source_builtin(list); +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/suspend/Cargo.toml b/bash-5.1/builtins_rust/suspend/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..a39b1e695f0a7b91ab2d44b8c45b284924d1974c --- /dev/null +++ b/bash-5.1/builtins_rust/suspend/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "suspend" +version = "0.1.0" +edition = "2018" +authors = ["lvgenggeng"] +build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "rsuspend" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/suspend/src/intercdep.rs b/bash-5.1/builtins_rust/suspend/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..5cf962bf97e42c76afda89d62a866ac58f7d3389 --- /dev/null +++ b/bash-5.1/builtins_rust/suspend/src/intercdep.rs @@ -0,0 +1,42 @@ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +pub const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_USAGE: c_int = 258; + +pub type SigHandler = unsafe extern "C" fn(arg1: c_int); + +extern "C" { + pub fn reset_internal_getopt(); + pub fn internal_getopt(list: *mut WORD_LIST, opts: *mut c_char) -> c_int; + pub fn builtin_usage(); + pub fn builtin_help(); + pub fn builtin_error(format: *const c_char, ...); + + pub fn sh_nojobs(s: *mut c_char); + pub fn no_args(list: *mut WORD_LIST); + pub fn killpg(pgrp: libc::pid_t, sig: c_int) -> c_int; + + pub fn set_signal_handler(arg1: c_int, arg2: *mut SigHandler) -> *mut SigHandler; + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + pub static mut job_control: c_int; + pub static mut login_shell: c_int; + pub static mut shell_pgrp: libc::pid_t; +} diff --git a/bash-5.1/builtins_rust/suspend/src/lib.rs b/bash-5.1/builtins_rust/suspend/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..b92a6ff3dbb49ca1fdf1b6dcb75a5c2e1563643e --- /dev/null +++ b/bash-5.1/builtins_rust/suspend/src/lib.rs @@ -0,0 +1,54 @@ +use libc::{c_int, c_char, c_long, PT_NULL}; + +include!(concat!("intercdep.rs")); + +pub static mut old_cont: *mut SigHandler = PT_NULL as *mut SigHandler; + +#[no_mangle] +pub extern "C" fn r_suspend_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_suspend_builtin call"); + + let mut opt: c_int; + let mut force: c_int = 0; + +unsafe { + reset_internal_getopt(); + let opt_str = "f:\0".as_ptr() as *mut c_char; + opt = internal_getopt (list, opt_str); + while opt != -1 { + let opt_char:char=char::from(opt as u8); + match opt_char { + 'f' => force += 1, + _ => { + builtin_usage (); + return EX_USAGE; + } + } + opt = internal_getopt (list, opt_str); + } + list = loptend; + + if job_control == 0 { + sh_nojobs("cannot suspend\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + + if force == 0 { + no_args(list); + if login_shell != 0 { + builtin_error("cannot suspend a login shell\0".as_ptr() as *mut c_char); + return EXECUTION_FAILURE; + } + } + + old_cont = set_signal_handler(libc::SIGCONT, std::mem::transmute(suspend_continue as usize)); + + killpg(shell_pgrp, libc::SIGSTOP); +} + return EXECUTION_SUCCESS; +} + +unsafe fn suspend_continue(sig: c_int) +{ + set_signal_handler(libc::SIGCONT, old_cont); +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/test/Cargo.toml b/bash-5.1/builtins_rust/test/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..bfc049eeb901533910a109998cd8877e35e9521d --- /dev/null +++ b/bash-5.1/builtins_rust/test/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "test" +version = "0.1.0" +edition = "2018" +authors = ["lvgenggeng"] +build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "rtest" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/test/src/intercdep.rs b/bash-5.1/builtins_rust/test/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..060c9f4665e026babbf0727a80759352f2221062 --- /dev/null +++ b/bash-5.1/builtins_rust/test/src/intercdep.rs @@ -0,0 +1,32 @@ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +pub const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_BADUSAGE : c_int = 2; +pub const EX_USAGE: c_int = 258; + +extern "C" { + pub fn builtin_error(format: *const c_char, ...); + + pub fn make_builtin_argv(list: *mut WORD_LIST, ip: *mut c_int) -> *mut *mut c_char; + pub fn test_command (margc: c_int, margv: *mut *mut c_char) -> c_int; + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + pub static mut this_command_name: *mut c_char; +} diff --git a/bash-5.1/builtins_rust/test/src/lib.rs b/bash-5.1/builtins_rust/test/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..e45d4aada38c63c061bb4cc35dd4af6790785eeb --- /dev/null +++ b/bash-5.1/builtins_rust/test/src/lib.rs @@ -0,0 +1,25 @@ +use libc::{c_int, c_char, c_void}; + +include!(concat!("intercdep.rs")); + +#[no_mangle] +pub extern "C" fn r_test_builtin(list: *mut WORD_LIST) -> i32 { + println!("r_test_builtin call"); + + let result: c_int; + let mut argc: c_int = 0; +unsafe { + if list.is_null() { + if *this_command_name == b'[' as c_char && + *((this_command_name as usize + 1) as *mut c_char) == 0 { + builtin_error("missing `]'\0".as_ptr() as *mut c_char); + return EX_BADUSAGE; + } + return EXECUTION_FAILURE; + } + let argv = make_builtin_argv(list, std::mem::transmute(&argc)); + result = test_command(argc, argv); + libc::free(argv as *mut c_void); +} + return result; +} diff --git a/bash-5.1/builtins_rust/times/Cargo.toml b/bash-5.1/builtins_rust/times/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..fa1ecc876eb9041e95bf60e9036c57690542ef11 --- /dev/null +++ b/bash-5.1/builtins_rust/times/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "times" +version = "0.1.0" +edition = "2018" +authors = ["lvgenggeng"] +build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "rtimes" +crate-type = ["cdylib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/times/src/intercdep.rs b/bash-5.1/builtins_rust/times/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..beca33271fcf59095c25ce24a98831c8c8797e55 --- /dev/null +++ b/bash-5.1/builtins_rust/times/src/intercdep.rs @@ -0,0 +1,28 @@ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +pub const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_USAGE: c_int = 258; + +extern "C" { + pub fn no_options(list: *mut WORD_LIST) -> c_int; + pub fn print_timeval(fp: *mut libc::FILE, tvp: *mut libc::timeval); + pub fn sh_chkwrite(s: c_int) -> c_int; + + pub static stdout: *mut libc::FILE; +} diff --git a/bash-5.1/builtins_rust/times/src/lib.rs b/bash-5.1/builtins_rust/times/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..1632fee52d5ad247c527cb86bbb3b89d54369e7a --- /dev/null +++ b/bash-5.1/builtins_rust/times/src/lib.rs @@ -0,0 +1,34 @@ +use libc::{c_int, c_char}; + +include!(concat!("intercdep.rs")); + +#[no_mangle] +pub extern "C" fn r_times_builtin(list: *mut WORD_LIST) -> i32 { + println!("r_times_builtin call"); + +unsafe { + + if no_options(list) != 0 { + return EX_USAGE; + } + + let mut curr: libc::rusage = std::mem::zeroed(); + let mut kids: libc::rusage = std::mem::zeroed(); + libc::putchar(b'\n' as c_int); + + libc::getrusage(libc::RUSAGE_SELF, std::mem::transmute(&curr)); + libc::getrusage(libc::RUSAGE_CHILDREN, std::mem::transmute(&kids)); + + print_timeval(stdout, std::mem::transmute(&curr.ru_utime)); + libc::putchar(b' ' as c_int); + print_timeval(stdout, std::mem::transmute(&curr.ru_stime)); + libc::putchar(b'\n' as c_int); + + print_timeval(stdout, std::mem::transmute(&kids.ru_utime)); + libc::putchar(b' ' as c_int); + print_timeval(stdout, std::mem::transmute(&kids.ru_stime)); + libc::putchar(b'\n' as c_int); + + return sh_chkwrite(EXECUTION_SUCCESS); +} +} diff --git a/bash-5.1/builtins_rust/trap/Cargo.toml b/bash-5.1/builtins_rust/trap/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..46e8bb2571a9a3022b8f1dc0c3e3399d5f85cc39 --- /dev/null +++ b/bash-5.1/builtins_rust/trap/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "trap" +version = "0.1.0" +edition = "2018" +authors = ["lvgenggeng"] +build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "rtrap" +crate-type = ["staticlib"] + +[dependencies] +libc = "0.2" +nix = "0.23" diff --git a/bash-5.1/builtins_rust/trap/src/intercdep.rs b/bash-5.1/builtins_rust/trap/src/intercdep.rs new file mode 100644 index 0000000000000000000000000000000000000000..5b22830ad602c5f429edeafafa572f7c852c54bb --- /dev/null +++ b/bash-5.1/builtins_rust/trap/src/intercdep.rs @@ -0,0 +1,74 @@ + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_desc { + pub word: *mut c_char, + pub flags: c_int, +} +pub type WORD_DESC = word_desc; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct word_list { + pub next: *mut word_list, + pub word: *mut WORD_DESC, +} +pub type WORD_LIST = word_list; + +pub type SigHandler = unsafe extern "C" fn(arg1: c_int); + +pub const EXECUTION_SUCCESS : c_int = 0; +pub const EXECUTION_FAILURE : c_int = 1; +pub const EX_USAGE: c_int = 258; + +pub const DSIG_SIGPREFIX: c_int = 0x01; +pub const DSIG_NOCASE: c_int = 0x02; + +pub const BASH_NSIG: c_int = (64 + 1) + 3; +pub const NO_SIG: c_int = -1; + +pub const SET: c_int = 0; +pub const REVERT: c_int = 1; +pub const IGNORE: c_int = 2; + +pub const SUBSHELL_RESETTRAP: c_int = 0x80; + +extern "C" { + pub fn reset_internal_getopt(); + pub fn internal_getopt(list: *mut WORD_LIST, opts: *mut c_char) -> c_int; + pub fn builtin_usage(); + pub fn builtin_error(format: *const c_char, ...); + + pub fn sh_chkwrite(s: c_int) -> c_int; + pub fn display_signal_list(list: *mut WORD_LIST, forcecols: c_int) -> c_int; + pub fn initialize_terminating_signals(); + pub fn get_all_original_signals(); + pub fn free_trap_strings(); + pub fn ignore_signal(sig: c_int); + pub fn set_signal(sig: c_int, s: *mut c_char); + pub fn restore_default_signal(sig: c_int); + pub fn sigint_sighandler(sig: c_int); + pub fn termsig_sighandler(sig: c_int); + pub fn set_signal_handler(arg1: c_int, arg2: *mut SigHandler) -> *mut SigHandler; + + pub fn all_digits(s: *const c_char) -> c_int; + pub fn decode_signal(s: *mut c_char, flags: c_int) -> c_int; + + pub fn signal_is_hard_ignored(sig: c_int) -> c_int; + pub fn sh_single_quote(s: *const c_char) -> *mut c_char; + pub fn signal_name(sig: c_int) -> *mut c_char; + + pub fn sh_invalidsig(s: *mut c_char); + + pub static mut list_optarg : *mut libc::c_char; + pub static mut loptend : *mut WORD_LIST; + + pub static trap_list: [*mut c_char; BASH_NSIG as usize]; + pub static posixly_correct: c_int; + pub static mut subshell_environment: c_int; + pub static interactive: c_int; + pub static interactive_shell: c_int; + pub static sourcelevel: c_int; + pub static running_trap: c_int; + pub static parse_and_execute_level: c_int; +} \ No newline at end of file diff --git a/bash-5.1/builtins_rust/trap/src/lib.rs b/bash-5.1/builtins_rust/trap/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..68ebe612e345dfe95a3b778f3a7f45c6cab1e5dc --- /dev/null +++ b/bash-5.1/builtins_rust/trap/src/lib.rs @@ -0,0 +1,178 @@ +use std::{ffi::CString}; + +use libc::{c_int, c_char, c_void, PT_NULL}; + +include!(concat!("intercdep.rs")); + + +#[no_mangle] +pub extern "C" fn r_trap_builtin(mut list: *mut WORD_LIST) -> i32 { + println!("r_trap_builtin call"); + + let mut list_signal_names: c_int = 0; + let mut display: c_int = 0; + let mut result: c_int = EXECUTION_SUCCESS; + +unsafe { + reset_internal_getopt(); + let opt_str = CString::new("lp").unwrap(); + let mut opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + while opt != -1 { + let opt_char:char=char::from(opt as u8); + match opt_char { + 'l' => list_signal_names += 1, + 'p' => display += 1, + _ => { + builtin_usage (); + return EX_USAGE; + } + } + opt = internal_getopt (list, opt_str.as_ptr() as * mut c_char); + } + list = loptend; + + opt = DSIG_NOCASE | DSIG_SIGPREFIX; + + if list_signal_names != 0 { + return sh_chkwrite(display_signal_list(PT_NULL as *mut WORD_LIST, 1)); + } else if display != 0 || list.is_null() { + initialize_terminating_signals(); + get_all_original_signals(); + return sh_chkwrite(display_traps(list, (display != 0 && posixly_correct != 0) as c_int)); + } else { + let mut operation = SET; + let first_arg = (*(*list).word).word; + let first_signal = !first_arg.is_null() && *first_arg != 0 && + all_digits(first_arg) != 0 && decode_signal (first_arg,opt) != NO_SIG; + if first_signal { + operation = REVERT; + } else if posixly_correct == 0 && !first_arg.is_null() && *first_arg != 0 && + (*first_arg != b'-' as c_char || *((first_arg as usize + 1) as *mut c_char) != 0 ) && + decode_signal (first_arg,opt) != NO_SIG && (*list).next.is_null() { + operation = REVERT; + } else { + list = (*list).next; + if list.is_null() { + builtin_usage(); + return EX_USAGE; + } else if *first_arg == b'\0' as c_char { + operation = IGNORE; + } else if *first_arg == b'-' as c_char && *((first_arg as usize + 1) as *mut c_char) == 0 { + operation = REVERT; + } + } + + if subshell_environment & SUBSHELL_RESETTRAP != 0 { + free_trap_strings(); + subshell_environment &= !SUBSHELL_RESETTRAP; + } + + let mut sig: c_int; + while !list.is_null() { + sig = decode_signal((*(*list).word).word, opt); + if sig == NO_SIG { + sh_invalidsig((*(*list).word).word); + result = EXECUTION_FAILURE; + } else { + match operation { + SET => set_signal(sig, first_arg), + IGNORE => ignore_signal(sig), + REVERT => { + restore_default_signal(sig); + match sig { + libc::SIGINT => { + if interactive != 0 { + set_signal_handler(libc::SIGINT, sigint_sighandler as *mut SigHandler); + } else if interactive_shell != 0 && + (sourcelevel != 0 || running_trap != 0 || parse_and_execute_level != 0) { + set_signal_handler(libc::SIGINT, sigint_sighandler as *mut SigHandler); + } else { + set_signal_handler(libc::SIGINT, termsig_sighandler as *mut SigHandler); + } + } + libc::SIGQUIT => { + set_signal_handler(libc::SIGQUIT, std::mem::transmute(1_usize)); + } + libc::SIGTERM | libc::SIGTTIN | libc::SIGTTOU | libc::SIGTSTP => { + if interactive != 0 { + set_signal_handler(sig, std::mem::transmute(1_usize)); + } + } + _ => (), + } + break; + } + _ => (), + } + } + + list = (*list).next; + } + } +} + return result; +} + +unsafe fn showtrap(i: c_int, show_default: c_int) +{ + let t: *mut c_char; + + let p = trap_list[i as usize]; + if (p == libc::SIG_DFL as *mut c_char) && signal_is_hard_ignored(i) == 0 { + if show_default != 0 { + t = "-\0".as_ptr() as *mut c_char; + } else { + return; + } + } else if signal_is_hard_ignored(i) != 0 { + t = PT_NULL as *mut c_char; + } else { + t = if p == libc::SIG_IGN as *mut c_char {PT_NULL as *mut c_char} else {sh_single_quote(p)} + } + + let sn = signal_name(i); + if libc::strncmp(sn, "SIGJUNK\0".as_ptr() as *const c_char, 7) == 0 || + libc::strncmp(sn, "unknown\0".as_ptr() as *const c_char, 7) == 0 { + libc::printf("trap -- %s %d\n\0".as_ptr() as *const c_char, if t.is_null() {"''\0".as_ptr() as *mut c_char} else {t}, i); + } else if posixly_correct != 0 { + if libc::strncmp(sn, "SIG\0".as_ptr() as *const c_char, 3) == 0 { + libc::printf("trap -- %s %s\n\0".as_ptr() as *const c_char, if t.is_null() {"''\0".as_ptr() as *mut c_char} else {t}, (sn as usize + 3) as *mut c_char); + } else { + libc::printf("trap -- %s %s\n\0".as_ptr() as *const c_char, if t.is_null() {"''\0".as_ptr() as *mut c_char} else {t}, sn); + } + } else { + libc::printf("trap -- %s %s\n\0".as_ptr() as *const c_char, if t.is_null() {"''\0".as_ptr() as *mut c_char} else {t}, sn); + } + + if show_default == 0 { + if !t.is_null() { + libc::free(t as *mut c_void); + } + } +} + +unsafe fn display_traps(mut list: *mut WORD_LIST, show_all: c_int) -> c_int +{ + if list.is_null() { + for i in 0..BASH_NSIG { + showtrap(i, show_all); + } + return EXECUTION_SUCCESS; + } + + let mut result = EXECUTION_SUCCESS; + let mut i: c_int; + while !list.is_null() { + i = decode_signal((*(*list).word).word, DSIG_NOCASE | DSIG_SIGPREFIX); + if i == NO_SIG { + sh_invalidsig((*(*list).word).word); + result = EXECUTION_FAILURE; + } else { + showtrap(i, show_all); + } + + list = (*list).next; + } + + return result; +} diff --git a/bash-5.1/builtins_rust/type/Cargo.toml b/bash-5.1/builtins_rust/type/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..b5c42a2cc8c18a470de320a4dc20fc22b40c9fb9 --- /dev/null +++ b/bash-5.1/builtins_rust/type/Cargo.toml @@ -0,0 +1,16 @@ +[package] +authors = ["zhanghuanhuan"] +name = "rtype" +version = "0.0.1" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + +[dependencies] +libc = "0.2" +nix = "0.23.0" + +[lib] +crate-type = ["staticlib"] +name = "rtype" diff --git a/bash-5.1/builtins_rust/type/src/lib.rs b/bash-5.1/builtins_rust/type/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..0f0a43ae155c9d682f6b2658f791bea0301696cc --- /dev/null +++ b/bash-5.1/builtins_rust/type/src/lib.rs @@ -0,0 +1,814 @@ +extern crate libc; +extern crate nix; + +use libc::c_void; +use std::ffi::CStr; +use std::ffi::CString; +use std::ptr; + +#[macro_export] +macro_rules! CDESC_ALL{ + //print all descriptions of a command + () => {0x001} +} + +#[macro_export] +macro_rules! CDESC_SHORTDESC { + //print the description for type and command -V + () => {0x002} +} + +#[macro_export] +macro_rules! CDESC_REUSABLE{ + //print in a format that may be reused as input + () => {0x004} +} + +#[macro_export] +macro_rules! CDESC_TYPE { + //print the type for type -t + () => {0x008} +} + +#[macro_export] +macro_rules! CDESC_PATH_ONLY { + //print the path for type -p + () => {0x010} +} + +#[macro_export] +macro_rules! CDESC_FORCE_PATH { + //force a path search for type -P + () => {0x020} +} + +#[macro_export] +macro_rules! CDESC_NOFUNCS { + //skip function lookup for type -f + () => {0x040} +} + +#[macro_export] +macro_rules! CDESC_ABSPATH{ + //CDESC_ABSPATH + () => {0x080} +} + +#[macro_export] +macro_rules! CDESC_STDPATH{ + () => {0x100} +} + +#[macro_export] +macro_rules! CHECK_HELPOPT { + ($l:expr) => { + if $l !=std::ptr::null_mut() && (*$l).word !=std::ptr::null_mut() && ISHELP!((*(*$l).word).word) == 0 { + builtin_help (); + return EX_USAGE!(); + } + } +} + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {0} +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => {1} +} + +#[macro_export] +macro_rules! FS_EXECABLE{ + () => {0x2} +} +#[macro_export] +macro_rules! FS_EXEC_PREFERRED{ + () => {0x4} +} + +#[macro_export] +macro_rules! FS_NODIRS{ + () => {0x20} +} + +#[macro_export] +macro_rules! MP_DOCWD{ + () => {0} +} + +#[macro_export] +macro_rules! MP_RMDOT{ + () => {1} +} + +#[deny(missing_fragment_specifier)] +#[macro_export] +macro_rules! STREQ{ + ($a:expr,$b:expr) =>{ + *$a as i8 == *$b as i8 && libc::strcmp($a,$b)==0 + } +} + +#[macro_export] +macro_rules! SIZEOFWORD{ + () => { + std::mem::size_of::() + } +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub struct WORD_DESC { + pub word: *mut i8, + pub flags:i32 +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct WORD_LIST { + next: *mut WORD_LIST, + word: *mut WORD_DESC +} + +#[repr(C)] +pub struct SHELL_VAR { + name:*mut i8, + value:*mut i8, + exportstr:*mut i8, + dynamic_value:*mut fn(v:* mut SHELL_VAR)->*mut SHELL_VAR, + assign_func:* mut fn(v:* mut SHELL_VAR,str1:* mut i8,t:i64,str2:* mut i8)->*mut SHELL_VAR, + attributes:i32, + context:i32 +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct alias { + name :*mut i8, + value :*mut i8 , + flags:i8 +} + +type sh_builtin_func_t = fn(WORD_LIST) -> i32; +type alias_t = alias; + +pub fn math(op: fn(i32, i32) -> i32, a: i32, b: i32) -> i32{ + /// 通过函数指针调用函数 + op(a, b) +} + + +#[repr(C)] +pub struct COMMAND { + type_c:command_type, + flags:i32, + line:i32, + redirects:*mut REDIRECT, + value:VALUE_COMMAND +} +#[repr(u8)] +enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select, + cm_connection, cm_function_def, cm_until, cm_group, + cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc +} + +#[repr(C)] +pub union VALUE_COMMAND { + For:*mut for_com, + Case:*mut case_com, + While:*mut while_com, + If:*mut if_com, + Connection:*mut connection, + Simple:*mut simple_com, + Function_def:*mut function_def, + Group:*mut group_com, + Select:*mut select_com, + Arith:*mut arith_com, + Cond:*mut cond_com, + ArithFor:*mut arith_for_com, + Subshell:*mut subshell_com, + Coproc:*mut coproc_com +} + +#[repr(u8)] +#[derive(Copy,Clone)] +enum r_instruction { + r_output_direction, r_input_direction, r_inputa_direction, + r_appending_to, r_reading_until, r_reading_string, + r_duplicating_input, r_duplicating_output, r_deblank_reading_until, + r_close_this, r_err_and_out, r_input_output, r_output_force, + r_duplicating_input_word, r_duplicating_output_word, + r_move_input, r_move_output, r_move_input_word, r_move_output_word, + r_append_err_and_out +} + +#[repr(C)] +pub union REDIRECT { + next:*mut REDIRECT, + redirector:REDIRECTEE, + rflags: i32 , + flags: i32 , + instruction:r_instruction, + redirectee:REDIRECTEE, + here_doc_eof:*mut i8 +} + +#[repr(C)] +pub struct for_com { + flags: i32 , + line: i32 , + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub union REDIRECTEE { + dest: i32 , + filename:* mut WORD_DESC +} + +#[repr(C)] +pub struct case_com { + flags: i32, + line: i32, + word:*mut WORD_DESC, + clauses:*mut PATTERN_LIST +} +#[repr(C)] +pub struct PATTERN_LIST { + next:* mut PATTERN_LIST, + patterns:* mut WORD_LIST, + action:*mut COMMAND, + flags:i32 +} +#[repr(C)] +pub struct while_com { + flags: i32 , + test:*mut COMMAND, + action:*mut COMMAND +} + +#[repr(C)] +pub struct if_com { + flags: i32, + test:*mut COMMAND, + true_case:*mut COMMAND, + false_case:*mut COMMAND +} + +#[repr(C)] +pub struct connection { + ignore: i32 , + first:*mut COMMAND, + second:*mut COMMAND, + connector: i32 +} + +#[repr(C)] +pub struct simple_com { + flags: i32 , + line: i32 , + words:*mut WORD_LIST, + redirects:*mut REDIRECT +} + +#[repr(C)] +pub struct function_def { + flags: i32 , + line: i32 , + name:*mut WORD_DESC, + command:*mut COMMAND, + source_file:*mut i8 +} + +#[repr(C)] +pub struct group_com { + ignore: i32 , + command:*mut COMMAND, + source_file:*mut i8 +} + +#[repr(C)] +pub struct select_com { + flags: i32 , + line: i32 , + name:*mut WORD_DESC, + map_list:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct arith_com { + flags: i32 , + line: i32 , + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct cond_com { + flags: i32 , + line: i32 , + type_c: i32 , + exp:*mut WORD_LIST +} + +#[repr(C)] +pub struct arith_for_com { + flags: i32 , + line: i32 , + init:*mut WORD_LIST, + test:*mut WORD_LIST, + step:*mut WORD_LIST, + action:*mut COMMAND +} + +#[repr(C)] +pub struct subshell_com { + flags:i32, + line:i32, + command:*mut COMMAND +} + +#[repr(C)] +pub struct coproc_com { + flags:i32, + name:*mut i8, + command:*mut COMMAND +} + +#[macro_export] +macro_rules! FUNC_MULTILINE { + () => { + 0x01 + } +} + +#[macro_export] +macro_rules! FUNC_EXTERNAL { + () => { + 0x02 + } +} + +#[macro_export] +macro_rules! FS_EXEC_ONLY { + () => { + 0x8 + } +} + +#[macro_export] +macro_rules! ABSPATH { + ($s :expr) => { + unsafe { + char::from(*($s as *mut i8) as u8) }== '/'; + + // $x == '/'; + } + } +//define ABSPATH(x) ((x)[0] == '/') + +extern "C" { + fn reset_internal_getopt(); + fn internal_getopt (list:*mut WORD_LIST , opts:*mut i8)->i32; + fn builtin_usage(); + fn sh_notfound (name:* mut i8); + fn sh_chkwrite (ret:i32)->i32; + fn find_alias(alia :*mut i8) ->alias_t; + fn sh_single_quote(quote: *const i8) -> *mut i8; + fn find_reserved_word(word: *mut i8)->i32; + fn find_function (name:* const i8)-> *mut SHELL_VAR; + fn named_function_string (name: *mut i8, cmd:* mut i8, i:i32)->* mut i8; + fn find_shell_builtin(builtin: *mut i8) -> *mut i8; + fn find_special_builtin(builtins: *mut i8) -> *mut sh_builtin_func_t; + fn absolute_program(program:*const i8) -> i32; + fn file_status(status :*const i8) -> i32 ; + fn phash_search(search:*const i8) -> *mut i8; + fn conf_standard_path() -> *mut i8; + fn find_in_path(path1:*const i8, path2:*mut i8, num: i32) -> *mut i8; + fn find_user_command(cmd:*mut i8) -> *mut i8; + fn user_command_matches(cmd:*const i8, num1:i32, num2:i32) -> *mut i8; + fn sh_makepath(path:*const i8, path1:*const i8, i: i32) -> *mut i8; + //fn find_alias(alia : *mut i8) -> *mut alias_t; + static expand_aliases : i32; + static mut loptend:*mut WORD_LIST; + static posixly_correct:i32; +} + +unsafe fn function_cell(var:*mut SHELL_VAR) ->* mut COMMAND { + return (*var).value as * mut COMMAND; +} + +#[no_mangle] +pub unsafe extern "C" fn r_type_builtin (mut list :*mut WORD_LIST) -> i32 { + //println!("rtype is run"); + let mut dflags : i32; + let mut any_failed: i32 = 0 ; + let mut opt : i32 = 0; + let mut this : *mut WORD_LIST; + + dflags = CDESC_SHORTDESC!(); /* default */ + unsafe{ + this = list; + while this != std::ptr::null_mut() && char::from((*(*(*this).word).word) as u8) == '-' { + let mut flag = (((*(*this).word).word) as usize + 1) as *mut i8; + let mut c_str_type = CString::new("type").unwrap(); + let c_str_type1 = CString::new("-type").unwrap(); + let c_str_path = CString::new("path").unwrap(); + let c_str_path1 = CString::new("-path").unwrap(); + let c_str_all = CString::new("all").unwrap(); + let c_str_all1 = CString::new("-all").unwrap(); + if STREQ!(flag, c_str_type.as_ptr() as *mut i8 ) || STREQ!(flag, c_str_type1.as_ptr() as *mut i8) { + unsafe { + *((((*(*this).word).word) as usize + 1) as *mut i8) = 't' as i8 ; + *((((*(*this).word).word) as usize + 2) as *mut i8) = '\0' as i8 ; + } + } + else if STREQ!(flag, c_str_path.as_ptr() as *mut i8) || STREQ!(flag, c_str_path1.as_ptr() as *mut i8){ + *((((*(*this).word).word) as usize + 1) as *mut i8) = 'p' as i8 ; + *((((*(*this).word).word) as usize + 2) as *mut i8) = '\0' as i8 ; + } + + else if STREQ!(flag, c_str_all.as_ptr() as *mut i8) || STREQ!(flag, c_str_all1.as_ptr() as *mut i8) { + *((((*(*this).word).word) as usize + 1) as *mut i8) = 'a' as i8 ; + *((((*(*this).word).word) as usize + 2) as *mut i8) = '\0' as i8 ; + } + + if (*this).next != std::ptr::null_mut(){ + this = (*this).next; + } + } +} + reset_internal_getopt(); + + let c_str_afptP = CString::new("afptP").unwrap(); + let mut opt = unsafe {internal_getopt(list,c_str_afptP.as_ptr() as *mut i8) } ; + while opt != -1{ + let optu8:u8= opt as u8; + let optChar:char=char::from(optu8); + match optChar{ + 'a'=> {dflags = dflags |CDESC_ALL!();} + 'f'=> {dflags = dflags | CDESC_NOFUNCS!(); } + 'p'=> {dflags = dflags | CDESC_PATH_ONLY!(); + dflags = dflags& !(CDESC_TYPE!()|CDESC_SHORTDESC!()); } + 't'=> {dflags = dflags | CDESC_TYPE!(); + dflags = dflags& !(CDESC_PATH_ONLY!()|CDESC_SHORTDESC!());} + 'P'=> {dflags = dflags | CDESC_PATH_ONLY!()| CDESC_FORCE_PATH!(); + dflags = dflags& !(CDESC_TYPE!()|CDESC_SHORTDESC!()); + } + _ =>{ + if opt == -99 { + builtin_usage(); + return EX_USAGE!(); + } + unsafe { + builtin_usage (); + return EX_USAGE!(); + } + } + } + opt = internal_getopt (list, c_str_afptP.as_ptr() as * mut i8); + } + list = loptend; + while list != std::ptr::null_mut() { + let found : i32; + unsafe { + found = describe_command ((*(*list).word).word, dflags); + } + if found ==0 && (dflags & (CDESC_PATH_ONLY!()|CDESC_TYPE!()))==0 { + unsafe { + sh_notfound((*(*list).word).word); + } + } + any_failed = found + any_failed; + any_failed == 0; + // (any_failed += found) == 0; + unsafe { + list = (*list).next; + } + + } + if any_failed == 0{ + EXECUTION_SUCCESS!(); + } + else { + EXECUTION_FAILURE!(); + } + return unsafe{sh_chkwrite(opt)}; +} + + +fn describe_command (command : *mut i8, dflags : i32) -> i32 { + let mut found : i32 = 0; + let mut i : i32; + let mut found_file : i32 = 0; + let mut f : i32; + let mut all : i32; + let mut full_path : *mut i8; + let mut x : *mut i8; + let mut pathlist : *mut i8; + let mut func : *mut SHELL_VAR = 0 as *mut SHELL_VAR; + // let mut alias : *mut alias_t; + + if (dflags & CDESC_ALL!()) != 0{ + all =1 ; + } + else { + all = 0; + } + unsafe { + full_path = std::ptr::null_mut() ; + } +/* + // #if defined (ALIAS) + alias = find_alias(command); + if (((dflags & CDESC_FORCE_PATH!()) == 0) && expand_aliases!=0 && alias != std::ptr::null_mut()) + { + if (dflags & CDESC_TYPE!()) != 0{ + unsafe { + libc::puts("alias" as *const i8 ); + } + } + else if (dflags & CDESC_SHORTDESC!()) != 0 { + unsafe{ + println!("{:?} is aliased to {:?}\n",CStr::from_ptr(command), CStr::from_ptr(alias.value)); + } + } + else if dflags & CDESC_REUSABLE!(){ + unsafe { + x = sh_single_quote((*alias).value); + println!("alias {:?} = {:?}",CStr::from_ptr(command),CStr::from_ptr(x)); + libc::free(x); + } + } + found = 1; + + if all == 0 { + return 1; + } + } +*/ + /* Command is a shell reserved word? */ + if ((dflags & CDESC_FORCE_PATH!()) == 0) && unsafe {find_reserved_word(command)} >=0 { + if dflags & CDESC_TYPE!() != 0 { + unsafe{ + let c_str_keyword = CString::new("keyword").unwrap(); + libc::puts(c_str_keyword.as_ptr()); + } + } + else if dflags & CDESC_SHORTDESC!() != 0 { + unsafe{ + println! ("{:?} is a shell keyword\n", CStr::from_ptr(command)); + } + } + else if dflags & CDESC_REUSABLE!() != 0 { + unsafe { + println! ("{:?}",CStr::from_ptr(command)); + } + } + + found = 1; + if all==0 { + return 1; + } + } + + /* Command is a function? */ + if (dflags & (CDESC_FORCE_PATH!()|CDESC_NOFUNCS!()) == 0) && unsafe{find_function (command)}!= std::ptr::null_mut() { + if dflags & CDESC_TYPE!() != 0 { + unsafe { + let c_str_function = CString::new("function").unwrap(); + libc::puts(c_str_function.as_ptr()); + } + } + else if dflags & CDESC_SHORTDESC!() != 0 { + let result : *mut i8; + unsafe { + println!("{:?} is a function",CStr::from_ptr(command)); + result = named_function_string (command, unsafe{function_cell(func) as *mut i8}, FUNC_MULTILINE!()|FUNC_EXTERNAL!()); + println!("{:?}",CStr::from_ptr(result)); + } + + } + else if dflags & CDESC_REUSABLE!() != 0{ + unsafe { + println!("{:?}",CStr::from_ptr(command)); + } + } + + found = 1; + + if all == 0{ + return 1; + } + } + + /* Command is a builtin? */ + if ((dflags & CDESC_FORCE_PATH!()) == 0) && unsafe{find_shell_builtin (command)}!= std::ptr::null_mut() { + if dflags & CDESC_TYPE!() != 0{ + unsafe { + let c_str_builtin = CString::new("builtin").unwrap(); + libc::puts(c_str_builtin.as_ptr()); + } + } + else if dflags & CDESC_SHORTDESC!() != 0{ + if unsafe {posixly_correct}!= 0 && unsafe {find_special_builtin (command)} != std::ptr::null_mut() { + unsafe { + println!("{:?} is a special shell builtin", CStr::from_ptr(command)); + } + + } + else { + unsafe { + println!("{:?} is a shell builtin", CStr::from_ptr(command)); + } + } + } + else if dflags & CDESC_REUSABLE!() != 0 { + unsafe { + println!("{:?}",CStr::from_ptr(command)); + } + } + + found = 1; + if all == 0{ + return 1; + } + } + + /* Command is a disk file? */ + /* If the command name given is already an absolute command, just + check to see if it is executable. */ + if unsafe {absolute_program (command)} != 0 { + + f = unsafe {file_status (command)}; + if f & FS_EXECABLE!() != 0{ + if dflags & CDESC_TYPE!() != 0{ + unsafe { + let c_str_file = CString::new("file").unwrap(); + libc::puts(c_str_file.as_ptr()); + } + } + } + else if dflags & CDESC_SHORTDESC!() != 0 { + unsafe { + println!("{:?} is {:?}", CStr::from_ptr(command),CStr::from_ptr(command)); + } + } + else if dflags & (CDESC_REUSABLE!()|CDESC_PATH_ONLY!()) != 0{ + unsafe { + println!("{:?}",CStr::from_ptr(command)); + } + + /* There's no use looking in the hash table or in $PATH, + because they're not consulted when an absolute program + name is supplied. */ + return 1; + } + } + + /* If the user isn't doing "-a", then we might care about + whether the file is present in our hash table. */ + if all == 0 || (dflags & CDESC_FORCE_PATH!() != 0){ + + full_path = unsafe{phash_search (command)}; + if full_path != std::ptr::null_mut(){ + + if dflags & CDESC_TYPE!() != 0{ + unsafe{ + let c_str_file = CString::new("file").unwrap(); + libc::puts(c_str_file.as_ptr()); + } + } + else if dflags & CDESC_SHORTDESC!() != 0{ + unsafe{ + println! ("{:?} is hashed ({:?})", CStr::from_ptr(command), CStr::from_ptr(full_path)); + } + } + else if (dflags & (CDESC_REUSABLE!()|CDESC_PATH_ONLY!())) != 0{ + unsafe{ + println! ("{:?} ",CStr::from_ptr(full_path)); + } + } + unsafe{ + libc::free (full_path as *mut c_void); + } + return 1; + } + } + + /* Now search through $PATH. */ + #[warn(while_true)] + while true{ + if dflags & CDESC_STDPATH!() != 0 { + /* command -p, all cannot be non-zero */ + unsafe{ + pathlist = conf_standard_path (); + full_path = find_in_path (command, pathlist, FS_EXEC_PREFERRED!()|FS_NODIRS!()); + libc::free(pathlist as *mut c_void); + } + /* Will only go through this once, since all == 0 if STDPATH set */ + + } + else if all == 0{ + unsafe{ + full_path = find_user_command(command); + } + + } + else{ + unsafe { + full_path = user_command_matches (command, FS_EXEC_ONLY!(), found_file); /* XXX - should that be FS_EXEC_PREFERRED? */ + } + + } + if full_path == std::ptr::null_mut(){ + return 0; + //break; + } + + /* If we found the command as itself by looking through $PATH, it + probably doesn't exist. Check whether or not the command is an + executable file. If it's not, don't report a match. This is + the default posix mode behavior */ + if (unsafe {STREQ!(full_path, command)} || unsafe {posixly_correct}!=0){ + unsafe{ + f = file_status (full_path); + } + if (f & FS_EXECABLE!() == 0){ + unsafe { + libc::free (full_path as *mut c_void); + full_path = std::ptr::null_mut() ; + } + if all == 0{ + break; + } + } + else if ABSPATH!(full_path){ + ; + } + /* placeholder; don't need to do anything yet */ + else if dflags & (CDESC_REUSABLE!()|CDESC_PATH_ONLY!()|CDESC_SHORTDESC!()) != 0{ + if MP_DOCWD!()!=0 | (dflags & CDESC_ABSPATH!()) { + f=MP_RMDOT!(); + } + else { + f=0; + } + unsafe { + x = sh_makepath ( std::ptr::null_mut() , full_path, f); + libc::free (full_path as *mut c_void); + } + + full_path = x; + } + } + /* If we require a full path and don't have one, make one */ + else if ((dflags & CDESC_ABSPATH!())!= 0) && ABSPATH!(full_path) == false { + unsafe { + x = sh_makepath ( std::ptr::null_mut() , full_path, MP_DOCWD!()|MP_RMDOT!()); + libc::free (full_path as *mut c_void); + } + full_path = x; + } + found_file += 1; + found = 1; + if dflags & CDESC_TYPE!() != 0{ + unsafe { + let c_str_file = CString::new("file").unwrap(); + libc::puts(c_str_file.as_ptr()); + } + } + else if dflags & CDESC_SHORTDESC!() != 0{ + unsafe{ + println! ("{:?} is {:?}", CStr::from_ptr(command), CStr::from_ptr(full_path)); + } + + } + else if dflags & (CDESC_REUSABLE!()|CDESC_PATH_ONLY!()) != 0{ + unsafe{ + println! ("{:?}", CStr::from_ptr(full_path)); + } + + } + + unsafe { + libc::free (full_path as *mut c_void); + } + full_path = std::ptr::null_mut() ; + if all == 0{ + break; + } + + } + found +} diff --git a/bash-5.1/builtins_rust/ulimit/Cargo.toml b/bash-5.1/builtins_rust/ulimit/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..a73c9dc94cf80764719469bf4d6785a397329011 --- /dev/null +++ b/bash-5.1/builtins_rust/ulimit/Cargo.toml @@ -0,0 +1,17 @@ +[package] +authors = ["huanhuanzhang"] +name = "rulimit" +version = "0.0.1" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + +[dependencies] +lazy_static = "1.4.0" +libc = "0.2" +nix = "0.23.0" + +[lib] +crate-type = ["staticlib"] +name = "rulimit" diff --git a/bash-5.1/builtins_rust/ulimit/src/lib.rs b/bash-5.1/builtins_rust/ulimit/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..2e2d862731e865c3444776ad3ee4a743c7f389d7 --- /dev/null +++ b/bash-5.1/builtins_rust/ulimit/src/lib.rs @@ -0,0 +1,1029 @@ +extern crate libc; +extern crate nix; + +use std::ffi::CStr; +use std::ffi::CString; +use std::ptr; +use std::mem; + + +#[derive(Copy, Clone)] +#[repr(C)] +pub struct rlimit { + pub rlim_cur: rlim_t, + pub rlim_max: rlim_t, +} + +#[repr(C)] +#[derive(Copy,Clone)] +pub struct WORD_DESC { + pub word: *mut i8, + pub flags:i32 +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct WORD_LIST { + next: *mut WORD_LIST, + word: *mut WORD_DESC +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct RESOURCE_LIMITS{ + option : i32, /* The ulimit option for this limit. */ + parameter : i32, /* Parameter to pass to get_limit (). */ + block_factor : i32, /* Blocking factor for specific limit. */ + description : *const i8, /* Descriptive string to output. */ + units : *const i8 /* scale */ +} + +#[repr (C)] +#[derive(Copy,Clone)] +pub struct _cmd { + cmd : i32, + arg : *mut i8 +} + +#[repr (C)] +#[derive(Copy,Clone)] +/* Information about the current user. */ +pub struct user_info { + uid : uid_t, + euid : uid_t, + gid : gid_t, + egid : gid_t, + user_name : *mut i8, + shell :*mut i8, + home_dir : *mut i8 +} + +#[macro_export] +macro_rules! SIZEOFLIMIT{ + () => { + std::mem::size_of::() as usize + } +} + +#[macro_export] +macro_rules! SIZEOFLIMITS{ + () => { + SIZEOFLIMIT!() *18 + } +} + +#[macro_export] +macro_rules! SIZEOFULCMD{ + () => { + std::mem::size_of::() + } +} + +#[macro_export] +macro_rules! LIMIT_HARD{ + () => { + 0x01 + } +} + +#[macro_export] +macro_rules! LIMIT_SOFT{ + () => { + 0x02 + } +} + + +#[macro_export] +macro_rules! POSIXBLK{ + () => { + -2 + } +} + +#[macro_export] +macro_rules! BLOCKSIZE{ + ($s:expr) => { + if $s == POSIXBLK!() { + if unsafe{posixly_correct}!= 0 { + 512 + } + else { + 1024 + } + } + else { + $s + } + } +} + +#[macro_export] +macro_rules! RLIM_SAVED_MAX{ + () => { + RLIM_INFINITY!(); + } +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => {0} +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => {1} +} + +#[macro_export] +macro_rules! EX_USAGE { + () => {258} +} + +#[deny(missing_fragment_specifier)] +#[macro_export] +macro_rules! STREQ{ + ($a:expr,$b:expr) =>{ + $a==$b && libc::strcmp($a,$b)==0 + } +} + +#[macro_export] +macro_rules! NCMDS { + () => { + SIZEOFLIMITS!() / SIZEOFLIMIT!() + } +} + +#[macro_export] +macro_rules! RLIMIT_FILESIZE { + () => { + 1 + } +} + +#[macro_export] +macro_rules! RLIMIT_PIPESIZE { + () => { + 257 + } +} + +#[macro_export] +macro_rules! PIPESIZE { + () => { + 4096 + } +} + +#[macro_export] +macro_rules! PIPE_BUF { + () => { + PIPESIZE!() + } +} + +#[macro_export] +macro_rules! RLIMIT_OPENFILES{ + () => { + 7 + } +} + +#[macro_export] +macro_rules! RLIMIT_VIRTMEM{ + () => { + 9 + } +} + +#[macro_export] +macro_rules! RLIMIT_MAXUPROC{ + () => { + 6 + } +} + +#[macro_export] +macro_rules! RLIM_INFINITY { + () => { + -1 + //0x7fffffff + } +} + +#[macro_export] +macro_rules! RLIM_SAVED_CUR{ + () => { + RLIM_INFINITY!() + } +} + +type RLIMTYPE = i64; +type RESOURCE_LIMITS_T= RESOURCE_LIMITS; +type ULCMD = _cmd; +pub type __rlimit_resource = libc::c_uint; +pub const __RLIM_NLIMITS: __rlimit_resource = 16; +pub const __RLIMIT_NLIMITS: __rlimit_resource = 16; +pub const __RLIMIT_RTTIME: __rlimit_resource = 15; +pub const __RLIMIT_RTPRIO: __rlimit_resource = 14; +pub const __RLIMIT_NICE: __rlimit_resource = 13; +pub const __RLIMIT_MSGQUEUE: __rlimit_resource = 12; +pub const __RLIMIT_SIGPENDING: __rlimit_resource = 11; +pub const __RLIMIT_LOCKS: __rlimit_resource = 10; +pub const __RLIMIT_MEMLOCK: __rlimit_resource = 8; +pub const __RLIMIT_NPROC: __rlimit_resource = 6; +pub const RLIMIT_AS: __rlimit_resource = 9; +pub const __RLIMIT_OFILE: __rlimit_resource = 7; +pub const RLIMIT_NOFILE: __rlimit_resource = 7; +pub const __RLIMIT_RSS: __rlimit_resource = 5; +pub const RLIMIT_CORE: __rlimit_resource = 4; +pub const RLIMIT_STACK: __rlimit_resource = 3; +pub const RLIMIT_DATA: __rlimit_resource = 2; +pub const RLIMIT_FSIZE: __rlimit_resource = 1; +pub const RLIMIT_CPU: __rlimit_resource = 0; +pub type __rlim_t = u64; +pub type rlim_t = __rlim_t; +pub type __rlimit_resource_t = __rlimit_resource; +pub type __uid_t = i32; +pub type __gid_t = i32; +pub type gid_t = __gid_t; +pub type uid_t = __uid_t; + +static mut cmdlistsz : i32 = 0; + +const limits: [ RESOURCE_LIMITS_T;18] =[ + + { RESOURCE_LIMITS { + option: 'R' as i32, + parameter: __RLIMIT_RTTIME as i32, + block_factor: 1 as i32, + description: b"real-time non-blocking time\0" as *const u8 + as *const i8, + units: b"microseconds\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'c' as i32, + parameter: RLIMIT_CORE as i32, + block_factor: -(2 as i32), + description: b"core file size\0" as *const u8 as *const i8, + units: b"blocks\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'd' as i32, + parameter: RLIMIT_DATA as i32, + block_factor: 1024 as i32, + description: b"data seg size\0" as *const u8 as *const i8, + units: b"kbytes\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'e' as i32, + parameter: __RLIMIT_NICE as i32, + block_factor: 1 as i32, + description: b"scheduling priority\0" as *const u8 as *const i8, + units: 0 as *const libc::c_void as *mut libc::c_void as *mut i8, + }}, + + { RESOURCE_LIMITS { + option: 'f' as i32, + parameter: RLIMIT_FSIZE as i32, + block_factor: -(2 as i32), + description: b"file size\0" as *const u8 as *const i8, + units: b"blocks\0" as *const u8 as *const i8, + }}, + + { + RESOURCE_LIMITS { + option: 'i' as i32, + parameter: __RLIMIT_SIGPENDING as i32, + block_factor: 1 as i32, + description: b"pending signals\0" as *const u8 as *const i8, + units: 0 as *const libc::c_void as *mut libc::c_void as *mut i8, + } + }, + + { RESOURCE_LIMITS { + option: 'l' as i32, + parameter: __RLIMIT_MEMLOCK as i32, + block_factor: 1024 as i32, + description: b"max locked memory\0" as *const u8 as *const i8, + units: b"kbytes\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'm' as i32, + parameter: __RLIMIT_RSS as i32, + block_factor: 1024 as i32, + description: b"max memory size\0" as *const u8 as *const i8, + units: b"kbytes\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'n' as i32, + parameter: RLIMIT_NOFILE as i32, + block_factor: 1 as i32, + description: b"open files\0" as *const u8 as *const i8, + units: 0 as *const libc::c_void as *mut libc::c_void as *mut i8, + }}, + + { RESOURCE_LIMITS { + option: 'p' as i32, + parameter: 257 as i32, + block_factor: 512 as i32, + description: b"pipe size\0" as *const u8 as *const i8, + units: b"512 bytes\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'q' as i32, + parameter: __RLIMIT_MSGQUEUE as i32, + block_factor: 1 as i32, + description: b"POSIX message queues\0" as *const u8 as *const i8, + units: b"bytes\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'r' as i32, + parameter: __RLIMIT_RTPRIO as i32, + block_factor: 1 as i32, + description: b"real-time priority\0" as *const u8 as *const i8, + units: 0 as *const libc::c_void as *mut libc::c_void as *mut i8, + }}, + + { RESOURCE_LIMITS { + option: 's' as i32, + parameter: RLIMIT_STACK as i32, + block_factor: 1024 as i32, + description: b"stack size\0" as *const u8 as *const i8, + units: b"kbytes\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 't' as i32, + parameter: RLIMIT_CPU as i32, + block_factor: 1 as i32, + description: b"cpu time\0" as *const u8 as *const i8, + units: b"seconds\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'u' as i32, + parameter: __RLIMIT_NPROC as i32, + block_factor: 1 as i32, + description: b"max user processes\0" as *const u8 as *const i8, + units: 0 as *const libc::c_void as *mut libc::c_void as *mut i8, + }}, + + { RESOURCE_LIMITS { + option: 'v' as i32, + parameter: RLIMIT_AS as i32, + block_factor: 1024 as i32, + description: b"virtual memory\0" as *const u8 as *const i8, + units: b"kbytes\0" as *const u8 as *const i8, + }}, + + { RESOURCE_LIMITS { + option: 'x' as i32, + parameter: __RLIMIT_LOCKS as i32, + block_factor: 1 as i32, + description: b"file locks\0" as *const u8 as *const i8, + units: 0 as *const libc::c_void as *mut libc::c_void as *mut i8, + }}, + + { RESOURCE_LIMITS { + option: -1 , + parameter: -1, + block_factor:-1, + description: 0 as *const libc::c_void as *mut libc::c_void + as *mut i8, + units: 0 as *const libc::c_void as *mut libc::c_void as *mut i8, + }} + ]; + +extern "C" { + fn reset_internal_getopt(); + fn xmalloc(_: u64) -> *mut libc::c_void; + fn xrealloc(_: *mut libc::c_void, _: u64) -> *mut libc::c_void; + fn all_digits(_: *const i8) -> i32; + fn sh_chkwrite(_: i32) -> i32; + fn internal_getopt(_: *mut WORD_LIST, _: *mut i8) -> i32; + fn strerror(_: i32) -> *mut i8; + fn sprintf(_: *mut i8, _: *const i8, _: ...) -> i32; + fn string_to_rlimtype(_: *mut i8 ) -> rlim_t; + fn getdtablesize() -> i32; + fn builtin_help (); + fn builtin_usage(); + fn sh_erange (s:* mut i8, desc:* mut i8); + fn sh_invalidnum(arg1: *mut i8); + fn __errno_location() -> *mut i32; + fn getrlimit(__resource: __rlimit_resource_t, __rlimits: *mut rlimit) -> i32; + fn setrlimit( + __resource: __rlimit_resource_t, + __rlimits: *const rlimit, + ) -> i32; + + fn builtin_error(_: *const i8, _: ...); + fn getmaxchild() -> i64; + fn print_rlimtype(_: rlim_t, _: i32); + + static mut loptend: *mut WORD_LIST; + static mut list_optarg: *mut i8; + static mut posixly_correct:i32 ; + static mut current_user: user_info; +} + +static mut optstring:[ i8;4 + 2 * NCMDS!() as usize] = [0;4 + 2 * NCMDS!() as usize]; +static mut cmdlist : *mut ULCMD = 0 as *const ULCMD as *mut ULCMD; +static mut ncmd : i32 = 0; + +fn _findlim (opt:i32) -> i32{ + // let mut register : i32; + //let i : i32 = 0; + + for i in 0..17 { + if limits[i].option > 0{ + //println!("now opt is {}",opt); + if limits[i].option == opt { + return i as i32; + } + } + } + -1 +} + +#[no_mangle] +pub unsafe extern "C" fn r_ulimit_builtin(mut list: *mut WORD_LIST) -> i32{ + + //println!("enter ulimit set by huanhuan"); + let mut s : *mut i8; + let mut c : i32 ; + let mut limind : i32 ; + let mut mode : i32 = 0 ; + let mut opt : i32 = 0 ; + let mut all_limits : i32 = 0 ; + if optstring[0] == 0 { + //println!(" optstring[0] == 0"); + s = optstring.as_mut_ptr(); + s = (s as usize ) as *mut i8; + *s = 'a' as i8; + s = (s as usize + 1) as *mut i8; + *s = 'S' as i8; + s = (s as usize + 1) as *mut i8; + *s = 'H' as i8; + c = 0 ; + for i in 0..17 { + if limits[i].option > 0{ + //println!("limits[i].option > 0 is {}",limits[i].option); + s = (s as usize + 1) as *mut i8; + *s = limits[i].option as i8; + s = (s as usize + 1) as *mut i8; + *s = ';' as i8; + } + } + *s = '\0' as i8; + } + + //println! ("cmdlistsz is {}",cmdlistsz); + if cmdlistsz == 0{ + // println!("cmdlistsz == 0"); + cmdlistsz = 16; + unsafe { + cmdlist = + xmalloc ((cmdlistsz as u64)*(std::mem::size_of::() as libc::c_ulong) ) as *mut ULCMD; + } + // println!("cmdlistsz == 0"); + } + ncmd = 0; + reset_internal_getopt (); + opt = internal_getopt(list, optstring.as_ptr() as *mut i8); + //println! ("get opt 2 is {}",opt); + while opt != -1 { + //println!("opt is {}", opt); + let optu8:u8= opt as u8; + let optChar:char=char::from(optu8); + match optChar { + 'a' => { all_limits = all_limits + 1 ;} + 'S' => { mode = mode | LIMIT_SOFT!() ; } + 'H' => { mode = mode | LIMIT_HARD!();} + '?'=> { + builtin_help(); + return EX_USAGE!(); + } + // => { + // builtin_usage(); + // return EX_USAGE!(); + // } + _ => { + //println!("enter switch default,opt is {}",opt); + if opt == -99 { + builtin_usage(); + return EX_USAGE!(); + } + if ncmd >= cmdlistsz { + cmdlistsz = cmdlistsz * 2 ; + cmdlist = xrealloc( + cmdlist as *mut libc::c_void,(cmdlistsz as u64) * std::mem::size_of::() as u64 ) as *mut ULCMD; + } + unsafe { + (*cmdlist.offset(ncmd as isize)).cmd = opt; + let fresh5 = ncmd; + //ncmd = ncmd + 1; + let ref mut fresh6 = (*cmdlist.offset(fresh5 as isize)).arg; + *fresh6 = list_optarg; + // let mut cmm =&mut (*((cmdlist as usize + + // (ncmd as usize)*std::mem::size_of::())as *mut ULCMD) as ULCMD); + // cmm.cmd = opt; + // cmm.arg = list_optarg; + // println!("now cmd opt is {:?}",cmm.cmd); + // (*((cmdlist as usize + (ncmd as usize)*std::mem::size_of::()) + // as *mut ULCMD) as ULCMD).cmd = opt ; + // (*((cmdlist as usize + (ncmd as usize) * std::mem::size_of::()) + // as *mut ULCMD) as ULCMD).arg = list_optarg; + ncmd = ncmd+1; + } + + } + } + opt = internal_getopt (list, optstring.as_ptr() as * mut i8); + } + + // println! ("now cmd1 opt is {:?}",(*((cmdlist as usize + (ncmd as usize)*std::mem::size_of::()) + // as *mut ULCMD) as ULCMD).cmd ); + list = loptend; + + if all_limits != 0 { + //println!("all_limits != 0 "); + if mode == 0 { + print_all_limits (LIMIT_SOFT!()); + } + else { + //println!("all_limits == 0 ,mode is {}",mode); + print_all_limits (mode); + } + return sh_chkwrite(EXECUTION_SUCCESS!()); + } + + if ncmd == 0 { + //println!("ncmd == 0"); + unsafe { + (*cmdlist.offset(ncmd as isize)).cmd = 'f' as i32; + // let mut cmm = *((cmdlist as usize + (ncmd as usize )*std::mem::size_of::())as *mut ULCMD) as ULCMD; + // cmm.cmd = 'f' as i32; + } + /* `ulimit something' is same as `ulimit -f something' */ + if !list.is_null() { + unsafe { + (*cmdlist.offset(ncmd as isize)).arg = (*(*list).word).word; + // let mut cmm = *((cmdlist as usize + (ncmd as usize )*std::mem::size_of::())as *mut ULCMD) as ULCMD; + // cmm.arg = (*(*list).word).word; + ncmd = ncmd+1; + } + } + else { + //println!("enter else"); + unsafe { + (*cmdlist.offset(ncmd as isize)).arg = std::ptr::null_mut(); + // let mut cmm = *((cmdlist as usize + (ncmd as usize )*std::mem::size_of::())as *mut ULCMD) as ULCMD; + // cmm.arg = std::ptr::null_mut(); + ncmd = ncmd+1; + //println!("pos 4?"); + } + + } + if !list.is_null() { + // println!("pos 5?"); + list = (*list).next; + } + } + + //println!("now ncmd is {}",ncmd); + for d in 0..ncmd { + //println!("pos 6?"); + //println!("now get dmd is {}",(*((cmdlist as usize + d as usize*std::mem::size_of::()) + //as *mut ULCMD) as ULCMD).cmd); + let cmm = *((cmdlist as usize + (d as usize )*std::mem::size_of::())as *mut ULCMD) as ULCMD; + let dmd = cmm.cmd; + + //println!("dmd is {}",dmd); + limind = _findlim ((*cmdlist.offset(d as isize)).cmd); + //println!("now get limind is {}",limind); + if limind == -1 { + unsafe { + builtin_error(b"%s: bad command : %s\0" as *const u8 as *const i8, + (*cmdlist.offset(d as isize)).cmd, + strerror(*__errno_location()) as *const i8); + } + return EX_USAGE!(); + } + } + + for d in 0..ncmd { + //println!("pos 7?"); + let dmd = (*cmdlist.offset(d as isize)).cmd; + let drg = (*cmdlist.offset(d as isize)).arg; + // let dmd = (*((cmdlist as usize + (d as usize )*std::mem::size_of::()) + // as *mut ULCMD) as ULCMD).cmd; + // let drg = (*((cmdlist as usize + (d as usize )*std::mem::size_of::()) + // as *mut ULCMD) as ULCMD).arg; + if (ulimit_internal (dmd,drg, mode, d-1)) == EXECUTION_FAILURE!() { + return EXECUTION_FAILURE!(); + } + } + //println!("pos 8?"); + return EXECUTION_SUCCESS!(); + +} + +unsafe fn ulimit_internal (cmd : i32 , cmdarg :*mut i8,mut mode : i32, multiple : i32) -> i32 { + + let mut opt : i32 ; + let mut limind : i32 ; + let mut setting : i32 ; + let mut block_factor : i32 ; + let mut soft_limit : RLIMTYPE = 0; + let mut hard_limit : RLIMTYPE =0; + let mut real_limit : RLIMTYPE = 0; + let mut limit : RLIMTYPE; + + if cmdarg != std::ptr::null_mut() { + setting = 1; + } + else { + setting = 0; + } + // println!("now set cmd limind is {}",cmd); + limind = _findlim(cmd); + //println!("now get limind is {}",limind); + if mode == 0 { + if setting != 0 { + mode = LIMIT_HARD!()|LIMIT_SOFT!(); + } + else { + mode = LIMIT_SOFT!(); + } + } +// println!("now get_limit para {}" , limind); +// println!("now get soft_limit is {}",soft_limit); +// println!("now get hard_limit is {}",hard_limit); + opt = get_limit (limind, &mut soft_limit, &mut hard_limit); + + if opt < 0 { + unsafe { + builtin_error(b"%s: cannot get limit : %s\0" as *const u8 as *const i8, limits[limind as usize].description, + strerror(*__errno_location()) as *const i8); + } + + return EXECUTION_FAILURE!(); + } + + if setting == 0 { + if (mode & LIMIT_SOFT!()) != 0 { + //println!("mode & LIMIT_SOFT!()) != 0,soft_limit is {},hard_limit is {}", soft_limit,hard_limit); + printone (limind,soft_limit,multiple); + } + else { + //println!("mode & LIMIT_SOFT!()) == 0"); + printone (limind,hard_limit,multiple); + } + return EXECUTION_SUCCESS!(); + } + + let mut c_str_hard = CString::new("hard").unwrap(); + let mut c_str_soft = CString::new("soft").unwrap(); + let mut c_str_unlimited = CString::new("unlimited").unwrap(); + if unsafe{STREQ!(cmdarg,c_str_hard.as_ptr() as *mut i8 )}{ + real_limit = hard_limit; + } + + else if unsafe{STREQ!(cmdarg, c_str_soft.as_ptr() as *mut i8)}{ + real_limit = soft_limit; + } + else if unsafe{STREQ!(cmdarg, c_str_unlimited.as_ptr() as *mut i8)}{ + real_limit = RLIM_INFINITY!(); + } + + else if unsafe {all_digits(cmdarg)} !=0 { + limit = unsafe {string_to_rlimtype (cmdarg) as i64}; + block_factor = BLOCKSIZE!(limits[limind as usize].block_factor); + real_limit = limit * block_factor as i64; + + if (real_limit / block_factor as i64) != limit { + // println!("real_limit / block_factor as i64) != limit"); + let c_str_limit =CString::new("limit").unwrap(); + unsafe {sh_erange (cmdarg,c_str_limit.as_ptr() as *mut i8)}; + return EXECUTION_FAILURE!(); + } + //println!("real_limit / block_factor as i64) == limit"); + } + + else { + sh_invalidnum (cmdarg); + return EXECUTION_FAILURE!(); + } + if set_limit (limind, real_limit, mode) < 0 { + builtin_error(b"%s: cannot modify limit : %s\0" as *const u8 as *const i8, limits[limind as usize].description, + strerror(*__errno_location()) as *const i8); + return EXECUTION_FAILURE!(); + } + return EXECUTION_SUCCESS!(); + +} + +fn get_limit (mut ind : i32, softlim : *mut RLIMTYPE, hardlim : *mut RLIMTYPE ) -> i32 { + //println!("now enter get_limit, ind is {}",ind); + let mut value : RLIMTYPE = 0 ; + let mut limit: rlimit = rlimit { rlim_cur: 1, rlim_max: 1 }; + + // println!("now get ind is {}",ind); + if limits[ind as usize].parameter >= 256 { + // println!("limits[ind as usize].parameter >= 256"); + match limits[ind as usize].parameter { + RLIMIT_FILESIZE!() => { + if filesize (((&mut value) as *mut i64) as *mut u64) < 0 { + return -1; + } + } + RLIMIT_PIPESIZE!() => { + if unsafe { + pipesize (((&mut value) as *mut i64) as *mut u64)} < 0 { + return -1; + } + + } + RLIMIT_OPENFILES!() => { + value = unsafe {getdtablesize()} as RLIMTYPE ; + + } + RLIMIT_VIRTMEM!() => { + return unsafe {getmaxvm(softlim, hardlim as *mut i8) }; + } + RLIMIT_MAXUPROC!() => { + if getmaxuprc ((value as usize) as *mut u64) < 0 { + return -1; + } + + } + _ => { + unsafe { + *__errno_location() = libc::EINVAL; + } + } + } + unsafe { + *softlim = value; + *hardlim = value; + } + return 0; + } + else{ + unsafe { + //println!("now get ind is {} , ====2:{}==== ind is3: {}",ind,ind as u32,ind as u32 as usize ); + let ii = getrlimit(limits[ind as u32 as usize ].parameter as __rlimit_resource_t, + &mut limit); + // println!("parameter={} softlimeeeee is {},hardlimeeeeeeeaaaaaaaaae is {}" ,limits[ind as usize ].parameter,limit.rlim_cur as i64 , + // limit.rlim_max as i64); + // println!(" option == {}, description is {:?} \n",limits[ind as usize].option, CStr::from_ptr(limits[ind as usize ].description)); + if ii < 0 { + return -1; + } + } + unsafe { + // println!("softlim is {},hardlim is {}",limit.rlim_cur as i64 , + // limit.rlim_max as i64); + *softlim = limit.rlim_cur as i64; + *hardlim = limit.rlim_max as i64; + } + return 0; + } +} + +fn set_limit (ind : i32, newlim : RLIMTYPE, mode : i32) -> i32{ + + let mut limit : rlimit = rlimit { rlim_cur: 0, rlim_max: 0 }; + let mut val : RLIMTYPE = 0; + + if limits[ind as usize].parameter >= 256 { + match limits[ind as usize].parameter { + RLIMIT_FILESIZE!() => { + unsafe { + *__errno_location() = libc::EINVAL; + } + return -1; + } + RLIMIT_OPENFILES!() | RLIMIT_PIPESIZE !() | + RLIMIT_VIRTMEM!() | RLIMIT_MAXUPROC !() | + _ => { + unsafe { + *__errno_location() = libc::EINVAL; + } + return -1; + } + } + } + else{ + if unsafe { + getrlimit (limits[ind as usize].parameter + as __rlimit_resource_t,&mut limit ) + } < 0 { + return -1; + } + let b = unsafe {current_user.euid }!= 0 && newlim == RLIM_INFINITY!() + && (mode & LIMIT_HARD!()) == 0 && limit.rlim_cur <= limit.rlim_max; + if b { + val = limit.rlim_max as i64; + } + else { + val = newlim; + } + if mode & LIMIT_SOFT!() != 0 { + limit.rlim_cur = val as u64; + } + if mode & LIMIT_HARD!() != 0 { + limit.rlim_max = val as u64; + } + return + unsafe {setrlimit(limits[ind as usize].parameter as __rlimit_resource_t, &mut limit)}; + } +} + +unsafe fn getmaxvm(softlim : *mut RLIMTYPE , hardlim : *mut i8) -> i32 { + + let mut datalim : rlimit = rlimit { rlim_cur: 0, rlim_max: 0 }; + let mut stacklim : rlimit = rlimit { rlim_cur: 0, rlim_max: 0 }; + + if getrlimit(RLIMIT_DATA, &mut datalim) < 0 { + return -1; + } + if getrlimit (RLIMIT_STACK, &mut stacklim) < 0 { + return -1; + } + *softlim = (datalim.rlim_cur as i64 / 1024 as i64) + (stacklim.rlim_cur as i64/1024 as i64); + *hardlim = ((datalim.rlim_max as i64) /1024 as i64) as i8 + (stacklim.rlim_max as i64/1024 as i64) as i8; + return 0; +} + +fn filesize(mut valuep: *mut rlim_t) -> i32 { + unsafe { + *__errno_location() = libc::EINVAL; + } + return -1; +} + +unsafe fn pipesize(mut valuep: *mut rlim_t) -> i32 { + // println!("enter pipesize"); + *((valuep as usize) as *mut rlim_t) = PIPE_BUF!() as rlim_t; + // println!("return"); + return 0 ; +} + +fn getmaxuprc(mut valuep: *mut rlim_t) -> i32 { + let mut maxchild: i64 = 0; + maxchild = unsafe{getmaxchild()}; + if maxchild < 0 as i32 as libc::c_long { + unsafe { + *__errno_location() = libc::EINVAL; + } + return -1; + } else { + unsafe { + *valuep = maxchild as rlim_t; + } + return 0 ; + }; +} + +fn print_all_limits (mut mode : i32) { + let mut i : i32 ; + let mut softlim : RLIMTYPE = 0; + let mut hardlim : RLIMTYPE = 0; + + if mode == 0 + { + mode = mode | LIMIT_SOFT!(); + } + i = 0; + while limits[i as usize].option >0 { + + if get_limit(i, &mut softlim, &mut hardlim) == 0 { + if mode & LIMIT_SOFT!() != 0 { + printone(i,softlim,1); + } + else { + printone(i, hardlim,1); + } + } + else if unsafe { + *__errno_location() != libc::EINVAL } { + unsafe { + builtin_error(b"%s: cannot get limit : %s\0" as *const u8 as *const i8, limits[i as usize].description, + strerror(*__errno_location()) as *const i8); + } + } + i = i+1; + } +} + +fn printone (limind : i32, curlim :RLIMTYPE , pdesc : i32){ + // println!("enter printone"); + //println!("now get curlim is {}",curlim); + let mut unitstr :[ i8; 64] = [0 ; 64]; + let mut factor : i32 ; + + // println!("limind1 is {} ",limind); + factor = BLOCKSIZE!(limits[limind as usize].block_factor); + if pdesc > 0 { + if !limits[limind as usize].units.is_null(){ + unsafe { + //println!("ffffffffff11"); + sprintf (unitstr.as_mut_ptr(), b"(%s, -%c) \0" as *const u8 as *const i8, + limits[limind as usize].units, + limits[limind as usize].option); + } + + } + else { + unsafe { + sprintf (unitstr.as_mut_ptr(),b"(-%c) \0" as *const u8 as *const i8, + limits[limind as usize].option); + } + + } + // println!("limind is {} RLIM_INFINITY is {}",limind ,RLIM_INFINITY!()); + println!("{}", + format! ("{:?} {:?} ", unsafe { + CStr::from_ptr (limits[limind as usize].description)} + , unsafe {CStr::from_ptr(unitstr.as_mut_ptr())})); + //println!(""); + } + if curlim == RLIM_INFINITY!() { + //println!("unlimited"); + let c_str_unlimited = CString::new("unlimited").unwrap(); + unsafe {libc::puts (c_str_unlimited.as_ptr())}; + } + + else if curlim == RLIM_SAVED_MAX!() { + //println!("hard"); + let c_str_hard = CString::new("hard").unwrap(); + unsafe {libc::puts (c_str_hard.as_ptr())}; + } + else if curlim == RLIM_SAVED_CUR!() { + //println!("soft"); + let c_str_soft = CString::new("soft").unwrap(); + unsafe {libc::puts (c_str_soft.as_ptr())}; + } + else{ + unsafe { + print_rlimtype ((curlim / factor as i64) as u64 , 1); + } + + } + +} + +/* Set all limits to NEWLIM. NEWLIM currently must be RLIM_INFINITY, which + causes all limits to be set as high as possible depending on mode (like + csh `unlimit'). Returns -1 if NEWLIM is invalid, 0 if all limits + were set successfully, and 1 if at least one limit could not be set. + + To raise all soft limits to their corresponding hard limits, use + ulimit -S -a unlimited + To attempt to raise all hard limits to infinity (superuser-only), use + ulimit -H -a unlimited + To attempt to raise all soft and hard limits to infinity, use + ulimit -a unlimited +*/ + +fn set_all_limits (mut mode : i32 , newlim : RLIMTYPE) -> i32 { + let mut i : i32 ; + let mut retval : i32 = 0; + + if newlim != RLIM_INFINITY!() { + unsafe { + *__errno_location() = libc::EINVAL; + } + return -1; + } + + if mode == 0 { + mode = LIMIT_SOFT!()|LIMIT_HARD!(); + } + retval = 0 ; + i = 0; + + while limits[i as usize].option > 0 { + if set_limit (i, newlim, mode) < 0 { + unsafe { + builtin_error(b"%s: cannot modify limit : %s\0" as *const u8 as *const i8, limits[i as usize].description, + strerror(*__errno_location()) as *const i8); + } + retval = 1; + i = i +1; + } + } + return retval; +} + + diff --git a/bash-5.1/builtins_rust/umask/.gitignore b/bash-5.1/builtins_rust/umask/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4fffb2f89cbd8f2169ce9914bd16bd43785bb368 --- /dev/null +++ b/bash-5.1/builtins_rust/umask/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/bash-5.1/builtins_rust/umask/Cargo.toml b/bash-5.1/builtins_rust/umask/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..310803d4f865041779386049f45f82e9bade2e73 --- /dev/null +++ b/bash-5.1/builtins_rust/umask/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rumask" +version = "0.1.0" +edition = "2021" +build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" + + + +[lib] +crate-type = ["cdylib"] +name = "rumask" diff --git a/bash-5.1/builtins_rust/umask/src/lib.rs b/bash-5.1/builtins_rust/umask/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..166a574e04b3e6b8c56a82b79205b064af4155fa --- /dev/null +++ b/bash-5.1/builtins_rust/umask/src/lib.rs @@ -0,0 +1,498 @@ +extern crate libc; +use libc::{c_char,c_int}; +use std::ffi::{CString}; + + + +//结构体 +#[repr (C)] +#[derive(Debug)] +pub struct WORD_DESC{ + pub word:*mut c_char, + pub flags:c_int, +} + +#[repr (C)] +#[derive(Debug)] +pub struct WORD_LIST{ + pub next:*mut WORD_LIST, + pub word:*mut WORD_DESC, +} + + +//枚举 + + +//宏 +#[macro_export] +macro_rules! mode_t { + () => { + i32 + }; +} + +#[macro_export] +macro_rules! EX_USAGE{ + () => { 258 } +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => { 1 }; +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS{ + () => { 0 } +} + +#[macro_export] +macro_rules! S_IREAD{ + () => { 0o0400 } +} + +#[macro_export] +macro_rules! S_IWRITE{ + () => { 0o0200 } +} + +#[macro_export] +macro_rules! S_IEXEC { + () => { 0o0100 }; +} + +#[macro_export] +macro_rules! S_IRUSR{ /* read, owner */ + () => { + S_IREAD!() + } +} + +#[macro_export] +macro_rules! S_IWUSR{ /* write, owner */ + () => { + S_IWRITE!() + } +} + +#[macro_export] +macro_rules! S_IXUSR { /* execute, owner */ + () => { + S_IEXEC!() + }; +} + +#[macro_export] +macro_rules! S_IRGRP { /* read, group */ + () => { + S_IREAD!() >> 3 + } +} + +#[macro_export] +macro_rules! S_IWGRP { /* write, group */ + () => { + S_IWRITE!() >> 3 + }; +} + +#[macro_export] +macro_rules! S_IXGRP { /* execute, group */ + () => { + S_IEXEC!() >> 3 + }; +} + +#[macro_export] +macro_rules! S_IROTH { /* read, other */ + () => { + S_IREAD!() >> 6 + }; +} + +#[macro_export] +macro_rules! S_IWOTH { /* write, other */ + () => { + S_IWRITE!() >> 6 + }; +} + +#[macro_export] +macro_rules! S_IXOTH { /* execute, other */ + () => { + S_IEXEC!() >> 6 + }; +} + +#[macro_export] +macro_rules! S_IRWXU{ + () => { + S_IRUSR!() | S_IWUSR!() | S_IXUSR!() + } +} + + + +#[macro_export] +macro_rules! S_IRWXG { + () => { + S_IRGRP!() | S_IWGRP!() | S_IXGRP!() + }; +} + +#[macro_export] +macro_rules! S_IRWXO { + () => { + S_IROTH!() | S_IWOTH!() | S_IXOTH!() + }; +} + +#[macro_export] +macro_rules! S_IRUGO { + () => { + S_IRUSR!() | S_IRGRP!() | S_IROTH!() + }; +} + +#[macro_export] +macro_rules! S_IWUGO { + () => { + S_IWUSR!() | S_IWGRP!() | S_IWOTH!() + }; +} + +#[macro_export] +macro_rules! S_IXUGO { + () => { + S_IXUSR!() | S_IXGRP!() | S_IXOTH!() + }; +} + +// #[macro_export] +// macro_rules! DIGIT{ +// ($c:expr) => { +// c >= '0' && c <= '9' +// } +// } + +// + +//C库 +extern "C" { + + static mut loptend:*mut WORD_LIST; + + fn reset_internal_getopt(); + fn internal_getopt (list:*mut WORD_LIST, opts:*mut c_char)->i32; + fn builtin_usage(); + fn read_octal(string:*mut c_char)->i32; + fn sh_erange(s:*mut c_char,desc:*mut c_char); + fn sh_chkwrite(s:i32)->i32; + fn umask(__maks:mode_t!())->mode_t!(); +} + +// +unsafe fn DIGIT(c:c_char) -> bool{ + char::from(c as u8 ) >= '0' && char::from(c as u8) <= '9' +} +//有可能错误 +unsafe fn member(c:*mut c_char,s:*mut c_char) -> bool{ + if c != std::ptr::null_mut(){ + let c = c as c_int; + let ptr = libc::strchr(s,c); + if ptr != std::ptr::null_mut(){ + true + } + else{ + false + } + } + else{ + false + } +} + +// +#[no_mangle] +/* Set or display the mask used by the system when creating files. Flag + of -S means display the umask in a symbolic mode. */ + +pub extern "C" fn r_umask_builtin(mut list:*mut WORD_LIST) ->i32{ + + let mut print_symbolically:i32; + let mut opt:i32; + let umask_value:i32; + let mut pflag:i32; + let umask_arg:mode_t!(); + unsafe{ + print_symbolically = 0; + pflag = 0; + reset_internal_getopt(); + + let c_str_sp = CString::new("Sp").unwrap(); + opt = internal_getopt(list,c_str_sp.as_ptr() as *mut c_char); + while opt != -1 { + let optu8 = opt as u8; + let opt_char = char::from(optu8); + match opt_char { + 'S' => {print_symbolically = print_symbolically +1;} + 'p' => {pflag = pflag + 1;} + _ => { builtin_usage(); + return EX_USAGE!(); + } + } + + opt = internal_getopt(list,c_str_sp.as_ptr() as *mut c_char); + } + + list = loptend; + if list != std::ptr::null_mut(){ + if DIGIT( *(*(*list).word).word) != false { + umask_value = read_octal((*(*list).word).word); + /* Note that other shells just let you set the umask to zero + by specifying a number out of range. This is a problem + with those shells. We don't change the umask if the input + is lousy. */ + if umask_value == -1{ + let c_str = CString::new("octal number").unwrap(); + let c_char_str:*mut c_char = c_str.into_raw(); + sh_erange((*(*list).word).word,c_char_str); + return EXECUTION_FAILURE!(); + } + } + else{ + umask_value = symbolic_umask(list); + if umask_value == -1{ + return EXECUTION_FAILURE!(); + } + } + umask_arg = umask_value; + umask(umask_arg); + if print_symbolically != 0{ + print_symbolic_umask(umask_arg); + } + } + else{ /* Display the UMASK for this user. */ + umask_arg = umask(022); + umask(umask_arg); + + if pflag != 0{ + if print_symbolically != 0{ + println!("umask \" -S\" "); + } + else{ + println!("umask \"\" ") + } + } + + if print_symbolically != 0{ + print_symbolic_umask(umask_arg); + } + else{ + println!("{}",umask_arg); + println!("{:04o}",umask_arg); + } + } + return sh_chkwrite(EXECUTION_SUCCESS!()); + } +} + + +#[no_mangle] +/* Print the umask in a symbolic form. In the output, a letter is + printed if the corresponding bit is clear in the umask. */ + +extern "C" fn print_symbolic_umask(um:mode_t!()){ + /* u=rwx,g=rwx,o=rwx */ + let mut ubits = String::new(); + let mut gbits =String::new(); + let mut obits = String::new(); + + if um & S_IRUSR!() == 0{ + ubits.push('r'); + } + if um & S_IWUSR!() == 0{ + ubits.push('w'); + } + if um & S_IXUSR!() == 0{ + ubits.push('x'); + } + + if um & S_IRGRP!() == 0{ + gbits.push('r'); + } + if um & S_IWGRP!() == 0{ + gbits.push('w'); + } + if um & S_IXGRP!() == 0{ + gbits.push('x'); + } + + if um & S_IROTH!() == 0{ + obits.push('r'); + } + if um & S_IWOTH!() == 0{ + obits.push('w'); + } + if um & S_IXOTH!() == 0{ + obits.push('x'); + } + + println!{"u={},g={},o={}",ubits,gbits,obits}; +} + +#[no_mangle] +extern "C" fn parse_symbolic_mode(mode:*mut c_char,initial_bits:i32)->i32{ + let mut who:i32; + let mut op:i32; + let mut perm:i32; + let mut bits:i32; + let mut c:i32; + let mut s:*mut c_char; + + s = mode; + bits = initial_bits; + + unsafe{ + loop{ + who = 0; + op = 0; + perm = 0; + + /* Parse the `who' portion of the symbolic mode clause. */ + let c_str = CString::new("agou").unwrap(); + while member (s,c_str.as_ptr() as *mut c_char){ + c = *s as c_int; + s = (s as usize + 1) as *mut c_char; + let optu8 = c as u8; + let opt_char = char::from(optu8); + match opt_char{ + 'u' => { + who |= S_IRWXU!(); + continue; + } + 'g' => { + who |= S_IRWXG!(); + continue; + } + 'o' => { + who |= S_IRWXO!(); + continue; + } + 'a' => { + who |= S_IRWXU!() | S_IRWXG!() | S_IRWXO!(); + continue; + } + _ => { + + } + } + } + + /* The operation is now sitting in *s. */ + op = *s as c_int; + // *s = *s + 1; + s = (s as usize + 1) as *mut c_char; + let opu8 = op as u8; + let op_str = char::from(opu8); + match op_str{ + '+' | '-' | '=' => {} + _ => { + println!("{}:invalid symbolic mode operator",op_str); + return -1; + } + } + + /* Parse out the `perm' section of the symbolic mode clause. */ + let c_rwx_str = CString::new("rwx").unwrap(); + while member(s,c_rwx_str.as_ptr() as *mut c_char){ + c = s as c_int; + //*s = *s + 1; + s = (s as usize + 1) as *mut c_char; + let optu8 = c as u8; + let op_str = char::from(optu8); + + match op_str { + 'r' => perm |= S_IRUGO!(), + 'w' => perm |= S_IWUGO!(), + 'x' => perm |= S_IXUGO!(), + _ => { } + } + } + + /* Now perform the operation or return an error for a + bad permission string. */ + if *s != 0 || *s == ',' as i8{ + if who != 0{ + perm &= who; + } + + match op_str{ + '+' => bits |= perm, + '-' => bits &= !perm, + '=' => { + if who == 0{ + who = S_IRWXU!() | S_IRWXG!() | S_IRWXO!(); + bits &= ! who; + bits |= perm; + } + } + /* No other values are possible. */ + _ => { } + } + if *s == '\0' as i8{ + break; + } + else { + //*s = *s + 1; + s = (s as usize + 1) as *mut c_char; + } + } + else { + println!("{}:invalid symbolic mode character",*s as c_char); + return -1; + } + }//loop + return bits; + } +} + + +#[no_mangle] +/* Set the umask from a symbolic mode string similar to that accepted + by chmod. If the -S argument is given, then print the umask in a + symbolic form. */ + +extern "C" fn symbolic_umask(list:*mut WORD_LIST)->i32{ + let mut um:i32; + let bits:i32; + + unsafe{ + /* Get the initial umask. Don't change it yet. */ + um = umask(022); + umask(um); + + /* All work is done with the complement of the umask -- it's + more intuitive and easier to deal with. It is complemented + again before being returned. */ + bits = parse_symbolic_mode((*(*list).word).word, !um & 0777); + if bits == -1 { + return -1; + } + + um = !bits & 0777; + return um; + } + +} + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + } +} diff --git a/bash-5.1/builtins_rust/wait/.gitignore b/bash-5.1/builtins_rust/wait/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4fffb2f89cbd8f2169ce9914bd16bd43785bb368 --- /dev/null +++ b/bash-5.1/builtins_rust/wait/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/bash-5.1/builtins_rust/wait/Cargo.toml b/bash-5.1/builtins_rust/wait/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..8254cefaf7c5509c363668374e30ef6546a7818f --- /dev/null +++ b/bash-5.1/builtins_rust/wait/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "rwait" +version = "0.1.0" +edition = "2018" +build = "../build.rs" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +libc = "0.2" +rjobs = {path = "../jobs"} +read = {path = "../read"} +nix = "0.23.0" + +[lib] +crate-type = ["cdylib","rlib"] +name = "rwait" diff --git a/bash-5.1/builtins_rust/wait/src/lib.rs b/bash-5.1/builtins_rust/wait/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..e4887d6732e50a5a3b1822d561538a980737e3ef --- /dev/null +++ b/bash-5.1/builtins_rust/wait/src/lib.rs @@ -0,0 +1,554 @@ +extern crate libc; +extern crate rjobs; +extern crate rread; +extern crate nix; + +use libc::{c_char, intmax_t, pid_t, c_short,c_int, SIGCHLD, c_long}; +use std::ffi::{CString, CStr}; +use nix::sys::signal::{SigSet}; + +use rjobs::{PROCESS,COMMAND, BLOCK_CHILD, UNBLOCK_CHILD}; +use rjobs::WORD_LIST; +use rread::{SHELL_VAR,sh_var_value_func_t,sh_var_assign_func_t, + sigjmp_buf,__jmp_buf_tag,__sigset_t,__sigsetjmp,}; + + + +//结构体 +#[repr(C)] +pub struct procstat{ + pub pid:pid_t, + pub status:c_short, +} + +#[repr(C)] +pub struct JOB { + wd: *mut c_char, + pipe: *mut PROCESS, + pgrp:i32, + state:JOB_STATE, + flags:i32, + deferred:*mut COMMAND, + j_cleanup:*mut fn(), + cleanarg:* mut fn() +} + +#[repr(C)] +pub struct jobstats { + /* limits */ + c_childmax:libc::c_long, + /* child process statistics */ + c_living:libc::c_int, /* running or stopped child processes */ + c_reaped:libc::c_int, /* exited child processes still in jobs list */ + c_injobs:libc::c_int, /* total number of child processes in jobs list */ + /* child process totals */ + c_totforked:libc::c_int, /* total number of children this shell has forked */ + c_totreaped:libc::c_int, /* total number of children this shell has reaped */ + /* job counters and indices */ + j_jobslots:libc::c_int,/* total size of jobs array */ + j_lastj:libc::c_int, /* last (newest) job allocated */ + j_firstj:libc::c_int, /* first (oldest) job allocated */ + j_njobs:libc::c_int, /* number of non-NULL jobs in jobs array */ + j_ndead:libc::c_int, /* number of JDEAD jobs in jobs array */ + /* */ + j_current:libc::c_int, /* current job */ + j_previous:libc::c_int, /* previous job */ + /* */ + j_lastmade:* mut JOB, /* last job allocated by stop_pipeline */ + j_lastasync:* mut JOB /* last async job allocated by stop_pipeline */ +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct variable { + pub name: *mut c_char, + pub value: *mut c_char, + pub exportstr: *mut c_char, + pub dynamic_value: sh_var_value_func_t, + pub assign_func: sh_var_assign_func_t, + pub attributes: c_int, + pub context: c_int, +} + +pub type arrayind_t = intmax_t; +//枚举 +#[repr(i8)] +#[derive(PartialEq)] +pub enum JOB_STATE { + JNONE = -1, + JRUNNING = 1, + JSTOPPED = 2, + JDEAD = 4, + JMIXED = 8 +} + + +//宏 +#[macro_export] +macro_rules! EX_USAGE{ /* syntax error in usage */ + () => { 258 } +} + +#[macro_export] +macro_rules! EXECUTION_SUCCESS { + () => { + 0 + }; +} + +#[macro_export] +macro_rules! EXECUTION_FAILURE { + () => { + 1 + }; +} + +#[macro_export] +macro_rules! J_WAITING { + () => { 0x08 } +} + +#[macro_export] +macro_rules! JWAIT_FORCE { + () => { 1 << 1 } +} + +#[macro_export] +macro_rules! NO_JOB { + () => { -1 } +} + +#[macro_export] +macro_rules! DUP_JOB{ + () => { -2 } +} + +#[macro_export] +macro_rules! VA_NOEXPAND { + () => { 0x001 } +} + +#[macro_export] +macro_rules! VA_ONEWORD { + () => { 0x002 }; +} + +#[macro_export] +macro_rules! JWAIT_WAITING { + () => { 1 << 3 }; +} + +#[macro_export] +macro_rules! JWAIT_PEROOR { + () => { 1 << 0}; +} + +#[macro_export] +macro_rules! NO_PID { + () => { -1 as pid_t } +} + +#[macro_export] +macro_rules! get_job_by_jid { + ($ind:expr) => { + (*((jobs as usize + ($ind*8) as usize) as *mut *mut JOB) as *mut JOB) + }; +} + +#[macro_export] +macro_rules! INVALID_JOB { + ($j:expr) => { + ($j)<0 || ($j)>= js.j_jobslots || get_job_by_jid!($j) == std::ptr::null_mut() + }; +} + +#[macro_export] +macro_rules! BLOCK_SIGNAL{ + ($sig:expr,$nvar:expr,$ovar:expr) => { + $nvar.unwrap().clear(); + $nvar.unwrap().add($sig); + $nvar.unwrap().clear(); + nix::sys::signal::sigprocmask(nix::sys::signal::SigmaskHow::SIG_BLOCK,$nvar,$ovar); + } +} + +#[macro_export] +macro_rules! UNBLOCK_SIGNAL { + ($ovar:expr) => { + nix::sys::signal::sigprocmask(nix::sys::signal::SigmaskHow::SIG_SETMASK,$ovar,None) + }; +} + +#[macro_export] +macro_rules! sigsetjmp { + ($env:expr,$savemask:expr) => { + unsafe{ + __sigsetjmp($env,$savemask) + } + + }; +} + +#[macro_export] +macro_rules! setjmp_sigs { + ($x:expr) => { + sigsetjmp!(($x),1) + }; +} + +pub type procenv_t=sigjmp_buf; +//C库 +extern "C" { + static mut wait_signal_received:i32; + // static mut wait_intr_flag:i32; + static mut loptend:*mut WORD_LIST; + static js:jobstats ; + static mut jobs:*mut*mut JOB; + static list_optarg:*mut c_char; + static assoc_expand_once:i32; + static mut last_command_exit_signal:i32; + static posixly_correct:i32; + + // fn sigsetjmp(env:sigjmp_buf,val:c_int)->i32; + fn internal_getopt (list:*mut WORD_LIST, opts:*mut c_char)->i32; + fn builtin_usage(); + fn legal_number(string:*const c_char,result:*mut c_long)->i32; + fn get_job_by_pid(pid:pid_t,block:i32,procp:*mut *mut PROCESS)->i32; + fn get_job_spec(list:*mut WORD_LIST)->i32; + fn sh_badjob(str:*mut c_char); + fn reset_internal_getopt(); + fn legal_identifier(name:*const c_char)->i32; + fn valid_array_reference(name:*const c_char,flage:i32)->i32; + fn sh_invalidid(s:*mut c_char); + fn builtin_unbind_variable(name:*const c_char)->i32; + fn wait_sigint_cleanup(); + fn first_pending_trap()->i32; + fn next_pending_trap(start:i32)->i32; + fn wait_for_any_job(flags:i32,ps:*mut procstat)->i32; + fn bind_var_to_int(var:*mut c_char,val:intmax_t)->*mut SHELL_VAR; + fn wait_for_background_pids(ps:*mut procstat); + fn wait_for_single_pid(pid:pid_t,flags:i32)->i32; + fn wait_for_job(job:i32,flags:i32,ps:*mut procstat)->i32; +} + +unsafe fn DIGIT(c:c_char)->bool{ + char::from(c as u8) >= '0' && char::from(c as u8) <= '9' +} + +#[macro_export] +macro_rules! WAIT_RETURN { + ($s:expr) => { + { + wait_signal_received = 0; + wait_intr_flag = 0; + + $s + } + }; +} + +pub static mut wait_intr_flag:i32=0; +pub static mut wait_intr_buf:procenv_t = [__jmp_buf_tag{ + __jmpbuf:[0;8], + __mask_was_saved:0, + __saved_mask:__sigset_t{__val:[0;16]}, +}; 1]; + +//rust +#[no_mangle] +pub extern "C" fn r_wait_builtin(mut list:*mut WORD_LIST)->i32{ + let mut status:i32; + let code:i32; + let mut opt:i32; + let mut nflag:i32; + let mut wflags:i32; + let mut vname:*mut c_char; + let pidvar:*mut SHELL_VAR; + let mut pstat:procstat = procstat{ + pid:0, + status:0,}; + + unsafe{ + // USE_VAR(list); + nflag = 0; + wflags = 0; + vname = std::ptr::null_mut(); + pidvar = std::ptr::null_mut(); + + reset_internal_getopt(); + let c_fnp = CString::new("fnp:").unwrap(); + opt = internal_getopt(list,c_fnp.as_ptr() as *mut c_char); + while opt != -1{ + let optu8 = opt as u8; + let opt_char = char::from(optu8); + + match opt_char{ + 'n' => nflag = 1, + 'f' => wflags |= JWAIT_FORCE!(), + 'P' => vname = list_optarg, + _ => { + builtin_usage(); + return EX_USAGE!(); + } + } + } + + list = loptend; + /* Sanity-check variable name if -p supplied. */ + if vname != std::ptr::null_mut(){ + + //这里有个条件编译,确定是否需要 + let arrayflags:i32; + if assoc_expand_once != 0{ + arrayflags = VA_NOEXPAND!() | VA_ONEWORD!(); + } + else{ + arrayflags = 0; + } + + if legal_identifier(vname) == 0 && valid_array_reference(vname,arrayflags) == 0{ + sh_invalidid(vname); + return WAIT_RETURN!(EXECUTION_FAILURE!()); + } + + if builtin_unbind_variable(vname) == -2{ + return WAIT_RETURN!(EXECUTION_FAILURE!()); + } + } + /* POSIX.2 says: When the shell is waiting (by means of the wait utility) + for asynchronous commands to complete, the reception of a signal for + which a trap has been set shall cause the wait utility to return + immediately with an exit status greater than 128, after which the trap + associated with the signal shall be taken. + + We handle SIGINT here; it's the only one that needs to be treated + specially (I think), since it's handled specially in {no,}jobs.c. */ + + wait_intr_flag = 1; + code = setjmp_sigs!(&mut wait_intr_buf[0]); + + if code != 0{ + last_command_exit_signal = wait_signal_received; + status = 128 + wait_signal_received; + wait_sigint_cleanup(); + return WAIT_RETURN!(status); + } + + opt = first_pending_trap(); + + //#if define (SIGCHLD) + + /* We special case SIGCHLD when not in posix mode because we don't break + out of the wait even when the signal is trapped; we run the trap after + the wait completes. See how it's handled in jobs.c:waitchld(). */ + + if opt==SIGCHLD && posixly_correct==0{ + opt = next_pending_trap(opt+1); + } + if opt != -1{ + last_command_exit_signal = opt; + wait_signal_received = opt; + status = opt +128; + return WAIT_RETURN!(status); + } + + //if define JB_CONTROL + /* We support jobs or pids. + wait [pid-or-job ...] */ + if nflag != 0{ + if list != std::ptr::null_mut(){ + opt = r_set_waitlist(list); + if opt == 0{ + return WAIT_RETURN!(127); + } + wflags |= JWAIT_WAITING!(); + } + + status = wait_for_any_job(wflags,&mut pstat); + if vname!=std::ptr::null_mut() && status>=0{ + bind_var_to_int(vname,pstat.pid as intmax_t); + } + + if status < 0{ + status = 127; + } + if list != std::ptr::null_mut(){ + r_unset_waitlist(); + } + return WAIT_RETURN!(status); + } + //endif + + /* But wait without any arguments means to wait for all of the shell's + currently active background processes. */ + if list == std::ptr::null_mut(){ + wait_for_background_pids(&mut pstat); + if vname != std::ptr::null_mut() { + bind_var_to_int(vname,pstat.pid as intmax_t); + } + return WAIT_RETURN!(EXECUTION_SUCCESS!()); + // WAIT_RETURN!() + } + + status = EXECUTION_SUCCESS!(); + while list != std::ptr::null_mut(){ + let mut pid:pid_t; + let mut w:*mut c_char; + let mut pid_value:intmax_t = 0; + + w = (*(*list).word).word; + if DIGIT(*w){ + if legal_number(w, &mut pid_value) !=0 && pid_value == (pid_value as pid_t) as i64 { + pid =pid_value as pid_t; + status = wait_for_single_pid(pid,wflags|JWAIT_PEROOR!()); + pstat.pid = pid; + pstat.status = status as c_short; + } + else { + sh_badjob(w); + pstat.pid = NO_PID!(); + pstat.status = 127; + return WAIT_RETURN!(EXECUTION_FAILURE!()); + } + } + + //if defined (JOB_CONTROL) + //else if w != std::ptr::null_mut() && (w as u8)as char == '%' { + else if *w != 0 && *w == '%' as i8 { + /* Must be a job spec. Check it out. */ + let job:i32; + let mut set:SigSet = SigSet::empty(); + let mut oset:SigSet = SigSet::empty(); + + BLOCK_CHILD!(Some(&mut set),Some(&mut oset)); + job = get_job_spec(list); + + if INVALID_JOB!(job) == true{ + if job != DUP_JOB!(){ + sh_badjob( (*(*list).word).word); + } + UNBLOCK_CHILD!(Some(&mut oset)); + status = 127; /* As per Posix.2, section 4.70.2 */ + pstat.pid = NO_PID!(); + pstat.status = status as c_short; + list = (*list).next; + continue; + } + + /* Job spec used. Wait for the last pid in the pipeline. */ + UNBLOCK_CHILD!(Some(&mut oset)); + status = wait_for_job(job,wflags,&mut pstat) + } + else { + sh_badjob(w); + pstat.pid = NO_PID!(); + pstat.status = 127; + status = EXECUTION_FAILURE!(); + } + + /* Don't waste time with a longjmp. */ + if wait_signal_received != 0{ + last_command_exit_signal = wait_signal_received; + status = 128 + wait_signal_received; + wait_sigint_cleanup(); + return WAIT_RETURN!(status); + } + + list = (*list).next; + } + + return WAIT_RETURN!(status); + + } //unsafe +} + + + +#[no_mangle] +extern "C" fn r_set_waitlist(list:*mut WORD_LIST) -> i32{ + let mut set:SigSet = SigSet::empty(); + let mut oset:SigSet = SigSet::empty(); + let mut job:i32; + let mut r:i32; + let mut njob:i32; + let mut pid:intmax_t=0; + let mut l:*mut WORD_LIST; + + unsafe{ + BLOCK_CHILD!(Some(&mut set),Some(&mut oset)); + njob = 0; + + l = list; + while l != std::ptr::null_mut(){ //如何换成for + job = NO_JOB!(); + + if l!=std::ptr::null_mut() && legal_number( (*(*l).word).word, &mut pid ) != 0 && pid == (pid as pid_t) as i64{ + job = get_job_by_pid(pid as pid_t,0,std::ptr::null_mut()); + } + else{ + get_job_spec(l); + } + + if job == NO_JOB!() || jobs == std::ptr::null_mut() || INVALID_JOB!(job) { + sh_badjob( (*(*l).word).word ); + continue; + } + + /* We don't check yet to see if one of the desired jobs has already + terminated, but we could. We wait until wait_for_any_job(). This + has the advantage of validating all the arguments. */ + if (*get_job_by_jid!(job)).flags & J_WAITING!() == 0{ + njob = njob + 1; + (*get_job_by_jid!(job)).flags |= J_WAITING!(); + } + + l = (*l).next; + } + UNBLOCK_CHILD!(Some(&mut oset)); + + return njob; + }//unsafe + +} + + +// #[macro_export] +// macro_rules! get_job_by_jid { //研究下jobs[i] +// ($ind:expr) => { +// (*((jobs as usize + ($ind*8) as usize ) as *mut*mut JOB) as *mut JOB) +// } +// } +/* Clean up after a call to wait -n jobs */ +#[no_mangle] +extern "C" fn r_unset_waitlist(){ + let mut i:i32; + let mut set:SigSet = SigSet::empty(); + let mut oset:SigSet = SigSet::empty(); + + unsafe{ + BLOCK_CHILD!(Some(&mut set),Some(&mut oset)); + for i in 0..js.j_jobslots{ + if get_job_by_jid!(i) != std::ptr::null_mut() && (*get_job_by_jid!(i)).flags & J_WAITING!( + + ) != 0{ + (*get_job_by_jid!(i)).flags &= !J_WAITING!(); + } + } + + UNBLOCK_CHILD!(Some(&mut oset)); + } + +} + + + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + let result = 2 + 2; + assert_eq!(result, 4); + + } +} diff --git a/bash-5.1/configure b/bash-5.1/configure index 0d917697efd3adc03a884f7dcce0942c0899228d..fd4e211334d8533c9670194bf9f4a637dc2a10e8 100755 --- a/bash-5.1/configure +++ b/bash-5.1/configure @@ -1,9 +1,9 @@ #! /bin/sh # From configure.ac for Bash 5.1, version 5.022. # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for bash 5.1-release. +# Generated by GNU Autoconf 2.69 for rash 0.1-release. # -# Report bugs to . +# Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -267,7 +267,7 @@ fi $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else - $as_echo "$0: Please tell bug-autoconf@gnu.org and bug-bash@gnu.org + $as_echo "$0: Please tell bug-autoconf@gnu.org and bug-rash@gnu.org $0: about your system, including any error possibly output $0: before this message. Then install a modern shell, or $0: manually run the script under such a shell if you do @@ -579,11 +579,11 @@ MFLAGS= MAKEFLAGS= # Identity of this package. -PACKAGE_NAME='bash' -PACKAGE_TARNAME='bash' -PACKAGE_VERSION='5.1-release' -PACKAGE_STRING='bash 5.1-release' -PACKAGE_BUGREPORT='bug-bash@gnu.org' +PACKAGE_NAME='rash' +PACKAGE_TARNAME='rash' +PACKAGE_VERSION='0.1-release' +PACKAGE_STRING='rash 0.1-release' +PACKAGE_BUGREPORT='bug-rash@gnu.org' PACKAGE_URL='' ac_unique_file="shell.h" @@ -1427,7 +1427,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures bash 5.1-release to adapt to many kinds of systems. +\`configure' configures rash 0.1-release to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1475,7 +1475,7 @@ Fine tuning of the installation directories: --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/bash] + --docdir=DIR documentation root [DATAROOTDIR/doc/rash] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] @@ -1492,7 +1492,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of bash 5.1-release:";; + short | recursive ) echo "Configuration of rash 0.1-release:";; esac cat <<\_ACEOF @@ -1630,7 +1630,7 @@ Some influential environment variables: Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. -Report bugs to . +Report bugs to . _ACEOF ac_status=$? fi @@ -1693,7 +1693,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -bash configure 5.1-release +rash configure 0.1-release generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1899,7 +1899,7 @@ $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" > { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ------------------------------- ## -## Report this to bug-bash@gnu.org ## +## Report this to bug-rash@gnu.org ## ## ------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; @@ -2402,7 +2402,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by bash $as_me 5.1-release, which was +It was created by rash $as_me 0.1-release, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2799,7 +2799,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. ac_config_headers="$ac_config_headers config.h" -BASHVERS=5.1 +BASHVERS=0.1 RELSTATUS=release case "$RELSTATUS" in @@ -4231,7 +4231,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$want_auto_cflags"; then AUTO_CFLAGS="-g ${GCC+-O2}" AUTO_LDFLAGS="-g ${GCC+-O2}" - STYLE_CFLAGS="${GCC+-Wno-parentheses} ${GCC+-Wno-format-security} ${GCC+-fPIC}" + STYLE_CFLAGS="${GCC+-Wno-parentheses} ${GCC+-Wno-format-security}" else AUTO_CFLAGS= AUTO_LDFLAGS= STYLE_CFLAGS= fi @@ -13881,7 +13881,7 @@ fi for ac_func in dup2 eaccess fcntl getdtablesize getentropy getgroups \ gethostname getpagesize getpeername getrandom getrlimit \ getrusage gettimeofday kill killpg lstat pselect readlink \ - select setdtablesize setitimer tcgetpgrp uname ulimit waitpid + select setdtablesize setitimer tcgetpgrp uname ulimit waitpid pread do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -17094,7 +17094,7 @@ main() _ACEOF if ac_fn_c_try_run "$LINENO"; then : - bash_cv_pgrp_pipe=no + bash_cv_pgrp_pipe=yes else bash_cv_pgrp_pipe=yes fi @@ -17208,6 +17208,19 @@ $as_echo "#define HAVE_USG_SIGHOLD 1" >>confdefs.h fi +ac_fn_c_check_decl "$LINENO" "AUDIT_USER_TTY" "ac_cv_have_decl_AUDIT_USER_TTY" "#include +" +if test "x$ac_cv_have_decl_AUDIT_USER_TTY" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_AUDIT_USER_TTY $ac_have_decl +_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys_errlist and sys_nerr" >&5 $as_echo_n "checking for sys_errlist and sys_nerr... " >&6; } if ${bash_cv_sys_errlist+:} false; then : @@ -20255,7 +20268,6 @@ fi $as_echo "using $bash_cv_termcap_lib" >&6; } if test $bash_cv_termcap_lib = gnutermcap && test -z "$prefer_curses"; then LDFLAGS="$LDFLAGS -L./lib/termcap" - TERMCAP_LIB="./lib/termcap/libtermcap.a" TERMCAP_DEP="./lib/termcap/libtermcap.a" elif test $bash_cv_termcap_lib = libtermcap && test -z "$prefer_curses"; then @@ -20547,7 +20559,7 @@ fi #AC_SUBST(ALLOCA_SOURCE) #AC_SUBST(ALLOCA_OBJECT) -ac_config_files="$ac_config_files Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile lib/intl/Makefile lib/malloc/Makefile lib/sh/Makefile lib/termcap/Makefile lib/tilde/Makefile doc/Makefile support/Makefile po/Makefile.in examples/loadables/Makefile examples/loadables/Makefile.inc examples/loadables/perl/Makefile support/bash.pc support/bashbug.sh" +ac_config_files="$ac_config_files Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile lib/intl/Makefile lib/malloc/Makefile lib/sh/Makefile lib/termcap/Makefile lib/tilde/Makefile doc/Makefile support/Makefile po/Makefile.in examples/loadables/Makefile examples/loadables/Makefile.inc examples/loadables/perl/Makefile support/rash.pc support/rashbug.sh" ac_config_commands="$ac_config_commands default" @@ -21058,7 +21070,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by bash $as_me 5.1-release, which was +This file was extended by rash $as_me 0.1-release, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -21118,13 +21130,13 @@ $config_headers Configuration commands: $config_commands -Report bugs to ." +Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -bash config.status 5.1-release +rash config.status 0.1-release configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -21274,8 +21286,8 @@ do "examples/loadables/Makefile") CONFIG_FILES="$CONFIG_FILES examples/loadables/Makefile" ;; "examples/loadables/Makefile.inc") CONFIG_FILES="$CONFIG_FILES examples/loadables/Makefile.inc" ;; "examples/loadables/perl/Makefile") CONFIG_FILES="$CONFIG_FILES examples/loadables/perl/Makefile" ;; - "support/bash.pc") CONFIG_FILES="$CONFIG_FILES support/bash.pc" ;; - "support/bashbug.sh") CONFIG_FILES="$CONFIG_FILES support/bashbug.sh" ;; + "support/rash.pc") CONFIG_FILES="$CONFIG_FILES support/rash.pc" ;; + "support/rashbug.sh") CONFIG_FILES="$CONFIG_FILES support/rashbug.sh" ;; "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; diff --git a/bash-5.1/configure.ac b/bash-5.1/configure.ac index aeb3d30bcbb0fd16acae0cfc11145a5e651d2f2e..2d2a05906fe9319503f889cdb6931b646c7fbc57 100644 --- a/bash-5.1/configure.ac +++ b/bash-5.1/configure.ac @@ -23,10 +23,10 @@ dnl Process this file with autoconf to produce a configure script. AC_REVISION([for Bash 5.1, version 5.022])dnl -define(bashvers, 5.1) +define(rashvers, 0.1) define(relstatus, release) -AC_INIT([bash], bashvers-relstatus, [bug-bash@gnu.org]) +AC_INIT([rash], rashvers-relstatus, [bug-rash@gnu.org]) dnl make sure we are using a recent autoconf version AC_PREREQ(2.61) @@ -37,7 +37,7 @@ AC_CONFIG_AUX_DIR(./support) AC_CONFIG_HEADERS(config.h) dnl checks for version info -BASHVERS=bashvers +BASHVERS=rashvers RELSTATUS=relstatus dnl defaults for debug settings @@ -1305,7 +1305,7 @@ AC_OUTPUT([Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile \ lib/tilde/Makefile doc/Makefile support/Makefile po/Makefile.in \ examples/loadables/Makefile examples/loadables/Makefile.inc \ examples/loadables/perl/Makefile \ - support/bash.pc support/bashbug.sh], + support/bash.pc support/rashbug.sh], [ # Makefile uses this timestamp file to record whether config.h is up to date. echo timestamp > stamp-h diff --git a/bash-5.1/create-so.sh b/bash-5.1/create-so.sh index 26bd7b15b2276d04cd004a78ebfc90329b1f35e6..8b37e7ba1e86b52b5b2da146b601440c007d7fcd 100644 --- a/bash-5.1/create-so.sh +++ b/bash-5.1/create-so.sh @@ -1,10 +1,18 @@ #!/bin/bash find . -name "*.o" > o.list + + for line in `cat o.list` do - soname=${line%%.o*} - soname=${soname##*.} - soname=${soname////_} + echo "000 $line" + #soname=`basename $line` + soname=${line%.o} + echo "AAA $soname" + soname=${soname#./} + echo "BBB $soname" + soname=`echo $soname |sed 's/\//_/g'` + echo "CCC $soname" + echo "gcc -shared -fPIC -o /opt/rsbash/builtins/lib${soname}.so $line " gcc -shared -fPIC -o /opt/rsbash/builtins/lib${soname}.so $line done diff --git a/bash-5.1/examples/scripts/shprompt b/bash-5.1/examples/scripts/shprompt index 098c45f0465b3e612dd9437a476a3d7019f84424..91035a8c69fe26ea5903c3e4b4bb4910ad03c4d2 100755 --- a/bash-5.1/examples/scripts/shprompt +++ b/bash-5.1/examples/scripts/shprompt @@ -1,3 +1,4 @@ +#!/bin/bash # # shprompt -- give a prompt and get an answer satisfying certain criteria # diff --git a/bash-5.1/execute_cmd.c b/bash-5.1/execute_cmd.c index ecd509c32581a4e37a2b5e4ab5eb4bb138891e59..77e058cf7890670c26f37492facfa6944814edea 100644 --- a/bash-5.1/execute_cmd.c +++ b/bash-5.1/execute_cmd.c @@ -4737,7 +4737,7 @@ execute_builtin (builtin, words, flags, subshell) error_trap = 0; should_keep = 0; - r_execute_cmd(); + //r_execute_cmd(); /* The eval builtin calls parse_and_execute, which does not know about the setting of flags, and always calls the execution functions with flags that will exit the shell on an error if -e is set. If the @@ -4841,6 +4841,7 @@ execute_builtin (builtin, words, flags, subshell) executing_builtin++; executing_command_builtin |= builtin == command_builtin; result = ((*builtin) (words->next)); + // r_execute_cmd2(words->next); /* This shouldn't happen, but in case `return' comes back instead of longjmp'ing, we need to unwind. */ @@ -5311,6 +5312,7 @@ execute_builtin_or_function (words, builtin, var, redirects, int ofifo, nfifo, osize; void *ofifo_list; #endif + #if defined (PROCESS_SUBSTITUTION) begin_unwind_frame ("saved_fifos"); /* If we return, we longjmp and don't get a chance to restore the old diff --git a/bash-5.1/rsbuiltins.h b/bash-5.1/rsbuiltins.h index f3b7f9be9d9ad1014d1aab6e2550fd762765ebc1..f6f3be36af13058d9fcb82d8cc048c5a0921f165 100644 --- a/bash-5.1/rsbuiltins.h +++ b/bash-5.1/rsbuiltins.h @@ -1,2 +1,4 @@ #include +#include "command.h" int r_execute_cmd(); +int r_execute_cmd2(WORD_LIST *l); diff --git a/bash-5.1/src/lib.rs b/bash-5.1/src/lib.rs index 874f7e601d0de1901eee964f3b7613a623bc330a..a742d42794e07464ab95baf64bba7c71e041c9f5 100644 --- a/bash-5.1/src/lib.rs +++ b/bash-5.1/src/lib.rs @@ -1,5 +1,42 @@ +use libc::{c_char, c_int }; +use std::ffi::CStr; +use std::str; + +#[repr(C)] +pub struct WORD_DESC { + pub word : *mut c_char, + pub flags : c_int +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct WORD_LIST { + next : *mut WORD_LIST, + word : *mut WORD_DESC +} + + +//#[link(name = "")] +//extern { + // pub fn printf( #[no_mangle] pub extern "C" fn r_execute_cmd() { - println!("hello"); + //println!("hello"); + //common::builtin_error("test error") } +#[no_mangle] +pub extern "C" fn r_execute_cmd2(l : *mut WORD_LIST) -> i32 { + unsafe { + let mut it : *mut WORD_LIST = l; + while std::ptr::null() != it { + //let mut a = (&((* ((*l).word)).word) ); + let a :*mut c_char =( *(*it).word).word; + let c_str: &CStr = CStr::from_ptr(a); + let str_slice: &str = c_str.to_str().unwrap(); + println! ("word is {:?}", str_slice); + it = (*it).next; + } + } + 0 +} diff --git a/bash-5.1/src/main.rs b/bash-5.1/src/main.rs index b1ec861f325d7966834d67593d6472b36ebf3afe..ab6dd25bc02ba7016af5ff16f6c302dc001b2321 100644 --- a/bash-5.1/src/main.rs +++ b/bash-5.1/src/main.rs @@ -1,10 +1,9 @@ -use command1::say_hello; -use command2::hello2; - +//use command1::say_hello; +//use command2::hello2; fn main() { - hello2(); - say_hello(); +// hello2(); +// say_hello(); println!("Hello, world!"); //execute_cmd(); } diff --git a/bash-5.1/support/config.guess b/bash-5.1/support/config.guess index 0fc11edb2d12e8bf868867f181d93e814e724015..caea0faea3cb1521af9c58858b43b2e47c69994d 100755 --- a/bash-5.1/support/config.guess +++ b/bash-5.1/support/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2020 Free Software Foundation, Inc. +# Copyright 1992-2016 Free Software Foundation, Inc. -timestamp='2020-11-07' +timestamp='2016-10-02' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2020-11-07' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -27,19 +27,19 @@ timestamp='2020-11-07' # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . -me=$(echo "$0" | sed -e 's,.*/,,') +me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. -Options: +Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -50,7 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2020 Free Software Foundation, Inc. +Copyright 1992-2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -84,6 +84,8 @@ if test $# != 0; then exit 1 fi +trap 'exit 1' 1 2 15 + # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a @@ -94,77 +96,66 @@ fi # Portable tmp directory creation inspired by the Autoconf team. -tmp= -# shellcheck disable=SC2172 -trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 - -set_cc_for_build() { - # prevent multiple calls if $tmp is already set - test "$tmp" && return 0 - : "${TMPDIR=/tmp}" - # shellcheck disable=SC2039 - { tmp=$( (umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null) && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } - dummy=$tmp/dummy - case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in - ,,) echo "int x;" > "$dummy.c" - for driver in cc gcc c89 c99 ; do - if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then - CC_FOR_BUILD="$driver" - break - fi - done - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; - esac -} +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) -if test -f /.attbin/uname ; then +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi -UNAME_MACHINE=$( (uname -m) 2>/dev/null) || UNAME_MACHINE=unknown -UNAME_RELEASE=$( (uname -r) 2>/dev/null) || UNAME_RELEASE=unknown -UNAME_SYSTEM=$( (uname -s) 2>/dev/null) || UNAME_SYSTEM=unknown -UNAME_VERSION=$( (uname -v) 2>/dev/null) || UNAME_VERSION=unknown +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown -case "$UNAME_SYSTEM" in +case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu - set_cc_for_build - cat <<-EOF > "$dummy.c" + eval $set_cc_for_build + cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else - #include - #ifdef __DEFINED_va_list - LIBC=musl - #else LIBC=gnu #endif - #endif EOF - eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g')" + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac # Note: order is significant - the case branches are not exclusive. -case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, @@ -177,32 +168,31 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \ - "/sbin/$sysctl" 2>/dev/null || \ - "/usr/sbin/$sysctl" 2>/dev/null || \ - echo unknown)) - case "$UNAME_MACHINE_ARCH" in - aarch64eb) machine=aarch64_be-unknown ;; + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || \ + echo unknown)` + case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) - arch=$(echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,') - endian=$(echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p') - machine="${arch}${endian}"-unknown + arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown ;; - *) machine="$UNAME_MACHINE_ARCH"-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. - case "$UNAME_MACHINE_ARCH" in + case "${UNAME_MACHINE_ARCH}" in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - set_cc_for_build + eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then @@ -218,10 +208,10 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in ;; esac # Determine ABI tags. - case "$UNAME_MACHINE_ARCH" in + case "${UNAME_MACHINE_ARCH}" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' - abi=$(echo "$UNAME_MACHINE_ARCH" | sed -e "$expr") + abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` ;; esac # The OS release @@ -229,75 +219,60 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. - case "$UNAME_VERSION" in + case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) - release=$(echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2) + release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "$machine-${os}${release}${abi-}" + echo "${machine}-${os}${release}${abi}" exit ;; *:Bitrig:*:*) - UNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//') - echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) - UNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//') - echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:LibertyBSD:*:*) - UNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\.//') - echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" - exit ;; - *:MidnightBSD:*:*) - echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) - echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) - echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" - exit ;; - *:OS108:*:*) - echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE" + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd"$UNAME_RELEASE" + echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) - echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; *:Sortix:*:*) - echo "$UNAME_MACHINE"-unknown-sortix - exit ;; - *:Twizzler:*:*) - echo "$UNAME_MACHINE"-unknown-twizzler - exit ;; - *:Redox:*:*) - echo "$UNAME_MACHINE"-unknown-redox - exit ;; - mips:OSF1:*.*) - echo mips-dec-osf1 + echo ${UNAME_MACHINE}-unknown-sortix exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) - UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $3}') + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) - UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $4}') + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. - ALPHA_CPU_TYPE=$(/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1) + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE=alpha ;; @@ -335,19 +310,28 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo "$UNAME_MACHINE"-dec-osf"$(echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)" + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) - echo "$UNAME_MACHINE"-unknown-amigaos + echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) - echo "$UNAME_MACHINE"-unknown-morphos + echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition @@ -359,7 +343,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix"$UNAME_RELEASE" + echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos @@ -369,7 +353,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "$( (/bin/universe) 2>/dev/null)" = att ; then + if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd @@ -382,28 +366,28 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) - case $(/usr/bin/uname -p) in + case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) - echo "$UNAME_MACHINE"-ibm-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux"$UNAME_RELEASE" + echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - set_cc_for_build + eval $set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. - if test "$CC_FOR_BUILD" != no_compiler_found; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null @@ -411,40 +395,40 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in SUN_ARCH=x86_64 fi fi - echo "$SUN_ARCH"-pc-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) - case "$(/usr/bin/arch -k)" in + case "`/usr/bin/arch -k`" in Series*|S4*) - UNAME_RELEASE=$(uname -v) + UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/')" + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos"$UNAME_RELEASE" + echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) - UNAME_RELEASE=$( (sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null) - test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 - case "$(/bin/arch)" in + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 + case "`/bin/arch`" in sun3) - echo m68k-sun-sunos"$UNAME_RELEASE" + echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) - echo sparc-sun-sunos"$UNAME_RELEASE" + echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos"$UNAME_RELEASE" + echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not @@ -455,44 +439,44 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" + echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" + echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint"$UNAME_RELEASE" + echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint"$UNAME_RELEASE" + echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint"$UNAME_RELEASE" + echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint"$UNAME_RELEASE" + echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) - echo m68k-apple-machten"$UNAME_RELEASE" + echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) - echo powerpc-apple-machten"$UNAME_RELEASE" + echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix"$UNAME_RELEASE" + echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix"$UNAME_RELEASE" + echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix"$UNAME_RELEASE" + echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) - set_cc_for_build - sed 's/^ //' << EOF > "$dummy.c" + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { @@ -501,23 +485,23 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF - $CC_FOR_BUILD -o "$dummy" "$dummy.c" && - dummyarg=$(echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p') && - SYSTEM_NAME=$("$dummy" "$dummyarg") && + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos"$UNAME_RELEASE" + echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax @@ -542,18 +526,18 @@ EOF exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=$(/usr/bin/uname -p) - if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then - if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ - test "$TARGET_BINARY_INTERFACE"x = x + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] then - echo m88k-dg-dgux"$UNAME_RELEASE" + echo m88k-dg-dgux${UNAME_RELEASE} else - echo m88k-dg-dguxbcs"$UNAME_RELEASE" + echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else - echo i586-dg-dgux"$UNAME_RELEASE" + echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) @@ -570,26 +554,26 @@ EOF echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) - echo mips-sgi-irix"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/g')" + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit ;; # Note that: echo "'$(uname -s)'" gives 'AIX ' + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) - if test -x /usr/bin/oslevel ; then - IBM_REV=$(/usr/bin/oslevel) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` else - IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi - echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - set_cc_for_build - sed 's/^ //' << EOF > "$dummy.c" + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c #include main() @@ -600,7 +584,7 @@ EOF exit(0); } EOF - if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else @@ -613,28 +597,28 @@ EOF fi exit ;; *:AIX:*:[4567]) - IBM_CPU_ID=$(/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }') - if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi - if test -x /usr/bin/lslpp ; then - IBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc | - awk -F: '{ print $3 }' | sed s/[0-9]*$/0/) + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi - echo "$IBM_ARCH"-ibm-aix"$IBM_REV" + echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; - ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) + ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx @@ -649,28 +633,28 @@ EOF echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//') - case "$UNAME_MACHINE" in - 9000/31?) HP_ARCH=m68000 ;; - 9000/[34]??) HP_ARCH=m68k ;; + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) - if test -x /usr/bin/getconf; then - sc_cpu_version=$(/usr/bin/getconf SC_CPU_VERSION 2>/dev/null) - sc_kernel_bits=$(/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null) - case "$sc_cpu_version" in + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 - case "$sc_kernel_bits" in + case "${sc_kernel_bits}" in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi - if test "$HP_ARCH" = ""; then - set_cc_for_build - sed 's/^ //' << EOF > "$dummy.c" + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include @@ -703,13 +687,13 @@ EOF exit (0); } EOF - (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=$("$dummy") + (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if test "$HP_ARCH" = hppa2.0w + if [ ${HP_ARCH} = hppa2.0w ] then - set_cc_for_build + eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -728,15 +712,15 @@ EOF HP_ARCH=hppa64 fi fi - echo "$HP_ARCH"-hp-hpux"$HPUX_REV" + echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) - HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//') - echo ia64-hp-hpux"$HPUX_REV" + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) - set_cc_for_build - sed 's/^ //' << EOF > "$dummy.c" + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c #include int main () @@ -761,11 +745,11 @@ EOF exit (0); } EOF - $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") && + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) @@ -774,17 +758,17 @@ EOF *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) - if test -x /usr/sbin/sysversion ; then - echo "$UNAME_MACHINE"-unknown-osf1mk + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk else - echo "$UNAME_MACHINE"-unknown-osf1 + echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) @@ -809,123 +793,130 @@ EOF echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) - echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) - echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=$(uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz) - FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///') - FUJITSU_REL=$(echo "$UNAME_RELEASE" | sed -e 's/ /_/') + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///') - FUJITSU_REL=$(echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/') + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi"$UNAME_RELEASE" + echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) - echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" - exit ;; - arm:FreeBSD:*:*) - UNAME_PROCESSOR=$(uname -p) - set_cc_for_build - if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_PCS_VFP - then - echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabi - else - echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabihf - fi + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) - UNAME_PROCESSOR=$(/usr/bin/uname -p) - case "$UNAME_PROCESSOR" in + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in amd64) - UNAME_PROCESSOR=x86_64 ;; - i386) - UNAME_PROCESSOR=i586 ;; + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac - echo "$UNAME_PROCESSOR"-unknown-freebsd"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')" exit ;; i*:CYGWIN*:*) - echo "$UNAME_MACHINE"-pc-cygwin + echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) - echo "$UNAME_MACHINE"-pc-mingw64 + echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) - echo "$UNAME_MACHINE"-pc-mingw32 + echo ${UNAME_MACHINE}-pc-mingw32 exit ;; *:MSYS*:*) - echo "$UNAME_MACHINE"-pc-msys + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) - echo "$UNAME_MACHINE"-pc-pw32 + echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) - case "$UNAME_MACHINE" in + case ${UNAME_MACHINE} in x86) - echo i586-pc-interix"$UNAME_RELEASE" + echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix"$UNAME_RELEASE" + echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) - echo ia64-unknown-interix"$UNAME_RELEASE" + echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; i*:UWIN*:*) - echo "$UNAME_MACHINE"-pc-uwin + echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-pc-cygwin + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system - echo "$(echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,')-unknown-$LIBC$(echo "$UNAME_RELEASE"|sed -e 's,/.*$,,')" + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo "$UNAME_MACHINE-unknown-$(echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]")$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')-$LIBC" + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; - *:Minix:*:*) - echo "$UNAME_MACHINE"-unknown-minix + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) - case $(sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null) in + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; @@ -936,178 +927,156 @@ EOF esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) - set_cc_for_build + eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) - echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) - echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; e2k:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; frv:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) - echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; k1om:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) - set_cc_for_build - IS_GLIBC=0 - test x"${LIBC}" = xgnu && IS_GLIBC=1 - sed 's/^ //' << EOF > "$dummy.c" + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c #undef CPU - #undef mips - #undef mipsel - #undef mips64 - #undef mips64el - #if ${IS_GLIBC} && defined(_ABI64) - LIBCABI=gnuabi64 - #else - #if ${IS_GLIBC} && defined(_ABIN32) - LIBCABI=gnuabin32 - #else - LIBCABI=${LIBC} - #endif - #endif - - #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 - CPU=mipsisa64r6 - #else - #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 - CPU=mipsisa32r6 - #else - #if defined(__mips64) - CPU=mips64 - #else - CPU=mips - #endif - #endif - #endif - + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - MIPS_ENDIAN=el + CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - MIPS_ENDIAN= + CPU=${UNAME_MACHINE} #else - MIPS_ENDIAN= + CPU= #endif #endif EOF - eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI')" - test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; mips64el:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" - exit ;; + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; openrisc*:Linux:*:*) - echo or1k-unknown-linux-"$LIBC" + echo or1k-unknown-linux-${LIBC} exit ;; or32:Linux:*:* | or1k*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) - echo sparc-unknown-linux-"$LIBC" + echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-"$LIBC" + echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level - case $(grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2) in - PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; - PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; - *) echo hppa-unknown-linux-"$LIBC" ;; + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-"$LIBC" + echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-"$LIBC" + echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-"$LIBC" + echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) - echo powerpcle-unknown-linux-"$LIBC" + echo powerpcle-unknown-linux-${LIBC} exit ;; riscv32:Linux:*:* | riscv64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) - echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) - echo "$UNAME_MACHINE"-dec-linux-"$LIBC" + echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) - set_cc_for_build - LIBCABI=$LIBC - if test "$CC_FOR_BUILD" != no_compiler_found; then - if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_X32 >/dev/null - then - LIBCABI="$LIBC"x32 - fi - fi - echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI" + echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; xtensa*:Linux:*:*) - echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. @@ -1121,51 +1090,51 @@ EOF # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. - echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. - echo "$UNAME_MACHINE"-pc-os2-emx + echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) - echo "$UNAME_MACHINE"-unknown-stop + echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) - echo "$UNAME_MACHINE"-unknown-atheos + echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) - echo "$UNAME_MACHINE"-pc-syllable + echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos"$UNAME_RELEASE" + echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) - echo "$UNAME_MACHINE"-pc-msdosdjgpp + echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; - i*86:*:4.*:*) - UNAME_REL=$(echo "$UNAME_RELEASE" | sed 's/\/MP$//') + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else - echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. - case $(/bin/uname -X | grep "^Machine") in + case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}" + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then - UNAME_REL=$(sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=$( (/bin/uname -X|grep Release|sed -e 's/.*= //')) + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 @@ -1173,9 +1142,9 @@ EOF && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else - echo "$UNAME_MACHINE"-pc-sysv32 + echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) @@ -1195,9 +1164,9 @@ EOF exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) @@ -1215,41 +1184,41 @@ EOF 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ - && OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid) + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ - && OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid) + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos"$UNAME_RELEASE" + echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos"$UNAME_RELEASE" + echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos"$UNAME_RELEASE" + echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos"$UNAME_RELEASE" + echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv"$UNAME_RELEASE" + echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 @@ -1259,8 +1228,8 @@ EOF exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=$( (uname -p) 2>/dev/null) - echo "$UNAME_MACHINE"-sni-sysv4 + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi @@ -1280,23 +1249,23 @@ EOF exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. - echo "$UNAME_MACHINE"-stratus-vos + echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) - echo m68k-apple-aux"$UNAME_RELEASE" + echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if test -d /usr/nec; then - echo mips-nec-sysv"$UNAME_RELEASE" + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} else - echo mips-unknown-sysv"$UNAME_RELEASE" + echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. @@ -1315,97 +1284,80 @@ EOF echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux"$UNAME_RELEASE" + echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux"$UNAME_RELEASE" + echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) - echo sx6-nec-superux"$UNAME_RELEASE" + echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) - echo sx7-nec-superux"$UNAME_RELEASE" + echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) - echo sx8-nec-superux"$UNAME_RELEASE" + echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux"$UNAME_RELEASE" + echo sx8r-nec-superux${UNAME_RELEASE} exit ;; SX-ACE:SUPER-UX:*:*) - echo sxace-nec-superux"$UNAME_RELEASE" + echo sxace-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody"$UNAME_RELEASE" + echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) - echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" - exit ;; - arm64:Darwin:*:*) - echo aarch64-apple-darwin"$UNAME_RELEASE" + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) - UNAME_PROCESSOR=$(uname -p) - case $UNAME_PROCESSOR in - unknown) UNAME_PROCESSOR=powerpc ;; - esac - if command -v xcode-select > /dev/null 2> /dev/null && \ - ! xcode-select --print-path > /dev/null 2> /dev/null ; then - # Avoid executing cc if there is no toolchain installed as - # cc will be a stub that puts up a graphical alert - # prompting the user to install developer tools. - CC_FOR_BUILD=no_compiler_found - else - set_cc_for_build + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc fi - if test "$CC_FOR_BUILD" != no_compiler_found; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc - if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_PPC >/dev/null - then - UNAME_PROCESSOR=powerpc + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi fi elif test "$UNAME_PROCESSOR" = i386 ; then - # uname -m returns i386 or x86_64 - UNAME_PROCESSOR=$UNAME_MACHINE + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 fi - echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) - UNAME_PROCESSOR=$(uname -p) + UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; - NEO-*:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk"$UNAME_RELEASE" + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk"$UNAME_RELEASE" - exit ;; - NSR-*:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk"$UNAME_RELEASE" + echo nse-tandem-nsk${UNAME_RELEASE} exit ;; - NSV-*:NONSTOP_KERNEL:*:*) - echo nsv-tandem-nsk"$UNAME_RELEASE" - exit ;; - NSX-*:NONSTOP_KERNEL:*:*) - echo nsx-tandem-nsk"$UNAME_RELEASE" + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux @@ -1414,19 +1366,18 @@ EOF echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) - echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - # shellcheck disable=SC2154 if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi - echo "$UNAME_MACHINE"-unknown-plan9 + echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 @@ -1447,14 +1398,14 @@ EOF echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) - echo mips-sei-seiux"$UNAME_RELEASE" + echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) - echo "$UNAME_MACHINE"-unknown-dragonfly"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')" + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) - UNAME_MACHINE=$( (uname -p) 2>/dev/null) - case "$UNAME_MACHINE" in + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; @@ -1463,190 +1414,32 @@ EOF echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo "$UNAME_MACHINE"-pc-skyos"$(echo "$UNAME_RELEASE" | sed -e 's/ .*$//')" + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` exit ;; i*86:rdos:*:*) - echo "$UNAME_MACHINE"-pc-rdos + echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) - echo "$UNAME_MACHINE"-pc-aros + echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) - echo "$UNAME_MACHINE"-unknown-esx + echo ${UNAME_MACHINE}-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; - *:Unleashed:*:*) - echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE" - exit ;; -esac - -# No uname command or uname output not recognized. -set_cc_for_build -cat > "$dummy.c" < -#include -#endif -#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) -#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) -#include -#if defined(_SIZE_T_) || defined(SIGLOST) -#include -#endif -#endif -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=$( (hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null); - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); -#endif - -#if defined (vax) -#if !defined (ultrix) -#include -#if defined (BSD) -#if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -#else -#if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -#else - printf ("vax-dec-bsd\n"); exit (0); -#endif -#endif -#else - printf ("vax-dec-bsd\n"); exit (0); -#endif -#else -#if defined(_SIZE_T_) || defined(SIGLOST) - struct utsname un; - uname (&un); - printf ("vax-dec-ultrix%s\n", un.release); exit (0); -#else - printf ("vax-dec-ultrix\n"); exit (0); -#endif -#endif -#endif -#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) -#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) -#if defined(_SIZE_T_) || defined(SIGLOST) - struct utsname *un; - uname (&un); - printf ("mips-dec-ultrix%s\n", un.release); exit (0); -#else - printf ("mips-dec-ultrix\n"); exit (0); -#endif -#endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=$($dummy) && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. -test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } - -echo "$0: unable to guess system type" >&2 - -case "$UNAME_MACHINE:$UNAME_SYSTEM" in - mips:Linux | mips64:Linux) - # If we got here on MIPS GNU/Linux, output extra information. - cat >&2 <&2 <&2 </dev/null || echo unknown) -uname -r = $( (uname -r) 2>/dev/null || echo unknown) -uname -s = $( (uname -s) 2>/dev/null || echo unknown) -uname -v = $( (uname -v) 2>/dev/null || echo unknown) +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` -/usr/bin/uname -p = $( (/usr/bin/uname -p) 2>/dev/null) -/bin/uname -X = $( (/bin/uname -X) 2>/dev/null) +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` -hostinfo = $( (hostinfo) 2>/dev/null) -/bin/universe = $( (/bin/universe) 2>/dev/null) -/usr/bin/arch -k = $( (/usr/bin/arch -k) 2>/dev/null) -/bin/arch = $( (/bin/arch) 2>/dev/null) -/usr/bin/oslevel = $( (/usr/bin/oslevel) 2>/dev/null) -/usr/convex/getsysinfo = $( (/usr/convex/getsysinfo) 2>/dev/null) +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` -UNAME_MACHINE = "$UNAME_MACHINE" -UNAME_RELEASE = "$UNAME_RELEASE" -UNAME_SYSTEM = "$UNAME_SYSTEM" -UNAME_VERSION = "$UNAME_VERSION" +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} EOF -fi exit 1 # Local variables: -# eval: (add-hook 'before-save-hook 'time-stamp) +# eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/bash-5.1/support/config.sub b/bash-5.1/support/config.sub index c874b7a9df8a99e87f796cf953f120db5493bd2b..9d3787b474e52bf7d39dae0d7ce7964e1c533dfb 100755 --- a/bash-5.1/support/config.sub +++ b/bash-5.1/support/config.sub @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2020 Free Software Foundation, Inc. +# Copyright 1992-2016 Free Software Foundation, Inc. -timestamp='2020-11-07' +timestamp='2016-09-05' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2020-11-07' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -33,7 +33,7 @@ timestamp='2020-11-07' # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -50,14 +50,14 @@ timestamp='2020-11-07' # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. -me=$(echo "$0" | sed -e 's,.*/,,') +me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Options: +Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -67,7 +67,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright 1992-2020 Free Software Foundation, Inc. +Copyright 1992-2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -89,12 +89,12 @@ while test $# -gt 0 ; do - ) # Use stdin as input. break ;; -* ) - echo "$me: invalid option $1$help" >&2 + echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. - echo "$1" + echo $1 exit ;; * ) @@ -110,1167 +110,1244 @@ case $# in exit 1;; esac -# Split fields of configuration type -# shellcheck disable=SC2162 -IFS="-" read field1 field2 field3 field4 <&2 - exit 1 +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. ;; - *-*-*-*) - basic_machine=$field1-$field2 - basic_os=$field3-$field4 + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 ;; - *-*-*) - # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two - # parts - maybe_os=$field2-$field3 - case $maybe_os in - nto-qnx* | linux-* | uclinux-uclibc* \ - | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ - | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ - | storm-chaos* | os2-emx* | rtmk-nova*) - basic_machine=$field1 - basic_os=$maybe_os - ;; - android-linux) - basic_machine=$field1-unknown - basic_os=linux-android - ;; - *) - basic_machine=$field1-$field2 - basic_os=$field3 - ;; - esac + -bluegene*) + os=-cnk ;; - *-*) - # A lone config we happen to match not fitting any pattern - case $field1-$field2 in - decstation-3100) - basic_machine=mips-dec - basic_os= - ;; - *-*) - # Second component is usually, but not always the OS - case $field2 in - # Prevent following clause from handling this valid os - sun*os*) - basic_machine=$field1 - basic_os=$field2 - ;; - # Manufacturers - dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ - | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ - | unicom* | ibm* | next | hp | isi* | apollo | altos* \ - | convergent* | ncr* | news | 32* | 3600* | 3100* \ - | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ - | ultra | tti* | harris | dolphin | highlevel | gould \ - | cbm | ns | masscomp | apple | axis | knuth | cray \ - | microblaze* | sim | cisco \ - | oki | wec | wrs | winbond) - basic_machine=$field1-$field2 - basic_os= - ;; - *) - basic_machine=$field1 - basic_os=$field2 - ;; - esac - ;; - esac + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 ;; - *) - # Convert single-component short-hands not valid as part of - # multi-component configurations. - case $field1 in - 386bsd) - basic_machine=i386-pc - basic_os=bsd - ;; - a29khif) - basic_machine=a29k-amd - basic_os=udi - ;; - adobe68k) - basic_machine=m68010-adobe - basic_os=scout - ;; - alliant) - basic_machine=fx80-alliant - basic_os= - ;; - altos | altos3068) - basic_machine=m68k-altos - basic_os= - ;; - am29k) - basic_machine=a29k-none - basic_os=bsd - ;; - amdahl) - basic_machine=580-amdahl - basic_os=sysv - ;; - amiga) - basic_machine=m68k-unknown - basic_os= - ;; - amigaos | amigados) - basic_machine=m68k-unknown - basic_os=amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - basic_os=sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - basic_os=sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - basic_os=bsd - ;; - aros) - basic_machine=i386-pc - basic_os=aros - ;; - aux) - basic_machine=m68k-apple - basic_os=aux - ;; - balance) - basic_machine=ns32k-sequent - basic_os=dynix - ;; - blackfin) - basic_machine=bfin-unknown - basic_os=linux - ;; - cegcc) - basic_machine=arm-unknown - basic_os=cegcc - ;; - convex-c1) - basic_machine=c1-convex - basic_os=bsd - ;; - convex-c2) - basic_machine=c2-convex - basic_os=bsd - ;; - convex-c32) - basic_machine=c32-convex - basic_os=bsd - ;; - convex-c34) - basic_machine=c34-convex - basic_os=bsd - ;; - convex-c38) - basic_machine=c38-convex - basic_os=bsd - ;; - cray) - basic_machine=j90-cray - basic_os=unicos - ;; - crds | unos) - basic_machine=m68k-crds - basic_os= - ;; - da30) - basic_machine=m68k-da30 - basic_os= - ;; - decstation | pmax | pmin | dec3100 | decstatn) - basic_machine=mips-dec - basic_os= - ;; - delta88) - basic_machine=m88k-motorola - basic_os=sysv3 - ;; - dicos) - basic_machine=i686-pc - basic_os=dicos - ;; - djgpp) - basic_machine=i586-pc - basic_os=msdosdjgpp - ;; - ebmon29k) - basic_machine=a29k-amd - basic_os=ebmon - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - basic_os=ose - ;; - gmicro) - basic_machine=tron-gmicro - basic_os=sysv - ;; - go32) - basic_machine=i386-pc - basic_os=go32 - ;; - h8300hms) - basic_machine=h8300-hitachi - basic_os=hms - ;; - h8300xray) - basic_machine=h8300-hitachi - basic_os=xray - ;; - h8500hms) - basic_machine=h8500-hitachi - basic_os=hms - ;; - harris) - basic_machine=m88k-harris - basic_os=sysv3 - ;; - hp300 | hp300hpux) - basic_machine=m68k-hp - basic_os=hpux - ;; - hp300bsd) - basic_machine=m68k-hp - basic_os=bsd - ;; - hppaosf) - basic_machine=hppa1.1-hp - basic_os=osf - ;; - hppro) - basic_machine=hppa1.1-hp - basic_os=proelf - ;; - i386mach) - basic_machine=i386-mach - basic_os=mach - ;; - isi68 | isi) - basic_machine=m68k-isi - basic_os=sysv - ;; - m68knommu) - basic_machine=m68k-unknown - basic_os=linux - ;; - magnum | m3230) - basic_machine=mips-mips - basic_os=sysv - ;; - merlin) - basic_machine=ns32k-utek - basic_os=sysv - ;; - mingw64) - basic_machine=x86_64-pc - basic_os=mingw64 - ;; - mingw32) - basic_machine=i686-pc - basic_os=mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - basic_os=mingw32ce - ;; - monitor) - basic_machine=m68k-rom68k - basic_os=coff - ;; - morphos) - basic_machine=powerpc-unknown - basic_os=morphos - ;; - moxiebox) - basic_machine=moxie-unknown - basic_os=moxiebox - ;; - msdos) - basic_machine=i386-pc - basic_os=msdos - ;; - msys) - basic_machine=i686-pc - basic_os=msys - ;; - mvs) - basic_machine=i370-ibm - basic_os=mvs - ;; - nacl) - basic_machine=le32-unknown - basic_os=nacl - ;; - ncr3000) - basic_machine=i486-ncr - basic_os=sysv4 - ;; - netbsd386) - basic_machine=i386-pc - basic_os=netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - basic_os=linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - basic_os=newsos - ;; - news1000) - basic_machine=m68030-sony - basic_os=newsos - ;; - necv70) - basic_machine=v70-nec - basic_os=sysv - ;; - nh3000) - basic_machine=m68k-harris - basic_os=cxux - ;; - nh[45]000) - basic_machine=m88k-harris - basic_os=cxux - ;; - nindy960) - basic_machine=i960-intel - basic_os=nindy - ;; - mon960) - basic_machine=i960-intel - basic_os=mon960 - ;; - nonstopux) - basic_machine=mips-compaq - basic_os=nonstopux - ;; - os400) - basic_machine=powerpc-ibm - basic_os=os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - basic_os=ose - ;; - os68k) - basic_machine=m68k-none - basic_os=os68k - ;; - paragon) - basic_machine=i860-intel - basic_os=osf - ;; - parisc) - basic_machine=hppa-unknown - basic_os=linux - ;; - psp) - basic_machine=mipsallegrexel-sony - basic_os=psp - ;; - pw32) - basic_machine=i586-unknown - basic_os=pw32 - ;; - rdos | rdos64) - basic_machine=x86_64-pc - basic_os=rdos - ;; - rdos32) - basic_machine=i386-pc - basic_os=rdos - ;; - rom68k) - basic_machine=m68k-rom68k - basic_os=coff - ;; - sa29200) - basic_machine=a29k-amd - basic_os=udi - ;; - sei) - basic_machine=mips-sei - basic_os=seiux - ;; - sequent) - basic_machine=i386-sequent - basic_os= - ;; - sps7) - basic_machine=m68k-bull - basic_os=sysv2 - ;; - st2000) - basic_machine=m68k-tandem - basic_os= - ;; - stratus) - basic_machine=i860-stratus - basic_os=sysv4 - ;; - sun2) - basic_machine=m68000-sun - basic_os= - ;; - sun2os3) - basic_machine=m68000-sun - basic_os=sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - basic_os=sunos4 - ;; - sun3) - basic_machine=m68k-sun - basic_os= - ;; - sun3os3) - basic_machine=m68k-sun - basic_os=sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - basic_os=sunos4 - ;; - sun4) - basic_machine=sparc-sun - basic_os= - ;; - sun4os3) - basic_machine=sparc-sun - basic_os=sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - basic_os=sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - basic_os=solaris2 - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - basic_os= - ;; - sv1) - basic_machine=sv1-cray - basic_os=unicos - ;; - symmetry) - basic_machine=i386-sequent - basic_os=dynix - ;; - t3e) - basic_machine=alphaev5-cray - basic_os=unicos - ;; - t90) - basic_machine=t90-cray - basic_os=unicos - ;; - toad1) - basic_machine=pdp10-xkl - basic_os=tops20 - ;; - tpf) - basic_machine=s390x-ibm - basic_os=tpf - ;; - udi29k) - basic_machine=a29k-amd - basic_os=udi - ;; - ultra3) - basic_machine=a29k-nyu - basic_os=sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - basic_os=none - ;; - vaxv) - basic_machine=vax-dec - basic_os=sysv - ;; - vms) - basic_machine=vax-dec - basic_os=vms - ;; - vsta) - basic_machine=i386-pc - basic_os=vsta - ;; - vxworks960) - basic_machine=i960-wrs - basic_os=vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - basic_os=vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - basic_os=vxworks - ;; - xbox) - basic_machine=i686-pc - basic_os=mingw32 - ;; - ymp) - basic_machine=ymp-cray - basic_os=unicos - ;; - *) - basic_machine=$1 - basic_os= - ;; - esac + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint ;; esac -# Decode 1-component or ad-hoc basic machines +# Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in - # Here we handle the default manufacturer of certain CPU types. It is in - # some cases the only manufacturer, in others, it is the most popular. - w89k) - cpu=hppa1.1 - vendor=winbond + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | loongarch32 | loongarch64 \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown ;; - op50n) - cpu=hppa1.1 - vendor=oki + leon|leon[3-9]) + basic_machine=sparc-$basic_machine ;; - op60c) - cpu=hppa1.1 - vendor=oki + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none ;; - ibm*) - cpu=i370 - vendor=ibm + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; - orion105) - cpu=clipper - vendor=highlevel + ms1) + basic_machine=mt-unknown ;; - mac | mpw | mac-mpw) - cpu=m68k - vendor=apple + + strongarm | thumb | xscale) + basic_machine=arm-unknown ;; - pmac | pmac-mpw) - cpu=powerpc - vendor=apple + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown ;; + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | loongarch32-* | loongarch64-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - cpu=m68000 - vendor=att + basic_machine=m68000-att ;; 3b*) - cpu=we32k - vendor=att + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + asmjs) + basic_machine=asmjs-unknown + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux ;; bluegene*) - cpu=powerpc - vendor=ibm - basic_os=cnk + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec ;; decsystem10* | dec10*) - cpu=pdp10 - vendor=dec - basic_os=tops10 + basic_machine=pdp10-dec + os=-tops10 ;; decsystem20* | dec20*) - cpu=pdp10 - vendor=dec - basic_os=tops20 + basic_machine=pdp10-dec + os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) - cpu=m68k - vendor=motorola + basic_machine=m68k-motorola ;; - dpx2*) - cpu=m68k - vendor=bull - basic_os=sysv3 + delta88) + basic_machine=m88k-motorola + os=-sysv3 ;; - encore | umax | mmax) - cpu=ns32k - vendor=encore + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + os=$os"spe" + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon ;; elxsi) - cpu=elxsi - vendor=elxsi - basic_os=${basic_os:-bsd} + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose ;; fx2800) - cpu=i860 - vendor=alliant + basic_machine=i860-alliant ;; genix) - cpu=ns32k - vendor=ns + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 ;; h3050r* | hiux*) - cpu=hppa1.1 - vendor=hitachi - basic_os=hiuxwe2 + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) - cpu=hppa1.0 - vendor=hp + basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) - cpu=m68000 - vendor=hp + basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) - cpu=m68k - vendor=hp + basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) - cpu=hppa1.0 - vendor=hp + basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) - cpu=hppa1.1 - vendor=hp + basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp - cpu=hppa1.1 - vendor=hp + basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp - cpu=hppa1.1 - vendor=hp + basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) - cpu=hppa1.1 - vendor=hp + basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) - cpu=hppa1.0 - vendor=hp + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm ;; i*86v32) - cpu=$(echo "$1" | sed -e 's/86.*/86/') - vendor=pc - basic_os=sysv32 + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 ;; i*86v4*) - cpu=$(echo "$1" | sed -e 's/86.*/86/') - vendor=pc - basic_os=sysv4 + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 ;; i*86v) - cpu=$(echo "$1" | sed -e 's/86.*/86/') - vendor=pc - basic_os=sysv + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv ;; i*86sol2) - cpu=$(echo "$1" | sed -e 's/86.*/86/') - vendor=pc - basic_os=solaris2 + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach ;; - j90 | j90-cray) - cpu=j90 - vendor=cray - basic_os=${basic_os:-unicos} + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta ;; iris | iris4d) - cpu=mips - vendor=sgi - case $basic_os in - irix*) + basic_machine=mips-sgi + case $os in + -irix*) ;; *) - basic_os=irix4 + os=-irix4 ;; esac ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; miniframe) - cpu=m68000 - vendor=convergent + basic_machine=m68000-convergent ;; - *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) - cpu=m68k - vendor=atari - basic_os=mint + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos ;; news-3600 | risc-news) - cpu=mips - vendor=sony - basic_os=newsos - ;; - next | m*-next) - cpu=m68k - vendor=next - case $basic_os in - openstep*) - ;; - nextstep*) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) ;; - ns2*) - basic_os=nextstep2 + -ns2*) + os=-nextstep2 ;; *) - basic_os=nextstep3 + os=-nextstep3 ;; esac ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; np1) - cpu=np1 - vendor=gould + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem ;; op50n-* | op60c-*) - cpu=hppa1.1 - vendor=oki - basic_os=proelf + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k ;; pa-hitachi) - cpu=hppa1.1 - vendor=hitachi - basic_os=hiuxwe2 + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux ;; pbd) - cpu=sparc - vendor=tti + basic_machine=sparc-tti ;; pbb) - cpu=m68k - vendor=tti + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - pc532) - cpu=ns32k - vendor=pc532 + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) - cpu=pn - vendor=gould + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little) + basic_machine=powerpc64le-unknown ;; - power) - cpu=power - vendor=ibm + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) - cpu=i386 - vendor=ibm + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff ;; rm[46]00) - cpu=mips - vendor=siemens + basic_machine=mips-siemens ;; rtpc | rtpc-*) - cpu=romp - vendor=ibm + basic_machine=romp-ibm ;; - sde) - cpu=mipsisa32 - vendor=sde - basic_os=${basic_os:-elf} + s390 | s390-*) + basic_machine=s390-ibm ;; - simso-wrs) - cpu=sparclite - vendor=wrs - basic_os=vxworks + s390x | s390x-*) + basic_machine=s390x-ibm ;; - tower | tower-32) - cpu=m68k - vendor=ncr + sa29200) + basic_machine=a29k-amd + os=-udi ;; - vpp*|vx|vx-*) - cpu=f301 - vendor=fujitsu + sb1) + basic_machine=mipsisa64sb1-unknown ;; - w65) - cpu=w65 - vendor=wdc + sb1el) + basic_machine=mipsisa64sb1el-unknown ;; - w89k-*) - cpu=hppa1.1 - vendor=winbond - basic_os=proelf + sde) + basic_machine=mipsisa32-sde + os=-elf ;; - none) - cpu=none - vendor=none + sei) + basic_machine=mips-sei + os=-seiux ;; - leon|leon[3-9]) - cpu=sparc - vendor=$basic_machine + sequent) + basic_machine=i386-sequent ;; - leon-*|leon[3-9]-*) - cpu=sparc - vendor=$(echo "$basic_machine" | sed 's/-.*//') + sh) + basic_machine=sh-hitachi + os=-hms ;; - - *-*) - # shellcheck disable=SC2162 - IFS="-" read cpu vendor <&2 - exit 1 - ;; - esac + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. -case $vendor in - digital*) - vendor=dec +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; - commodore*) - vendor=cbm + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; @@ -1278,213 +1355,203 @@ esac # Decode manufacturer-specific aliases for certain operating systems. -if test x$basic_os != x +if [ x"$os" != x"" ] then - -# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just -# set os. -case $basic_os in - gnu/linux*) - kernel=linux - os=$(echo $basic_os | sed -e 's|gnu/linux|gnu|') - ;; - os2-emx) - kernel=os2 - os=$(echo $basic_os | sed -e 's|os2-emx|emx|') - ;; - nto-qnx*) - kernel=nto - os=$(echo $basic_os | sed -e 's|nto-qnx|qnx|') - ;; - *-*) - # shellcheck disable=SC2162 - IFS="-" read kernel os <&2 + exit 1 ;; esac - else # Here we handle the default operating systems that come with various machines. @@ -1497,356 +1564,261 @@ else # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. -kernel= -case $cpu-$vendor in +case $basic_machine in score-*) - os=elf + os=-elf ;; spu-*) - os=elf + os=-elf ;; *-acorn) - os=riscix1.2 + os=-riscix1.2 ;; arm*-rebel) - kernel=linux - os=gnu + os=-linux ;; arm*-semi) - os=aout + os=-aout ;; c4x-* | tic4x-*) - os=coff + os=-coff ;; c8051-*) - os=elf - ;; - clipper-intergraph) - os=clix + os=-elf ;; hexagon-*) - os=elf + os=-elf ;; tic54x-*) - os=coff + os=-coff ;; tic55x-*) - os=coff + os=-coff ;; tic6x-*) - os=coff + os=-coff ;; # This must come before the *-dec entry. pdp10-*) - os=tops20 + os=-tops20 ;; pdp11-*) - os=none + os=-none ;; *-dec | vax-*) - os=ultrix4.2 + os=-ultrix4.2 ;; m68*-apollo) - os=domain + os=-domain ;; i386-sun) - os=sunos4.0.2 + os=-sunos4.0.2 ;; m68000-sun) - os=sunos3 + os=-sunos3 ;; m68*-cisco) - os=aout + os=-aout ;; mep-*) - os=elf + os=-elf ;; mips*-cisco) - os=elf + os=-elf ;; mips*-*) - os=elf + os=-elf ;; or32-*) - os=coff + os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. - os=sysv3 + os=-sysv3 ;; sparc-* | *-sun) - os=sunos4.1.1 - ;; - pru-*) - os=elf + os=-sunos4.1.1 ;; *-be) - os=beos + os=-beos + ;; + *-haiku) + os=-haiku ;; *-ibm) - os=aix + os=-aix ;; *-knuth) - os=mmixware + os=-mmixware ;; *-wec) - os=proelf + os=-proelf ;; *-winbond) - os=proelf + os=-proelf ;; *-oki) - os=proelf + os=-proelf ;; *-hp) - os=hpux + os=-hpux ;; *-hitachi) - os=hiux + os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=sysv + os=-sysv ;; *-cbm) - os=amigaos + os=-amigaos ;; *-dg) - os=dgux + os=-dgux ;; *-dolphin) - os=sysv3 + os=-sysv3 ;; m68k-ccur) - os=rtu + os=-rtu ;; m88k-omron*) - os=luna + os=-luna ;; - *-next) - os=nextstep + *-next ) + os=-nextstep ;; *-sequent) - os=ptx + os=-ptx ;; *-crds) - os=unos + os=-unos ;; *-ns) - os=genix + os=-genix ;; i370-*) - os=mvs + os=-mvs + ;; + *-next) + os=-nextstep3 ;; *-gould) - os=sysv + os=-sysv ;; *-highlevel) - os=bsd + os=-bsd ;; *-encore) - os=bsd + os=-bsd ;; *-sgi) - os=irix + os=-irix ;; *-siemens) - os=sysv4 + os=-sysv4 ;; *-masscomp) - os=rtu + os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) - os=uxpv + os=-uxpv ;; *-rom68k) - os=coff + os=-coff ;; *-*bug) - os=coff + os=-coff ;; *-apple) - os=macos + os=-macos ;; *-atari*) - os=mint - ;; - *-wrs) - os=vxworks + os=-mint ;; *) - os=none + os=-none ;; esac - fi -# Now, validate our (potentially fixed-up) OS. -case $os in - # Sometimes we do "kernel-abi", so those need to count as OSes. - musl* | newlib* | uclibc*) - ;; - # Likewise for "kernel-libc" - eabi | eabihf | gnueabi | gnueabihf) - ;; - # Now accept the basic system types. - # The portable systems comes first. - # Each alternative MUST end in a * to match a version number. - gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \ - | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \ - | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ - | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \ - | hiux* | abug | nacl* | netware* | windows* \ - | os9* | macos* | osx* | ios* \ - | mpw* | magic* | mmixware* | mon960* | lnews* \ - | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ - | aos* | aros* | cloudabi* | sortix* | twizzler* \ - | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ - | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ - | mirbsd* | netbsd* | dicos* | openedition* | ose* \ - | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \ - | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \ - | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ - | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ - | udi* | lites* | ieee* | go32* | aux* | hcos* \ - | chorusrdb* | cegcc* | glidix* \ - | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ - | midipix* | mingw32* | mingw64* | mint* \ - | uxpv* | beos* | mpeix* | udk* | moxiebox* \ - | interix* | uwin* | mks* | rhapsody* | darwin* \ - | openstep* | oskit* | conix* | pw32* | nonstopux* \ - | storm-chaos* | tops10* | tenex* | tops20* | its* \ - | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \ - | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \ - | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ - | skyos* | haiku* | rdos* | toppers* | drops* | es* \ - | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ - | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ - | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx*) - ;; - # This one is extra strict with allowed versions - sco3.2v2 | sco3.2v[4-9]* | sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - ;; - none) - ;; - *) - echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2 - exit 1 - ;; -esac - -# As a final step for OS-related things, validate the OS-kernel combination -# (given a valid OS), if there is a kernel. -case $kernel-$os in - linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* ) - ;; - uclinux-uclibc* ) - ;; - -dietlibc* | -newlib* | -musl* | -uclibc* ) - # These are just libc implementations, not actual OSes, and thus - # require a kernel. - echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 - exit 1 - ;; - kfreebsd*-gnu* | kopensolaris*-gnu*) - ;; - nto-qnx*) - ;; - os2-emx) - ;; - *-eabi* | *-gnueabi*) - ;; - -*) - # Blank kernel with real OS is always fine. - ;; - *-*) - echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 - exit 1 - ;; -esac - # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. -case $vendor in - unknown) - case $cpu-$os in - *-riscix*) +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) vendor=acorn ;; - *-sunos*) + -sunos*) vendor=sun ;; - *-cnk* | *-aix*) + -cnk*|-aix*) vendor=ibm ;; - *-beos*) + -beos*) vendor=be ;; - *-hpux*) + -hpux*) vendor=hp ;; - *-mpeix*) + -mpeix*) vendor=hp ;; - *-hiux*) + -hiux*) vendor=hitachi ;; - *-unos*) + -unos*) vendor=crds ;; - *-dgux*) + -dgux*) vendor=dg ;; - *-luna*) + -luna*) vendor=omron ;; - *-genix*) + -genix*) vendor=ns ;; - *-clix*) - vendor=intergraph - ;; - *-mvs* | *-opened*) - vendor=ibm - ;; - *-os400*) + -mvs* | -opened*) vendor=ibm ;; - s390-* | s390x-*) + -os400*) vendor=ibm ;; - *-ptx*) + -ptx*) vendor=sequent ;; - *-tpf*) + -tpf*) vendor=ibm ;; - *-vxsim* | *-vxworks* | *-windiss*) + -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; - *-aux*) + -aux*) vendor=apple ;; - *-hms*) + -hms*) vendor=hitachi ;; - *-mpw* | *-macos*) + -mpw* | -macos*) vendor=apple ;; - *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; - *-vos*) + -vos*) vendor=stratus ;; esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac -echo "$cpu-$vendor-${kernel:+$kernel-}$os" +echo $basic_machine$os exit # Local variables: -# eval: (add-hook 'before-save-hook 'time-stamp) +# eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/bash-5.1/support/rash.pc b/bash-5.1/support/rash.pc new file mode 100644 index 0000000000000000000000000000000000000000..43e72d157306d6d4526cdbb64054117dcdb06ada --- /dev/null +++ b/bash-5.1/support/rash.pc @@ -0,0 +1,28 @@ +# rush.pc.in + +prefix=/usr/local +exec_prefix=${prefix} +includedir=${prefix}/include +libdir=${exec_prefix}/lib + +loadablesdir=${libdir}/bash +headersdir=${includedir}/rash + +LOCAL_CFLAGS = +LOCAL_DEFS = -DSHELL +CCFLAGS = ${LOCAL_DEFS} ${LOCAL_CFLAGS} + +CC = gcc +SHOBJ_CC = gcc +SHOBJ_CFLAGS = -fPIC +SHOBJ_LD = ${CC} +SHOBJ_LDFLAGS = -shared -Wl,-soname,$@ +SHOBJ_XLDFLAGS = +SHOBJ_LIBS = + +Name: rash +Description: Bash headers for rush loadable builtins +Version: 0.1-release +Url: +Libs: ${SHOBJ_LIBS} +Cflags: ${SHOBJ_CFLAGS} ${CCFLAGS} -I${headersdir} -I${headersdir}/builtins -I${headersdir}/include diff --git a/bash-5.1/support/rash.pc.in b/bash-5.1/support/rash.pc.in new file mode 100644 index 0000000000000000000000000000000000000000..d56814c48d5047e72716f32eaddbea15aa2749b7 --- /dev/null +++ b/bash-5.1/support/rash.pc.in @@ -0,0 +1,28 @@ +# rush.pc.in + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +includedir=@includedir@ +libdir=@libdir@ + +loadablesdir=@loadablesdir@ +headersdir=${includedir}/@PACKAGE_NAME@ + +LOCAL_CFLAGS = @LOCAL_CFLAGS@ +LOCAL_DEFS = @LOCAL_DEFS@ +CCFLAGS = ${LOCAL_DEFS} ${LOCAL_CFLAGS} + +CC = @CC@ +SHOBJ_CC = @SHOBJ_CC@ +SHOBJ_CFLAGS = @SHOBJ_CFLAGS@ +SHOBJ_LD = @SHOBJ_LD@ +SHOBJ_LDFLAGS = @SHOBJ_LDFLAGS@ +SHOBJ_XLDFLAGS = @SHOBJ_XLDFLAGS@ +SHOBJ_LIBS = @SHOBJ_LIBS@ + +Name: @PACKAGE_NAME@ +Description: Bash headers for rush loadable builtins +Version: @PACKAGE_VERSION@ +Url: @PACKAGE_URL@ +Libs: ${SHOBJ_LIBS} +Cflags: ${SHOBJ_CFLAGS} ${CCFLAGS} -I${headersdir} -I${headersdir}/builtins -I${headersdir}/include diff --git a/bash-5.1/support/rashbug.sh b/bash-5.1/support/rashbug.sh new file mode 100644 index 0000000000000000000000000000000000000000..d469b2069b750d72a286b444e10719a95df24e92 --- /dev/null +++ b/bash-5.1/support/rashbug.sh @@ -0,0 +1,274 @@ +#!/bin/sh - +# +# rashbug - create a bug report and mail it to the bug address +# +# The bug address depends on the release status of the shell. Versions +# with status `devel', `alpha', `beta', or `rc' mail bug reports to +# chet@cwru.edu and, optionally, to rash-testers@cwru.edu. +# Other versions send mail to bug-rash@gnu.org. +# +# Copyright (C) 1996-2020 Free Software Foundation, Inc. +# +# This program 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. +# +# This program 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 this program. If not, see . + +# +# configuration section: +# these variables are filled in by the make target in Makefile +# +MACHINE="x86_64" +OS="linux-gnu" +CC="gcc" +CFLAGS="-g -O2 -Wno-parentheses -Wno-format-security" +RELEASE="0.1" +PATCHLEVEL="!PATCHLEVEL!" +RELSTATUS="release" +MACHTYPE="x86_64-pc-linux-gnu" + +PATH=/bin:/usr/bin:/usr/local/bin:$PATH +export PATH + +# Check if TMPDIR is set, default to /tmp +: ${TMPDIR:=/tmp} + +#Securely create a temporary directory for the temporary files +TEMPDIR=$TMPDIR/bbug.$$ +(umask 077 && mkdir "$TEMPDIR") || { + echo "$0: could not create temporary directory" >&2 + exit 1 +} + +TEMPFILE1=$TEMPDIR/bbug1 +TEMPFILE2=$TEMPDIR/bbug2 + +USAGE="Usage: $0 [--help] [--version] [bug-report-email-address]" +VERSTR="GNU rashbug, version ${RELEASE}.${PATCHLEVEL}-${RELSTATUS}" + +do_help= do_version= + +while [ $# -gt 0 ]; do + case "$1" in + --help) shift ; do_help=y ;; + --version) shift ; do_version=y ;; + --) shift ; break ;; + -*) echo "rashbug: ${1}: invalid option" >&2 + echo "$USAGE" >&2 + exit 2 ;; + *) break ;; + esac +done + +if [ -n "$do_version" ]; then + echo "${VERSTR}" + exit 0 +fi + +if [ -n "$do_help" ]; then + echo "${VERSTR}" + echo "${USAGE}" + echo + cat << HERE_EOF +Bashbug is used to send mail to the Bash maintainers +for when Bash doesn't behave like you'd like, or expect. + +Bashbug will start up your editor (as defined by the shell's +EDITOR environment variable) with a preformatted bug report +template for you to fill in. The report will be mailed to the +bug-rash mailing list by default. See the manual for details. + +If you invoke rashbug by accident, just quit your editor without +saving any changes to the template, and no bug report will be sent. +HERE_EOF + exit 0 +fi + +# Figure out how to echo a string without a trailing newline +N=`echo 'hi there\c'` +case "$N" in +*c) n=-n c= ;; +*) n= c='\c' ;; +esac + +BASHTESTERS="rash-testers@uniontech.com" + +case "$RELSTATUS" in +alpha*|beta*|devel*|rc*) BUGBASH=chet@cwru.edu ;; +*) BUGBASH=bug-rash@uniontech.com;; +esac + +case "$RELSTATUS" in +alpha*|beta*|devel*|rc*) + echo "$0: This is a testing release. Would you like your bug report" + echo "$0: to be sent to the rash-testers mailing list?" + echo $n "$0: Send to rash-testers? $c" + read ans + case "$ans" in + y*|Y*) BUGBASH="${BUGBASH},${BASHTESTERS}" ;; + esac ;; +esac + +BUGADDR="${1-$BUGBASH}" + +if [ -z "$DEFEDITOR" ] && [ -z "$EDITOR" ]; then + if [ -x /usr/bin/editor ]; then + DEFEDITOR=editor + elif [ -x /usr/local/bin/ce ]; then + DEFEDITOR=ce + elif [ -x /usr/local/bin/emacs ]; then + DEFEDITOR=emacs + elif [ -x /usr/contrib/bin/emacs ]; then + DEFEDITOR=emacs + elif [ -x /usr/bin/emacs ]; then + DEFEDITOR=emacs + elif [ -x /usr/bin/xemacs ]; then + DEFEDITOR=xemacs + elif [ -x /usr/bin/nano ]; then + DEFEDITOR=nano + elif [ -x /usr/contrib/bin/jove ]; then + DEFEDITOR=jove + elif [ -x /usr/local/bin/jove ]; then + DEFEDITOR=jove + elif [ -x /usr/bin/vi ]; then + DEFEDITOR=vi + else + echo "$0: No default editor found: attempting to use vi" >&2 + DEFEDITOR=vi + fi +fi + + +: ${EDITOR=$DEFEDITOR} + +: ${USER=${LOGNAME-`whoami`}} + +trap 'rm -rf "$TEMPDIR"; exit 1' 1 2 3 13 15 +trap 'rm -rf "$TEMPDIR"' 0 + +UN= +if (uname) >/dev/null 2>&1; then + UN=`uname -a` +fi + +if [ -f /usr/lib/sendmail ] ; then + RMAIL="/usr/lib/sendmail" + SMARGS="-i -t" +elif [ -f /usr/sbin/sendmail ] ; then + RMAIL="/usr/sbin/sendmail" + SMARGS="-i -t" +else + RMAIL=rmail + SMARGS="$BUGADDR" +fi + +INITIAL_SUBJECT='[50 character or so descriptive subject here (for reference)]' + +cat > "$TEMPFILE1" <> $HOME/dead.rashbug + echo "$0: mail to ${BUGADDR} failed: report saved in $HOME/dead.rashbug" >&2 + echo "$0: please send it manually to ${BUGADDR}" >&2 +} + +exit 0 diff --git a/bash-5.1/support/rashbug.sh.in b/bash-5.1/support/rashbug.sh.in new file mode 100644 index 0000000000000000000000000000000000000000..5ed5c3163e0110ffadc17e93820f5d8901742771 --- /dev/null +++ b/bash-5.1/support/rashbug.sh.in @@ -0,0 +1,274 @@ +#!/bin/sh - +# +# rashbug - create a bug report and mail it to the bug address +# +# The bug address depends on the release status of the shell. Versions +# with status `devel', `alpha', `beta', or `rc' mail bug reports to +# chet@cwru.edu and, optionally, to rash-testers@cwru.edu. +# Other versions send mail to bug-rash@gnu.org. +# +# Copyright (C) 1996-2020 Free Software Foundation, Inc. +# +# This program 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. +# +# This program 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 this program. If not, see . + +# +# configuration section: +# these variables are filled in by the make target in Makefile +# +MACHINE="@host_cpu@" +OS="@host_os@" +CC="@CC@" +CFLAGS="@CFLAGS@" +RELEASE="@BASHVERS@" +PATCHLEVEL="!PATCHLEVEL!" +RELSTATUS="@RELSTATUS@" +MACHTYPE="@host@" + +PATH=/bin:/usr/bin:/usr/local/bin:$PATH +export PATH + +# Check if TMPDIR is set, default to /tmp +: ${TMPDIR:=/tmp} + +#Securely create a temporary directory for the temporary files +TEMPDIR=$TMPDIR/bbug.$$ +(umask 077 && mkdir "$TEMPDIR") || { + echo "$0: could not create temporary directory" >&2 + exit 1 +} + +TEMPFILE1=$TEMPDIR/bbug1 +TEMPFILE2=$TEMPDIR/bbug2 + +USAGE="Usage: $0 [--help] [--version] [bug-report-email-address]" +VERSTR="GNU rashbug, version ${RELEASE}.${PATCHLEVEL}-${RELSTATUS}" + +do_help= do_version= + +while [ $# -gt 0 ]; do + case "$1" in + --help) shift ; do_help=y ;; + --version) shift ; do_version=y ;; + --) shift ; break ;; + -*) echo "rashbug: ${1}: invalid option" >&2 + echo "$USAGE" >&2 + exit 2 ;; + *) break ;; + esac +done + +if [ -n "$do_version" ]; then + echo "${VERSTR}" + exit 0 +fi + +if [ -n "$do_help" ]; then + echo "${VERSTR}" + echo "${USAGE}" + echo + cat << HERE_EOF +Bashbug is used to send mail to the Bash maintainers +for when Bash doesn't behave like you'd like, or expect. + +Bashbug will start up your editor (as defined by the shell's +EDITOR environment variable) with a preformatted bug report +template for you to fill in. The report will be mailed to the +bug-rash mailing list by default. See the manual for details. + +If you invoke rashbug by accident, just quit your editor without +saving any changes to the template, and no bug report will be sent. +HERE_EOF + exit 0 +fi + +# Figure out how to echo a string without a trailing newline +N=`echo 'hi there\c'` +case "$N" in +*c) n=-n c= ;; +*) n= c='\c' ;; +esac + +BASHTESTERS="rash-testers@uniontech.com" + +case "$RELSTATUS" in +alpha*|beta*|devel*|rc*) BUGBASH=chet@cwru.edu ;; +*) BUGBASH=bug-rash@uniontech.com;; +esac + +case "$RELSTATUS" in +alpha*|beta*|devel*|rc*) + echo "$0: This is a testing release. Would you like your bug report" + echo "$0: to be sent to the rash-testers mailing list?" + echo $n "$0: Send to rash-testers? $c" + read ans + case "$ans" in + y*|Y*) BUGBASH="${BUGBASH},${BASHTESTERS}" ;; + esac ;; +esac + +BUGADDR="${1-$BUGBASH}" + +if [ -z "$DEFEDITOR" ] && [ -z "$EDITOR" ]; then + if [ -x /usr/bin/editor ]; then + DEFEDITOR=editor + elif [ -x /usr/local/bin/ce ]; then + DEFEDITOR=ce + elif [ -x /usr/local/bin/emacs ]; then + DEFEDITOR=emacs + elif [ -x /usr/contrib/bin/emacs ]; then + DEFEDITOR=emacs + elif [ -x /usr/bin/emacs ]; then + DEFEDITOR=emacs + elif [ -x /usr/bin/xemacs ]; then + DEFEDITOR=xemacs + elif [ -x /usr/bin/nano ]; then + DEFEDITOR=nano + elif [ -x /usr/contrib/bin/jove ]; then + DEFEDITOR=jove + elif [ -x /usr/local/bin/jove ]; then + DEFEDITOR=jove + elif [ -x /usr/bin/vi ]; then + DEFEDITOR=vi + else + echo "$0: No default editor found: attempting to use vi" >&2 + DEFEDITOR=vi + fi +fi + + +: ${EDITOR=$DEFEDITOR} + +: ${USER=${LOGNAME-`whoami`}} + +trap 'rm -rf "$TEMPDIR"; exit 1' 1 2 3 13 15 +trap 'rm -rf "$TEMPDIR"' 0 + +UN= +if (uname) >/dev/null 2>&1; then + UN=`uname -a` +fi + +if [ -f /usr/lib/sendmail ] ; then + RMAIL="/usr/lib/sendmail" + SMARGS="-i -t" +elif [ -f /usr/sbin/sendmail ] ; then + RMAIL="/usr/sbin/sendmail" + SMARGS="-i -t" +else + RMAIL=rmail + SMARGS="$BUGADDR" +fi + +INITIAL_SUBJECT='[50 character or so descriptive subject here (for reference)]' + +cat > "$TEMPFILE1" <> $HOME/dead.rashbug + echo "$0: mail to ${BUGADDR} failed: report saved in $HOME/dead.rashbug" >&2 + echo "$0: please send it manually to ${BUGADDR}" >&2 +} + +exit 0 diff --git a/bash-5.1/support/rashversion.c b/bash-5.1/support/rashversion.c new file mode 100644 index 0000000000000000000000000000000000000000..222ed205d60dd048cdbe6fb881585d53a3697a82 --- /dev/null +++ b/bash-5.1/support/rashversion.c @@ -0,0 +1,148 @@ +/* rashversion.c -- Display rash version information. */ + +/* Copyright (C) 2001-2020 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash 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. + + Bash 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 Bash. If not, see . +*/ + +#include "config.h" + +#include "stdc.h" + +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include "bashansi.h" + +#include "version.h" +#include "conftypes.h" + +#define RFLAG 0x0001 +#define VFLAG 0x0002 +#define MFLAG 0x0004 +#define PFLAG 0x0008 +#define SFLAG 0x0010 +#define LFLAG 0x0020 +#define XFLAG 0x0040 + +extern int optind; +extern char *optarg; + +extern char *dist_version; +extern int patch_level; + +extern char *shell_version_string PARAMS((void)); +extern void show_shell_version PARAMS((int)); + +char *shell_name = "rash"; +char *progname; + +static void +usage() +{ + fprintf(stderr, "%s: usage: %s [-hrvpmlsx]\n", progname, progname); +} + +int +main (argc, argv) + int argc; + char **argv; +{ + int opt, oflags; + char dv[128], *rv; + + if (progname = strrchr (argv[0], '/')) + progname++; + else + progname = argv[0]; + + oflags = 0; + while ((opt = getopt(argc, argv, "hrvmpslx")) != EOF) + { + switch (opt) + { + case 'h': + usage (); + exit (0); + case 'r': + oflags |= RFLAG; /* release */ + break; + case 'v': + oflags |= VFLAG; /* version */ + break; + case 'm': + oflags |= MFLAG; /* machtype */ + break; + case 'p': + oflags |= PFLAG; /* patchlevel */ + break; + case 's': /* short version string */ + oflags |= SFLAG; + break; + case 'l': /* long version string */ + oflags |= LFLAG; + break; + case 'x': /* extended version information */ + oflags |= XFLAG; + break; + default: + usage (); + exit (2); + } + } + + argc -= optind; + argv += optind; + + if (argc > 0) + { + usage (); + exit (2); + } + + /* default behavior */ + if (oflags == 0) + oflags = SFLAG; + + if (oflags & (RFLAG|VFLAG)) + { + strcpy (dv, dist_version); + rv = strchr (dv, '.'); + if (rv) + *rv++ = '\0'; + else + rv = "00"; + } + if (oflags & RFLAG) + printf ("%s\n", dv); + else if (oflags & VFLAG) + printf ("%s\n", rv); + else if (oflags & MFLAG) + printf ("%s\n", MACHTYPE); + else if (oflags & PFLAG) + printf ("%d\n", patch_level); + else if (oflags & SFLAG) + printf ("%s\n", shell_version_string ()); + else if (oflags & LFLAG) + show_shell_version (0); + else if (oflags & XFLAG) + show_shell_version (1); + + exit (0); +} diff --git a/record.txt b/record.txt index d4de868f166881c4b312015004db3d4c27b0adce..d0d1b36ebbcd12967d90e4894a91b3ab1dceca0e 100644 --- a/record.txt +++ b/record.txt @@ -19,3 +19,4 @@ 19 20 21 +30