You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言自定义Shell错误提示修复求助:缺失Shell名与行号

C语言简易Shell错误提示格式修复方案

问题根源

  1. Shell名称获取逻辑错误:通过getppid()结合ps命令获取父进程名称的方式不可靠——管道执行场景下,自定义Shell的子进程父进程可能不是Shell本身,且fgets会将换行符读入shell变量,导致输出时出现多余换行或格式错乱。
  2. 行号错误:使用__LINE__获取的是代码文件中的行号,并非用户输入命令的逻辑行号(如管道输入时应为1)。
  3. 参数传递缺失: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 00:17:01