0

我正在尝试编写以下 C 赋值:一个程序 my-if 接受两个参数,它将运行第一个参数,然后在成功时运行第二个参数。这是我想出的:

#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>

char ** split(char * s) {
  char ** words = malloc(sizeof(char *));
  int i = 0;
  char * word = strtok(strdup(s), " ");
  while (word) {
    words = realloc(words, sizeof(char *) * (i + 1));
    words[i] = malloc(strlen(word) + 1);
    strcpy(words[i++], word);
    word = strtok(NULL, " ");
  }
  words[i] = NULL;
  return words;
}


int main(int argc, char * argv[]) {
  char ** argv1 = split(argv[1]);
  char ** argv2 = split(argv[2]);

  int t = fork();
  if (t == -1)
    exit(1);
  else if (t == 0) 
    execvp(argv1[0], argv1);
  else {
    int status;
    wait(&status);
    if (WIFEXITED(status))
      printf("exit status %d\n", WEXITSTATUS(status));
  }
  return 0;
}

我的问题是弄清楚如何在子进程中捕获错误。WIFEXITSTATUS 始终为 0,即使在 shell 中运行相同的命令然后执行 'echo $?' 将打印 127。例如 my-if 'toto' 'tutu' 会给我一个 WEXITSTATUS = 0,即使

$ toto
$ echo $?
$ 127

我尝试了 WSIGNALED、WSTOPPED,但我真的不知道如何捕捉错误。我是在寻找正确的方向,还是完全不同的东西,例如启动一个 shell,然后执行我的命令,错误是 shell 固有的,而不是命令?

4

3 回答 3

0

非常感谢大家的意见。我只需要返回 execv() 的潜在返回,然后它成为原始 fork() 的 wait() 的 WEXITSTATUS。

else if (t == 0) 
**return** execvp(argv1[0], argv1);
于 2013-10-22T12:09:47.863 回答
0

将您的呼叫更改为execvp. 尝试:

execvp( argv[1], argv + 1 );
于 2013-10-22T11:42:57.173 回答
-1

你应该检查是否wait真的返回了一些东西。如果返回值不是您的 childpid,那么您无法解释状态。

    if(wait(&status) != child)
    {
        printf("Error in wait\n");
        return -1;
    }

我使用此代码来解释各种状态。我认为代码很容易通过我使用的日志注释来理解。

如果您的孩子崩溃了,它将以 SINGAL 而不是 exit 终止,在这种情况下,您还必须检查相应的宏。

    if(WIFEXITED(status) == 0 && WIFSIGNALED(status) == 0)
    {
        LOGGER(MODULE_TAG, DEBUG2) << "Child: " << pid << " still running";
        setRunning(true);
        setTerminated(false);
        setTerminationSignal(0);
        setExitStatus(-1);
    }
    else if(WIFSTOPPED(status))
    {
        LOGGER(MODULE_TAG, DEBUG2) << "Child: " << pid << " stopped";
        setRunning(false);
    }
    else if(WIFCONTINUED(status))
    {
        LOGGER(MODULE_TAG, DEBUG2) << "Child: " << pid << " continued";
        setRunning(true);
    }
    else
    {
        setRunning(false);
        setTerminated(true);
        if(WIFEXITED(status))
        {
            LOGGER(MODULE_TAG, DEBUG2) << "Child: " << pid << " terminated normally";
            setTerminationSignal(0);
            setExitStatus(WEXITSTATUS(status));   // Exitcode from the child
        }
        else
        {
            LOGGER(MODULE_TAG, DEBUG2) << "Child: " << pid << " terminated by signal";
            setTerminationSignal(WTERMSIG(status));
            setExitStatus(-1);
        }
    }
于 2013-10-22T11:36:22.643 回答