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