|  | /* 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); | 
|  | } | 
|  |  |