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