修正前 修正後
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>   // fork, execvp #include <unistd.h>   // fork, execvp
#include <sys/wait.h> // waitpid #include <sys/wait.h> // waitpid
.  #include <glob.h>     // glob
   
#define MAX_CMD_LEN 1024 #define MAX_CMD_LEN 1024
#define MAX_ARGS 100 #define MAX_ARGS 100
   
// コマンドをスペースで分割する関数 // コマンドをスペースで分割する関数
void parse_command(char *cmd, char *argv[]) { void parse_command(char *cmd, char *argv[]) {
    char *token = strtok(cmd, " \n");     char *token = strtok(cmd, " \n");
    int i = 0;     int i = 0;
    while (token != NULL) {     while (token != NULL) {
        argv[i++] = token;         argv[i++] = token;
        token = strtok(NULL, " \n");         token = strtok(NULL, " \n");
    }     }
    argv[i] = NULL; // 最後の引数をNULLで終わらせる     argv[i] = NULL; // 最後の引数をNULLで終わらせる
} }
   
.  // 引数リストにパス名展開を適用する関数
  int expand_arguments(char *argv[], char **expanded_argv) {
      glob_t glob_result;
      int argc = 0; // 展開後の引数数
   
      for (int i = 0; argv[i] != NULL; i++) {
          if (strchr(argv[i], '*') || strchr(argv[i], '?') || strchr(argv[i], '[')) {
              // パス名展開が必要な場合
              if (glob(argv[i], GLOB_NOCHECK | GLOB_TILDE, NULL, &glob_result) != 0) {
                  perror("glob failed");
                  return -1;
              }
              // 展開された結果を追加
              for (size_t j = 0; j < glob_result.gl_pathc; j++) {
                  if (argc >= MAX_ARGS - 1) {
                      fprintf(stderr, "Too many arguments after glob expansion\n");
                      globfree(&glob_result);
                      return -1;
                  }
                  expanded_argv[argc++] = strdup(glob_result.gl_pathv[j]);
              }
              globfree(&glob_result); // メモリを解放
          } else {
              // パス名展開が不要な場合
              if (argc >= MAX_ARGS - 1) {
                  fprintf(stderr, "Too many arguments\n");
                  return -1;
              }
              expanded_argv[argc++] = strdup(argv[i]);
          }
      }
      expanded_argv[argc] = NULL; // 最後にNULLを追加
      return argc;
  }
   
int main() { int main() {
    char cmd[MAX_CMD_LEN]; // コマンド入力用のバッファ     char cmd[MAX_CMD_LEN]; // コマンド入力用のバッファ
    char *argv[MAX_ARGS];  // コマンド引数     char *argv[MAX_ARGS];  // コマンド引数
.      char *expanded_argv[MAX_ARGS]; // 展開後の引数
    pid_t pid;     pid_t pid;
    int status;     int status;
   
    // シェルのメインループ     // シェルのメインループ
    while (1) {     while (1) {
        // プロンプトを表示         // プロンプトを表示
        fprintf(stderr, "mysh> ");         fprintf(stderr, "mysh> ");
   
        // コマンドを読み込む         // コマンドを読み込む
        if (fgets(cmd, sizeof(cmd), stdin) == NULL) {         if (fgets(cmd, sizeof(cmd), stdin) == NULL) {
            if (feof(stdin)) {             if (feof(stdin)) {
                break; // EOFが入力された場合、終了                 break; // EOFが入力された場合、終了
            }             }
            perror("fgets failed");             perror("fgets failed");
            continue;             continue;
        }         }
   
        // コマンドを解析         // コマンドを解析
        parse_command(cmd, argv);         parse_command(cmd, argv);
   
        // 空のコマンドの場合は次の入力へスキップ         // 空のコマンドの場合は次の入力へスキップ
        if (argv[0] == NULL) {         if (argv[0] == NULL) {
            continue;             continue;
        }         }
   
        // 終了コマンドの場合         // 終了コマンドの場合
        if (strcmp(argv[0], "exit") == 0) {         if (strcmp(argv[0], "exit") == 0) {
            break;             break;
        }         }
   
.          // 引数を展開
          if (expand_arguments(argv, expanded_argv) == -1) {
              fprintf(stderr, "Argument expansion failed\n");
              continue;
          }
   
        // 子プロセスを作成してコマンドを実行         // 子プロセスを作成してコマンドを実行
        pid = fork();         pid = fork();
        if (pid == -1) {         if (pid == -1) {
            perror("fork failed");             perror("fork failed");
            exit(1);             exit(1);
        }         }
   
        // 子プロセス         // 子プロセス
        if (pid == 0) {         if (pid == 0) {
            // execvpを使用してコマンドを実行             // execvpを使用してコマンドを実行
.            if (execvp(argv[0], argv) == -1) {             if (execvp(expanded_argv[0], expanded_argv) == -1) {
                perror("exec failed");                 perror("exec failed");
                exit(1);                 exit(1);
            }             }
        }         }
   
        // 親プロセス         // 親プロセス
        if (waitpid(pid, &status, 0) == (pid_t)-1) { // 子プロセスの終了を待つ         if (waitpid(pid, &status, 0) == (pid_t)-1) { // 子プロセスの終了を待つ
            perror("waitpid failed");             perror("waitpid failed");
            exit(1);             exit(1);
.          }
   
          // メモリを解放
          for (int i = 0; expanded_argv[i] != NULL; i++) {
              free(expanded_argv[i]);
        }         }
    }     }
   
    printf("Exiting shell...\n");     printf("Exiting shell...\n");
    return 0;     return 0;
} }