112710Smckusick #ifndef lint 2*21392Smckusick static char sccsid[] = "@(#)quota.c 4.5 (Berkeley, from Melbourne) 05/30/85"; 312710Smckusick #endif 412710Smckusick 512710Smckusick /* 612710Smckusick * Disk quota reporting program. 712710Smckusick */ 812710Smckusick #include <stdio.h> 912710Smckusick #include <fstab.h> 1012710Smckusick #include <ctype.h> 1112710Smckusick #include <pwd.h> 12*21392Smckusick #include <errno.h> 1312710Smckusick 1412710Smckusick #include <sys/param.h> 1512710Smckusick #include <sys/quota.h> 1612710Smckusick #include <sys/file.h> 1712710Smckusick #include <sys/stat.h> 1812710Smckusick 1912710Smckusick int qflag; 2012710Smckusick int vflag; 2112710Smckusick int done; 2212710Smckusick int morethanone; 2312711Smckusick char *qfname = "quotas"; 2412710Smckusick 2512710Smckusick main(argc, argv) 2612710Smckusick char *argv[]; 2712710Smckusick { 2812710Smckusick register char *cp; 29*21392Smckusick extern int errno; 3012710Smckusick 31*21392Smckusick if (quota(Q_SYNC, 0, 0, 0) < 0 && errno == EINVAL) { 32*21392Smckusick fprintf(stderr, "There are no quotas on this system\n"); 33*21392Smckusick exit(0); 34*21392Smckusick } 3512710Smckusick argc--,argv++; 3612710Smckusick while (argc > 0) { 3712710Smckusick if (argv[0][0] == '-') 3812710Smckusick for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { 3912710Smckusick 4012710Smckusick case 'v': 4112710Smckusick vflag++; 4212710Smckusick break; 4312710Smckusick 4412710Smckusick case 'q': 4512710Smckusick qflag++; 4612710Smckusick break; 4712710Smckusick 4812710Smckusick default: 4912710Smckusick fprintf(stderr, "quota: %c: unknown option\n", 5012710Smckusick *cp); 5112710Smckusick exit(1); 5212710Smckusick } 5312710Smckusick else 5412710Smckusick break; 5512710Smckusick argc--, argv++; 5612710Smckusick } 5712710Smckusick morethanone = argc > 1; 5812710Smckusick if (argc == 0) { 5912710Smckusick showuid(getuid()); 6012710Smckusick exit(0); 6112710Smckusick } 6212710Smckusick for (; argc > 0; argc--, argv++) { 6312710Smckusick if (alldigits(*argv)) 6412710Smckusick showuid(atoi(*argv)); 6512710Smckusick else 6612710Smckusick showname(*argv); 6712710Smckusick } 6812710Smckusick } 6912710Smckusick 7012710Smckusick showuid(uid) 7112710Smckusick int uid; 7212710Smckusick { 7312710Smckusick struct passwd *pwd = getpwuid(uid); 7412710Smckusick 7512710Smckusick if (pwd == NULL) 7612710Smckusick showquotas(uid, "(no account)"); 7712710Smckusick else 7812710Smckusick showquotas(uid, pwd->pw_name); 7912710Smckusick } 8012710Smckusick 8112710Smckusick showname(name) 8212710Smckusick char *name; 8312710Smckusick { 8412710Smckusick struct passwd *pwd = getpwnam(name); 8512710Smckusick 8612710Smckusick if (pwd == NULL) { 8712710Smckusick fprintf(stderr, "quota: %s: unknown user\n", name); 8812710Smckusick return; 8912710Smckusick } 9012710Smckusick showquotas(pwd->pw_uid, name); 9112710Smckusick } 9212710Smckusick 9312710Smckusick showquotas(uid, name) 9412710Smckusick int uid; 9512710Smckusick char *name; 9612710Smckusick { 9712710Smckusick register char c, *p; 9812710Smckusick register struct fstab *fs; 99*21392Smckusick register char *msgi = (char *)0, *msgb = (char *)0; 100*21392Smckusick register enab = 1; 101*21392Smckusick dev_t fsdev; 102*21392Smckusick struct stat statb; 103*21392Smckusick struct dqblk dqblk; 104*21392Smckusick int myuid, fd; 105*21392Smckusick char qfilename[MAXPATHLEN + 1], iwarn[8], dwarn[8]; 10612710Smckusick 10712710Smckusick myuid = getuid(); 10812710Smckusick if (uid != myuid && myuid != 0) { 10912710Smckusick printf("quota: %s (uid %d): permission denied\n", name, uid); 11012710Smckusick return; 11112710Smckusick } 11212710Smckusick done = 0; 11312710Smckusick setfsent(); 11412710Smckusick while (fs = getfsent()) { 11512710Smckusick if (stat(fs->fs_spec, &statb) < 0) 11612710Smckusick continue; 11712710Smckusick fsdev = statb.st_rdev; 11812711Smckusick (void) sprintf(qfilename, "%s/%s", fs->fs_file, qfname); 11912711Smckusick if (stat(qfilename, &statb) < 0 || statb.st_dev != fsdev) 12012710Smckusick continue; 12112710Smckusick if (quota(Q_GETDLIM, uid, fsdev, &dqblk) != 0) { 122*21392Smckusick fd = open(qfilename, O_RDONLY); 12312710Smckusick if (fd < 0) 12412710Smckusick continue; 12512721Smckusick lseek(fd, (long)(uid * sizeof (dqblk)), L_SET); 12612710Smckusick if (read(fd, &dqblk, sizeof dqblk) != sizeof (dqblk)) { 12712710Smckusick close(fd); 12812710Smckusick continue; 12912710Smckusick } 13012710Smckusick close(fd); 13112710Smckusick if (dqblk.dqb_isoftlimit == 0 && 13212710Smckusick dqblk.dqb_bsoftlimit == 0) 13312710Smckusick continue; 13412710Smckusick enab = 0; 13512710Smckusick } 13612710Smckusick if (dqblk.dqb_ihardlimit && 13712710Smckusick dqblk.dqb_curinodes >= dqblk.dqb_ihardlimit) 13812710Smckusick msgi = "File count limit reached on %s"; 13912710Smckusick else if (enab && dqblk.dqb_iwarn == 0) 14012710Smckusick msgi = "Out of inode warnings on %s"; 14112710Smckusick else if (dqblk.dqb_isoftlimit && 14212710Smckusick dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit) 14312710Smckusick msgi = "Too many files on %s"; 14412710Smckusick if (dqblk.dqb_bhardlimit && 14512710Smckusick dqblk.dqb_curblocks >= dqblk.dqb_bhardlimit) 14612710Smckusick msgb = "Block limit reached on %s"; 14712710Smckusick else if (enab && dqblk.dqb_bwarn == 0) 14812710Smckusick msgb = "Out of block warnings on %s"; 14912710Smckusick else if (dqblk.dqb_bsoftlimit && 15012710Smckusick dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit) 15112710Smckusick msgb = "Over disc quota on %s"; 15212710Smckusick if (dqblk.dqb_iwarn < MAX_IQ_WARN) 15312710Smckusick sprintf(iwarn, "%d", dqblk.dqb_iwarn); 15412710Smckusick else 15512710Smckusick iwarn[0] = '\0'; 15612710Smckusick if (dqblk.dqb_bwarn < MAX_DQ_WARN) 15712710Smckusick sprintf(dwarn, "%d", dqblk.dqb_bwarn); 15812710Smckusick else 15912710Smckusick dwarn[0] = '\0'; 16012710Smckusick if (qflag) { 16112710Smckusick if (msgi != (char *)0 || msgb != (char *)0) 16212710Smckusick heading(uid, name); 16312710Smckusick if (msgi != (char *)0) 16412710Smckusick xprintf(msgi, fs->fs_file); 16512710Smckusick if (msgb != (char *)0) 16612710Smckusick xprintf(msgb, fs->fs_file); 16712710Smckusick continue; 16812710Smckusick } 16912710Smckusick if (vflag || dqblk.dqb_curblocks || dqblk.dqb_curinodes) { 17012710Smckusick heading(uid, name); 17113222Ssam printf("%10s%8d%c%7d%8d%8s%8d%c%7d%8d%8s\n" 17212710Smckusick , fs->fs_file 17312721Smckusick , (dqblk.dqb_curblocks / btodb(1024)) 17412710Smckusick , (msgb == (char *)0) ? ' ' : '*' 17512721Smckusick , (dqblk.dqb_bsoftlimit / btodb(1024)) 17612721Smckusick , (dqblk.dqb_bhardlimit / btodb(1024)) 17712710Smckusick , dwarn 17812710Smckusick , dqblk.dqb_curinodes 17912710Smckusick , (msgi == (char *)0) ? ' ' : '*' 18012710Smckusick , dqblk.dqb_isoftlimit 18112721Smckusick , dqblk.dqb_ihardlimit 18212710Smckusick , iwarn 18312710Smckusick ); 18412710Smckusick } 18512710Smckusick } 18612710Smckusick endfsent(); 18712710Smckusick if (!done && !qflag) { 18812710Smckusick if (morethanone) 18912710Smckusick putchar('\n'); 19012710Smckusick xprintf("Disc quotas for %s (uid %d):", name, uid); 19112710Smckusick xprintf("none."); 19212710Smckusick } 19312710Smckusick xprintf(0); 19412710Smckusick } 19512710Smckusick 19612710Smckusick heading(uid, name) 19712710Smckusick int uid; 19812710Smckusick char *name; 19912710Smckusick { 20012710Smckusick 20112710Smckusick if (done++) 20212710Smckusick return; 20312710Smckusick xprintf(0); 20412710Smckusick if (qflag) { 20512710Smckusick if (!morethanone) 20612710Smckusick return; 20712710Smckusick xprintf("User %s (uid %d):", name, uid); 20812710Smckusick xprintf(0); 20912710Smckusick return; 21012710Smckusick } 21112710Smckusick putchar('\n'); 21212710Smckusick xprintf("Disc quotas for %s (uid %d):", name, uid); 21312710Smckusick xprintf(0); 21413222Ssam printf("%10s%8s %7s%8s%8s%8s %7s%8s%8s\n" 21512710Smckusick , "Filsys" 21612710Smckusick , "current" 21712710Smckusick , "quota" 21812710Smckusick , "limit" 21912710Smckusick , "#warns" 22012710Smckusick , "files" 22112710Smckusick , "quota" 22212710Smckusick , "limit" 22312710Smckusick , "#warns" 22412710Smckusick ); 22512710Smckusick } 22612710Smckusick 22712710Smckusick xprintf(fmt, arg1, arg2, arg3, arg4, arg5, arg6) 22812710Smckusick char *fmt; 22912710Smckusick { 23012710Smckusick char buf[100]; 23112710Smckusick static int column; 23212710Smckusick 23312710Smckusick if (fmt == 0 && column || column >= 40) { 23412710Smckusick putchar('\n'); 23512710Smckusick column = 0; 23612710Smckusick } 23712710Smckusick if (fmt == 0) 23812710Smckusick return; 23912710Smckusick sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5, arg6); 24012710Smckusick if (column != 0 && strlen(buf) < 39) 24112710Smckusick while (column++ < 40) 24212710Smckusick putchar(' '); 24312710Smckusick else if (column) { 24412710Smckusick putchar('\n'); 24512710Smckusick column = 0; 24612710Smckusick } 24712710Smckusick printf("%s", buf); 24812710Smckusick column += strlen(buf); 24912710Smckusick } 25012710Smckusick 25112710Smckusick alldigits(s) 25212710Smckusick register char *s; 25312710Smckusick { 25412710Smckusick register c; 25512710Smckusick 25612710Smckusick c = *s++; 25712710Smckusick do { 25812710Smckusick if (!isdigit(c)) 25912710Smckusick return (0); 26012710Smckusick } while (c = *s++); 26112710Smckusick return (1); 26212710Smckusick } 263