1/*
2 * Copyright (c) 2000,2002 Todd C. Miller <Todd.Miller@courtesan.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
9 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
11 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17/*
18 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
19 *
20 * Permission to use, copy, modify, and distribute this software for any
21 * purpose with or without fee is hereby granted, provided that the above
22 * copyright notice and this permission notice appear in all copies.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
25 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
27 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
28 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
29 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
30 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 */
32#include <sys/cdefs.h>
33#if !defined(lint) && !defined(LINT)
34#if 0
35static char rcsid[] = "Id: pw_dup.c,v 1.2 2004/01/23 18:56:43 vixie Exp";
36#else
37__RCSID("$NetBSD$");
38#endif
39#endif
40
41#include <sys/param.h>
42
43#if !defined(OpenBSD) || OpenBSD < 200105
44
45#include <pwd.h>
46#include <stdlib.h>
47#include <stdio.h>
48#include <string.h>
49#include <bitstring.h>
50
51#include "config.h"
52#include "macros.h"
53#include "structs.h"
54#include "funcs.h"
55
56struct passwd *
57pw_dup(const struct passwd *pw) {
58	char		*cp;
59	size_t		 nsize, psize, gsize, dsize, ssize, total;
60#ifdef LOGIN_CAP
61	size_t		 csize;
62#endif
63	struct passwd	*newpw;
64
65	/* Allocate in one big chunk for easy freeing */
66	total = sizeof(struct passwd);
67	if (pw->pw_name) {
68		nsize = strlen(pw->pw_name) + 1;
69		total += nsize;
70	} else
71		nsize = 0;
72	if (pw->pw_passwd) {
73		psize = strlen(pw->pw_passwd) + 1;
74		total += psize;
75	} else
76		psize = 0;
77#ifdef LOGIN_CAP
78	if (pw->pw_class) {
79		csize = strlen(pw->pw_class) + 1;
80		total += csize;
81	} else
82		csize = 0;
83#endif /* LOGIN_CAP */
84	if (pw->pw_gecos) {
85		gsize = strlen(pw->pw_gecos) + 1;
86		total += gsize;
87	} else
88		gsize = 0;
89	if (pw->pw_dir) {
90		dsize = strlen(pw->pw_dir) + 1;
91		total += dsize;
92	} else
93		dsize = 0;
94	if (pw->pw_shell) {
95		ssize = strlen(pw->pw_shell) + 1;
96		total += ssize;
97	} else
98		ssize = 0;
99	if ((newpw = malloc(total)) == NULL)
100		return (NULL);
101	cp = (char *)(void *)newpw;
102
103	/*
104	 * Copy in passwd contents and make strings relative to space
105	 * at the end of the buffer.
106	 */
107	(void)memcpy(newpw, pw, sizeof(struct passwd));
108	cp += sizeof(struct passwd);
109	if (pw->pw_name) {
110		(void)memcpy(cp, pw->pw_name, nsize);
111		newpw->pw_name = cp;
112		cp += nsize;
113	}
114	if (pw->pw_passwd) {
115		(void)memcpy(cp, pw->pw_passwd, psize);
116		newpw->pw_passwd = cp;
117		cp += psize;
118	}
119#ifdef LOGIN_CAP
120	if (pw->pw_class) {
121		(void)memcpy(cp, pw->pw_class, csize);
122		newpw->pw_class = cp;
123		cp += csize;
124	}
125#endif /* LOGIN_CAP */
126	if (pw->pw_gecos) {
127		(void)memcpy(cp, pw->pw_gecos, gsize);
128		newpw->pw_gecos = cp;
129		cp += gsize;
130	}
131	if (pw->pw_dir) {
132		(void)memcpy(cp, pw->pw_dir, dsize);
133		newpw->pw_dir = cp;
134		cp += dsize;
135	}
136	if (pw->pw_shell) {
137		(void)memcpy(cp, pw->pw_shell, ssize);
138		newpw->pw_shell = cp;
139		cp += ssize;
140	}
141
142	return (newpw);
143}
144
145#endif /* !OpenBSD || OpenBSD < 200105 */
146