httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dean Gaudet <dgau...@arctic.org>
Subject [PATCH] inaddr printf stuff
Date Tue, 07 Apr 1998 09:51:02 GMT
Sorry to detract from the holy naming wars.  Here's a patch I'm wavering
on.  This is the evolution of a patch I posted last october to give us a
method of easily printing struct inaddr and such.  The intent was for this
to be used to improve the content of the error messages in apache 1.3
(which has less content than 1.2 -- 1.2 includes the client address in a
lot more errors than 1.3)

But I'm not sure any more that I want to go this way.  The advantage to
this is that it's easy to print multiple inet addrs should you need to
(i.e. in the proxy).  But the disadvantage is that it still requires a lot
of code to be fixed, and folks will still forget this stuff in their error
messages.

So in addition I'd like to propose:

API_EXPORT(void) aplog_rerror(const char *file, int line, int level,
                             const request_rec *s, const char *fmt, ...)
                            __attribute__((format(printf,5,6)));

Which takes a request_rec instead of a server_rec, and prints the relevant
client fields at the beginning of the message.

Why not add a flag to aplog_error()?  Well because that would ditch type
checking... if we changed it to take a void * instead of a server_rec *
(so that we could pass a server_rec or a request_rec) then we'd lose type
checking.  I'd rather not do that.  I'd rather we did this, and have a
static routine in http_log.c which does both.

Anyhow, here's the patch for the printf extensions, search down to
include/ap.h for docs.  Oh yeah there's a performance improvement in
there that I'll commit regardless.

Dean

Index: ap/ap_snprintf.c
===================================================================
RCS file: /export/home/cvs/apache-1.3/src/ap/ap_snprintf.c,v
retrieving revision 1.18
diff -u -r1.18 ap_snprintf.c
--- ap_snprintf.c	1998/03/31 12:52:13	1.18
+++ ap_snprintf.c	1998/04/07 09:31:03
@@ -384,6 +384,43 @@
 
 
 
+static char *conv_in_addr(struct in_addr *ia, char *buf_end, int *len)
+{
+    unsigned addr = ntohl(ia->s_addr);
+    char *p = buf_end;
+    bool_int is_negative;
+    int sub_len;
+
+    p = conv_10((addr & 0x000000FF)      , TRUE, &is_negative, p, &sub_len);
+    *--p = '.';
+    p = conv_10((addr & 0x0000FF00) >>  8, TRUE, &is_negative, p, &sub_len);
+    *--p = '.';
+    p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len);
+    *--p = '.';
+    p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len);
+
+    *len = buf_end - p;
+    return (p);
+}
+
+
+
+static char *conv_sockaddr_in(struct sockaddr_in *si, char *buf_end, int *len)
+{
+    char *p = buf_end;
+    bool_int is_negative;
+    int sub_len;
+
+    p = conv_10(ntohs(si->sin_port), TRUE, &is_negative, p, &sub_len);
+    *--p = ':';
+    p = conv_in_addr(&si->sin_addr, p, &sub_len);
+
+    *len = buf_end - p;
+    return (p);
+}
+
+
+
 /*
  * Convert a floating point number to a string formats 'f', 'e' or 'E'.
  * The result is placed in buf, and len denotes the length of the string
@@ -660,33 +697,27 @@
 		    i_num = va_arg(ap, u_wide_int);
 		else
 		    i_num = (wide_int) va_arg(ap, unsigned int);
-		/*
-		 * The rest also applies to other integer formats, so fall
-		 * into that case.
-		 */
+		s = conv_10(i_num, 1, &is_negative,
+			    &num_buf[NUM_BUF_SIZE], &s_len);
+		FIX_PRECISION(adjust_precision, precision, s, s_len);
+		break;
+
 	    case 'd':
 	    case 'i':
-		/*
-		 * Get the arg if we haven't already.
-		 */
-		if ((*fmt) != 'u') {
-		    if (is_long)
-			i_num = va_arg(ap, wide_int);
-		    else
-			i_num = (wide_int) va_arg(ap, int);
-		};
-		s = conv_10(i_num, (*fmt) == 'u', &is_negative,
+		if (is_long)
+		    i_num = va_arg(ap, wide_int);
+		else
+		    i_num = (wide_int) va_arg(ap, int);
+		s = conv_10(i_num, 0, &is_negative,
 			    &num_buf[NUM_BUF_SIZE], &s_len);
 		FIX_PRECISION(adjust_precision, precision, s, s_len);
 
-		if (*fmt != 'u') {
-		    if (is_negative)
-			prefix_char = '-';
-		    else if (print_sign)
-			prefix_char = '+';
-		    else if (print_blank)
-			prefix_char = ' ';
-		}
+		if (is_negative)
+		    prefix_char = '-';
+		else if (print_sign)
+		    prefix_char = '+';
+		else if (print_blank)
+		    prefix_char = ' ';
 		break;
 
 
@@ -801,26 +832,77 @@
 		break;
 
 		/*
-		 * Always extract the argument as a "char *" pointer. We 
-		 * should be using "void *" but there are still machines 
-		 * that don't understand it.
-		 * If the pointer size is equal to the size of an unsigned
-		 * integer we convert the pointer to a hex number, otherwise 
-		 * we print "%p" to indicate that we don't handle "%p".
+		 * This is where we extend the printf format, with a second
+		 * type specifier
 		 */
 	    case 'p':
-		ui_num = (u_wide_int) va_arg(ap, char *);
+		switch(*++fmt) {
+		    /*
+		     * If the pointer size is equal to the size of an unsigned
+		     * integer we convert the pointer to a hex number, otherwise 
+		     * we print "%p" to indicate that we don't handle "%p".
+		     */
+		case 'p':
+		    ui_num = (u_wide_int) va_arg(ap, void *);
+
+		    if (sizeof(char *) <= sizeof(u_wide_int))
+				s = conv_p2(ui_num, 4, 'x',
+					    &num_buf[NUM_BUF_SIZE], &s_len);
+		    else {
+			s = "%p";
+			s_len = 2;
+		    }
+		    pad_char = ' ';
+		    break;
 
-		if (sizeof(char *) <= sizeof(u_wide_int))
-		               s = conv_p2(ui_num, 4, 'x',
-					   &num_buf[NUM_BUF_SIZE], &s_len);
-		else {
-		    s = "%p";
-		    s_len = 2;
+		    /* print a struct sockaddr_in as a.b.c.d:port */
+		case 'I':
+		    {
+			struct sockaddr_in *si;
+
+			si = va_arg(ap, struct sockaddr_in *);
+			if (si != NULL) {
+			    s = conv_sockaddr_in(si, &num_buf[NUM_BUF_SIZE], &s_len);
+			    if (adjust_precision && precision < s_len)
+				s_len = precision;
+			}
+			else {
+			    s = S_NULL;
+			    s_len = S_NULL_LEN;
+			}
+			pad_char = ' ';
+		    }
+		    break;
+
+		    /* print a struct in_addr as a.b.c.d */
+		case 'A':
+		    {
+			struct in_addr *ia;
+
+			ia = va_arg(ap, struct in_addr *);
+			if (ia != NULL) {
+			    s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len);
+			    if (adjust_precision && precision < s_len)
+				s_len = precision;
+			}
+			else {
+			    s = S_NULL;
+			    s_len = S_NULL_LEN;
+			}
+			pad_char = ' ';
+		    }
+		    break;
+
+		case NUL:
+		    /* if %p ends the string, oh well ignore it */
+		    continue;
+
+		default:
+		    s = "bogus %p";
+		    s_len = 8;
+		    break;
 		}
-		pad_char = ' ';
 		break;
-
 
 	    case NUL:
 		/*
Index: include/ap.h
===================================================================
RCS file: /export/home/cvs/apache-1.3/src/include/ap.h,v
retrieving revision 1.11
diff -u -r1.11 ap.h
--- ap.h	1998/03/31 12:52:17	1.11
+++ ap.h	1998/04/07 09:31:05
@@ -81,8 +81,21 @@
 #endif
 #endif /* WIN32 */
 
-/* ap_vformatter() is a generic printf-style formatting routine
- * with some extensions.
+/* apapi_vformatter() is a generic printf-style formatting routine
+ * with some extensions.  The extensions are:
+ *
+ * %pA	takes a struct in_addr *, and prints it as a.b.c.d
+ * %pI	takes a struct sockaddr_in * and prints it as a.b.c.d:port
+ * %pp  takes a void * and outputs it in hex
+ *
+ * The %p hacks are to force gcc's printf warning code to skip
+ * over a pointer argument without complaining.  This does
+ * mean that the ANSI-style %p (output a void * in hex format) won't
+ * work as expected at all, but that seems to be a fair trade-off
+ * for the increased robustness of having printf-warnings work.
+ *
+ * Additionally, apapi_vformatter allows for arbitrary output methods
+ * using the apapi_vformatter_buff and flush_func.
  *
  * The ap_vformatter_buff has two elements curpos and endpos.
  * curpos is where ap_vformatter will write the next byte of output.
Index: modules/standard/mod_access.c
===================================================================
RCS file: /export/home/cvs/apache-1.3/src/modules/standard/mod_access.c,v
retrieving revision 1.33
diff -u -r1.33 mod_access.c
--- mod_access.c	1998/03/31 12:53:05	1.33
+++ mod_access.c	1998/04/07 09:31:06
@@ -377,7 +377,8 @@
     if (ret == FORBIDDEN
 	&& (satisfies(r) != SATISFY_ANY || !some_auth_required(r))) {
 	aplog_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
-		  "Client denied by server configuration: %s", r->filename);
+		  "client %pI denied by server configuration: %s",
+		  &r->connection->remote_addr, r->filename);
     }
 
     return ret;




Mime
View raw message