gethostbyname and pointers

gethostbyname and pointers

Post by Jacques B. Dimanch » Sun, 18 Apr 1999 04:00:00



Hello There,

    I am new to C programming, and am not very good with pointers.  However,
I was wondering what I did wrong with the following so that I can learn from
my mistakes.  What I was trying to do, was get a substring from the referer
environment variable in a POST method CGI script.  Then pass this variable
to gethostbyname.  Following is the code that does NOT work.  I got it to
work properly  by converting *data into an array of type char.  The main
problem is that when it gets to the first debug print, data contains the
information that it is supposed to.  However, after calling gethostbyname,
the last character is a garbage character and host is NULL.  What am I doing
wrong? Thanks in advance for any tips of any nature (including my sucky
coding style, though it IS properly indented on the actual code.).

#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef struct hostent hostent;
int main ( void )
{
 char *referer, *data;
 hostent *host;
 int i;

 data = calloc(1, sizeof( char * ) );

 printf ("Content-type: text/html\n\n");

 referer = getenv("HTTP_REFERER");

 referer += 7;  /* skip past the 7 characters of "http://" */
 for ( i = 0 ; *referer != '/'; )
      *(data + i++) = *referer++;
 *(data + i ) = '\0';
 printf ("%s:<BR>\n", data );    /*First debug print to check data */
 host = gethostbyname(data);
 printf ("%s:<BR>\n", data );    /*Second debug print to check data */
 return 0;

Quote:}

 
 
 

gethostbyname and pointers

Post by Eric Gillespie, J » Sun, 18 Apr 1999 04:00:00


On Sat, 17 Apr 1999 15:56:03 +0800,

Quote:> Hello There,

>     I am new to C programming, and am not very good with pointers.  However,
> I was wondering what I did wrong with the following so that I can learn from
> my mistakes.  What I was trying to do, was get a substring from the referer
> environment variable in a POST method CGI script.  Then pass this variable
> to gethostbyname.  Following is the code that does NOT work.  I got it to
> work properly  by converting *data into an array of type char.  The main
> problem is that when it gets to the first debug print, data contains the
> information that it is supposed to.  However, after calling gethostbyname,
> the last character is a garbage character and host is NULL.  What am I doing
> wrong? Thanks in advance for any tips of any nature (including my sucky
> coding style, though it IS properly indented on the actual code.).

It worked for me with no problems. Maybe someone else can help you.

--
/-----------------------------------------------------------\

|----------------------------<*>----------------------------|
| "Between depriving a man of one hour from his life and    |
|  depriving him of his life there exists only a difference |
|  of degree."                                              |
|  --Emperor Paul Muad'dib (Frank Herbert's Dune Messiah)   |
\-----------------------------------------------------------/

 
 
 

gethostbyname and pointers

Post by Jacques B. Dimanch » Sun, 18 Apr 1999 04:00:00



Quote:> It worked for me with no problems. Maybe someone else can help you.

This is what is bugging me... it should work.  According to the manual, in
no way is the data of the pointer modified by gethostname, but just returns
a pointer to the memory space of a structure of type hostent.  Why for some
ungodly reason does it not work on my system.  But yet, a similar program
that I wrote exactly the same code for, but not in a CGI environment, works
fine.  Sigh.

--

Sincerely,

Jacques Dimanche
VP of Network Operations
Tridel Technologies, Inc.

 
 
 

gethostbyname and pointers

Post by David N. Lombar » Sun, 18 Apr 1999 04:00:00




Quote:>  data = calloc(1, sizeof( char * ) );

This allocates space for a POINTER to a character string (this would
typically be 4 or 8 bytes for UNIX systems).  You want to allocate space for
the actual character string.   Bottom line, you're hammering something in
memory.  So whether it ever *appeared* to work is irrelevant, it didn't, by
definition.  After the getenv, something like:

    data = calloc( strlen( referer ), sizeof( char ) );

Before the getenv, try

    data = calloc( 256, sizeof( char ) );

Or even forget the calloc, and just declare it, you'll have faster code that
way.

Quote:>  for ( i = 0 ; *referer != '/'; )
>       *(data + i++) = *referer++;
>  *(data + i ) = '\0';

While legal, this is coded in a strange way and fails to check for the end
of the string.  Try one of these:

   char *p, *q;
   .
   .
   .
   for( p = referer, q ,= data; *p && *p != '/'; p++ )
      *q++ = *p;
   *q = '\0';

The above has the for stmnt controlling p, uses only pointers, and will
notice the end of string.

   for( i = 0; *referer[i] && referer[i] != '/'; i++
     data[i] = *referer++;
   data[i] = '\0';

This is "closer" to your code, but uses array syntax.

Be very clear you understand how pointers and arrays work.  For example,
*(data + i) and data[i] both point to the identical character.  Your code
will tell you when one is more appropriate than the other.  Try to use the
most obvious code.

--
David N. Lombard

 
 
 

gethostbyname and pointers

Post by Jacques B. Dimanch » Mon, 19 Apr 1999 04:00:00


Quote:> memory.  So whether it ever *appeared* to work is irrelevant, it didn't,
by
> definition.  After the getenv, something like:
>     data = calloc( strlen( referer ), sizeof( char ) );

    Your absolutely correct.  I changed my calloc code to reflect the above,
and it worked fine.  Thanks, now I understand a bit more.  I really need to
hammer into my head how the memory is addressed.  Considering that I am
constantly playing with root, this could cause some problems in the future
if I am not careful.

Quote:> Or even forget the calloc, and just declare it, you'll have faster code
that
> way.

     I guess I was just trying to figure out how to properly address memory
space.  Maybe you can explain why even if you declare a char *buf, when you
try to do a fread with buf as the destination it segment faults unless you
m/calloc the memory space.

Quote:> While legal, this is coded in a strange way and fails to check for the end
> of the string.  Try one of these:

    Normally I do check for end of string, however this was just a quick
hash to see if the gethostbyname worked.  I have a weird way of approaching
things.  First I code it for a controlled environment, where I always know
what input is received, how long, etc.  Once I know that the guts of the
program is working, then I go into dynamic input to ensure for user foobars.

    Thank you for your response... it was very useful.

 
 
 

gethostbyname and pointers

Post by Barry Margoli » Tue, 20 Apr 1999 04:00:00



Quote:>     I guess I was just trying to figure out how to properly address memory
>space.  Maybe you can explain why even if you declare a char *buf, when you
>try to do a fread with buf as the destination it segment faults unless you
>m/calloc the memory space.

fread() is expecting to fill in memory that you've allocated.  If you just
declare a pointer and don't assign anything to it, it can point anywhere in
memory, and most likely points to memory that hasn't been allocated,
resulting in a Segmentation Violation.

--

GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

 
 
 

gethostbyname and pointers

Post by Andrew Chalup » Thu, 22 Apr 1999 04:00:00


On Sun, 18 Apr 1999 11:59:52 +0800, "Jacques B. Dimanche"


>     I guess I was just trying to figure out how to properly address memory
>space.  Maybe you can explain why even if you declare a char *buf, when you
>try to do a fread with buf as the destination it segment faults unless you
>m/calloc the memory space.

I remember finding this confusing when I started programming as well.
Here's a general rule of thumb:  when dealing with pointers to blocks
of memory, you need to tell the process how big the memory space is.
There are two ways to accomplish this:  declaring the buffer name and
allocating memory at the same time (i.e. char buf[50]; ) or doing it
in two steps (i.e. char *buf; buf = (char *)malloc(50);)

For example, consider the following bit of code which copies 50 bytes
from a text file into a buffer (and prints it to the screen for good
measure):

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

void main(int argc, char *argv[]) {

  char buf[50];
  int file, nbytes;

  if ( (file = open("stuff.txt", O_RDONLY)) < 0) {
    perror("open");
    exit(1);
  }
  if ( (nbytes = read(file, buf, 50)) < 0) {
    perror("read");
    exit(1);
  }
  fprintf(stdout, "%s\n", buf);

Quote:}

This works.  However, if I change the declaration of buf to "char
*buf;" and then run the program, I get a read error ("Bad address")
because buf is only pointing to single memory address and not a block
of memory, as it should be.  Adding the statement "buf = (char
*)malloc(50);" will fix this.  

Andrew
--
e-mail: andcha at nortelnetworks dot com