>> 4299 ありがとうございます。 確認してみます。 |
>>4299 has ありがとうございます。 期待していた結果が得られました。 commというコマンドがあるのですね。 知りませんでした。 勉強になりました。 |
突然すみません。私は、いま卒業研究で動画像を処理しようとしてるものです。bmpファイルからppmやpgmへの一括変換はできたのですが、それらが生(raw)なので、つまりP6なので処理に困ってます。P3にしたいのですが大量のPPM、PGMをまとめてASCIIに変換することは可能でしょうか?よろしければ教えていただけると助かります。 |
>>4302 tana 試してませんが、ppmtogif して giftoppm で戻すとか。 |
giftoppmって一度に多数のファイルを変換できますか? |
>>4304 tana 知りませんが、もしできないとしても for i in *.ppm; do ppmtogif < $i | giftoppm > out/$i; done とか、 ls *.gif | sed 's/\(.*\)/ppmtogif < \1 | gitoppm > out\/\1/' | sh とか。 拡張子は適当に変更するということで。 |
blog なるものを始めてみました。 http://68user.blog27.fc2.com/ 入力が非常に面倒なのですが (HTML 手打ちと変わらない)、世の人たちは 使いこなしているんですかねぇ…。 |
日記を書く習慣の無い僕にとっては、blogを使う利点が未だに理解できないです。 もし、68userさんの視点でその利点を見出せたら、是非とも教えていただきたく、 宜しくお願いいたします。 追伸 FreeBSDでの活動は、今でもされているのですか? |
>>4307 へにか 技術的なことは、最終的に web にまとめたいと思っています。しかしそれを 行うにはある程度の時間と労力がかかります。よって、とりあえず殴り書きを するネタ帳として blog を活用できないかと考えました。 また、 http://x68000.q-e-d.net/~68user/cgi-bin/wwwboard.cgi?log=4061 http://x68000.q-e-d.net/~68user/cgi-bin/wwwboard.cgi?log=3774 のような、ひとつのコンテンツとしてまとめづらいメモを書く場所として 適切ではないだろうか、と思っています。 それと、コメントやトラックバックという仕組みがあるため、web よりは フィードバックが得られるのではないかと。 しかし、perl+DBI のネタを書いてみてわかったのですが、わたしは完璧主義者 なので、結局はエディタで下書き・推敲しないと気がすまないようです。あまり blog 向きではないのかもしれません。 あとこれは愚痴ですが、入力が非常に面倒です。まず、WRAP="OFF" 属性が付いて いない TEXTAREA 要素の相手をすることが苦痛です。 また、ソースを張る際に <PRE>〜</PRE> で囲んでみましたが、行間に変な間が 空いてしまい、結局スペースを に置換して張っていたりします。 「blog は更新が簡単」と世の人は言いますが、fc2 に限れば嘘です。 > FreeBSDでの活動は、今でもされているのですか? 最近はしていませんが、するべき立場にあります。すべてはモチベーションの 問題です。 |
>>4308 68user なるほど。コメントがつけられる掲示板のような使い方+トラックバックですね。 コメント:誰でも簡単に書きやすい。 トラックバック:細かい指摘事項が伝わりやすい。 ってところでしょうか。仕組みとしては、やりたいことに一番近そうに見えますが、 >「blog は更新が簡単」と世の人は言いますが、fc2 に限れば嘘です。 恐らく、今流行っているタイプのblogの使用目的に合致していない、と思います。 ・・・と言いつつ、実はblogを理解して無いので、間違った事を言っているかもしれませんが。 >すべてはモチベーションの問題です それはいえるかもしれませんね。元同僚は、とある部分のソースを書くという 立場にいるそうですが、結構(手続きが?)大変だ、といってましたし。 自分の時間がとれて、収入に余裕があって、FreeBSDに絶対に貢献したいという 意思が無ければ、なかなか腰が上がらないのだと、勝手ながら推測しております。 |
突然ですみません、UNIX初心者です。 UNIXにて以下の様な事がしたいのですが、よい方法があれば教えて下さい。 随時追加されるあるファイル(aaa.txt)の内容を行単位ででCプログラムで読込みたい。 条件) 1.aaa.txtは行単位に随時追加される。 2.Cプログラムに渡すのはある文字が含まれる行のみ。 以下の様なことを試したのですが、うまくいきませんでした。 tail -f aaa.txt | grep ABC | Cプログラム ※Cプログラムは今の所、標準入力(gets)から読み込むだけのプログラムです。 |
>>4309 へにか > なるほど。コメントがつけられる掲示板のような使い方+トラックバックですね。 そうですね。ただ、コメントやトラックバックより、思いついたことを すぐに書くための場所、という方がわたしにとっては重要かなと思っています。 > 恐らく、今流行っているタイプのblogの使用目的に合致していない、と思います。 いや、ただインタフェースがイマイチなだけだと思います。空白を に 変換してくれればそれで解決する話ですから。 >>4310 UNIX初心者 こちらを。 http://x68000.q-e-d.net/~68user/cgi-bin/wwwboard.cgi?log=2800 |
>tail -f log | perl -ne '$|=1;print if m/foo/' >> log2 で試してみたのですが、perlがインストールされていない為、エラーとなってしまいました。 今回は急ぐので、プログラムで対応してしまいました。 また、利用させて下さい、ありがとうございました。 |
>>4312 UNIX初心者 解決したとのことなので返信不要ですが、perl がないなら % tail -f aaa.txt | awk '/ABC/{print;system("")}' | Cプログラム ですかね。FreeBSD 5.2.1-RELEASE ではうまくいきました。 |
Solaris8のBシェルで、CSV形式のデータのソートを行っています。 数字順にソートしたいのですが、ソート対象の列が半角英数のため 数字順になりません。うまい方法はないでしょうか。 英字が先頭にある場合は、英字を取り除いて数字順にしたいのです。 うまい方法はないでしょうか。 sortコマンドだけでは、だめでした。 --データ 山本 こうたろう,企画,100 山下 大介,企画,A101 山田 太郎,営業,80 山田 花子,営業,A92 山田 一郎,営業,A82 鈴木 一郎,販売,85 鈴木 一郎,海外,1001 松井 英樹,海外,2001 斉藤 次郎,製造,125 佐藤 三郎,組立,A124 武藤 五郎,検査,130 --結果 山田 太郎,営業,80 山田 一郎,営業,A82 鈴木 一郎,販売,85 山田 花子,営業,A92 山本 こうたろう,企画,100 山下 大介,企画,A101 佐藤 三郎,組立,A124 斉藤 次郎,製造,125 武藤 五郎,検査,130 鈴木 一郎,海外,1001 松井 英樹,海外,2001 sortコマンドの「-n」を付けてやってみたのですが、数値として判断するため 上手くできません。 また、付けないと、数値順に並んでくれません。 |
>>4314 hagu 訂正です。 名前の前に社員IDがあり、 半角英数字でソートし、社員IDでソートとなります。 データは、「社員ID、名前、仕事、コード」 コードの半角英数字で数字順に並び替えで、 コードが同じな場合は、社員IDで並び替えです。 英字が先頭にある場合は、英字を取り除いて数字順にしたいのです。 No.4314の結果にしたいのです。 |
>>4314 hagu 101 と A101 という社員 ID が存在する可能性があるか、存在するならソート順は どうするかという仕様が不明確ですが、それは置いておくとして。 > 山本 こうたろう,企画,100 > 山下 大介,企画,A101 > 山田 太郎,営業,80 > 山田 花子,営業,A92 わたしなら一度 sed などで 山本 こうたろう,企画,,100 山下 大介,企画,A,101 山田 太郎,営業,,80 山田 花子,営業,A,92 と別項目にし、sort して、再度 sed で元に戻します。 |
>>4316 68user ありがとうございます。 一度、コードの値を分解しには、気がつきませんでした。 いいかも知れません。 >101 と A101 という社員 ID が存在する可能性があるか、存在するならソート順は >どうするかという仕様が不明確ですが、それは置いておくとして。 コードでソートした後、同じコードないで、社員IDをソートします。 ただし、数字のコードは、数字のコード内で、 英字付きのコードは、英字付きコード内で、 社員IDを並びかえます。 |
お世話になります。 C言語でHTTPクライアントを作成しています。ここのサイトもありますが、自作で行いました。 AのHPを取得してうまく表示されますが、BのHPを取得すると、表示されません。 取得したページのヘッダ情報はどっちも異常はありませんでした。 デバックではどっちでも表示されます。でも、BのHPが取得しても表示されません。 何か助言をして頂けたら幸いです。よろしくお願い致します。 |
>>4318 匿名希望 - 現象が再現する最小限まで削ったソースを提示してください。 - A と B の URL を提示してください。 - そちらで実行した結果を提示してください (ヘッダ情報とかデバッグを含む全部) - OS・コンパイラなどの情報を提示してください。 なお、UNIX 以外であれば、わたしはコンパイル環境がないのでわかりません。 |
初めて投稿します。 自分はSSLを組み込もうとしていろいろ調べているんですが、 調べていると、WindowsでのSSLの設置方法がかかれてないんです。 やっっぱりリナックスで設置したほうがいいのでしょうか? |
>>4320 SSL初心者 まずは検索を。 http://www.google.co.jp/search?q=windows+apache2+ssl&hl=ja&lr=lang_ja&ie=utf-8&oe=utf-8 |
お世話になります。 「マッケーブの循環的複雑度」を出力するツールを探しており、 当ホームページから コマンドcccc(C言語・C++・Java のソース コードのステップ数を調べるツール。)を探し当てました。 ところが、身近にあるサーバで試してみると、 $ cccc hoge.java -bash: cccc: command not found と出力されます。 コマンドccccを実行するための条件等、ありますでしょうか。 ご教示、よろしくお願いします。 |
初めまして。 『UNIXの部屋』の localtime(3) のサンプルコードにある tm_timeの一連の変数参照が間違っています。 |
>> 4322 http://x68000.q-e-d.net/~68user/unix/pickup?Command+not+found 2 又は 6 では無かろうか. |
サーバーの件でメールをお送りしました |
すみません。SSLをWindowsで設定しているんですが、 Apacheのインストールで下記のエラーが出ます。 (OS 10048)通常、各ソケット アドレスに対してプロトコル、ネットワーク アドレス、 たはポートのどれか 1 つ のみを使用できます。 : make_sock: could not bind to dress 0.0.0.0:80 no listening sockets available, shutting down Unable to open logs これは、どういった意味のエラーなのかさっぱりわかりません。 自分で調べてもどの方面から調べるのかわからずじまいで投稿しました。 環境は以下のとうりです。 OS - Windows98 Apache - Apache_2.0.55-Openssl_0.9.8a-Win32をダウンロード OpenSSL - Win32OpenSSL-v0.9.8を使用 参考HP - www.rinzo2.jp/~rinzo/apache_ssl/apache_and_ssl_00.htm ご意見お待ちしております |
シェル内にて以下の記述を入れるとエラーが発生します。 ■エラー発生箇所 cat ./temp.txt | awk 'BEGIN{FS=","}{if(match($1,"^${_XXX_}")!=0){print $0}}' > ./test.csv ■出力エラー awk: There is a regular expression error. ?, *, or + not preceded by valid regular expression The source line number is 1. The error context is >>> BEGIN{FS=","}{if(match($1,"^${_XXX_}") <<< "^${_XXX_}"の部分がエラーとなっているようですがここでは変数は使用できないのでしょうか? |
>>4326 SSL初心者 「OS 10048」で検索した結果の 1番目に出てくるのがおそらく答えです。 http://www.google.co.jp/search?q=OS+10048&start=0&start=0&hl=ja&lr=lang_ja >>4327 awk初体験。 ウチの環境ではエラーにならないのでよくわかりませんが、 ${_XXX_} って変数のつもりで書いてるんですよね? どこで ${_XXX_} に値をセット しているのですか? もしシェルスクリプトでシェル変数や環境変数にセットしているのなら、 引数全体を '' で囲んでいるので置換されません。というわけで cat ./temp.txt | awk 'BEGIN{FS=","}{if(match($1,"^'${_XXX_}'")!=0){print $0}}' > ./test.csv などと ${_XXX_} を外に出します。 |
>>4323 ミケフォ > 『UNIXの部屋』の localtime(3) のサンプルコードにある > tm_timeの一連の変数参照が間違っています。 ありがとうございます。bugid 18 として登録しました。 http://x68000.q-e-d.net/~68user/bugnote/viewbug.php?projectid=1&bugid=18 # 登録する暇があるなら、さっさと直せと。 |
すみません,昨日18時頃から本日11時まで サーバーの通信が切れていました. 昨日13時頃に回線工事があって無事完了したのですが, 終端装置の接続が雑だったらしく,17時頃に突然接続が落ちました. すぐ業者に連絡したのですが既に営業時間外で, 朝まで修理を呼べませんでした. 本日11時に業者が来て直りました. ご報告まで. |
お世話になります。 C言語でHTTPクライアントを作成してますが、HTTPSの場合のポート番号が サイトを探しても見つからないですが、ご存知でしょうか? よろしくお願い致します。 |
>>4330 Netboy 対処いただきありがとうございます。IP アドレスの件はもう少々お待ちください。 >>4331 キック 「https ポート番号」で検索したら一番最初に出てきます。 http://www.google.co.jp/search?q=https+%E3%83%9D%E3%83%BC%E3%83%88%E7%95%AA%E5%8F%B7&hl=ja&lr=lang_ja |
>>4332 68user ありがとうございます。 初歩的ですみません(^ ^;)> |
シェルで、ftpを自動で実行しています。 ftpの接続、ログインの判定や、ファイルのput/getの判定 ができたか判断したいのですが、できるのでしょうか。 エラーが発生したら、「exit 1;」などで終了させて、その ステータスを判断するといったことはできないのでしょうか。 ----------------- ftp -v -n ${SERVER} <<END >/dev/null user ${FTP_USER_ID} ${FTP_PASSWORD} cd ${FTP_DIRECTORY} lcd ${LOCAL_DIRECTORY} get ${GET_FILE} bye END 環境: Solaris8i Bシェル |
No. 4327 で質問させていただきました。 変数はシェル内で実行していました。 そのため""で括った所上手くいきました。 ご回答ありがとうございます。 さらに別の質問させてください。 カンマ及びスラッシュを区切り文字としたいのですが… -FオプションやFS=の指定で複数の区切り文字を指定することはできるのでしょうか? |
>>4335 awk初体験。 区切り文字に正規表現を使用できるawkであれば可能です。 (gawkやnawkなら使用可能ですが、Solaris標準のawk等では使用できません。) $ nawk -F"[,/]" '{ .... }' file $ nawk 'BEGIN{ FS="[,/]" } { .... }' file |
2005/10/29(金) 00:00:00 ごろから IP アドレスの変更・それに伴う DNS 設定変更を 行いました。Refresh とか Retry とか Expire などを理解していないので、何も対策 せずいきなり切り替えました。そのせいで つながらなかった人もいると思いますが、 ご迷惑をおかけしました (わたしも数時間つながらなかった)。 ご協力ありがとうございました>Netboy さん >>4323 ミケフォ 遅くなりましたが、修正しました。 ご指摘ありがとうございました。 # http://x68000.q-e-d.net/~68user/bugnote/viewbug.php?projectid=1&bugid=18 >>4334 hagu わたしなら Perl の Net::FTP モジュールなどできっちりエラーチェックしますが、 どうしても ftp コマンドを使わざるをえないなら、 - ftp コマンドに -d オプションなどをつけて実行結果のログをとる。最後に ログを解析してステータスコードに 4xx 系・5xx 系 がないことをチェックする。 - 接続した時点でリモートに同名のファイル名がないならば、get/put を行って、 最後に ls して、結果をログに保存する。ls の結果を解析し、ファイル一覧・ ファイルサイズ・ファイル個数などのチェックを行う。 くらいしかないような気がします。 |
>>4337 68user > 2005/10/29(金) 00:00:00 ごろから 2005/10/29(土) 00:00:00 の誤りでした。 |
A君とB君(ユーザーIDはそれぞれAとB)は同じグループG(グループIDはG)に属しているとします。 A君は、自分のホームディレクトリ(~A)にあるディレクトリDの中の全てのファイルを、B君など同じ グループに属する人にだけ閲覧可能にしたいと考えました。ただし、A君はディレクトリD以外の ファイル・ディレクトリは(それらのリストを取る(lsコマンド)ことも許可したくありません。 A君はどのようなパーミッションを設定すればよいでしょうか? |
>>4339 TKG ~A/ 710 ~A/D/ 750 ~A/X/ (D 以外) 700 でしょうか。 |
Solarisでシェルスクリプトを起動する場合。 $ csh script.cshと入力しなければなりませんが、 最初のcsh を省略して$ script.cshで起動する方法を教えて下さい。 宜しくお願いします。 |
> 68user様 http://x68000.q-e-d.net/~68user/unix/genre.html#genre22 にheadが二つ表示されています。 >>4341 誠 UNIXの部屋を読めば判ると思いますが・・・ 1.スクリプトの一行目にシェルのパスを指定する。 2.環境変数PATHを設定する。 3.スクリプトに実行権をつける。 といったところでしょうか。 http://x68000.q-e-d.net/~68user/unix/pickup?Command+not+found |
>> 誠さん 4342 で言われている PATH の設定は csh が置かれている場所にパスを通すって 意味であって、PATH に "."(カレントディレクトリ) を加えるって話では無い筈です。 従って、 単に script.csh ではなく ./script.csh って起動方法になると思います。 PATH に "." を加える事の問題とか、csh スクリプトを覚えるよりも sh 系の スクリプトを覚えた方が良いって話は検索すれば出てきますので読んでみましょう。 |
>>4343 hoge スクリプト専用のの格納ディレクトリがあるのかと思い PATHの設定が必要と書きました。 ・・・・ちょっと意地悪したくなったのも事実ですが。 |
>>4337 68user 返事が遅くなって申し訳ありません。 アドバイスありがとうございます。 ログに出力し、ログをチェックする方法でやってみます。 |
sedを使用して大文字から小文字に変換したいのですが、 なかなか上手くいきません。 例えば、「YAMADA」を「Yamada」と先頭の1文字目は大文字で、 2文字目以降を小文字に変換したいのですが、以下の様にsed を使ってやったのですが上手く行きません。 sedでは、無理なのでしょうか。 環境は、Solaris8、Bシェルです。 ---------------------- NM=Ya1AMADA echo $NM | sed 's/[A-Z].*/[a-z]/g' NM=YAMADA echo $NM | sed 's/\(.\)[A-Z]*/\1/g' |
>>4346 hagu 多分、sedだけでは無理だと思います。 sedを使わなくても、awkだけでも可能です。 echo $NM | nawk '{for(j=i=1;i<=length($0); i++) if(i==1) {NM[i]=substr($0,i,1)} else {NM[i]=tolower(substr($0,i,1))}} END{for(count in NM) printf("%c",NM[count]); printf("\n")}' |
>>4347 お 試してみましたが、出方が変です。 amadaY となります。 |
始めまして、ネットワークプログラミング周辺読ませて頂きました。 簡潔なソースで読みやすかったです。 お礼に掲示板カキコ、それにしてもみなさん勉強熱心ですね(笑 ---------------------------------------- echo $NM | \ sed -e h -e 's/^\(.\)\(.*\)/\1/g' \ -e 'y/[abcdefghijklmnopqrstuvwxyz]/[ABCDEFGHIJKLMNOPQRSTUVWXYZ]/' \ -e x \ -e 's/^.\(.\)/\1/g' \ -e 'y/[ABCDEFGHIJKLMNOPQRSTUVWXYZ]/[abcdefghijklmnopqrstuvwxyz]/' \ -e H \ -e g \ -e 's/\n//' ---------------------------------------- なんとなしsedの勉強してしまった、本買う気にはならないけどね。 http://web.archive.org/web/19961202111128/http://yase.yajima.kuis.kyoto-u.ac.jp/staffs/sengoku/sedlec/ |
>>4346 hagu もしperlならこんな感じなんでしょうか? echo $NM | perl -ple 'y/A-Z/a-z/;substr($_,0,1)=~y/a-z/A-Z/;' |
>>4347 お >>4348 hagu 連想配列の場合、表示の順序は、ハッシュ法に従うのでランダムとなります。 すみません。 echo $NM | nawk '{for(i=1;i<=length($0); i++) if(i==1) {NM[i]=substr($0,i,1)} else {NM[i]=tolower(substr($0,i,1))}} END{for(j=1; j<i; j++) printf("%c",NM[j]); printf("\n")}' |
>>4349 マーブル 凄い。 sedだけでですね。 でも、凄く、複雑すぎます。 >>4351 お 今度は、期待したいた結果が得られました。 awkを使っているのも複雑ですね。 |
>>4352 hagu これじゃだめ? $ echo $NM | nawk '{ a=toupper(substr($0,1,1)); b=tolower(substr($0,2)); printf "%s%s\n",a,b; }' |
>>4353 zsh そうですよね。 substr()で2文字目以降すべてを変換してしまえばいんですよね。 何、ループで1文字ずつ変換し、表示しているんだろう。 |
あまり知られていないscanfの用法。 既出でしたか残念。>>4041>>4042 http://www.linux.or.jp/JM/html/LDP_man-pages/man3/scanf.3.html 以下同意 ------------------------------------- sscanf(host_path,"%[^/]%s",host,path); ------------------------------------- p = strchr(host_path, '/'); if ( p != NULL ){ strcpy(path, p); *p = '\0'; strcpy(host, host_path); } else { strcpy(host, host_path); } ------------------------------------- |
fdopen()で作成されたストリームが閉じられたときにファイル記述子も 閉じられる。 http://www.linux.or.jp/JM/html/LDP_man-pages/man3/fdopen.3.html よって以下のページのL:125は不要です。 http://x68000.q-e-d.net/~68user/net/c-http-2.html |
>>4356 マーブル ありがとうございます。とりあえず POSIX を確認させてください (明日以降)。 http://www.opengroup.org/onlinepubs/009695399/functions/fdopen.html |
>>4357 68user 明日以降と言いつつ今確認してみましたが、POSIX にはそういう記述は ないように見えます。また、Solaris9 のマニュアルにも書いてないように 見えます。 http://www.freebsd.org/cgi/man.cgi?query=fdopen&sektion=3C&manpath=SunOS+5.9 しかし BSD ならば、4.4BSD-Lite2 にはそのような記述があります。 http://www.freebsd.org/cgi/man.cgi?query=fdopen&manpath=4.4BSD+Lite2&format=html Solaris や HP-UX が手元にある方にお願いなのですが、fdclose して fclose した ときにソケットディスクリプタがクローズされるかどうか truss コマンドなどで 確認していただけないでしょうか (わたしのまわりは FreeBSD と Linux しかないので)。 いずれにせよ何かしらの補足は追記したいと考えています。 |
>>4358 68user > fdclose して fclose したときに 「fdopen して fclose したときに」の誤りでした。 ちなみに「UNIX ネットワークプログラミング第2版」からは、この件についての 記述を読み取ることはできませんでした。 |
>>4359 68user 機種依存等深く考えずに書き込んでしまって申し訳ございません。 また知合いに話せる人がいない為に決めつけたような書き込みになってしまったこともお詫びします。 基本的にFILE構造体にfileディスクリプタが含まれているものと理解していたもので、 fclose時に連動してcloseされるかな?と単純に考えてしまいました。 trussで確認した結果が以下でcloseされているようでした(これおもしろいですね) SunOS eibw23 5.9 Generic_112233-03 sun4u sparc SUNW(Solaris8か9) ----------------------------------------------------------- read(0, 0xFF3414EC, 1024) (sleeping...) read(0, "\n", 1024) = 1 llseek(3, 0, SEEK_CUR) = 0 close(3) = 0 read(0, 0xFF3414EC, 1024) (sleeping...) read(0, "\n", 1024) = 1 _exit(0) |
>>4360 マーブル うゎ、アドレス込みで貼っちまった、ハズカシィ |
>>4360 マーブル opensolarisがsolarisとどれだけ違うかわかりませんが、 http://cvs.opensolaris.org/source/xref/on/usr/src/lib/libc/port/stdio/fdopen.c#64 fdの値は単純に渡されているように見えます。 (↑のサイト使い安くて良く使ってます、BSDでこのような感じのページご存知ですか?) |
>>4360 マーブル 昨日は変なことを書いてしまいました。fclose したんだから close するのは 当然ですよね。まぁ fdopen したものはフラッシュだけ行って close しない 実装があっても不思議ではないですが、素直に考えれば close するはず。 よって、125行目の close は削除します。 >>4362 マーブル > (↑のサイト使い安くて良く使ってます、BSDでこのような感じのページご存知ですか?) 普通の cvsweb でよければ、以下のものが cvsgraph が組み込まれているのでよく使います。 http://cvsweb.allbsd.org/cvsweb.cgi/src/lib/libc/stdio/fdopen.c ソース閲覧なら GLOBAL を使ったFreeBSD Source Code Tour が便利ですが、ファイル名が ころころ変わるので URL を保存しておいても役に立たないのがが困りものです。 http://snapshots.jp.freebsd.org/tour/ http://snapshots.jp.freebsd.org/tour/current/userland/cgi-bin/global.cgi?pattern=fdopen&id=&type=definition http://snapshots.jp.freebsd.org/tour/current/userland/S/9687.html#53 OpenSolaris のソースを見られるところは知りませんでした。今後活用させて いただきます。 |
初めましてWindowsユーザですが、仕事上 LinuxやCVSを使うことがあります。 コマンドをなかなか覚えられなくて、いつも参考にさせて頂いています。 |
>>4353 zsh 凄いです。 変換されました。 |
よくパーミッションでrは読む権利を、wは書く権利を、 xは実行する権利を与えるといいますが、それぞれの権利が 与えられている時、いない時は具体的にどのようなコマンド が有効であるのか、いまいちはっきり理解できません。 どなたか詳しくをしえてください。 |
>>4366 anonymous > それぞれの権利が与えられている時、いない時は具体的にどのようなコマンドが > 有効であるのか 何か哲学的なニオイがするので(?)、そもそも私が答えられる内容でも無い気は しますがそれでもよければ教えてください。 ええと、ちょっと見た限りでは書き込み中の「有効」の意味がよくわかりません。 もしかしたら具体的に何か目的があるんでしょうか。 あと、パーミッションが与えられているのはプログラム?読み書きするファイル? |
>>4364 がちゃぴ ありがとうございます。ご意見・ご指摘がありましたら遠慮なくどうぞ。 なお、世の中いろんな人がいますので、文章の一部を削除させていただきました。 削除した部分に関する話題はご遠慮いただきたく思います。ご理解ください。 >>4366 anonymous 紛らわしいのでハンドルを「68user」から「anonymous」と変更しました。 今後は適切なハンドルを使用してください。 |
>>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 サーバに問い合わせを行っている事を視覚的にアピールしつつ、 提出期限が迫っているので、現状のソースをなるべく触らない方向でまとめてみました。 なお学校の課題用は最近取り掛かったこともあり、 完成度は前者に比べかなり劣ってます (実用に耐えれないという意味ではどちらも同じですが)。 |