• R/O
  • SSH
  • HTTPS

yash: 提交


Commit MetaInfo

修訂4126 (tree)
時間2020-11-02 23:08:17
作者magicant

Log Message

Implement exec_one_command & exec_simple_command

The new two functions replace the exec_process function.

Change Summary

差異

--- yash/branches/exec/exec.c (revision 4125)
+++ yash/branches/exec/exec.c (revision 4126)
@@ -158,10 +158,9 @@
158158 __attribute__((nonnull));
159159 static void exec_one_command(command_T *c, bool finally_exit)
160160 __attribute__((nonnull));
161+static void exec_simple_command(const command_T *c, bool finally_exit)
162+ __attribute__((nonnull));
161163 // TODO Reconsider order of functions around here
162-static pid_t exec_process(
163- command_T *restrict c, exec_T type, pipeinfo_T *restrict pi, pid_t pgid)
164- __attribute__((nonnull));
165164 static inline void connect_pipes(pipeinfo_T *pi)
166165 __attribute__((nonnull));
167166 static void become_child(sigtype_T sigtype);
@@ -613,6 +612,8 @@
613612 exec_one_command: /* child process */
614613 free(job);
615614 connect_pipes(&pipe);
615+ if (type == E_ASYNC && pipe.pi_fromprevfd < 0)
616+ maybe_redirect_stdin_to_devnull();
616617 exec_one_command(c, true);
617618 assert(false);
618619 } else if (pid >= 0) {
@@ -803,6 +804,7 @@
803804 xerror(errno, Ngt("cannot open a pipe"));
804805 }
805806
807+/* Executes the command. */
806808 void exec_one_command(command_T *c, bool finally_exit)
807809 {
808810 /* prevent the command data from being freed in case the command is part of
@@ -809,76 +811,51 @@
809811 * a function that is unset during execution. */
810812 c = comsdup(c);
811813
814+ update_lineno(c->c_lineno);
815+
812816 if (c->c_type == CT_SIMPLE) {
817+ exec_simple_command(c, finally_exit);
813818 } else {
819+ savefd_T *savefd;
820+ if (open_redirections(c->c_redirs, &savefd)) {
821+ exec_nonsimple_command(c, finally_exit && savefd == NULL);
822+ undo_redirections(savefd);
823+ } else {
824+ laststatus = Exit_REDIRERR;
825+ apply_errexit_errreturn(NULL);
826+ }
814827 }
815- // TODO implement exec_one_command
816828
817829 comsfree(c);
830+
831+ if (finally_exit)
832+ exit_shell();
818833 }
819834
820-/* Executes the command.
821- * If job control is active, the child process's process group ID is set to
822- * `pgid'. If `pgid' is 0, the child process's process ID is used as the process
823- * group ID.
824- * If the child process forked successfully, its process ID is returned.
825- * If the command was executed without forking, `laststatus' is set to the exit
826- * status of the command and 0 is returned.
827- * if `type' is E_SELF, this function never returns. */
828-pid_t exec_process(
829- command_T *restrict c, exec_T type, pipeinfo_T *restrict pi, pid_t pgid)
835+/* Executes the simple command. */
836+void exec_simple_command(const command_T *c, bool finally_exit)
830837 {
831- bool finally_exit; /* never return? */
838+ lastcmdsubstatus = Exit_SUCCESS;
839+
840+ /* expand the command words */
832841 int argc;
833- void **argv = NULL;
834- char *argv0 = NULL;
835- pid_t cpid = 0;
842+ void **argv;
843+ if (!expand_line(c->c_words, &argc, &argv)) {
844+ laststatus = Exit_EXPERROR;
845+ goto done;
846+ }
847+ if (is_interrupted())
848+ goto done1;
836849
837- update_lineno(c->c_lineno);
838-
839- finally_exit = (type == E_SELF);
840- if (finally_exit) {
841- if (c->c_type == CT_SUBSHELL)
842- /* No command follows this subshell command, so we can execute the
843- * subshell directly in this process. */
844- become_child(0);
850+ char *argv0; // a multi-byte version of argv[0]
851+ if (argc == 0) {
852+ argv0 = NULL;
845853 } else {
846- /* fork first if `type' is E_ASYNC, the command type is subshell,
847- * or there is a pipe. */
848- if (type == E_ASYNC || c->c_type == CT_SUBSHELL
849- || pi->pi_fromprevfd >= 0 || pi->pi_tonextfds[PIPE_OUT] >= 0) {
850- sigtype_T sigtype = (type == E_ASYNC) ? t_quitint : 0;
851- cpid = fork_and_reset(pgid, type == E_NORMAL, sigtype);
852- if (cpid != 0)
853- goto done;
854- finally_exit = true;
855- }
854+ argv0 = malloc_wcstombs(argv[0]);
855+ if (argv0 == NULL)
856+ argv0 = xstrdup("");
856857 }
857858
858- lastcmdsubstatus = Exit_SUCCESS;
859-
860- /* connect pipes and close leftovers */
861- connect_pipes(pi);
862-
863- if (c->c_type == CT_SIMPLE) {
864- if (!expand_line(c->c_words, &argc, &argv)) {
865- laststatus = Exit_EXPERROR;
866- goto done;
867- }
868- if (is_interrupted()) {
869- plfree(argv, free);
870- goto done;
871- }
872- if (argc == 0) {
873- argv0 = NULL;
874- } else {
875- argv0 = malloc_wcstombs(argv[0]);
876- if (argv0 == NULL)
877- argv0 = xstrdup("");
878- }
879- }
880- /* `argc' and `argv' are used only for `CT_SIMPLE'. */
881-
882859 /* open redirections */
883860 savefd_T *savefd;
884861 if (!open_redirections(c->c_redirs, &savefd)) {
@@ -885,24 +862,12 @@
885862 /* On redirection error, the command is not executed. */
886863 laststatus = Exit_REDIRERR;
887864 apply_errexit_errreturn(NULL);
888- if (posixly_correct && !is_interactive_now && c->c_type == CT_SIMPLE &&
865+ if (posixly_correct && !is_interactive_now &&
889866 argc > 0 && is_special_builtin(argv0))
890867 finally_exit = true;
891868 goto done2;
892869 }
893-
894- if (type == E_ASYNC && pi->pi_fromprevfd < 0)
895- maybe_redirect_stdin_to_devnull();
896870
897- if (c->c_type != CT_SIMPLE) {
898- if (c->c_type == CT_SUBSHELL) {
899- clear_savefd(savefd);
900- savefd = NULL;
901- }
902- exec_nonsimple_command(c, finally_exit && savefd == NULL);
903- goto done1;
904- }
905-
906871 last_assign = c->c_assigns;
907872 if (argc == 0) {
908873 /* if there is no command word, just perform assignments */
@@ -917,14 +882,13 @@
917882 goto done2;
918883 }
919884
885+ /* check if the command is a special built-in or function */
920886 commandinfo_T cmdinfo;
921- bool temp;
922-
923- /* check if the command is a special built-in or a function and determine
924- * whether we have to open a temporary environment. */
925887 search_command(argv0, argv[0], &cmdinfo, SCT_BUILTIN | SCT_FUNCTION);
926888 special_builtin_executed = (cmdinfo.type == CT_SPECIALBUILTIN);
927- temp = c->c_assigns != NULL && !special_builtin_executed;
889+
890+ /* open a temporary variable environment */
891+ bool temp = c->c_assigns != NULL && !special_builtin_executed;
928892 if (temp)
929893 open_new_environment(true);
930894
@@ -953,29 +917,10 @@
953917 }
954918 }
955919
956- /* create a child process to execute the external command */
957- if (cmdinfo.type == CT_EXTERNALPROGRAM && !finally_exit) {
958- assert(type == E_NORMAL);
959- cpid = fork_and_reset(pgid, true, t_leave);
960- if (cpid != 0)
961- goto done3;
962- finally_exit = true;
963- }
964-
965920 /* execute! */
966- bool finally_exit2;
967- switch (cmdinfo.type) {
968- case CT_EXTERNALPROGRAM:
969- finally_exit2 = true;
970- break;
971- case CT_FUNCTION:
972- finally_exit2 = (finally_exit && /* !temp && */ savefd == NULL);
973- break;
974- default:
975- finally_exit2 = false;
976- break;
977- }
978- invoke_simple_command(&cmdinfo, argc, argv0, argv, finally_exit2);
921+ invoke_simple_command(&cmdinfo, argc, argv0, argv,
922+ finally_exit && /* !temp && */ savefd == NULL);
923+ // TODO refactor invoke_simple_command
979924
980925 /* Redirections are not undone after a successful "exec" command:
981926 * remove the saved data of file descriptors. */
@@ -985,22 +930,18 @@
985930 }
986931 exec_builtin_executed = false;
987932
933+ /* cleanup */
988934 done3:
989935 if (temp)
990936 close_current_environment();
991937 done2:
992- if (c->c_type == CT_SIMPLE)
993- plfree(argv, free), free(argv0);
938+ undo_redirections(savefd);
939+ free(argv0);
994940 done1:
995- undo_redirections(savefd);
941+ plfree(argv, free);
996942 done:
997- if (cpid < 0) {
998- laststatus = Exit_NOEXEC;
999- cpid = 0;
1000- }
1001943 if (finally_exit)
1002944 exit_shell();
1003- return cpid;
1004945 }
1005946
1006947 /* Connects the pipe(s) and closes the pipes left. */
@@ -1234,6 +1175,7 @@
12341175 */
12351176 void exec_nonsimple_command(command_T *c, bool finally_exit)
12361177 {
1178+ // TODO fork or become_child(0) if CT_GROUP
12371179 switch (c->c_type) {
12381180 case CT_SIMPLE:
12391181 assert(false);
Show on old repository browser