Search code examples
cstringrpcansi-c

How to properly initialize a string that is a field of an autogenerated structure from RPC in ANSI-C


I'm programming a RPC client-server application using ANSI-C, in Ubuntu 17.04. I'm having big troubles at the time of properly initializing strings that are auto-generated from a predefined structures using RPC, and passing it from client-side to server.

Here's my definition of the structure (in RPC):

struct usuario{
   int codigo;
   string nombreUsuario<25>;
   string nombreReal<25>;
   string apellido1<25>;
   string apellido2<25>;
   string clave<25>;
   int num_tarjeta;
   string fechaAlta<10>;
   string fechaBaja<10>;
};

Here the remote function definition (in RPC):

program NPROG {
 version NVERS {
  string registrarse(usuario)=2;
 }=1;
}=0x20000001;

NOTE: I initialize all the fields, and all the strings before the remote call, the strings like the way I'm going to show below, but I'm writing just one here in order to not writing a long question.

Now I've got something like this in my client side:

void
nprog_1(char *host)
{
CLIENT *clnt;
char * *result_1;
usuario  register_arg;

#ifndef DEBUG
clnt = clnt_create (host, NPROG, NVERS, "tcp");
if (clnt == NULL) {
    clnt_pcreateerror (host);
    exit (1);
}
#endif  /* DEBUG */



register_arg.codigo = 0;

// In this way, Segment fault, the two functions, strcpy and strncpy
// strcpy(register_arg.nombreUsuario, "SomeName");

strncpy(register_arg.nombreUsuario, "SomeName", sizeof(register_arg.nombreUsuario));

// call failed en registro: RPC: Remote system error
// register_arg.nombreUsuario = "SomeName";

result_1 = registrarse_1(&register_arg, clnt);
if (result_1 == (char **) NULL) {
    clnt_perror (clnt, "call failed en registro");
}

#ifndef DEBUG
clnt_destroy (clnt);
#endif   /* DEBUG */
} 

I don't put the remote/server code because I'm not even able to get there.


Solution

  • The problem is, that in the generated struct for strings no memory is preallocated, these are just dangling pointers! So you have to care about the memory for the string yourself, you could for example pass a constant:

    register_arg.nombreUsuario = "SomeName";
    

    or allocate the memory yourself:

    register_arg.nombreUsuario = strdup("SomeName");
    

    Then it should work as you expect.