home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 25 / CDROM25.iso / Share / linux / apache / contrib / modules / mod_limit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-11  |  7.2 KB  |  258 lines

  1.  
  2. /* ====================================================================
  3.  * Copyright (c) 1995 The Apache Group.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer. 
  11.  *
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in
  14.  *    the documentation and/or other materials provided with the
  15.  *    distribution.
  16.  *
  17.  * 3. All advertising materials mentioning features or use of this
  18.  *    software must display the following acknowledgment:
  19.  *    "This product includes software developed by the Apache Group
  20.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  21.  *
  22.  * 4. The names "Apache Server" and "Apache Group" must not be used to
  23.  *    endorse or promote products derived from this software without
  24.  *    prior written permission.
  25.  *
  26.  * 5. Redistributions of any form whatsoever must retain the following
  27.  *    acknowledgment:
  28.  *    "This product includes software developed by the Apache Group
  29.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  30.  *
  31.  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  32.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  33.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  34.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
  35.  * IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  36.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  37.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  38.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  40.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  41.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  42.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  43.  * ====================================================================
  44.  *
  45.  * This software consists of voluntary contributions made by many
  46.  * individuals on behalf of the Apache Group and was originally based
  47.  * on public domain software written at the National Center for
  48.  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  49.  * For more information on the Apache Group and the Apache HTTP server
  50.  * project, please see <http://www.apache.org/>.
  51.  *
  52.  */
  53.  
  54. /*
  55.  * mod_limit.c: limits on daily usage by users
  56.  * A user can only xfer so many bytes/period.
  57.  *
  58.  * Sameer Parekh
  59.  */
  60.  
  61.  
  62. #include "httpd.h"
  63. #include "http_config.h"
  64. #include "mod_limit.h"
  65. #include <sys/mman.h>
  66.  
  67. module limit_module;
  68.  
  69. typedef struct {
  70.     struct user_limit *tableptr;
  71.     char *dataFile;
  72. } limit_state;
  73.  
  74. void *
  75. make_limit_state (pool *p, server_rec *s)
  76. {
  77.     limit_state *cls =
  78.       (limit_state *)palloc (p, sizeof (limit_state));
  79.  
  80.     cls->tableptr == NULL;
  81.     cls->dataFile == NULL;
  82.  
  83.     return (void *)cls;
  84. }
  85.  
  86. char *
  87. set_limit (cmd_parms *parms, void *dummy, char *arg)
  88. {
  89.     limit_state *cls = get_module_config (parms->server->module_config,
  90.                            &limit_module);
  91.     /* Create mmaped data */
  92.     cls->dataFile = arg;
  93.  
  94.     return NULL;
  95. }
  96.  
  97. command_rec limit_cmds[] = {
  98. { "LimitServer", set_limit, NULL, RSRC_CONF, TAKE1,
  99.     "the filename of the limitation database" },
  100. { NULL }
  101. };
  102.  
  103. void
  104. init_limit (server_rec *s, pool *p)
  105. {
  106.   limit_state *cls = get_module_config (s->module_config,
  107.                     &limit_module);
  108.   FILE *fp;
  109.   int uid, max;
  110.   char name[MAX_STRING_LEN];
  111.  
  112.   cls->tableptr = 
  113.     (struct user_limit *) mmap((caddr_t)0, NUM_RECORDS *
  114.                    sizeof(struct user_limit), PROT_READ | PROT_WRITE,
  115.                    MAP_ANON | MAP_SHARED, -1, 0);
  116.   if(cls->tableptr == (struct user_limit *) -1 )
  117.     {
  118.       perror("mmap");
  119.       fprintf(stderr, "httpd: Could not map memory for limits\n");
  120.       exit(1);
  121.     }
  122.  
  123.   /* Open up the initialization file */
  124.   cls->dataFile = server_root_relative(p, cls->dataFile);
  125.   fp=fopen(cls->dataFile, "r");
  126.   while(fscanf(fp, "%d %s %d", &uid, name, &max) != EOF)
  127.     {
  128.       if(uid > NUM_RECORDS)
  129.     continue;
  130.       strncpy(cls->tableptr[uid].account, name, 16);
  131.       cls->tableptr[uid].bytes_sent = 0;
  132.       cls->tableptr[uid].bytes_max = max;
  133.     }
  134.   fclose(fp);
  135. }
  136.  
  137. int
  138. check_limits(request_rec *r)
  139. {
  140.   limit_state *cls = get_module_config(r->server->module_config,
  141.                        &limit_module);
  142.  
  143.   if(r->finfo.st_uid > NUM_RECORDS)
  144.     return OK;
  145.  
  146.   if(cls->tableptr[r->finfo.st_uid].bytes_max == 0)
  147.     return OK;
  148.  
  149.   if(cls->tableptr[r->finfo.st_uid].bytes_max
  150.      < cls->tableptr[r->finfo.st_uid].bytes_sent)
  151.     {
  152.       log_reason("user over limit", r->filename, r);
  153.       return SERVICE_UNAVAILABLE;
  154.     }
  155.  
  156.   return OK;
  157. }
  158.  
  159. int
  160. limit_transaction(request_rec *orig)
  161. {
  162.   /* Add some bits to a given user's data */
  163.  
  164.   limit_state *cls = get_module_config (orig->server->module_config,
  165.                          &limit_module);
  166.  
  167.   /* Find the actual request */
  168.   for( ; orig->next != NULL; orig = orig->next);
  169.  
  170.   if(orig->finfo.st_mode == 0)
  171.     {
  172.       return OK;
  173.     }
  174.   if(orig->finfo.st_uid > NUM_RECORDS)
  175.     return OK;
  176.   if(orig->bytes_sent > 0)
  177.     cls->tableptr[orig->finfo.st_uid].bytes_sent += orig->bytes_sent;
  178.  
  179.   return OK;
  180. }
  181.  
  182. static int
  183. limit_trans(request_rec *r)
  184. {
  185.   limit_state *cls = get_module_config(r->server->module_config,
  186.                        &limit_module);
  187.  
  188.   if(!strncmp("/limits/", r->uri, 8))
  189.     {
  190.       r->filename = pstrcat(r->pool, "limits:", r->uri+8, NULL);
  191.       return OK;
  192.     }
  193.   return DECLINED;
  194. }
  195.  
  196. static int
  197. limit_type(request_rec *r)
  198. {
  199.   if(!strncmp(r->filename, "limits:", 7))
  200.     {
  201.       r->content_type = LIMIT_MAGIC_TYPE;
  202.       return OK;
  203.     }
  204.   return DECLINED;
  205. }
  206.  
  207. static int
  208. limit_handler(request_rec *r)
  209. {
  210.   limit_state *cls = get_module_config(r->server->module_config,
  211.                        &limit_module);
  212.   int index;
  213.  
  214.   /* Spew to client info about limits */
  215.  
  216.   /* This version ignores the file, later versions */
  217.   /* will use the file to make info more specific */
  218.   r->content_type = "text/html";
  219.   send_http_header(r);
  220.  
  221.   rprintf(r, "<TABLE BORDER>\n"
  222.          "<TR><TH>Name</TH><TH>UID</TH><TH>Used</TH><TH>Max</TH></TR>\n");
  223.   for(index = 0; index < NUM_RECORDS; index++)
  224.     {
  225.       if(cls->tableptr[index].bytes_sent != 0)
  226.     rprintf(r, "<TR><TD>%s</TD><TD>%d</TD><TD>%6.2f</TD><TD>%6.2f</TD>\n",
  227.         cls->tableptr[index].account,
  228.         index,
  229.         (float) cls->tableptr[index].bytes_sent / (float) 1048576,
  230.         (float) cls->tableptr[index].bytes_max / (float) 1048576);
  231.     }
  232.   rprintf(r, "</TABLE>\n");
  233.   return OK;
  234. }
  235.     
  236. handler_rec limit_handlers[] = {
  237.   { LIMIT_MAGIC_TYPE, limit_handler },
  238.   { NULL }
  239. };
  240.  
  241. module limit_module = {
  242.    STANDARD_MODULE_STUFF,
  243.    init_limit,            /* initializer */
  244.    NULL,            /* create per-dir config */
  245.    NULL,            /* merge per-dir config */
  246.    make_limit_state,               /* server config */
  247.    NULL,            /* merge server config */
  248.    limit_cmds,                 /* command table */
  249.    limit_handlers,        /* handlers */
  250.    limit_trans,            /* filename translation */
  251.    NULL,            /* check_user_id */
  252.    NULL,            /* check auth */
  253.    check_limits,        /* check access */
  254.    limit_type,            /* type_checker */
  255.    NULL,            /* fixups */
  256.    limit_transaction       /* logger */
  257. };
  258.