Annotation of 43BSDTahoe/etc/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 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: #ifndef lint
        !            19: char copyright[] =
        !            20: "@(#) Copyright (c) 1987 Regents of the University of California.\n\
        !            21:  All rights reserved.\n";
        !            22: #endif /* not lint */
        !            23: 
        !            24: #ifndef lint
        !            25: static char sccsid[] = "@(#)vipw.c     5.5 (Berkeley) 6/18/88";
        !            26: #endif /* not lint */
        !            27: 
        !            28: #include <machine/machparam.h>
        !            29: #include <sys/types.h>
        !            30: #include <sys/stat.h>
        !            31: #include <sys/signal.h>
        !            32: #include <sys/file.h>
        !            33: #include <stdio.h>
        !            34: #include <errno.h>
        !            35: 
        !            36: /*
        !            37:  * Password file editor with locking.
        !            38:  */
        !            39: static char    *passwd = "/etc/passwd", buf[BUFSIZ];
        !            40: 
        !            41: main()
        !            42: {
        !            43:        register int n, fd_passwd, fd_temp;
        !            44:        static char *temp = "/etc/ptmp";
        !            45:        struct stat s1, s2;
        !            46:        char *editor, *getenv();
        !            47: 
        !            48:        (void)signal(SIGHUP, SIG_IGN);
        !            49:        (void)signal(SIGINT, SIG_IGN);
        !            50:        (void)signal(SIGQUIT, SIG_IGN);
        !            51: 
        !            52:        setbuf(stderr, (char *)NULL);
        !            53:        (void)umask(0);
        !            54: 
        !            55:        if ((fd_passwd = open(passwd, O_RDONLY, 0)) < 0) {
        !            56:                fputs("vipw: ", stderr);
        !            57:                perror(passwd);
        !            58:                exit(1);
        !            59:        }
        !            60:        if ((fd_temp = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) {
        !            61:                extern int errno;
        !            62: 
        !            63:                if (errno == EEXIST) {
        !            64:                        fputs("vipw: password file busy.\n", stderr);
        !            65:                        exit(1);
        !            66:                }
        !            67:                fputs("vipw: ", stderr);
        !            68:                perror(temp);
        !            69:                exit(1);
        !            70:        }
        !            71:        while ((n = read(fd_passwd, buf, sizeof(buf))) > 0)
        !            72:                if (write(fd_temp, buf, n) != n) {
        !            73:                        perror("vipw: write");
        !            74:                        goto bad;
        !            75:                }
        !            76:        if (n == -1) {
        !            77:                perror("vipw: read");
        !            78:                goto bad;
        !            79:        }
        !            80:        (void)close(fd_passwd);
        !            81:        if (fsync(fd_temp)) {
        !            82:                perror("vipw: fsync");
        !            83:                goto bad;
        !            84:        }
        !            85:        if (fstat(fd_temp, &s1)) {
        !            86:                perror("vipw: fstat");
        !            87:                goto bad;
        !            88:        }
        !            89:        (void)close(fd_temp);
        !            90: 
        !            91:        if (!(editor = getenv("EDITOR")))
        !            92:                editor = "vi";
        !            93:        (void)sprintf(buf, "%s %s", editor, temp);
        !            94:        if (system(buf)) {
        !            95:                perror("vipw: system");
        !            96:                goto bad;
        !            97:        }
        !            98: 
        !            99:        if (!freopen(temp, "r", stdin)) {
        !           100:                fprintf(stderr, "vipw: can't reopen temp file; %s unchanged.\n", passwd);
        !           101:                goto bad;
        !           102:        }
        !           103:        if (fstat(fileno(stdin), &s2)) {
        !           104:                fprintf(stderr, "vipw: can't stat temp file; %s unchanged.\n", passwd);
        !           105:                goto bad;
        !           106:        }
        !           107:        if (s1.st_mtime == s2.st_mtime) {
        !           108:                fprintf(stderr, "vipw: %s unchanged.\n", passwd);
        !           109:                goto bad;
        !           110:        }
        !           111:        if (!s2.st_size) {
        !           112:                fprintf(stderr, "vipw: bad temp file; %s unchanged.\n", passwd);
        !           113:                goto bad;
        !           114:        }
        !           115:        if (check()) {
        !           116:                static char     *temp_pag = "/etc/ptmp.pag",
        !           117:                                *temp_dir = "/etc/ptmp.dir",
        !           118:                                *passwd_pag = "/etc/passwd.pag",
        !           119:                                *passwd_dir = "/etc/passwd.dir";
        !           120: 
        !           121:                if (makedb(temp) < 0)
        !           122:                        fputs("vipw: mkpasswd failed.\n", stderr);
        !           123:                else if (rename(temp_pag, passwd_pag) < 0) {
        !           124:                        fprintf(stderr, "vipw: ");
        !           125:                        perror(temp_pag);
        !           126:                }
        !           127:                else if (rename(temp_dir, passwd_dir) < 0) {
        !           128:                        fprintf(stderr, "vipw: ");
        !           129:                        perror(temp_dir);
        !           130:                }
        !           131:                else if (rename(temp, passwd) < 0) {
        !           132:                        fprintf(stderr, "vipw: ");
        !           133:                        perror("rename");
        !           134:                }
        !           135:                else
        !           136:                        exit(0);
        !           137:                (void)unlink(temp_pag);
        !           138:                (void)unlink(temp_dir);
        !           139:        }
        !           140: bad:   (void)unlink(temp);
        !           141:        exit(1);
        !           142: }
        !           143: 
        !           144: #define        CHN     ((char *)NULL)
        !           145: static
        !           146: check()
        !           147: {
        !           148:        register char *cp, *sh;
        !           149:        register long id;
        !           150:        register int root;
        !           151:        long atol();
        !           152:        char *token(), *getusershell();
        !           153: 
        !           154:        for (root = 0; gets(buf); root = 0) {
        !           155:                if (!*buf) {
        !           156:                        fputs("vipw: empty line.\n", stderr);
        !           157:                        continue;
        !           158:                }
        !           159:                if (!(cp = token(buf)) || !*cp)         /* login */
        !           160:                        goto bad;
        !           161:                if (!strcmp(cp, "root"))
        !           162:                        root = 1;
        !           163:                (void)token(CHN);                       /* passwd */
        !           164:                if (!(cp = token(CHN)) || !*cp)         /* uid */
        !           165:                        goto bad;
        !           166:                id = atol(cp);
        !           167:                if (root && id) {
        !           168:                        fprintf(stderr, "vipw: root uid should be 0; %s unchanged.\n", passwd);
        !           169:                        return(0);
        !           170:                }
        !           171:                if (id > USHRT_MAX) {
        !           172:                        fprintf(stderr, "vipw: %s > max uid value (%d); %s unchanged.\n", cp, USHRT_MAX, passwd);
        !           173:                        return(0);
        !           174:                }
        !           175:                if (!(cp = token(CHN)) || !*cp)         /* gid */
        !           176:                        goto bad;
        !           177:                id = atol(cp);
        !           178:                if (id > USHRT_MAX) {
        !           179:                        fprintf(stderr, "vipw: %s > max gid value (%d); %s unchanged.\n", cp, USHRT_MAX, passwd);
        !           180:                        return(0);
        !           181:                }
        !           182:                (void)token(CHN);                       /* gcos */
        !           183:                if (!token(CHN))                        /* home directory */
        !           184:                        goto bad;
        !           185:                if (!(cp = token(CHN)))                 /* shell */
        !           186:                        goto bad;
        !           187:                if (root && *cp)                        /* empty == /bin/sh */
        !           188:                        for (;;)
        !           189:                                if (!(sh = getusershell())) {
        !           190:                                        fprintf(stderr, "vipw: illegal shell (%s) for root; %s unchanged.\n", cp, passwd);
        !           191:                                        return(0);
        !           192:                                }
        !           193:                                else if (!strcmp(cp, sh))
        !           194:                                        break;
        !           195:                if (token(CHN)) {                       /* too many fields */
        !           196: bad:                   fprintf(stderr, "vipw: corrupted entry; %s unchanged.\n", passwd);
        !           197:                        return(0);
        !           198:                }
        !           199:        }
        !           200:        return(1);
        !           201: }
        !           202: 
        !           203: static
        !           204: makedb(file)
        !           205:        char *file;
        !           206: {
        !           207:        int status, pid, w;
        !           208: 
        !           209:        if (!(pid = vfork())) {
        !           210:                execl("/etc/mkpasswd", "mkpasswd", file, 0);
        !           211:                _exit(127);
        !           212:        }
        !           213:        while ((w = wait(&status)) != pid && w != -1);
        !           214:        if (w == -1 || status)
        !           215:                return(-1);
        !           216:        return(0);
        !           217: }
        !           218: 
        !           219: static char *
        !           220: token(bfr)
        !           221:        char *bfr;
        !           222: {
        !           223:        static char *cp;
        !           224:        char *start;
        !           225: 
        !           226:        if (bfr)                        /* re-init string */
        !           227:                cp = bfr;
        !           228:        else if (!cp)                   /* check if hit EOS last time */
        !           229:                return(CHN);
        !           230:        else if (!bfr)                  /* start at next char after ':' */
        !           231:                ++cp;
        !           232:        for (start = cp;; ++cp)
        !           233:                if (!*cp) {             /* found EOS; mark it for next time */
        !           234:                        cp = CHN;
        !           235:                        break;
        !           236:                }
        !           237:                else if (*cp == ':') {  /* found ':'; end token */
        !           238:                        *cp = '\0';
        !           239:                        break;
        !           240:                }
        !           241:        return(start);                  /* return token */
        !           242: }

unix.superglobalmegacorp.com

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