>>4363 68user 御回答ありがとうございました。 また情報交換ができてうれしく思います、重ねてお礼申し上げます。 >>4367 has 話に割り込んでしまってごめんなさい。 >>4366 anonymous コマンドが読み書きするファイルのアクセス権限を考慮して判断するのが良いと思います。 例えばmountコマンドでは一般userにデバイスへのアクセス権限がないので(当方FreeBSD)、 コマンドは実行できてもmountはできません。 また許可を与えたい場合、デバイスファイルのパーミッションを変更すれば使用できますが、 いろいろ問題がありそうなので、 http://x68000.q-e-d.net/~68user/unix/pickup?sudo の方法を取ったりするそうです。 ついでにちょっと変な話。 実行権限がないディレクトリに対して移動(cd)もディレクトリの内容の確認も(ls)もできません。 が、opendir(c言語)を用いいると実行権限がなくても内容の確認ができてしまいます。 なんだか不思議な感じがしませんか? |
>>4369 マーブル > 実行権限がないディレクトリに対して移動(cd)もディレクトリの内容の確認も(ls)もできません。 > が、opendir(c言語)を用いいると実行権限がなくても内容の確認ができてしまいます。 少々誤解があるようですが、実行権限がないディレクトリに対しては、移動 (cd) は できませんが、ディレクトリの内容の確認 (ls) はできます (読み込み権限があれば)。 しかし ls -l はこけます。 引数なしの ls が行っていることは opendir(2) なわけですが、opendir(2) は ディレクトリの下にアクセスしません。ディレクトリエントリを読むだけなので % cat ディレクトリ名 相当の処理しかしていません。よって、ディレクトリに対する読み込み権限があれば ファイル一覧を取得できます (ディレクトリも広義のファイル)。 一方 ls -l は opendir(2) して、取得したファイル名それぞれについて stat(2) する わけですが、stat(2) するには それぞれのファイルの i-node を知る必要があります。 しかし i-node を知るには、そのファイルが属する上位ディレクトリの実行権限が必要です。 結局のところ、ディレクトリに対する実行権限とは 「ファイル名から i-node への変換を許可するかどうか」 であり、言い換えると 「namei(9) を許可するかどうか」 だとわたしは思っていますが、違っていたら誰か教えてください。 |
>>4370 68user すいません-Fのエイリアス掛かってました。 \lsで動作します、掲示板汚してごめんなさい。 truss ls -F testdirの結果の一部 fchdir(0x5) ERR#13 'Permission denied' よりディレクトリ内に移動できないということらしいです(FreeBSD) (Linuxで試したらfstatでのエラーだったのでものによりけりな予感 |
~はunixではどのような存在なのですか? |
>>4368 68user >>4366 anonymous は解決したのですか? |
はじめまして。 学校の課題で、C言語でnslookupみたいな動作をするプログラムを作るように言われ こちらのサイトを参考に作成させていただいております。 それで一箇所気になったのですが、 http://x68000.q-e-d.net/~68user/net/resolver-3.htmlの > タイプが TXT なら、そのまま表示します。 > これは多分間違い。 > % ./resolver-1.pl www.jp.freebsd.org version.bind txt chaos > リソースデータは「&Sorry, no version string is available」と表示されるが、 > dig や nslookup は「Sorry, no version string is available」となります > (& がない)。 > 先頭の & を削るような規則があるようだが、それが何なのかはわからなかった。 の部分ですが、&の文字コードは0x26(10進数で言う38)。 そしてその後に続く 【Sorry, no version string is available.】 は38文字。 つまりドメイン名の3www8livedoor3com0と同じような意味かなと思います。 そのため先頭の1バイト目を出力しないようにすればdigやnslookupと同じような 表記になるのではと思います。 例) sega.jpを調べるとunknownが帰ってきますが、その中身は 【07 75 6e 6b 6e 6f 77 6e】です。 文字数が32文字以上ないと画面上には何も表示されないので、 それ以下の文字数のところでは結果的にうまく出力されているのかなと思います。 そのため【タイプが TXT なら、そのまま表示します。】ではなく、 【タイプが TXT なら、先頭1バイト以外をそのまま表示します。】かなと思います。 ぜんぜん的外れな事言っていたらすいません。 |
こちらのサイトを参考にresolver-1.plと似たような動作をする C言語のプログラムを作成したのですが、一箇所分からないところがあったので、 もしお分かりになるようでしたらアドバイスをいただけないでしょうか。 作成ソース(一応問題なく動くと思います) windows版(CPad 2.31使用) http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1052.txt linux版(gcc 2.96使用) http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1053.txt それで、分からないのは【DNS query 送信時にごみデータが後ろに大量に付く】事です。 ごみが付いてしまう理由は、 DNS query の質問レコードの照会名(可変長)の長さは 実際に名前解決ホスト名を入力されないと分からないので、 char QUERIES[400];と宣言し、そこに名前解決ホスト名を格納しているからです。 そして、その後ろに、タイプとクラスを連結しています。 そのためQUERIES[400]の余った部分がごみデータとなってしまいます。 実際の動作には問題が無いみたいで、 パケットをキャプチャしなければごみが付いているのは分からないのですが、 気持ち悪いので改善したいと思っております。 アドバイスをいただけるようでしたら、どうかよろしくお願いします。 |
たびたびすいません。 No 4375のソースですが、 掲示板から直接クリックするとアップロードしたソースが見えないようなので、 ブラウザを新規に立ち上げてアドレス欄にコピーしてアクセスしていただけますでしょうか。 |
テストサーバ:solaris8 本番サーバ :solaris8 ワークステーション間のファイル転送について質問です。 テストサーバで構築したディレクトリを本番サーバに移行しようとしています。 条件としてファイルのパーミッション、ユーザ.グループ、タイムスタンプは 変わらないようにします。 そのため "tar cvf /tmp/system.tar ." でアーカイブして"rcp"で本番サーバにアーカイブファイルを転送してファイルを 展開したのですがユーザ.グループが本番サーバのログインユーザのものになって しまいました。 tarは既存の状態をそのままアーカイブすると思っていたのですがrcpで転送すると 変わってしまうのでしょうか? よろしくお願いします。 |
No.4377の質問をした者です。 本番サーバでアーカイブしたファイルを展開時に"root”ユーザで実行したところ 既存の環境のままで展開できました。 solarisでは["o"オーナーシップ]というオプションが"root"ユーザ以外のユーザが アーカイブファイル展開時に付属するようでした。 おさわがせしましたm(__)m |
>>4374 DNS勉強中 ありがとうございます。 以前も length では、というご指摘をいただいたのですが、RFC などの 一次資料を見つけられずにいます。 http://x68000.q-e-d.net/~68user/cgi-bin/wwwboard.cgi?log=4283 http://x68000.q-e-d.net/~68user/cgi-bin/wwwboard.cgi?log=4293 この件に関する一次資料をご存知でしょうか? >>4375 DNS勉強中 > 分からないのは【DNS query 送信時にごみデータが後ろに大量に付く】事です。 > sendto(s, (const char *)&DNS_Send, sizeof(DNS_Send), 0, (struct sockaddr *)&server, sizeof(server)) < 0) { sizeof(DNS_Send) バイトを送信しているのがまずいので、必要なバイト数分だけ 送信すればよいと思います。この例なら送信バイト数は (DNS_Send.QUERIES - &DNS_Send.id + count + 4) バイト ですかね? (自信なし) まぁこれだと汚いので、質問数や長さを保持する変数を 追加した方がよいと思います。 あとは struct DNS_Packet のパディングが心配です (実際は id や flag は short なのでほとんどの環境では問題ないと思いますが)。わたしなら struct DNS_Query { .... }; struct DNS_Question { short id short flag; short QDCOUNT; short ANCOUNT; short NSCOUNT; short ARCOUNT; struct DNS_Query *q; }; struct DNS_Packet { char data[1000]; int length; }; として (命名は適当)、問い合わせ内容を DNS_Question に構築し、送信時に DNS_Packet にコピーして send すると思います。といっても、わたしのソースの方 では全く実践できていないですけれども。 ところで、全体的にはかなり読みやすいと思うんですが、このソースのライセンスを 教えてください。要は、これを修正したものを、わたしのページに C のサンプル コードとして記載することは可能でしょうか? ということです。 >>4378 Yuusuke 一般ユーザで展開したときに他ユーザの所有者でファイルを作成できてしまうと、 適当な tar ファイルをでっちあげれば他のユーザのファイルを自由に作成できる ことになってしまうので、普通の UNIX ではできません。 root で展開するのもひとつの方法ですが、Solaris では /etc/system で rstchown=0 と設定することで一般ユーザが chown できるようになります (セキュリティを 犠牲にするので、わたしはしません)。そうしておけば、一般ユーザが tar xfp すると、他ユーザが所有するファイルを作成できるかもしれません (試してません)。 |
>>4379 68userさん ご返答をいただきありがとうございます。 length の件ですが、もうしわけありませんが一次資料は存じておりません。 今回のプログラムで私が一次資料として利用したのが、 こちらのサイトということもありまして(^^;。 それとごみデータの件ですが、おっしゃりたいことは分かりました (まだソース上では試しておりませんが)。 送信するデータ量で調整すると言う発想は出てきませんでした。 明日にでもその部分は組めそうな気がします。 どうもありがとうございます。 後、構造体の中に構造体を書くスタイルも勉強になりました。 このスタイルを取り入れた形で動かせるよう努力してみたいと思います。 それとライセンスの件ですが、このソースの中に書かれている関数 ( make_domain, parse_response, get_domain )や 出力結果を見ていただければ分かるかと思いますが、 resolver-1.pl を C に移植しようとしたものがこのソースです。 移植作業自体は私が行いました。 もっとも pack とかの動作をどうやって C で再現すればよいのか等 わからない事が多かったので、 resolver-1.pl の出力結果や etherealの結果から 自分なりに解釈して組んでいる部分はありますので、 完全移植は出来ておりません。 そのため、このサイトで有効利用していただけるのでしたらありがたいです。 私がこのサイトから学んだことを還元できればうれしいですし、 修正したソースを見て勉強させていただけたらと思います。 とりあえず自分で組んだソースなので、 現在このソースが抱えている内部的な問題とか分かる範囲で明日まとめてみます。 実際にソースを読んでいただいているようですが、 情報を提供しないよりは、提供した方が良いかなと思いますので。 |
>>4380 DNS勉強中 > length の件ですが、もうしわけありませんが一次資料は存じておりません。 了解しました。一次資料を発見されたら、ご教示いただけると幸いです。 > そのため、このサイトで有効利用していただけるのでしたらありがたいです。 ありがとうございます。C でのサンプルソースとしてぜひ使わせていただければ と思います。ただ、今は時間がとれないので、半年後とか 1年後、もしかしたら 数年後となるかもしれません。その点はご了承ください。 > resolver-1.pl を C に移植しようとしたものがこのソースです。 そうなんですか。わたしはこんなわかりやすいソースを書いた覚えはないんですが、 とても可読性が高いように感じます。 なぜでしょうね? コメントが充実しているから? わたしは「適切な変数名・関数名を 使用していれば、あまりコメントを書かなくても問題ない」という考え方だった のですが、ちょっと考えが変わりそうです。 |
人材募集です。ご興味を持たれた方はお気軽にどうぞ。 http://X68000.q-e-d.net/~68user/tmp/job.html |
>>4381 68userさん 今回作成したソースは resolver-1.pl を参考に書かせていただきましたが、 どちらかというと書かれているソースではなく、 書かれているコメントを参考に作成しました。 理由は単に perl が分からないからです(^^;。 ただ、コメントから行っている動作が分かれば、 それを C で実現するにはどうすればよいかを考えれば良いのかなと。 以上のことより、 resolver-1.pl と同じような事を実現していても ソース自体は似つかないものになっているかもしれません。 と言いますか perl が読めないので「似てるか否かわからない」 というのが実際のところです(^^;。 後、ソースを利用する/しない、時期などはすべてお任せします。 それとごみデータの件ですが、下記の記述でうまくいきました。 sizeof(DNS_Send) - sizeof(DNS_Send.QUERIES) + count + 4 アドバイスを頂き、どうもありがとうございました。 |
投稿した DNS のソースコードの問題点 その1 ( Linux版のみ )照会タイプと照会クラスを共に指定しないと、 照会クラスに PWD=/root/src が挿入され (null にならず)、エラーになってしまう。 その部分にだけ絞ったサンプルソース( Windows/Linux 兼用 ) http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1057.c windowでの実行結果 argv[0] = C:\src\argv.exe(←これは私の実行ファイル名です) argv[1] = (null) argv[2] = (null) argv[3] = (null) argv[4] = (null) linuxでの実行結果 argv[0] = ./test24(←これは私の実行ファイル名です) argv[1] = (null) argv[2] = PWD=/root/src argv[3] = HOSTNAME=gifu-vm-35 argv[4] = LESSOPEN=|/usr/bin/lesspipe.sh %s 思いつく回避方法は、 1,照会タイプを入力必須にする。 2,照会クラスのみ引数ではなく、別途入力するようにする。 3,照会クラスの先頭3文字が PWD なら INTERNET に置き換えてしまう。 と言った所ですが、1,2は resolver-1.pl にくらべ多く入力する必要があり、 3は環境依存度が高いかも知れません。 このサイトで公開される際は、この部分は何かしか改善を加えた方が良いかもしれません。 |
>>4384 DNS勉強中 > 後、ソースを利用する/しない、時期などはすべてお任せします。 ありがとうございます。有効に活用させていただきたいと思います。再配布 ライセンスやクレジット表記について要望があれば、今のうちに承っておきます。 > printf("argv[0] = %s\n", argv[0]); > printf("argv[1] = %s\n", argv[1]); C の話になりますが、argv の要素数は argc を参照しなければいけません。領域を 超えた部分に何が入っているかは環境依存です。Windows で NULL が入っているのは たまたまです。OS のバージョンやコンパイラを変えたらどうなるかわかりません。 Linux の場合は、環境変数を保持している environ の環境にアクセスしていますが、 これもたまたまです。 # この領域は、普通は int main(int argc, char *argv[], char *envp[]) # などとアクセスします。 よって、 char query_type[256]; char query_class[256]; if ( argc >= 4 ){ strcpy(query_type, argv[3]); } else { strcpy(query_type, "A"); } if ( argc >= 5 ){ strcpy(query_class, argv[4]); } else { strcpy(query_class, "INTERNET"); } や char *query_type = "A"; char *query_class = "INTERNET"; if ( argc >= 4 ) query_type = argv[3]; if ( argc >= 5 ) query_class = argv[4]; などとするのがよいでしょう。 |
>>4385 68userさん ライセンスなどは不要です。 それと引数の御指導どうもありがとうございます。 よく理解でき、Linuxでの動作も確認いたしました。 おかげで問題点が1つ解消されました。 後、パディングが心配との事で、構造体を書いていただきましたので、 それを参考にソースを書き直してみました。 Windows版 http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1058.txt ただ struct DNS_Query { .... }; の .... の意味するところが分からなかったので ここは私なりに解釈して記述しています。 またstruct DNS_Query *q;の必要性が分からなかったので、これは記述していません。 しかし、 > 問い合わせ内容を DNS_Question に構築し、 > 送信時にDNS_Packet にコピーして send すると思います。 の部分は実現したつもりです。 もっともパディングが心配という事が良く理解できていないので、 果たして組んだソースが意図を汲んでいるかどうかは自信がありません。 後このソースの問題点ですが、いま自分が気づいているところでは2点あります。 変数 search と 変数 DNS_question.flag の保守性です。 動作自体には問題はないと思います。 ただこれは自分で直せる気がするので週末にでも直したいと思います。 |
>>4379 68user ありがとうございます。 おかげさまでつい先ほど本番サーバへ移行が完了しました。 本番サーバではリモートコマンドはできないポリシーになっていたようなのでftp でtarファイルを転送し、rootで展開しました。 |
>>4386 DNS勉強中 > ここは私なりに解釈して記述しています。 わたしの意図どおりの実装になっています。 > またstruct DNS_Query *q;の必要性が分からなかったので、これは記述していません。 struct DNS_Question { short id short flag; short QDCOUNT; short ANCOUNT; short NSCOUNT; short ARCOUNT; struct DNS_Query *query; }; と書くと、DNS_Question というものは 「id・flag・{QD,AN,NS,AR}COUNT・DNS_Query から成り立つ」 という関係がソース上に明示されます。プログラムは「データ構造+アルゴリズム」 ですので、正確なデータ構造を最初に明示しておけば、ソースを理解しやすくなる ということです。 また、こうしておけば、 main(){ make_question(&DNS_question); } make_question(DNS_Question *question){ question->id = ...; question->flag = ...; make_query(question->query); } make_query(DNS_Query *query){ query を作成 } というふうに、変数の受け渡しがすっきりします。 ただ、フラットな構成の方がわかりやすい場合もありますので、ケースバイケースかと 思います。 > もっともパディングが心配という事が良く理解できていないので、 わたしの環境では int main (){ struct { char a[1]; int b; } hoge; printf("%d\n", sizeof(hoge)); } の結果は 8 になります。構造体のメンバ間にどれだけのパディングが入るかは 環境依存なので、パディングが入らないことを前提としたコーディングをするのは 怖いなぁ、ということです。 > 後このソースの問題点ですが、いま自分が気づいているところでは2点あります。 > 変数 search と 変数 DNS_question.flag の保守性です。 なるほど、学校の課題にも関わらず細かな部分の完成度を高めたいというのは 素晴らしいですね。余計なお世話かもしれませんが細かいところまで見てみました。 > #include <netdb.h> 必要なヘッダファイルを include していません。その結果、引数チェックが 行われず、戻り値は int として扱われているはず。 このことに気づかないということは、警告オプションを有効にしていないと推察 されます。gcc であれば -Wall オプションを付けると幸せな人生を送れます。 > char *make_domain(char *domain_name); プロトタイプ宣言で変数名は不要で、 char *make_domain(char *); でよいです。別に引数名を記述しても動作には影響ないですが、引数名を変更 したときに直し忘れてズレが出るので、わたしは書きません。/usr/include/*.h にも書いてないです。 > fprintf(stderr, "Error: Socket作成失敗\n"); なぜ失敗したのかがわからないため、システムコールのエラー時には errno を 出力しましょう。わたしは fprintf(stderr, "Error: Socket作成失敗。errno[%s]\n", strerror(errno)); とするのが好みですが、perror(3) などを使う人も多いです。 bind 失敗時も同様。エラーメッセージが Bind error であるのと Bind error [Address already in use] と表示されるのでは、対処時間に大きな差が出ると思います。 ちなみに gethostbyname(3) のエラー処理が抜けています。gethostbyname は ソケットまわりのシステムコール呼び出し時のエラー以外にも、データ内容の エラーが発生する可能性があるので herror(3) や hstrerror(3) を使います。 > return -1; main で戻せる値は 0〜255 です。あと、exit と return が混在しているのが 気になります。 > questions = two_bytes(int_buf[search], int_buf[search+1]); > search += 2; two_bytes・four_bytes のインタフェースがいまいちです。データ取得と インクリメントを別々に行うと、インクリメント忘れ・インクリメントミスが 発生する危険性があります。 たとえば questions = two_bytes(&int_buf, &search); とインタフェースを変え、 int two_bytes(int *int_buf, int *search){ int sum; sum = int_buf[*search] * 16 * 16 + int_buf[*(search+1)]; *search += 2; return sum; } とすればデータ解析とインクリメントを同時に行えます。ここまでくれば、 struct DNS_Response { char data[10000]; int int_data[10000]; int pos; }; という構造体を作った方がよいかもしれません。 上記と関連しますが、 additional = two_bytes(&int_buf[search], &search); search += 1; これは一見すると謎なコードです。2バイト取得しているのに 1バイトしか進めて いないので、わたしはしばらく悩みました。結局は get_domain() の先頭で 1バイト 進めているから問題ないのですが、直感に反するコーディングだと思います。 > int conv_class(char *class){ > switch (class) { > case 1: printf("1 (INTERNET)\n"); break; > case 2: printf("2 (CSNET)\n"); break; > case 3: printf("3 (CNAME)\n"); break; > case 4: printf("4 (HESIOD)\n"); break; > case 5: printf("5 (ANY)\n"); break; > } わたしなら、 typedef struct { char name[100]; int code; } codelist_t; としておいて、 int conv_class(char *class){ codelist_t class_list[] = { {"INTERNET", 1}, {"CSNET", 2}, {"CHAOS", 3}, {"HESIOD", 4}, {"ANY", 5}, }; for ( i=0 ; i<sizeof(class_list)/sizeof(class_list[0]) ; i++ ){ if ( strcmp(class, class_list[i].str) == 0 ){ return class_list[i].code; } } と直します。class_list は void class_print(int class) で共用してもよいでしょう (resolver-1.pl と同じやり方)。 > memset(&client, '\0', sizeof(client)); > host[j] = 0; /* 最後に0を代入する */ memset は 0 で埋めて、host[j] は '\0' で終端すべきです。文字終端の '\0' と 値としての 0 を区別しておくと、後から読んだ人に意図が伝わりますので。 あとは命名について。関数名は動詞、変数名は名詞という基本ルールがあるよう ですが、徹底されていないように思います。 いまいちだと思う関数名: int domain_count(char *); → get_domain_length などが適切では。 int end_domain(int, int *); → is_XXX とか check_XXX がよいのでは。 int resource_data(int *, int, int, char *); → 名詞になっている。しかし他の hogehoge_print より一段レベルが高いので、 混同しないような命名をしたいところ。 void conv_time(int); → 「変換」といいつつ実際に行っているのは「出力」。 いまいちだと思う変数名: int search; → 動詞に見える。pos あたりでいいのでは。 int questions; int answer; int authority; int additional; → s が付いていたり付いていなかったり。あと、この変数の本質は「個数」で あるはず。であれば question_count とか question_num などにしたい。 int flag = 0; → flag や tmp という変数名が許されるのは変数スコープが 5行以内の場合 (わたしの中では)。それ以上ならもう少し長い名前を。 > int resource_data(int *int_buf, int search, int max, char *print); int max → record_num あたりで。 char *print → record_name あたりで。 > int domain_count(char *argv) argv は渡す側の変数名であって、この引数の本質は「ホスト名」であるため、 int domain_count(char *hostname) int domain_count(char *host) などがよいと思います。 と、わたしならこう書くという部分はあるものの、それでも可読性が高い と感じました。たとえば codelist_t は保守性は高いのですが、ぱっと見 読みやすいのは case 文の羅列です。勉強用のソースであれば、下手に 構造化しすぎることなく、あえてベタ書きしたほうがいいのではないかと 考え始めています。 あと、hoge_print 関数も、わたしはこういう書き方をせずに char *a_record_print(int_buf, search); と文字列を返すほうですが、メモリ確保を行うのは呼び出し側か、関数の 中で static に持つか、など悩ましいです。すっぱり割り切って関数内で printf するのも、保守性はともかく可読性は悪くない、と思いました。 あと、 - two_bytes・four_bytes という関数は便利で読みやすい。 - int_buf にコピーするのは、型変換のバグを避ける手法としては 優れているのかも (ちょっと逃げっぽいけど)。 - perl 版の可読性を落としているのはやはり pack。num2bin などの 関数を作り、直接 pack を呼ぶのは避けた方がよいのかも。 - やはり C は構造体がすっきり書けるのがよいところ。perl の場合、 ハッシュだとタイプミス耐性がないし、Class::Struct だとインクリメント が面倒だし、package を作るのは大げさ。 などといろいろと思うところはありました。自分が書いたものを他人が リライトすると、いろいろと気づくことがあっておもしろいですね。 いろいろ偉そうに書きましたが、指摘したことは当ページでは全然実践できて いません (エラーチェックは甘いし、herror(3) は使っていないし、resolver-1.pl ではデータ取得とインクリメントを別々に行っているし)。その辺はご容赦ください。 |
>>4388 68userさん いろいろと細かい点までアドバイスをしていただきましてありがとうございます。 大変勉強になります。 全てに指摘点に対しご回答差し上げたいのですが、 まだ指摘された部分の修正作業を行っておりませんので、 一通り読ませていただき、気づいた点について記述させていただきます。 まず return と exit の混在ですが、 これは conv_type 関数や conv_class 関数の部分だけを 指した指摘でしょうか。 それとも exit を一つも使わない方が良いという事でしょうか。 return と exit の混在のデメリットが分からなかったので。 後、変数 search ですが、仰るとおりインターフェースがいまいちです。 何故なら現在位置を返す関数と返さない関数が混在しているからです。 ここの処理がうまく思いつかなかったので search += 2; で逃げていました(^^;。 そして変数 search の大きな問題が仰るとおり > additional = two_bytes(&int_buf[search], &search); > search += 1; です。 ここは作った当人で無いと分からないですよね(^^;。 その理由は、開発途中で方針を変更してしまったためです。 そのため現在位置は ・解析し終わった部分の、次の部分の先頭に現在位置を合わせている所 ・解析し終わった部分の末尾に現在位置を合わせている所 の2パターンが発生してしまいました。 その代償が search += 2; と search += 1; の混在です。 ここは人に解析してもらう際にはまずいので修正します。 あと host[j] = 0; ですが、ここでは www.livedoor.com というドメイン名を 3www8livedoor3com0(数字の部分は文字ではなく、文字コード)に変換しているのですが、host[j] = 0; は ドメインの最後に文字コードの 0 を連結する と言う意味で記述しました。 何となく思ったのですが、 3www8livedoor3com0 の最後の 0 は終端という意味かな。 そう考えると仰られている意味が分かりました。 その部分に関しては、記述ミスと言うより、私の理解が間違っていたのかなと思います。 それと、int_buf は完全に逃げです(^^;。 ここの部分のうまい処理が思いつきませんでした。 他の指摘された部分につきましても、順次修正して良いものを作りたいと思います。 お忙しい中、いろいろご指摘いただきありがとうございます。 |
>>4389 DNS勉強中 > まず return と exit の混在ですが、 main から抜ける際に return と exit が混在していることを指したつもりでした。 下請け関数から exit するのは、狙っているのなら別にいいんじゃないかと思います (課題のプログラムですし)。変な値がやってきたら終了してしまうようでは、本格的な 運用で使うことはできませんが、 - 本格的な運用では使えないことを認識している。 - どういう要求が出てきたときに問題が起こるかなんとなく想像できる。 たとえば web サーバのログから IP アドレスを拾って、複数の名前解決を 高速に行うプログラムを作りたいという要求があったとすると、この プログラムではひとつでも変なレスポンスがくると exit してしまうので 実運用には耐えられない。 - 本格的な運用で使用する場合は、どこをどういうふうに書き換えればよいか だいたい把握している。 なら問題ないと思います。 > return と exit の混在のデメリットが分からなかったので。 わたしの中では以下のようなルールにしています。 1. 基本的に main まで戻る。エラー発生時の情報出力を行うことを考えると、 各関数の役割分担が明確になるから。 2. 例外として、引数解析エラー表示の usage 関数内では exit してよい。 理由は、処理が始まっておらず後始末が不要であることと、usage は 数箇所〜数十箇所から呼ばれる可能性があり、呼び出し元での exit 忘れが怖いこと。 if ( argv[i][0] != '-' ){ usage(); exit(1); /* これを書き忘れると処理が続行してしまう */ } 1 の詳細は以下のとおり。 今回のように 1件だけのデータを処理する場合は、変な値がきたときに ほげフラグが 1〜5 の範囲外です などと出力すれば問題ないが、 一度に複数のデータを処理するバッチの場合は ほげフラグが 1〜5 の範囲外です。受注番号[%d] レコード番号[%d] 顧客番号 [%d] などとより多くの情報を出力しないと、どのデータがおかしいのか特定できない。 とはいえ、下請け関数である 文字列→コード変換関数に、 conv_type(query_type, order_no, rec_no, customer_no); などとエラー発生時に備えて各種情報を渡すのは変。エラー出力用のグローバル変数を 作って err_order_no = order_no; err_rec_no = rec_no; err_customer = customer_no; conv_type(query_type); とする、なんてのも馬鹿馬鹿しい (後者はたまに見かけてイラッときますが)。 となると、 int main(){ ret = file_main(); if ( ret == -1 ){ logging("エラー発生。処理中断・ロールバックし、全データを元に戻します"); /* 後始末を一箇所にまとめる */ } } int file_main(){ fp = fopen(filename[i], "rw"); while (1){ fgets(fp, buf, sizeof(buf)); ret = hoge_main(buf); if ( ret == -1 ){ logging("hoge_main でエラー発生。ファイル名[%d] 行番号[%d]", filename[i], line); return -1; } } } int hoge_main(char *buf){ type = conv_type(query_type); if ( type == -1 ){ logging("query_type に変換に失敗。受注番号[%d]", rec_no): return -1; } } int conv_type(char *type){ if ( 異常値 ){ logging("type が異常値 [%s]", type); return -1; } } として main まで戻るのが現実的。conv_type はファイル名だの受注番号だの 責任範囲外のことを知らなくてもよいが、最終的にはエラーリカバリに必要な 情報が揃う。 Java などのいまどきな言語であれば例外を使うべきだろうと思います。 > 3www8livedoor3com0(数字の部分は文字ではなく、文字コード)に変換して > いるのですが、host[j] = 0; は ドメインの最後に文字コードの 0 を連結 > すると言う意味で記述しました。 戻り値を strcpy(DNS_Send.QUERIES, make_domain(argv[2])); と文字列として扱うのであれば、末尾は文字終端 '\0' であるべきで、 host[j] = 0; より host[j] = '\0'; にすべきという意味で書きましたが、たしかに文字列終端でもあり、DNS 的な 0 終端でもあるわけで微妙なところですね。 バイナリ列とみなして長さを明示的に管理し、strcpy のかわりに memcpy を 使うか、あるいは動作的には問題ないのでコメントで補足しておくか、あるいは 修正は不要なのか…。 > それと、int_buf は完全に逃げです(^^;。 いいんじゃないでしょうか。「バグを出さない」ということを第一目的とするなら アリだと思います。わたしなどいまだに char と unsigned char あたりの暗黙の 型変換ではまったりしていますので、キャストがちりばめられているソースだったら 解読に苦労していたかもしれません。 ちなみに単なる「char」が signed であるか unsigned であるかは環境依存です。 とはいえ、わたしは一般的な UNIX しか知らないので、char が unsinged char である環境は見たことはないですが。 |
>>4389 DNS勉強中 あと、さらに細かいことをひとつ。インデントは正確につけましょう。フラグ表示 の部分をわかりやすくするために、ひとつ余計にインデントしていますが、 { フラグ表示 } と、ブロックで囲めばすみます。 インデントはプログラマがつけるものではなくエディタが勝手につけるものであり (emacs の M-x indent-region などで)、もしエディタが変なふうにインデントして しまったら、それは括弧の過不足や文字列の閉じ忘れが原因、などと気づくことが できます (python などは除く)。 # というわたしのポリシーはなかなか理解してもらえない。なぜ手でインデントを # 付ける人が多いのだろう (って、素の vi やメモ帳を使ったりするからだが)。 # めんどくさくないのかなぁ。 |
>>4388 68user >>4390 68user >>4391 68userさん 今日は上記3レスでアドバイスいただいた内容についてある程度修正したり、 理解に努めておりました。 ・ struct DNS_Query *query; の必要性について理解いたしました。 確かに仰られるとおり、ソースが理解しやすくなると思いました。 そのため、その部分は修正しました。 (ただ make_question, make_query との関係上、一部修正しております)。 また、make_question と make_query を作成することにより、 main 部の記述を減らし、ソースを読みやすくしました。 ただ、記述していただいたとおりに作れなかったので、メイン部に make_question(&DNS_question); count = make_query(&DNS_query, argc, argv[2], argv[3], argv[4]); と2つにわけて記述しております。 ・ パディングについても理解いたしました。 確かに私の以前のソースはパディングが入らない前提で組んでありました。 やっと意図されたことが分かりました(^^;。 ・ /usr/include/bfd.h をみて、 プロトタイプ宣言について仰られていることを確認・理解し、修正しました。 ・ perror を用いエラー処理を追加しました。 ・ 抜けていた gethostbyname のエラー処理を追加しました。 ただし、 herror や hstrerror を Windowsで使う方法が分からなかったので、 とりあえず perror を使っております。 ・ return と exit の混在を解消しました。 それにともない、 main に戻らずに終了していた所を、 main に戻って終了するように変更しました。 またそれらしいエラー情報を出力するように変更しました。 ・ two_bytes の記述変更について理解いたしました。 アドレス渡しで現在位置を変更して、 戻り値で2バイトの値を取得する方法は大変参考になりました。 確かに、教えていただいた記述の方が何かと便利ですので、 ほぼ同じソースを移植させていただきました。 それに伴い、謎の search += 1; を修正しました。 また four_bytes も同様にソースを変更しました。 この作業を実施したことにより、 search += 2; や search += 4; を大幅に減らすことが出来ました。 ・ conv_type, conv_class, class_print, type_print を codelist_t を使用する形に変更しました。 ただし、 void class_print(int class) を用いた共用の記述の仕方が 分からなかったので、 codelist_t {class, type}_list[] = { ... };をグローバル化して共用しています。 また、 qr_print, opcode_print, aa_print, tc_print, rd_print, ra_print, rcode_print も同様に codelist_t { ... }_list[]化しました(こちらはローカル)。 ・ 0 と \0 の混在を修正しました。 ・ 変数名や関数名の命名を修正しました。 ・ フラグ部分のインデントを変更しました。 ブロックで囲むと言う発想が出てこず、 かといって、インデントなりコメントで上下を囲むなどしないと、 のちのち分からないだろうなと思い、 インデントしてしまったのですが、 ブロックで囲むと言う方法が教えていただき、大変参考になりました。 とりあえず今日修正できたところは以上です。 上記以外の部分についてはまだ手をつけておりません。 他に、今まで教えていただいた事を他の部分にも流用できないか、 ソースを一通り読み直してみて調べてみようと思います。 また search を触ったことのより、ある程度検証をする必要があるのかなと思います。 月曜日は予定が入っているので、まとめるのは難しいかも知れませんが、 火曜日くらいにある程度まとめて一度アップしてみようと思います。 いろいろ参考になるアドバイスをいただきまして、ありがとうございます。 |
to 68userさん さっそくですが、IPv6 のアドレス省略について 双方のプログラム(resolver-1.pl, 1058.txt)に バグがあるかも知れないのでご報告します。 一例として、 198.41.0.4 www.yahoo.co.jpと入力して、 {A, B, C, D, E, F}.DNS.jpを表示させたとき、 追加情報の F.DNS.jp の出力結果は下記のとおりになります。 resolver-1.pl 2001:2F8::100::153 私の出力結果 2001:2f8::100:0:0:0:153 ちなみにEtherealの出力結果は下記のとおりです。 2001:2f8:0:100::153 IPv6 のアドレス省略表記に関する説明を下記のサイトで拝見したのですが、 http://www.soi.wide.ad.jp/iw2001/slides/04/04-1/53.html そこには IPv6 のアドレス表記に関して2つの原則が書かれていました。 1,【連続する】0 のブロックは省略できる。 2,省略できるのは【1ヶ所】だけ。 そして出力結果から推察するに、 resolver-1.pl では、原則の1, 2共に満たしてないように見受けられます。 perl が分からないので想像ですが、 resolver-1.pl では 0 を見つけたら即座に :: に置き換え、 何回でも省略が使用できるように組んであるのかなと思われます。 私の方では、一度省略を使用したら、二度と使えないようには組んでいるのですが、 0 は即座に :: に置き換えております。 そのため 0 を見つけたら、次の場所を見て、 ・次の場所も 0 なら :: に置き換える ・次の場所が 0 で無ければ、 0 を出力する。 というコードを追加しないといけないかもしれません。 勘違いでしたらすいません。 |
>>4393 DNS勉強中 ありがとうございます。 とりあえず TYPE=TXT の件と IPv6 の件を bugid20・21 として登録しました。 http://x68000.q-e-d.net/~68user/bugnote/bugindex.php?projectid=1 ちなみになぜわたしが web を更新しないのは、解説文からソースへの リンク方法が http://x68000.q-e-d.net/~68user/cgi-bin/cvsweb.cgi/public_html/net/org/resolver-3.html?rev=1.11&content-type=text/x-cvsweb-markup のように :preinclude 21-106 などと行番号で指定しているため、修正が非常に面倒であるからです (まぁただの言い訳なのですが)。 +10 などの相対指定にしようかとか、 m/bind\(/ などと文字列で引っ掛けようかとか迷いつつここまで来てしまいました。 ご指摘を頂いたことについては大変感謝しておりますが、修正が遅いのは なにとぞご容赦ください。 |
>>4392 DNS勉強中 > ただし、 void class_print(int class) を用いた共用の記述の仕方が > 分からなかったので、 > codelist_t {class, type}_list[] = { ... };をグローバル化して共用しています。 一般的には、codelist_t を扱う関数を別ソースにし、ソース先頭で static codelist_t class_list[] = { ... }; と配列を宣言して、conv_class()・class_print() でその配列を使用 します。static をつければ外部ソースからアクセスできないので、 隠蔽できます。 ただ、複数ファイルに分けると、ヘッダファイルが必要だったり Makefile を 書きたくなったりするので、サンプルであれば分ける必要はないかもしれません。 それはそれとして複数のソースから構成される場合に、グローバル変数の 宣言をヘッダファイルで一元管理する方法をご存知なければ、一度書いて みるとよいでしょう。 --- var.h ---- #ifdef THIS_IS_MAIN #define GLOBAL #else #define GLOBAL extern #endif GLOBAL class_list[] = {...}; --- main.c --- #define THIS_IS_MAIN #include "var.h" --- sub.c --- #include "var.h" こんな感じです。 |
>>4394 68user 修正の件了解致しました。 その後修正したもの ・教えていただいた >struct DNS_Response { > char data[10000]; > int int_data[10000]; > int pos; >}; の構造体を下記のような感じに少し修正し、流用しました。 /* DNSサーバへの質問 */ struct DNS_Query { char data[10000]; int length; }; /* DNSサーバからの応答 */ struct DNS_Response { int int_data[10000]; int pos; }; 今まで int_data と pos の 2 つの引数を渡していたところが、 struct DNS_Response だけを渡せばよくなったので、 分かりやすくなったかなと思います。 ・ linux 版の warning を解消しました。 てっきり netdb.h を include したら sys/socket.h なども include してくれるものだと勘違いしておりました。 そのため、いままでの作ってきた他のソースでも warning がたくさん出ておりました。 大変勉強になりましたm(__)m。 ・ AAAA の表示を仕様に添った形に変更しました。 そんな感じに修正を施した現状のソースをアップロードしておきます(linux版)。 http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1091.txt 後、指摘された部分で残っている修正点は ・ hoge_print 関数の書き方 ・ >>4395 全般 くらいかなと思います。 直したつもりで、意図に沿っていない修正をしている箇所はあるかもしれませんが(^^;。 他には、個人的に「フラグを構成する各要素」を resolver-1.pl のように簡単に設定出来た方が良いかなと思ってます。 私のソースでは、下記一行で設定してしまってるのがいまいちかなと。 DNS_packet->flag = 0x0100; ビットフィールドあたりで記述してうまく動作すれば良いのですが。 もっともここ自体は今回のソースでは変更することはなさそうなので、 このままでも良いのかもと思ったりも…。 |
>>4395 68user 今まで一つのソースで完結するものばかり書いていたので、 static の付いたグローバル変数(内部結合グローバル変数)を 使った事はありませんでした。 大変勉強になりました。 後、グローバル変数の宣言を一元管理する方法は存じてなかったので、試してみました。 http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1093.txt ただ上記は意図に沿った記述かどうか自信がありません。 それと、この件は今回のソースとは直接関係ないという認識で宜しいでしょうか? 仮に提示どおりソースを分割しても class_list[] は sub.c でしか必要ないのかなと思ったので。 その後修正したもの ・ ソースを main.c, sub.c, var.h に分割しました。 ・ 「フラグを構成する各要素」を resolver-1.pl のような感じに変更しました。 main.c(linux版) http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1094.c Makefile(linux版) http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1095.txt sub.c(linux版) http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1096.txt var.c(linux版) http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1097.txt |
>>4397 DNS勉強中 > http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1093.txt > ただ上記は意図に沿った記述かどうか自信がありません。 そういえばわたしには、複数ファイルから参照されるグローバル変数で、 宣言と初期化を同時に行った経験がありませんでした (わたしはこういう 場合は init_hoge() という関数を作るので)。 要は main.c で codelist_t class_list[]; codelist_t class_list[] = { {"INTERNET", 1}, ... }; となるわけですが、これはコンパイル通りますか? 少なくとも警告くらいは 出そうな気がします。 普通はどう書くんでしょうね>どなたか > それと、この件は今回のソースとは直接関係ないという認識で宜しいでしょうか? その通りです。 その他ソースについて。 > int soa_record_print(struct DNS_Response *DNS_response, char *print, int i) 引数が i というのはかなりいただけないので、record_num あたりで。 > for (i=0; type[i]!='\0'; i++) > /* 照会タイプの文字の中に英小文字があれば英大文字に変換 */ > type[i] = toupper(type[i]); そういえば strcasecmp(3) というライブラリ関数があるのを思い出しました (使ったことはないですが)。 > void qr_print(int qr){ > codelist_t qr_list[] = { > ... > }; 動作的には問題ありませんが、関数呼び出しのたびにスタックに qr_list の値が 積まれるのは無駄なので、一般的には static codelist_t qr_list[] = { ... }; とします。これだとスタックではなくヒープに置かれ、初期化は一度しか行われません。 > Makefile(linux版) > http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1095.txt わたしなら以下のように書きますが、あまり Makefile に詳しくないので怪しげです。 TARGET= domain_to_ip OBJS = main.o sub.o CFLAGS = -Wall $(TARGET): $(OBJS) $(CC) $(CFLAGS) -o $(TARGET) $(OBJS) .c.o: sub.h $(CC) $(CFLAGS) -c $< clean: rm -f *.o *~ core $(TARGET) $(OBJS) あと、main がとても長くて汚い関数に見えますので、 make_query(); send_receive(); parse_response(); の 3行か+エラー処理か、あるいは make_query(); send_query(); receive_response(); parse_response(); の 4行+エラー処理くらいになるとよいかも、と思いました。 続く。 |
>>4398 68user 1093.txtのソースは何故か警告が出ることも無く、コンパイル出来ました。 定義を二回していますので、仰るとおり何か言われてもおかしくないと思われますが。 ちなみに下記はエラーが出ません。 #include <stdio.h> int a; int a = 10; int main(void) { printf("a = %d\n", a); return 0; } ただし下記はエラーが出ます。 #include <stdio.h> int main(void) { int a; int a = 10; printf("a = %d\n", a); return 0; } 上記の結果をみると、グローバルでは複数定義してもかまわないのかもしれません。 それと、本来は定義 codelist_t class_list[] = {...} をmain.cに書いて、 宣言 extern codelist_t class_list[]; を sub.c に書くのかも知れません。 ただ、そういたしますと、どうヘッダで一元管理すれば良いか思いつきませんでした。 修正した所 ・ soa_record_print の引数 ・ codelist_t を auto から static に変更しました。 static はどうしても値を保持し続けておかないといけない物以外には 使う必要がないと思ってました。 auto なら不要になったら解放されますし。 メモリ領域は、よく分かってないので勉強になります。 ・ main 部分を preprocessing(); … 前処理 make_query(); … 照会用の DNS パケットを作成 send_query(); … DNS サーバに問い合わせを送信 receive_response(); … DNS サーバからの応答を受信 parse_response(); … DNS サーバからの応答を解析 に集約しました。 分からなかった所 ・strcasecmp は、「大文字/小文字を無視して二つの文字列を比較する」そうですが、 私のソースでどうすれば有効活用出来るか分かりませんでしたので、使用しておりません。 それと Makefile のサンプルありがとうございません。 その記述で動作することを確認しました。 その書き方ですと、ソースファイルが増えても OBJS に追加するだけで良いので、 大変助かりました。 現状のソース(linux版(1ソース版)) http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1101.txt 上記のソースは今までと少し動作が違いまして、 【実行ファイル DNSサーバ 名前解決ホスト名】 と入力しますと、回答が得られるまで名前解決を行います。 現状の問題点 ・ リソースデータがドメイン名だけで、IPアドレスの情報が無いと名前解決が出来ない。 例) 198.41.0.4 www.livedoor.co.jp zns05.data-hotel.net と zns06.data-hotel.net しか返してくれません。 get_domain(); で、ドメイン名のラベルの部分を出力し、 print_domain(); で【.】を出力し、 ドメイン名の終端に達するまで両関数間を行ったりきたりしているのが原因です。 DNS サーバが IP アドレスでしたら、 a_record_print(); で姑息に sprintf で抜き出せたのですが。 そう考えますと、以前仰られていた > あと、hoge_print 関数も、わたしはこういう書き方をせずに > char *a_record_print(int_buf, search); > と文字列を返すほうですが、メモリ確保を行うのは呼び出し側か、関数の > 中で static に持つか、など悩ましいです。すっぱり割り切って関数内で > printf するのも、保守性はともかく可読性は悪くない、と思いました。 の部分が非常に重要かなと思いました。 文字列を上位に返すようにしていれば、流用もしやすかったのかなと。 そういう部分も保守性なのかなと思いました。 |
to 68userさん 急な話ですが、昨日の夜に就職が決まりまして、 来週月曜日からの勤務となりました。 そのため研修は明日で修了となりました。 そして課題の提出も明日となりました。 そのため、ご指摘いただいた箇所すべてを訂正して、 提出することは無理かなと言う感じです。 いろいろ教えていただきましたが、 それらをすべて反映できないことはお許しください。 修正したところ ・ hoge_print 関数を文字列を返す形に変更(それに伴い関数名も変更) resolver-1.pl 互換を目指した Linux 版 http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1107.txt 学校の課題用に上記ソースを修正した Linux 版 http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1108.txt 表示イメージは下記のとおりです。 実行ファイル名 198.41.0.4 www.livedoor.com DNSサーバ【198.41.0.4】に【www.livedoor.com】の名前解決を依頼 DNSサーバ【198.41.0.4】からの受信データバイト数: 506バイト DNSサーバ【192.12.94.30】に【www.livedoor.com】の名前解決を依頼 DNSサーバ【192.12.94.30】からの受信データバイト数: 120バイト DNSサーバ【203.174.65.123】に【www.livedoor.com】の名前解決を依頼 DNSサーバ【203.174.65.123】からの受信データバイト数: 136バイト 回答(1): リソースデータ: 203.131.197.197 nslookup のような感じの表示に近づけつつ、 実際に再帰的に DNS サーバに問い合わせを行っている事を視覚的にアピールしつつ、 提出期限が迫っているので、現状のソースをなるべく触らない方向でまとめてみました。 なお学校の課題用は最近取り掛かったこともあり、 完成度は前者に比べかなり劣ってます (実用に耐えれないという意味ではどちらも同じですが)。 |
>>4400 DNS勉強中 おめでとうございます。向上心のある方のように見受けられますので、どんな 業界でも能力を発揮できることと思います。ご活躍を期待しております。 わたしの方は指摘点をまとめているところですが、あまり時間が取れず 進んでいません。課題提出後なので意味はありませんが、中途半端なのは 気持ちが悪いので、infoseek の方はしばらくそのままにしていただけると ありがたく思います。 |
>>4401 68user ありがとうございます。 それと本日は作成したプログラムのドキュメント作成などで時間が取れなかったので 結局 >>4400 のソースを二つとも提出しました。 後、指摘点をまとめていただいていると言うことでどうもありがとうございます。 私のほうでも修正し次第アップロードします。 それとアップロード先の infoseek ですが、 私の管理下に無いアップローダにアップロードしております。 そのため何時消えてしまうか分からないのが現状です。 もっとも一年近く前のアップロード品も残っているようなので、 大丈夫だとは思います。 消えたら別の場所にアップロードします。 |
今日は仕事が休みで時間があったのでソースコードを修正しました。 resolver-1.pl 互換を目指した Linux 版 http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1142.zip 修正点 ・自作関数が文字列を返すことに伴い、グローバル変数が増えてしまったので、 ローカル static 変数に変更しました。 ・原則 1 つの関数につき、 1 つのソースコードにしました。 そのためソースファイル数が 30 あまりになりました。 ただし、グローバル変数の宣言の定義がよく分からなかったので、 class_list と type_list 関係は type_and_class.c でひとまとめにしました。 ・関数の流れ図?を簡易的に表した html を作成しました。 |
resolver-1.pl 互換を目指した Linux 版 http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1160.zip 微修正を加えただけです。 ただこれで、指摘していただきました問題点についてはすべて対応したつもりです。 それと、昨日引越しを伴う出向を言い渡されました。 当分の間ネットにつなげる環境も開発環境も無いと思われます。 そのため何かご指摘いただいても、返答を差し上げることは出来ないと思います。 よろしくお願いします。 |
こんにちは。 だいぶ前に書き込みをしたものですが 今回自力で何とかしてみようとふんばってみたものの、 2週間近く解決できません 助言をお願いいたしたく書き込みをしました。 SSLを↓のHPを参考に設定してみました http://www.rinzo2.jp/~rinzo/apache_ssl/apache_and_ssl_00.htm 何とか起動はしたんですが、 当初の目的では、 課題として作成したmysqlとJSP(Tomcat4.1)を使用し 作成したjspファイルを SSLの状態で表示させることでした。 例) http://localhost:8080/examples/index.jsp を https://localhost:8080/examples/index.jsp の形に 何とかできないかと、Apache2とTomcatを連携させてみたものの できませんでした。 もともとできないのかもわからず、 書き込んでみました。 あたりまえのことができてない といった返答でもいんで なるべくわかりやすく 助言のほどお願いします。 設定等で疑問のほどありましたら わかる範囲で答えますんでよろしくお願いします |
はじめまして、ファンと申します。上海から来ました。いまrsaを勉強していますが、 ちょっと困った事があったので、教えてもらいたいです。 pkcs#1中で、rsa暗号化処理前に、暗号プロックフォーマット処理が必要になりますが、 もし、rsa_no_paddingモードを使用なら、暗号プロックフォーマットの処理必要が なくなりますか。宜しくお願いいたします。 |
はじめまして SSL/TLS でアクセスしてみよう (2)を参考にHTTPSでの接続を行っていたのですが、 2回目のSSL_writeに対して、SSL_readの戻り値(文字列長)が0になってしまいます。 https-client-2.c の167〜187行をfor文に入れて2回呼んだ場合も同じように 2回目は文字列長が0で返ってきました。 リクエスト送信のたびにSSL_CTX_freeまで行って、次回は再接続から行わないとだめなのでしょうか? |
>>4404 DNS勉強中 すみません、まだ書いている途中です。と言ってもそんなに長くはないんですが、 気力充実待ちの状態です。もう見ておられないとは思いますが、今月中には何とか。 >>4405 SSL初心者 とりあえずできることはできるでしょう。Tomcat 単体でも SSL に対応しているし、 Apache と Tomcat で連携するなら mod_jk とか mod_webapps とか mod_jk2 とか いろいろあるようですが、わたしが使ったのは 4年ほど前なので最新事情はよく わかりません。 何をどこまでやって、どううまくいかないのか書いていないので何もアドバイスは できませんが、とりあえず http://www.mki.ne.jp/developers/doc/https/apache20.html を真似てみればよいのではないでしょうか。 と思ったら、今は Jakarta Tomcat Connectors って言うんですかね? それとも mod_jk に戻った? この辺は相変わらずめちゃくちゃですね。 http://tomcat.apache.org/connectors-doc/index.html >>4406 fan lihong > もし、rsa_no_paddingモードを使用なら、暗号プロックフォーマットの処理必要が > なくなりますか。 暗号ブロックフォーマットは PKCS#1 の一部ですから、RSA_NO_PADDING なら必要 ないと思います。 >>4407 びすこ > https-client-2.c の167〜187行をfor文に入れて2回呼んだ場合も同じように > 2回目は文字列長が0で返ってきました。 https-client-2.c の HTTP リクエスト部分をそのまま 2回繰り返すだけなら そうなるでしょうが、それは SSL の問題ではなく単なる HTTP の仕様です。 接続したまま何度もリクエストしたいなら HTTP/1.1 で Connection: keep-alive を付けたりします。とりあえずは、telnet で HTTP を話して試すべきです。 |
awkを使用してカンマ区切りのCSV形式のファイルから指定したフィールド位置 の値を取得しようとしているのですが、以下の様にするとファイル名までが 表示されてしまいます。 正しく、表示するよにはどうしたらいいのですか。 実際には、以下の様に出力されます。 ファイル名:20051201 : 1 ファイル名:20051202 : 3 を以下の様に出力したいのです。 20051201 : 1 20051202 : 3 環境は、Solaris8i Bシェル -------------------- ファイル 年月,名前,ID,値1,値2,値3 20051201,山田 太郎,001,1,1,1 20051201,山田 花子,001,1,2,10 ------------------- 第1パラメータ:年月(YYYYMM) 第2パラメータ:ID -------------------- #!/bin/sh # grep $2 ./$1/DiskCapacityTotal_Daily_$1*.csv | awk -F"," '{printf("%s : %s\n",$1,$4)}' ---------------------- |
>>4409 hagu grep に -h オプションを付けるとか、sed で s/^[^:]*// するとか。 |
>>4409 hagu FreeBSDでやってみたら、正しく表示されましたが。。 |
>>4410 68user >>4411 yasu ありがとうございます。 $1ではなく、$2とか$3と指定すると正しく表示されます。 ファイル名がててきません。 grep $2 ./$1/DiskCapacityTotal_Daily_$1*.csv | awk -F"," '{printf("%s : %s\n",$2,$4)} |
>>4409 hagu grep $2 ./$1/DiskCapacityTotal_Daily_$1*.csv | awk -F"," '{printf("%s : %s\n",$1,$4)' | sed 's/^[^:]*//' としたとき、ファイル名は消えたのですが、 $1の値を表示した際、前に「:」が残ります。 消したいのですが。 ------------ :20051201 : 1 :20051202 : 3 となります。 |
>>4413 だん ・・・・まあgrep自体なくても出来るというのは置いといて。 そもそも「ファイル名:」を付加しているのはgrepなんだから、 4410で68userさんが仰っているように、 grepに-hオプションをつけるだけだと思いますが、 こちらは試しましたか? |
>>No. 4408 68user 回答ありがとうございました。 HTTPでのお試しソースにはConnection: keep-aliveがあって、 HTTPSの方では抜けているのに気がついていませんでした。 HTTPの方でも判ってて書いてたわけではないので、 リクエストについてもっと調べてみます。 |
はじめまして。 ここのソースを参考にさせてもらい、Mac OSX用のFTPクライアントを以前作りました。 今回、POPクライアントを作ろうと思うのですが、C言語で書かれたシンプルなPOPクライアント のソースってないもんでしょうか? 今のところネットを検索していて、 http://www.oss-watch.ac.uk/resources/emailclients.xml にあった、mutt-1.5.10というのがまあまあかと見ていますが、やや面倒。 よろしくお願いします。 |
>>4416 はる fetchmail の前身である popclient はどうでしょうね。 http://www.interlog.com/~esmith/flames/pop.html から popclient-2.21 が落とせますが、手ごろなサイズで、それなりにソースも キレイではないかと思います。 % wc -l *.[ch] 58 config.h 535 pop2.c 533 pop3.c 592 popclient.c 93 popclient.h 175 socket.c 71 socket.h 2057 合計 手元の Linux でコンパイルすると可変長引数あたりでこけましたが、適当に直せば 動くでしょう。 |
>>4417 68userさん これよさそうですね。 cソースが4つしかないし、pop3.cだけ見ていれば分かりそう。 コンパイルは通らなくてもOKです。これを元にいじってしまいますから。 どうもありがとうございます! |
こんにちわ。 シェルにて簡単なメニュー画面作成しているのですが、 一点困ったところがあるので教えてください。 本シェルはrshによって呼び出されていて親シェルとは違うサーバで起動しています。 メニュー画面という事で画面上の掃除のためclearコマンドを使用しているのですが、 rshで呼び出された場合はclear処理が行われておりません。 ローカルでの実行では勿論問題なくclearされます。 rshにて実行する場合画面のclear方法などがご存知でしたら教えてください。 よろしくお願いします。 |
>>4419 KA 状況がよくわかりませんが (rsh でコマンドを指定せず実質的には rlogin を 使用するのと同じなのかとか、rsh 先で端末が割り当てられているのかとか、 端末の種類が違うだけなのかとか)、とりあえず % clear > clear.txt としてシーケンスを保存しておき、そのデータを出力してはどうでしょうか。 |
cronの変更方法を教えて下さい。 Cシェルの場合は以下コマンドでviが開きます。 setenv EDITOR vi cd /var/spool/cron/crontabs crontab -e root shシェルの場合はsetenvが使用できないので 以下コマンドを使いましたが982とか数字がでてきてviが開きません。 EDITOR=vi export EDITOR cd /var/spool/cron/crontabs crontab -e root shシェルでのcrontab -e rootの起動はどうづれば良いのでしょうか。 |
cronの編集について教えて下さい。 Cシェルの場合は以下の方法で編集しています。これでviが起動できます。 setenv EDITOR vi cd /var/spool/cron/crontabs crontab -e root shシェルの場合、以下コマンドを使用しましたがWAIT状態になりviが起動 できません。起動の方法を教えて下さい。 EDITOR=vi export EDITOR cd /var/spool/cron/crontabs crontab -e root |
初めて質問させていただきます。よろしくお願いします。 マシンはUNIX(日立:HI-UX/WE2)です。 cronで1分間隔でシェルを起動しているのですが、mail情報を 削除していなかったため、大量に溜まってしまい「out of i-nodes」の メッセーシ゛が出力され、dfコマント゛で確認するとi-nodesが0となっていました。 /usr/spool/mqueueには50万件のmailがたまっています。 また、mailboxも大量にたまり、mailbox.lockというlockファイルができています。 上記内容について、対処方法がありましたら教えてください。 (cronでmail情報を制御する方法は当ホームページで理解できました。) 以上 よろしくお願いします。 |
>>4422 cafe 手順としては間違っていないと思います (cd は不要ですが)。何がどうなっていて WAIT 状態と判断したのかわからないので、これ以上は何とも言えませんが、普通に % vi 適当なファイル名 で編集はできないのなら vi の問題でしょう。 >>4423 久 ファイル数が多すぎるので、df で i-node が full になっているファイルシステム内の ファイルを削除してください。 > mailboxも大量にたまり、mailbox.lockというlockファイルができています。 おそらく dotlock なファイルでしょうけど、いつまでたっても消えないなら 消していいと思います (心配なら MTA などのサーバ類を終了してから)。 |
回答ありがとうございました。無事RSAの確認できました。 sslv3のFinishedメッセージのことで質問ですが、 ClientKeyExchangeの後のEncrypted HandshakeはFinishedのことでそうか。 あと、Finishedメッセージはmd5_hash[16]+sha_hash[20]と他に何がついてますか。 あと、md5_hash[16]+sha_hash[20]の値が一致しないのですが、何かアドバイスを いただけないでしょうか。 宜しくお願いします。 |
こんばんは。初めて質問させていただきます。 AIXのサーバ上で「各レコードに改行コードが付いておらずファイルの最後に EOF(0a00)だけが付いているファイル」を2個連結したいのですが、 単純にcatで連結すると、2つのファイルのレコードの間に(0a)が入ってしまいます。 (例) ファイル1→ xxxx0a00 ファイル2→ yyyy0a00 の場合 cat ファイル1 ファイル2 > ファイル3 とすると ファイル3→ xxxx0ayyyy0a00 となってしまうが、実は以下のようにしたい ファイル3→ xxxxyyyy0a00 シェルまたはコマンドを用いて(C言語でプログラミングしない)で、 簡単に上記の形でファイルを連結する方法がありましたら教えて頂けないでしょうか? よろしくお願いします。 |
>>4425 fan SSL クライアントを実装したことがないのでわかりません (短めのサンプル ソースを出してもらえばわかるかもしれませんし、やっぱりわからないかも しれません)。 >>4426 shin1 > AIXのサーバ上で「各レコードに改行コードが付いておらずファイルの最後に > EOF(0a00)だけが付いているファイル」を2個連結したいのですが、 0x0A は LF、0x00 は NULL 文字で、EOF ではありません。 コントロールコードにおける EOF は 0x1A です (が、UNIX や Windows で 別にファイル終端コードとしての意味を持つわけではない)。 というわけで何を削除したいのかよくわかりませんが、0x1A ならば http://x68000.q-e-d.net/~68user/unix/pickup?tr など。 0x0A ならば、他の LF も削除してしまうと困るでしょうから、最後の 1バイトを削るのがよいでしょう。sed とか head とか dd とか perl とか を使えばできるのではないかと思います。 |
教えてください。DOSのコマンドで、チェックサムを自動で 計算するコマンドはあるのでしょうか? 例)JX12345-04のチェックサム(E0)を知りたい場合 |
こんにちは、初めて質問させていただきます。 こちらに載っているOpenSSLを用いたRSA暗号を動かして見たいので、 Windows上でのOpenSSLのインストールの仕方を教えてもらえませんか。 OSはXPでVisual C++.NETを使っています。 |
お騒がせしました。 自己解決しました。 |
こんにちは!! HP-UNIXなんですが、どなたか教えてください。 lsコマンドのタイムスタンプを常に西暦を表示するようにしたいのですが そのままls -l では直近6ヵ月未満までは西暦がでません。 該当するオプションがあるのでしょうか? ちなみに-Tはだめでした。 よろしくお願いします。 |
>>4431 まっちゅう@ペガサス流星拳 HP-UX 標準の ls では無理だと思います。代案としては、 - tar cf - ファイル | tar tvf - - sed で置換 - perl などを使う など。 |
ありがとうございます。 運良くFinishedメッセージは解決できました。 その次のAppricationDataの暗号化で質問があるのですが、 SSLCompressedが良く分からないです。 もし、ご存知なら、教えていただけないでしょうか。 お願いします。お願いします。 |
やっぱり無理ですか。。。。 代案までありがとうございました。 |
tarコマンドで、コマンドの実行ディレクトリからサブディレクトリも含めて、 ワイルドカードで指定したファイル、例えば、「*.txt」の様に指定して、 すべてのファイルを1つのアーカイブにまとめたいのですが、可能なので しょうか。 ディレクトリも含めたかたちにしたいのですが。 tar -cvf aaa.tar *.txt だと、直下のファイルのみ tar -cvf aaa.tar *.* だと、すべてのファイル |
>>4435 hagu いくつか方法はあると思いますが、 $ find . -name "*.txt" | xargs tar cvf outfile.tar 等とすればできます。 |
>> 4436 ありがとうございます。 試してみます。 |
>>4436 zsh Solaris の xargs (だったような気がしますが) は、LINE_MAX の長さがかなり 短くて、たしか 10KB 程度しかなかったような気がします。この使い方だと 複数回 tar コマンドが実行された場合、最後の方しかアーカイブに含まれない ので注意が必要です。 |
>>4408 68user 亀レスすいません。 DNS のプログラミングのアドバイスをしていただいたものです。 出張先の住まいがレオパレスでネット環境があると聞いていたので、 すぐに閲覧できると思いましたが、いろいろ問題があり今までかかりました。 今後は普通に対応できると思います。 よろしくお願いします。 |
>>4438 68user ご指摘ありがとうございます。 確かに複数回実行された場合の考慮が漏れていました。 ちなみに、Solaris の LINE_MAX の値は 2KB のようです。 |
>>4438 68user >>4440 zsh 試して見ました。 ご指摘の通りでした。 標準出力には、すべて出てきましたが、 最後の方しかアーカイブに含まれていませんでした。 どう対応すればよいのですか。 |
>>4441 hagu カナリ遅いですが. cat /dev/null>outfile.tar && find . -name "*.txt" | while read F in; do tar rvf outfile.tar "$F"; done |
サーバーアドレスの見方はどうすれば??教えてください! |
>>4441 hagu 試してませんが、 $ find . -name "*.txt" | xargs tar rvf outfile.tar でいけると思います。 (tar は r を指定すると追記になります。) |
>>4439 DNS勉強中 宣言した「今月中」もあと残すところ 6日。一度言ったことは守れよ、と 自分にプレッシャーをかける毎日です。 >>4441 hagu その他。 - tar cf outfile.tar `find . -name "*.txt"` (長すぎると Argument list too long になるが、エラーかどうかがはっきり わかるので使えなくもない) - tar の、ファイル名一覧をファイルから取得するオプションを使う。 >>4443 不明5号 質問の意味がわかりません。 |
>>4445 68user >>4444 zsh ありがとうございます。 試してみます。 >tar の、ファイル名一覧をファイルから取得するオプションを使う。 探して見たのですが、使い方がわかりませんでした。 使い方教えてください。 |
>>4445 68user >>4444 zsh ゴミすみません。 名前のところに”お”が入ったままで書いてしまった。 ありがとうございます。 試してみます。 >tar の、ファイル名一覧をファイルから取得するオプションを使う。 探して見たのですが、使い方がわかりませんでした。 使い方教えてください。 |
>>4447 hagu http://x68000.q-e-d.net/~68user/cgi-bin/wwwboard.cgi?howtouse にあるように、 OS 名を明らかにすれば期待する回答が返ってくる可能性が高まると思われます。 |
>>4448 68user すみません。 UNIXで、Solaris8 です。 |
>>4449 hagu man tar で出てきますが・・・ http://docs.sun.com/app/docs/doc/816-3518/6m9ptvr58?l=ja&a=view |
>>4449 hagu 具体的には % find . -name "*.txt" > filelist.txt % tar cf outfile.tar -I filelist.txt てな感じで。手元に Solaris がないので動くかどうかはわかりません。 |
>>4404 DNS勉強中 > resolver-1.pl 互換を目指した Linux 版 > http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1160.zip 今月中にと宣言したのでレビューをしようとしたのですが、上記ファイルが not found になっていて見ることができませんでした。 自宅のマシンには以前ダウンロードしたファイルがあるかもしれませんが、 今は出先なので見ることができません。もたもたしていてすみません。 とりあえず、1関数 1ソースはやめた方がよいとわたしは考えます。普通は プログラム全体 > モジュール > 関数 > ブロック という階層構造があり、例えば変数については - グローバル変数にする - ファイル内で static としてそのソース内 (モジュール) からのみ参照できるようにする - 関数内のローカル変数にする などの選択肢がありますが、1関数 1ソースだと、ここで言うモジュールという 選択肢がなくなってしまいます。 あとは Makefile を書くのがダルい、というデメリットもありますね。 |
>>4452 68user すいません。 アップロードしなおしました。 http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1374.zip ただこれは1関数1ソースバージョンです。 今出張先でこのソースバージョンしか持っていないです。 それと1関数1ソースのデメリット分かりました。 特にMakefileは書いてて同じ事を感じてました。 |
一応1ソースバージョンもアップロードしました。 http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1375.zip ただこれは学校に提出したバージョンのため、>>4453のソースの1つ前のバージョンのソースとなります。 |
>>4453 DNS勉強中 > http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1374.zip そろそろケチをつけるところもあまりなくて、重箱の隅的ではありますがいくつか。 > char *tc_search(int tc){ > static char tc_result[20]; > ... > return tc_result; > } こういうふうにしてしまうと char *p = tc_search(tc_1); char *q = tc_search(tc_2); という使い方ができなくなります (p が指す内容が上書きされてしまうため)。 スレッドセーフでなくなるのと、利用者のレベルが低ければ余計なバグを生む 危険性があります。 UNIX のライブラリ関数でも、最初は localtime・ctime・strtok・gethostbyname などの 非スレッドセーフ版しかありませんでしたが、localtime_r・ctime_r・strtok_r・ gethostbyname_r などのスレッドセーフ版を用意する羽目になってしまいました。 承知の上でそうしておられるならば問題ないと思います。 > /* フラグ一覧を出力 */ > qr = (DNS_response.int_data[DNS_response.pos] & 0x80) >> 7; > printf(" QR: (Query/Response): %s\n", qr_search(qr)); > > opcode = ((DNS_response.int_data[DNS_response.pos] & 0x40) >> 6) * 8; > opcode += ((DNS_response.int_data[DNS_response.pos] & 0x20) >> 5) * 4; > opcode += ((DNS_response.int_data[DNS_response.pos] & 0x10) >> 4) * 2; > opcode += (DNS_response.int_data[DNS_response.pos] & 0x08) >> 3; > printf(" OPCODE: %s\n", opcode_search(opcode)); わかりやすい変数名を使うこと自体は非常によいのですが、同じ値を繰り返し 使用する場合は、 int flag = DNS_response.int_data[DNS_response.pos]; qr = (flag & 0x80) >> 7; printf(" QR: (Query/Response): %s\n", qr_search(qr)); opcode = ((flag & 0x40) >> 6) * 8; opcode += ((flag & 0x20) >> 5) * 4; opcode += ((flag & 0x10) >> 4) * 2; opcode += (flag & 0x08) >> 3; printf(" OPCODE: %s\n", opcode_search(opcode)); などと一時変数に代入することをお勧めします。狙いは可読性向上と、変更時の 修正ミス防止です。わたしの場合は、 for ( int i=0 ; i<length ; i++ ){ struct *hoge_p = hoge_list.buf[x]; printf("%s\n", hoge_p->foo); printf("%s\n", hoge_p->bar); printf("%s\n", hoge_p->baz); } などと、ループ中でもよく一時変数に代入します。これは、ループ先頭の struct *hoge_p = hoge_list.buf[x]; で、 このループ中で参照するのは hoge_list.buf[x] だけ。hoge_list.buf[x+1] を 参照したりはしないよ。 というメッセージを送っているつもりです (効果があるかどうかは知りませんが)。 > DNS_query->data[0] = DNS_packet->id >> 8; > DNS_query->data[1] = DNS_packet->id & 0xff; > ... > DNS_query->data[11] = DNS_packet->ARCOUNT & 0xff; > for (i=12, j=0; i<12+domain_length; i++, j++) > DNS_query->data[i] = DNS_question_record->Name[j]; この場合は、変更時の作業量削減とマジックナンバ排除のため一時変数を使うべきです。 char *data_p = DNS_query->data; *(data_p++) = DNS_packet->id >> 8; *(data_p++) = DNS_packet->id & 0xff; ... *(data_p++) = DNS_packet->ARCOUNT & 0xff; for ( i=0; i<domain_length; i++) *(data_p++) = DNS_question_record->Name[i]; > FLAG flag_list[] = {{ /* 外側の中括弧は構造体の、内側の中括弧は配列の初期値を示す */ > 0, > ... > }}; > > return ((flag_list->qr * 128 + flag_list->opcode * 8 + .... )); FLAG flag = { 0, ... }; return (flag.qr*128 + flag.opcode*8 ... ); でよいと思います。あと、ビットシフトをしたい場合は乗算ではなく、>> や << で 表現した方が素直かなと思いました。 > int make_question_record(struct DNS_Question_Record *DNS_question_record, > int argc, char *hostname, char *type, char *class){ > /* 照会タイプが何も入力されていなければデフォルトの A を代入する */ > if (argc >= 4) > strcpy(query_type, type); > else > strcpy(query_type, "A"); ここまで argc を引っ張らず、もっと上位の関数で query_type を設定すべきと 思います (preprocessing あたりで)。 argc を引っ張りすぎると、もし引数のインタフェースを変更した場合、ソース 全体を調べて argc 関連の部分を修正することになってしまいます。 > /* DNS_response_before_conv->recv_bufはchar型なので、 > その中に格納されている数字は+127(0000007e)までしか表現できない */ しょーもないことですが、複数行のコメントは /* DNS_response_before_conv->recv_bufはchar型なので、 * その中に格納されている数字は+127(0000007e)までしか表現できない */ などと書けば、grep したときにその行がコメントであることが一目でわかります。 > goto comp2; 再起であれば、これまでの状態を脳内スタックに積んで、新たに呼ばれた関数の 引数と戻り値だけを考えればいいですが、こういう goto は覚えておかなくては ならない状態が多すぎるので、こういう goto はわたしは使いません (というか 頭が混乱してしまうので使えません)。 わたしは、エラー発生時の脱出以外で goto を使わない派です。 1ヶ月以上引っ張ってしまったわりに、たいしたレビューができませんで 申し訳ないです。 |
新版 UNIX 由来/読み方辞書 http://X68000.q-e-d.net/~68user/unix/unix-term-dic.html なるものを作ってみました。 元々あったオリジナルが 200個、わたしが追加したのが 60個程度です。 オリジナルの記述を読んでると時代を感じますね…。 |
a.outでtypo指摘っす > 実態にそぐわなかくなったが |
>>4457 Netboy ありがとうございます。今晩修正します。 追加ネタメモ。 abbrev yum xargs |
>>4457 Netboy 修正いたしました。ご指摘ありがとうございました。 |