xref: /original-bsd/old/mkpasswd/mkpasswd.c (revision 909c03fb)
1 /*
2  * Copyright (c) 1980, 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1980, 1983 Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)mkpasswd.c	5.7 (Berkeley) 07/17/92";
16 #endif /* not lint */
17 
18 #include <sys/param.h>
19 #include <sys/file.h>
20 #include <ndbm.h>
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  */
41 
42 main(argc, argv)
43 	int argc;
44 	char **argv;
45 {
46 	extern int errno, optind;
47 	register char *flag, *p, *t;
48 	register int makeold;
49 	FILE *oldfp;
50 	DBM *dp;
51 	datum key, content;
52 	int ch;
53 	char buf[8192], nbuf[50], *strerror();
54 	static int scanpw();
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);
77 		exit(1);
78 	}
79 
80 	rmall(*argv);
81 	(void)umask(0);
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));
91 			exit(1);
92 		}
93 		if (!(oldfp = fdopen(oldfd, "w"))) {
94 			(void)fprintf(stderr, "mkpasswd: %s: fdopen failed.\n",
95 			    buf);
96 			exit(1);
97 		}
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);
148 	}
149 	dbm_close(dp);
150 	exit(0);
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();
185 	char *bp;
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 		}
200 		bp = line;
201 		_pw_passwd.pw_name = strsep(&bp, ":\n");
202 		_pw_passwd.pw_passwd = strsep(&bp, ":\n");
203 		offset += _pw_passwd.pw_passwd - line;
204 		if (!(cp = strsep(&bp, ":\n")))
205 			continue;
206 		_pw_passwd.pw_uid = atoi(cp);
207 		if (!(cp = strsep(&bp, ":\n")))
208 			continue;
209 		_pw_passwd.pw_gid = atoi(cp);
210 		_pw_passwd.pw_class = strsep(&bp, ":\n");
211 		if (!(cp = strsep(&bp, ":\n")))
212 			continue;
213 		_pw_passwd.pw_change = atol(cp);
214 		if (!(cp = strsep(&bp, ":\n")))
215 			continue;
216 		_pw_passwd.pw_expire = atol(cp);
217 		_pw_passwd.pw_gecos = strsep(&bp, ":\n");
218 		_pw_passwd.pw_dir = strsep(&bp, ":\n");
219 		_pw_passwd.pw_shell = strsep(&bp, ":\n");
220 		return(1);
221 	}
222 	/* NOTREACHED */
223 }
224