質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

1回答

1841閲覧

Cでリダイレクトを作成したい。

oika77

総合スコア184

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2018/06/03 06:22

前提・実現したいこと

c言語でリダイレクトを作りたいのですが、なかなかうまく行きません。
初心者ですので簡単なミスかもしれませんが、結構考えて答えにたどり着かなかったので質問させていただきます。

該当のソースコード

コード #include<unistd.h> #include<string.h> #include<fcntl.h> #include<sys/types.h> #include<sys/wait.h> #define MAX_LINE_IN 1000 #define MAX_ARGS 30 void redirect(char *args[], int REDI){ int fd; // printf("%sこれにリダイレクトします。\n", args[REDI]); fd=open(args[REDI], O_WRONLY | O_CREAT, 0664); close(STDOUT_FILENO); dup(fd); execvp(args[0],args); } int main(int argc, char *argv[]){ int pid, status; char line_in[MAX_LINE_IN]; char *args[MAX_ARGS]; int nargs; int REDI; for(;;){ printf("> "); if(fgets(line_in, MAX_LINE_IN, stdin) == NULL) exit(0); line_in[strlen(line_in) - 1] = '\0'; REDI=0; char *token = strtok(line_in, " "); nargs = 0; args[nargs++] = token; while(token != NULL){ token=strtok(NULL, " "); if(token != NULL){ args[nargs++]=token; if(strcmp(token,">")==0){ REDI=nargs; } } } args[nargs] = NULL; if(strcmp(args[0], "exit")==0) break; if(fork()==0){ if(REDI!=0){ redirect(args, REDI); } execvp(args[0],args); printf("command not found\n"); exit(1); } else{ wait(&status); } } return 0; }

試したこと

『これにリダイレクトします。』というところは>を実行した時に表示されていたので、redirectの関数の中には入っているようです。またその関数の中に入ったargs[REDI]の文字列もレダイレクトの対象とするテキストファイル名が入っていたので問題ないと思います。

このコンパイルに関してはエラーはありませんでした。

実行 > echo hello > text.txt

これを実行した時は
text.txtのファイルに hello > text.txt という文字列が入りました。

実行 > cal > text.txt

とした時には cal: year `text.txt' not in range 1..9999
というエラーが出てtext.txtには何も入りませんでした。

補足情報(FW/ツールのバージョンなど)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2018/06/03 07:07 編集

実行を試されている状況が良く分からないのですが、コンパイル(ビルド)したプログラムの実行ファイル名は何なのでしょうか。また、Windowsなのか、unix系(linux?)なのかを書いた方がより回答を得やすいと思います。(fork()を使われているのでunix系だとは思いますが、cygwinと言うことも考えられるので)
oika77

2018/06/03 08:12 編集

ご指摘ありがとうございます。macを使用しております。実行の部分では初めの>は無視してください。(コードの真ん中あたりのprintf("< ");から来ています。)
guest

回答1

0

ベストアンサー

redirect関数を呼び出すときの引数が不適切なのが原因です。

echo hello > text.txt

これを実行する際、echoへの引数は

args[0] = "echo"
args[1] = "hello"
args[2] = NULL

が期待ですがご質問のコードでは

args[2] = ">"
args[3] = "text.txt"
args[4] = NULL

と、リダイレクト指示がそのまま引数になってしまってます。これだとechoは
args[1]~args[3]までの3つのパラメータを印字しようとしますし、calは意味不明なパラメーター
">" "text.txt"を受け取ってしまいますのでエラーを引き起こします。

とりあえず動くようにするためには以下の(A)を追加すればよいです。

C

1void redirect(char *args[], int REDI){ 2 int fd; 3 4 fd=open(args[REDI], O_WRONLY | O_CREAT, 0664); 5 close(STDOUT_FILENO); 6 dup(fd); 7 8 // ">"とその次のリダイレクト先のファイル名を起動コマンドへ渡さないようにする 9 args[REDI - 1] = NULL; //(A) 10 execvp(args[0],args); 11}

投稿2018/06/03 07:16

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2018/06/03 07:23 編集

余談ですが、 line_in[strlen(line_in) - 1] = '\0'; は意味がないです。strlenが文字列の長さを返せるということは既に'\0'がバッファ内の適切な位置に「存在している」ということですから。この行はあってもなくても同じです。
oika77

2018/06/03 08:17

回答ありがとうございます!!本当に助かりました。 うまくリダイレクト実行することが出来ました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問