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