|
|
1.1 root 1: /*
2: * Copyright (c) 1980, 1983 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: char copyright[] =
22: "@(#) Copyright (c) 1980, 1983 Regents of the University of California.\n\
23: All rights reserved.\n";
24: #endif /* not lint */
25:
26: #ifndef lint
27: static char sccsid[] = "@(#)mkpasswd.c 5.6 (Berkeley) 6/1/90";
28: #endif /* not lint */
29:
30: #include <sys/param.h>
31: #include <sys/file.h>
32: #include <ndbm.h>
33: #include <pwd.h>
34: #include <stdio.h>
35:
36: static FILE *_pw_fp;
37: static struct passwd _pw_passwd;
38: static off_t offset;
39:
40: #define MAXLINELENGTH 1024
41: static char line[MAXLINELENGTH];
42:
43: /*
44: * Mkpasswd does two things -- use the ``arg'' file to create ``arg''.{pag,dir}
45: * for ndbm, and, if the -p flag is on, create a password file in the original
46: * format. It doesn't use the getpwent(3) routines because it has to figure
47: * out offsets for the encrypted passwords to put in the dbm files. One other
48: * problem is that, since the addition of shadow passwords, getpwent(3) has to
49: * use the dbm databases rather than simply scanning the actual file. This
50: * required the addition of a flag field to the dbm database to distinguish
51: * between a record keyed by name, and one keyed by uid.
52: */
53:
54: main(argc, argv)
55: int argc;
56: char **argv;
57: {
58: extern int errno, optind;
59: register char *flag, *p, *t;
60: register int makeold;
61: FILE *oldfp;
62: DBM *dp;
63: datum key, content;
64: int ch;
65: char buf[8192], nbuf[50], *strerror();
66:
67: makeold = 0;
68: while ((ch = getopt(argc, argv, "pv")) != EOF)
69: switch(ch) {
70: case 'p': /* create ``password.orig'' */
71: makeold = 1;
72: /* FALLTHROUGH */
73: case 'v': /* backward compatible */
74: break;
75: case '?':
76: default:
77: usage();
78: }
79: argc -= optind;
80: argv += optind;
81:
82: if (argc != 1)
83: usage();
84:
85: if (!(_pw_fp = fopen(*argv, "r"))) {
86: (void)fprintf(stderr,
87: "mkpasswd: %s: can't open for reading.\n", *argv);
88: exit(1);
89: }
90:
91: rmall(*argv);
92: (void)umask(0);
93:
94: /* open old password format file, dbm files */
95: if (makeold) {
96: int oldfd;
97:
98: (void)sprintf(buf, "%s.orig", *argv);
99: if ((oldfd = open(buf, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) {
100: (void)fprintf(stderr, "mkpasswd: %s: %s\n", buf,
101: strerror(errno));
102: exit(1);
103: }
104: if (!(oldfp = fdopen(oldfd, "w"))) {
105: (void)fprintf(stderr, "mkpasswd: %s: fdopen failed.\n",
106: buf);
107: exit(1);
108: }
109: }
110: if (!(dp = dbm_open(*argv, O_WRONLY|O_CREAT|O_EXCL, 0644))) {
111: (void)fprintf(stderr, "mkpasswd: %s: %s\n", *argv,
112: strerror(errno));
113: exit(1);
114: }
115:
116: content.dptr = buf;
117: while (scanpw()) {
118: /* create dbm entry */
119: p = buf;
120: #define COMPACT(e) t = e; while (*p++ = *t++);
121: COMPACT(_pw_passwd.pw_name);
122: (void)sprintf(nbuf, "%ld", offset);
123: COMPACT(nbuf);
124: bcopy((char *)&_pw_passwd.pw_uid, p, sizeof(int));
125: p += sizeof(int);
126: bcopy((char *)&_pw_passwd.pw_gid, p, sizeof(int));
127: p += sizeof(int);
128: bcopy((char *)&_pw_passwd.pw_change, p, sizeof(time_t));
129: p += sizeof(time_t);
130: COMPACT(_pw_passwd.pw_class);
131: COMPACT(_pw_passwd.pw_gecos);
132: COMPACT(_pw_passwd.pw_dir);
133: COMPACT(_pw_passwd.pw_shell);
134: bcopy((char *)&_pw_passwd.pw_expire, p, sizeof(time_t));
135: p += sizeof(time_t);
136: flag = p;
137: *p++ = _PW_KEYBYNAME;
138: content.dsize = p - buf;
139: #ifdef debug
140: (void)printf("store %s, uid %d\n", _pw_passwd.pw_name,
141: _pw_passwd.pw_uid);
142: #endif
143: key.dptr = _pw_passwd.pw_name;
144: key.dsize = strlen(_pw_passwd.pw_name);
145: if (dbm_store(dp, key, content, DBM_INSERT) < 0)
146: goto bad;
147: key.dptr = (char *)&_pw_passwd.pw_uid;
148: key.dsize = sizeof(int);
149: *flag = _PW_KEYBYUID;
150: if (dbm_store(dp, key, content, DBM_INSERT) < 0)
151: goto bad;
152:
153: /* create original format password file entry */
154: if (!makeold)
155: continue;
156: fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n", _pw_passwd.pw_name,
157: _pw_passwd.pw_uid, _pw_passwd.pw_gid, _pw_passwd.pw_gecos,
158: _pw_passwd.pw_dir, _pw_passwd.pw_shell);
159: }
160: dbm_close(dp);
161: exit(0);
162:
163: bad: (void)fprintf(stderr, "mkpasswd: dbm_store failed.\n");
164: rmall(*argv);
165: exit(1);
166: }
167:
168: rmall(fname)
169: char *fname;
170: {
171: register char *p;
172: char buf[MAXPATHLEN], *strcpy();
173:
174: for (p = strcpy(buf, fname); *p; ++p);
175: bcopy(".pag", p, 5);
176: (void)unlink(buf);
177: bcopy(".dir", p, 5);
178: (void)unlink(buf);
179: bcopy(".orig", p, 6);
180: (void)unlink(buf);
181: }
182:
183: usage()
184: {
185: (void)fprintf(stderr, "usage: mkpasswd [-p] passwd_file\n");
186: exit(1);
187: }
188:
189: /* from libc/gen/getpwent.c */
190:
191: static
192: scanpw()
193: {
194: register char *cp;
195: long atol(), ftell();
196: char *bp;
197: char *fgets(), *strsep(), *index();
198:
199: for (;;) {
200: offset = ftell(_pw_fp);
201: if (!(fgets(line, sizeof(line), _pw_fp)))
202: return(0);
203: /* skip lines that are too big */
204: if (!index(line, '\n')) {
205: int ch;
206:
207: while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
208: ;
209: continue;
210: }
211: bp = line;
212: _pw_passwd.pw_name = strsep(&bp, ":\n");
213: _pw_passwd.pw_passwd = strsep(&bp, ":\n");
214: offset += _pw_passwd.pw_passwd - line;
215: if (!(cp = strsep(&bp, ":\n")))
216: continue;
217: _pw_passwd.pw_uid = atoi(cp);
218: if (!(cp = strsep(&bp, ":\n")))
219: continue;
220: _pw_passwd.pw_gid = atoi(cp);
221: _pw_passwd.pw_class = strsep(&bp, ":\n");
222: if (!(cp = strsep(&bp, ":\n")))
223: continue;
224: _pw_passwd.pw_change = atol(cp);
225: if (!(cp = strsep(&bp, ":\n")))
226: continue;
227: _pw_passwd.pw_expire = atol(cp);
228: _pw_passwd.pw_gecos = strsep(&bp, ":\n");
229: _pw_passwd.pw_dir = strsep(&bp, ":\n");
230: _pw_passwd.pw_shell = strsep(&bp, ":\n");
231: return(1);
232: }
233: /* NOTREACHED */
234: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.