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