xref: /csrg-svn/usr.bin/quota/quota.c (revision 21520)
1*21520Smckusick /*
2*21520Smckusick  * Copyright (c) 1980 Regents of the University of California.
3*21520Smckusick  * All rights reserved.  The Berkeley software License Agreement
4*21520Smckusick  * specifies the terms and conditions for redistribution.
5*21520Smckusick  */
6*21520Smckusick 
712710Smckusick #ifndef lint
8*21520Smckusick char copyright[] =
9*21520Smckusick "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10*21520Smckusick  All rights reserved.\n";
11*21520Smckusick #endif not lint
1212710Smckusick 
13*21520Smckusick #ifndef lint
14*21520Smckusick static char sccsid[] = "@(#)quota.c	5.1 (Berkeley) 05/30/85";
15*21520Smckusick #endif not lint
16*21520Smckusick 
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);
13812710Smckusick 			if (read(fd, &dqblk, sizeof dqblk) != sizeof (dqblk)) {
13912710Smckusick 				close(fd);
14012710Smckusick 				continue;
14112710Smckusick 			}
14212710Smckusick 			close(fd);
14312710Smckusick 			if (dqblk.dqb_isoftlimit == 0 &&
14412710Smckusick 			    dqblk.dqb_bsoftlimit == 0)
14512710Smckusick 				continue;
14612710Smckusick 			enab = 0;
14712710Smckusick 		}
14812710Smckusick 		if (dqblk.dqb_ihardlimit &&
14912710Smckusick 		    dqblk.dqb_curinodes >= dqblk.dqb_ihardlimit)
15012710Smckusick 			msgi = "File count limit reached on %s";
15112710Smckusick 		else if (enab && dqblk.dqb_iwarn == 0)
15212710Smckusick 			msgi = "Out of inode warnings on %s";
15312710Smckusick 		else if (dqblk.dqb_isoftlimit &&
15412710Smckusick 		    dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit)
15512710Smckusick 			msgi = "Too many files on %s";
15612710Smckusick 		if (dqblk.dqb_bhardlimit &&
15712710Smckusick 		    dqblk.dqb_curblocks >= dqblk.dqb_bhardlimit)
15812710Smckusick 			msgb = "Block limit reached on %s";
15912710Smckusick 		else if (enab && dqblk.dqb_bwarn == 0)
16012710Smckusick 			msgb = "Out of block warnings on %s";
16112710Smckusick 		else if (dqblk.dqb_bsoftlimit &&
16212710Smckusick 		    dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit)
16312710Smckusick 			msgb = "Over disc quota on %s";
16412710Smckusick 		if (dqblk.dqb_iwarn < MAX_IQ_WARN)
16512710Smckusick 			sprintf(iwarn, "%d", dqblk.dqb_iwarn);
16612710Smckusick 		else
16712710Smckusick 			iwarn[0] = '\0';
16812710Smckusick 		if (dqblk.dqb_bwarn < MAX_DQ_WARN)
16912710Smckusick 			sprintf(dwarn, "%d", dqblk.dqb_bwarn);
17012710Smckusick 		else
17112710Smckusick 			dwarn[0] = '\0';
17212710Smckusick 		if (qflag) {
17312710Smckusick 			if (msgi != (char *)0 || msgb != (char *)0)
17412710Smckusick 				heading(uid, name);
17512710Smckusick 			if (msgi != (char *)0)
17612710Smckusick 				xprintf(msgi, fs->fs_file);
17712710Smckusick 			if (msgb != (char *)0)
17812710Smckusick 				xprintf(msgb, fs->fs_file);
17912710Smckusick 			continue;
18012710Smckusick 		}
18112710Smckusick 		if (vflag || dqblk.dqb_curblocks || dqblk.dqb_curinodes) {
18212710Smckusick 			heading(uid, name);
18313222Ssam 			printf("%10s%8d%c%7d%8d%8s%8d%c%7d%8d%8s\n"
18412710Smckusick 				, fs->fs_file
18512721Smckusick 				, (dqblk.dqb_curblocks / btodb(1024))
18612710Smckusick 				, (msgb == (char *)0) ? ' ' : '*'
18712721Smckusick 				, (dqblk.dqb_bsoftlimit / btodb(1024))
18812721Smckusick 				, (dqblk.dqb_bhardlimit / btodb(1024))
18912710Smckusick 				, dwarn
19012710Smckusick 				, dqblk.dqb_curinodes
19112710Smckusick 				, (msgi == (char *)0) ? ' ' : '*'
19212710Smckusick 				, dqblk.dqb_isoftlimit
19312721Smckusick 				, dqblk.dqb_ihardlimit
19412710Smckusick 				, iwarn
19512710Smckusick 			);
19612710Smckusick 		}
19712710Smckusick 	}
19812710Smckusick 	endfsent();
19912710Smckusick 	if (!done && !qflag) {
20012710Smckusick 		if (morethanone)
20112710Smckusick 			putchar('\n');
20212710Smckusick 		xprintf("Disc quotas for %s (uid %d):", name, uid);
20312710Smckusick 		xprintf("none.");
20412710Smckusick 	}
20512710Smckusick 	xprintf(0);
20612710Smckusick }
20712710Smckusick 
20812710Smckusick heading(uid, name)
20912710Smckusick 	int uid;
21012710Smckusick 	char *name;
21112710Smckusick {
21212710Smckusick 
21312710Smckusick 	if (done++)
21412710Smckusick 		return;
21512710Smckusick 	xprintf(0);
21612710Smckusick 	if (qflag) {
21712710Smckusick 		if (!morethanone)
21812710Smckusick 			return;
21912710Smckusick 		xprintf("User %s (uid %d):", name, uid);
22012710Smckusick 		xprintf(0);
22112710Smckusick 		return;
22212710Smckusick 	}
22312710Smckusick 	putchar('\n');
22412710Smckusick 	xprintf("Disc quotas for %s (uid %d):", name, uid);
22512710Smckusick 	xprintf(0);
22613222Ssam 	printf("%10s%8s %7s%8s%8s%8s %7s%8s%8s\n"
22712710Smckusick 		, "Filsys"
22812710Smckusick 		, "current"
22912710Smckusick 		, "quota"
23012710Smckusick 		, "limit"
23112710Smckusick 		, "#warns"
23212710Smckusick 		, "files"
23312710Smckusick 		, "quota"
23412710Smckusick 		, "limit"
23512710Smckusick 		, "#warns"
23612710Smckusick 	);
23712710Smckusick }
23812710Smckusick 
23912710Smckusick xprintf(fmt, arg1, arg2, arg3, arg4, arg5, arg6)
24012710Smckusick 	char *fmt;
24112710Smckusick {
24212710Smckusick 	char	buf[100];
24312710Smckusick 	static int column;
24412710Smckusick 
24512710Smckusick 	if (fmt == 0 && column || column >= 40) {
24612710Smckusick 		putchar('\n');
24712710Smckusick 		column = 0;
24812710Smckusick 	}
24912710Smckusick 	if (fmt == 0)
25012710Smckusick 		return;
25112710Smckusick 	sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5, arg6);
25212710Smckusick 	if (column != 0 && strlen(buf) < 39)
25312710Smckusick 		while (column++ < 40)
25412710Smckusick 			putchar(' ');
25512710Smckusick 	else if (column) {
25612710Smckusick 		putchar('\n');
25712710Smckusick 		column = 0;
25812710Smckusick 	}
25912710Smckusick 	printf("%s", buf);
26012710Smckusick 	column += strlen(buf);
26112710Smckusick }
26212710Smckusick 
26312710Smckusick alldigits(s)
26412710Smckusick 	register char *s;
26512710Smckusick {
26612710Smckusick 	register c;
26712710Smckusick 
26812710Smckusick 	c = *s++;
26912710Smckusick 	do {
27012710Smckusick 		if (!isdigit(c))
27112710Smckusick 			return (0);
27212710Smckusick 	} while (c = *s++);
27312710Smckusick 	return (1);
27412710Smckusick }
275