blob: 218508241cd5208acac82e7b1379a01820a7ccef [file] [log] [blame]
/* Copyright (c) 2015 Google Inc., All Rights Reserved.
* Kevin Klues <klueska@google.com>
* See LICENSE for details. */
#include <parlib/serialize.h>
#include <malloc.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
struct serialized_data *serialize_argv_envp(char *const argv[],
char *const envp[])
{
size_t bufsize = 0;
size_t argc = 0, envc = 0;
struct serialized_data *sd;
/* Count how many args and environment variables we have. */
if(argv) while(argv[argc]) argc++;
if(envp) while(envp[envc]) envc++;
/* Reserve space for argc and envc as well as space for the actual
* pointers to our arguments and environment variables in a
* to-be-allocated buffer ... */
bufsize += sizeof(argc) + sizeof(envc);
bufsize += ((argc + envc) * sizeof(uintptr_t));
/* Reserve space in the buffer for each of our arguments (the +1 comes
* from the '\0' character) */
int arglens[argc];
for (int i = 0; i < argc; i++) {
arglens[i] = strlen(argv[i]) + 1;
bufsize += arglens[i];
}
/* Reserve space in our buffer for each of our environment variables
* (the +1 comes from the '\0' character) */
int envlens[envc];
for (int i = 0; i < envc; i++) {
envlens[i] = strlen(envp[i]) + 1;
bufsize += envlens[i];
}
/* Allocate an sd struct with enough room for all of our
* arguments, environment variables, and their pointers. */
sd = calloc(1, sizeof(struct serialized_data) + bufsize);
if (!sd)
return sd;
/* Now fill in the buffer!. */
size_t *sd_argc = (size_t*)(sd->buf);
size_t *sd_envc = (size_t*)(sd->buf + sizeof(size_t));
char **ppos = (char**)(sd->buf + 2*sizeof(size_t));
char *vpos = (char*)(ppos + argc + envc);
char *vpos_base = vpos;
sd->len = bufsize;
*sd_argc = argc;
*sd_envc = envc;
for (int i = 0; i < argc; i++) {
ppos[i] = (char*)(vpos - vpos_base);
memcpy(vpos, argv[i], arglens[i]);
vpos += arglens[i];
}
for(int i = 0; i < envc; i++) {
ppos[argc + i] = (char*)(vpos - vpos_base);
memcpy(vpos, envp[i], envlens[i]);
vpos += envlens[i];
}
return sd;
}
void free_serialized_data(struct serialized_data *sd)
{
free(sd);
}