1: /* 2: * Copyright (c) 1980 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: char copyright[] = 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: #endif not lint 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)quota.c 5.4 (Berkeley) 2/24/86"; 15: #endif not lint 16: 17: /* 18: * Disk quota reporting program. 19: */ 20: #include <stdio.h> 21: #include <fstab.h> 22: #include <ctype.h> 23: #include <pwd.h> 24: #include <errno.h> 25: 26: #include <sys/param.h> 27: #include <sys/quota.h> 28: #include <sys/file.h> 29: #include <sys/stat.h> 30: 31: int qflag; 32: int vflag; 33: int done; 34: int morethanone; 35: char *qfname = "quotas"; 36: 37: main(argc, argv) 38: char *argv[]; 39: { 40: register char *cp; 41: extern int errno; 42: 43: if (quota(Q_SYNC, 0, 0, (caddr_t)0) < 0 && errno == EINVAL) { 44: fprintf(stderr, "There are no quotas on this system\n"); 45: exit(0); 46: } 47: argc--,argv++; 48: while (argc > 0) { 49: if (argv[0][0] == '-') 50: for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { 51: 52: case 'v': 53: vflag++; 54: break; 55: 56: case 'q': 57: qflag++; 58: break; 59: 60: default: 61: fprintf(stderr, "quota: %c: unknown option\n", 62: *cp); 63: exit(1); 64: } 65: else 66: break; 67: argc--, argv++; 68: } 69: morethanone = argc > 1; 70: if (argc == 0) { 71: showuid(getuid()); 72: exit(0); 73: } 74: for (; argc > 0; argc--, argv++) { 75: if (alldigits(*argv)) 76: showuid(atoi(*argv)); 77: else 78: showname(*argv); 79: } 80: } 81: 82: showuid(uid) 83: int uid; 84: { 85: struct passwd *pwd = getpwuid(uid); 86: 87: if (pwd == NULL) 88: showquotas(uid, "(no account)"); 89: else 90: showquotas(uid, pwd->pw_name); 91: } 92: 93: showname(name) 94: char *name; 95: { 96: struct passwd *pwd = getpwnam(name); 97: 98: if (pwd == NULL) { 99: fprintf(stderr, "quota: %s: unknown user\n", name); 100: return; 101: } 102: showquotas(pwd->pw_uid, name); 103: } 104: 105: showquotas(uid, name) 106: int uid; 107: char *name; 108: { 109: register struct fstab *fs; 110: register char *msgi, *msgb; 111: register enab = 1; 112: dev_t fsdev; 113: struct stat statb; 114: struct dqblk dqblk; 115: int myuid, fd; 116: char qfilename[MAXPATHLEN + 1], iwarn[8], dwarn[8]; 117: 118: myuid = getuid(); 119: if (uid != myuid && myuid != 0) { 120: printf("quota: %s (uid %d): permission denied\n", name, uid); 121: return; 122: } 123: done = 0; 124: (void) setfsent(); 125: while (fs = getfsent()) { 126: if (stat(fs->fs_spec, &statb) < 0) 127: continue; 128: msgi = msgb = (char *) 0; 129: fsdev = statb.st_rdev; 130: (void) sprintf(qfilename, "%s/%s", fs->fs_file, qfname); 131: if (stat(qfilename, &statb) < 0 || statb.st_dev != fsdev) 132: continue; 133: if (quota(Q_GETDLIM, uid, fsdev, (caddr_t)&dqblk) != 0) { 134: fd = open(qfilename, O_RDONLY); 135: if (fd < 0) 136: continue; 137: (void) lseek(fd, (off_t)(uid * sizeof (dqblk)), L_SET); 138: switch (read(fd, (char *)&dqblk, sizeof dqblk)) { 139: case 0: /* EOF */ 140: /* 141: * Convert implicit 0 quota (EOF) 142: * into an explicit one (zero'ed dqblk). 143: */ 144: bzero((caddr_t)&dqblk, sizeof dqblk); 145: break; 146: 147: case sizeof dqblk: /* OK */ 148: break; 149: 150: default: /* ERROR */ 151: fprintf(stderr, "quota: read error in "); 152: perror(qfilename); 153: (void) close(fd); 154: continue; 155: } 156: (void) close(fd); 157: if (!vflag && dqblk.dqb_isoftlimit == 0 && 158: dqblk.dqb_bsoftlimit == 0) 159: continue; 160: enab = 0; 161: } 162: if (dqblk.dqb_ihardlimit && 163: dqblk.dqb_curinodes >= dqblk.dqb_ihardlimit) 164: msgi = "File count limit reached on %s"; 165: else if (enab && dqblk.dqb_iwarn == 0) 166: msgi = "Out of inode warnings on %s"; 167: else if (dqblk.dqb_isoftlimit && 168: dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit) 169: msgi = "Too many files on %s"; 170: if (dqblk.dqb_bhardlimit && 171: dqblk.dqb_curblocks >= dqblk.dqb_bhardlimit) 172: msgb = "Block limit reached on %s"; 173: else if (enab && dqblk.dqb_bwarn == 0) 174: msgb = "Out of block warnings on %s"; 175: else if (dqblk.dqb_bsoftlimit && 176: dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit) 177: msgb = "Over disc quota on %s"; 178: if (dqblk.dqb_iwarn < MAX_IQ_WARN) 179: (void) sprintf(iwarn, "%d", dqblk.dqb_iwarn); 180: else 181: iwarn[0] = '\0'; 182: if (dqblk.dqb_bwarn < MAX_DQ_WARN) 183: (void) sprintf(dwarn, "%d", dqblk.dqb_bwarn); 184: else 185: dwarn[0] = '\0'; 186: if (qflag) { 187: if (msgi != (char *)0 || msgb != (char *)0) 188: heading(uid, name); 189: if (msgi != (char *)0) 190: xprintf(msgi, fs->fs_file); 191: if (msgb != (char *)0) 192: xprintf(msgb, fs->fs_file); 193: continue; 194: } 195: if (vflag || dqblk.dqb_curblocks || dqblk.dqb_curinodes) { 196: heading(uid, name); 197: printf("%10s%8d%c%7d%8d%8s%8d%c%7d%8d%8s\n" 198: , fs->fs_file 199: , dbtob(dqblk.dqb_curblocks) / 1024 200: , (msgb == (char *)0) ? ' ' : '*' 201: , dbtob(dqblk.dqb_bsoftlimit) / 1024 202: , dbtob(dqblk.dqb_bhardlimit) / 1024 203: , dwarn 204: , dqblk.dqb_curinodes 205: , (msgi == (char *)0) ? ' ' : '*' 206: , dqblk.dqb_isoftlimit 207: , dqblk.dqb_ihardlimit 208: , iwarn 209: ); 210: } 211: } 212: (void) endfsent(); 213: if (!done && !qflag) { 214: if (morethanone) 215: (void) putchar('\n'); 216: xprintf("Disc quotas for %s (uid %d):", name, uid); 217: xprintf("none."); 218: } 219: xprintf((char *)0); 220: } 221: 222: heading(uid, name) 223: int uid; 224: char *name; 225: { 226: 227: if (done++) 228: return; 229: xprintf((char *)0); 230: if (qflag) { 231: if (!morethanone) 232: return; 233: xprintf("User %s (uid %d):", name, uid); 234: xprintf((char *)0); 235: return; 236: } 237: (void) putchar('\n'); 238: xprintf("Disc quotas for %s (uid %d):", name, uid); 239: xprintf((char *)0); 240: printf("%10s%8s %7s%8s%8s%8s %7s%8s%8s\n" 241: , "Filsys" 242: , "current" 243: , "quota" 244: , "limit" 245: , "#warns" 246: , "files" 247: , "quota" 248: , "limit" 249: , "#warns" 250: ); 251: } 252: 253: /*VARARGS1*/ 254: xprintf(fmt, arg1, arg2, arg3, arg4, arg5, arg6) 255: char *fmt; 256: { 257: char buf[100]; 258: static int column; 259: 260: if (fmt == 0 && column || column >= 40) { 261: (void) putchar('\n'); 262: column = 0; 263: } 264: if (fmt == 0) 265: return; 266: (void) sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5, arg6); 267: if (column != 0 && strlen(buf) < 39) 268: while (column++ < 40) 269: (void) putchar(' '); 270: else if (column) { 271: (void) putchar('\n'); 272: column = 0; 273: } 274: printf("%s", buf); 275: column += strlen(buf); 276: } 277: 278: alldigits(s) 279: register char *s; 280: { 281: register c; 282: 283: c = *s++; 284: do { 285: if (!isdigit(c)) 286: return (0); 287: } while (c = *s++); 288: return (1); 289: }