Commit | Line | Data |
---|---|---|
2a18434a KM |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
f9ac90b4 KB |
3 | * All rights reserved. |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
5e8b0e60 KB |
6 | * provided that the above copyright notice and this paragraph are |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
2a18434a KM |
16 | */ |
17 | ||
18 | #ifndef lint | |
19 | char copyright[] = | |
20 | "@(#) Copyright (c) 1980 Regents of the University of California.\n\ | |
21 | All rights reserved.\n"; | |
f9ac90b4 | 22 | #endif /* not lint */ |
2a18434a | 23 | |
304d49a2 | 24 | #ifndef lint |
5e8b0e60 | 25 | static char sccsid[] = "@(#)quota.c 5.6 (Berkeley) %G%"; |
f9ac90b4 | 26 | #endif /* not lint */ |
304d49a2 KM |
27 | |
28 | /* | |
29 | * Disk quota reporting program. | |
30 | */ | |
31 | #include <stdio.h> | |
32 | #include <fstab.h> | |
33 | #include <ctype.h> | |
34 | #include <pwd.h> | |
879c30d3 | 35 | #include <errno.h> |
304d49a2 KM |
36 | |
37 | #include <sys/param.h> | |
304d49a2 KM |
38 | #include <sys/quota.h> |
39 | #include <sys/file.h> | |
40 | #include <sys/stat.h> | |
41 | ||
42 | int qflag; | |
43 | int vflag; | |
44 | int done; | |
45 | int morethanone; | |
a233b96c | 46 | char *qfname = "quotas"; |
304d49a2 KM |
47 | |
48 | main(argc, argv) | |
49 | char *argv[]; | |
50 | { | |
51 | register char *cp; | |
879c30d3 | 52 | extern int errno; |
304d49a2 | 53 | |
509d661f | 54 | if (quota(Q_SYNC, 0, 0, (caddr_t)0) < 0 && errno == EINVAL) { |
879c30d3 KM |
55 | fprintf(stderr, "There are no quotas on this system\n"); |
56 | exit(0); | |
57 | } | |
304d49a2 KM |
58 | argc--,argv++; |
59 | while (argc > 0) { | |
60 | if (argv[0][0] == '-') | |
61 | for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { | |
62 | ||
63 | case 'v': | |
64 | vflag++; | |
65 | break; | |
66 | ||
67 | case 'q': | |
68 | qflag++; | |
69 | break; | |
70 | ||
71 | default: | |
72 | fprintf(stderr, "quota: %c: unknown option\n", | |
73 | *cp); | |
74 | exit(1); | |
75 | } | |
76 | else | |
77 | break; | |
78 | argc--, argv++; | |
79 | } | |
80 | morethanone = argc > 1; | |
81 | if (argc == 0) { | |
82 | showuid(getuid()); | |
83 | exit(0); | |
84 | } | |
85 | for (; argc > 0; argc--, argv++) { | |
86 | if (alldigits(*argv)) | |
87 | showuid(atoi(*argv)); | |
88 | else | |
89 | showname(*argv); | |
90 | } | |
91 | } | |
92 | ||
93 | showuid(uid) | |
94 | int uid; | |
95 | { | |
96 | struct passwd *pwd = getpwuid(uid); | |
97 | ||
98 | if (pwd == NULL) | |
99 | showquotas(uid, "(no account)"); | |
100 | else | |
101 | showquotas(uid, pwd->pw_name); | |
102 | } | |
103 | ||
104 | showname(name) | |
105 | char *name; | |
106 | { | |
107 | struct passwd *pwd = getpwnam(name); | |
108 | ||
109 | if (pwd == NULL) { | |
110 | fprintf(stderr, "quota: %s: unknown user\n", name); | |
111 | return; | |
112 | } | |
113 | showquotas(pwd->pw_uid, name); | |
114 | } | |
115 | ||
116 | showquotas(uid, name) | |
117 | int uid; | |
118 | char *name; | |
119 | { | |
304d49a2 | 120 | register struct fstab *fs; |
509d661f | 121 | register char *msgi, *msgb; |
879c30d3 KM |
122 | register enab = 1; |
123 | dev_t fsdev; | |
124 | struct stat statb; | |
125 | struct dqblk dqblk; | |
126 | int myuid, fd; | |
127 | char qfilename[MAXPATHLEN + 1], iwarn[8], dwarn[8]; | |
304d49a2 KM |
128 | |
129 | myuid = getuid(); | |
130 | if (uid != myuid && myuid != 0) { | |
131 | printf("quota: %s (uid %d): permission denied\n", name, uid); | |
132 | return; | |
133 | } | |
134 | done = 0; | |
509d661f | 135 | (void) setfsent(); |
304d49a2 | 136 | while (fs = getfsent()) { |
304d49a2 KM |
137 | if (stat(fs->fs_spec, &statb) < 0) |
138 | continue; | |
509d661f | 139 | msgi = msgb = (char *) 0; |
304d49a2 | 140 | fsdev = statb.st_rdev; |
a233b96c KM |
141 | (void) sprintf(qfilename, "%s/%s", fs->fs_file, qfname); |
142 | if (stat(qfilename, &statb) < 0 || statb.st_dev != fsdev) | |
304d49a2 | 143 | continue; |
509d661f | 144 | if (quota(Q_GETDLIM, uid, fsdev, (caddr_t)&dqblk) != 0) { |
879c30d3 | 145 | fd = open(qfilename, O_RDONLY); |
304d49a2 KM |
146 | if (fd < 0) |
147 | continue; | |
509d661f JL |
148 | (void) lseek(fd, (off_t)(uid * sizeof (dqblk)), L_SET); |
149 | switch (read(fd, (char *)&dqblk, sizeof dqblk)) { | |
605f81f3 S |
150 | case 0: /* EOF */ |
151 | /* | |
152 | * Convert implicit 0 quota (EOF) | |
153 | * into an explicit one (zero'ed dqblk). | |
154 | */ | |
155 | bzero((caddr_t)&dqblk, sizeof dqblk); | |
156 | break; | |
157 | ||
158 | case sizeof dqblk: /* OK */ | |
159 | break; | |
160 | ||
161 | default: /* ERROR */ | |
162 | fprintf(stderr, "quota: read error in "); | |
163 | perror(qfilename); | |
509d661f | 164 | (void) close(fd); |
304d49a2 KM |
165 | continue; |
166 | } | |
509d661f | 167 | (void) close(fd); |
605f81f3 | 168 | if (!vflag && dqblk.dqb_isoftlimit == 0 && |
304d49a2 KM |
169 | dqblk.dqb_bsoftlimit == 0) |
170 | continue; | |
171 | enab = 0; | |
172 | } | |
173 | if (dqblk.dqb_ihardlimit && | |
174 | dqblk.dqb_curinodes >= dqblk.dqb_ihardlimit) | |
175 | msgi = "File count limit reached on %s"; | |
176 | else if (enab && dqblk.dqb_iwarn == 0) | |
177 | msgi = "Out of inode warnings on %s"; | |
178 | else if (dqblk.dqb_isoftlimit && | |
179 | dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit) | |
180 | msgi = "Too many files on %s"; | |
181 | if (dqblk.dqb_bhardlimit && | |
182 | dqblk.dqb_curblocks >= dqblk.dqb_bhardlimit) | |
183 | msgb = "Block limit reached on %s"; | |
184 | else if (enab && dqblk.dqb_bwarn == 0) | |
185 | msgb = "Out of block warnings on %s"; | |
186 | else if (dqblk.dqb_bsoftlimit && | |
187 | dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit) | |
188 | msgb = "Over disc quota on %s"; | |
189 | if (dqblk.dqb_iwarn < MAX_IQ_WARN) | |
509d661f | 190 | (void) sprintf(iwarn, "%d", dqblk.dqb_iwarn); |
304d49a2 KM |
191 | else |
192 | iwarn[0] = '\0'; | |
193 | if (dqblk.dqb_bwarn < MAX_DQ_WARN) | |
509d661f | 194 | (void) sprintf(dwarn, "%d", dqblk.dqb_bwarn); |
304d49a2 KM |
195 | else |
196 | dwarn[0] = '\0'; | |
197 | if (qflag) { | |
198 | if (msgi != (char *)0 || msgb != (char *)0) | |
199 | heading(uid, name); | |
200 | if (msgi != (char *)0) | |
201 | xprintf(msgi, fs->fs_file); | |
202 | if (msgb != (char *)0) | |
203 | xprintf(msgb, fs->fs_file); | |
204 | continue; | |
205 | } | |
206 | if (vflag || dqblk.dqb_curblocks || dqblk.dqb_curinodes) { | |
207 | heading(uid, name); | |
c085c6e0 | 208 | printf("%10s%8d%c%7d%8d%8s%8d%c%7d%8d%8s\n" |
304d49a2 | 209 | , fs->fs_file |
285a6d40 | 210 | , dbtob(dqblk.dqb_curblocks) / 1024 |
304d49a2 | 211 | , (msgb == (char *)0) ? ' ' : '*' |
285a6d40 JB |
212 | , dbtob(dqblk.dqb_bsoftlimit) / 1024 |
213 | , dbtob(dqblk.dqb_bhardlimit) / 1024 | |
304d49a2 KM |
214 | , dwarn |
215 | , dqblk.dqb_curinodes | |
216 | , (msgi == (char *)0) ? ' ' : '*' | |
217 | , dqblk.dqb_isoftlimit | |
96b539f0 | 218 | , dqblk.dqb_ihardlimit |
304d49a2 KM |
219 | , iwarn |
220 | ); | |
221 | } | |
222 | } | |
509d661f | 223 | (void) endfsent(); |
304d49a2 KM |
224 | if (!done && !qflag) { |
225 | if (morethanone) | |
509d661f | 226 | (void) putchar('\n'); |
304d49a2 KM |
227 | xprintf("Disc quotas for %s (uid %d):", name, uid); |
228 | xprintf("none."); | |
229 | } | |
605f81f3 | 230 | xprintf((char *)0); |
304d49a2 KM |
231 | } |
232 | ||
233 | heading(uid, name) | |
234 | int uid; | |
235 | char *name; | |
236 | { | |
237 | ||
238 | if (done++) | |
239 | return; | |
605f81f3 | 240 | xprintf((char *)0); |
304d49a2 KM |
241 | if (qflag) { |
242 | if (!morethanone) | |
243 | return; | |
244 | xprintf("User %s (uid %d):", name, uid); | |
605f81f3 | 245 | xprintf((char *)0); |
304d49a2 KM |
246 | return; |
247 | } | |
509d661f | 248 | (void) putchar('\n'); |
304d49a2 | 249 | xprintf("Disc quotas for %s (uid %d):", name, uid); |
605f81f3 | 250 | xprintf((char *)0); |
c085c6e0 | 251 | printf("%10s%8s %7s%8s%8s%8s %7s%8s%8s\n" |
304d49a2 KM |
252 | , "Filsys" |
253 | , "current" | |
254 | , "quota" | |
255 | , "limit" | |
256 | , "#warns" | |
257 | , "files" | |
258 | , "quota" | |
259 | , "limit" | |
260 | , "#warns" | |
261 | ); | |
262 | } | |
263 | ||
605f81f3 | 264 | /*VARARGS1*/ |
304d49a2 KM |
265 | xprintf(fmt, arg1, arg2, arg3, arg4, arg5, arg6) |
266 | char *fmt; | |
267 | { | |
268 | char buf[100]; | |
269 | static int column; | |
270 | ||
271 | if (fmt == 0 && column || column >= 40) { | |
509d661f | 272 | (void) putchar('\n'); |
304d49a2 KM |
273 | column = 0; |
274 | } | |
275 | if (fmt == 0) | |
276 | return; | |
509d661f | 277 | (void) sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5, arg6); |
304d49a2 KM |
278 | if (column != 0 && strlen(buf) < 39) |
279 | while (column++ < 40) | |
509d661f | 280 | (void) putchar(' '); |
304d49a2 | 281 | else if (column) { |
509d661f | 282 | (void) putchar('\n'); |
304d49a2 KM |
283 | column = 0; |
284 | } | |
285 | printf("%s", buf); | |
286 | column += strlen(buf); | |
287 | } | |
288 | ||
289 | alldigits(s) | |
290 | register char *s; | |
291 | { | |
292 | register c; | |
293 | ||
294 | c = *s++; | |
295 | do { | |
296 | if (!isdigit(c)) | |
297 | return (0); | |
298 | } while (c = *s++); | |
299 | return (1); | |
300 | } |