Issue with popen() fread()

This is a discussion on Issue with popen() fread() within the C Programming forums, part of the General Programming Boards category; Hi everyone. I just started C this weekend so sorry if I am extremely confused with everything. I am very ...

  1. #1
    Registered User
    Join Date
    Mar 2013
    Posts
    3

    Issue with popen() fread()

    Hi everyone. I just started C this weekend so sorry if I am extremely confused with everything.

    I am very new to C so sorry if I am really confused.

    I am trying to have a server process fork() another process to run a C program through popen(). But as soon as I attempt to read the bytes, I get an error from my accept() in my main server process. Here is where I am getting the error.

    Can someone please help.

    Code:
                        pipe_pointer = popen(cgi_command, "r");
                        
                        if(pipe_pointer != NULL) {
                            while(!feof(pipe_pointer)) {
                                bytes_read = fread(buf, 1, sizeof(buf), pipe_pointer);
                                
                                send(clientSock, buf, bytes_read, 0);
                            
                            }
                        }
                        
                        
                        pclose(pipe_pointer);
    Here is the entire code




    Code:
        /**
         * This method processes the first line of the HTTP request and stores it in the variable that the pointer
         * buffer points to. In this case that variable is the request variable in the request_handler method. Returns 0 if nothing was received.
         **/
        int process_request(int clientSock, char *buffer) {
            #define EOL "\r\n"
            #define EOL_SIZE 2
            
            char *bufferPointer = buffer;
            int eol_matched = 0;
            
            while(recv(clientSock, bufferPointer, 1, 0) != 0) {
                if(*bufferPointer == EOL[eol_matched]) {
                    ++eol_matched;
                    
                    if(eol_matched == EOL_SIZE) {
                        *(bufferPointer+1-EOL_SIZE) = '\0';
                        return(strlen(buffer));
                    }
                }
                else {
                    eol_matched = 0;
                }
                bufferPointer++;
            }
            return(0);
        }
        
        int validate_get_request(char *buffer) {
            char get_string[5] = "GET /";
            if(strncasecmp(buffer, get_string, 5) != 0) {
                return(-1);
            }
            else {
                return(1);
            }
        }
        
        /**
         *This method takes a valid request and a pointer to a empty path variable, then fills out the path variable with the path of the requested file. Also it stores the requested filename in the filename variable
         **/
        void get_path(char *request, char *path, char *filename) {
            char buf[1024];
            int i = 0;
            char *pointer = request;
            pointer += 4;
            while(!ISspace(pointer[i]) && pointer[i] != '\0') {
                filename[i] = pointer[i];
                i++;
            }
            filename[i] = '\0';
            
        
            if(strcmp(filename, "/") == 0) {
                strcpy(filename, "/index.html");
            }
            
            if(strstr(filename, ".cgi") != NULL) {
                strcpy(path, CGIROOT);
            }
            else {
                strcpy(path, DOCROOT);
            }
            strcat(path, filename);
        }
        
        
        void send_ok_header(int clientSock, char *mime) {
            char buf[1024];
            //Create OK Header, then add the file
            
            strcpy(buf, "HTTP/1.0 200 OK\r\n");
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, SERVER);
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, "Content-Type: ");
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, mime);
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, "\r\n\r\n");
            send(clientSock, buf, strlen(buf), 0);
        }
        
        void send_not_found(int clientSock, char *mime) {
            char buf[1024];
            //Create not found Header, then add the file
            strcpy(buf, "HTTP/1.0 404 NOT FOUND\r\n");
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, SERVER);
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, "Content-Type: ");
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, mime);
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, "\r\n\r\n");
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, "404 Sorry this webpage cannot be found\n");
            send(clientSock, buf, strlen(buf), 0);
        }
        
        void send_unsupported(int clientSock, char *mime) {
            char buf[1024];
            //Create not found Header, then add the file
            strcpy(buf, "HTTP/1.0 415 UNSUPPORTED MEDIA TYPE\r\n");
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, SERVER);
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, "Content-Type: ");
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, mime);
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, "\r\n\r\n");
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, "415 Sorry this media type is not supported!!!\n");
            send(clientSock, buf, strlen(buf), 0);
        }
        
        void send_unimplemented(int clientSock, char *mime) {
            char buf[1024];
            //Create not found Header, then add the file
            strcpy(buf, "HTTP/1.0 501 UNIMPLEMENTED\r\n");
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, SERVER);
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, "Content-Type: ");
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, mime);
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, "\r\n\r\n");
            send(clientSock, buf, strlen(buf), 0);
            strcpy(buf, "501 Sorry this server only implements valid GET request\n");
            send(clientSock, buf, strlen(buf), 0);
        }
        
        
        
        /**
         This method takes the filename and fills the variable mime with its appropriate MIME type. Returns -1 if there is an unrecognized filename
         **/
        int get_mime_type(char *filename, char *mime, int *is_cgi) {
            //WHY DOES THIS START WITH SOME WEIRD INITIAL VALUE ON THE 2ND TIME A REQUEST IS MADE?????
            char extension[50] = "";
            int return_val = -1;
            char *pointer;
            int filename_len = sizeof(filename);
            int i = 0;
            
            pointer = strstr(filename, ".");
            if(pointer != NULL) {
                while(pointer[i] != '\0') {
                    extension[i] = pointer[i];
                    i++;
                }
            }
        
            
            if(strcasecmp(extension, ".html") == 0 || strcasecmp(extension, ".htm") == 0) {
                strcpy(mime, "text/html");
                return_val = 1;
            }
            
            else if(strcasecmp(extension, ".jpeg") == 0 || strcasecmp(extension, ".jpg") == 0) {
                strcpy(mime, "image/jpeg");
                return_val = 1;
            }
            
            else if(strcasecmp(extension, ".gif") == 0) {
                strcpy(mime, "image/gif");
                return_val = 1;
            }
            
            else if(strcasecmp(extension, ".txt") == 0) {
                strcpy(mime, "text/plain");
                return_val = 1;
            }
            
            //set the cgi variable to 1
            else if(strcasecmp(extension, ".cgi") == 0) {
                strcpy(mime, "text/html");
                *is_cgi = 1;
                return_val = 1;
            }
            
            
            
            return(return_val);
        }
        
        
        
        /**
         * This is the function that the handler thread executes to handle each request
         */
        void request_handler(int clientSock) {
            FILE *pipe_pointer = NULL;
            int i = 0;
            int is_cgi = 0;
            char buf[1024], path[1024], request[1024], mime[20], filename[50], *query_string[50] = {NULL}, *query_pointer, cgi_command[1024], cgibuf[1024];
            long bytes_read;
            
            //Send the actual html file with header
            FILE *requestedfile = NULL;
            
            //Take a request and fill it in the request variable
            if(process_request(clientSock, request) != 0) {
                //If it is a get request
                if(validate_get_request(request) != -1) {
                    
                    
                    query_pointer = strtok(request, " ?=&");
                    strcpy(request, query_pointer);
                    while(query_pointer != NULL) {
                        query_string[i] = malloc(strlen(query_pointer) + 1);
                        strcpy(query_string[i], query_pointer);
                        query_pointer = strtok(NULL, " ?=&");
                        i++;
                    }
                    query_string[i] = NULL;
                    
                    
                    get_path(request, path, filename);
                    
                    access(path, R_OK);
                    
                    //if the file extension is unsupported throw a 415 code
                    if(get_mime_type(filename, mime, &is_cgi) != 1) {
                        send_unsupported(clientSock, mime);
                    }
                    else if(errno == ENOENT) { //filetype is recognized, but file cannot be found
                        send_not_found(clientSock, mime);
                    }
                    else if(errno == EACCES) { //filetype and file found, but no read access to the file
                        //fix this to a 403 error
                        perror("no access");
                    }
                    else { //PUT THE CGI code somewhere in this else statement
                        
                        if(is_cgi == 1) {
                            i = 1;
                            //Create command to open cgi script
                            strcpy(cgi_command, "(cd ");
                            strcat(cgi_command, CGIROOT);
                            strcat(cgi_command, "; .");
                            strcat(cgi_command, filename);
                            strcat(cgi_command, " ");
                            
                            
                            while(query_string[2*i + 1] != NULL) {
                                strcat(cgi_command, query_string[2*i + 1]);
                                i++;
                            }
                            strcat(cgi_command, ")");
                            
                            free(*query_string);
                            
                            
                            
                            
                            
                            pipe_pointer = popen(cgi_command, "r");
                            
                            if(pipe_pointer != NULL) {
                                while(!feof(pipe_pointer)) {
                                
                                    bytes_read = fread(cgibuf, 1, sizeof(cgibuf), pipe_pointer);
                                    
                                    send(clientSock, cgibuf, bytes_read, 0);
                                
                                }
                            }
                            
                            
                            pclose(pipe_pointer);
                        }
                        else {
                            //Open the file and start to send it
                            requestedfile = fopen(path, "rb");
        
                            //Send header
                            send_ok_header(clientSock, mime);
                
                            //Read the file by 1024 byte increments and send it
                            while(!feof(requestedfile)) {
                                bytes_read = fread(buf, 1, sizeof(buf), requestedfile);
                                send(clientSock, buf, bytes_read, 0);
                                
                            }
                        }
                    }
                
                }
                else { //not a get request
                    
                    send_unimplemented(clientSock, mime);
        
                }
            }
            //Close the client socket when the request is fulfilled
            //thread will die after this
            close(clientSock);
        }
        
        int main(int argc, const char * argv[])
        {
            int server_sock_desc;
            struct sockaddr_in name;
            
            int client_sock_desc;
            struct sockaddr_in client_name;
            socklen_t addr_size;
            
            pthread_t handler_thread;
            
            //connection setup
            server_sock_desc = socket(PF_INET, SOCK_STREAM, 0);
            if(server_sock_desc != -1) {
                memset(&name, 0, sizeof(name));
                name.sin_family = AF_INET;
                name.sin_port = htons(PORTNUMBER);
                name.sin_addr.s_addr = htonl(INADDR_ANY);
                int bind_result = bind(server_sock_desc, (struct sockaddr *) &name, sizeof(name));
                if(bind_result == 0) {
                    if(listen(server_sock_desc, BACKLOG) < 0) {
                        perror("listen failed");
                    }
                    
                    addr_size = sizeof(client_name);
                    
                    //Server Loop will continue to run listening for clients connecting to the server
                    while(1) {
                        
                        //new client attempting to connect to the server
                        client_sock_desc = accept(server_sock_desc, (struct sockaddr *) &client_name, &addr_size);
                        if(client_sock_desc == -1) {
                            perror("accept failed");
                        }
                
                        //connection starts here
                        
                        //create a thread for the new clients request to be handled
                        if(pthread_create(&handler_thread, NULL, request_handler, client_sock_desc) != 0) {
                            perror("pthread_create failed");
                        }
                    }
                }
                else {
                    perror("bind failed");
                }
            }
            else {
                perror("socket failed");
            }
        
        }


    After fread() is executed program execution immediately jumps to this loop and gets stuck on the second line

    Code:
        while(recv(clientSock, bufferPointer, 1, 0) != 0) {
                if(*bufferPointer == EOL[eol_matched]) {
                    ++eol_matched;
        
                    if(eol_matched == EOL_SIZE) {
                        *(bufferPointer+1-EOL_SIZE) = '\0';
                        return(strlen(buffer));
                    }
                }
                else {
                    eol_matched = 0;
                }
                bufferPointer++;
            }

    I really hope someone can help me out. I am extremely lost
    Attached Files Attached Files

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,848
    > strcpy(buf, "HTTP/1.0 200 OK\r\n");
    > send(clientSock, buf, strlen(buf), 0);
    You should create a new utility function, say
    Code:
    void sendString ( int clientSock, const char *buf ) {
      send(clientSock, buf, strlen(buf), 0);
    }
    Then you can write
    Code:
        sendString(clientSock, "HTTP/1.0 200 OK\r\n");
        sendString(clientSock, buf);
        sendString(clientSock, SERVER);
        sendString(clientSock, "Content-Type: ");
        sendString(clientSock, mime);
        sendString(clientSock, "\r\n\r\n");
    -
    > int filename_len = sizeof(filename);
    You probably meant strlen here, since filename is a pointer.
    It's a good job you don't actually use it.

    Code:
    >         while(pointer[i] != '\0') {
                extension[i] = pointer[i];
                i++;
            }
    You just implemented strcpy again.

    > *is_cgi = 1;
    Ideally, you should have
    *is_cgi = 0;
    at the start of the function, just to make it plain that this is the single special case.


    > while(query_pointer != NULL)
    Add
    while(query_pointer != NULL && i < 50 )
    to make sure you don't overflow the array.


    > while(query_string[2*i + 1] != NULL)
    I would suggest a proper for loop, based on the known number of parameters.
    If someone feeds in a badly formatted request which results in an odd number of tokens, then you're borked.

    > free(*query_string);
    This is plain wrong.
    You have
    query_string[i] = malloc(....
    That means you need
    free(query_string[i]);
    for each element you allocated.

    > while(!feof(requestedfile))
    SourceForge.net: Feof - cpwiki
    Try instead
    Code:
    while ( (bytes_read = fread(buf, 1, sizeof(buf), requestedfile)) != 0 ) 
        send(clientSock, buf, bytes_read, 0);
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  3. #3
    a_capitalist_story
    Join Date
    Dec 2007
    Posts
    2,657
    Hi everyone. I just started C this weekend so sorry if I am extremely confused with everything.
    o_0

    Maybe you should...I don't know...start with something a little more basic than trying to write a web server???

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. using popen
    By frs in forum Linux Programming
    Replies: 6
    Last Post: 06-14-2010, 02:26 PM
  2. popen(man XX | col -b)
    By MK27 in forum Linux Programming
    Replies: 2
    Last Post: 09-26-2008, 03:47 PM
  3. Replies: 6
    Last Post: 06-16-2008, 05:06 AM
  4. popen()
    By Cactus_Hugger in forum Windows Programming
    Replies: 2
    Last Post: 10-22-2005, 04:16 PM
  5. popen
    By Shakespeare in forum C++ Programming
    Replies: 1
    Last Post: 01-27-2003, 09:22 AM

Tags for this Thread


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21