Annotation of 43BSDReno/usr.bin/quota/quota.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980, 1990 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * Robert Elz at The University of Melbourne.
                      7:  *
                      8:  * Redistribution and use in source and binary forms are permitted provided
                      9:  * that: (1) source distributions retain this entire copyright notice and
                     10:  * comment, and (2) distributions including binaries display the following
                     11:  * acknowledgement:  ``This product includes software developed by the
                     12:  * University of California, Berkeley and its contributors'' in the
                     13:  * documentation or other materials provided with the distribution and in
                     14:  * all advertising materials mentioning features or use of this software.
                     15:  * Neither the name of the University nor the names of its contributors may
                     16:  * be used to endorse or promote products derived from this software without
                     17:  * specific prior written permission.
                     18:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     19:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     20:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     21:  */
                     22: 
                     23: #ifndef lint
                     24: char copyright[] =
                     25: "@(#) Copyright (c) 1980, 1990 Regents of the University of California.\n\
                     26:  All rights reserved.\n";
                     27: #endif /* not lint */
                     28: 
                     29: #ifndef lint
                     30: static char sccsid[] = "@(#)quota.c    5.11 (Berkeley) 6/1/90";
                     31: #endif /* not lint */
                     32: 
                     33: /*
                     34:  * Disk quota reporting program.
                     35:  */
                     36: #include <sys/param.h>
                     37: #include <sys/file.h>
                     38: #include <sys/stat.h>
                     39: #include <ufs/quota.h>
                     40: #include <stdio.h>
                     41: #include <fstab.h>
                     42: #include <ctype.h>
                     43: #include <pwd.h>
                     44: #include <grp.h>
                     45: #include <errno.h>
                     46: 
                     47: struct quotause {
                     48:        struct  quotause *next;
                     49:        long    flags;
                     50:        struct  dqblk dqblk;
                     51:        char    fsname[MAXPATHLEN + 1];
                     52: } *getprivs();
                     53: #define        FOUND   0x01
                     54: 
                     55: int    qflag;
                     56: int    vflag;
                     57: 
                     58: main(argc, argv)
                     59:        char *argv[];
                     60: {
                     61:        int ngroups, gidset[NGROUPS];
                     62:        int i, gflag = 0, uflag = 0;
                     63:        char ch;
                     64:        extern char *optarg;
                     65:        extern int optind, errno;
                     66: 
                     67:        if (quotactl("/", 0, 0, (caddr_t)0) < 0 && errno == EOPNOTSUPP) {
                     68:                fprintf(stderr, "There are no quotas on this system\n");
                     69:                exit(0);
                     70:        }
                     71:        while ((ch = getopt(argc, argv, "ugvq")) != EOF) {
                     72:                switch(ch) {
                     73:                case 'g':
                     74:                        gflag++;
                     75:                        break;
                     76:                case 'u':
                     77:                        uflag++;
                     78:                        break;
                     79:                case 'v':
                     80:                        vflag++;
                     81:                        break;
                     82:                case 'q':
                     83:                        qflag++;
                     84:                        break;
                     85:                default:
                     86:                        usage();
                     87:                }
                     88:        }
                     89:        argc -= optind;
                     90:        argv += optind;
                     91:        if (!uflag && !gflag)
                     92:                uflag++;
                     93:        if (argc == 0) {
                     94:                if (uflag)
                     95:                        showuid(getuid());
                     96:                if (gflag) {
                     97:                        ngroups = getgroups(NGROUPS, gidset);
                     98:                        if (ngroups < 0) {
                     99:                                perror("quota: getgroups");
                    100:                                exit(1);
                    101:                        }
                    102:                        for (i = 1; i < ngroups; i++)
                    103:                                showgid(gidset[i]);
                    104:                }
                    105:                exit(0);
                    106:        }
                    107:        if (uflag && gflag)
                    108:                usage();
                    109:        if (uflag) {
                    110:                for (; argc > 0; argc--, argv++) {
                    111:                        if (alldigits(*argv))
                    112:                                showuid(atoi(*argv));
                    113:                        else
                    114:                                showusrname(*argv);
                    115:                }
                    116:                exit(0);
                    117:        }
                    118:        if (gflag) {
                    119:                for (; argc > 0; argc--, argv++) {
                    120:                        if (alldigits(*argv))
                    121:                                showgid(atoi(*argv));
                    122:                        else
                    123:                                showgrpname(*argv);
                    124:                }
                    125:                exit(0);
                    126:        }
                    127: }
                    128: 
                    129: usage()
                    130: {
                    131: 
                    132:        fprintf(stderr, "%s\n%s\n%s\n",
                    133:                "Usage: quota [-guqv]",
                    134:                "\tquota [-qv] -u username ...",
                    135:                "\tquota [-qv] -g groupname ...");
                    136:        exit(1);
                    137: }
                    138: 
                    139: /*
                    140:  * Print out quotas for a specified user identifier.
                    141:  */
                    142: showuid(uid)
                    143:        u_long uid;
                    144: {
                    145:        struct passwd *pwd = getpwuid(uid);
                    146:        u_long myuid;
                    147:        char *name;
                    148: 
                    149:        if (pwd == NULL)
                    150:                name = "(no account)";
                    151:        else
                    152:                name = pwd->pw_name;
                    153:        myuid = getuid();
                    154:        if (uid != myuid && myuid != 0) {
                    155:                printf("quota: %s (uid %d): permission denied\n", name, uid);
                    156:                return;
                    157:        }
                    158:        showquotas(USRQUOTA, uid, name);
                    159: }
                    160: 
                    161: /*
                    162:  * Print out quotas for a specifed user name.
                    163:  */
                    164: showusrname(name)
                    165:        char *name;
                    166: {
                    167:        struct passwd *pwd = getpwnam(name);
                    168:        u_long myuid;
                    169: 
                    170:        if (pwd == NULL) {
                    171:                fprintf(stderr, "quota: %s: unknown user\n", name);
                    172:                return;
                    173:        }
                    174:        myuid = getuid();
                    175:        if (pwd->pw_uid != myuid && myuid != 0) {
                    176:                fprintf(stderr, "quota: %s (uid %d): permission denied\n",
                    177:                    name, pwd->pw_uid);
                    178:                return;
                    179:        }
                    180:        showquotas(USRQUOTA, pwd->pw_uid, name);
                    181: }
                    182: 
                    183: /*
                    184:  * Print out quotas for a specified group identifier.
                    185:  */
                    186: showgid(gid)
                    187:        u_long gid;
                    188: {
                    189:        struct group *grp = getgrgid(gid);
                    190:        int ngroups, gidset[NGROUPS];
                    191:        register int i;
                    192:        char *name;
                    193: 
                    194:        if (grp == NULL)
                    195:                name = "(no entry)";
                    196:        else
                    197:                name = grp->gr_name;
                    198:        ngroups = getgroups(NGROUPS, gidset);
                    199:        if (ngroups < 0) {
                    200:                perror("quota: getgroups");
                    201:                return;
                    202:        }
                    203:        for (i = 1; i < ngroups; i++)
                    204:                if (gid == gidset[i])
                    205:                        break;
                    206:        if (i >= ngroups && getuid() != 0) {
                    207:                fprintf(stderr, "quota: %s (gid %d): permission denied\n",
                    208:                    name, gid);
                    209:                return;
                    210:        }
                    211:        showquotas(GRPQUOTA, gid, name);
                    212: }
                    213: 
                    214: /*
                    215:  * Print out quotas for a specifed group name.
                    216:  */
                    217: showgrpname(name)
                    218:        char *name;
                    219: {
                    220:        struct group *grp = getgrnam(name);
                    221:        int ngroups, gidset[NGROUPS];
                    222:        register int i;
                    223: 
                    224:        if (grp == NULL) {
                    225:                fprintf(stderr, "quota: %s: unknown group\n", name);
                    226:                return;
                    227:        }
                    228:        ngroups = getgroups(NGROUPS, gidset);
                    229:        if (ngroups < 0) {
                    230:                perror("quota: getgroups");
                    231:                return;
                    232:        }
                    233:        for (i = 1; i < ngroups; i++)
                    234:                if (grp->gr_gid == gidset[i])
                    235:                        break;
                    236:        if (i >= ngroups && getuid() != 0) {
                    237:                fprintf(stderr, "quota: %s (gid %d): permission denied\n",
                    238:                    name, grp->gr_gid);
                    239:                return;
                    240:        }
                    241:        showquotas(GRPQUOTA, grp->gr_gid, name);
                    242: }
                    243: 
                    244: showquotas(type, id, name)
                    245:        int type;
                    246:        u_long id;
                    247:        char *name;
                    248: {
                    249:        register struct quotause *qup;
                    250:        struct quotause *quplist, *getprivs();
                    251:        char *msgi, *msgb, *timeprt();
                    252:        int myuid, fd, lines = 0;
                    253:        static int first;
                    254:        static time_t now;
                    255: 
                    256:        if (now == 0)
                    257:                time(&now);
                    258:        quplist = getprivs(id, type);
                    259:        for (qup = quplist; qup; qup = qup->next) {
                    260:                if (!vflag &&
                    261:                    qup->dqblk.dqb_isoftlimit == 0 &&
                    262:                    qup->dqblk.dqb_ihardlimit == 0 &&
                    263:                    qup->dqblk.dqb_bsoftlimit == 0 &&
                    264:                    qup->dqblk.dqb_bhardlimit == 0)
                    265:                        continue;
                    266:                msgi = (char *)0;
                    267:                if (qup->dqblk.dqb_ihardlimit &&
                    268:                    qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_ihardlimit)
                    269:                        msgi = "File limit reached on";
                    270:                else if (qup->dqblk.dqb_isoftlimit &&
                    271:                    qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_isoftlimit)
                    272:                        if (qup->dqblk.dqb_itime > now)
                    273:                                msgi = "In file grace period on";
                    274:                        else
                    275:                                msgi = "Over file quota on";
                    276:                msgb = (char *)0;
                    277:                if (qup->dqblk.dqb_bhardlimit &&
                    278:                    qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bhardlimit)
                    279:                        msgb = "Block limit reached on";
                    280:                else if (qup->dqblk.dqb_bsoftlimit &&
                    281:                    qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bsoftlimit)
                    282:                        if (qup->dqblk.dqb_btime > now)
                    283:                                msgb = "In block grace period on";
                    284:                        else
                    285:                                msgb = "Over block quota on";
                    286:                if (qflag) {
                    287:                        if ((msgi != (char *)0 || msgb != (char *)0) &&
                    288:                            lines++ == 0)
                    289:                                heading(type, id, name, "");
                    290:                        if (msgi != (char *)0)
                    291:                                printf("\t%s %s\n", msgi, qup->fsname);
                    292:                        if (msgb != (char *)0)
                    293:                                printf("\t%s %s\n", msgb, qup->fsname);
                    294:                        continue;
                    295:                }
                    296:                if (vflag ||
                    297:                    qup->dqblk.dqb_curblocks ||
                    298:                    qup->dqblk.dqb_curinodes) {
                    299:                        if (lines++ == 0)
                    300:                                heading(type, id, name, "");
                    301:                        printf("%15s%8d%c%7d%8d%8s"
                    302:                                , qup->fsname
                    303:                                , dbtob(qup->dqblk.dqb_curblocks) / 1024
                    304:                                , (msgb == (char *)0) ? ' ' : '*'
                    305:                                , dbtob(qup->dqblk.dqb_bsoftlimit) / 1024
                    306:                                , dbtob(qup->dqblk.dqb_bhardlimit) / 1024
                    307:                                , (msgb == (char *)0) ? ""
                    308:                                    : timeprt(qup->dqblk.dqb_btime));
                    309:                        printf("%8d%c%7d%8d%8s\n"
                    310:                                , qup->dqblk.dqb_curinodes
                    311:                                , (msgi == (char *)0) ? ' ' : '*'
                    312:                                , qup->dqblk.dqb_isoftlimit
                    313:                                , qup->dqblk.dqb_ihardlimit
                    314:                                , (msgi == (char *)0) ? ""
                    315:                                    : timeprt(qup->dqblk.dqb_itime)
                    316:                        );
                    317:                        continue;
                    318:                }
                    319:        }
                    320:        if (!qflag && lines == 0)
                    321:                heading(type, id, name, "none");
                    322: }
                    323: 
                    324: heading(type, id, name, tag)
                    325:        int type;
                    326:        u_long id;
                    327:        char *name, *tag;
                    328: {
                    329: 
                    330:        printf("Disk quotas for %s %s (%cid %d): %s\n", qfextension[type],
                    331:            name, *qfextension[type], id, tag);
                    332:        if (!qflag && tag[0] == '\0') {
                    333:                printf("%15s%8s %7s%8s%8s%8s %7s%8s%8s\n"
                    334:                        , "Filesystem"
                    335:                        , "blocks"
                    336:                        , "quota"
                    337:                        , "limit"
                    338:                        , "grace"
                    339:                        , "files"
                    340:                        , "quota"
                    341:                        , "limit"
                    342:                        , "grace"
                    343:                );
                    344:        }
                    345: }
                    346: 
                    347: /*
                    348:  * Calculate the grace period and return a printable string for it.
                    349:  */
                    350: char *
                    351: timeprt(seconds)
                    352:        time_t seconds;
                    353: {
                    354:        time_t hours, minutes;
                    355:        static char buf[20];
                    356:        static time_t now;
                    357: 
                    358:        if (now == 0)
                    359:                time(&now);
                    360:        if (now > seconds)
                    361:                return ("none");
                    362:        seconds -= now;
                    363:        minutes = (seconds + 30) / 60;
                    364:        hours = (minutes + 30) / 60;
                    365:        if (hours >= 36) {
                    366:                sprintf(buf, "%ddays", (hours + 12) / 24);
                    367:                return (buf);
                    368:        }
                    369:        if (minutes >= 60) {
                    370:                sprintf(buf, "%2d:%d", minutes / 60, minutes % 60);
                    371:                return (buf);
                    372:        }
                    373:        sprintf(buf, "%2d", minutes);
                    374:        return (buf);
                    375: }
                    376: 
                    377: /*
                    378:  * Collect the requested quota information.
                    379:  */
                    380: struct quotause *
                    381: getprivs(id, quotatype)
                    382:        register long id;
                    383:        int quotatype;
                    384: {
                    385:        register struct fstab *fs;
                    386:        register struct quotause *qup, *quptail;
                    387:        struct quotause *quphead;
                    388:        char *qfpathname;
                    389:        int qcmd, fd;
                    390: 
                    391:        setfsent();
                    392:        quphead = (struct quotause *)0;
                    393:        qcmd = QCMD(Q_GETQUOTA, quotatype);
                    394:        while (fs = getfsent()) {
                    395:                if (strcmp(fs->fs_vfstype, "ufs"))
                    396:                        continue;
                    397:                if (!hasquota(fs, quotatype, &qfpathname))
                    398:                        continue;
                    399:                if ((qup = (struct quotause *)malloc(sizeof *qup)) == NULL) {
                    400:                        fprintf(stderr, "quota: out of memory\n");
                    401:                        exit(2);
                    402:                }
                    403:                if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) {
                    404:                        if ((fd = open(qfpathname, O_RDONLY)) < 0) {
                    405:                                perror(qfpathname);
                    406:                                free(qup);
                    407:                                continue;
                    408:                        }
                    409:                        lseek(fd, (long)(id * sizeof(struct dqblk)), L_SET);
                    410:                        switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) {
                    411:                        case 0:                 /* EOF */
                    412:                                /*
                    413:                                 * Convert implicit 0 quota (EOF)
                    414:                                 * into an explicit one (zero'ed dqblk)
                    415:                                 */
                    416:                                bzero((caddr_t)&qup->dqblk,
                    417:                                    sizeof(struct dqblk));
                    418:                                break;
                    419: 
                    420:                        case sizeof(struct dqblk):      /* OK */
                    421:                                break;
                    422: 
                    423:                        default:                /* ERROR */
                    424:                                fprintf(stderr, "quota: read error");
                    425:                                perror(qfpathname);
                    426:                                close(fd);
                    427:                                free(qup);
                    428:                                continue;
                    429:                        }
                    430:                        close(fd);
                    431:                }
                    432:                strcpy(qup->fsname, fs->fs_file);
                    433:                if (quphead == NULL)
                    434:                        quphead = qup;
                    435:                else
                    436:                        quptail->next = qup;
                    437:                quptail = qup;
                    438:                qup->next = 0;
                    439:        }
                    440:        endfsent();
                    441:        return (quphead);
                    442: }
                    443: 
                    444: /*
                    445:  * Check to see if a particular quota is to be enabled.
                    446:  */
                    447: hasquota(fs, type, qfnamep)
                    448:        register struct fstab *fs;
                    449:        int type;
                    450:        char **qfnamep;
                    451: {
                    452:        register char *opt;
                    453:        char *cp, *index(), *strtok();
                    454:        static char initname, usrname[100], grpname[100];
                    455:        static char buf[BUFSIZ];
                    456: 
                    457:        if (!initname) {
                    458:                sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname);
                    459:                sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname);
                    460:                initname = 1;
                    461:        }
                    462:        strcpy(buf, fs->fs_mntops);
                    463:        for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
                    464:                if (cp = index(opt, '='))
                    465:                        *cp++ = '\0';
                    466:                if (type == USRQUOTA && strcmp(opt, usrname) == 0)
                    467:                        break;
                    468:                if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
                    469:                        break;
                    470:        }
                    471:        if (!opt)
                    472:                return (0);
                    473:        if (cp) {
                    474:                *qfnamep = cp;
                    475:                return (1);
                    476:        }
                    477:        (void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
                    478:        *qfnamep = buf;
                    479:        return (1);
                    480: }
                    481: 
                    482: alldigits(s)
                    483:        register char *s;
                    484: {
                    485:        register c;
                    486: 
                    487:        c = *s++;
                    488:        do {
                    489:                if (!isdigit(c))
                    490:                        return (0);
                    491:        } while (c = *s++);
                    492:        return (1);
                    493: }

unix.superglobalmegacorp.com

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