-2

I am trying to write a web server in C and my code is segfaulting at the moment and I have no idea why. It seems to have something to do with my strcats but thats as far as I've been able to get. I have posted the code and the gdb output. Any help is greatly appreciated.

*** CODE ***

    /*  web-server.c    */

    #include <arpa/inet.h>
    #include <netdb.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>

    #define BUFLEN 1500
    #define BACKLOG 10

    static int server_socket(int port) {
int fd;
struct sockaddr_in servaddr;

if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
    perror("Unable to create socket");
    return -1;
}
printf("created socket\n");
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(port);

if (bind(fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
    perror("Unable to bind to port");
    return -1;
}
printf("binding completed\n");
if (listen(fd, BACKLOG) == -1){
    perror("Unable to listen for connections");
    return -1;
}
printf("socket setup\n");
return fd;

    }

    static char *html_request(char *request) {
char request_code[3], url[BUFLEN], http_code[BUFLEN];
printf(request);
printf("\n");
sscanf(request, "%3s %s %s", request_code, url, http_code);
return url;
    }


    int main() {
int connfd, servfd, rlen, i, eof;
int content_length = 0;
char buf[BUFLEN];
struct sockaddr_in saddr;
char *response;
char *read_buffer = malloc(1);
    char *response200 = "HTTP/1.1 200 OK\nContent-Type: text/html\nConnection: close\nConnection-Length: ";
char *response404 = "HTTP/1.1 404 Not Found\nContent-Type: text/html\nConnection: close\nConnection-Length: ";
FILE *in;
char buffer[1500], content_buffer[5];
char *headers = malloc(BUFLEN);
char *output = malloc(BUFLEN);
socklen_t saddr_len = sizeof(saddr);
servfd = server_socket(8080);
printf("before connection\n");
if ((connfd = accept(servfd, (struct sockaddr *)&saddr, &saddr_len)) == -1) {
    perror("Unable to accept connection");
    return -1;
}
else {
printf("Accept connection\n");

}
if ((rlen = read(connfd, buf, BUFLEN)) > 0) {
    realloc(read_buffer,rlen);
    for (i = 0; i < rlen; i++){
        printf("%c", buf[i]);
        read_buffer[i] = buf[i];
    }
    printf("\n");

}
printf("IMMA BEAST!\n");
response = html_request(read_buffer);
printf(response);

if (strcmp(response, "/index.html") == 0){
    printf("\nMatches!");
    in = fopen("index.txt", "r");
    if (in == NULL){
        printf("Read fail!");
    }
    while ((eof = fread(buffer, 1, 296, in )) > 0){
        content_length = content_length + 1;
    }
    snprintf(content_buffer, 5, "%d" ,content_length);
    headers = strcat(response200, content_buffer);
}
else{
    printf("\nFails!");
    in = fopen("index-error.txt", "r");
    if (in == NULL){
        printf("Read fail!");
    }
    while ((eof = fread(buffer, 1, 300, in )) > 0){
        content_length = content_length + 1;
    }
    snprintf(content_buffer, 5, "%d" ,content_length);
    headers = strcat(response404, content_buffer);
}
fclose(in);
output = strcat(headers, buffer);
write(connfd, output, BUFLEN);
close(connfd);
free(read_buffer);
free(headers);
free(output);

return 0;

}

* GDB OUTPUT *

Program received signal SIGSEGV, Segmentation fault.
0x0000003d4647eff0 in strcat () from /lib64/libc.so.6
(gdb) where
#0  0x0000003d4647eff0 in strcat () from /lib64/libc.so.6
#1  0x0000000000400ecd in main ()
(gdb) n
Single stepping until exit from function strcat,
which has no line number information.

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
user207421
  • 305,947
  • 44
  • 307
  • 483
zanlura
  • 3
  • 2

2 Answers2

8

This is not OK at all:

strcat("HTTP/1.1 404 Not Found\nContent-Type: text/html\nConnection: close\nConnection-Length: ", content_buffer);

strcat() appends the second argument to the first. The first argument there is a literal string, which must never be modified. The only reason C allows this to compile at all is the unfortunate fact that old code depends on literal strings being of type char[] rather than const char[].

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • put this into char *response200 and then used strcat(response200,content_buffer) and still get a segfault – zanlura Feb 26 '13 at 13:11
  • 2
    Let me guess, you didn't allocate any memory for the destination string. I suggest reading some tutorials about strcat and C string handling, but meanwhile, Jeremy's answer elsewhere on this page may help too! – John Zwinck Feb 26 '13 at 13:14
  • 1
    String literal's type is `char[]` not `char*`. – P.P Feb 26 '13 at 13:17
  • @KingsIndian: you are technically correct--the best kind of correct! I have edited the `*`s in my answer to `[]`s. – John Zwinck Feb 26 '13 at 13:18
  • Not that it makes any difference to OP's problem. But that didn't stop me from upvoting you ;) – P.P Feb 26 '13 at 13:21
  • 1
    @user2039272: Have you noticed how many people are voting this answer up? What is the difference between `char *foo = "ma"; strcat(foo, "ssive long string that causes havoc");` and `char foo[1024] = "ma"; strcat(foo, "ssive long string that causes havoc");`? Do you see any difference? If not, perhaps you should compare them by testing... and get a book :) – autistic Feb 26 '13 at 13:41
0

http://www.manpagez.com/man/3/strcat/

You have to malloc your first string with the right size (length of first string + length of second string + 1.

http://www.manpagez.com/man/3/malloc/

Something like:

char *str;
int len = (strlen("HTTP/1.1 200 OK\nContent-Type: text/html\nConnection: close\nConnection-Length: ") + strlen(content_buffer));

str = malloc((len + 1) * sizeof(char));
bzero(str, len);
strcpy(str, "HTTP/1.1 200 OK\nContent-Type: text/html\nConnection: close\nConnection-Length: ");
strcat(str, content_buffer);
str[len] = 0;
Jeremy
  • 1,461
  • 12
  • 26