左無題 右無題
#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 #include <glob.h>     // glob
#include <errno.h>    // errno #include <errno.h>    // errno
.  #include <limits.h>   // PATH_MAX
   
#define MAX_CMD_LEN 1024 #define MAX_CMD_LEN 1024
#define MAX_ARGS 100 #define MAX_ARGS 100
   
.  // 組み込みコマンド関連の宣言
  int cd (char *argv[]);
  int pwd(char *argv[]);
  struct builtin {
      char cmd[256];              // コマンド名
      int (*func)(char *argv[]);  // 関数へのポインタ
  };
  struct builtin blt_in[] = {{"cd",cd}, {"pwd",pwd}, {"",0}};
   
// コマンドをスペースで分割する関数 // コマンドをスペースで分割する関数
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で終わらせる
} }
   
// 引用符を削除する関数 // 引用符を削除する関数
void remove_quotes(char *str) { void remove_quotes(char *str) {
    char *src = str, *dst = str;     char *src = str, *dst = str;
    while (*src) {     while (*src) {
        if (*src == '"' || *src == '\'') {         if (*src == '"' || *src == '\'') {
            src++;  // 引用符をスキップ             src++;  // 引用符をスキップ
        } else {         } else {
            *dst++ = *src++;             *dst++ = *src++;
        }         }
    }     }
    *dst = '\0';  // 文字列の終端を追加     *dst = '\0';  // 文字列の終端を追加
} }
   
// 引数リストにパス名展開を適用する関数 // 引数リストにパス名展開を適用する関数
int expand_arguments(char *argv[], char **expanded_argv) { int expand_arguments(char *argv[], char **expanded_argv) {
    glob_t glob_result;     glob_t glob_result;
    int argc = 0; // 展開後の引数数     int argc = 0; // 展開後の引数数
   
    for (int i = 0; argv[i] != NULL; i++) {     for (int i = 0; argv[i] != NULL; i++) {
        // 引用符が含まれている場合は展開しない         // 引用符が含まれている場合は展開しない
        if ((strchr(argv[i], '*') || strchr(argv[i], '?') || strchr(argv[i], '[')) &&         if ((strchr(argv[i], '*') || strchr(argv[i], '?') || strchr(argv[i], '[')) &&
            (argv[i][0] != '"' && argv[i][0] != '\'')) { // 引用符外でパス名展開             (argv[i][0] != '"' && argv[i][0] != '\'')) { // 引用符外でパス名展開
            if (glob(argv[i], GLOB_NOCHECK | GLOB_TILDE, NULL, &glob_result) != 0) {             if (glob(argv[i], GLOB_NOCHECK | GLOB_TILDE, NULL, &glob_result) != 0) {
                perror("glob failed");                 perror("glob failed");
                return -1;                 return -1;
            }             }
            // 展開された結果を追加             // 展開された結果を追加
            for (size_t j = 0; j < glob_result.gl_pathc; j++) {             for (size_t j = 0; j < glob_result.gl_pathc; j++) {
                if (argc >= MAX_ARGS - 1) {                 if (argc >= MAX_ARGS - 1) {
                    fprintf(stderr, "Too many arguments after glob expansion\n");                     fprintf(stderr, "Too many arguments after glob expansion\n");
                    globfree(&glob_result);                     globfree(&glob_result);
                    return -1;                     return -1;
                }                 }
                expanded_argv[argc++] = strdup(glob_result.gl_pathv[j]);                 expanded_argv[argc++] = strdup(glob_result.gl_pathv[j]);
            }             }
            globfree(&glob_result); // メモリを解放             globfree(&glob_result); // メモリを解放
        } else {         } else {
            // 引用符を取り除く             // 引用符を取り除く
            remove_quotes(argv[i]);             remove_quotes(argv[i]);
   
            // パス名展開が不要な場合             // パス名展開が不要な場合
            if (argc >= MAX_ARGS - 1) {             if (argc >= MAX_ARGS - 1) {
                fprintf(stderr, "Too many arguments\n");                 fprintf(stderr, "Too many arguments\n");
                return -1;                 return -1;
            }             }
            expanded_argv[argc++] = strdup(argv[i]);             expanded_argv[argc++] = strdup(argv[i]);
        }         }
    }     }
    expanded_argv[argc] = NULL; // 最後にNULLを追加     expanded_argv[argc] = NULL; // 最後にNULLを追加
    return argc;     return argc;
} }
   
.  // 組み込みコマンドの判定・実行
  int built_in(char *argv[]){
      struct builtin *p;
      // 組み込みコマンド配列(blt_in)の走査
      for (p = blt_in; *p->cmd != '\0'; p++) {
          // 組み込みコマンドでない場合は次をチェック
          if (strcmp(p->cmd, argv[0]) != 0) continue;
          // 組み込みコマンドの関数を呼び出し
          (p->func)(argv);
          return 0;
      }
      return -1;
  }
   
  // cd コマンド
  int cd(char *argv[]) {
      if (argv[1] == NULL) {
          // 引数なしの場合はホームディレクトリに移動
          const char *home_dir = getenv("HOME");
          if (home_dir == NULL) {
              perror("cd: HOME not set");
              return -1;
          } else {
              if (chdir(home_dir) != 0) {
                  perror("cd failed");
                  return -1;
              }
          }
      } else {
          // 引数が指定された場合、そのディレクトリに移動
          if (chdir(argv[1]) != 0) {
              perror("cd failed");
              return -1;
          }
      }
      return 0;
  }
   
  // pwd コマンド
  int pwd(char *argv[]){
      char buf[PATH_MAX+1];
      if (getcwd(buf, sizeof(buf)) == NULL) {
          perror("getcwd failed");
          return -1;
      }
      printf("%s\n", buf);
      return 0;
  }
   
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]; // 展開後の引数     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) {         if (expand_arguments(argv, expanded_argv) == -1) {
            fprintf(stderr, "Argument expansion failed\n");             fprintf(stderr, "Argument expansion failed\n");
.              continue;
          }
   
          // 組み込みコマンド判定・実行
          if (built_in(expanded_argv) == 0) {
            continue;             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(expanded_argv[0], expanded_argv) == -1) {             if (execvp(expanded_argv[0], expanded_argv) == -1) {
                perror("exec failed");                 perror("exec failed");
                exit(1);                 exit(1);
            }             }
        }         }
   
        // 親プロセス         // 親プロセス
        while (1) {         while (1) {
            if (waitpid(pid, &status, 0) == (pid_t)-1) { // 子プロセスの終了を待つ             if (waitpid(pid, &status, 0) == (pid_t)-1) { // 子プロセスの終了を待つ
                if (errno == EINTR) {                 if (errno == EINTR) {
                    continue; // 割り込み発生時はリトライする                     continue; // 割り込み発生時はリトライする
                } else {                 } else {
                    perror("waitpid failed");                     perror("waitpid failed");
                    exit(1);                     exit(1);
                }                 }
            }             }
            break;             break;
        }         }
   
        // メモリを解放         // メモリを解放
        for (int i = 0; expanded_argv[i] != NULL; i++) {         for (int i = 0; expanded_argv[i] != NULL; i++) {
            free(expanded_argv[i]);             free(expanded_argv[i]);
        }         }
    }     }
   
    printf("Exiting shell...\n");     printf("Exiting shell...\n");
    return 0;     return 0;
} }