2007年9月24日月曜日

CD-Plamoをカスタマイズしてみる



いろいろな都合でCDから起動する環境が必要になりました。


そこで、いつも使っているPlamoLinuxをベースにしたCD-Plamoを使うことにしました。


Knoppixとかも使ってみたんですが、やっぱり少し豪華すぎる気がしちゃいました。


ということで、CD-Plamoを使っていたんですが、いろいろいじりたくなったので、なんとなくでいじってみました。





●準備


contribからmkisosfをインストールしておく。それとディレクトリを圧縮する必要があるので、mkzftreeコマンドをインストールしておきます。


mkzftreeコマンドは、zisofsからソースをダウンロードできます。





CDの中味を全てコピーします。


CD-Plamoは、特殊な圧縮方式をつかっているので、Linux上で作業する必要があります。


デバイスをコピーするんでrootで作業します。



/root

|__/work

|__/CDPlamo  (ここにコピーしました)








chroot


chrootというコマンドを利用することで、指定したディレクトリを仮想的に'/'とすることができます。






#cd /root/work


#chroot /CDPlamo /bin/bash






これで/CDPlamoディレクトリを'/'としてbashを起動します。


これ以降は、このbash上で作業を行いますが、このシェルでは、/root/work/CDPlamoが仮想的な'/'になって、これより上に移動できないので、別のコンソールを開いて、そちらでファイルの追加等を行います。(この別のコンソールをzshと表記します)


既存のシステム上のディレクトリを母艦と表記します。





chrootの方と通常のシェルを間違って作業すると大変なことになります。


移動するごとにpwd,ls等で現在位置を確認してください。





●いじったところ


1.不要なアプリの削除


 通常と同じようにpkgtoolを利用して削除できる。


 この時に/dev/nullがないとエラーが出ますので。/devディレクトリを作って、その中に母艦から/dev/nullをコピーしておきます。






zsh


#mkdir /root/work/plamo/dev


#cp -a /dev/null /root/work/plamo/dev (aオプションを忘れない)






2.追加のアプリをインストール


 これも通常と同じようにinstallpkgを利用できる。


 このとき/tmpがないとエラーが出ますのでbashの方で作っておきます。(作らなくてもいけそうです)


 アプリを/usr/local以下に入れるのが主流だと思うんですが、/usr/local以下は存在しません。ので、/usr以下に入れて逃げました。


(自分メモ)


 vim,fluxbox,fluxconf,mpg123


変更等がおわったら、先程作った/tmp,/devディレクトリを削除し、chrootを終了しておきます。exitで終了できます。





3.ホームに置く設定ファイルの追加、変更


 追加したアプリや独自の設定があるアプリの設定ファイルを追加、変更しました。


 zshで、母艦のホームディレクトリからファイルを持ってきたり、bashで普通に編集したりします。


(自分メモ)


/home-----.fluxbox,.w3m,.zshrc,.vimrc,.gvimrc,.mozilla


/usr/sbin-viをrename、vimのシンボルリンクをviでつくる。





4.initrd.gzの変更


 起動したときにram上に展開される、つまり書き込みが可能になる部分は、このinitrd.gzの中に入ってるので、これを展開、マウントして、必要な部分を変更する。


 



zsh


#cd /root/work/plamo/isolinux


#cp initrd.gz ../../


#cd ../../


#ls


initrd.gz plamo/


#gzip -d initrd.gz


#mount -o loop initrd /mnt






これで、initrd.gzが/mntにマウントされ編集可能になります。


ここでは、/etc,/rootで編集が必要な設定ファイルを変更しました。


(自分メモ)


/etc-----hosts,network.conf,passwd(シェルの変更)


/root----.bashrc





変更が終わったらinitrdをアンマウント、圧縮する。






zsh


#umount /mnt


#cd /root/work 


#gzip -9 initrd


#ls


initrd.gz






5.isoイメージを作る


 コピーしたinitrd.gzをもとに戻し、isolinuxディレクトリは、圧縮しないので、ひとつ上にコピーします。


 その後、圧縮して、isoイメージをつくります。






zsh


#cd /root/work/


#ls


initrd.gz plamo/


#mv initrd.gz plamo/isolinux


#cp -ar plamo/isolinux .


#ls


isolinux/ plamo/


#mkzftree plamo/ plamo_cus  (plamoディレクトリを圧縮しplamo_cusを作る


#cp -ar isolinux plamo_cus (isolinuxディレクトリをもどす)


#mkisofs -v -J -R -z -b isolinux/isolinux.bin -c isolinux/boot.cat \


-no-emul-boot -boot-load-size 4 -boot-info-table \


-V CDplamo_cus -o cdplamo_cus.iso plamo_cus


(ブート可能なisoイメージをつくる)


 #ls


cdplamo_cus.iso plamo/ plamo_cus/






完成です!!





ここまで、一週間かかりました。。。





2007年9月16日日曜日

VMware PlayerでCD-Plamoを起動してみる。









参考になるページ


本当に無償で使える「VMware Player」


SynHack(リンクが上手く張れないのでVM/VMware Playerの項目を探してください)








1.VMware Playerをダウンロード


VMwareのダウンロードページ


普通のアプリケーションと同じ様にインストール可能。





2.QEMUをダウンロード


武田俊也さんのページ


アーカイブを解凍する。





3.CD Plamoのisoイメージをダウンロードする。





4.コマンドプロンプトでqemu-img.exeを実行する。


>qemu-img.exe create -f vmdk C:\VMware\plamo\cdplamo.vmdk 10G


vmdkというVMware形式のイメージを作成します。


10Gとサイズを指定していますが、10Gのファイルができるわけではないので、大きめにつくります。





5.plamo.vmxという名前の設定ファイルを作ります。


参考になるページ1にあったのをそのままコピーさせてもらいました。



virtualHW.version = "3"


memsize = "256"


ide0:0.present = "TRUE"


ide0:0.fileName = "filename.vmdk"


ide1:0.present = "TRUE"


ide1:0.fileName = "auto detect"


ide1:0.deviceType = "cdrom-raw"


floppy0.fileName = "A:"


ethernet0.present = "TRUE"


ethernet0.connectionType = "nat"


usb.present = "TRUE"


sound.present = "TRUE"


sound.virtualDev = "es1371"


displayName = "Fedora Core4"


guestOS = "other26xlinux"


nvram = "filename.nvram"


scsi0:0.redo = ""


ethernet0.addressType = "generated"


uuid.location = "56 4d 4a 15 2a 3f 49 70-03 c9 82 f3 02 82 dc 4c"


uuid.bios = "56 4d 4a 15 2a 3f 49 70-03 c9 82 f3 02 82 dc 4c"


ide1:0.autodetect = "TRUE"


ethernet0.generatedAddress = "00:0c:29:82:dc:4c"


ethernet0.generatedAddressOffset = "0"


checkpoint.vmState = "filename.vmss"


tools.remindInstall = "TRUE"


ide0:0.redo = ""






以下の部分を変更しました。



ide0:0.fileName = "cdplamo.vmdk" 先ほど作ったイメージファイル名を指定


ide1:0.fileName = "cdplamo-1.37.iso" CD Plamoのイソイメージファイル名を指定


ide1:0.deviceType = "cdrom-image"


displayName = "CDPlamo" 適当な名前


nvram = "cdplamo.nvram" 適当にvmdkのファイル名に合わせておきました


checkpoint.vmState = "cdplamo.vmss" 適当にvmdkのファイル名に合わせておきました






6.vmxファイルを実行するとVMware Playerが立ち上がって、CD Plamoが起動します。





マシンがしょぼいのかすごく重かったです。メモリ1.5Gも積んでるのに、まだ少ないのかなぁ







Vector - Website Explorer


Webサイトを階層的に表示してくれる。保存したりもできるみたい。


後でつかってみる。


どなたかの日記で紹介されていました。





2007年9月9日日曜日

UDP版echoサーバ







#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>


#define MAX 255

void exitWithError(char *message);


int main(int argc,char *argv[])
{
int sock;
struct sockaddr_in echoServAddr;
struct sockaddr_in echoCliAddr;
unsigned int cliAddrLen;
char echoBuffer[MAX];
unsigned short echoServPort;
int recvMsgSize;


if(argc != 2){
fprintf(stderr,"Usage %s <Port>\n,argv[0]");
exit (1);
}

echoServPort = atoi(argv[1]);


if((sock = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
exitWithError("socket() error\n");


memset(&echoServAddr,0,sizeof(echoServAddr));
echoServAddr.sin_family = AF_INET;
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
echoServAddr.sin_port = htons(echoServPort);


if(bind(sock,(struct sockaddr *)&echoServAddr,sizeof(echoServAddr)) < 0)
exitWithError("bind() error\n");


for(;;)
{
cliAddrLen = sizeof(echoCliAddr);

if((recvMsgSize = recvfrom(sock,echoBuffer,MAX,0,(struct sockaddr *)&echoCliAddr,&cliAddrLen)) < 0)
exitWithError("recvfrom() error\n");


printf("Handling: %s\n",inet_ntoa(echoCliAddr.sin_addr));

if(sendto(sock,echoBuffer,recvMsgSize,0,(struct sockaddr *)&echoCliAddr,sizeof(echoCliAddr)) != recvMsgSize)
exitWithError("sendto() bytes error\n");

}

}

void exitWithError(char *message)
{
printf("%s\n",message);
exit(1);
}





2007年9月7日金曜日

UDP版echoクライアント







#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

#define MAX 255

void exitWithError(char *message);

int main(int argc,char *argv[])
{
int sock;
struct sockaddr_in servAddr;
struct sockaddr_in fromAddr;
unsigned short servPort;
unsigned int fromSize;
char *echoString;
char *servIP;
char echoBuffer[MAX+1];
int echoStringLen;
int recvStringLen;



if(argc < 3){
fprintf(stderr,"Usage: %s <ServIP> <Word> [<Serv Port>]\n",argv[0]);
exit (1);
}

echoString = argv[2];
servIP = argv[1];


if((echoStringLen = strlen(echoString)) > MAX)
exitWithError("word is too long\n");


if(argc == 4)
servPort = atoi(argv[3]);
else
servPort = 7;


if((sock = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
exitWithError("sockt() error\n");

memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(servIP);
servAddr.sin_port = htons(servPort);


if(sendto(sock,echoString,echoStringLen,0,(struct sockaddr *) &servAddr,sizeof(servAddr)) != echoStringLen)
exitWithError("sendto() error\n");


fromSize = sizeof(fromAddr);


if((recvStringLen = recvfrom(sock,echoBuffer,MAX,0,(struct sockaddr *) &fromAddr,&fromSize)) != echoStringLen)
exitWithError("recvfrom() error\n");


if(servAddr.sin_addr.s_addr != fromAddr.sin_addr.s_addr)
{
fprintf(stderr,"recv from unkown host\n");
exit (1);
}

echoBuffer[recvStringLen] = '\0';
printf("Received: %s\n",echoBuffer);

close(sock);

return 0;
}

void exitWithError(char *message)
{
printf("%s\n",message);
exit (1);
}



コンパイルも通って実行もできるのに、なぜかエコーされてこないと思ったら


udpのエコーサーバが動いてませんでした。。。。


それで1時間ぐらい悩んでしまいました。





2007年9月4日火曜日

daytimeクライアント




#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include<netdb.h>


#define RCVSIZE 1024

void exitError(char *message);


int main(int argc,char *argv[])
{
int sock;
char buffer[RCVSIZE];
char *servIP;
struct sockaddr_in sockaddr;
int bytes=0;

if(argc < 1)
{
fprintf(stderr,"Usage %s <servIP>\n",argv[0]);
exit (1);
}


servIP = argv[1];


if((sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0)
exitError("socket() error\n");


memset(&sockaddr,0,sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = inet_addr(servIP);
sockaddr.sin_port = htons(13);


if(connect(sock,(struct sockaddr *) &sockaddr,sizeof(sockaddr)) < 0)
exitError("connect error\n");

while(recv(sock,buffer,RCVSIZE,0) >= 1)
{
printf("%s",buffer);
}

close(sock);
}


void exitError(char *message)
{
printf("%s\n",message);
exit (1);
}





2007年9月3日月曜日

これまでのまとめ






クライアントの方は、



  • 1.socket()でソケットを作成する。

  • 2.connect()でサーバへ接続する。

  • 3.send()で送信、recv()で受信する。

  • 4.close()で接続を切断し、ソケットを破棄する。



サーバの方は、



  • 1.socket()でソケットを作成する。

  • 2.bind()でソケットにポート番号を割り当てる。

  • 3.listen()でソケットを接続待ちにする。

  • 4.accept()を呼び出してソケットを新しくつくる。

  • 5.recv()で受信、send()で送信する。

  • 6.close()で接続を切断、新しく作ったソケットを破棄する。






ソケット関連の関数のメモ3



CPUのバイトオーダの関係で送受信したバイトの順序がおかしくなるので、


送信する順序を統一する必要がある。そのために、送信前に変換する。





long int htonl(long int hostLong)


short int htons(short int hostShort)


ホストのバイトオーダからネットワークバイトオーダに変換する。





long int ntohl(long int netLong)


short int ntohs(short int netShort)


ホストのバイトオーダからネットワークバイトオーダに変換する。