Annotation of 43BSDTahoe/etc/vipw.c, revision 1.1.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.