5

シンプルなシェルを作っています。また、テキスト ファイルを行ごとに読み取ることができる必要があります。これは私のコードです:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>

// Exit when called, with messages
void my_exit() {
    printf("Bye!\n");
    exit(0);
}

int main(void) {

  setvbuf(stdout, NULL, _IONBF, 0);

  // Char array to store the input
  char buff[1024];

  // For the fork
  int fid;

  // Get all the environment variables
  char dir[50];
  getcwd(dir,50);
  char *user = getenv("USER");
  char *host = getenv("HOST");

  // Issue the prompt here.
  printf("%s@%s:%s> ", user, host, dir);

  // If not EOF, then do stuff!
  while (fgets(buff, 1024, stdin) != NULL) {

    // Get rid of the new line character at the end
    // We will need more of these for special slash cases
    int i = strlen(buff) - 1;
    if (buff[i] == '\n') {
      buff[i] = 0;
    }

    // If the text says 'exit', then exit
    if (!strcmp(buff,"exit")) {
      my_exit();
    }

    // Start forking!
    fid = fork();

    // If fid == 0, then we have the child!
    if (fid == 0) {

      // To keep track of the number of arguments in the buff
      int nargs = 0;

      // This is a messy function we'll have to change. For now,
      // it just counts the number of spaces in the buff and adds
      // one. So (ls -a -l) = 3. AKA 2 spaces + 1. Really in the
      // end, we should be counting the number of chunks in between
      // the spaces.
      for (int i = 0; buff[i] != '\0'; i++) {
        if (buff[i] == ' ') nargs ++;
      }

      // Allocate the space for an array of pointers to args the
      // size of the number of args, plus one for the NULL pointer.
      char **args = malloc((sizeof(char*)*(nargs + 2)));

      // Set the last element to NULL
      args[nargs+1] = NULL;

      // Split string into tokens by space
      char *temp = strtok (buff," ");

      // Copy each token into the array of args
      for (int i = 0; temp != NULL; i++) {
        args[i] = malloc (strlen(temp) + 1);
        strcpy(args[i], temp);
        temp = strtok (NULL, " ");
      }

      // Run the arguments with execvp
      if (execvp(args[0], args)) {
        my_exit();
      }
    }

    //  If fid !=0 then we still have the parent... Need to
    //  add specific errors.
    else {
        wait(NULL);
    }

    // Issue the prompt again.
    printf("%s@%s:%s> ", user, host, dir);
  }

  // If fgets == NULL, then exit!
  my_exit();
  return 0;
}

シェルとして単独で実行すると、うまく機能します。./myshell < commands.txt を実行すると、機能しません。

commands.txt は次のとおりです。

ls -l -a
pwd
ls

しかし、出力は次のとおりです。

>Bye!
>Bye!
>Bye!
>Bye!
>Bye!
>Bye!>Bye!
>Bye!
>Bye!
>Bye!

コマンドすら実行しません。何か案は?while ループはかなり単純だと思いました。

4

2 に答える 2

3

これが問題かどうかはわかりませんが、*args配列に「NULLポインターにプラス1」を割り当てる必要があると(正しく)コメントで述べています。

*argsただし、実際には最後のポインターを NULLに設定しません。

execvp()それは気に入らないでしょう。

リダイレクトされた入力とリダイレクトされていない入力に違いがある理由を説明していません。未定義の動作はろくでなしです。

于 2012-09-22T22:55:03.293 に答える
1

みなさんごめんなさい-私のテキストファイルはMacのTextEditGUIからのある種の痴呆なフォーマットだったことがわかりました。すべてがうまく機能しています。

有益な回答のすべてに本当に感謝しています

于 2012-09-23T00:06:55.860 に答える