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