xref: /csrg-svn/usr.bin/quota/quota.c (revision 38515)
121520Smckusick /*
221520Smckusick  * Copyright (c) 1980 Regents of the University of California.
334372Sbostic  * All rights reserved.
434372Sbostic  *
534372Sbostic  * Redistribution and use in source and binary forms are permitted
634911Sbostic  * provided that the above copyright notice and this paragraph are
734911Sbostic  * duplicated in all such forms and that any documentation,
834911Sbostic  * advertising materials, and other materials related to such
934911Sbostic  * distribution and use acknowledge that the software was developed
1034911Sbostic  * by the University of California, Berkeley.  The name of the
1134911Sbostic  * University may not be used to endorse or promote products derived
1234911Sbostic  * from this software without specific prior written permission.
1334911Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434911Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534911Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621520Smckusick  */
1721520Smckusick 
1812710Smckusick #ifndef lint
1921520Smckusick char copyright[] =
2021520Smckusick "@(#) Copyright (c) 1980 Regents of the University of California.\n\
2121520Smckusick  All rights reserved.\n";
2234372Sbostic #endif /* not lint */
2312710Smckusick 
2421520Smckusick #ifndef lint
25*38515Sbostic static char sccsid[] = "@(#)quota.c	5.8 (Berkeley) 07/30/89";
2634372Sbostic #endif /* not lint */
2721520Smckusick 
2812710Smckusick /*
2912710Smckusick  * Disk quota reporting program.
3012710Smckusick  */
3137078Sbostic #include <sys/param.h>
3237078Sbostic #include <sys/file.h>
3337078Sbostic #include <sys/stat.h>
34*38515Sbostic #include <ufs/quota.h>
3512710Smckusick #include <stdio.h>
3612710Smckusick #include <fstab.h>
3712710Smckusick #include <ctype.h>
3812710Smckusick #include <pwd.h>
3921392Smckusick #include <errno.h>
4012710Smckusick 
4112710Smckusick 
4212710Smckusick int	qflag;
4312710Smckusick int	vflag;
4412710Smckusick int	done;
4512710Smckusick int	morethanone;
4612711Smckusick char	*qfname = "quotas";
4712710Smckusick 
4812710Smckusick main(argc, argv)
4912710Smckusick 	char *argv[];
5012710Smckusick {
5112710Smckusick 	register char *cp;
5221392Smckusick 	extern int errno;
5312710Smckusick 
5426401Slepreau 	if (quota(Q_SYNC, 0, 0, (caddr_t)0) < 0 && errno == EINVAL) {
5521392Smckusick 		fprintf(stderr, "There are no quotas on this system\n");
5621392Smckusick 		exit(0);
5721392Smckusick 	}
5812710Smckusick 	argc--,argv++;
5912710Smckusick 	while (argc > 0) {
6012710Smckusick 		if (argv[0][0] == '-')
6112710Smckusick 			for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {
6212710Smckusick 
6312710Smckusick 			case 'v':
6412710Smckusick 				vflag++;
6512710Smckusick 				break;
6612710Smckusick 
6712710Smckusick 			case 'q':
6812710Smckusick 				qflag++;
6912710Smckusick 				break;
7012710Smckusick 
7112710Smckusick 			default:
7212710Smckusick 				fprintf(stderr, "quota: %c: unknown option\n",
7312710Smckusick 					*cp);
7412710Smckusick 				exit(1);
7512710Smckusick 			}
7612710Smckusick 		else
7712710Smckusick 			break;
7812710Smckusick 		argc--, argv++;
7912710Smckusick 	}
8012710Smckusick 	morethanone = argc > 1;
8112710Smckusick 	if (argc == 0) {
8212710Smckusick 		showuid(getuid());
8312710Smckusick 		exit(0);
8412710Smckusick 	}
8512710Smckusick 	for (; argc > 0; argc--, argv++) {
8612710Smckusick 		if (alldigits(*argv))
8712710Smckusick 			showuid(atoi(*argv));
8812710Smckusick 		else
8912710Smckusick 			showname(*argv);
9012710Smckusick 	}
9112710Smckusick }
9212710Smckusick 
9312710Smckusick showuid(uid)
9412710Smckusick 	int uid;
9512710Smckusick {
9612710Smckusick 	struct passwd *pwd = getpwuid(uid);
9712710Smckusick 
9812710Smckusick 	if (pwd == NULL)
9912710Smckusick 		showquotas(uid, "(no account)");
10012710Smckusick 	else
10112710Smckusick 		showquotas(uid, pwd->pw_name);
10212710Smckusick }
10312710Smckusick 
10412710Smckusick showname(name)
10512710Smckusick 	char *name;
10612710Smckusick {
10712710Smckusick 	struct passwd *pwd = getpwnam(name);
10812710Smckusick 
10912710Smckusick 	if (pwd == NULL) {
11012710Smckusick 		fprintf(stderr, "quota: %s: unknown user\n", name);
11112710Smckusick 		return;
11212710Smckusick 	}
11312710Smckusick 	showquotas(pwd->pw_uid, name);
11412710Smckusick }
11512710Smckusick 
11612710Smckusick showquotas(uid, name)
11712710Smckusick 	int uid;
11812710Smckusick 	char *name;
11912710Smckusick {
12012710Smckusick 	register struct fstab *fs;
12126401Slepreau 	register char *msgi, *msgb;
12221392Smckusick 	register enab = 1;
12321392Smckusick 	dev_t	fsdev;
12421392Smckusick 	struct	stat statb;
12521392Smckusick 	struct	dqblk dqblk;
12621392Smckusick 	int myuid, fd;
12721392Smckusick 	char qfilename[MAXPATHLEN + 1], iwarn[8], dwarn[8];
12812710Smckusick 
12912710Smckusick 	myuid = getuid();
13012710Smckusick 	if (uid != myuid && myuid != 0) {
13112710Smckusick 		printf("quota: %s (uid %d): permission denied\n", name, uid);
13212710Smckusick 		return;
13312710Smckusick 	}
13412710Smckusick 	done = 0;
13526401Slepreau 	(void) setfsent();
13612710Smckusick 	while (fs = getfsent()) {
13712710Smckusick 		if (stat(fs->fs_spec, &statb) < 0)
13812710Smckusick 			continue;
13926401Slepreau 		msgi = msgb = (char *) 0;
14012710Smckusick 		fsdev = statb.st_rdev;
14112711Smckusick 		(void) sprintf(qfilename, "%s/%s", fs->fs_file, qfname);
14212711Smckusick 		if (stat(qfilename, &statb) < 0 || statb.st_dev != fsdev)
14312710Smckusick 			continue;
14426401Slepreau 		if (quota(Q_GETDLIM, uid, fsdev, (caddr_t)&dqblk) != 0) {
14521392Smckusick 			fd = open(qfilename, O_RDONLY);
14612710Smckusick 			if (fd < 0)
14712710Smckusick 				continue;
14826401Slepreau 			(void) lseek(fd, (off_t)(uid * sizeof (dqblk)), L_SET);
14926401Slepreau 			switch (read(fd, (char *)&dqblk, sizeof dqblk)) {
15024684Sserge 			case 0:			/* EOF */
15124684Sserge 				/*
15224684Sserge 				 * Convert implicit 0 quota (EOF)
15324684Sserge 				 * into an explicit one (zero'ed dqblk).
15424684Sserge 				 */
15524684Sserge 				bzero((caddr_t)&dqblk, sizeof dqblk);
15624684Sserge 				break;
15724684Sserge 
15824684Sserge 			case sizeof dqblk:	/* OK */
15924684Sserge 				break;
16024684Sserge 
16124684Sserge 			default:		/* ERROR */
16224684Sserge 				fprintf(stderr, "quota: read error in ");
16324684Sserge 				perror(qfilename);
16426401Slepreau 				(void) close(fd);
16512710Smckusick 				continue;
16612710Smckusick 			}
16726401Slepreau 			(void) close(fd);
16824684Sserge 			if (!vflag && dqblk.dqb_isoftlimit == 0 &&
16912710Smckusick 			    dqblk.dqb_bsoftlimit == 0)
17012710Smckusick 				continue;
17112710Smckusick 			enab = 0;
17212710Smckusick 		}
17312710Smckusick 		if (dqblk.dqb_ihardlimit &&
17412710Smckusick 		    dqblk.dqb_curinodes >= dqblk.dqb_ihardlimit)
17512710Smckusick 			msgi = "File count limit reached on %s";
17612710Smckusick 		else if (enab && dqblk.dqb_iwarn == 0)
17712710Smckusick 			msgi = "Out of inode warnings on %s";
17812710Smckusick 		else if (dqblk.dqb_isoftlimit &&
17912710Smckusick 		    dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit)
18012710Smckusick 			msgi = "Too many files on %s";
18112710Smckusick 		if (dqblk.dqb_bhardlimit &&
18212710Smckusick 		    dqblk.dqb_curblocks >= dqblk.dqb_bhardlimit)
18312710Smckusick 			msgb = "Block limit reached on %s";
18412710Smckusick 		else if (enab && dqblk.dqb_bwarn == 0)
18512710Smckusick 			msgb = "Out of block warnings on %s";
18612710Smckusick 		else if (dqblk.dqb_bsoftlimit &&
18712710Smckusick 		    dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit)
18812710Smckusick 			msgb = "Over disc quota on %s";
18912710Smckusick 		if (dqblk.dqb_iwarn < MAX_IQ_WARN)
19026401Slepreau 			(void) sprintf(iwarn, "%d", dqblk.dqb_iwarn);
19112710Smckusick 		else
19212710Smckusick 			iwarn[0] = '\0';
19312710Smckusick 		if (dqblk.dqb_bwarn < MAX_DQ_WARN)
19426401Slepreau 			(void) sprintf(dwarn, "%d", dqblk.dqb_bwarn);
19512710Smckusick 		else
19612710Smckusick 			dwarn[0] = '\0';
19712710Smckusick 		if (qflag) {
19812710Smckusick 			if (msgi != (char *)0 || msgb != (char *)0)
19912710Smckusick 				heading(uid, name);
20012710Smckusick 			if (msgi != (char *)0)
20112710Smckusick 				xprintf(msgi, fs->fs_file);
20212710Smckusick 			if (msgb != (char *)0)
20312710Smckusick 				xprintf(msgb, fs->fs_file);
20412710Smckusick 			continue;
20512710Smckusick 		}
20612710Smckusick 		if (vflag || dqblk.dqb_curblocks || dqblk.dqb_curinodes) {
20712710Smckusick 			heading(uid, name);
20813222Ssam 			printf("%10s%8d%c%7d%8d%8s%8d%c%7d%8d%8s\n"
20912710Smckusick 				, fs->fs_file
21025400Sbloom 				, dbtob(dqblk.dqb_curblocks) / 1024
21112710Smckusick 				, (msgb == (char *)0) ? ' ' : '*'
21225400Sbloom 				, dbtob(dqblk.dqb_bsoftlimit) / 1024
21325400Sbloom 				, dbtob(dqblk.dqb_bhardlimit) / 1024
21412710Smckusick 				, dwarn
21512710Smckusick 				, dqblk.dqb_curinodes
21612710Smckusick 				, (msgi == (char *)0) ? ' ' : '*'
21712710Smckusick 				, dqblk.dqb_isoftlimit
21812721Smckusick 				, dqblk.dqb_ihardlimit
21912710Smckusick 				, iwarn
22012710Smckusick 			);
22112710Smckusick 		}
22212710Smckusick 	}
22326401Slepreau 	(void) endfsent();
22412710Smckusick 	if (!done && !qflag) {
22512710Smckusick 		if (morethanone)
22626401Slepreau 			(void) putchar('\n');
22712710Smckusick 		xprintf("Disc quotas for %s (uid %d):", name, uid);
22812710Smckusick 		xprintf("none.");
22912710Smckusick 	}
23024684Sserge 	xprintf((char *)0);
23112710Smckusick }
23212710Smckusick 
23312710Smckusick heading(uid, name)
23412710Smckusick 	int uid;
23512710Smckusick 	char *name;
23612710Smckusick {
23712710Smckusick 
23812710Smckusick 	if (done++)
23912710Smckusick 		return;
24024684Sserge 	xprintf((char *)0);
24112710Smckusick 	if (qflag) {
24212710Smckusick 		if (!morethanone)
24312710Smckusick 			return;
24412710Smckusick 		xprintf("User %s (uid %d):", name, uid);
24524684Sserge 		xprintf((char *)0);
24612710Smckusick 		return;
24712710Smckusick 	}
24826401Slepreau 	(void) putchar('\n');
24912710Smckusick 	xprintf("Disc quotas for %s (uid %d):", name, uid);
25024684Sserge 	xprintf((char *)0);
25113222Ssam 	printf("%10s%8s %7s%8s%8s%8s %7s%8s%8s\n"
25212710Smckusick 		, "Filsys"
25312710Smckusick 		, "current"
25412710Smckusick 		, "quota"
25512710Smckusick 		, "limit"
25612710Smckusick 		, "#warns"
25712710Smckusick 		, "files"
25812710Smckusick 		, "quota"
25912710Smckusick 		, "limit"
26012710Smckusick 		, "#warns"
26112710Smckusick 	);
26212710Smckusick }
26312710Smckusick 
26424684Sserge /*VARARGS1*/
26512710Smckusick xprintf(fmt, arg1, arg2, arg3, arg4, arg5, arg6)
26612710Smckusick 	char *fmt;
26712710Smckusick {
26812710Smckusick 	char	buf[100];
26912710Smckusick 	static int column;
27012710Smckusick 
27112710Smckusick 	if (fmt == 0 && column || column >= 40) {
27226401Slepreau 		(void) putchar('\n');
27312710Smckusick 		column = 0;
27412710Smckusick 	}
27512710Smckusick 	if (fmt == 0)
27612710Smckusick 		return;
27726401Slepreau 	(void) sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5, arg6);
27812710Smckusick 	if (column != 0 && strlen(buf) < 39)
27912710Smckusick 		while (column++ < 40)
28026401Slepreau 			(void) putchar(' ');
28112710Smckusick 	else if (column) {
28226401Slepreau 		(void) putchar('\n');
28312710Smckusick 		column = 0;
28412710Smckusick 	}
28512710Smckusick 	printf("%s", buf);
28612710Smckusick 	column += strlen(buf);
28712710Smckusick }
28812710Smckusick 
28912710Smckusick alldigits(s)
29012710Smckusick 	register char *s;
29112710Smckusick {
29212710Smckusick 	register c;
29312710Smckusick 
29412710Smckusick 	c = *s++;
29512710Smckusick 	do {
29612710Smckusick 		if (!isdigit(c))
29712710Smckusick 			return (0);
29812710Smckusick 	} while (c = *s++);
29912710Smckusick 	return (1);
30012710Smckusick }
301