0

我正在为课堂写一个小shell。我呼吁execvp使用非内置命令。在开发它的一段时间内,它以 -1 正常返回,一切正常。但是,现在我可以在 shell 中输入任何内容,它会启动一个进程,该进程会立即以状态 11 终止(SIGSEGV,分段错误)。

Meta:我曾尝试将其缩减为 SSCCE,但没有成功:当我删除 周围的所有内容时execvp,它可以正常运行。我很乐意提供完整的源代码,但目前超过 750 行似乎过多。

这是调用 execvp 的函数。

void eval(char *cmdline)
{
char **argv = malloc(MAXLINE);
int bg = parseline(cmdline,argv);

if (argv[0] == 0)
{
    free(argv);
    return;
}
if(builtin_cmd(argv) == 0)
{
    pid_t pid;
    sigset_t set, oset;

    /* set mask */
    sigemptyset(&set);
    sigaddset(&set, SIGCHLD);
    sigprocmask(SIG_SETMASK, &set, &oset);

    /* proceed to fork */
    if ((pid = Fork()) == 0)
    {
        app_debug("execvp <%s>", argv[0]);
        setpgid(0,0);
        sigprocmask(SIG_UNBLOCK, &set, &oset);
        execvp(argv[0], argv);
        app_notify("%s command not found.", errno, argv[0]);
        exit(0);
    } else if (pid == -1) {
        app_notify("fork failed");
        return;
    } else {
        addjob(jobs, pid, bg + 1, cmdline);
        sigprocmask(SIG_UNBLOCK, &set, &oset);
        if (bg == 0) {
            app_debug("[%d] (%d) Waiting for %s", pid2jid(pid), pid, cmdline);
            waitfg(pid);
        } else {
            app_notify("[%d] (%d) %s", pid2jid(pid), pid, cmdline);
        }
    }
}
free(argv);
return;
}

这是解析线。

int parseline(const char *cmdline, char **argv)
{
static char array[MAXLINE]; /* holds local copy of command line */
char *buf = array;          /* ptr that traverses command line */
char *delim;                /* points to first space delimiter */
int argc;                   /* number of args */
int bg;                     /* background job? */

strcpy(buf, cmdline);
buf[strlen(buf)-1] = ' ';  /* replace trailing '\n' with space */
while (*buf && (*buf == ' ')) /* ignore leading spaces */
buf++;

/* Build the argv list */
argc = 0;
if (*buf == '\'') {
buf++;
delim = strchr(buf, '\'');
}
else {
delim = strchr(buf, ' ');
}

while (delim) {
argv[argc++] = buf;
*delim = '\0';
buf = delim + 1;
while (*buf && (*buf == ' ')) /* ignore spaces */
       buf++;

if (*buf == '\'') {
    buf++;
    delim = strchr(buf, '\'');
}
else {
    delim = strchr(buf, ' ');
}
}
argv[argc] = NULL;

if (argc == 0)  /* ignore blank line */
return 1;

/* should the job run in the background? */
if ((bg = (*argv[argc-1] == '&')) != 0) {
argv[--argc] = NULL;
}
return bg;
}
4

1 回答 1

0

在 execvp 之后,app_notify("%s command not found.", errno, argv[0]);seg 立即出现故障。它本质上包装了一个 printf 并且在引用的字符串之后应该只有一个参数,因为只有一个替换。

调试的关键是发现set follow-fork-mode childgdb。

感谢您的帮助,吉姆等人。

于 2012-10-08T22:48:11.760 回答