* clarification questions ** exit default status when no value is specified for exit builting, it uses what the value of $? _would_ be if you had to support, which means exit status of most recently terminated command. 1. exec fails a. errno is ENOENT, command not found (exit status 127) b. any thing is 126 2. WIFSIGNALED(status) -- 128+WTERMSIG(status) 3. WEXITSTATUS(status) ** shell environment *** diff between process env and shell env process environment is pointed to be char **environ shell environment is in varlist (initialized from environ) *** how export works in varlist is_env field indicates if the variable is exported all variables imported from proc env have is_env==1 VLexport sets is_env==1 VLtable2environ creates an environ vector execute sets environ = VLtable2environ so that execvp can access it in dash, set shows all variables (exported or not) the command printenv is used to see what's exported ** "missing fi" case in test script syntax errors are all detected based on the status of controlflow.c when you get to EOF on the primary input, if the state in controlflow.c is not NORMAL, it's an error * three recursion cases ** execute an external script as a child command (fork + execvp) ./exscript <- executes as a child process # more commands <- execute in the parent process ** sourcing a script (the dot command) (no fork and no execvp) . ./exscript <- open the file and execute it's commands in the parent # more commands <- return here in parent after EOF on exscript ** use the exec builtin (no fork but yes execvp) exec ./exscript <- call execvp on the script # more commands <- not executed unless execvp fails * review how pipes work int pipe_fd[2]; if ( pipe(pipe_fd) < 0 ) // error case ** for command substitution IPC ... 1. call pipe 2. fork 3. close the fd you don't need a. child -- close(pipe_fd[0]) b. parent -- close(pipe_fd[1]) 4. child uses close+dup or dup2 to make pipe_fd[1] stdout close(1); dup(pipe_fd[1]); close(pipe_fd[1]); close(pipe_fd[0]); dup2(pipe_fd[1], 1); close(pipe_fd[1]); close(pipe_fd[0]); 5. parent process reads from the child close(pipe_fd[1]); // read from pipe_fd[0] until EOF replacing '\n' with ' ' // might be useful to call fdopen on pipe_fd[0] to get a FILE* close(pipe_fd[0]);