プログラム
簡易の自作シェルを作成しようとしています。作成途中のプログラム(以下、「本プログラム」という。)から切り出してきたもの(以下、「小プログラム」という。)を以下に示します。なお、以下の小プログラムも実行しましたが、本プログラムと全く同じ出力を得ており、同一視できるものと考えます。
C
1#include <stdio.h> 2#include <stdlib.h> 3#include <sys/types.h> 4#include <unistd.h> 5#include <sys/wait.h> 6#include <string.h> 7 8#define BUFLEN 1024 9#define MAXARGNUM 256 10 11void execute_command(char *[], int); 12int parse(char [], char *[]); 13 14int main() 15{ 16 char command_buffer[BUFLEN]; // コマンド用のバッファ 17 char *args[MAXARGNUM]; // 引数へのポインタの配列 18 int command_status; // コマンドの状態を表す 19 20 for(;;){ 21 printf("Command: "); // プロンプトを表示 22 23 if(fgets(command_buffer, BUFLEN, stdin) == NULL){ 24 printf("\n"); 25 exit(0); 26 } 27 printf("buf = %s", command_buffer);// debug 28 29 /* 入力されたバッファ内のコマンドを解析 */ 30 command_status = parse(command_buffer, args); 31 32 for(int i = 0; args[i] != NULL; ++i){ 33 printf("args[%d] = [%s]\n", i, args[i]); 34 } // debug 35 36 if(command_status == 2){ 37 printf("done.\n"); 38 exit(EXIT_SUCCESS); 39 } else if(command_status == 3){ 40 continue; 41 } 42 43 execute_command(args, command_status); // コマンドを実行 44 } 45 return 0; 46} 47 48int parse(char buffer[], char *args[]) 49{ 50 int arg_index = 0; // 引数用のインデックス 51 int status = 0; // コマンドの状態を表す 52 53 /* バッファ内の最後にある改行をヌル文字へ変更 */ 54 char *p; 55 p = buffer + (strlen(buffer) - 1); 56 if(*p == '\n'){ 57 *p = '\0'; 58 } 59 60 if(strcmp(buffer, "exit") == 0){ 61 status = 2; 62 return status; 63 } 64 65 while(*buffer != '\0'){ 66 while(*buffer == ' ' || *buffer == '\t'){ 67 *(buffer++) = '\0'; 68 } 69 /* 空白の後が終端文字であればループを抜ける */ 70 if(*buffer == '\0'){ 71 break; 72 } 73 args[arg_index] = buffer; 74 ++arg_index; 75 while((*buffer != '\0') && (*buffer != ' ') && (*buffer != '\t')){ 76 ++buffer; 77 } 78 } 79 80 /* 最後の引数の次にはヌルへのポインタを格納する */ 81 args[arg_index] = NULL; 82 83 if(arg_index > 0 && strcmp(args[arg_index - 1], "&") == 0){ 84 --arg_index; 85 args[arg_index] = '\0'; 86 status = 1; 87 } 88 else{ 89 status = 0; 90 } 91 92 /* 引数が何もなかった場合 */ 93 if(arg_index == 0) { 94 status = 3; 95 } 96 97 /* コマンドの状態を返す*/ 98 return status; 99} 100 101void execute_command(char *args[], int command_status) 102{ 103 int pid; // プロセスID 104 int status; // 子プロセスの終了ステータス 105 106 switch(pid = fork()){ 107 case 0: 108 //子プロセス 109 exit(1); 110 case -1: 111 perror("fork"); 112 exit(1); 113 default: 114 if(waitpid(pid, &status, 0) < 0){ 115 perror("waitpid"); 116 exit(1); 117 } 118 } 119 return; 120}
プログラムの補足
関数parseは、command_bufferに格納された文字列を引数ごとに分解するのが主たる働きです。
command_buffer = ls -l
の場合、
args[0] = ls
args[1] = -l <-文末の改行コードは取り除かれます
args[2] = NULL
が格納されます。
状況
まず、test.txtを以下とします:
text
1cd 2history (←改行なし)
シェルで「./a.out < test.txt」を実行すると、次のような出力となります。
./test < text Command: buf = cd args[0] = [cd] Command: buf = historyhistoryargs[0] = [historyhistory] Command:
本来は、以下の出力を期待しています。
Command: buf = cd args[0] = [cd] Command: buf = historyargs[0] = [history] Command:
今わかっていること
プログラム43行目:execute_commandの実行をコメントアウトすると期待する出力をします。
つまり、execute_commandが原因だと思うのですが、全く見当がつきません。
誤りを指摘いただければと思います。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/07/22 01:04
2021/07/22 01:16