qmailとsudoの相性の問題?
先日、学科のメインサーバのアップデートで、sudoなども更新された。 これでMovableTypeの記事をメールで書き込む mail2entry.pl の動きがおかしくなった。
具体的には、今までは、sudo を使って www-data 権限を得て 記事を書き込んでいた。
(( .qmail-XXXX )) | /usr/bin/sudo -u www-data /usr/lib/cgi-bin/movabletype/mail2entry.pl
しかし、sudo-1.8.3p2 では、記事書き込み終了後に、mail2entry.pl が ZOMBIE になって処理が終わらず、上位プロセス sudo , qmail-local が残って しまう。このため、一定数以上のmovabletype記事書き込みが溜まると、 メールシステム全体がメール配達が止まったり遅配となっていた。
どうも、sudo の問題みたいなので、sudo を使わずに処理を行うように、 設定を変更した。具体的には、/var/qmail/users/assign によって、 www-data 権限を与えて動かすようにした。
(( /var/qmail/users/assign )) +mt-XXXX:www-data:33:33:/var/qmail/alias:-:mt-XXXX: (( /var/qmail/alias/.qmail-mt-XXXX )) | /usr/lib/cgi-bin/movabletype/mail2entry.pl (( 設定 )) # chmod 644 /var/qmail/alias/.qmail-mt-XXXX # qmail-newu # /etc/init.d/qmail restart
純粋仮想基底クラスと関数ポインタ
先週の仮想関数の説明の応用ということで、 コンテナクラスなどの話につなげるための純粋仮想基底クラスの説明を行う。 その前に、仮想関数の実装の元となっている関数ポインタを簡単に紹介する。
関数ポインタ
関数ポインタとは、名前の通りで、動作説明の簡単なプログラムを紹介。
int add( int x , int y ) { // 加算関数 return x + y ; } int mul( int x , int y ) { // 乗算関数 return x * y ; } void main() { int (*f)(int,int) ; // int×2引数、返り値intの関数へのポインタ f = add ; printf( "%d" , (*f)( 2 , 3 ) ) ; // 5を表示 f = mul ; printf( "%d" , (*f)( 2 , 3 ) ) ; // 6を表示 }
関数ポインタを利用すれば、異なるデータに対する処理を、 汎用性高く作ることも可能となる。
int intcmp( int* x , int* y ) { // 整数比較関数 if ( *x > *y ) return 1 ; else if ( *x < *y ) return -1 ; else return 0 ; } int vmax( void* array , // 配列先頭アドレス int size , // 配列データ件数 int sizeofdata , // 1件あたりのbyte数 int(*f)( void*,void* ) ) { // 比較関数 int i , max = 0 ; for( i = 0 ; i < size ; i++ ) if ( (*f)( array + max * sizeofdata , array + i * sizeofdata ) ) max = i ; return max ; } int idata[ 4 ] = { 11 , 33 , 22 , 44 } ; char sdata[ 4 ][ 4 ] = { "ab" , "bc" , "aa" , "c" } ; void main() { int m ; // intcmp関数を使って、idata から最大値を探す m = vmax( idata , 4 , sizeof(int) , intcmp ) ; printf( "%d" , idata[ m ] ) ; // strcmp関数を使って、sdata から最大値を探す m = vmax( sdata , 4 , sizeof(sdata[0]) , strcmp ) ; printf( "%s" , sdata[ m ] ) ; }
純粋仮想基底クラス
これらの仮想基底クラスの考え方をもっと利用すると、 1つの配列に、異なる型の派生クラスを保存することも可能となる。
// 純粋仮想基底クラス class Object { public: virtual void print() = 0 ; } ; // 整数クラス class IntObject : public Object { private: int data ; public: IntObject( int x ) { data = x ; } virtual void print() { printf( "%d" , data ) ; } } ; // 実数クラス class DoubleObject : public Object { private: double data ; public: DoubleObject( double x ) { data = x ; } virtual void print() { printf( "%f" , data ) ; } } ; // 文字列クラス class StringObject : public Object { private: char* data ; public: StringObject( char* x ) { data = x ; } virtual void print() { printf( "%s" , data ) ; } } ; void main() { Object* a[ 3 ] ; // 配列に整数・実数・文字列が混在できる。 a[0] = new IntObject( 123 ) ; a[1] = new DoubleObject( 1.23 ) ; a[2] = new StringObject( "abc" ) ; // 混在したデータでも、正しく全要素をprint()できる for( int i = 0 ; i < 3 ; i++ ) a[ i ]->print() ; }