void devnull_stdout() { int i, j; if (fmode & 01000) { printf("\"fd y\" ignored (mode +v)\r\n"); } /* if (fmode & 01000) */ else { /* Only switch output to /dev/null if not there already. */ /* If o/p is to /dev/null, orig_stdout has original fd */ if (orig_stdout == -1) { do orig_stdout = dup(1); while (orig_stdout == -1 && errno == EINTR); if (orig_stdout == -1) { fprintf(stderr, "\r\n%s. (dup(1))\r\n", strerror(errno)); refrsh(NULL); return; } /* if (orig_stdout == -1) */ do i = close(1); while (i == -1 && errno == EINTR); do i = open("/dev/null", O_RDWR); while (i == -1 && errno == EINTR); if (i == -1) { fprintf(stderr, "\r\n%s. /dev/null (open)\r\n", strerror(errno)); refrsh(NULL); restore_stdout(); return; } /* if (i == -1) */ /* Verify we opened fd 1. Attempt to rectify if not */ if (i != 1) { do j = dup2(i, 1); while (j == -1 && errno == EINTR); if (j == -1) { fprintf(stderr, "\r\n%s. (dup2(%d, 1))\r\n", strerror(errno), i); do j = close(i); while (j == -1 && errno == EINTR); restore_stdout(); return; } /* if (j == -1) */ } /* if (i != 1) */ } /* if (orig_stdout == -1) */ stdinfo[stdidx].nullstdout = true; } /* if (fmode & 01000) else */ } /* devnull_stdout() */
void define_test(void(*callback)(ZRuntimeContext *), struct zco_context_t *ctx, const char *title) { trace("======================\n"); trace("%s:\n", title); /* redirect stdout to a pipe */ int the_pipe[2]; pipe(the_pipe); int original_stdout = write_stdout_to_pipe(the_pipe[1]); /* run test in native mode */ ZRuntimeContext *runtime_context = z_runtime_context_new(ctx, NULL); z_runtime_context_set_target(runtime_context, 0); callback(runtime_context); /* restore stdout as we don't need any more data that is sent to it */ restore_stdout(original_stdout); /* read data that is sent to the pipe and close the pipe */ ZString *out = read_from_fd(ctx, NULL, the_pipe[0]); close(the_pipe[0]); z_object_unref(Z_OBJECT(runtime_context)); /* run test in JS mode and verify its output */ runtime_context = z_runtime_context_new(ctx, NULL); z_runtime_context_set_target(runtime_context, 1); callback(runtime_context); verify_output(runtime_context, out); z_object_unref(Z_OBJECT(runtime_context)); /* print out the expected string */ char *print_out = z_string_get_cstring(out, Z_STRING_ENCODING_UTF8); fputs(print_out, stdout); free(print_out); z_object_unref(Z_OBJECT(out)); trace("\n"); }
void verify_output(ZRuntimeContext *runtime_context, ZString *expected_value) { pid_t pid; /* create a full-duplex pipe */ int pipe_to_child[2]; int pipe_to_parent[2]; pipe(pipe_to_child); pipe(pipe_to_parent); switch (pid = fork()) { case -1: perror("fork"); abort(); break; case 0: /* child */ close(pipe_to_child[1]); close(pipe_to_parent[0]); dup2(pipe_to_child[0], 0); dup2(pipe_to_parent[1], 1); execlp("node", "node", NULL); break; } close(pipe_to_child[0]); close(pipe_to_parent[1]); if (is_verbose) { /* print out the script if we are in verbose mode */ z_runtime_context_run(runtime_context); } /* backup the original stdout and redirect stdout to 'pipe_to_child' */ int original_stdout = write_stdout_to_pipe(pipe_to_child[1]); /* push the script to stdout, which is the pipe to the child */ z_runtime_context_run(runtime_context); z_runtime_context_clear(runtime_context); /* restore the original stdout */ restore_stdout(original_stdout); /* wait for child to exit */ siginfo_t info; memset (&info, 0, sizeof(info)); waitid (P_PID, pid, &info, WEXITED | WUNTRACED | WNOHANG | WNOWAIT); /* read all data from pipe_to_parent[0] and store it in a string */ ZString *out = read_from_fd(CTX_FROM_OBJECT(runtime_context), ALLOCATOR_FROM_OBJECT(runtime_context), pipe_to_parent[0]); close(pipe_to_parent[0]); /* compare the output matches the expected value */ if (z_string_compare(out, NULL, expected_value, NULL, 0, -1)) { char *s; s = z_string_get_cstring(expected_value, Z_STRING_ENCODING_UTF8); printf("Expected value: \n'%s'\n", s); free(s); s = z_string_get_cstring(out, Z_STRING_ENCODING_UTF8); printf("\nActual value: \n'%s'\n", s); free(s); abort(); } z_object_unref(Z_OBJECT(out)); }
/* * Executes a builtin shell command * * Parameters: * argc - number of arguments in the command * argv - the user's command * mods - special modifiers for the command * * Returns: * 0 on success, -1 otherwise */ int execute_builtin(size_t argc, char *const argv[], const mods_t *const mods) { // Handle file redirection int fd; if (mods->out_file != NULL && (fd = redirect_stdout(mods->out_file)) == -1) return -1; // HELP if (strcmp(argv[0], "help") == 0) { print_help(); } // EXIT else if (strcmp(argv[0], "exit") == 0) { return -1; } // PID else if (strcmp(argv[0], "pid") == 0) { printf("[%d] shell\n", getpid()); } // PPID else if (strcmp(argv[0], "ppid") == 0) { printf("[%d] parent\n", getppid()); } // PWD else if (strcmp(argv[0], "pwd") == 0) { char dir[PATH_MAX]; if (getcwd(dir, sizeof(dir)) == NULL) perror("ERROR: getcwd():"); else printf("%s\n", dir); } // CD else if (strcmp(argv[0], "cd") == 0) { int err = 0; if (argc > 1) err = chdir(argv[1]); else err = chdir(getenv("HOME")); if (err != 0) perror("ERROR: chdir():"); } // GET else if (strcmp(argv[0], "get") == 0) { if (argc > 1) { char *var = getenv(argv[1]); if (var == NULL) printf("ERROR: Unknown variable '%s'.\n", argv[1]); else printf("%s\n", var); } else printf("Usage: get <var>.\n"); } // SET else if (strcmp(argv[0], "set") == 0) { if (argc == 1) printf("Usage: set <var> <value>\n"); else if (argc == 2 && unsetenv(argv[1]) == -1) perror("ERROR: unsetenv():"); else if (setenv(argv[1], argv[2], 1) == -1) perror("ERROR: setenv():"); } // Revert file redirection if (mods->out_file != NULL && restore_stdout(fd) == -1) return -1; return 0; }