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