121520Smckusick /* 221520Smckusick * Copyright (c) 1980 Regents of the University of California. 321520Smckusick * All rights reserved. The Berkeley software License Agreement 421520Smckusick * specifies the terms and conditions for redistribution. 521520Smckusick */ 621520Smckusick 712710Smckusick #ifndef lint 821520Smckusick char copyright[] = 921520Smckusick "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 1021520Smckusick All rights reserved.\n"; 1121520Smckusick #endif not lint 1212710Smckusick 1321520Smckusick #ifndef lint 14*25400Sbloom static char sccsid[] = "@(#)quota.c 5.3 (Berkeley) 11/04/85"; 1521520Smckusick #endif not lint 1621520Smckusick 1712710Smckusick /* 1812710Smckusick * Disk quota reporting program. 1912710Smckusick */ 2012710Smckusick #include <stdio.h> 2112710Smckusick #include <fstab.h> 2212710Smckusick #include <ctype.h> 2312710Smckusick #include <pwd.h> 2421392Smckusick #include <errno.h> 2512710Smckusick 2612710Smckusick #include <sys/param.h> 2712710Smckusick #include <sys/quota.h> 2812710Smckusick #include <sys/file.h> 2912710Smckusick #include <sys/stat.h> 3012710Smckusick 3112710Smckusick int qflag; 3212710Smckusick int vflag; 3312710Smckusick int done; 3412710Smckusick int morethanone; 3512711Smckusick char *qfname = "quotas"; 3612710Smckusick 3712710Smckusick main(argc, argv) 3812710Smckusick char *argv[]; 3912710Smckusick { 4012710Smckusick register char *cp; 4121392Smckusick extern int errno; 4212710Smckusick 4321392Smckusick if (quota(Q_SYNC, 0, 0, 0) < 0 && errno == EINVAL) { 4421392Smckusick fprintf(stderr, "There are no quotas on this system\n"); 4521392Smckusick exit(0); 4621392Smckusick } 4712710Smckusick argc--,argv++; 4812710Smckusick while (argc > 0) { 4912710Smckusick if (argv[0][0] == '-') 5012710Smckusick for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { 5112710Smckusick 5212710Smckusick case 'v': 5312710Smckusick vflag++; 5412710Smckusick break; 5512710Smckusick 5612710Smckusick case 'q': 5712710Smckusick qflag++; 5812710Smckusick break; 5912710Smckusick 6012710Smckusick default: 6112710Smckusick fprintf(stderr, "quota: %c: unknown option\n", 6212710Smckusick *cp); 6312710Smckusick exit(1); 6412710Smckusick } 6512710Smckusick else 6612710Smckusick break; 6712710Smckusick argc--, argv++; 6812710Smckusick } 6912710Smckusick morethanone = argc > 1; 7012710Smckusick if (argc == 0) { 7112710Smckusick showuid(getuid()); 7212710Smckusick exit(0); 7312710Smckusick } 7412710Smckusick for (; argc > 0; argc--, argv++) { 7512710Smckusick if (alldigits(*argv)) 7612710Smckusick showuid(atoi(*argv)); 7712710Smckusick else 7812710Smckusick showname(*argv); 7912710Smckusick } 8012710Smckusick } 8112710Smckusick 8212710Smckusick showuid(uid) 8312710Smckusick int uid; 8412710Smckusick { 8512710Smckusick struct passwd *pwd = getpwuid(uid); 8612710Smckusick 8712710Smckusick if (pwd == NULL) 8812710Smckusick showquotas(uid, "(no account)"); 8912710Smckusick else 9012710Smckusick showquotas(uid, pwd->pw_name); 9112710Smckusick } 9212710Smckusick 9312710Smckusick showname(name) 9412710Smckusick char *name; 9512710Smckusick { 9612710Smckusick struct passwd *pwd = getpwnam(name); 9712710Smckusick 9812710Smckusick if (pwd == NULL) { 9912710Smckusick fprintf(stderr, "quota: %s: unknown user\n", name); 10012710Smckusick return; 10112710Smckusick } 10212710Smckusick showquotas(pwd->pw_uid, name); 10312710Smckusick } 10412710Smckusick 10512710Smckusick showquotas(uid, name) 10612710Smckusick int uid; 10712710Smckusick char *name; 10812710Smckusick { 10912710Smckusick register char c, *p; 11012710Smckusick register struct fstab *fs; 11121392Smckusick register char *msgi = (char *)0, *msgb = (char *)0; 11221392Smckusick register enab = 1; 11321392Smckusick dev_t fsdev; 11421392Smckusick struct stat statb; 11521392Smckusick struct dqblk dqblk; 11621392Smckusick int myuid, fd; 11721392Smckusick char qfilename[MAXPATHLEN + 1], iwarn[8], dwarn[8]; 11812710Smckusick 11912710Smckusick myuid = getuid(); 12012710Smckusick if (uid != myuid && myuid != 0) { 12112710Smckusick printf("quota: %s (uid %d): permission denied\n", name, uid); 12212710Smckusick return; 12312710Smckusick } 12412710Smckusick done = 0; 12512710Smckusick setfsent(); 12612710Smckusick while (fs = getfsent()) { 12712710Smckusick if (stat(fs->fs_spec, &statb) < 0) 12812710Smckusick continue; 12912710Smckusick fsdev = statb.st_rdev; 13012711Smckusick (void) sprintf(qfilename, "%s/%s", fs->fs_file, qfname); 13112711Smckusick if (stat(qfilename, &statb) < 0 || statb.st_dev != fsdev) 13212710Smckusick continue; 13312710Smckusick if (quota(Q_GETDLIM, uid, fsdev, &dqblk) != 0) { 13421392Smckusick fd = open(qfilename, O_RDONLY); 13512710Smckusick if (fd < 0) 13612710Smckusick continue; 13712721Smckusick lseek(fd, (long)(uid * sizeof (dqblk)), L_SET); 13824684Sserge switch (read(fd, &dqblk, sizeof dqblk)) { 13924684Sserge case 0: /* EOF */ 14024684Sserge /* 14124684Sserge * Convert implicit 0 quota (EOF) 14224684Sserge * into an explicit one (zero'ed dqblk). 14324684Sserge */ 14424684Sserge bzero((caddr_t)&dqblk, sizeof dqblk); 14524684Sserge break; 14624684Sserge 14724684Sserge case sizeof dqblk: /* OK */ 14824684Sserge break; 14924684Sserge 15024684Sserge default: /* ERROR */ 15124684Sserge fprintf(stderr, "quota: read error in "); 15224684Sserge perror(qfilename); 15312710Smckusick close(fd); 15412710Smckusick continue; 15512710Smckusick } 15612710Smckusick close(fd); 15724684Sserge if (!vflag && dqblk.dqb_isoftlimit == 0 && 15812710Smckusick dqblk.dqb_bsoftlimit == 0) 15912710Smckusick continue; 16012710Smckusick enab = 0; 16112710Smckusick } 16212710Smckusick if (dqblk.dqb_ihardlimit && 16312710Smckusick dqblk.dqb_curinodes >= dqblk.dqb_ihardlimit) 16412710Smckusick msgi = "File count limit reached on %s"; 16512710Smckusick else if (enab && dqblk.dqb_iwarn == 0) 16612710Smckusick msgi = "Out of inode warnings on %s"; 16712710Smckusick else if (dqblk.dqb_isoftlimit && 16812710Smckusick dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit) 16912710Smckusick msgi = "Too many files on %s"; 17012710Smckusick if (dqblk.dqb_bhardlimit && 17112710Smckusick dqblk.dqb_curblocks >= dqblk.dqb_bhardlimit) 17212710Smckusick msgb = "Block limit reached on %s"; 17312710Smckusick else if (enab && dqblk.dqb_bwarn == 0) 17412710Smckusick msgb = "Out of block warnings on %s"; 17512710Smckusick else if (dqblk.dqb_bsoftlimit && 17612710Smckusick dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit) 17712710Smckusick msgb = "Over disc quota on %s"; 17812710Smckusick if (dqblk.dqb_iwarn < MAX_IQ_WARN) 17912710Smckusick sprintf(iwarn, "%d", dqblk.dqb_iwarn); 18012710Smckusick else 18112710Smckusick iwarn[0] = '\0'; 18212710Smckusick if (dqblk.dqb_bwarn < MAX_DQ_WARN) 18312710Smckusick sprintf(dwarn, "%d", dqblk.dqb_bwarn); 18412710Smckusick else 18512710Smckusick dwarn[0] = '\0'; 18612710Smckusick if (qflag) { 18712710Smckusick if (msgi != (char *)0 || msgb != (char *)0) 18812710Smckusick heading(uid, name); 18912710Smckusick if (msgi != (char *)0) 19012710Smckusick xprintf(msgi, fs->fs_file); 19112710Smckusick if (msgb != (char *)0) 19212710Smckusick xprintf(msgb, fs->fs_file); 19312710Smckusick continue; 19412710Smckusick } 19512710Smckusick if (vflag || dqblk.dqb_curblocks || dqblk.dqb_curinodes) { 19612710Smckusick heading(uid, name); 19713222Ssam printf("%10s%8d%c%7d%8d%8s%8d%c%7d%8d%8s\n" 19812710Smckusick , fs->fs_file 199*25400Sbloom , dbtob(dqblk.dqb_curblocks) / 1024 20012710Smckusick , (msgb == (char *)0) ? ' ' : '*' 201*25400Sbloom , dbtob(dqblk.dqb_bsoftlimit) / 1024 202*25400Sbloom , dbtob(dqblk.dqb_bhardlimit) / 1024 20312710Smckusick , dwarn 20412710Smckusick , dqblk.dqb_curinodes 20512710Smckusick , (msgi == (char *)0) ? ' ' : '*' 20612710Smckusick , dqblk.dqb_isoftlimit 20712721Smckusick , dqblk.dqb_ihardlimit 20812710Smckusick , iwarn 20912710Smckusick ); 21012710Smckusick } 21112710Smckusick } 21212710Smckusick endfsent(); 21312710Smckusick if (!done && !qflag) { 21412710Smckusick if (morethanone) 21512710Smckusick putchar('\n'); 21612710Smckusick xprintf("Disc quotas for %s (uid %d):", name, uid); 21712710Smckusick xprintf("none."); 21812710Smckusick } 21924684Sserge xprintf((char *)0); 22012710Smckusick } 22112710Smckusick 22212710Smckusick heading(uid, name) 22312710Smckusick int uid; 22412710Smckusick char *name; 22512710Smckusick { 22612710Smckusick 22712710Smckusick if (done++) 22812710Smckusick return; 22924684Sserge xprintf((char *)0); 23012710Smckusick if (qflag) { 23112710Smckusick if (!morethanone) 23212710Smckusick return; 23312710Smckusick xprintf("User %s (uid %d):", name, uid); 23424684Sserge xprintf((char *)0); 23512710Smckusick return; 23612710Smckusick } 23712710Smckusick putchar('\n'); 23812710Smckusick xprintf("Disc quotas for %s (uid %d):", name, uid); 23924684Sserge xprintf((char *)0); 24013222Ssam printf("%10s%8s %7s%8s%8s%8s %7s%8s%8s\n" 24112710Smckusick , "Filsys" 24212710Smckusick , "current" 24312710Smckusick , "quota" 24412710Smckusick , "limit" 24512710Smckusick , "#warns" 24612710Smckusick , "files" 24712710Smckusick , "quota" 24812710Smckusick , "limit" 24912710Smckusick , "#warns" 25012710Smckusick ); 25112710Smckusick } 25212710Smckusick 25324684Sserge /*VARARGS1*/ 25412710Smckusick xprintf(fmt, arg1, arg2, arg3, arg4, arg5, arg6) 25512710Smckusick char *fmt; 25612710Smckusick { 25712710Smckusick char buf[100]; 25812710Smckusick static int column; 25912710Smckusick 26012710Smckusick if (fmt == 0 && column || column >= 40) { 26112710Smckusick putchar('\n'); 26212710Smckusick column = 0; 26312710Smckusick } 26412710Smckusick if (fmt == 0) 26512710Smckusick return; 26612710Smckusick sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5, arg6); 26712710Smckusick if (column != 0 && strlen(buf) < 39) 26812710Smckusick while (column++ < 40) 26912710Smckusick putchar(' '); 27012710Smckusick else if (column) { 27112710Smckusick putchar('\n'); 27212710Smckusick column = 0; 27312710Smckusick } 27412710Smckusick printf("%s", buf); 27512710Smckusick column += strlen(buf); 27612710Smckusick } 27712710Smckusick 27812710Smckusick alldigits(s) 27912710Smckusick register char *s; 28012710Smckusick { 28112710Smckusick register c; 28212710Smckusick 28312710Smckusick c = *s++; 28412710Smckusick do { 28512710Smckusick if (!isdigit(c)) 28612710Smckusick return (0); 28712710Smckusick } while (c = *s++); 28812710Smckusick return (1); 28912710Smckusick } 290