//================================================================ // bbs.cc // 原始的CGI掲示版 // Copyright (C) Naoki Watanabe. 2000. All rights reserved. //================================================================ #include #include #include //★ 本書配布の form.cc から 試食用main関数を削除して // 必要最低限の header file を作成しておいてください。 #include "form.h" //---- エラーメッセージを表示して終了する関数 void Die( char* msg ) { if( errno ){ printf( "

Error : %s : %s

", msg, sys_errlist[errno] ); }else{ printf( "

Error : %s

", msg ); } exit(1); } //---- 指定番号の記事のファイル名を返す関数 char* ArtFile( int no ) { static char fname[32]; snprintf( fname, sizeof(fname), "ART/%04d", no ); return fname; } //---- 指定番号の記事を表示する関数 int ShowArticle( int no ) { FILE* fptr; if( (fptr = fopen( ArtFile(no), "r" )) == NULL ) return -1; char buf[1024]; while( fgets( buf, sizeof(buf), fptr ) ){ fputs( buf, stdout ); } fclose(fptr); return 0; } //---- 指定番号のファイルに記事を保存する関数 int WriteArticle( int no, char* content ) { // 記事を開く FILE* fptr; if( (fptr = fopen( ArtFile(no), "w" )) == NULL ){ Die("WriteArticle : fopen"); } fprintf( fptr, "

Article %0d

\n

", no ); for( ; *content; content++ ){ // HTMLタグを一切無効にする。改行を
に取り換える。 switch( *content ){ case '<' : fputs( "<", fptr ); break; case '>' : fputs( ">", fptr ); break; case '&' : fputs( "&", fptr ); break; case '\r' : break; case '\n' : fputs( "
\n", fptr ); break; default : fputc( *content, fptr ); break; } } fprintf( fptr, "\n


\n"); fclose(fptr); return 0; } //---- 最新記事の番号を返す関数 int CurrentSequence( void ) { FILE* fptr; if( (fptr = fopen( "ART/sequence", "r" )) == NULL ){ Die("CurrentSequence : fopen"); } int seq = 0; if( 1 != fscanf( fptr, "%d", &seq ) ){ Die("CurrentSequence : fscanf"); } fclose(fptr); return seq; } //---- 最新記事の番号をひとつ増やす関数 int IncCurrentSequence( void ) { // 番号管理ファイルを読み書き両用で開く FILE* fptr; if( (fptr = fopen( "ART/sequence", "r+" )) == NULL ){ Die("IncCurrentSequence : fopen"); } // 同時アクセスを防ぐため排他ロックをかける #ifdef LOCK_EX // BSD flock( fileno(fptr), LOCK_EX ); #else // non-BSD lockf( fileno(fptr), F_LOCK, 0 ); #endif // 現在の記事番号を得る int seq = 0; if( 1 != fscanf( fptr, "%d", &seq ) ){ Die("IncCurrentSequence : fscanf"); } // 書き込み位置を先頭に巻戻す rewind(fptr); // ひとつ足した値を書き込む fprintf( fptr, "%04d\n", ++seq ); fclose(fptr); return seq; } //---- 投稿用FORMを表示する関数 void ShowForm( void ) { puts( "
\n" "
\n" "\n" "\n" "
\n" ); } int main( void ) { puts("Content-type: text/html\n"); ShowForm(); // 投稿データがあれば記事としてファイルに保存する FormTerm* term; if( 1 == GetForm(term) ){ WriteArticle( IncCurrentSequence(), term[0].value ); } // 全部の記事を表示する for( int n=CurrentSequence(); n>0; n-- ){ ShowArticle(n); } return 0; }