Annotation of 43BSDTahoe/etc/edquota.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 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) 1980 Regents of the University of California.\n\
                     21:  All rights reserved.\n";
                     22: #endif /* not lint */
                     23: 
                     24: #ifndef lint
                     25: static char sccsid[] = "@(#)edquota.c  5.6 (Berkeley) 6/18/88";
                     26: #endif /* not lint */
                     27: 
                     28: /*
                     29:  * Disk quota editor.
                     30:  */
                     31: #include <stdio.h>
                     32: #include <signal.h>
                     33: #include <errno.h>
                     34: #include <pwd.h>
                     35: #include <ctype.h>
                     36: #include <fstab.h>
                     37: 
                     38: #include <sys/param.h>
                     39: #include <sys/stat.h>
                     40: #include <sys/file.h>
                     41: #include <sys/quota.h>
                     42: 
                     43: #define        DEFEDITOR       "/usr/ucb/vi"
                     44: 
                     45: struct dquot dq[NMOUNT];
                     46: struct dquot odq[NMOUNT];
                     47: char   dqf[NMOUNT][MAXPATHLEN + 1];
                     48: char   odqf[NMOUNT][MAXPATHLEN + 1];
                     49: 
                     50: char   tmpfil[] = "/tmp/EdP.aXXXXX";
                     51: char   *qfname = "quotas";
                     52: char   *getenv();
                     53: 
                     54: main(argc, argv)
                     55:        char **argv;
                     56: {
                     57:        int uid;
                     58:        char *arg0;
                     59: 
                     60:        mktemp(tmpfil);
                     61:        close(creat(tmpfil, 0600));
                     62:        chown(tmpfil, getuid(), getgid());
                     63:        arg0 = *argv++;
                     64:        if (argc < 2) {
                     65:                fprintf(stderr, "Usage: %s [-p username] username ...\n", arg0);
                     66:                unlink(tmpfil);
                     67:                exit(1);
                     68:        }
                     69:        --argc;
                     70:        if (getuid()) {
                     71:                fprintf(stderr, "%s: permission denied\n", arg0);
                     72:                unlink(tmpfil);
                     73:                exit(1);
                     74:        }
                     75:        if (argc > 2 && strcmp(*argv, "-p") == 0) {
                     76:                argc--, argv++;
                     77:                uid = getentry(*argv++);
                     78:                if (uid < 0) {
                     79:                        unlink(tmpfil);
                     80:                        exit(1);
                     81:                }
                     82:                getprivs(uid);
                     83:                argc--;
                     84:                while (argc-- > 0) {
                     85:                        uid = getentry(*argv++);
                     86:                        if (uid < 0)
                     87:                                continue;
                     88:                        getdiscq(uid, odq, odqf);
                     89:                        putprivs(uid);
                     90:                }
                     91:                unlink(tmpfil);
                     92:                exit(0);
                     93:        }
                     94:        while (--argc >= 0) {
                     95:                uid = getentry(*argv++);
                     96:                if (uid < 0)
                     97:                        continue;
                     98:                getprivs(uid);
                     99:                if (editit())
                    100:                        putprivs(uid);
                    101:        }
                    102:        unlink(tmpfil);
                    103:        exit(0);
                    104: }
                    105: 
                    106: getentry(name)
                    107:        char *name;
                    108: {
                    109:        struct passwd *pw;
                    110:        int uid;
                    111: 
                    112:        if (alldigits(name))
                    113:                uid = atoi(name);
                    114:        else if (pw = getpwnam(name))
                    115:                uid = pw->pw_uid;
                    116:        else {
                    117:                fprintf(stderr, "%s: no such user\n", name);
                    118:                sleep(1);
                    119:                return (-1);
                    120:        }
                    121:        return (uid);
                    122: }
                    123: 
                    124: editit()
                    125: {
                    126:        register int pid, xpid;
                    127:        long omask;
                    128:        int stat;
                    129: 
                    130:        omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
                    131:  top:
                    132:        if ((pid = fork()) < 0) {
                    133:                extern errno;
                    134: 
                    135:                if (errno == EPROCLIM) {
                    136:                        fprintf(stderr, "You have too many processes\n");
                    137:                        return(0);
                    138:                }
                    139:                if (errno == EAGAIN) {
                    140:                        sleep(1);
                    141:                        goto top;
                    142:                }
                    143:                perror("fork");
                    144:                return (0);
                    145:        }
                    146:        if (pid == 0) {
                    147:                register char *ed;
                    148: 
                    149:                sigsetmask(omask);
                    150:                setgid(getgid());
                    151:                setuid(getuid());
                    152:                if ((ed = getenv("EDITOR")) == (char *)0)
                    153:                        ed = DEFEDITOR;
                    154:                execlp(ed, ed, tmpfil, 0);
                    155:                perror(ed);
                    156:                exit(1);
                    157:        }
                    158:        while ((xpid = wait(&stat)) >= 0)
                    159:                if (xpid == pid)
                    160:                        break;
                    161:        sigsetmask(omask);
                    162:        return (!stat);
                    163: }
                    164: 
                    165: getprivs(uid)
                    166:        register uid;
                    167: {
                    168:        register i;
                    169:        FILE *fd;
                    170: 
                    171:        getdiscq(uid, dq, dqf);
                    172:        for (i = 0; i < NMOUNT; i++) {
                    173:                odq[i] = dq[i];
                    174:                strcpy(odqf[i], dqf[i]);
                    175:        }
                    176:        if ((fd = fopen(tmpfil, "w")) == NULL) {
                    177:                fprintf(stderr, "edquota: ");
                    178:                perror(tmpfil);
                    179:                exit(1);
                    180:        }
                    181:        for (i = 0; i < NMOUNT; i++) {
                    182:                if (*dqf[i] == '\0')
                    183:                        continue;
                    184:                fprintf(fd,
                    185: "fs %s blocks (soft = %d, hard = %d) inodes (soft = %d, hard = %d)\n"
                    186:                        , dqf[i]
                    187:                        , dbtob(dq[i].dq_bsoftlimit) / 1024
                    188:                        , dbtob(dq[i].dq_bhardlimit) / 1024
                    189:                        , dq[i].dq_isoftlimit
                    190:                        , dq[i].dq_ihardlimit
                    191:                );
                    192:        }
                    193:        fclose(fd);
                    194: }
                    195: 
                    196: putprivs(uid)
                    197:        register uid;
                    198: {
                    199:        register i, j;
                    200:        int n;
                    201:        FILE *fd;
                    202:        char line[BUFSIZ];
                    203: 
                    204:        fd = fopen(tmpfil, "r");
                    205:        if (fd == NULL) {
                    206:                fprintf(stderr, "Can't re-read temp file!!\n");
                    207:                return;
                    208:        }
                    209:        for (i = 0; i < NMOUNT; i++) {
                    210:                char *cp, *dp, *next();
                    211: 
                    212:                if (fgets(line, sizeof (line), fd) == NULL)
                    213:                        break;
                    214:                cp = next(line, " \t");
                    215:                if (cp == NULL)
                    216:                        break;
                    217:                *cp++ = '\0';
                    218:                while (*cp && *cp == '\t' && *cp == ' ')
                    219:                        cp++;
                    220:                dp = cp, cp = next(cp, " \t");
                    221:                if (cp == NULL)
                    222:                        break;
                    223:                *cp++ = '\0';
                    224:                while (*cp && *cp == '\t' && *cp == ' ')
                    225:                        cp++;
                    226:                strcpy(dqf[i], dp);
                    227:                n = sscanf(cp,
                    228: "blocks (soft = %d, hard = %d) inodes (soft = %hd, hard = %hd)\n"
                    229:                        , &dq[i].dq_bsoftlimit
                    230:                        , &dq[i].dq_bhardlimit
                    231:                        , &dq[i].dq_isoftlimit
                    232:                        , &dq[i].dq_ihardlimit
                    233:                );
                    234:                if (n != 4) {
                    235:                        fprintf(stderr, "%s: bad format\n", cp);
                    236:                        continue;
                    237:                }
                    238:                dq[i].dq_bsoftlimit = btodb(dq[i].dq_bsoftlimit * 1024);
                    239:                dq[i].dq_bhardlimit = btodb(dq[i].dq_bhardlimit * 1024);
                    240:        }
                    241:        fclose(fd);
                    242:        n = i;
                    243:        for (i = 0; i < n; i++) {
                    244:                if (*dqf[i] == '\0')
                    245:                        break;
                    246:                for (j = 0; j < NMOUNT; j++) {
                    247:                        if (strcmp(dqf[i], odqf[j]) == 0)
                    248:                                break;
                    249:                }
                    250:                if (j >= NMOUNT)
                    251:                        continue;
                    252:                *odqf[j] = '\0';
                    253:                /*
                    254:                 * This isn't really good enough, it is quite likely
                    255:                 * to have changed while we have been away editing,
                    256:                 * but it's not important enough to worry about at
                    257:                 * the minute.
                    258:                 */
                    259:                dq[i].dq_curblocks = odq[j].dq_curblocks;
                    260:                dq[i].dq_curinodes = odq[j].dq_curinodes;
                    261:                /*
                    262:                 * If we've upped the inode or disk block limits
                    263:                 * and the guy is out of warnings, reinitialize.
                    264:                 */
                    265:                if (dq[i].dq_bsoftlimit > odq[j].dq_bsoftlimit &&
                    266:                    dq[i].dq_bwarn == 0)
                    267:                        dq[i].dq_bwarn = MAX_DQ_WARN;
                    268:                if (dq[i].dq_isoftlimit > odq[j].dq_isoftlimit &&
                    269:                    dq[i].dq_iwarn == 0)
                    270:                        dq[i].dq_iwarn = MAX_IQ_WARN;
                    271:        }
                    272:        if (i < NMOUNT) {
                    273:                for (j = 0; j < NMOUNT; j++) {
                    274:                        if (*odqf[j] == '\0')
                    275:                                continue;
                    276:                        strcpy(dqf[i], odqf[j]);
                    277:                        dq[i].dq_isoftlimit = 0;
                    278:                        dq[i].dq_ihardlimit = 0;
                    279:                        dq[i].dq_bsoftlimit = 0;
                    280:                        dq[i].dq_bhardlimit = 0;
                    281:                        /*
                    282:                         * Same applies as just above
                    283:                         * but matters not at all, as we are just
                    284:                         * turning quota'ing off for this filesys.
                    285:                         */
                    286:                        dq[i].dq_curblocks = odq[j].dq_curblocks;
                    287:                        dq[i].dq_curinodes = odq[j].dq_curinodes;
                    288:                        if (++i >= NMOUNT)
                    289:                                break;
                    290:                }
                    291:        }
                    292:        if (*dqf[0])
                    293:                putdiscq(uid, dq, dqf);
                    294: }
                    295: 
                    296: char *
                    297: next(cp, match)
                    298:        register char *cp;
                    299:        char *match;
                    300: {
                    301:        register char *dp;
                    302: 
                    303:        while (cp && *cp) {
                    304:                for (dp = match; dp && *dp; dp++)
                    305:                        if (*dp == *cp)
                    306:                                return (cp);
                    307:                cp++;
                    308:        }
                    309:        return ((char *)0);
                    310: }
                    311: 
                    312: alldigits(s)
                    313:        register char *s;
                    314: {
                    315:        register c;
                    316: 
                    317:        c = *s++;
                    318:        do {
                    319:                if (!isdigit(c))
                    320:                        return (0);
                    321:        } while (c = *s++);
                    322:        return (1);
                    323: }
                    324: 
                    325: getdiscq(uid, dq, dqf)
                    326:        register uid;
                    327:        register struct dquot *dq;
                    328:        register char (*dqf)[MAXPATHLEN + 1];
                    329: {
                    330:        register struct fstab *fs;
                    331:        char qfilename[MAXPATHLEN + 1];
                    332:        struct stat statb;
                    333:        struct dqblk dqblk;
                    334:        dev_t fsdev;
                    335:        int fd;
                    336:        static int warned = 0;
                    337:        extern int errno;
                    338: 
                    339:        setfsent();
                    340:        while (fs = getfsent()) {
                    341:                if (stat(fs->fs_spec, &statb) < 0)
                    342:                        continue;
                    343:                fsdev = statb.st_rdev;
                    344:                sprintf(qfilename, "%s/%s", fs->fs_file, qfname);
                    345:                if (stat(qfilename, &statb) < 0 || statb.st_dev != fsdev)
                    346:                        continue;
                    347:                if (quota(Q_GETDLIM, uid, fsdev, &dqblk) != 0) {
                    348:                        if (errno == EINVAL && !warned) {
                    349:                                warned++;
                    350:                                fprintf(stderr, "Warning: %s\n",
                    351:                                    "Quotas are not compiled into this kernel");
                    352:                                sleep(3);
                    353:                        }
                    354:                        fd = open(qfilename, O_RDONLY);
                    355:                        if (fd < 0)
                    356:                                continue;
                    357:                        lseek(fd, (long)(uid * sizeof dqblk), L_SET);
                    358:                        switch (read(fd, &dqblk, sizeof dqblk)) {
                    359:                        case 0:                 /* EOF */
                    360:                                /*
                    361:                                 * Convert implicit 0 quota (EOF)
                    362:                                 * into an explicit one (zero'ed dqblk)
                    363:                                 */
                    364:                                bzero((caddr_t)&dqblk, sizeof dqblk);
                    365:                                break;
                    366: 
                    367:                        case sizeof dqblk:      /* OK */
                    368:                                break;
                    369: 
                    370:                        default:                /* ERROR */
                    371:                                fprintf(stderr, "edquota: read error in ");
                    372:                                perror(qfilename);
                    373:                                close(fd);
                    374:                                continue;
                    375:                        }
                    376:                        close(fd);
                    377:                }
                    378:                dq->dq_dqb = dqblk;
                    379:                dq->dq_dev = fsdev;
                    380:                strcpy(*dqf, fs->fs_file);
                    381:                dq++, dqf++;
                    382:        }
                    383:        endfsent();
                    384:        **dqf = '\0';
                    385: }
                    386: 
                    387: putdiscq(uid, dq, dqf)
                    388:        register uid;
                    389:        register struct dquot *dq;
                    390:        register char (*dqf)[MAXPATHLEN + 1];
                    391: {
                    392:        register fd, cnt;
                    393:        struct stat sb;
                    394:        struct fstab *fs;
                    395: 
                    396:        cnt = 0;
                    397:        for (cnt = 0; ++cnt <= NMOUNT && **dqf; dq++, dqf++) {
                    398:                fs = getfsfile(*dqf);
                    399:                if (fs == NULL) {
                    400:                        fprintf(stderr, "%s: not in /etc/fstab\n", *dqf);
                    401:                        continue;
                    402:                }
                    403:                strcat(*dqf, "/");
                    404:                strcat(*dqf, qfname);
                    405:                if (stat(*dqf, &sb) >= 0)
                    406:                        quota(Q_SETDLIM, uid, sb.st_dev, &dq->dq_dqb);
                    407:                if ((fd = open(*dqf, 1)) < 0) {
                    408:                        perror(*dqf);
                    409:                } else {
                    410:                        lseek(fd, (long)uid * (long)sizeof (struct dqblk), 0);
                    411:                        if (write(fd, &dq->dq_dqb, sizeof (struct dqblk)) !=
                    412:                            sizeof (struct dqblk)) {
                    413:                                fprintf(stderr, "edquota: ");
                    414:                                perror(*dqf);
                    415:                        }
                    416:                        close(fd);
                    417:                }
                    418:        }
                    419: }

unix.superglobalmegacorp.com

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