int (*builtin_func[])(char **) = {&lsh_cd, &lsh_help, &lsh_exit};
intlsh_cd(char **args) { if (args[1] == NULL) { fprintf(stderr, "lsh: expected argument to \"cd\"\n"); } else { if (chdir(args[1]) != 0) { perror("lsh"); } } return1; }
intlsh_help(char **args) { printf("LSH (Based on Stephen Brennan's LSH)\n"); printf("Type program names and arguments, and hit enter.\n"); printf("The following are built in:\n");
for (unsigned i = 0; i < sizeof(builtin_str) / sizeof(char *); i++) { printf(" %s\n", builtin_str[i]); }
printf("Use the man command for information on other programs.\n"); return1; }
intlsh_exit(char **args) { return0; }
外部命令的处理逻辑最复杂,也是 shell 最核心的部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// external commands pid_t pid = fork(); if (pid == 0) { // Child process if (execvp(args[0], args) == -1) { perror("lsh"); } exit(EXIT_FAILURE); } elseif (pid < 0) { // Error forking perror("lsh"); } else { // Parent process int status; do { waitpid(pid, &status, WUNTRACED); } while (!WIFEXITED(status) && !WIFSIGNALED(status)); }
int (*builtin_func[])(char **) = {&lsh_cd, &lsh_help, &lsh_exit};
intlsh_cd(char **args) { if (args[1] == NULL) { fprintf(stderr, "lsh: expected argument to \"cd\"\n"); } else { if (chdir(args[1]) != 0) { perror("lsh"); } } return1; }
intlsh_help(char **args) { printf("LSH (Based on Stephen Brennan's LSH)\n"); printf("Type program names and arguments, and hit enter.\n"); printf("The following are built in:\n");
for (unsigned i = 0; i < sizeof(builtin_str) / sizeof(char *); i++) { printf(" %s\n", builtin_str[i]); }
printf("Use the man command for information on other programs.\n"); return1; }
intlsh_exit(char **args) { return0; }
intlsh_execute(char **args) { // An empty command was entered. if (args[0] == NULL) { return1; }
// builtin commands for (unsigned i = 0; i < sizeof(builtin_str) / sizeof(char *); i++) { if (strcmp(args[0], builtin_str[i]) == 0) { return (*builtin_func[i])(args); } }
// external commands pid_t pid = fork(); if (pid == 0) { // Child process if (execvp(args[0], args) == -1) { perror("lsh"); } exit(EXIT_FAILURE); } elseif (pid < 0) { // Error forking perror("lsh"); } else { // Parent process int status; do { waitpid(pid, &status, WUNTRACED); } while (!WIFEXITED(status) && !WIFSIGNALED(status)); }
return1; }
char *lsh_read_line(void) { char *line = NULL; size_t bufsize = 0; // have getline allocate a buffer for us if (getline(&line, &bufsize, stdin) == -1) { if (feof(stdin)) { exit(EXIT_SUCCESS); // We received an EOF } else { perror("lsh: getline\n"); exit(EXIT_FAILURE); } } return line; }
char **lsh_split_line(char *line) { int bufsize = 64; int position = 0; char **tokens = malloc(bufsize * sizeof(char *));
if (!tokens) { fprintf(stderr, "lsh: allocation error\n"); exit(EXIT_FAILURE); }