xref: /csrg-svn/usr.bin/quota/quota.c (revision 12710)
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