added "more" command
[unix-history] / usr / src / usr.bin / quota / quota.c
CommitLineData
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
8char 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
14static 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
31int qflag;
32int vflag;
33int done;
34int morethanone;
a233b96c 35char *qfname = "quotas";
304d49a2
KM
36
37main(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
82showuid(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
93showname(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
105showquotas(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
208heading(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
239xprintf(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
263alldigits(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}