Commit | Line | Data |
---|---|---|
380054c3 | 1 | /* |
56623898 KB |
2 | * Copyright (c) 1980, 1983 Regents of the University of California. |
3 | * All rights reserved. | |
4 | * | |
417f7a11 | 5 | * %sccs.include.redist.c% |
380054c3 DF |
6 | */ |
7 | ||
8 | #ifndef lint | |
9 | char copyright[] = | |
56623898 | 10 | "@(#) Copyright (c) 1980, 1983 Regents of the University of California.\n\ |
380054c3 | 11 | All rights reserved.\n"; |
56623898 | 12 | #endif /* not lint */ |
380054c3 | 13 | |
2b55f05a | 14 | #ifndef lint |
3cee3d34 | 15 | static char sccsid[] = "@(#)mkpasswd.c 5.7 (Berkeley) %G%"; |
56623898 | 16 | #endif /* not lint */ |
2b55f05a | 17 | |
259b2b93 | 18 | #include <sys/param.h> |
2b55f05a | 19 | #include <sys/file.h> |
2b55f05a | 20 | #include <ndbm.h> |
259b2b93 KB |
21 | #include <pwd.h> |
22 | #include <stdio.h> | |
23 | ||
24 | static FILE *_pw_fp; | |
25 | static struct passwd _pw_passwd; | |
26 | static off_t offset; | |
27 | ||
28 | #define MAXLINELENGTH 1024 | |
29 | static char line[MAXLINELENGTH]; | |
30 | ||
31 | /* | |
32 | * Mkpasswd does two things -- use the ``arg'' file to create ``arg''.{pag,dir} | |
33 | * for ndbm, and, if the -p flag is on, create a password file in the original | |
34 | * format. It doesn't use the getpwent(3) routines because it has to figure | |
35 | * out offsets for the encrypted passwords to put in the dbm files. One other | |
36 | * problem is that, since the addition of shadow passwords, getpwent(3) has to | |
37 | * use the dbm databases rather than simply scanning the actual file. This | |
38 | * required the addition of a flag field to the dbm database to distinguish | |
39 | * between a record keyed by name, and one keyed by uid. | |
40 | */ | |
2b55f05a | 41 | |
2b55f05a | 42 | main(argc, argv) |
56623898 | 43 | int argc; |
259b2b93 | 44 | char **argv; |
2b55f05a | 45 | { |
259b2b93 KB |
46 | extern int errno, optind; |
47 | register char *flag, *p, *t; | |
48 | register int makeold; | |
49 | FILE *oldfp; | |
2b55f05a RC |
50 | DBM *dp; |
51 | datum key, content; | |
259b2b93 KB |
52 | int ch; |
53 | char buf[8192], nbuf[50], *strerror(); | |
3cee3d34 | 54 | static int scanpw(); |
259b2b93 KB |
55 | |
56 | makeold = 0; | |
57 | while ((ch = getopt(argc, argv, "pv")) != EOF) | |
58 | switch(ch) { | |
59 | case 'p': /* create ``password.orig'' */ | |
60 | makeold = 1; | |
61 | /* FALLTHROUGH */ | |
62 | case 'v': /* backward compatible */ | |
63 | break; | |
64 | case '?': | |
65 | default: | |
66 | usage(); | |
67 | } | |
68 | argc -= optind; | |
69 | argv += optind; | |
70 | ||
71 | if (argc != 1) | |
72 | usage(); | |
73 | ||
74 | if (!(_pw_fp = fopen(*argv, "r"))) { | |
75 | (void)fprintf(stderr, | |
76 | "mkpasswd: %s: can't open for reading.\n", *argv); | |
63e9078a RC |
77 | exit(1); |
78 | } | |
259b2b93 KB |
79 | |
80 | rmall(*argv); | |
56623898 | 81 | (void)umask(0); |
259b2b93 KB |
82 | |
83 | /* open old password format file, dbm files */ | |
84 | if (makeold) { | |
85 | int oldfd; | |
86 | ||
87 | (void)sprintf(buf, "%s.orig", *argv); | |
88 | if ((oldfd = open(buf, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) { | |
89 | (void)fprintf(stderr, "mkpasswd: %s: %s\n", buf, | |
90 | strerror(errno)); | |
403de8f5 RC |
91 | exit(1); |
92 | } | |
259b2b93 KB |
93 | if (!(oldfp = fdopen(oldfd, "w"))) { |
94 | (void)fprintf(stderr, "mkpasswd: %s: fdopen failed.\n", | |
95 | buf); | |
403de8f5 RC |
96 | exit(1); |
97 | } | |
259b2b93 KB |
98 | } |
99 | if (!(dp = dbm_open(*argv, O_WRONLY|O_CREAT|O_EXCL, 0644))) { | |
100 | (void)fprintf(stderr, "mkpasswd: %s: %s\n", *argv, | |
101 | strerror(errno)); | |
102 | exit(1); | |
103 | } | |
104 | ||
105 | content.dptr = buf; | |
106 | while (scanpw()) { | |
107 | /* create dbm entry */ | |
108 | p = buf; | |
109 | #define COMPACT(e) t = e; while (*p++ = *t++); | |
110 | COMPACT(_pw_passwd.pw_name); | |
111 | (void)sprintf(nbuf, "%ld", offset); | |
112 | COMPACT(nbuf); | |
113 | bcopy((char *)&_pw_passwd.pw_uid, p, sizeof(int)); | |
114 | p += sizeof(int); | |
115 | bcopy((char *)&_pw_passwd.pw_gid, p, sizeof(int)); | |
116 | p += sizeof(int); | |
117 | bcopy((char *)&_pw_passwd.pw_change, p, sizeof(time_t)); | |
118 | p += sizeof(time_t); | |
119 | COMPACT(_pw_passwd.pw_class); | |
120 | COMPACT(_pw_passwd.pw_gecos); | |
121 | COMPACT(_pw_passwd.pw_dir); | |
122 | COMPACT(_pw_passwd.pw_shell); | |
123 | bcopy((char *)&_pw_passwd.pw_expire, p, sizeof(time_t)); | |
124 | p += sizeof(time_t); | |
125 | flag = p; | |
126 | *p++ = _PW_KEYBYNAME; | |
127 | content.dsize = p - buf; | |
128 | #ifdef debug | |
129 | (void)printf("store %s, uid %d\n", _pw_passwd.pw_name, | |
130 | _pw_passwd.pw_uid); | |
131 | #endif | |
132 | key.dptr = _pw_passwd.pw_name; | |
133 | key.dsize = strlen(_pw_passwd.pw_name); | |
134 | if (dbm_store(dp, key, content, DBM_INSERT) < 0) | |
135 | goto bad; | |
136 | key.dptr = (char *)&_pw_passwd.pw_uid; | |
137 | key.dsize = sizeof(int); | |
138 | *flag = _PW_KEYBYUID; | |
139 | if (dbm_store(dp, key, content, DBM_INSERT) < 0) | |
140 | goto bad; | |
141 | ||
142 | /* create original format password file entry */ | |
143 | if (!makeold) | |
144 | continue; | |
145 | fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n", _pw_passwd.pw_name, | |
146 | _pw_passwd.pw_uid, _pw_passwd.pw_gid, _pw_passwd.pw_gecos, | |
147 | _pw_passwd.pw_dir, _pw_passwd.pw_shell); | |
2b55f05a | 148 | } |
403de8f5 | 149 | dbm_close(dp); |
2b55f05a | 150 | exit(0); |
259b2b93 KB |
151 | |
152 | bad: (void)fprintf(stderr, "mkpasswd: dbm_store failed.\n"); | |
153 | rmall(*argv); | |
154 | exit(1); | |
155 | } | |
156 | ||
157 | rmall(fname) | |
158 | char *fname; | |
159 | { | |
160 | register char *p; | |
161 | char buf[MAXPATHLEN], *strcpy(); | |
162 | ||
163 | for (p = strcpy(buf, fname); *p; ++p); | |
164 | bcopy(".pag", p, 5); | |
165 | (void)unlink(buf); | |
166 | bcopy(".dir", p, 5); | |
167 | (void)unlink(buf); | |
168 | bcopy(".orig", p, 6); | |
169 | (void)unlink(buf); | |
170 | } | |
171 | ||
172 | usage() | |
173 | { | |
174 | (void)fprintf(stderr, "usage: mkpasswd [-p] passwd_file\n"); | |
175 | exit(1); | |
176 | } | |
177 | ||
178 | /* from libc/gen/getpwent.c */ | |
179 | ||
180 | static | |
181 | scanpw() | |
182 | { | |
183 | register char *cp; | |
184 | long atol(), ftell(); | |
b064a2d2 | 185 | char *bp; |
259b2b93 KB |
186 | char *fgets(), *strsep(), *index(); |
187 | ||
188 | for (;;) { | |
189 | offset = ftell(_pw_fp); | |
190 | if (!(fgets(line, sizeof(line), _pw_fp))) | |
191 | return(0); | |
192 | /* skip lines that are too big */ | |
193 | if (!index(line, '\n')) { | |
194 | int ch; | |
195 | ||
196 | while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) | |
197 | ; | |
198 | continue; | |
199 | } | |
b064a2d2 MT |
200 | bp = line; |
201 | _pw_passwd.pw_name = strsep(&bp, ":\n"); | |
202 | _pw_passwd.pw_passwd = strsep(&bp, ":\n"); | |
259b2b93 | 203 | offset += _pw_passwd.pw_passwd - line; |
b064a2d2 | 204 | if (!(cp = strsep(&bp, ":\n"))) |
259b2b93 KB |
205 | continue; |
206 | _pw_passwd.pw_uid = atoi(cp); | |
b064a2d2 | 207 | if (!(cp = strsep(&bp, ":\n"))) |
259b2b93 KB |
208 | continue; |
209 | _pw_passwd.pw_gid = atoi(cp); | |
b064a2d2 MT |
210 | _pw_passwd.pw_class = strsep(&bp, ":\n"); |
211 | if (!(cp = strsep(&bp, ":\n"))) | |
259b2b93 KB |
212 | continue; |
213 | _pw_passwd.pw_change = atol(cp); | |
b064a2d2 | 214 | if (!(cp = strsep(&bp, ":\n"))) |
259b2b93 KB |
215 | continue; |
216 | _pw_passwd.pw_expire = atol(cp); | |
b064a2d2 MT |
217 | _pw_passwd.pw_gecos = strsep(&bp, ":\n"); |
218 | _pw_passwd.pw_dir = strsep(&bp, ":\n"); | |
219 | _pw_passwd.pw_shell = strsep(&bp, ":\n"); | |
259b2b93 KB |
220 | return(1); |
221 | } | |
222 | /* NOTREACHED */ | |
2b55f05a | 223 | } |