Annotation of 43BSDReno/sbin/vipw/vipw.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1987 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: (1) source distributions retain this entire copyright
        !             7:  * notice and comment, and (2) distributions including binaries display
        !             8:  * the following acknowledgement:  ``This product includes software
        !             9:  * developed by the University of California, Berkeley and its contributors''
        !            10:  * in the documentation or other materials provided with the distribution
        !            11:  * and in all advertising materials mentioning features or use of this
        !            12:  * software. Neither the name of the University nor the names of its
        !            13:  * contributors may be used to endorse or promote products derived
        !            14:  * from this software without specific prior written permission.
        !            15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
        !            16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
        !            17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            18:  */
        !            19: 
        !            20: #ifndef lint
        !            21: char copyright[] =
        !            22: "@(#) Copyright (c) 1987 Regents of the University of California.\n\
        !            23:  All rights reserved.\n";
        !            24: #endif /* not lint */
        !            25: 
        !            26: #ifndef lint
        !            27: static char sccsid[] = "@(#)vipw.c     5.14 (Berkeley) 6/1/90";
        !            28: #endif /* not lint */
        !            29: 
        !            30: #include <sys/param.h>
        !            31: #include <sys/stat.h>
        !            32: #include <sys/signal.h>
        !            33: #include <sys/file.h>
        !            34: #include <sys/time.h>
        !            35: #include <sys/resource.h>
        !            36: #include <errno.h>
        !            37: #include <pwd.h>
        !            38: #include <stdio.h>
        !            39: #include <string.h>
        !            40: 
        !            41: char *passwd, *temp;
        !            42: 
        !            43: main()
        !            44: {
        !            45:        extern int errno;
        !            46:        register int n, fd_passwd, fd;
        !            47:        struct rlimit rlim;
        !            48:        struct stat s1, s2;
        !            49:        FILE *tfp;
        !            50:        char *fend, *tend;
        !            51:        char buf[8*1024], from[MAXPATHLEN], to[MAXPATHLEN];
        !            52: 
        !            53:        (void)signal(SIGHUP, SIG_IGN);
        !            54:        (void)signal(SIGINT, SIG_IGN);
        !            55:        (void)signal(SIGQUIT, SIG_IGN);
        !            56:        (void)signal(SIGTSTP, SIG_IGN);
        !            57: 
        !            58:        rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
        !            59:        (void)setrlimit(RLIMIT_CPU, &rlim);
        !            60:        (void)setrlimit(RLIMIT_FSIZE, &rlim);
        !            61: 
        !            62:        (void)umask(0);
        !            63: 
        !            64:        temp = _PATH_PTMP;
        !            65:        if ((fd = open(temp, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0) {
        !            66:                if (errno == EEXIST)
        !            67:                        (void)fprintf(stderr, "vipw: password file busy.\n");
        !            68:                else
        !            69:                        (void)fprintf(stderr,
        !            70:                            "vipw: %s: %s\n", temp, strerror(errno));
        !            71:                exit(1);
        !            72:        }
        !            73:        passwd = _PATH_MASTERPASSWD;
        !            74:        if ((fd_passwd = open(passwd, O_RDONLY, 0)) < 0) {
        !            75:                (void)fprintf(stderr, "vipw: %s: %s\n", passwd,
        !            76:                    strerror(errno));
        !            77:                exit(1);
        !            78:        }
        !            79:        while ((n = read(fd_passwd, buf, sizeof(buf))) > 0)
        !            80:                if (write(fd, buf, n) != n)
        !            81:                        goto syserr;
        !            82: 
        !            83:        if (n == -1 || close(fd_passwd)) {
        !            84: syserr:                (void)fprintf(stderr, "vipw: %s: %s; ",
        !            85:                    passwd, strerror(errno));
        !            86:                stop(1);
        !            87:        }
        !            88: 
        !            89:        (void)fstat(fd, &s1);
        !            90:        (void)close(fd);
        !            91:        for (;;) {
        !            92:                if (edit()) {
        !            93:                        (void)fprintf(stderr, "vipw: edit failed; ");
        !            94:                        stop(1);
        !            95:                }
        !            96:                /*
        !            97:                 * close and re-open the file each time we edit it; some
        !            98:                 * editors create a new physical file on each edit session.
        !            99:                 */
        !           100:                if (!(tfp = fopen(temp, "r"))) {
        !           101:                        (void)fprintf(stderr, "vipw: %s: %s; ",
        !           102:                            temp, strerror(errno));
        !           103:                        stop(1);
        !           104:                }
        !           105:                (void)fstat(fileno(tfp), &s2);
        !           106:                if (s1.st_mtime == s2.st_mtime) {
        !           107:                        (void)fprintf(stderr, "vipw: no changes made; ");
        !           108:                        stop(0);
        !           109:                }
        !           110:                if (!check(tfp))
        !           111:                        break;
        !           112:                if (prompt())
        !           113:                        stop(0);
        !           114:                (void)fstat(fileno(tfp), &s1);
        !           115:                (void)fclose(tfp);
        !           116:        }
        !           117: 
        !           118:        switch(fork()) {
        !           119:        case 0:
        !           120:                break;
        !           121:        case -1:
        !           122:                (void)fprintf(stderr, "vipw: can't fork; ");
        !           123:                stop(1);
        !           124:                /* NOTREACHED */
        !           125:        default:
        !           126:                exit(0);
        !           127:                /* NOTREACHED */
        !           128:        }
        !           129: 
        !           130:        if (makedb(temp)) {
        !           131:                (void)fprintf(stderr, "vipw: mkpasswd failed; ");
        !           132:                stop(1);
        !           133:        }
        !           134: 
        !           135:        /*
        !           136:         * possible race; have to rename four files, and someone could slip
        !           137:         * in between them.  LOCK_EX and rename the ``passwd.dir'' file first
        !           138:         * so that getpwent(3) can't slip in; the lock should never fail and
        !           139:         * it's unclear what to do if it does.  Rename ``ptmp'' last so that
        !           140:         * passwd/vipw/chpass can't slip in.
        !           141:         */
        !           142:        (void)setpriority(PRIO_PROCESS, 0, -20);
        !           143:        fend = strcpy(from, temp) + strlen(temp);
        !           144:        tend = strcpy(to, _PATH_PASSWD) + strlen(_PATH_PASSWD);
        !           145:        bcopy(".dir", fend, 5);
        !           146:        bcopy(".dir", tend, 5);
        !           147:        if ((fd = open(from, O_RDONLY, 0)) >= 0)
        !           148:                (void)flock(fd, LOCK_EX);
        !           149:        /* here we go... */
        !           150:        (void)rename(from, to);
        !           151:        bcopy(".pag", fend, 5);
        !           152:        bcopy(".pag", tend, 5);
        !           153:        (void)rename(from, to);
        !           154:        bcopy(".orig", fend, 6);
        !           155:        (void)rename(from, _PATH_PASSWD);
        !           156:        (void)rename(temp, passwd);
        !           157:        /* done! */
        !           158:        exit(0);
        !           159: }
        !           160: 
        !           161: check(tfp)
        !           162:        FILE *tfp;
        !           163: {
        !           164:        register long id;
        !           165:        register int lcnt, root;
        !           166:        register char *p, *sh;
        !           167:        long atol();
        !           168:        char buf[1024], *bp, *getusershell();
        !           169: 
        !           170:        for (lcnt = 1; fgets(buf, sizeof(buf), tfp); ++lcnt) {
        !           171:                /* skip lines that are too big */
        !           172:                if (!(p = index(buf, '\n'))) {
        !           173:                        (void)fprintf(stderr, "vipw: line too long");
        !           174:                        goto bad;
        !           175:                }
        !           176:                *p = '\0';
        !           177:                bp = buf;
        !           178:                if (!(p = strsep(&bp, ":")))            /* login */
        !           179:                        goto general;
        !           180:                root = !strcmp(p, "root");
        !           181:                (void)strsep(&bp, ":"); /* passwd */
        !           182:                if (!(p = strsep(&bp, ":")))    /* uid */
        !           183:                        goto general;
        !           184:                id = atol(p);
        !           185:                if (root && id) {
        !           186:                        (void)fprintf(stderr, "vipw: root uid should be 0");
        !           187:                        goto bad;
        !           188:                }
        !           189:                if (id > USHRT_MAX) {
        !           190:                        (void)fprintf(stderr, "vipw: %s > max uid value (%d)",
        !           191:                            p, USHRT_MAX);
        !           192:                        goto bad;
        !           193:                }
        !           194:                if (!(p = strsep(&bp, ":")))    /* gid */
        !           195:                        goto general;
        !           196:                id = atol(p);
        !           197:                if (id > USHRT_MAX) {
        !           198:                        (void)fprintf(stderr, "vipw: %s > max gid value (%d)",
        !           199:                            p, USHRT_MAX);
        !           200:                        goto bad;
        !           201:                }
        !           202:                (void)strsep(&bp, ":"); /* class */
        !           203:                (void)strsep(&bp, ":"); /* change */
        !           204:                (void)strsep(&bp, ":"); /* expire */
        !           205:                (void)strsep(&bp, ":"); /* gecos */
        !           206:                (void)strsep(&bp, ":"); /* directory */
        !           207:                if (!(p = strsep(&bp, ":")))    /* shell */
        !           208:                        goto general;
        !           209:                if (root && *p)                         /* empty == /bin/sh */
        !           210:                        for (setusershell();;)
        !           211:                                if (!(sh = getusershell())) {
        !           212:                                        (void)fprintf(stderr,
        !           213:                                            "vipw: warning, unknown root shell.\n");
        !           214:                                        break;
        !           215:                                }
        !           216:                                else if (!strcmp(p, sh))
        !           217:                                        break;
        !           218:                if (p = strsep(&bp, ":")) {     /* too many */
        !           219: (void)fprintf(stderr, "got {%s}\n", p);
        !           220: general:               (void)fprintf(stderr, "vipw: corrupted entry");
        !           221: bad:                   (void)fprintf(stderr, "; line #%d.\n", lcnt);
        !           222:                        (void)fflush(stderr);
        !           223:                        return(1);
        !           224:                }
        !           225:        }
        !           226:        return(0);
        !           227: }
        !           228: 
        !           229: makedb(file)
        !           230:        char *file;
        !           231: {
        !           232:        int status, pid, w;
        !           233: 
        !           234:        if (!(pid = vfork())) {
        !           235:                execl(_PATH_MKPASSWD, "mkpasswd", "-p", file, NULL);
        !           236:                _exit(127);
        !           237:        }
        !           238:        while ((w = wait(&status)) != pid && w != -1);
        !           239:        return(w == -1 || status);
        !           240: }
        !           241: 
        !           242: edit()
        !           243: {
        !           244:        extern int errno;
        !           245:        int status, pid, w;
        !           246:        char *p, *editor, *getenv(), *strerror();
        !           247: 
        !           248:        if (editor = getenv("EDITOR")) {
        !           249:                if (p = rindex(editor, '/'))
        !           250:                        ++p;
        !           251:                else
        !           252:                        p = editor;
        !           253:        }
        !           254:        else
        !           255:                p = editor = "vi";
        !           256:        if (!(pid = vfork())) {
        !           257:                execlp(editor, p, temp, NULL);
        !           258:                (void)fprintf(stderr, "vipw: %s: %s\n", editor,
        !           259:                    strerror(errno));
        !           260:                _exit(127);
        !           261:        }
        !           262:        while ((w = wait(&status)) != pid && w != -1);
        !           263:        return(w == -1 || status);
        !           264: }
        !           265: 
        !           266: prompt()
        !           267: {
        !           268:        register int c;
        !           269: 
        !           270:        for (;;) {
        !           271:                (void)printf("re-edit the password file? [y]: ");
        !           272:                (void)fflush(stdout);
        !           273:                c = getchar();
        !           274:                if (c != EOF && c != (int)'\n')
        !           275:                        while (getchar() != (int)'\n');
        !           276:                return(c == (int)'n');
        !           277:        }
        !           278:        /* NOTREACHED */
        !           279: }
        !           280: 
        !           281: stop(val)
        !           282:        int val;
        !           283: {
        !           284:        (void)fprintf(stderr, "%s unchanged.\n", passwd);
        !           285:        (void)unlink(temp);
        !           286:        exit(val);
        !           287: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.