PDA

View Full Version : C/C++のcgi


Ratoku
2001/12/06, 02:09 PM
はじめまして。
質問です。

TurboLinux6.0でコンパイル、確認をしたCGIをアップロードして実行して
みたところ、以下のページが表示されてしまいます。
 http://www.xrea.com/err500.htm

拡張子を.xcgにしているのが原因かと思い.cgiで実行してみたのですが
結果は同じでした。以前、他のCGIはTurboLinuxで動作確認が取れたものはXREAでも問題は発生しません
でした。

想像ですが、
 fp=fopen("../main.html", "r");
の一番目の引数のパスの指定が間違っているか、また、使用できない
標準関数を使用しているとかではないかと思います。
が、原因が特定出来ません。

解決する方法は無いでしょうか?
パーミッションを変更してみた際に、一度は解決したと思ったのですが、
結局だめでした。

以下はそのプログラムのソースです。

---------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define MAXBUF 2048

void Count(char*);

int main(void)
{
FILE *fp;
char buf[MAXBUF];

printf("Content-Type: text/plain\n\n");

fp=fopen("../main.html", "r");

while(fgets(buf, MAXBUF, fp)){
if(strstr(buf, "<!--counter-->")){
Count("count.dat");
}else{
fputs(buf, stdout);
}
}
fclose(fp);
fflush(stdout);

return 0;
}

void Count(char* cntfl)
{
int cnt;
FILE* fp;

fp = fopen(cntfl, "r+");
lockf(fileno(fp), F_LOCK, 0);

if( fscanf( fp, "%d", &cnt ) != 1 ){
if(fp != NULL){
fclose(fp);
}
printf("<FONT size=\"-1\" color=\"#FFFFFF\">あなたは ???????? 番目のお客様です。</FONT>");
return;
}

cnt++;

rewind(fp);
fprintf(fp, "%08d", cnt);

lockf(fileno(fp), F_ULOCK, 0);
fclose(fp);

printf("<FONT size=\"-1\" color=\"#FFFFFF\">あなたは %08d 番目のお客様です。</FONT>", cnt);
}

mstk
2001/12/06, 02:59 PM
CGIを置いたディレクトリに、 core という名前のファイルができていませんか?
その場合、 指定したファイルが無かったからです。
具体的には、このCGIの場合、CGIを置いたディレクトリに count.dat、
その一つ上のディレクトリに main.html が無いと
core というファイルを作って止まります。

P.S.
さすがに少しで良いのでエラー処理を考えた方が良いのではないかと思います。
例えば、
if (fp=fopen(〜)) {

fclose(fp);
}
とか。

Ratoku
2001/12/06, 03:23 PM
レス有難うございます。

確認してみましたが、core という名前のファイルは出来ていませんでした。
ということは、main.html と count.dat が見つからなくて落ちている
わけではなさそうです。

そうなると、ますます原因が解らなくなって来ました・・・。

mstk
2001/12/06, 03:31 PM
とりあえず ../main.html を main.html に変えて実際にxreaに置いてみたところ、動作しました。

ということで、よく分からないので、下のようなCGIでエラーメッセージを見てみてください。
cginame.cgi を 実際のCGIの名前に変えます。

-----
#!/bin/sh

echo "Content-Type: text/plain
echo
./cginame.cgi 2>&1

Ratoku
2001/12/06, 05:20 PM
実行してみました。
帰ってきたエラーは、

./main.xcg: error while loading shared libraries:
libstdc++-libc6.1-2.so.3:
cannot load shared object file: No such file or directory

です。
ライブラリが見つからないと言ってますね・・・。

原因は解りましたが、やはり他の環境でコンパイルしたほうが
いいんでしょうか・・・?

mstk
2001/12/06, 06:12 PM
コンパイルするとき、g++ を使ってませんか?
gcc でコンパイルすればOKだと思います。

どうしても同じ環境でc++を使ってコンパイルしたいということであれば、 -static オプションを付けてコンパイルするという手もあります。

Ratoku
2001/12/06, 08:20 PM
g++を使ってコンパイルしていました。
gccでコンパイルしなおして試してみます。

有難うございました。

cucu81
2001/12/06, 09:37 PM
このソースで-lstdc++ を g++ が付けてしまう判断をするとすれば、
どの記述なのだろう?

mstkさんは、わかりますか?

string.h 入れてるからかな?

mstk
2001/12/06, 10:12 PM
C は必要に迫られたときしか使わないので、良くは知りませんが、

> echo "int main() {}" > test.c
> g++ -o test test.c
> ldd test
test:
libstdc++.so.3 => /usr/lib/libstdc++.so.3 (0x28065000)
libm.so.2 => /usr/lib/libm.so.2 (0x280aa000)
libc.so.4 => /usr/lib/libc.so.4 (0x280c6000)

ということで、gcc を使ったときの libc と同レベルで無条件でつくようです。リンクさせないようにする -nostdlib というオプションもあるようですが、これをつけると、 -lc としてもlibc のリンクに失敗してしまい、コンパイルを通す方法はよくわかりませんでした。

cucu81
2001/12/06, 11:57 PM
おかしいな〜。

うーむ、なにもつけないのに、std++つけちゃうのもすごいな

確かに調べたところ、問題となっているバージョンのlibstd++
はXREAにはないね

libstdc++-2-libc6.1-1-2.9.0.so
libstdc++-3-libc6.2-2-2.10.0.a
libstdc++-3-libc6.2-2-2.10.0.so
libstdc++-libc6.1-1.so.2
libstdc++-libc6.2-2.a.3
libstdc++-libc6.2-2.so.3
libstdc++.so.2.7.2
libstdc++.so.2.7.2.8
libstdc++.so.2.8
libstdc++.so.2.8.0
libstdc++.so.2.9



今メジャーなのは
libstdc++-libc6.2-2.so.3
だと思うんで、これがリンクされるバージョンの g++ にした方が
楽だと思う。

gcc のバージョン2.96 あたり。

mstk
2001/12/07, 09:16 AM
すいません。環境は
> gcc version 2.95.3 20010315 (release) [FreeBSD]
こんなんでした。でも、
> gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release) (ちなみにVine 2.1.5です。)
を使っても、(これはちょっと古いけど)
> ldd test
libstdc++-libc6.1-1.so.2 => /usr/lib/libstdc++-libc6.1-1.so.2 (0x2aac4000)
libm.so.6 => /lib/libm.so.6 (0x2ab06000)
libc.so.6 => /lib/libc.so.6 (0x2ab24000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x2aaab000)

となるので、libstdc++ をリンクするのは g++の仕様だと思います。

cucu81
2001/12/07, 01:27 PM
そうか〜、しようっぽいでござまふか〜、

1)まぁ、ということなので、当初mstkたんがいっていたように[静的にリンク]するか、
2)libstdc++-libc6.1-1.so.2 に動的リンクする、[トクトクでコンパイル]して持ってくるか、(GCC2.91系)
3)libstdc++-libc6.2-2.so.3 に動的にリンクする、[gcc拾ってきて]、自分の
ところでコンパイルするか(GCC2.96系)ですね。


領域が十分あるので、1)が一番とおもいまする。

Ratoku
2001/12/08, 11:30 AM
今回はgccでコンパイルし直すことで問題解決しました。

丁寧な回答をいただき、どうもありがとうございました。

mstk
2001/12/09, 01:14 PM
Originally posted by mstk
リンクさせないようにする -nostdlib というオプションもあるようですが、これをつけると、 -lc としてもlibc のリンクに失敗してしまい、コンパイルを通す方法はよくわかりませんでした。
このあたりの話が、UNIX User の1月号に載ってました。
g++ -nostdlib /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtbegin.o test.c -lc /usr/lib/crtend.o /usr/lib/crtn.o

でいけました。素直にgcc使った方がはやいですけどね。
gcc -v test.c とかやってみると、なかなか面白いです。

ちなみに記事中では、glibcからの独立と題して、-lcすら取っ払ってしまおうという話になっています。

cucu81
2001/12/09, 11:12 PM
どのみちC++つかわなきゃ、わけわからんからね。

MAPコンテナやstringクラスなしに、まともな規模のC系CGIは作りにくいよ。
(今のGCCは文字列をヌル切りすると、CORE吐くからね。
 昔みたいに、ポインタのトリック使ってCでカリカリという利点はないね)