C语言自定义Shell错误提示修复求助:缺失Shell名与行号
C语言简易Shell错误提示格式修复方案
问题根源
- Shell名称获取逻辑错误:通过
getppid()结合ps命令获取父进程名称的方式不可靠——管道执行场景下,自定义Shell的子进程父进程可能不是Shell本身,且fgets会将换行符读入shell变量,导致输出时出现多余换行或格式错乱。 - 行号错误:使用
__LINE__获取的是代码文件中的行号,并非用户输入命令的逻辑行号(如管道输入时应为1)。 - 参数传递缺失:
execute_command函数无法获取正确的Shell标识和命令行号,导致输出缺失关键信息。
修复步骤与代码实现
1. 调整函数参数
修改execute_command的参数列表,增加Shell名称和命令行号的传入;同时更新头文件中的函数原型。
2. 维护命令行号
在main函数中添加行号计数器,交互式模式下每次输入递增,管道模式下固定为1。
3. 移除不可靠的进程名称获取逻辑
直接使用程序启动时的argv[0]作为Shell名称,无需依赖外部命令。
修改后的完整代码:
#define SHELL_H #define MAX_NUM_ARGS 10 /* Standard Headers */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/wait.h> /* Function Prototypes */ void parse_command(char *command, char *args[]); void execute_command(char *shell_name, int line_num, char *args[]); #endif /* #ifndef SHELL_H */ void execute_command(char *shell_name, int line_num, char *args[]) { int status; pid_t pid; pid = fork(); if (pid == 0) { execvp(args[0], args); // 输出符合要求的错误格式 fprintf(stderr, "%s: %d: %s: not found\n", shell_name, line_num, args[0]); exit(127); // 遵循Shell惯例,命令未找到时返回127 } else if (pid > 0) { wait(&status); } else { perror("Error: failed to fork"); exit(1); } } void parse_command(char *command, char *args[]) { char *token = strtok(command, " "); int i = 0; while (token != NULL && i < MAX_NUM_ARGS) { args[i] = token; token = strtok(NULL, " "); i++; } args[i] = NULL; } int main(int argc, char *argv[]) { char *command = NULL; size_t n = 0; char *args[MAX_NUM_ARGS + 1]; int line_num = 1; // 命令行号计数器 /* 检查输入是否来自管道 */ if (!isatty(STDIN_FILENO)) { if (getline(&command, &n, stdin) == -1) { perror("Error: getline() failed"); return (1); } command[strcspn(command, "\n")] = '\0'; parse_command(command, args); execute_command(argv[0], line_num, args); free(command); return (0); } /* 交互式模式 */ while (1) { printf(">>> "); if (getline(&command, &n, stdin) == -1) { perror("Error: getline() failed"); break; } command[strcspn(command, "\n")] = '\0'; parse_command(command, args); if (strcmp(args[0], "exit") == 0) { break; } execute_command(argv[0], line_num, args); line_num++; // 交互式模式下递增行号 } free(command); return (0); }
关键说明
- 使用
argv[0]作为Shell名称:这是程序启动时的真实名称(如./hsh),完全符合需求。 - 命令行号维护:管道输入时行号固定为1,交互式模式下每次输入后递增,与标准Shell行为一致。
- 错误输出到
stderr:标准Shell的错误信息会输出到标准错误流,而非标准输出,这里用fprintf(stderr, ...)修正这一点。 - 返回码127:遵循Unix Shell惯例,命令未找到时返回127,增强兼容性。
内容的提问来源于stack exchange,提问作者Akintola Oluwaseyi Alex
相关产品推荐
相关产品推荐

