[C]Segmentation error

I made a program using smtp and pop3, it is a switch to choose smtp and pop3, the program in the first starts, in the second iteration have a core dump in the line sin.sin_addr.s_addr = *((unsigned long*) he->h_addr);.
This is the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
 
#include <winsock2.h> 
#include <stdlib.h> 
#include <conio.h> 
#include <stdio.h> 
#include <string.h> 

#define host "xxxxxxxxx.com" 
#define portm 25

#define host1 "xxxxxxxxx.com"
#define port1 110

/* Macro definitions */
#define TABLELEN        63
#define BUFFFERLEN      128

#define ENCODERLEN      4
#define ENCODEROPLEN    0
#define ENCODERBLOCKLEN 3

#define PADDINGCHAR     '='
#define BASE64CHARSET   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"\
                        "abcdefghijklmnopqrstuvwxyz"\
                        "0123456789"\
                        "+/";

/* Function prototypes */
int Base64Encode(char *input, char *output, int oplen);
int encodeblock(char *input, char *output, int oplen);
int Base64Decode(char *input, char *output, int oplen);
int decodeblock(char *input, char *output, int oplen);
int main() 
{ 
    fflush(stdin);
    fflush(stdout);
    WORD AS;                                     //WORD -> unsigned short int 
   WSADATA WData;        
   SOCKET s;  
   struct hostent *he;                          //host 
     
/*variabili client smtp*/

    char answer[256]="";
    int rc= 0;
    char sendp [BUFFFERLEN + 1]= "";             /* indirizzo email password*/
    char sendp1[BUFFFERLEN+1]="";                /*indirizzo email mittente*/
    char sendp2[BUFFFERLEN+1]="";                /*indirizzo email destinatario*/                
    char encodedoutput[BUFFFERLEN + 1] = "";     /*variabile con indirizzo email password con base 64*/
    char msped[BUFFFERLEN+1]="";                 /*messaggio mandato*/    
    
/*variabili per pop3*/            
    SOCKET s1;  
    char answer1[4290]="";
    char sendpop1[256]="";                /* indirizzo email password*/
    char answer2[4096]="";
    char leg='a';                         /*risposta per la lettura di una email*/
    int rin=1;       
    int i;   
    char str[strlen("\r\n.\r\n")]="\r\n.\r\n";     

/*variabili condivise*/        
    char in='a';                                 /*risposta iniziale*/
    int port=0;   
    char rit='s';    
    system("cls"); 
    
                                                //system("Pause"); 
    
    AS = MAKEWORD(2, 0);    

   if (WSAStartup(AS, &WData) != 0)             //inizializza in WSAStartup 
    { 
    printf("error cant initialize WinSock2\n"); 
   WSACleanup();                                //si pulisce con WSACleanup
   return 1; 
   } 
    
   while (rit=='s')
   {   
   port=0;
   
   printf("Benvenuto, se vuoi mandare una email scrivi a,\r\nse vuoi leggere una email scrivi b\r\n");
   fflush(stdin);
   scanf("%c",&in);   
   
   if (in=='a')
   {he = gethostbyname(host);                    //getting host   
    port=portm;
    printf("1\r\n");
    }   
   
   else {he = gethostbyname(host1);                    //getting host
        port=port1;
        printf("2\r\n");
        }   

struct  sockaddr_in sin; 
    sin.sin_family = AF_INET;                                                   /*internet address family*/
    sin.sin_addr.s_addr = *((unsigned long*) he->h_addr);                       /*indirizzo del server*/
    sin.sin_port = htons(port);                                                 //numero di porta 

/*memcpy(h_addr,he->h_addr,sizeof(he->h_addr));*/
   
   switch (in) 
   { 
   case 'a': 

   if (he == NULL) 
    { 
   printf("\r\n");
   printf("host not found.\n"); 
   system("PAUSE"); 
   return 1; 
   } 
    else 
    { 
    printf("\r\n");
    printf("host found.\n");    
    }
...
default :
 printf("Hai digitato una lettera sbagliata\r\n");

 getch();
 return 0;
 
 }
 
 printf("\r\n");
 printf("Desideri mandare una email oppure leggerne digita s \r\nse non vuoi inserisci un'altra lettera\r\n");
 
 fflush(stdin);
 scanf("%c",&rit);
 printf("\r\n");
 
 }
 
 printf("\r\n");
 printf("Arrivederci\r\n");
 getch(); 


 }
 
Last edited on
You are NOT allocating any memory for the hostent structure itself. Use malloc() (I see you are using C headers, so no suggestion regarding new operator) or create it on the stack, you only have a pointer which points to some random memory. When you dereference it, it crashes, absolutely normal.

The problem is line 40.
Last edited on
what is the correct function that I have to put?
Where what form will it be put?
Last edited on
This is wrong:
 
char str[strlen("\r\n.\r\n")]="\r\n.\r\n";

and should be:
 
char str[] = "\r\n.\r\n";


There's no point in calling WSACleanup if WSAStartup failed in:
1
2
3
4
5
6
   if (WSAStartup(AS, &WData) != 0)             //inizializza in WSAStartup 
   { 
      printf("error cant initialize WinSock2\n"); 
      WSACleanup();                                //si pulisce con WSACleanup
      return 1; 
   }


When setting up the address structure, you're using he before checking if it's null. That's probably where the crash happens.:
1
2
3
4
   struct  sockaddr_in sin; 
   sin.sin_family = AF_INET;                                                   /*internet address family*/
   sin.sin_addr.s_addr = *((unsigned long*) he->h_addr);                       /*indirizzo del server*/
   sin.sin_port = htons(port);                                                 //numero di porta 
Last edited on
what would I do?
In the last comment you said that I would do a control on he but I made before a correction in the cases of the first if like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
he = gethostbyname(host1);                    //getting host
        port=port1;
        printf("2\r\n");
                        if (he == NULL) 
                        { 
                        printf("\r\n");
                        printf("host not found.\n"); 
                        system("PAUSE"); 
                        return 1; 
                        } 
                        else 
                        { 
                        printf("\r\n");
                        printf("host found.\n");    
                         }
How and where have I to put malloc ?
he=malloc(sizeof(he)); is the sintax ?
Last edited on
It looks like you want to set up an address structure dependent on whether the user wants to send or read emails. So you could move the work into a function to make your main program a little simpler.

First declare a structure that hold the host details and declare the send and read hosts.
1
2
3
4
5
6
7
8
struct MailHostInfo
{
    char name[64];
    unsigned short port;
};

const MailHostInfo sendinfo = { "xxxxxxxxx.com", 24 };
const MailHostInfo readnfo = { "xxxxxxxxx.com", 110 };


Then the lookup function. I'll make it return false if it failed to look up the hostname, and true if it worked.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool GetMailAddress(bool sendrequest, struct sockaddr_in &ip4addr)
{
    const char* host = (sendrequest ? sendinfo.name : readnfo.name);
    unsigned short port = (sendrequest ? sendinfo.port : readinfo.port);

    if (struct hostent* hent = gethostbyname(host))
    {
        if (hent->h_addrtype == AF_INET  &&  hent->h_length == sizeof(unsigned))
        {
            addr.sin_family = AF_INET;
            addr.sin_port = htons(port);
            addr.sin_addr = *(unsigned*)hent->h_addr;
            return true;
        }
    }

    return false;
}


Then in your main code, you can call it like:
1
2
3
4
5
6
    struct sockaddr_in addr;
    if (GetMailAddress((in == 'a'), addr)
    {
        std::clog << "cannot find host name" << std::endl;
        return 1;
    }


I've not compiled the code, so it may have errors. Also, I gave a recent example of how to use gethostbyname().
http://www.cplusplus.com/forum/windows/74966/#msg402736
http://www.cplusplus.com/forum/windows/74966/#msg403696
Last edited on
what is sendrequest?
It is correct ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <winsock2.h> 
#include <stdlib.h> 
#include <conio.h> 
#include <stdio.h> 
#include <string.h> 

#define host "smtp.unimi.it" 
#define portm 25

#define host1 "mailserver.unimi.it"
#define port1 110

/* Macro definitions */
#define TABLELEN        63
#define BUFFFERLEN      128

#define ENCODERLEN      4
#define ENCODEROPLEN    0
#define ENCODERBLOCKLEN 3

#define PADDINGCHAR     '='
#define BASE64CHARSET   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"\
                        "abcdefghijklmnopqrstuvwxyz"\
                        "0123456789"\
                        "+/";

/* Function prototypes */
int Base64Encode(char *input, char *output, int oplen);
int encodeblock(char *input, char *output, int oplen);
int Base64Decode(char *input, char *output, int oplen);
int decodeblock(char *input, char *output, int oplen);
                                                                                /*programma esempio per codificare con base 64 una parola da una stringa*/    

bool GetMailAddress(bool sendrequest, struct sockaddr_in &ip4addr)
{
    const char* host = (sendrequest ? sendinfo.name : readnfo.name);
    unsigned short port = (sendrequest ? sendinfo.port : readinfo.port);

    if (struct hostent* hent = gethostbyname(host))
    {
        if (hent->h_addrtype == AF_INET  &&  hent->h_length == sizeof(unsigned short))
        {
            addr.sin_family = AF_INET;
            addr.sin_port = htons(port);
            addr.sin_addr = *(unsigned short*)hent->h_addr;
            return true;
        }
    }

/*
int main(void) {
   int rc = 0;
   char input[BUFFFERLEN + 1] = "";
   char encodedoutput[BUFFFERLEN + 1] = "";
   char decodedoutput[BUFFFERLEN + 1] = "";

   printf("Enter a string: \n");
   scanf("%s", input);

   rc = Base64Encode(input, encodedoutput, BUFFFERLEN);
   printf("Base64 Encoded value: %s\n", encodedoutput);

   rc = Base64Decode(encodedoutput, decodedoutput, BUFFFERLEN);
   printf("Base64 Decoded value: %s", decodedoutput);

getch();
 return rc;
}
*/

int main() 
{ 
    fflush(stdin);
    fflush(stdout);
    WORD AS;                                     //WORD -> unsigned short int 
   WSADATA WData;        
   SOCKET s;  

/*variabili client smtp*/

    char answer[256]="";
    int rc= 0;
    char sendp [BUFFFERLEN + 1]= "";             /* indirizzo email password*/
    char sendp1[BUFFFERLEN+1]="";                /*indirizzo email mittente*/
    char sendp2[BUFFFERLEN+1]="";                /*indirizzo email destinatario*/                
    char encodedoutput[BUFFFERLEN + 1] = "";     /*variabile con indirizzo email password con base 64*/
    char msped[BUFFFERLEN+1]="";                 /*messaggio mandato*/    

struct MailHostInfo
{
    char name[64];
    unsigned short port;
};

const MailHostInfo sendinfo = { "xxxxxxxxx.com", 24 };
const MailHostInfo readnfo = { "xxxxxxxxx.com", 110 };
    
/*variabili per pop3*/            
    SOCKET s1;  
    char answer1[4290]="";
    char sendpop1[256]="";                /* indirizzo email password*/
    char answer2[4096]="";
    char leg='a';                         /*risposta per la lettura di una email*/
    int rin=1;       
    int i;   
    char str[]="\r\n.\r\n";     

/*variabili condivise*/        
    char in='a';                                 /*risposta iniziale*/
    int port=0;   
    char rit='s';    
    system("cls"); 
    
                                                //system("Pause"); 
    
    AS = MAKEWORD(2, 0);    

   if (WSAStartup(AS, &WData) != 0)             //inizializza in WSAStartup 
    { 
    printf("error cant initialize WinSock2\n"); 
   WSACleanup();                                //si pulisce con WSACleanup
   return 1; 
   } 
    
   while (rit=='s')
   {   
   port=0;
   
   printf("Benvenuto, se vuoi mandare una email scrivi a,\r\nse vuoi leggere una email scrivi b\r\n");
   fflush(stdin);
   scanf("%c",&in);   

struct sockaddr_in addr;
    if (GetMailAddress((in == 'a'), addr)
    {
        std::clog << "cannot find host name" << std::endl;
        return 1;
    }

/*memcpy(h_addr,he->h_addr,sizeof(he->h_addr));*/
   
   switch (in) 
   { 
   case 'a': 
       
    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);                              //viene costruita la socket  
    if (s <0)
    {printf("la socket non funziona /r/n");
     return 1;}
Last edited on
sendrequest is a bool that is true if you want the address to send and email, and false if you want to the address to receive an email.

It's filled in by the expression in == 'a'. if the user selects option a, variable in will contain character a and the expression in == 'a' will be true., and if the user selects option b, variable in will contain b and the expression in == 'a' will be false.

Don't get hung up on all this. The main thing I'd like you to understand is how to call gethostbyname() and process the return correctly, including processing NULL if it can't find the address.
Last edited on
I used in the program your comments but have errors : 45 \maildsmtppop3a.cpp expected primary-expression before "const" .
I have interest in solve the error, your comments are useful to make the program simpler, can you give me more directions to solve the problem, the part of the program that i put before is correct?
Last edited on
The syntax error is because you declared GetMailAddress() before you declared sendinfo and readinfo. Those names are used in GetMailAddress, but the compiler hasn't seen declarations for them yet.

It's best if you first have some psuedo-code of what you intend to do, then implement that. It's a rudimentary, but very useful, tool to get you started and keep you on track. It also keeps your main code neat and shows what tasks can be split off into seperate functions. I think this is what you're doing. You will need to improve it according to what you're actually doing though.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
while !quit
    print user options
    get user selection

    switch selection
        send email:
            get connection details
            connect to server
            get user message
            use SMTP protocol to send message
            end send email
       receive email:
           get connection details
           connect to server
           user POP3 protocol to receive messages
           end receive email
    end switch
end while
Topic archived. No new replies allowed.