LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Having issues with typedef struct in c (https://www.linuxquestions.org/questions/programming-9/having-issues-with-typedef-struct-in-c-818917/)

andy89038 07-09-2010 09:27 AM

Having issues with typedef struct in c
 
Thanks for taking the time to read my post. I'm trying to read from a config file and set my results to a struct so that I can access the parameters easily. My code was modified from a post by paulsm4 and is as follows:

Code:

#include <stdio.h>
#include <time.h>
#include <string.h>
#include <ctype.h>


typedef struct {
        char *base;
        char *alert_status_file;
        char *alert_email;
        char *log_file;
        int email_throttle;
        char *dbase;
        char *db_usr;
        char *db_pass;
        char *test;
} CONFIG ;

#define MAXLEN 80


time_t get_time();
void get_config(CONFIG *conf);
void mysql();
trim (char* in_string);



int main ()
{
        printf("%ld hours since January 1, 1970. \n", get_time());
       
        CONFIG cfg;
        get_config(&cfg);
       
        printf("base is: %s \n",cfg.base);
        printf("dbase is: %s \n",cfg.dbase);
        printf("db_usr is: %s \n",cfg.db_usr);
        printf("alert_status_file is: %s \n",cfg.alert_status_file);
        printf("alert_email is: %s \n",cfg.alert_email);
        printf("log_file is: %s \n",cfg.log_file);
        printf("db_pass is: %s \n",cfg.db_pass);
        printf("email_throttle is: %s \n",cfg.email_throttle);
        return 0;
}
       
       
       
time_t get_time () {
        time_t seconds, rt_time;
        seconds = time (NULL);
        rt_time = seconds/3600;
        return rt_time;
}       



void get_config (CONFIG *conf)
{
        char *line, buffer[MAXLEN];
        char key[MAXLEN], value[MAXLEN];
        FILE *FH;
       
        FH = fopen("snort_alert.conf", "r");
        if (FH == NULL)
        {
                printf("Could not open snort_alert.conf\n");
                exit(1);
        }
       
        while (line = fgets(buffer, sizeof(buffer), FH) != NULL)
        {

                /* Skip blank lines and comments */
                if(buffer[0] == "\n" || buffer[0] == "#")
                        continue;
               
                /*tokanize key value pairs*/
                line = strtok(buffer, "=");
                if(line == NULL){
                        continue;
                }
                else {
                        strncpy(key, line, MAXLEN);
                        trim(key);
                }
               
                line = strtok(NULL, "=");
                if(line == NULL){
                        continue;
                }
                else{
                        strncpy(value, line, MAXLEN);
                        trim(value);
                }
               
                printf("key = %s: value = %s\n",key,value);
                /* Copy into correct entry in parameters struct */
                if(!strcmp( key, "base"))
                        conf->base = value;
                else if (!strcmp( key, "alert_status_file"))
                        conf->alert_status_file = value;
                else if (!strcmp( key, "alert_email"))
                        conf->alert_email = value;
                else if (!strcmp( key, "log_file"))       
                        conf->log_file = value;
                else if (!strcmp( key, "email_throttle"))       
                        conf->email_throttle = value;
                else if (!strcmp( key, "dbase"))
                        conf->dbase = value;
                else if (!strcmp( key, "db_usr"))
                        conf->db_usr = value;
                else if (!strcmp( key, "db_pass"))
                        conf->db_pass = value;
                else
                        printf("WARNING: %s/%s: Unknown name/value pair!\n", key, value);
                       

               
        }
                if(!strcmp(key, "alert_email"))
                        printf("***key %s equals base.  Value was set to %s\n",key, conf->base);
               
        fclose(FH);
                printf("  base = %s\n  alert_status_file = %s\n",conf->base,conf->alert_status_file);
}

trim (char * in_string)
{
        /* Initialize start, end pointers */
        char *start_pos = in_string, *end_pos = &in_string[strlen (in_string) - 1];

        /* Trim and delimit right side */
        while ( (isspace (*end_pos)) && (end_pos >= start_pos) )
        {
                end_pos--;
          *(end_pos+1) = '\0';
        }
       
        /* Trim left side */
        while ( (isspace (*start_pos)) && (start_pos < end_pos) )
        {
                start_pos++;
        }
       
        /* Copy finished string */
        strcpy (in_string, start_pos);
        return in_string;
}

config file
Code:

#snort alert config file

base = /etc/snort_alerts
dbase = snort
db_usr = _snort
email_throttle = 10
alert_status_file = alert_stat
alert_email = lahblah@blah.com
log_file = alert_log
db_pass= xxxxx

Pardon all my debugging statements.
The output is:
Code:

355189 hours since January 1, 1970.
key = base: value = /etc/snort_alerts
key = dbase: value = snort
key = db_usr: value = _snort
key = email_throttle: value = 10
key = alert_status_file: value = alert_stat
key = alert_email: value = blahblah@blah.com
key = log_file: value = alert_log
key = db_pass: value = xxxxx
  base = xxxxx
  alert_status_file = xxxxx
base is: xxxxx
dbase is: xxxxx
db_usr is: xxxxx
alert_status_file is: xxxxx
alert_email is: xxxxx
log_file is: xxxxx
db_pass is: xxxxx
email_throttle is: xxxxx

As you can see from the output everything seems to go fine up until I start trying to store my values. I'm thinking my problem is pointers but when I try to specify the size of the variables I start getting errors. I have a test case in which I can get it all to work fine and I'm not understanding why it works in my test case and not in the code above. I haven't done much C programming and any help you can provide would be greatly appreciated. Here is my test case that appears to work correctly...

Code:

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

typedef struct {
        char *a;
        char *b;
        char *c;
        char *d;
        int e;
} test ;

void get_value (test *p);



int main ()
{
        test mystructure;
        get_value(&mystructure);
        printf("The value of a is: %s.\n",mystructure.a);
                printf("The value of b is : %s\n",mystructure.b);
                printf("The value of c is : %s\n",mystructure.c);
                printf("The value of d is : %s\n",mystructure.d);
                printf("The value of e is : %d\n",mystructure.e);
        return 0;
}



void get_value (test *p)
{
                char *value1;
                char *value2;
                char *value3;
                char *value4;
                int value5;
                value1 = "Hello World";
                value2 = "tset1";
                value3 = "eh";
                value4 = "Testing";
                value5 = 10;
                if(!strcmp(value1, "Hello World"));
                        p->a = value1;
        p->b = value2;
                p->c = value3;
                p->d = value4;
                p->e = value5;
}


irmin 07-09-2010 09:43 AM

Welcome to LQ,

I think I located your error and am able to explain it: The problem is with the pointers, as you said correctly. You are assigning the values as follows:
Code:

conf->email_throttle = value;
This will set conf->email_throttle to the address of value[0]. But every key you assign so will get the same value. This means in the end all pointers will point to the same memory region and thus will contain the same contents. You override the contents with strncpy in each iteration. Try to assign it in such a way:
Code:

if( conf->email_throttle ) {
  printf("WARNING: %s/%s: Reassigning name/value pair!\n", key, value);
  free(conf->email_throttle);
}

conf->email_throttle = strdup(value);

But then you will have to free() the memory explicitly when the config object is no longer needed. To make the above code work, you will have to set all pointers to NULL, before reading the data. Otherwise your program may crash, since it tries to free some memory, that was not allocated on the heap before.
Please also note, that the code in the first example is unstable, since you passed the address of a stack object to the calling function. This means, that you are going to access some memory, that might be used by another function later and this may cause a SIGSEGV or this function may destroy your config values.

The second example works, since you assign to each pointer the beginning of a distinct memory region. Thus there will be no overwritings.

I hope this helps you.

andy89038 07-09-2010 10:52 AM

Thank you for your response. I knew I was pointing to the same address I just wasn't seeing how to get around it.


All times are GMT -5. The time now is 09:12 PM.