1 /* $OpenBSD: pw_dup.c,v 1.9 2019/01/25 00:19:25 millert Exp $ */ 2 3 /* 4 * Copyright (c) 2000, 2002 Todd C. Miller <millert@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * Sponsored in part by the Defense Advanced Research Projects 19 * Agency (DARPA) and Air Force Research Laboratory, Air Force 20 * Materiel Command, USAF, under agreement number F39502-99-1-0512. 21 */ 22 23 #include <sys/types.h> 24 25 #include <pwd.h> 26 #include <stdlib.h> 27 #include <stdio.h> 28 #include <string.h> 29 30 #define PW_SIZE(name, size) \ 31 do { \ 32 if (pw->name) { \ 33 size = strlen(pw->name) + 1; \ 34 total += size; \ 35 } \ 36 } while (0) 37 38 #define PW_COPY(name, size) \ 39 do { \ 40 if (pw->name) { \ 41 (void)memcpy(cp, pw->name, size); \ 42 newpw->name = cp; \ 43 cp += size; \ 44 } \ 45 } while (0) 46 47 struct passwd * 48 pw_dup(const struct passwd *pw) 49 { 50 char *cp; 51 size_t nsize, psize, csize, gsize, dsize, ssize, total; 52 struct passwd *newpw; 53 54 /* Allocate in one big chunk for easy freeing */ 55 total = sizeof(struct passwd); 56 PW_SIZE(pw_name, nsize); 57 PW_SIZE(pw_passwd, psize); 58 PW_SIZE(pw_class, csize); 59 PW_SIZE(pw_gecos, gsize); 60 PW_SIZE(pw_dir, dsize); 61 PW_SIZE(pw_shell, ssize); 62 63 if ((cp = malloc(total)) == NULL) 64 return (NULL); 65 newpw = (struct passwd *)cp; 66 67 /* 68 * Copy in passwd contents and make strings relative to space 69 * at the end of the buffer. 70 */ 71 (void)memcpy(newpw, pw, sizeof(struct passwd)); 72 cp += sizeof(struct passwd); 73 74 PW_COPY(pw_name, nsize); 75 PW_COPY(pw_passwd, psize); 76 PW_COPY(pw_class, csize); 77 PW_COPY(pw_gecos, gsize); 78 PW_COPY(pw_dir, dsize); 79 PW_COPY(pw_shell, ssize); 80 81 return (newpw); 82 } 83 DEF_WEAK(pw_dup); 84