0

similar to 'Loading Variables from Text File in C++' but in C instead of c++

i want to have a main program that acts as a web server and then the webserver.conf file which loads variables. basically webserver.conf will determine how the web server acts (for example when a GET request is received)

variables such as

hostname = 127.0.0.1
port = 80

etc...

i understand the concept of fopen fclose and the basic C functions for reading a file, but still learning about these and i can't find much on the net about reading and setting variables from a file.

Could anyone provide a very simple example where a C program, sort of started below with a super simple fopen for a file.

int main(void) {

FILE *fp;
char *mode = "r";

fp = fopen("/home/lewis/Documents/config/webconfig.conf", mode);


 if (fp == NULL) {
 fprintf(stderr, "Can't open input file webconfig.conf!\n");
 exit(1);

return (EXIT_SUCCESS);
}
}

the context is i want to use a GET command and then print the result (config file)

sorry that the purpose seems skewed... i'll try to apply logic..

main web server

loads webconfig (should be default file to load for GET) to set internal variables

determines action for receiving a GET command

receieves GET command from keyboard

Checks file that is requested

opens file, reads contents

prints contents to stdout

i understand there will be multiple files for each different function, file handling, input handling etc...

just need a bit of a push in the right direction as tying to learn and wrap my head around it.

****DO NOT NECESSARILY WANT CODE, SIMPLY A LOGIC AND UNDERSTANDING OF HOW A C PROGRAM LIKE THIS WOULD COME TOGETHER*****

thanks

Community
  • 1
  • 1
LewisFletch
  • 125
  • 3
  • 6
  • 16

2 Answers2

1

This is perhaps more on topic in programmers' StackExchange, and the problem itself is perhaps more complicated and broad than you realize; perhaps a smaller initial project would be in order.

Simple configuration management is usually done using the well known INI format. You can google 'INI management in C' for some pointers, with code. You will also find answers here on SO with more suggestions, both of ready-made libraries, and of working code.

However, before investigating configuration files, I think you first need to consider how a browser works (actually how a browser might work; there are several options).

The simplest approach, I think would be that of a blocking server, with a simple loop whereby it accepts connections from the Internet:

- load configuration and prepare environment
- create a socket
- bind it to an address and port
- listen on said socket
- forever:
    - check whether anything has been received
    - if so, act upon it
    - continue waiting for the next request

This is woefully inefficient because while handling one request, the server is deaf to any other requests. We can improve on this by implementing worker processes, i.e. "functions" that receive a connection and act upon it, inheriting information from the parent loop but having a mind and an existence of their own:

- forever:
    - check whether anything has been received
    - if so, create a connection
    - create a copy of the current process using fork()
    - from now on there are two "identical" processes, so each line
      will be considered twice.
    - am I the parent? [both processes ask the system this question]
      - if so, continue waiting. [only one receives a 'Yes, you are']
    - I am the child:
      - release all resources I won't need
      - handle the request and send the response on the connection
      - release the connection
      - die.

This still is not really efficient, but at least it's working. It won't do C10K ever (you need to handle connections better for that), but it can be used for learning and small projects. You can find lots of material, as well as sample code, on this topic by googling "client server in C". Here for example.

The next part you have to tackle is HTTP protocol in order to answer meaningfully not to a custom client, but to a browser. Which means understanding the request and the accompanying headers, and respond in kind. Not so easy as it seems, and that's why usually these projects are usually done with "text chat servers", which just exchange lines of free-format ASCII text.

One higher level approach is to study and adapt some already existing program or better yet, library. A well known server in C is Boa. Another, used for reference, is this.

Community
  • 1
  • 1
LSerni
  • 55,617
  • 10
  • 65
  • 107
1

Yore just opening file descriptor and you need to parse values from file.

here is a config file example:

hostname 127.0.0.1

port 8080

and here is a code how to parse it:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct 
{
    char *addr;
    int port;
} MainStruct;

int parse_config(MainStruct * inf) 
{
    /* Used variables */
    FILE *file;
    char * line = NULL;
    char *addr;
    size_t len = 0;
    ssize_t read;

    /* Open file pointer */
    file = fopen("config.conf", "r");
    if(file != NULL)
    {

        /* Line-by-line read cache file */
        while ((read = getline(&line, &len, file)) != -1) 
        {
            /* Find key in file */
            if(strstr(line, "hostname") != NULL) 
            {
                /* Get addres */
                inf->addr = strdup(line+8);
            }

            if(strstr(line, "port") != NULL) 
            {
                /* Get port */
                inf->port = atoi(line+4);
            }
        }
        /* Close file */
        fclose(file);
    } else return 0;

    return 1;
}

int main() 
{
    /* Used variables */
    MainStruct val;
    int status;

    /* Parse congig */
    status = parse_config(&val);

    /* Check status */
    if (status) printf("File parsed succssesfuly\n");
    else printf("Error while parsing file\n");
    
    /* Print parsed values */
    printf("Port: %d\n", val.port);
    printf("Addr: %s\n", val.addr);
}

You can run function parse_config() and give an argument of MainStruct structure variable, like that:

MainStruct val;
parse_config(&val)

printf("Hostname: %s\n", val.addr);
printf("Port: %d\n", val.port); 

the variables of hostname and port will be saved in MainStruct structure variables.

output will be:

Port: 8080
Addr:  127.0.0.1

Also, I have written simple non-blocking web server shttpd: https://github.com/kala13x/shttpd

you can check and use it, ih has conf file 'config.cfg' and Im using inih parser to parse values from config. You can download check and compile to see how it works. Hope this answer will be useful for you

Community
  • 1
  • 1
Sun Dro
  • 581
  • 4
  • 9
  • Thanks for your answer, this made everything click into place. currently going over structures as we speak and didn't even think about them previously as still getting into the hang of it. and thank you for the link to a non blocking server as isemi mentioned below. very good reading and a basis for further understanding. – LewisFletch Apr 03 '15 at 14:02
  • Also i should add that *char server; should be *char addr in the main structure and also translates down to the printf block as val.addr and it compiles runs and prints the conf file. – LewisFletch Apr 03 '15 at 14:12
  • Im glad that this things helped you. Also I edited post and changed source and it works now perfect. I changed *server to *addr too – Sun Dro Apr 03 '15 at 15:21