Commit | Line | Data |
---|---|---|
304d49a2 | 1 | #ifndef lint |
c085c6e0 | 2 | static char sccsid[] = "@(#)quota.c 4.4 (Berkeley, from Melbourne) %G%"; |
304d49a2 KM |
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> | |
304d49a2 KM |
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; | |
a233b96c | 22 | char *qfname = "quotas"; |
304d49a2 KM |
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; | |
a233b96c | 108 | char qfilename[MAXPATHLEN + 1], iwarn[8], dwarn[8]; |
304d49a2 KM |
109 | |
110 | if (stat(fs->fs_spec, &statb) < 0) | |
111 | continue; | |
112 | fsdev = statb.st_rdev; | |
a233b96c KM |
113 | (void) sprintf(qfilename, "%s/%s", fs->fs_file, qfname); |
114 | if (stat(qfilename, &statb) < 0 || statb.st_dev != fsdev) | |
304d49a2 KM |
115 | continue; |
116 | if (quota(Q_GETDLIM, uid, fsdev, &dqblk) != 0) { | |
96b539f0 | 117 | register fd = open(qfilename, O_RDONLY); |
304d49a2 KM |
118 | |
119 | if (fd < 0) | |
120 | continue; | |
96b539f0 | 121 | lseek(fd, (long)(uid * sizeof (dqblk)), L_SET); |
304d49a2 KM |
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); | |
c085c6e0 | 167 | printf("%10s%8d%c%7d%8d%8s%8d%c%7d%8d%8s\n" |
304d49a2 | 168 | , fs->fs_file |
96b539f0 | 169 | , (dqblk.dqb_curblocks / btodb(1024)) |
304d49a2 | 170 | , (msgb == (char *)0) ? ' ' : '*' |
96b539f0 KM |
171 | , (dqblk.dqb_bsoftlimit / btodb(1024)) |
172 | , (dqblk.dqb_bhardlimit / btodb(1024)) | |
304d49a2 KM |
173 | , dwarn |
174 | , dqblk.dqb_curinodes | |
175 | , (msgi == (char *)0) ? ' ' : '*' | |
176 | , dqblk.dqb_isoftlimit | |
96b539f0 | 177 | , dqblk.dqb_ihardlimit |
304d49a2 KM |
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); | |
c085c6e0 | 210 | printf("%10s%8s %7s%8s%8s%8s %7s%8s%8s\n" |
304d49a2 KM |
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 | } |