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.6 (Berkeley) 06/01/90"; 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 55 makeold = 0; 56 while ((ch = getopt(argc, argv, "pv")) != EOF) 57 switch(ch) { 58 case 'p': /* create ``password.orig'' */ 59 makeold = 1; 60 /* FALLTHROUGH */ 61 case 'v': /* backward compatible */ 62 break; 63 case '?': 64 default: 65 usage(); 66 } 67 argc -= optind; 68 argv += optind; 69 70 if (argc != 1) 71 usage(); 72 73 if (!(_pw_fp = fopen(*argv, "r"))) { 74 (void)fprintf(stderr, 75 "mkpasswd: %s: can't open for reading.\n", *argv); 76 exit(1); 77 } 78 79 rmall(*argv); 80 (void)umask(0); 81 82 /* open old password format file, dbm files */ 83 if (makeold) { 84 int oldfd; 85 86 (void)sprintf(buf, "%s.orig", *argv); 87 if ((oldfd = open(buf, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) { 88 (void)fprintf(stderr, "mkpasswd: %s: %s\n", buf, 89 strerror(errno)); 90 exit(1); 91 } 92 if (!(oldfp = fdopen(oldfd, "w"))) { 93 (void)fprintf(stderr, "mkpasswd: %s: fdopen failed.\n", 94 buf); 95 exit(1); 96 } 97 } 98 if (!(dp = dbm_open(*argv, O_WRONLY|O_CREAT|O_EXCL, 0644))) { 99 (void)fprintf(stderr, "mkpasswd: %s: %s\n", *argv, 100 strerror(errno)); 101 exit(1); 102 } 103 104 content.dptr = buf; 105 while (scanpw()) { 106 /* create dbm entry */ 107 p = buf; 108 #define COMPACT(e) t = e; while (*p++ = *t++); 109 COMPACT(_pw_passwd.pw_name); 110 (void)sprintf(nbuf, "%ld", offset); 111 COMPACT(nbuf); 112 bcopy((char *)&_pw_passwd.pw_uid, p, sizeof(int)); 113 p += sizeof(int); 114 bcopy((char *)&_pw_passwd.pw_gid, p, sizeof(int)); 115 p += sizeof(int); 116 bcopy((char *)&_pw_passwd.pw_change, p, sizeof(time_t)); 117 p += sizeof(time_t); 118 COMPACT(_pw_passwd.pw_class); 119 COMPACT(_pw_passwd.pw_gecos); 120 COMPACT(_pw_passwd.pw_dir); 121 COMPACT(_pw_passwd.pw_shell); 122 bcopy((char *)&_pw_passwd.pw_expire, p, sizeof(time_t)); 123 p += sizeof(time_t); 124 flag = p; 125 *p++ = _PW_KEYBYNAME; 126 content.dsize = p - buf; 127 #ifdef debug 128 (void)printf("store %s, uid %d\n", _pw_passwd.pw_name, 129 _pw_passwd.pw_uid); 130 #endif 131 key.dptr = _pw_passwd.pw_name; 132 key.dsize = strlen(_pw_passwd.pw_name); 133 if (dbm_store(dp, key, content, DBM_INSERT) < 0) 134 goto bad; 135 key.dptr = (char *)&_pw_passwd.pw_uid; 136 key.dsize = sizeof(int); 137 *flag = _PW_KEYBYUID; 138 if (dbm_store(dp, key, content, DBM_INSERT) < 0) 139 goto bad; 140 141 /* create original format password file entry */ 142 if (!makeold) 143 continue; 144 fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n", _pw_passwd.pw_name, 145 _pw_passwd.pw_uid, _pw_passwd.pw_gid, _pw_passwd.pw_gecos, 146 _pw_passwd.pw_dir, _pw_passwd.pw_shell); 147 } 148 dbm_close(dp); 149 exit(0); 150 151 bad: (void)fprintf(stderr, "mkpasswd: dbm_store failed.\n"); 152 rmall(*argv); 153 exit(1); 154 } 155 156 rmall(fname) 157 char *fname; 158 { 159 register char *p; 160 char buf[MAXPATHLEN], *strcpy(); 161 162 for (p = strcpy(buf, fname); *p; ++p); 163 bcopy(".pag", p, 5); 164 (void)unlink(buf); 165 bcopy(".dir", p, 5); 166 (void)unlink(buf); 167 bcopy(".orig", p, 6); 168 (void)unlink(buf); 169 } 170 171 usage() 172 { 173 (void)fprintf(stderr, "usage: mkpasswd [-p] passwd_file\n"); 174 exit(1); 175 } 176 177 /* from libc/gen/getpwent.c */ 178 179 static 180 scanpw() 181 { 182 register char *cp; 183 long atol(), ftell(); 184 char *bp; 185 char *fgets(), *strsep(), *index(); 186 187 for (;;) { 188 offset = ftell(_pw_fp); 189 if (!(fgets(line, sizeof(line), _pw_fp))) 190 return(0); 191 /* skip lines that are too big */ 192 if (!index(line, '\n')) { 193 int ch; 194 195 while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) 196 ; 197 continue; 198 } 199 bp = line; 200 _pw_passwd.pw_name = strsep(&bp, ":\n"); 201 _pw_passwd.pw_passwd = strsep(&bp, ":\n"); 202 offset += _pw_passwd.pw_passwd - line; 203 if (!(cp = strsep(&bp, ":\n"))) 204 continue; 205 _pw_passwd.pw_uid = atoi(cp); 206 if (!(cp = strsep(&bp, ":\n"))) 207 continue; 208 _pw_passwd.pw_gid = atoi(cp); 209 _pw_passwd.pw_class = strsep(&bp, ":\n"); 210 if (!(cp = strsep(&bp, ":\n"))) 211 continue; 212 _pw_passwd.pw_change = atol(cp); 213 if (!(cp = strsep(&bp, ":\n"))) 214 continue; 215 _pw_passwd.pw_expire = atol(cp); 216 _pw_passwd.pw_gecos = strsep(&bp, ":\n"); 217 _pw_passwd.pw_dir = strsep(&bp, ":\n"); 218 _pw_passwd.pw_shell = strsep(&bp, ":\n"); 219 return(1); 220 } 221 /* NOTREACHED */ 222 } 223