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 |
2a18434a KM |
14 | static char sccsid[] = "@(#)quota.c 5.1 (Berkeley) %G%"; |
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 | |
879c30d3 KM |
43 | if (quota(Q_SYNC, 0, 0, 0) < 0 && errno == EINVAL) { |
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 | { | |
109 | register char c, *p; | |
110 | register struct fstab *fs; | |
879c30d3 KM |
111 | register char *msgi = (char *)0, *msgb = (char *)0; |
112 | register enab = 1; | |
113 | dev_t fsdev; | |
114 | struct stat statb; | |
115 | struct dqblk dqblk; | |
116 | int myuid, fd; | |
117 | char qfilename[MAXPATHLEN + 1], iwarn[8], dwarn[8]; | |
304d49a2 KM |
118 | |
119 | myuid = getuid(); | |
120 | if (uid != myuid && myuid != 0) { | |
121 | printf("quota: %s (uid %d): permission denied\n", name, uid); | |
122 | return; | |
123 | } | |
124 | done = 0; | |
125 | setfsent(); | |
126 | while (fs = getfsent()) { | |
304d49a2 KM |
127 | if (stat(fs->fs_spec, &statb) < 0) |
128 | continue; | |
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 KM |
132 | continue; |
133 | if (quota(Q_GETDLIM, uid, fsdev, &dqblk) != 0) { | |
879c30d3 | 134 | fd = open(qfilename, O_RDONLY); |
304d49a2 KM |
135 | if (fd < 0) |
136 | continue; | |
96b539f0 | 137 | lseek(fd, (long)(uid * sizeof (dqblk)), L_SET); |
304d49a2 KM |
138 | if (read(fd, &dqblk, sizeof dqblk) != sizeof (dqblk)) { |
139 | close(fd); | |
140 | continue; | |
141 | } | |
142 | close(fd); | |
143 | if (dqblk.dqb_isoftlimit == 0 && | |
144 | dqblk.dqb_bsoftlimit == 0) | |
145 | continue; | |
146 | enab = 0; | |
147 | } | |
148 | if (dqblk.dqb_ihardlimit && | |
149 | dqblk.dqb_curinodes >= dqblk.dqb_ihardlimit) | |
150 | msgi = "File count limit reached on %s"; | |
151 | else if (enab && dqblk.dqb_iwarn == 0) | |
152 | msgi = "Out of inode warnings on %s"; | |
153 | else if (dqblk.dqb_isoftlimit && | |
154 | dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit) | |
155 | msgi = "Too many files on %s"; | |
156 | if (dqblk.dqb_bhardlimit && | |
157 | dqblk.dqb_curblocks >= dqblk.dqb_bhardlimit) | |
158 | msgb = "Block limit reached on %s"; | |
159 | else if (enab && dqblk.dqb_bwarn == 0) | |
160 | msgb = "Out of block warnings on %s"; | |
161 | else if (dqblk.dqb_bsoftlimit && | |
162 | dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit) | |
163 | msgb = "Over disc quota on %s"; | |
164 | if (dqblk.dqb_iwarn < MAX_IQ_WARN) | |
165 | sprintf(iwarn, "%d", dqblk.dqb_iwarn); | |
166 | else | |
167 | iwarn[0] = '\0'; | |
168 | if (dqblk.dqb_bwarn < MAX_DQ_WARN) | |
169 | sprintf(dwarn, "%d", dqblk.dqb_bwarn); | |
170 | else | |
171 | dwarn[0] = '\0'; | |
172 | if (qflag) { | |
173 | if (msgi != (char *)0 || msgb != (char *)0) | |
174 | heading(uid, name); | |
175 | if (msgi != (char *)0) | |
176 | xprintf(msgi, fs->fs_file); | |
177 | if (msgb != (char *)0) | |
178 | xprintf(msgb, fs->fs_file); | |
179 | continue; | |
180 | } | |
181 | if (vflag || dqblk.dqb_curblocks || dqblk.dqb_curinodes) { | |
182 | heading(uid, name); | |
c085c6e0 | 183 | printf("%10s%8d%c%7d%8d%8s%8d%c%7d%8d%8s\n" |
304d49a2 | 184 | , fs->fs_file |
96b539f0 | 185 | , (dqblk.dqb_curblocks / btodb(1024)) |
304d49a2 | 186 | , (msgb == (char *)0) ? ' ' : '*' |
96b539f0 KM |
187 | , (dqblk.dqb_bsoftlimit / btodb(1024)) |
188 | , (dqblk.dqb_bhardlimit / btodb(1024)) | |
304d49a2 KM |
189 | , dwarn |
190 | , dqblk.dqb_curinodes | |
191 | , (msgi == (char *)0) ? ' ' : '*' | |
192 | , dqblk.dqb_isoftlimit | |
96b539f0 | 193 | , dqblk.dqb_ihardlimit |
304d49a2 KM |
194 | , iwarn |
195 | ); | |
196 | } | |
197 | } | |
198 | endfsent(); | |
199 | if (!done && !qflag) { | |
200 | if (morethanone) | |
201 | putchar('\n'); | |
202 | xprintf("Disc quotas for %s (uid %d):", name, uid); | |
203 | xprintf("none."); | |
204 | } | |
205 | xprintf(0); | |
206 | } | |
207 | ||
208 | heading(uid, name) | |
209 | int uid; | |
210 | char *name; | |
211 | { | |
212 | ||
213 | if (done++) | |
214 | return; | |
215 | xprintf(0); | |
216 | if (qflag) { | |
217 | if (!morethanone) | |
218 | return; | |
219 | xprintf("User %s (uid %d):", name, uid); | |
220 | xprintf(0); | |
221 | return; | |
222 | } | |
223 | putchar('\n'); | |
224 | xprintf("Disc quotas for %s (uid %d):", name, uid); | |
225 | xprintf(0); | |
c085c6e0 | 226 | printf("%10s%8s %7s%8s%8s%8s %7s%8s%8s\n" |
304d49a2 KM |
227 | , "Filsys" |
228 | , "current" | |
229 | , "quota" | |
230 | , "limit" | |
231 | , "#warns" | |
232 | , "files" | |
233 | , "quota" | |
234 | , "limit" | |
235 | , "#warns" | |
236 | ); | |
237 | } | |
238 | ||
239 | xprintf(fmt, arg1, arg2, arg3, arg4, arg5, arg6) | |
240 | char *fmt; | |
241 | { | |
242 | char buf[100]; | |
243 | static int column; | |
244 | ||
245 | if (fmt == 0 && column || column >= 40) { | |
246 | putchar('\n'); | |
247 | column = 0; | |
248 | } | |
249 | if (fmt == 0) | |
250 | return; | |
251 | sprintf(buf, fmt, arg1, arg2, arg3, arg4, arg5, arg6); | |
252 | if (column != 0 && strlen(buf) < 39) | |
253 | while (column++ < 40) | |
254 | putchar(' '); | |
255 | else if (column) { | |
256 | putchar('\n'); | |
257 | column = 0; | |
258 | } | |
259 | printf("%s", buf); | |
260 | column += strlen(buf); | |
261 | } | |
262 | ||
263 | alldigits(s) | |
264 | register char *s; | |
265 | { | |
266 | register c; | |
267 | ||
268 | c = *s++; | |
269 | do { | |
270 | if (!isdigit(c)) | |
271 | return (0); | |
272 | } while (c = *s++); | |
273 | return (1); | |
274 | } |