0

I try to write a program using this structure containing strings :

typedef struct s_conf
{
    char *shell1;
    char *shell2;
    char *shell3;
    char *shell4;
    char *server_ip;    
} t_conf;

Parsing a config text file line per line, I get this information and I store it into variables such as line1 and line4. Now I want to assign my struct fields the values of the variables line1 and line4:

char *line1 = "/var/www/host/current/app/console robot:file";
char *line4 = "192.168.00.00";

t_conf *conf;
if ((conf = malloc(sizeof(t_conf))) == NULL)
        {
            fprintf(stderr, "Malloc error\n");
            return (-1);
        }

strcpy(conf->shell1, line1);
strcpy(conf->server_ip, line4);

printf("line1 : '%s'\n"; line1);
printf("line4 : '%s'\n"; line4);

printf("t_conf->shell1 : '%s'\n", conf->shell1);
printf("t_conf->server_ip : '%s'\n", conf->server_ip);

The output :

line1 : '/var/www/host/current/app/console robot:file'
line4 : '192.168.00.00'
t_conf->shell1 : '/var/www/host/current/app'
t_conf->server_ip : '192.168.00.00'

How to correctly assign the c string t_conf->shell1 ? I try other functions like memcpy(), strdup() and allocate the variable with malloc : t_conf->shell1 = malloc(strlen(line1) + 1) but it gives me the same result, I lose a portion of line1 ?

2 Answers 2

1

I try to write a program using this structure containing strings :

struct s_conf below contains 5 pointers. It does not contains any strings. With the C standard library, a string is an array of characters up to and including a final null character ('\0'). For your code to work, memory for these arrays are needed - someplace.

typedef struct s_conf {
    char *shell1;
    char *shell2;
    char *shell3;
    char *shell4;
    char *server_ip;    
} t_conf;

strcpy(conf->shell1, line1); fails because conf->shell1 does not yet have a value pointing to available memory for the copy.


Populate these 5 pointers with values pointing to memory containing the needed data.

// allocate memory for the structure
conf = malloc(sizeof *conf);
assert(conf);

// Simply copy the pointer if `line1` will exist for as long as `conf`.
conf->shell1 = line1;

// or
// Create an allocated copy.
conf->shell1 = strdup(line1);
// With this method, be sure to free the memory before freeing conf
...
free(conf->shell1);
free(conf);

strdup() is not a standard library function, yet very common. Make an equivalent if needed. Example: (tailor to your needs)

char *my_strdup(const char *s) {
  if (s) {
    size_t sz = strlen(s) + 1;
    char *dest = malloc(sz);
    if (dest) {
      return memcpy(dest, src, sz);
    }
  }
  return NULL;
}
Sign up to request clarification or add additional context in comments.

Comments

1
strcpy(conf->shell1, line1);

You need space to store line1

Furthermore (as pointed out by @cat in comments) strcpy is dangerous and must be avoided in production code, an alternative is strdup (non standard), or snprintf:

size_t size = strlen(line1) + 1;
conf->shell1 = malloc(size);
snprintf(conf->shell1, size, "%s", line1);

The space should be returned with free(conf->shell1); when it is no longer needed.

Same for conf->server_ip

Note that if you don't need to modify those strings, you don't need to copy, just assign:

conf->shell1 = line1;

8 Comments

Don't recommend the use of strcpy and strndup, please. Instead, strndup and strnlen are POSIX.1-2008.
@cat: you probably mean strdup (on the left side). Also, strlcpy can be a good choice.
@cat right you are, edited, IMO a better choice is snprintf since its standard
@Aif Yeah, I mistyped it. strlcpy seems to be BSD, which means I can get it on a GNU/Linux machine with -lbsd, or by default on BSD but not anything else.
Suggesting snprintf() with out showing how to handle the problems it causes simply trades one problem of buffer overflow (using sprintf()) with incomplete "printing" - which this code certainly does.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.