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
35 static char rcsid[] = "Id: pw_dup.c,v 1.2 2004/01/23 18:56:43 vixie Exp";
36 #else
37 __RCSID("$NetBSD: pw_dup.c,v 1.2 2010/05/06 18:53:17 christos Exp $");
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 
56 struct passwd *
pw_dup(const struct passwd * pw)57 pw_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