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