ます’s Blog - どうでもいい記事100選

どうでもいい記事100選

mod_maintenance(1.3系統用)

指定した期間内でアクセスがあった場合、指定したURLへ遷移させるApacheモジュールです。
主に定期的なメンテナンス等で利用します。

以下はhttpd.confで設定できる内容です。
各環境用にURLを定義しないと動作しません(要するにURLは全て定義しておいてね、って事です)。
こちらは「MaintenanceStartTime」と「MaintenanceEndTime」の両方を定義しないと動作しません(片方の定義だけでは動作しません)。

<IfModule mod_maintenance.c>
  # 毎週1時から3時までの間は指定したURLへ遷移
  <Location /TEST1/>
    MaintenanceLocationURL_PC       http://www.example.com/mainte.html
    MaintenanceLocationURL_DOCOMO   http://www.example.com/i/mainte.html
    MaintenanceLocationURL_EZWEB    http://www.example.com/ez/mainte.html
    MaintenanceLocationURL_SOFTBANK http://www.example.com/sb/mainte.html
    MaintenanceStartTime            010000
    MaintenanceEndTime              030000
  </Location>

  # 毎週木曜日の1時から3時までの間は指定したURLへ遷移
  <Location /TEST2/>
    MaintenanceLocationURL_PC       http://www.example.com/mainte.html
    MaintenanceLocationURL_DOCOMO   http://www.example.com/i/mainte.html
    MaintenanceLocationURL_EZWEB    http://www.example.com/ez/mainte.html
    MaintenanceLocationURL_SOFTBANK http://www.example.com/sb/mainte.html
    MaintenanceStartTime            010000
    MaintenanceEndTime              030000
    # define of Sun or Mon or Tue or Wed or Thu or Fri or Sat
    MaintenanceWeek                 Thu
  </Location>
</IfModule>

ビルドの仕方は(説明するまでもありませんが)makeファイルとプログラムファイルを同一の場所に配置して、make && make installを実行します。
以下はmakeファイルの内容です。APXSとAPACHECTLのパスは適切な場所を定義してください。
Makefile」として保存するか、別名にする時はmakeコマンドの-fオプションを使ってファイルを指定してください。

##
##  Makefile -- Build procedure for maintenance Apache module
##

MODULE_NAME = mod_maintenance
VERSION     = 0.0.1

# the used tools
APXS      = /usr/local/apache/bin/apxs
APACHECTL = /usr/local/apache/bin/apachectl

#   the default target
all: mod_maintenance.so

# compile the DSO file
mod_maintenance.so: mod_maintenance.c
	$(APXS) -c $(DEF) $(INC) $(LIB) mod_maintenance.c

#   install the DSO file into the Apache installation
#   and activate it in the Apache configuration
install: all
	$(APXS) -i -a -n 'maintenance' mod_maintenance.so

# cleanup
clean:
	rm -f mod_maintenance.o mod_maintenance.so

以下はプログラムファイルの内容です。
「mod_maintenance.c」として保存してください。
mod_datetimelimitをコピー&ペーストして作ったのでコーディングの質については、ご容赦、という事で。

/**************************************************************************
  mod_maintenance.c -- Apache maintenance module
**************************************************************************/


/**************************************************************************
  define of proto-type for utility functions
**************************************************************************/
static int maintenance_is_digit( const char * );


/**************************************************************************
  define of header file
**************************************************************************/
#include "httpd.h"
#include "http_conf_globals.h"
#include "http_config.h"
#include "http_core.h"
#include "http_log.h"
#include "http_protocol.h"
#include "ap_config.h"
#include "scoreboard.h"


/**************************************************************************
  define of struct type etc...
**************************************************************************/
typedef struct st_maintenance_config
{
 char *location_pc;
 char *location_docomo;
 char *location_ezweb;
 char *location_softbank;
 long start_time;
 long end_time;
 long week;
} maintenance_config;

module MODULE_VAR_EXPORT maintenance_module;


/**************************************************************************
  define of main function
**************************************************************************/
static void *maintenance_cdir_config( pool *pool, char *path )
{
 maintenance_config *cfg = (maintenance_config *)ap_pcalloc( pool, sizeof( maintenance_config ) );

 cfg->location_pc       = NULL;
 cfg->location_docomo   = NULL;
 cfg->location_ezweb    = NULL;
 cfg->location_softbank = NULL;
 cfg->start_time        = -1;
 cfg->end_time          = -1;
 cfg->week              = -1;

 return (void *)cfg;
}


/*************************************************************************/
static const char *set_maintenance_location_pc( cmd_parms *parms, void *myconfig, char *Buffer )
{
 maintenance_config *cfg = (maintenance_config *)myconfig;

 if( !ap_is_url( Buffer ) && Buffer[0] != '/' )
   {
    return "argument is not also a URL or a path in MaintenanceStartLocationURL_PC.";
   }

 if( cfg->location_pc )
   {
    return "duplicate entry for MaintenanceStartLocationURL_PC.";
   }

 cfg->location_pc = ap_pstrdup( parms->pool, Buffer );

 return NULL;
}


/*************************************************************************/
static const char *set_maintenance_location_docomo( cmd_parms *parms, void *myconfig, char *Buffer )
{
 maintenance_config *cfg = (maintenance_config *)myconfig;

 if( !ap_is_url( Buffer ) && Buffer[0] != '/' )
   {
    return "argument is not also a URL or a path in MaintenanceStartLocationURL_DOCOMO.";
   }

 if( cfg->location_docomo )
   {
    return "duplicate entry for MaintenanceStartLocationURL_DOCOMO.";
   }

 cfg->location_docomo = ap_pstrdup( parms->pool, Buffer );

 return NULL;
}


/*************************************************************************/
static const char *set_maintenance_location_ezweb( cmd_parms *parms, void *myconfig, char *Buffer )
{
 maintenance_config *cfg = (maintenance_config *)myconfig;

 if( !ap_is_url( Buffer ) && Buffer[0] != '/' )
   {
    return "argument is not also a URL or a path in MaintenanceStartLocationURL_EZWEB.";
   }

 if( cfg->location_ezweb )
   {
    return "duplicate entry for MaintenanceStartLocationURL_EZWEB.";
   }

 cfg->location_ezweb = ap_pstrdup( parms->pool, Buffer );

 return NULL;
}


/*************************************************************************/
static const char *set_maintenance_location_softbank( cmd_parms *parms, void *myconfig, char *Buffer )
{
 maintenance_config *cfg = (maintenance_config *)myconfig;

 if( !ap_is_url( Buffer ) && Buffer[0] != '/' )
   {
    return "argument is not also a URL or a path in MaintenanceStartLocationURL_SOFTBANK.";
   }

 if( cfg->location_softbank )
   {
    return "duplicate entry for MaintenanceStartLocationURL_SOFTBANK.";
   }

 cfg->location_softbank = ap_pstrdup( parms->pool, Buffer );

 return NULL;
}


/*************************************************************************/
static const char *set_maintenance_start_time( cmd_parms *parms, void *myconfig, char *Buffer )
{
 maintenance_config *cfg = (maintenance_config *)myconfig;

 if( !maintenance_is_digit( Buffer ) )
   {
    return "argument is not a number for MaintenanceStartTime.";
   }

 if( strlen( Buffer ) != 6 )
   {
    return "argument fomat error for MaintenanceStartTime.";
   }

 cfg->start_time = atol( Buffer );

 return NULL;
}


/*************************************************************************/
static const char *set_maintenance_end_time( cmd_parms *parms, void *myconfig, char *Buffer )
{
 maintenance_config *cfg = (maintenance_config *)myconfig;

 if( !maintenance_is_digit( Buffer ) )
   {
    return "argument is not a number for MaintenanceEndTime.";
   }

 if( strlen( Buffer ) != 6 )
   {
    return "argument fomat error for MaintenanceEndTime.";
   }

 cfg->end_time = atol( Buffer );

 return NULL;
}


/*************************************************************************/
static const char *set_maintenance_week( cmd_parms *parms, void *myconfig, char *Buffer )
{
 maintenance_config *cfg = (maintenance_config *)myconfig;

 if( cfg->week >= 0 )
   {
    return "duplicate entry for MaintenanceWeek.";
   }

 if( strcasecmp( "Sun", Buffer ) == 0 )
   {
    cfg->week = 0;
   }
   else
 if( strcasecmp( "Mon", Buffer ) == 0 )
   {
    cfg->week = 1;
   }
   else
 if( strcasecmp( "Tue", Buffer ) == 0 )
   {
    cfg->week = 2;
   }
   else
 if( strcasecmp( "Wed", Buffer ) == 0 )
   {
    cfg->week = 3;
   }
   else
 if( strcasecmp( "Thu", Buffer ) == 0 )
   {
    cfg->week = 4;
   }
   else
 if( strcasecmp( "Fri", Buffer ) == 0 )
   {
    cfg->week = 5;
   }
   else
 if( strcasecmp( "Sat", Buffer ) == 0 )
   {
    cfg->week = 6;
   }
   else
   {
    return "unknown parameter in MaintenanceWeek.";
   }

 return NULL;
}


/*************************************************************************/
static int maintenance_getenv( request_rec *rec, maintenance_config *cfg )
{
 const char *agent;
 int Result;

 Result = 0;

 agent  = ap_table_get( rec->headers_in, "User-Agent" );

 if( strncmp( agent, "DoCoMo", 6 ) == 0 )
   {
    if( !cfg->location_docomo )
      {
       return Result;
      }

     Result = 2;
   }
   else
 if( strncmp( agent, "UP.Browser", 10 ) == 0 ||
     strncmp( agent, "KDDI-",      5 )  == 0 )
   {
    if( !cfg->location_ezweb )
      {
       return Result;
      }

     Result = 3;
   }
   else
 if( strncmp( agent, "J-PHONE",    7 )  == 0 ||
     strncmp( agent, "Vodafone",   8 )  == 0 ||
     strncmp( agent, "MOT-",       4 )  == 0 ||
     strncmp( agent, "J-EMULATOR", 10 ) == 0 ||
     strncmp( agent, "SoftBank",   8 )  == 0 ||
     strncmp( agent, "Vemulator",  9 )  == 0 ||
     strncmp( agent, "Semulator",  9 )  == 0 )
   {
    if( !cfg->location_softbank )
      {
       return Result;
      }

     Result = 4;
   }
   else
   {
    if( !cfg->location_pc )
      {
       return Result;
      }

     Result = 1;
   }

 return Result;
}


/*************************************************************************/
static int maintenance_is_check( request_rec *rec )
{

 maintenance_config *cfg = (maintenance_config *)ap_get_module_config( rec->per_dir_config, &maintenance_module );
 char *url;
 int Result;
 time_t timer;
 struct tm *localtimer;
 char Buffer[10];
 long target_time;
 long target_week;

 timer       = time( NULL );
 localtimer  = localtime( &timer );

 Buffer[0]   = '\0';
 sprintf( Buffer, "%02d%02d%02d", localtimer->tm_hour, localtimer->tm_min, localtimer->tm_sec );
 target_time = atol( Buffer );
 target_week = localtimer->tm_wday;

 if( cfg->week >= 0 &&  cfg->week != target_week )
   {
    return DECLINED;
   }

 if( cfg->start_time < 0 || cfg->end_time < 0 )
   {
    return DECLINED;
   }

 Result = maintenance_getenv( rec, cfg );

 if( !Result )
   {
    return DECLINED;
   }

 if( !( cfg->start_time <= target_time && target_time <= cfg->end_time ) )
   {
    Result = 0;
   }

 if( Result )
   {
    switch( Result )
    {
     case  4 : {
                if( cfg->location_softbank[0] == '/' )
                  {
                   if( strcmp( cfg->location_softbank, rec->uri ) == 0 )
                     {
                      return DECLINED;
                     }
                     else
                     {
                      url = ap_construct_url( rec->pool, cfg->location_softbank, rec );
                     }
                  }
                  else
                 {
                  url = cfg->location_softbank;
                 }

                break;
               }
     case  3 : {
                if( cfg->location_ezweb[0] == '/' )
                  {
                   if( strcmp( cfg->location_ezweb, rec->uri ) == 0 )
                     {
                      return DECLINED;
                     }
                     else
                     {
                      url = ap_construct_url( rec->pool, cfg->location_ezweb, rec );
                     }
                  }
                  else
                 {
                  url = cfg->location_ezweb;
                 }

                break;
               }
     case  2 : {
                if( cfg->location_docomo[0] == '/' )
                  {
                   if( strcmp( cfg->location_docomo, rec->uri ) == 0 )
                     {
                      return DECLINED;
                     }
                     else
                     {
                      url = ap_construct_url( rec->pool, cfg->location_docomo, rec );
                     }
                  }
                  else
                 {
                  url = cfg->location_docomo;
                 }

                break;
               }
     default : {
                if( cfg->location_pc[0] == '/' )
                  {
                   if( strcmp( cfg->location_pc, rec->uri ) == 0 )
                     {
                      return DECLINED;
                     }
                     else
                     {
                      url = ap_construct_url( rec->pool, cfg->location_pc, rec );
                     }
                  }
                  else
                 {
                  url = cfg->location_pc;
                 }
                break;
               }
    }

    ap_table_setn( rec->headers_out, "Location", url );
    return HTTP_MOVED_TEMPORARILY;
   }

 return DECLINED;
}


/**************************************************************************
 define of utility functions
**************************************************************************/
static int maintenance_is_digit( const char *Buffer )
{
 if( !ap_isdigit( *Buffer ) )
   {
    return 0;
   }

 while( ap_isdigit( *( ++Buffer ) ) )
 {
 }

 return *Buffer == '\0' ? 1 : 0;
}


/**************************************************************************
  Dispatch list for API hooks
**************************************************************************/
static command_rec maintenance_cmds[] =
{
 { "MaintenanceLocationURL_PC", set_maintenance_location_pc,             NULL, OR_LIMIT, TAKE1,
   "specify location start URL for PC" },
 { "MaintenanceLocationURL_DOCOMO", set_maintenance_location_docomo,     NULL, OR_LIMIT, TAKE1,
   "specify location start URL for DOCOMO" },
 { "MaintenanceLocationURL_EZWEB", set_maintenance_location_ezweb,       NULL, OR_LIMIT, TAKE1,
   "specify location start URL for EZWEB" },
 { "MaintenanceLocationURL_SOFTBANK", set_maintenance_location_softbank, NULL, OR_LIMIT, TAKE1,
   "specify location start URL for SOFTBANK" },
 { "MaintenanceStartTime", set_maintenance_start_time,                   NULL, OR_LIMIT, TAKE1,
   "specify start TIME" },
 { "MaintenanceEndTime", set_maintenance_end_time,                       NULL, OR_LIMIT, TAKE1,
   "specify start TIME" },
 { "MaintenanceWeek", set_maintenance_week,                              NULL, OR_LIMIT, TAKE1,
   "specify Maintenance Week(Sun or Mon or Tue or Wed or Thu or Fri or Sat)" },
 { NULL }
};

module MODULE_VAR_EXPORT maintenance_module = {
    STANDARD_MODULE_STUFF,
    NULL,                     /* module initializer                  */
    maintenance_cdir_config,  /* create per-dir    config structures */
    NULL,                     /* merge  per-dir    config structures */
    NULL,                     /* create per-server config structures */
    NULL,                     /* merge  per-server config structures */
    maintenance_cmds,         /* table of config file commands       */
    NULL,                     /* [#8] MIME-typed-dispatched handlers */
    NULL,                     /* [#1] URI to filename translation    */
    NULL,                     /* [#4] validate user id from request  */
    NULL,                     /* [#5] check if the user is ok _here_ */
    maintenance_is_check,     /* [#3] check access by host address   */
    NULL,                     /* [#6] determine MIME type            */
    NULL,                     /* [#7] pre-run fixups                 */
    NULL,                     /* [#9] log a transaction              */
    NULL,                     /* [#2] header parser                  */
    NULL,                     /* child_init                          */
    NULL,                     /* child_exit                          */
    NULL                      /* [#0] post read-request              */
};

Linux(Debian 4.0 2.6.18-5-686) とSolaris10(sparc)で確認しています。
コンテンツを置く場所を持っていないので、ここに貼り付けてるのはスミマセン。