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

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

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

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

Q&A

2回答

3390閲覧

C言語で popen()を再現したい

LEO_

総合スコア6

C

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

0グッド

0クリップ

投稿2020/03/23 03:50

編集2020/03/23 05:28

C 言語のpopen() の ”r”(リード) モードを再現しなくはならなくて困っております。
一応fork()で Parent プロセスと Child プロセスを 作り、 pipe() を作って そのパイプのファイルポインターに return しろという事で 精一杯やってみたのですがこの後どうすれば良いのか分からなくなってしまいました。
myargs[0] = strdup("ls"); この文では本来なら cmd を入れたいのですが、どのようにポインターを myargs[0] に入れれば良いのかわかりません。
その点も含めて御助力いただけたら幸いです。
よろしければどのように改善出来るか教えていただけたら幸いです。 

C言語

コード #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> FILE *popen(const char *cmd, const char *mode){//cmd = LINUXコマンド、mode = モード FILE *fp;//戻り値 int fd[2]; // open pipe and fork, check for availability if(pipe(fd)== -1){ fprintf(stderr, "Pipe Failed"); } // popen part if (fork() == -1){ perror("fork failed\n"); exit(-1); }else if (fork() == 0){ close(fd[0]); close(STDOUT_FILENO); dup2(fd[1], STDOUT_FILENO); char *myargs[1]; myargs[0] = strdup(" ls"); myargs[1] = NULL; execvp(myargs[0], myargs); }else{ close(fd[1]); fp = fdopen(fd[1], "r"); //close(0); return fp; } }

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

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

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

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

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

nskydiving

2020/03/23 05:17

コードのレイアウトが崩れてしまっていますので、マークダウンの<code>タグを使って修正してください。 質問欄は「編集」ボタンから変更することができます。
LEO_

2020/03/23 05:32

ああ。すいません。別に学生という訳では無いんです。 知り合いにこういう事は知っておいた方が良いからやってみろと言われまして。 説明する必要が無いと思って課題という風に書いてしました。 紛らわしくて申し訳ありません。
otn

2020/03/23 07:16

目的を明確にした方が良いです。 ・簡易シェルを作る ・popenの実装の体験 後者であれば、exec部分は手を抜いて、 execlp("ls","ls",(char*)NULL); あたりで十分です。 前者であっても、コマンドラインの構文解析、パイプ・リダイレクト、変数、構造を持った構文それぞれなど、別々にトライするのが良いと思います。必要なら、最後に組み合わせる。
guest

回答2

0

exec*系の関数を使うのであれば、cmdを空白で分解する必要がありますね。

strsep()のような関数を使うと、任意のデリミタ(区切り文字)で引数として与えた文字列を分解することができるので覚えておいて損はないとおもいます。

たとえば、今後シェルを自作することがある場合、パイプ(|)を扱う必要がありますが、そのような場合にも応用が効くと思います。


exec*()system()を使った実行形式の起動はそれなりに危険性が伴います。
これらの関数の存在だけでなく、セキュリティに関する次のような文献の存在を覚えておいて損はないと思います。

投稿2020/03/23 06:53

TsukubaDepot

総合スコア5086

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

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

0

pipe(fd) が失敗しても、実行を継続するのはよくありません。

fork() を 2回実行していますね。
子プロセスが 2つでき、孫プロセスまでできてしまいますよ。

pipe(fd) で作ったパイプは、fd[0] が読み出し用、fd[1] が書き込み用です。

execvp の代わりに system(cmd); を使ってみたらどうなりますか?

main を書いてみました。

C

1#include <stdio.h> 2 3int main(void) 4{ 5 FILE *fp = popen("ls", "r"); 6 if (!fp) return 1; 7 char buf[1024]; 8 while (fgets(buf, sizeof buf, fp)) 9 fputs(buf, stdout); 10 pclose(fp); 11}

pclose があったほうがいいですね。
fork の後始末の wait を実行する必要がありますから。

投稿2020/03/23 05:29

kazuma-s

総合スコア8224

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問