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