1*bf198cc6Smillert /* $OpenBSD: pw_dup.c,v 1.9 2019/01/25 00:19:25 millert Exp $ */
29a234f2dSmillert
39a234f2dSmillert /*
4*bf198cc6Smillert * Copyright (c) 2000, 2002 Todd C. Miller <millert@openbsd.org>
59a234f2dSmillert *
606f01696Smillert * Permission to use, copy, modify, and distribute this software for any
706f01696Smillert * purpose with or without fee is hereby granted, provided that the above
806f01696Smillert * copyright notice and this permission notice appear in all copies.
99a234f2dSmillert *
10328f1f07Smillert * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11328f1f07Smillert * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12328f1f07Smillert * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13328f1f07Smillert * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14328f1f07Smillert * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15328f1f07Smillert * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16328f1f07Smillert * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17328f1f07Smillert *
18328f1f07Smillert * Sponsored in part by the Defense Advanced Research Projects
19328f1f07Smillert * Agency (DARPA) and Air Force Research Laboratory, Air Force
20328f1f07Smillert * Materiel Command, USAF, under agreement number F39502-99-1-0512.
219a234f2dSmillert */
229a234f2dSmillert
239a234f2dSmillert #include <sys/types.h>
249a234f2dSmillert
25ad7a8559Smillert #include <pwd.h>
269a234f2dSmillert #include <stdlib.h>
279a234f2dSmillert #include <stdio.h>
289a234f2dSmillert #include <string.h>
299a234f2dSmillert
30311f4922Spat #define PW_SIZE(name, size) \
31311f4922Spat do { \
32311f4922Spat if (pw->name) { \
33311f4922Spat size = strlen(pw->name) + 1; \
34311f4922Spat total += size; \
35311f4922Spat } \
36311f4922Spat } while (0)
37311f4922Spat
38311f4922Spat #define PW_COPY(name, size) \
39311f4922Spat do { \
40311f4922Spat if (pw->name) { \
41311f4922Spat (void)memcpy(cp, pw->name, size); \
42311f4922Spat newpw->name = cp; \
43311f4922Spat cp += size; \
44311f4922Spat } \
45311f4922Spat } while (0)
46311f4922Spat
479a234f2dSmillert struct passwd *
pw_dup(const struct passwd * pw)48ad7a8559Smillert pw_dup(const struct passwd *pw)
499a234f2dSmillert {
509a234f2dSmillert char *cp;
51ad7a8559Smillert size_t nsize, psize, csize, gsize, dsize, ssize, total;
52ad7a8559Smillert struct passwd *newpw;
539a234f2dSmillert
549a234f2dSmillert /* Allocate in one big chunk for easy freeing */
55ad7a8559Smillert total = sizeof(struct passwd);
56311f4922Spat PW_SIZE(pw_name, nsize);
57311f4922Spat PW_SIZE(pw_passwd, psize);
58311f4922Spat PW_SIZE(pw_class, csize);
59311f4922Spat PW_SIZE(pw_gecos, gsize);
60311f4922Spat PW_SIZE(pw_dir, dsize);
61311f4922Spat PW_SIZE(pw_shell, ssize);
62311f4922Spat
63ad7a8559Smillert if ((cp = malloc(total)) == NULL)
649a234f2dSmillert return (NULL);
659a234f2dSmillert newpw = (struct passwd *)cp;
669a234f2dSmillert
679a234f2dSmillert /*
689a234f2dSmillert * Copy in passwd contents and make strings relative to space
699a234f2dSmillert * at the end of the buffer.
709a234f2dSmillert */
71ad7a8559Smillert (void)memcpy(newpw, pw, sizeof(struct passwd));
729a234f2dSmillert cp += sizeof(struct passwd);
73311f4922Spat
74311f4922Spat PW_COPY(pw_name, nsize);
75311f4922Spat PW_COPY(pw_passwd, psize);
76311f4922Spat PW_COPY(pw_class, csize);
77311f4922Spat PW_COPY(pw_gecos, gsize);
78311f4922Spat PW_COPY(pw_dir, dsize);
79311f4922Spat PW_COPY(pw_shell, ssize);
809a234f2dSmillert
819a234f2dSmillert return (newpw);
829a234f2dSmillert }
83f3415991Sguenther DEF_WEAK(pw_dup);
84