dirkx       99/04/05 06:52:21

  Modified:    src/support ab.8 ab.c
  Added:       src/support README
  Log:
  Added Basic Auth, Cookies and arbitrary headers to ab.c/ab.8. Sorry
  for the diff; ident seemed to have mangled some lines with the current
  .indedent.pro. Sneaked in a write() to writev() replacement which
  at least on FreeBSD makes a POST significantly 2-5% faster.
  
  Added a README file. To make it even more obvious that there are
  usefull things such as rotate_log, split_log and the likes.
  
  Revision  Changes    Path
  1.5       +47 -0     apache-1.3/src/support/ab.8
  
  Index: ab.8
  ===================================================================
  RCS file: /x3/home/cvs/apache-1.3/src/support/ab.8,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ab.8      1999/02/19 16:25:35     1.4
  +++ ab.8      1999/04/05 13:52:20     1.5
  @@ -1,4 +1,5 @@
   .TH ab 1 "March 1998"
  +.\" $Id: ab.8,v 1.5 1999/04/05 13:52:20 dirkx Exp $
   .\" Copyright (c) 1998-1999 The Apache Group. All rights reserved.
   .\"
   .\" Redistribution and use in source and binary forms, with or without
  @@ -66,6 +67,14 @@
   ] [
   .BI \-p " POST file"
   ] [
  +.BI \-A " Authenticate username:password"
  +] [
  +.BI \-P " Proxy Authenticate username:password"
  +] [
  +.BI \-H " Custom header"
  +] [
  +.BI \-C " Cookie name=value"
  +] [
   .BI \-T " content-type"
   ] [
   .BI \-v " verbosity"
  @@ -126,6 +135,31 @@
   File containing data to POST.
   
   .TP 12
  +.BI \-A " Authorization username:password"
  +Supply BASIC Authentification credentials to the server. The username
  +and password are separated by a single ':' and send on the wire uuencoded.
  +The string is send regardless of wether the server needs it; (i.e. has
  +send an 401. Authentifcation needed).
  +
  +.TP 12
  +.BI \-p " Proxy-Authorization username:password"
  +Supply BASIC Authentification credentials to a proxy en-route. The username
  +and password are separated by a single ':' and send on the wire uuencoded.
  +The string is send regardless of wether the proxy needs it; (i.e. has
  +send an 407 Proxy authentifcation needed).
  +
  +.TP 12
  +.BI \-C " Cookie name=value"
  +Add a 'Cookie:' line to the request. The argument is typically in the form
  +of a 'name=value' pair. This field is repeatable.
  +
  +.TP 12
  +.BI \-p " Header string"
  +Postfix extra headers to the request. The argument is typically in the form
  +of a valid header line; containing a colon separated field value pair. (i.e. 
  +'Accept-Encoding: zip/zop;8bit').
  +
  +.TP 12
   .BI \-T " content-type"
   Content-type header to use for POST data.
   
  @@ -158,6 +192,19 @@
   .B \-h 
   Display usage information.
   .PD
  +.SH BUGS
  +There are various statically declared buffers of fixed length. Combined
  +with the lazy parsing of the command line arguments, the response headers
  +from the server and other external inputs this might bite you.
  +.P
  +It does not implment HTTP/1.x fully; only accepts some 'expected' forms
  +of responses. The rather heavy use of 
  +.BR strstr(3)
  +shows up top in profile,
  +which might indicate a performance problem; i.e. you would measure the
  +.BR ab
  +performance rather than the server's.
  +
   .SH SEE ALSO
   .BR httpd(8)
   .
  
  
  
  1.21      +130 -30   apache-1.3/src/support/ab.c
  
  Index: ab.c
  ===================================================================
  RCS file: /x3/home/cvs/apache-1.3/src/support/ab.c,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- ab.c      1999/02/19 16:25:35     1.20
  +++ ab.c      1999/04/05 13:52:21     1.21
  @@ -81,6 +81,7 @@
      **    - Cleaned up by Ralf S. Engelschall <[EMAIL PROTECTED]>, March 1998
      **    - POST and verbosity by Kurt Sussman <[EMAIL PROTECTED]>, August 
1998
      **    - HTML table output added by David N. Welton <[EMAIL PROTECTED]>, 
January 1999
  +   **    - Added Cookie, Arbitrary header and auth support. <[EMAIL 
PROTECTED]>, April 199
      **
    */
   
  @@ -120,11 +121,17 @@
   #include <string.h>
   
   #define ap_select       select
  -#else /* (!)NO_APACHE_INCLUDES */
  +#else                                /* (!)NO_APACHE_INCLUDES */
   #include "ap_config.h"
   #include <fcntl.h>
   #include <sys/time.h>
  -#endif /* NO_APACHE_INCLUDES */
  +
  +#ifndef NO_WRITEV
  +#include <sys/types.h>
  +#include <sys/uio.h>
  +#endif
  +
  +#endif                               /* NO_APACHE_INCLUDES */
   /* ------------------- DEFINITIONS -------------------------- */
   
   /* maximum number of requests on a time limited test */
  @@ -146,7 +153,8 @@
       char cbuff[CBUFFSIZE];   /* a buffer to store server response header */
       int cbx;                 /* offset in cbuffer */
       int keepalive;           /* non-zero if a keep-alive request */
  -    int gotheader;           /* non-zero if we have the entire header in 
cbuff */
  +    int gotheader;           /* non-zero if we have the entire header in
  +                              * cbuff */
       struct timeval start, connect, done;
   };
   
  @@ -174,6 +182,10 @@
   char *postdata;                      /* *buffer containing data from 
postfile */
   int postlen = 0;             /* length of data to be POSTed */
   char content_type[1024];     /* content type to put in POST header */
  +char cookie[1024],           /* optional cookie line */
  +     auth[1024],             /* optional (basic/uuencoded)
  +                              * authentification */
  +     hdrs[4096];             /* optional arbitrary headers */
   int port = 80;                       /* port number */
   
   int use_html = 0;            /* use html in the report */
  @@ -223,20 +235,63 @@
       exit(errno);
   }
   
  +/* -- simple uuencode, lifted from main/util.c which
  + *    needed the pool, so duplicated here with normal
  + *    malloc.
  + */
  +static const char basis_64[] =
  +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  +
  +static char *uuencode(char *string)
  +{
  +    int i, len = strlen(string);
  +    char *p;
  +    char *encoded = (char *) malloc((len + 2) / 3 * 4 + 1);
  +    p = encoded;
  +    for (i = 0; i < len; i += 3) {
  +     *p++ = basis_64[string[i] >> 2];
  +     *p++ = basis_64[((string[i] & 0x3) << 4) |
  +                     ((int) (string[i + 1] & 0xF0) >> 4)];
  +     *p++ = basis_64[((string[i + 1] & 0xF) << 2) |
  +                     ((int) (string[i + 2] & 0xC0) >> 6)];
  +     *p++ = basis_64[string[i + 2] & 0x3F];
  +    };
  +    *p-- = '\0';
  +    *p-- = '=';
  +    *p-- = '=';
  +    return encoded;
  +}
  +
  +
   /* --------------------------------------------------------- */
   
   /* write out request to a connection - assumes we can write
      (small) request out in one go into our new socket buffer  */
   
  -static void write_request(struct connection *c)
  +static void write_request(struct connection * c)
   {
  +#ifndef NO_WRITEV
  +    struct iovec out[2]; int outcnt = 1;
  +#endif
       gettimeofday(&c->connect, 0);
  -    /* XXX: this could use writev for posting -- more efficient -djg */
  -    write(c->fd, request, reqlen);
  +#ifndef NO_WRITEV
  +    out[0].iov_base = request;
  +    out[0].iov_len = reqlen;
  +
       if (posting) {
  -     write(c->fd, postdata, postlen);
  +     out[1].iov_base = postdata;
  +     out[1].iov_len = postlen;
  +     outcnt = 2;
        totalposted += (reqlen + postlen);
       }
  +    writev(c->fd,out, outcnt);
  +#else
  +    write(c->fd,request,reqlen);
  +    if (posting) {
  +        write(c->fd,postdata,postlen);
  +        totalposted += (reqlen + postlen);
  +    }
  +#endif
   
       c->state = STATE_READ;
       FD_SET(c->fd, &readbits);
  @@ -469,7 +524,7 @@
   
   /* start asnchronous non-blocking connection */
   
  -static void start_connect(struct connection *c)
  +static void start_connect(struct connection * c)
   {
       c->read = 0;
       c->bread = 0;
  @@ -484,7 +539,7 @@
       nonblock(c->fd);
       gettimeofday(&c->start, 0);
   
  -    if (connect(c->fd, (struct sockaddr *) &server, sizeof(server)) < 0) {
  +    if (connect(c->fd, (struct sockaddr *) & server, sizeof(server)) < 0) {
        if (errno == EINPROGRESS) {
            c->state = STATE_CONNECTING;
            FD_SET(c->fd, &writebits);
  @@ -508,7 +563,7 @@
   
   /* close down connection and save stats */
   
  -static void close_connection(struct connection *c)
  +static void close_connection(struct connection * c)
   {
       if (c->read == 0 && c->keepalive) {
        /* server has legitimately shut down an idle keep alive request */
  @@ -548,7 +603,7 @@
   
   /* read data from connection */
   
  -static void read_connection(struct connection *c)
  +static void read_connection(struct connection * c)
   {
       int r;
       char *part;
  @@ -570,13 +625,14 @@
       if (!c->gotheader) {
        char *s;
        int l = 4;
  -     int space = CBUFFSIZE - c->cbx - 1;     /* -1 to allow for 0 terminator 
*/
  +     int space = CBUFFSIZE - c->cbx - 1;     /* -1 to allow for 0
  +                                              * terminator */
        int tocopy = (space < r) ? space : r;
   #ifndef CHARSET_EBCDIC
        memcpy(c->cbuff + c->cbx, buffer, space);
  -#else /*CHARSET_EBCDIC */
  +#else                                /* CHARSET_EBCDIC */
        ascii2ebcdic(c->cbuff + c->cbx, buffer, space);
  -#endif /*CHARSET_EBCDIC */
  +#endif                               /* CHARSET_EBCDIC */
        c->cbx += tocopy;
        space -= tocopy;
        c->cbuff[c->cbx] = 0;   /* terminate for benefit of strstr */
  @@ -584,8 +640,10 @@
            printf("LOG: header received:\n%s\n", c->cbuff);
        }
        s = strstr(c->cbuff, "\r\n\r\n");
  -     /* this next line is so that we talk to NCSA 1.5 which blatantly breaks
  -        the http specifaction */
  +     /*
  +      * this next line is so that we talk to NCSA 1.5 which blatantly
  +      * breaks the http specifaction
  +      */
        if (!s) {
            s = strstr(c->cbuff, "\n\n");
            l = 2;
  @@ -620,10 +678,12 @@
                *q = 0;
            }
   
  -         /* XXX: this parsing isn't even remotely HTTP compliant...
  -          * but in the interest of speed it doesn't totally have to be,
  -          * it just needs to be extended to handle whatever servers
  -          * folks want to test against. -djg */
  +         /*
  +          * XXX: this parsing isn't even remotely HTTP compliant... but in
  +          * the interest of speed it doesn't totally have to be, it just
  +          * needs to be extended to handle whatever servers folks want to
  +          * test against. -djg
  +          */
   
            /* check response code */
            part = strstr(c->cbuff, "HTTP");    /* really HTTP/1.x_ */
  @@ -732,29 +792,31 @@
       if (!posting) {
        sprintf(request, "GET %s HTTP/1.0\r\n"
                "User-Agent: ApacheBench/%s\r\n"
  -             "%s"
  +             "%s" "%s" "%s"
                "Host: %s\r\n"
                "Accept: */*\r\n"
  -             "\r\n",
  +             "\r\n" "%s",
                path,
                VERSION,
                keepalive ? "Connection: Keep-Alive\r\n" : "",
  -             hostname);
  +             cookie, auth, hostname, hdrs);
       }
       else {
        sprintf(request, "POST %s HTTP/1.0\r\n"
                "User-Agent: ApacheBench/%s\r\n"
  -             "%s"
  +             "%s" "%s" "%s"
                "Host: %s\r\n"
                "Accept: */*\r\n"
                "Content-length: %d\r\n"
                "Content-type: %s\r\n"
  +             "%s"
                "\r\n",
                path,
                VERSION,
                keepalive ? "Connection: Keep-Alive\r\n" : "",
  +             cookie, auth,
                hostname, postlen,
  -             (content_type[0]) ? content_type : "text/plain");
  +             (content_type[0]) ? content_type : "text/plain", hdrs);
       }
   
       if (verbosity >= 2)
  @@ -764,7 +826,7 @@
   
   #ifdef CHARSET_EBCDIC
       ebcdic2ascii(request, request, reqlen);
  -#endif /*CHARSET_EBCDIC */
  +#endif                               /* CHARSET_EBCDIC */
   
       /* ok - lets start */
       gettimeofday(&start, 0);
  @@ -851,6 +913,13 @@
       fprintf(stderr, "    -x attributes   String to insert as table 
attributes\n");
       fprintf(stderr, "    -y attributes   String to insert as tr 
attributes\n");
       fprintf(stderr, "    -z attributes   String to insert as td or th 
attributes\n");
  +    fprintf(stderr, "    -C attribute    Add cookie, eg. 'Apache=1234. 
(repeatable)\n");
  +    fprintf(stderr, "    -H attribute    Add Arbitrary header line, eg. 
'Accept-Encoding: zop'\n");
  +    fprintf(stderr, "                    Inserted after all normal header 
lines. (repeatable)\n");
  +    fprintf(stderr, "    -A attribute    Add Basic WWW Authentication, the 
attributes\n");
  +    fprintf(stderr, "                    are a colon separated username and 
password.\n");
  +    fprintf(stderr, "    -p attribute    Add Basic Proxy Authentication, the 
attributes\n");
  +    fprintf(stderr, "                    are a colon separated username and 
password.\n");
       fprintf(stderr, "    -V              Print version number and exit\n");
       fprintf(stderr, "    -k              Use HTTP KeepAlive feature\n");
       fprintf(stderr, "    -h              Display usage information (this 
message)\n");
  @@ -929,9 +998,11 @@
       tablestring = "";
       trstring = "";
       tdstring = "bgcolor=white";
  -
  +    cookie[0] = '\0';
  +    auth[0] = '\0';
  +    hdrs[0] = '\0';
       optind = 1;
  -    while ((c = getopt(argc, argv, "n:c:t:T:p:v:kVhwx:y:z:")) > 0) {
  +    while ((c = getopt(argc, argv, "n:c:t:T:p:v:kVhwx:y:z:C:H:P:A:")) > 0) {
        switch (c) {
        case 'n':
            requests = atoi(optarg);
  @@ -958,11 +1029,37 @@
            break;
        case 't':
            tlimit = atoi(optarg);
  -         requests = MAX_REQUESTS;    /* need to size data array on something 
*/
  +         requests = MAX_REQUESTS;    /* need to size data array on
  +                                      * something */
            break;
        case 'T':
            strcpy(content_type, optarg);
            break;
  +     case 'C':
  +         strncat(cookie, "Cookie: ", sizeof(cookie));
  +         strncat(cookie, optarg, sizeof(cookie));
  +         strncat(cookie, "\r\n", sizeof(cookie));
  +         break;
  +     case 'A':
  +         /*
  +          * assume username passwd already to be in colon separated form.
  +          */
  +         strncat(auth, "Authorization: basic ", sizeof(auth));
  +         strncat(auth, uuencode(optarg), sizeof(auth));
  +         strncat(auth, "\r\n", sizeof(auth));
  +         break;
  +     case 'P':
  +         /*
  +          * assume username passwd already to be in colon separated form.
  +          */
  +         strncat(auth, "Proxy-Authorization: basic ", sizeof(auth));
  +         strncat(auth, uuencode(optarg), sizeof(auth));
  +         strncat(auth, "\r\n", sizeof(auth));
  +         break;
  +     case 'H':
  +         strncat(hdrs, optarg, sizeof(hdrs));
  +         strncat(hdrs, "\r\n", sizeof(hdrs));
  +         break;
        case 'V':
            copyright();
            exit(0);
  @@ -970,7 +1067,10 @@
        case 'w':
            use_html = 1;
            break;
  -         /* if any of the following three are used, turn on html output 
automatically  */
  +         /*
  +          * if any of the following three are used, turn on html output
  +          * automatically
  +          */
        case 'x':
            use_html = 1;
            tablestring = optarg;
  
  
  
  1.1                  apache-1.3/src/support/README
  
  Index: README
  ===================================================================
  Support files:
  
  ab
        ABuse your server with this benchmarker. Rudimentary
        command line testing tool.
  
  apachectl
        Apache run-time Control script. To facilitate the
        administrator and/or your rc.d scripts to control the 
        functioning of the Apache httpd daemon.
  
  apxs
        APache eXtenSion tool. Eases building and installing
        DSO style modules.
  
  dbmmanage
        Create and update user authentication files in the faster
        DBM format used by mod_auth_db.
  
  htdigest
        Create and update user authentication files used in
        DIGEST authentification. See mod_auth_digest.
  
  htpasswd 
        Create and update user authentication files used in
        BASIC authentification. I.e. the htpasswd files.
        See mod_auth.
  
  httpd.8
        General apache man page.
  
  log_server_status
        This script is designed to be run at a frequent interval by something
        like cron.  It connects to the server and downloads the status
        information.  It reformats the information to a single line and logs
        it to a file. 
  
  logresolve
        resolve hostnames for IP-adresses in Apache logfiles
  
  phf_abuse_log.cgi
        This script can be used to detect people trying to abuse an ancient
        and long plugged security hole which existed in a CGI script distributed
        with Apache 1.0.3 and earlier versions.
  
  rotatelogs
        rotate Apache logs without having to kill the server.
  
  split-logfile
        This script will take a combined virtual hosts access
        log file and break its contents into separate files.
  
  suexec
        Switch User For Exec. Used internally by apache, 
          see  the  document  `Apache  suEXEC  Support'
        under http://www.apache.org/docs/suexec.html .
  
  
  
  

Reply via email to