/* A simple simulated shell can be executed with an input redirection (or an output redirection or pipeline) command. The program is imperfect and can basically use */# include <stdio. h> # include <stdlib. h> # include <ctype. h> # include <string. h> # include <unistd. h> # include <fcntl. h> # include <sys/types. h> # include <sys/Wait. h> # include <dirent. h> char Command [100];/* storage command */Char argv [50] [50];/* storage command */INT count; /* Number of commands after decomposition * // * Enumeration type, indicating general commands in turn, with output redirection commands, with input redirection commands, with pipeline commands */Enum specify {normal, out_redirect, in_redirect, pipe};/* function declaration */I NT analysis_command (); int do_command (); int find_command (char * command);/* main function */INT main () {While (1) {printf ("$ my_shell: "); command [0] = 0; gets (command); If (! Analysis_command () continue; do_command ();} return 0;}/* Resolution command */INT analysis_command () {char * s = command; int I = 0, j = 0, state = 0; strcat (command, "");/* separate commands with spaces and store them in argv */while (* s) {Switch (state) {Case 0: If (! Isspace (* s) State = 1; else s ++; break; Case 1: If (isspace (* s )) {argv [I] [J] = '\ 0'; I ++; j = 0; State = 0;} else {argv [I] [J] = * s; j ++;} s ++; break;} COUNT = I; If (COUNT = 0) return 0; If (strcmp (argv [0], "logout ") = 0 | strcmp (argv [0], "exit") = 0) Exit (0);/* determine whether the command exists */If (! Find_command (argv [0]) {puts ("error: Can't find command"); Return 0 ;}return 1 ;}/ * Execute Command */INT do_command () {int I, j; char * file; char * Arg [50]; char * arg2 [50]; int f = 0, back_run = 0; int FD, PID, fd2, pid2; Enum specify type = normal; for (I = 0; I <count; I ++) {Arg [I] = argv [I];} arg [I] = NULL; If (strcmp (ARG [count-1], "<") = 0 | strcmp (ARG [count-1], "> ") = 0 | strcmp (ARG [count-1], "|") = 0) {printf ("error: Command error \ n "); Return 0 ;}for (I = 0; I <count; I ++) {If (strcmp (ARG [I], "<") = 0) {f ++; file = Arg [I + 1]; arg [I] = NULL; type = in_redirect;} else if (strcmp (ARG [I], "> ") = 0) {f ++; file = Arg [I + 1]; arg [I] = NULL; type = out_redirect;} else if (strcmp (ARG [I], "|") = 0) {f ++; type = pipe; arg [I] = NULL; For (j = I + 1; j <count; j ++) {arg2 [j-i-1] = Arg [J];} arg2 [j-i-1] = NULL; If (! Find_command (arg2 [0]) {printf ("error: Can't find command \ n"); Return 0 ;}}} if (strcmp (ARG [count-1], "&") = 0) {back_run = 1; arg [count-1] = NULL;} If (F> 1) {printf ("error: Don't identify the command"); Return 0;} pid = fork (); If (PID <0) {perror ("fork error "); exit (0);} else if (pid = 0) {/* in the sub-process */switch (type) {Case normal: execvp (ARG [0], arg); break; Case in_redirect: FD = open (file, o_rdonly); dup2 (FD, stdin_fileno); exe CVP (ARG [0], ARG); break; Case out_redirect: FD = open (file, o_wronly | o_creat | o_trunc, 0666); dup2 (FD, stdout_fileno ); execvp (ARG [0], ARG); break; Case pipe: pid2 = fork (); If (pid2 = 0) {fd2 = open ("tempfile ", o_wronly | o_creat | o_trunc, 0600); dup2 (fd2, stdout_fileno); execvp (ARG [0], ARG);} else {waitpid (pid2, null, 0 ); FD = open ("tempfile", o_rdonly); dup2 (FD, stdin_fileno); execvp (arg2 [0], arg2);} break ;}} else {If (! Back_run) waitpid (PID, null, 0);} return 1;}/* SEARCH Command */INT find_command (char * command) {dir * D; struct dirent * PTR; char temp [100]; char * dir;/* Get the environment variable */char * Path = getenv ("path");/* separate the environment variables, check the directories in sequence to see if the command exists */strcpy (temp, PATH); Dir = strtok (temp, ":"); While (DIR) {d = opendir (DIR); While (PTR = readdir (D ))! = NULL) if (strcmp (PTR-> d_name, command) = 0) {closedir (d); return 1;} closedir (d); Dir = strtok (null, ":");} return 0 ;}