68user's page 掲示板

Prev< No. 4375〜4455> Next  [最新発言に戻る] [過去ログ一覧]
No. 4375 # DNS勉強中 2005/11/10 (木) 16:55:45
こちらのサイトを参考に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. 4376 # DNS勉強中 2005/11/10 (木) 16:58:56
たびたびすいません。
No 4375のソースですが、
掲示板から直接クリックするとアップロードしたソースが見えないようなので、
ブラウザを新規に立ち上げてアドレス欄にコピーしてアクセスしていただけますでしょうか。

No. 4377 # Yuusuke 2005/11/10 (木) 18:07:20
テストサーバ:solaris8
本番サーバ :solaris8
ワークステーション間のファイル転送について質問です。
テストサーバで構築したディレクトリを本番サーバに移行しようとしています。
条件としてファイルのパーミッション、ユーザ.グループ、タイムスタンプは
変わらないようにします。
そのため
"tar cvf /tmp/system.tar ."
でアーカイブして"rcp"で本番サーバにアーカイブファイルを転送してファイルを
展開したのですがユーザ.グループが本番サーバのログインユーザのものになって
しまいました。
tarは既存の状態をそのままアーカイブすると思っていたのですがrcpで転送すると
変わってしまうのでしょうか?
よろしくお願いします。

No. 4378 # Yuusuke 2005/11/10 (木) 18:57:26
No.4377の質問をした者です。
本番サーバでアーカイブしたファイルを展開時に"root”ユーザで実行したところ
既存の環境のままで展開できました。
solarisでは["o"オーナーシップ]というオプションが"root"ユーザ以外のユーザが
アーカイブファイル展開時に付属するようでした。
おさわがせしましたm(__)m

No. 4379 # 68user 2005/11/10 (木) 20:19:47
>>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
すると、他ユーザが所有するファイルを作成できるかもしれません (試してません)。

No. 4380 # DNS勉強中 2005/11/11 (金) 01:20:02
>>4379 68userさん
ご返答をいただきありがとうございます。

length の件ですが、もうしわけありませんが一次資料は存じておりません。
今回のプログラムで私が一次資料として利用したのが、
こちらのサイトということもありまして(^^;。

それとごみデータの件ですが、おっしゃりたいことは分かりました
(まだソース上では試しておりませんが)。
送信するデータ量で調整すると言う発想は出てきませんでした。
明日にでもその部分は組めそうな気がします。
どうもありがとうございます。

後、構造体の中に構造体を書くスタイルも勉強になりました。
このスタイルを取り入れた形で動かせるよう努力してみたいと思います。

それとライセンスの件ですが、このソースの中に書かれている関数
( make_domain, parse_response, get_domain )や
出力結果を見ていただければ分かるかと思いますが、
resolver-1.pl を C に移植しようとしたものがこのソースです。
移植作業自体は私が行いました。
もっとも pack とかの動作をどうやって C で再現すればよいのか等
わからない事が多かったので、
resolver-1.pl の出力結果や etherealの結果から
自分なりに解釈して組んでいる部分はありますので、
完全移植は出来ておりません。

そのため、このサイトで有効利用していただけるのでしたらありがたいです。
私がこのサイトから学んだことを還元できればうれしいですし、
修正したソースを見て勉強させていただけたらと思います。

とりあえず自分で組んだソースなので、
現在このソースが抱えている内部的な問題とか分かる範囲で明日まとめてみます。
実際にソースを読んでいただいているようですが、
情報を提供しないよりは、提供した方が良いかなと思いますので。

No. 4381 # 68user 2005/11/11 (金) 03:06:30
>>4380 DNS勉強中
> length の件ですが、もうしわけありませんが一次資料は存じておりません。
了解しました。一次資料を発見されたら、ご教示いただけると幸いです。

> そのため、このサイトで有効利用していただけるのでしたらありがたいです。
ありがとうございます。C でのサンプルソースとしてぜひ使わせていただければ
と思います。ただ、今は時間がとれないので、半年後とか 1年後、もしかしたら
数年後となるかもしれません。その点はご了承ください。

> resolver-1.pl を C に移植しようとしたものがこのソースです。
そうなんですか。わたしはこんなわかりやすいソースを書いた覚えはないんですが、
とても可読性が高いように感じます。

なぜでしょうね? コメントが充実しているから? わたしは「適切な変数名・関数名を
使用していれば、あまりコメントを書かなくても問題ない」という考え方だった
のですが、ちょっと考えが変わりそうです。

No. 4382 # 68user 2005/11/11 (金) 03:08:04
人材募集です。ご興味を持たれた方はお気軽にどうぞ。
    http://X68000.q-e-d.net/~68user/tmp/job.html

No. 4383 # DNS勉強中 2005/11/11 (金) 09:44:05
>>4381 68userさん
今回作成したソースは resolver-1.pl を参考に書かせていただきましたが、
どちらかというと書かれているソースではなく、
書かれているコメントを参考に作成しました。
理由は単に perl が分からないからです(^^;。

ただ、コメントから行っている動作が分かれば、
それを C で実現するにはどうすればよいかを考えれば良いのかなと。

以上のことより、 resolver-1.pl と同じような事を実現していても
ソース自体は似つかないものになっているかもしれません。
と言いますか perl が読めないので「似てるか否かわからない」
というのが実際のところです(^^;。

後、ソースを利用する/しない、時期などはすべてお任せします。

それとごみデータの件ですが、下記の記述でうまくいきました。
sizeof(DNS_Send) - sizeof(DNS_Send.QUERIES) + count + 4
アドバイスを頂き、どうもありがとうございました。

No. 4384 # DNS勉強中 2005/11/11 (金) 11:15:02
投稿した 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は環境依存度が高いかも知れません。
このサイトで公開される際は、この部分は何かしか改善を加えた方が良いかもしれません。

No. 4385 # 68user 2005/11/11 (金) 14:01:36
>>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];
などとするのがよいでしょう。

No. 4386 # DNS勉強中 2005/11/11 (金) 17:12:48
>>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 の保守性です。
動作自体には問題はないと思います。
ただこれは自分で直せる気がするので週末にでも直したいと思います。

No. 4387 # Yuusuke 2005/11/11 (金) 18:06:11
>>4379 68user
ありがとうございます。
おかげさまでつい先ほど本番サーバへ移行が完了しました。
本番サーバではリモートコマンドはできないポリシーになっていたようなのでftp
でtarファイルを転送し、rootで展開しました。

No. 4388 # 68user 2005/11/12 (土) 14:20:21
>>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
ではデータ取得とインクリメントを別々に行っているし)。その辺はご容赦ください。

No. 4389 # DNS勉強中 2005/11/12 (土) 17:37:13
>>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 は完全に逃げです(^^;。
ここの部分のうまい処理が思いつきませんでした。


他の指摘された部分につきましても、順次修正して良いものを作りたいと思います。
お忙しい中、いろいろご指摘いただきありがとうございます。

No. 4390 # 68user 2005/11/12 (土) 23:12:39
>>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
である環境は見たことはないですが。

No. 4391 # 68user 2005/11/12 (土) 23:36:45
>>4389 DNS勉強中
あと、さらに細かいことをひとつ。インデントは正確につけましょう。フラグ表示
の部分をわかりやすくするために、ひとつ余計にインデントしていますが、
      {
          フラグ表示
      }
と、ブロックで囲めばすみます。

インデントはプログラマがつけるものではなくエディタが勝手につけるものであり
(emacs の M-x indent-region などで)、もしエディタが変なふうにインデントして
しまったら、それは括弧の過不足や文字列の閉じ忘れが原因、などと気づくことが
できます (python などは除く)。

# というわたしのポリシーはなかなか理解してもらえない。なぜ手でインデントを
# 付ける人が多いのだろう (って、素の vi やメモ帳を使ったりするからだが)。
# めんどくさくないのかなぁ。

No. 4392 # DNS勉強中 2005/11/14 (月) 00:18:28
>>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 を触ったことのより、ある程度検証をする必要があるのかなと思います。
月曜日は予定が入っているので、まとめるのは難しいかも知れませんが、
火曜日くらいにある程度まとめて一度アップしてみようと思います。

いろいろ参考になるアドバイスをいただきまして、ありがとうございます。

No. 4393 # DNS勉強中 2005/11/14 (月) 09:44:17
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 を出力する。
というコードを追加しないといけないかもしれません。

勘違いでしたらすいません。

No. 4394 # 68user 2005/11/15 (火) 01:45:04
>>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\(/
などと文字列で引っ掛けようかとか迷いつつここまで来てしまいました。
ご指摘を頂いたことについては大変感謝しておりますが、修正が遅いのは
なにとぞご容赦ください。

No. 4395 # 68user 2005/11/15 (火) 01:55:14
>>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"

こんな感じです。

No. 4396 # DNS勉強中 2005/11/15 (火) 12:19:47
>>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;
ビットフィールドあたりで記述してうまく動作すれば良いのですが。
もっともここ自体は今回のソースでは変更することはなさそうなので、
このままでも良いのかもと思ったりも…。

No. 4397 # DNS勉強中 2005/11/15 (火) 17:14:29
>>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

No. 4398 # 68user 2005/11/16 (水) 03:05:19
>>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行+エラー処理くらいになるとよいかも、と思いました。

続く。

No. 4399 # DNS勉強中 2005/11/16 (水) 17:13:10
>>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 するのも、保守性はともかく可読性は悪くない、と思いました。

の部分が非常に重要かなと思いました。
文字列を上位に返すようにしていれば、流用もしやすかったのかなと。
そういう部分も保守性なのかなと思いました。

No. 4400 # DNS勉強中 2005/11/17 (木) 17:11:38
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 サーバに問い合わせを行っている事を視覚的にアピールしつつ、
提出期限が迫っているので、現状のソースをなるべく触らない方向でまとめてみました。

なお学校の課題用は最近取り掛かったこともあり、
完成度は前者に比べかなり劣ってます
(実用に耐えれないという意味ではどちらも同じですが)。

No. 4401 # 68user 2005/11/18 (金) 05:26:21
>>4400 DNS勉強中
おめでとうございます。向上心のある方のように見受けられますので、どんな
業界でも能力を発揮できることと思います。ご活躍を期待しております。

わたしの方は指摘点をまとめているところですが、あまり時間が取れず
進んでいません。課題提出後なので意味はありませんが、中途半端なのは
気持ちが悪いので、infoseek の方はしばらくそのままにしていただけると
ありがたく思います。

No. 4402 # DNS勉強中 2005/11/18 (金) 18:39:49
>>4401 68user
ありがとうございます。
それと本日は作成したプログラムのドキュメント作成などで時間が取れなかったので
結局 >>4400 のソースを二つとも提出しました。

後、指摘点をまとめていただいていると言うことでどうもありがとうございます。
私のほうでも修正し次第アップロードします。

それとアップロード先の infoseek ですが、
私の管理下に無いアップローダにアップロードしております。
そのため何時消えてしまうか分からないのが現状です。
もっとも一年近く前のアップロード品も残っているようなので、
大丈夫だとは思います。

消えたら別の場所にアップロードします。

No. 4403 # DNS勉強中 2005/11/22 (火) 22:13:22
今日は仕事が休みで時間があったのでソースコードを修正しました。
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 を作成しました。

No. 4404 # DNS勉強中 2005/11/27 (日) 17:36:49
resolver-1.pl 互換を目指した Linux 版
http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1160.zip

微修正を加えただけです。
ただこれで、指摘していただきました問題点についてはすべて対応したつもりです。

それと、昨日引越しを伴う出向を言い渡されました。
当分の間ネットにつなげる環境も開発環境も無いと思われます。
そのため何かご指摘いただいても、返答を差し上げることは出来ないと思います。
よろしくお願いします。

No. 4405 # SSL初心者 2005/11/28 (月) 14:44:25
こんにちは。
だいぶ前に書き込みをしたものですが
今回自力で何とかしてみようとふんばってみたものの、
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を連携させてみたものの
できませんでした。
もともとできないのかもわからず、
書き込んでみました。

あたりまえのことができてない
といった返答でもいんで
なるべくわかりやすく
助言のほどお願いします。

設定等で疑問のほどありましたら
わかる範囲で答えますんでよろしくお願いします

No. 4406 # fan lihong [E-mail] 2005/11/29 (火) 14:38:50
はじめまして、ファンと申します。上海から来ました。いまrsaを勉強していますが、
ちょっと困った事があったので、教えてもらいたいです。
pkcs#1中で、rsa暗号化処理前に、暗号プロックフォーマット処理が必要になりますが、
もし、rsa_no_paddingモードを使用なら、暗号プロックフォーマットの処理必要が
なくなりますか。宜しくお願いいたします。

No. 4407 # びすこ 2005/11/29 (火) 21:22:32
はじめまして
SSL/TLS でアクセスしてみよう (2)を参考にHTTPSでの接続を行っていたのですが、
2回目のSSL_writeに対して、SSL_readの戻り値(文字列長)が0になってしまいます。

https-client-2.c の167〜187行をfor文に入れて2回呼んだ場合も同じように
2回目は文字列長が0で返ってきました。

リクエスト送信のたびにSSL_CTX_freeまで行って、次回は再接続から行わないとだめなのでしょうか?

No. 4408 # 68user 2005/12/01 (木) 01:41:34
>>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 を話して試すべきです。

No. 4409 # hagu 2005/12/02 (金) 12:40:44
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)}'
----------------------

No. 4410 # 68user 2005/12/02 (金) 13:37:40
>>4409 hagu
grep に -h オプションを付けるとか、sed で s/^[^:]*// するとか。

No. 4411 # yasu 2005/12/02 (金) 23:15:35
>>4409 hagu
FreeBSDでやってみたら、正しく表示されましたが。。

No. 4412 # 2005/12/03 (土) 01:27:30
>>4410 68user
>>4411 yasu

ありがとうございます。

$1ではなく、$2とか$3と指定すると正しく表示されます。
ファイル名がててきません。

grep $2 ./$1/DiskCapacityTotal_Daily_$1*.csv | awk -F"," '{printf("%s : %s\n",$2,$4)}

No. 4413 # だん 2005/12/03 (土) 09:35:22
>>4409 hagu

grep $2 ./$1/DiskCapacityTotal_Daily_$1*.csv | awk -F"," '{printf("%s : %s\n",$1,$4)' | sed 's/^[^:]*//'

としたとき、ファイル名は消えたのですが、
$1の値を表示した際、前に「:」が残ります。
消したいのですが。

------------
:20051201 : 1
:20051202 : 3
となります。

No. 4414 # zsh 2005/12/03 (土) 14:06:35
>>4413 だん
・・・・まあgrep自体なくても出来るというのは置いといて。

そもそも「ファイル名:」を付加しているのはgrepなんだから、
4410で68userさんが仰っているように、
grepに-hオプションをつけるだけだと思いますが、
こちらは試しましたか?

No. 4415 # びすこ 2005/12/05 (月) 21:24:30
>>No. 4408 68user

回答ありがとうございました。

HTTPでのお試しソースにはConnection: keep-aliveがあって、
HTTPSの方では抜けているのに気がついていませんでした。

HTTPの方でも判ってて書いてたわけではないので、
リクエストについてもっと調べてみます。

No. 4416 # はる 2005/12/06 (火) 19:25:59
はじめまして。
ここのソースを参考にさせてもらい、Mac OSX用のFTPクライアントを以前作りました。
今回、POPクライアントを作ろうと思うのですが、C言語で書かれたシンプルなPOPクライアント
のソースってないもんでしょうか?
今のところネットを検索していて、
http://www.oss-watch.ac.uk/resources/emailclients.xml
にあった、mutt-1.5.10というのがまあまあかと見ていますが、やや面倒。
よろしくお願いします。

No. 4417 # 68user 2005/12/06 (火) 22:21:34
>>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 でコンパイルすると可変長引数あたりでこけましたが、適当に直せば
動くでしょう。

No. 4418 # はる 2005/12/07 (水) 07:27:04
>>4417 68userさん
これよさそうですね。
cソースが4つしかないし、pop3.cだけ見ていれば分かりそう。
コンパイルは通らなくてもOKです。これを元にいじってしまいますから。
どうもありがとうございます!

No. 4419 # KA 2005/12/07 (水) 13:10:25
こんにちわ。
シェルにて簡単なメニュー画面作成しているのですが、
一点困ったところがあるので教えてください。
本シェルはrshによって呼び出されていて親シェルとは違うサーバで起動しています。
メニュー画面という事で画面上の掃除のためclearコマンドを使用しているのですが、
rshで呼び出された場合はclear処理が行われておりません。
ローカルでの実行では勿論問題なくclearされます。
rshにて実行する場合画面のclear方法などがご存知でしたら教えてください。
よろしくお願いします。

No. 4420 # 68user 2005/12/08 (木) 00:26:55
>>4419 KA
状況がよくわかりませんが (rsh でコマンドを指定せず実質的には rlogin を
使用するのと同じなのかとか、rsh 先で端末が割り当てられているのかとか、
端末の種類が違うだけなのかとか)、とりあえず
    % clear > clear.txt
としてシーケンスを保存しておき、そのデータを出力してはどうでしょうか。

No. 4421 # cafe 2005/12/08 (木) 09:58:39
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の起動はどうづれば良いのでしょうか。

No. 4422 # cafe 2005/12/08 (木) 10:16:19
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

No. 4423 # 2005/12/08 (木) 16:58:58
初めて質問させていただきます。よろしくお願いします。
マシンは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情報を制御する方法は当ホームページで理解できました。)
以上 よろしくお願いします。

赤色の文字は 「Windows 機種依存文字」か、いわゆる「半角カナ」です。 この掲示板では自動変換されますが、今後は使用しないで下さい

No. 4424 # 68user 2005/12/09 (金) 00:35:57
>>4422 cafe
手順としては間違っていないと思います (cd は不要ですが)。何がどうなっていて
WAIT 状態と判断したのかわからないので、これ以上は何とも言えませんが、普通に
      % vi 適当なファイル名
で編集はできないのなら vi の問題でしょう。

>>4423
ファイル数が多すぎるので、df で i-node が full になっているファイルシステム内の
ファイルを削除してください。

> mailboxも大量にたまり、mailbox.lockというlockファイルができています。
おそらく dotlock なファイルでしょうけど、いつまでたっても消えないなら
消していいと思います (心配なら MTA などのサーバ類を終了してから)。

No. 4425 # fan 2005/12/12 (月) 17:46:30
回答ありがとうございました。無事RSAの確認できました。
sslv3のFinishedメッセージのことで質問ですが、
ClientKeyExchangeの後のEncrypted HandshakeはFinishedのことでそうか。
あと、Finishedメッセージはmd5_hash[16]+sha_hash[20]と他に何がついてますか。
あと、md5_hash[16]+sha_hash[20]の値が一致しないのですが、何かアドバイスを
いただけないでしょうか。
宜しくお願いします。

No. 4426 # shin1 2005/12/16 (金) 00:33:37
こんばんは。初めて質問させていただきます。
AIXのサーバ上で「各レコードに改行コードが付いておらずファイルの最後に
EOF(0a00)だけが付いているファイル」を2個連結したいのですが、
単純にcatで連結すると、2つのファイルのレコードの間に(0a)が入ってしまいます。
(例)
ファイル1→  xxxx0a00
ファイル2→  yyyy0a00   の場合
cat ファイル1 ファイル2 > ファイル3 とすると
ファイル3→  xxxx0ayyyy0a00  となってしまうが、実は以下のようにしたい

ファイル3→  xxxxyyyy0a00

シェルまたはコマンドを用いて(C言語でプログラミングしない)で、
簡単に上記の形でファイルを連結する方法がありましたら教えて頂けないでしょうか?
よろしくお願いします。

No. 4427 # 68user 2005/12/16 (金) 01:53:00
>>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 とか
を使えばできるのではないかと思います。

No. 4428 # kevin 2005/12/16 (金) 17:37:44
教えてください。DOSのコマンドで、チェックサムを自動で
計算するコマンドはあるのでしょうか?
例)JX12345-04のチェックサム(E0)を知りたい場合

No. 4429 # tamama 2005/12/17 (土) 17:53:52
こんにちは、初めて質問させていただきます。
こちらに載っているOpenSSLを用いたRSA暗号を動かして見たいので、
Windows上でのOpenSSLのインストールの仕方を教えてもらえませんか。
OSはXPでVisual C++.NETを使っています。

No. 4430 # tamama 2005/12/18 (日) 14:10:38
お騒がせしました。
自己解決しました。

No. 4431 # まっちゅう@ペガサス流星拳 2005/12/21 (水) 14:11:13
こんにちは!!
HP-UNIXなんですが、どなたか教えてください。
lsコマンドのタイムスタンプを常に西暦を表示するようにしたいのですが
そのままls -l では直近6ヵ月未満までは西暦がでません。
該当するオプションがあるのでしょうか?
ちなみに-Tはだめでした。
よろしくお願いします。

No. 4432 # 68user 2005/12/22 (木) 13:15:43
>>4431 まっちゅう@ペガサス流星拳
HP-UX 標準の ls では無理だと思います。代案としては、
    - tar cf - ファイル | tar tvf -
    - sed で置換
    - perl などを使う
など。

No. 4433 # fan 2005/12/22 (木) 15:05:38
ありがとうございます。
運良くFinishedメッセージは解決できました。
その次のAppricationDataの暗号化で質問があるのですが、
SSLCompressedが良く分からないです。
もし、ご存知なら、教えていただけないでしょうか。
お願いします。お願いします。

No. 4434 # まっちゅう@ペガサス流星拳 2005/12/22 (木) 17:23:10
やっぱり無理ですか。。。。
代案までありがとうございました。

No. 4435 # hagu 2005/12/24 (土) 15:23:32
tarコマンドで、コマンドの実行ディレクトリからサブディレクトリも含めて、
ワイルドカードで指定したファイル、例えば、「*.txt」の様に指定して、
すべてのファイルを1つのアーカイブにまとめたいのですが、可能なので
しょうか。
ディレクトリも含めたかたちにしたいのですが。

tar -cvf aaa.tar *.txt だと、直下のファイルのみ
tar -cvf aaa.tar *.* だと、すべてのファイル

No. 4436 # zsh 2005/12/24 (土) 22:29:16
>>4435 hagu
いくつか方法はあると思いますが、
$ find . -name "*.txt" | xargs tar cvf outfile.tar
等とすればできます。

No. 4437 # hagu 2005/12/24 (土) 23:07:40
>> 4436

ありがとうございます。
試してみます。

No. 4438 # 68user 2005/12/25 (日) 22:17:24
>>4436 zsh
Solaris の xargs (だったような気がしますが) は、LINE_MAX の長さがかなり
短くて、たしか 10KB 程度しかなかったような気がします。この使い方だと
複数回 tar コマンドが実行された場合、最後の方しかアーカイブに含まれない
ので注意が必要です。

No. 4439 # DNS勉強中 2005/12/26 (月) 00:16:19
>>4408 68user
亀レスすいません。
DNS のプログラミングのアドバイスをしていただいたものです。
出張先の住まいがレオパレスでネット環境があると聞いていたので、
すぐに閲覧できると思いましたが、いろいろ問題があり今までかかりました。
今後は普通に対応できると思います。
よろしくお願いします。

No. 4440 # zsh 2005/12/26 (月) 10:44:00
>>4438 68user
ご指摘ありがとうございます。
確かに複数回実行された場合の考慮が漏れていました。
ちなみに、Solaris の LINE_MAX の値は 2KB のようです。

No. 4441 # hagu 2005/12/26 (月) 11:49:22
>>4438 68user
>>4440 zsh

試して見ました。
ご指摘の通りでした。

標準出力には、すべて出てきましたが、
最後の方しかアーカイブに含まれていませんでした。

どう対応すればよいのですか。

No. 4442 # とーりすがり 2005/12/26 (月) 22:08:58
>>4441 hagu

カナリ遅いですが.

cat /dev/null>outfile.tar && find . -name "*.txt" | while read F in; do tar rvf outfile.tar "$F"; done

No. 4443 # 不明5号 2005/12/26 (月) 22:55:20
サーバーアドレスの見方はどうすれば??教えてください!

No. 4444 # zsh 2005/12/26 (月) 23:37:46
>>4441 hagu
試してませんが、
$ find . -name "*.txt" | xargs tar rvf outfile.tar
でいけると思います。
(tar は r を指定すると追記になります。)

No. 4445 # 68user 2005/12/27 (火) 00:30:52
>>4439 DNS勉強中
宣言した「今月中」もあと残すところ 6日。一度言ったことは守れよ、と
自分にプレッシャーをかける毎日です。

>>4441 hagu
その他。
    - tar cf outfile.tar `find . -name "*.txt"`
        (長すぎると Argument list too long になるが、エラーかどうかがはっきり
          わかるので使えなくもない)
    - tar の、ファイル名一覧をファイルから取得するオプションを使う。

>>4443 不明5号
質問の意味がわかりません。

No. 4446 # 2005/12/28 (水) 00:16:05
>>4445 68user
>>4444 zsh

ありがとうございます。
試してみます。

>tar の、ファイル名一覧をファイルから取得するオプションを使う。
探して見たのですが、使い方がわかりませんでした。
使い方教えてください。

No. 4447 # hagu 2005/12/28 (水) 00:17:47
>>4445 68user
>>4444 zsh

ゴミすみません。
名前のところに”お”が入ったままで書いてしまった。

ありがとうございます。
試してみます。

>tar の、ファイル名一覧をファイルから取得するオプションを使う。
探して見たのですが、使い方がわかりませんでした。
使い方教えてください。

No. 4448 # 68user 2005/12/28 (水) 03:44:29
>>4447 hagu
http://x68000.q-e-d.net/~68user/cgi-bin/wwwboard.cgi?howtouse にあるように、
OS 名を明らかにすれば期待する回答が返ってくる可能性が高まると思われます。

No. 4449 # hagu 2005/12/29 (木) 09:27:24
>>4448 68user

すみません。
UNIXで、Solaris8 です。

No. 4450 # zsh 2005/12/29 (木) 11:07:56
>>4449 hagu
man tar で出てきますが・・・
http://docs.sun.com/app/docs/doc/816-3518/6m9ptvr58?l=ja&a=view

No. 4451 # 68user 2005/12/29 (木) 13:06:57
>>4449 hagu
具体的には
    % find . -name "*.txt" > filelist.txt
    % tar cf outfile.tar -I filelist.txt
てな感じで。手元に Solaris がないので動くかどうかはわかりません。

No. 4452 # 68user 2005/12/31 (土) 18:25:28
>>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 を書くのがダルい、というデメリットもありますね。

No. 4453 # DNS勉強中 2005/12/31 (土) 23:36:08
>>4452 68user
すいません。
アップロードしなおしました。
http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1374.zip
ただこれは1関数1ソースバージョンです。
今出張先でこのソースバージョンしか持っていないです。
それと1関数1ソースのデメリット分かりました。
特にMakefileは書いてて同じ事を感じてました。

No. 4454 # DNS勉強中 2005/12/31 (土) 23:56:31
一応1ソースバージョンもアップロードしました。
http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1375.zip
ただこれは学校に提出したバージョンのため、>>4453のソースの1つ前のバージョンのソースとなります。

No. 4455 # 68user 2006/01/09 (月) 05:54:07
>>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ヶ月以上引っ張ってしまったわりに、たいしたレビューができませんで
申し訳ないです。

Prev< No. 4375〜4455> Next  [最新発言に戻る] [過去ログ一覧]