xref: /openbsd/lib/libc/gen/pw_dup.c (revision bf198cc6)
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