68user's page 掲示板

Prev< No. 1514〜1530> Next  [最新発言に戻る] [過去ログ一覧]
No. 1514 # taka 2001/01/06 (土) 23:41:56
はじめまして
すいませんが質問です。
vi でヒアドキメントの使い方がわかりません
linuxで試しているのですが
ex/vi: Vi's standard input and output must be a terminal
とエラーになってしまいます。
できないのでしょうか?

No. 1515 # rosegarden 2001/01/07 (日) 00:08:35
>>1514 taka
> vi でヒアドキメントの使い方がわかりません

ex mode なら大丈夫なようです。ただし ex コマンド使わないと
いけませんが。そのまま vi mode で使う方法は分かりません。

#!/bin/sh

( vi -e | sed -e 's/^#/foo: /' ) << 'END'
a
hoge
hoge
hoge hoge
.
1,$s/^/#/
1,$p
q!
END

あとシングルクォートかエスケープ使った方が良いです。
最後の行の $ とシェル変数がバッティングしますから。

No. 1516 # taka 2001/01/07 (日) 01:05:59
有難うございます
以下のシェルで更新できました。

#!/bin/sh
vi -e data001 << 'END'
i
hoge
hoge
hoge hoge
.
wq!
END

ps
レスのつけ方がわかりませんでしたすいません

No. 1517 # 68user 2001/01/07 (日) 02:21:32
>>1510 E田
構造体の受け渡しに関しては、僕の出る幕はなさげですが、
一応まとめておきます。まず、E田さんはポインタの使い方を
学んで下さい。rosegarden さんのソースは
      tes_s.test1 = ((unsigned long *)ptr)[0];
      tes_s.test2 = ((unsigned short *)ptr)[1];
となっていますが、rosegarden さん自身が説明されている通り
これではまずいので
      tes_s.test1 = *(unsigned long *)(ptr);
      tes_s.test2 = *(unsigned short *)(ptr+4);
の方がいいでしょう。わからなければ再度質問してください。

で、それを理解してからやっとバイトオーダの話になります。これは
今回の件では関係ないかもしれない (エンディアンによってたまたま
問題が顕在化していないかもしれない) ので、参考程度にどうぞ。

以下のソースでは配列 data から変数 test1/2/3 に値を代入しようと
しています。

#include <stdio.h>
#include <string.h>

void
my_memcpy(char *dst, char *src, size_t len){
    src += len-1;
    while (len--) *dst++ = *src--;
}

main(){
    unsigned long test1;
    unsigned short test2;
    unsigned short test3;
    char data[] = {0x12,0x34,0x56,0x78,0x0,0x1,0x0,0x2};
    char *ptr = data;

    test1 = *(unsigned long *)(ptr);
    test2 = *(unsigned short *)(ptr+4);
    test3 = *(unsigned short *)(ptr+6);
    printf("普通に代入 0x%x 0x%x 0x%x\n", test1, test2, test3);

    memcpy(&test1, ptr+0, sizeof(test1));
    memcpy(&test2, ptr+4, sizeof(test2));
    memcpy(&test3, ptr+6, sizeof(test3));
    printf("memcpy 0x%x 0x%x 0x%x\n", test1, test2, test3);

    test1 = htonl(*(unsigned long *)(ptr));
    test2 = htons(*(unsigned short *)(ptr+4));
    test3 = htons(*(unsigned short *)(ptr+6));
    printf("hton して代入 0x%x 0x%x 0x%x\n", test1, test2, test3);

    my_memcpy(&test1, ptr+0, sizeof(test1));
    my_memcpy(&test2, ptr+4, sizeof(test2));
    my_memcpy(&test3, ptr+6, sizeof(test3));
    printf("逆順にmemcpy 0x%x 0x%x 0x%x\n", test1, test2, test3);
}

このサンプルでは
    char data[] = {0x12,0x34,0x56,0x78,0x0,0x1,0x0,0x2};
となっていますが、これを適当に切り取って変数に代入すると
順序が狂ってしまいます。実行結果は以下の通り。
    普通に代入 0x78563412 0x100 0x200 (間違い)
    memcpy 0x78563412 0x100 0x200 (間違い)
    hton して代入 0x12345678 0x1 0x2 (正しい)
    逆順にmemcpy 0x12345678 0x1 0x2 (正しい)
前の2つは順序が逆になっています。これはリトルエンディアンマシン
(x86 など) で発生します。ビッグエンディアン (68000, Sparc など)
では起こりません。

後の2つは htons/htonl や自作の my_memcpy でバイト順を置換して
代入しています (もちろん hton を使う方がよい)。

これはソケット経由でデータを送ると、バイト順が狂うという
意味ではありません。エンディアンが異なるマシン間でも、
データは送った順序で届きます。ですから、同じエンディアン
同士でデータを送りあえば問題は顕在化しません。

ただし、
    「異なるエンディアン間で変数の値を直接送信したとき」
は、
    「一方の CPU 内部ではバイト順の交換が行われるのに、
        他方では行われない」
ので、バイト順が狂ってしまいます。ですから、
    「事前にネットワークバイトオーダに変換してから送信」
し、
    「受信側はネットワークバイトオーダと認識して変数に代入する」
のが望ましいということです。

実際のソースで書くと、以下のような感じになります。

    送受信側でバイトオーダが一致していれば OK。異なるなら NG。
        (送信側)
        long send_num=0x12345678L;
        write(socket, &send_num, sizeof(send_num));
        (受信側)
        long recv_num;
        read(socket, &recv_num, sizeof(recv_num));

    バイト列をソケット経由で変数に代入する。受け手側が
    リトルエンディアンなら OK。そうでなければ NG。
        (送信側)
        char buf[]={0x12,0x34,0x56,0x78}; /* 0x12345687 を送りたいとする */
        write(socket, buf, sizeof(buf));
        (受信側)
        long recv_num;
        read(socket, &recv_num, sizeof(recv_num));

    ネットワークバイトオーダで送信。ネットワークバイトオーダを
    ホストバイトオーダにして代入。これが一番よい。
        (送信側)
        long send_num = htonl(0x12345678L);
        write(socket, &send_num, sizeof(send_num));
        (受信側)
        long recv_num;
        char buf[256];
        read(socket, buf, sizeof(recv_num));
        recv_num = ntohl(*(long *)(buf));

なお、ネットワークバイトオーダ=ビッグエンディアンのオーダです。
別に両者で合意が取れていればいいので、リトルエンディアンで
統一したければそれはそれで構いません。

ちなみに X プロトコルでは高速化のため、事前にクライアント・サーバ
間でバイトオーダが異なるかどうかチェックして、
    - 同じバイトオーダならそのままデータを送る
    - 異なるバイトオーダならネットワークバイトオーダに変換してから送る
となっているとか。

ところで
    my_memcpy(void *dst, void *src, size_t len){
とすると gcc に invalid use of void expression と怒られるんですが、
引数を void * で受けるのってできないんでしたっけ?

>>1512 gixs
> Linuxのselect(2)は、戻った時、第5引数の値が残り時間を示して戻ってくる
> (タイムアウトしたら値はゼロになる) ので、waitvalの値の設定はwhile
> ループ内でやる必要があります(manにも書いてあります)。
ご指摘どうもです。その通りですね。ちなみに FreeBSD では
select(2) の BUGS の項で、本来上記のような動作をするべきだが、
現状ではそうなっていない (waitval の値は書き換えられない) と
あります。

>>1513 CoreFighter
> NICにはMACアドレスってのがありますよね。
> モデムやTAにもMACアドレスってあるのでしょうか?
ないです。なぜかっちゅうと NIC は Ethernet の端点だからです。
# なぜ Ethernet だと MAC アドレスが必要で、モデム/TA に
# MAC アドレスが必要ないか…は、うまく説明できないなぁ。
# 誰か教えて下さい。

No. 1518 # taka 2001/01/07 (日) 14:58:23
すいませんがまた質問です。
今度はftp でヒアドキメントの使い方がわかりません
ftp ftp.xxx.xxx.ne.jp << EOF
userid
password
by
EOF
これで実行すると
Password:Name(ftp.xxx.xxx.ne.jp:root):
と聞かれてしまいます。
シェルだけで実行する方法はありませんか?

No. 1519 # 68user 2001/01/07 (日) 17:43:41
>>1518 taka
> 今度はftp でヒアドキメントの使い方がわかりません
http://X68000.startshop.co.jp/~68user/unix/pickup?ftp
の -n オプションの説明を見て下さい (Linux で使えるかどうかは
わかりませんが)。

No. 1520 # rosegarden 2001/01/07 (日) 22:00:02
>>1487 68user
先日の FreeBSD の crypt(3) のデフォルトについてですが、
暮れから新年にかけてライブラリ関数のレベルで切り替えの
メカニズムが commit されたようです。いまとのところ
5-current でしか使えず、管理権限がないと切り替えられないのですが。
/etc/auth.conf に crypt_default=md5 という設定を入れると perl の
crypt もデフォルトが md5 になるようです。

# 今日 CVSup でソースとって来た人は 20 時以降のソースとって来た方が
# いいです。昼のソースだと pccard 周りのコンパイルが出来ません。
# 今はなおっていますが。

No. 1521 # 68user 2001/01/08 (月) 03:02:15
せっかくなので、
>>1509 68user
のソースを書き直して
    「C 言語で echo サーバを作ってみよう (2)」
    http://X68000.startshop.co.jp/~68user/net/c-echo-2.html
を作ってみました。C言語+select によるタイムアウト機能付き echo サーバです。
# 一応バグは潰したつもり。

あと、これまでご指摘を頂いた
>>1389 Yuuki
の accept のバグ、
>>1215 UNIX見習い
>>1216 68user
の LocalAddr のバグを修正しました。お二人に感謝。

No. 1522 # 68user 2001/01/08 (月) 14:58:03
>>1520 rosegarden
おろ、/etc/login.conf には passwd_format=md5 で、/etc/auth.conf には
crypt_default = md5 des で、libutil で、libcrypt ですか。全然なにが
なんだかわかってませんが、手元にソースがないので調べにくい。MFC を待つか…。

# 軟弱なので、うちは今朝の 4-STABLE です。

No. 1523 # rosegarden 2001/01/08 (月) 20:08:16
>>1522 68user
言葉が足りないようですみません。
4-stable では /etc/login.conf に passwd_format=md5 と明示的に
指定することによって passwd コマンドなどで
使用するハッシュ関数は変更できますが、perl などで使用している
crypt(3) などのハッシュ関数はそのまま des だったりします。
解禁以降、大抵の人はそのまま des 入れているでしょうから。
一方、5-current だと /etc/login.conf でのハッシュ関数の
指定は passwd コマンドでは有効になりますが、それとは別に crypt(3)
のハッシュ関数を /etc/auth.conf で指定できます。
これはさっき CVSup して確かめましたが、4-stable には反映されていません。
http://www.jp.FreeBSD.org/cgi/cvsweb.cgi/src/lib/libcrypt/crypt.c
ソースはここで確かめられます。
CGI で差分も見れます。

> # 軟弱なので、うちは今朝の 4-STABLE です。
いや、あまり関係ないかと思います。去年の暮れに 4-stable が page fault 頻発して
放棄せざるを得ない状態まで追い込まれたことあります。結局
kernel panic 起こしながら、数個ずつ kernel のファイルをコンパイルして、
安定した kernel をインストールし、それで回復させましたが。
同じ時期の 5-current はすごく安定していました。
ハード構成いかんではそういうことも起こり得ます。

No. 1524 # みかん 2001/01/08 (月) 22:48:59
初めまして。
FreeBSD 3.5.1と、それに付属のperlを使っています。
そこでソケットに関するプログラムを組みましたが、ちょっと問題が出てきました。
下記のソースを見てください。
HTTPサーバに接続して、メッセージを受け取り、一定時間何も受信できないと
プログラムを終了しようとしています。
(本当は、相手のサーバからコネクションを切られたら終了するようにしたいんです。)

サーバと接続されいる状態では、selectは期待した値を戻してくれるのですが、
接続が切断されたあとも、selectの戻り値が 0以外で、いつまでたっても、
ループから抜けられません。
なにか解決方法はないでしょうか?

(大抵のサンプルはwhile (<SOCK>) って感じでやってるみたいですが、
    バイナリファイルが対象でもうまくいくのでしょうか?)

## ソケットを開いて、ポート80)に繋ぐ。 ##
send(SOCK,"GET /index.html HTTP1.0\r\n",0);
$rin='';
vec($rin,fileno(SOCK),1)=1;
while (1) {
    $ret = select($rout=$rin,undef,undef,1);
    if ($ret == 0 ) { last; } #タイムアウト
    recv(SOCK,$x,1,0);
    print $x;
}

No. 1525 # 68user 2001/01/08 (月) 22:58:40
>>1524 みかん
ちろっと見た感じでは
    1. \r\n が一個足りません。
    2. 相手側がコネクションを切断したときも select は 1 を返します。
          その際、recv すると1バイトも読めず、0を返しているはずなのに
          無視しているので永遠に終わらないのです。

# http://X68000.startshop.co.jp/~68user/net/echo-4.html

No. 1526 # 68user 2001/01/08 (月) 23:25:51
>>1523 rosegarden
> 言葉が足りないようですみません。
いや、解説を催促するつもりはなかったのですが、恐縮です。
login.conf ということはユーザごとに DES か MD5 を定義
できて、しかも各ユーザは ~/.login_conf で上書き自由、
ということだと思うんですが、それが出来て何がうれしい
んだろう…ってのが疑問なんです。

# NIS 使用時に幸せ?

> 去年の暮れに 4-stable が page fault 頻発して
> 放棄せざるを得ない状態まで追い込まれたことあります。
恐いですねぇ。僕は FreeBSD-stable も流し読みだし、make world で
こけたとき直すスキルもないので、ビクビクしながらやってます。
4-STABLE じゃなくて 4.2-RELEASE にしとけばよかったな。

>>1524 みかん
> 大抵のサンプルはwhile (<SOCK>) って感じでやってるみたいですが、
> バイナリファイルが対象でもうまくいくのでしょうか?
<> は C でいうところの fgets 相当 (+バッファサイズが無限長) なので
うまくいきます。

うまくいきますが、改行コードが1つもないデータを読もうとすると
一度に多くのバッファ (=メモリ) を消費するので、
    sysread(SOCK, $buf, 8192);
    read(SOCK, $buf, 8192);
    while ( read(SOCK, $buf, 8192) ){ print $buf }
などの方がよいです。

ついでに言っておくと、状況にもよりますが、select に
<> や read を使うのは不適切です。select で読み込み
可能だからといって、「改行コードを含むデータ」や
「指定したサイズのデータ」が読み込めるとは限らない
ので (データの前半部分だけが先に到着しているかも
しれない) からです。せっかく select でブロッキングを
回避しているのに、<> や read の部分でブロッキング
してしまうかもしれない。

# ここでいう read は read(2) でなく perl の read (fread(3)) です。

No. 1527 # gixs 2001/01/08 (月) 23:45:36
>>1517 68user
> ところで
> my_memcpy(void *dst, void *src, size_t len){
> とすると gcc に invalid use of void expression と怒られるんですが、
> 引数を void * で受けるのってできないんでしたっけ?

おや?
68userさんにしては珍しい。
# まあ、プログラミング言語って(自然言語も同じようなものですが)、
# ちょっと離れるだけで勘がにぶって、ポカをやらかしてしまいますが。

そのエラーは、引数で受けた部分ではなく、
dst++などの演算のところのエラーですね。

逆に、char*で受けた場合、gcc -Wallのwarningを黙らすために、
(char*)&test1のようなキャストが必要です。
# gccはいつも-Wall。これでポカミスを結構見付けられます。

No. 1528 # rosegarden 2001/01/09 (火) 02:27:54
>>1526 68user
> それが出来て何がうれしい
うーん、それはそうですね。ただ、人によってこだわりは
あるでしょうから。本当の理由は私も良く分かりませんが、
des インストールしても md5 で crypt できるのはやはり
嬉しいです。

No. 1529 # 68user 2001/01/09 (火) 06:52:37
>>1527 gixs
> そのエラーは、引数で受けた部分ではなく、
> dst++などの演算のところのエラーですね
なるほどなるほど。
    void
    my_memcpy(void *dst, char *src, size_t len){
        (char *)src += len-1;
        while (len--){
            *((char *)dst)++ = *((char *)src)--;
        }
    }
てな感じでしょうか。

> おや? 68userさんにしては珍しい。
僕は元々ヘボです。-Wall は付けてますが、いつも warning が出る
ものの、キャストの仕方がわからず、大抵「まぁ動いているからいいや」で
済ましてしまうレベル (^^;

>>1528 rosegarden
> des インストールしても md5 で crypt できるのはやはり
> 嬉しいです。
ちと考えてみましたが、例えば apache+suExec で CGI を動かす
とき、「俺は前の環境で作成したパスワードがあるので DES」
とか「私はセキュリティ重視で MD5」などと、ユーザごとに
DES/MD5 を選べたりする、ってな場合があるかもしれませんね。


全然関係ありませんが、掲示板の使い方
    http://X68000.startshop.co.jp/~68user/cgi-bin/wwwboard.cgi?howtouse
を作りました。上の [使い方] から飛べます。

No. 1530 # みかん 2001/01/09 (火) 17:21:00
こんにちは、UNIX1年生のみかんと申します。

文字列置換のsedコマンドを使って変数の中の文字列を置換して
別の変数に入れたいと考えております。このようなことは可能でしょうか?

sed -e "s/aaa/bbb/g" ${ABC}

ここで変数${ABC} の中に入っている値(例えばaaa)を置換して
変数${CBA}に挿入したいと考えております。

大変に恐縮ですが、ご存知の方がいらっしゃいましたらご教授いただけませんでしょうか。よろしくお願いします。

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