1 /* $OpenBSD: pw_dup.c,v 1.5 2003/06/17 21:56:23 millert Exp $ */ 2 3 /* 4 * Copyright (c) 2000, 2002 Todd C. Miller <Todd.Miller@courtesan.com> 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 #if defined(LIBC_SCCS) && !defined(lint) 24 static const char rcsid[] = "$OpenBSD: pw_dup.c,v 1.5 2003/06/17 21:56:23 millert Exp $"; 25 #endif /* LIBC_SCCS and not lint */ 26 27 #include <sys/types.h> 28 29 #include <pwd.h> 30 #include <stdlib.h> 31 #include <stdio.h> 32 #include <string.h> 33 34 struct passwd * 35 pw_dup(const struct passwd *pw) 36 { 37 char *cp; 38 size_t nsize, psize, csize, gsize, dsize, ssize, total; 39 struct passwd *newpw; 40 41 /* Allocate in one big chunk for easy freeing */ 42 total = sizeof(struct passwd); 43 if (pw->pw_name) { 44 nsize = strlen(pw->pw_name) + 1; 45 total += nsize; 46 } 47 if (pw->pw_passwd) { 48 psize = strlen(pw->pw_passwd) + 1; 49 total += psize; 50 } 51 if (pw->pw_class) { 52 csize = strlen(pw->pw_class) + 1; 53 total += csize; 54 } 55 if (pw->pw_gecos) { 56 gsize = strlen(pw->pw_gecos) + 1; 57 total += gsize; 58 } 59 if (pw->pw_dir) { 60 dsize = strlen(pw->pw_dir) + 1; 61 total += dsize; 62 } 63 if (pw->pw_shell) { 64 ssize = strlen(pw->pw_shell) + 1; 65 total += ssize; 66 } 67 if ((cp = malloc(total)) == NULL) 68 return (NULL); 69 newpw = (struct passwd *)cp; 70 71 /* 72 * Copy in passwd contents and make strings relative to space 73 * at the end of the buffer. 74 */ 75 (void)memcpy(newpw, pw, sizeof(struct passwd)); 76 cp += sizeof(struct passwd); 77 if (pw->pw_name) { 78 (void)memcpy(cp, pw->pw_name, nsize); 79 newpw->pw_name = cp; 80 cp += nsize; 81 } 82 if (pw->pw_passwd) { 83 (void)memcpy(cp, pw->pw_passwd, psize); 84 newpw->pw_passwd = cp; 85 cp += psize; 86 } 87 if (pw->pw_class) { 88 (void)memcpy(cp, pw->pw_class, csize); 89 newpw->pw_class = cp; 90 cp += csize; 91 } 92 if (pw->pw_gecos) { 93 (void)memcpy(cp, pw->pw_gecos, gsize); 94 newpw->pw_gecos = cp; 95 cp += gsize; 96 } 97 if (pw->pw_dir) { 98 (void)memcpy(cp, pw->pw_dir, dsize); 99 newpw->pw_dir = cp; 100 cp += dsize; 101 } 102 if (pw->pw_shell) { 103 (void)memcpy(cp, pw->pw_shell, ssize); 104 newpw->pw_shell = cp; 105 cp += ssize; 106 } 107 108 return (newpw); 109 } 110