file reorg, pathnames.h, paths.h
[unix-history] / usr / src / usr.sbin / edquota / edquota.c
CommitLineData
2a18434a
KM
1/*
2 * Copyright (c) 1980 Regents of the University of California.
7a7c7584
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
b8c620d6
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
19char copyright[] =
20"@(#) Copyright (c) 1980 Regents of the University of California.\n\
21 All rights reserved.\n";
7a7c7584 22#endif /* not lint */
2a18434a 23
311ea057 24#ifndef lint
7abf8d65 25static char sccsid[] = "@(#)edquota.c 5.9 (Berkeley) %G%";
7a7c7584 26#endif /* not lint */
311ea057
KM
27
28/*
29 * Disk quota editor.
30 */
311ea057 31#include <sys/param.h>
311ea057
KM
32#include <sys/stat.h>
33#include <sys/file.h>
61184f42 34#include <sys/quota.h>
0086a7e5
KB
35#include <signal.h>
36#include <errno.h>
37#include <fstab.h>
38#include <pwd.h>
39#include <ctype.h>
40#include <stdio.h>
2e433f8d 41#include "pathnames.h"
311ea057
KM
42
43struct dquot dq[NMOUNT];
44struct dquot odq[NMOUNT];
45char dqf[NMOUNT][MAXPATHLEN + 1];
46char odqf[NMOUNT][MAXPATHLEN + 1];
47
7abf8d65 48char tmpfil[] = _PATH_TMP;
1cfb1c19 49char *qfname = "quotas";
311ea057
KM
50char *getenv();
51
52main(argc, argv)
53 char **argv;
54{
61184f42
KM
55 int uid;
56 char *arg0;
311ea057
KM
57
58 mktemp(tmpfil);
59 close(creat(tmpfil, 0600));
60 chown(tmpfil, getuid(), getgid());
61 arg0 = *argv++;
62 if (argc < 2) {
61184f42 63 fprintf(stderr, "Usage: %s [-p username] username ...\n", arg0);
311ea057
KM
64 unlink(tmpfil);
65 exit(1);
66 }
67 --argc;
68 if (getuid()) {
69 fprintf(stderr, "%s: permission denied\n", arg0);
70 unlink(tmpfil);
71 exit(1);
72 }
61184f42
KM
73 if (argc > 2 && strcmp(*argv, "-p") == 0) {
74 argc--, argv++;
75 uid = getentry(*argv++);
76 if (uid < 0) {
77 unlink(tmpfil);
78 exit(1);
79 }
80 getprivs(uid);
81 argc--;
82 while (argc-- > 0) {
83 uid = getentry(*argv++);
84 if (uid < 0)
85 continue;
86 getdiscq(uid, odq, odqf);
87 putprivs(uid);
88 }
89 unlink(tmpfil);
90 exit(0);
91 }
92 while (--argc >= 0) {
93 uid = getentry(*argv++);
94 if (uid < 0)
95 continue;
96 getprivs(uid);
97 if (editit())
98 putprivs(uid);
99 }
311ea057
KM
100 unlink(tmpfil);
101 exit(0);
102}
103
61184f42
KM
104getentry(name)
105 char *name;
311ea057 106{
61184f42
KM
107 struct passwd *pw;
108 int uid;
311ea057
KM
109
110 if (alldigits(name))
111 uid = atoi(name);
112 else if (pw = getpwnam(name))
113 uid = pw->pw_uid;
114 else {
61184f42 115 fprintf(stderr, "%s: no such user\n", name);
311ea057 116 sleep(1);
61184f42 117 return (-1);
311ea057 118 }
61184f42 119 return (uid);
311ea057
KM
120}
121
122editit()
123{
a08c12bc
KB
124 register int pid, xpid;
125 long omask;
126 int stat;
311ea057 127
a08c12bc 128 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
311ea057
KM
129 top:
130 if ((pid = fork()) < 0) {
131 extern errno;
132
133 if (errno == EPROCLIM) {
134 fprintf(stderr, "You have too many processes\n");
135 return(0);
136 }
137 if (errno == EAGAIN) {
138 sleep(1);
139 goto top;
140 }
141 perror("fork");
142 return (0);
143 }
144 if (pid == 0) {
145 register char *ed;
146
8daa86a6 147 sigsetmask(omask);
311ea057
KM
148 setgid(getgid());
149 setuid(getuid());
311ea057 150 if ((ed = getenv("EDITOR")) == (char *)0)
7abf8d65 151 ed = _PATH_VI;
311ea057
KM
152 execlp(ed, ed, tmpfil, 0);
153 perror(ed);
154 exit(1);
155 }
156 while ((xpid = wait(&stat)) >= 0)
157 if (xpid == pid)
158 break;
8daa86a6 159 sigsetmask(omask);
311ea057
KM
160 return (!stat);
161}
162
163getprivs(uid)
164 register uid;
165{
166 register i;
167 FILE *fd;
168
169 getdiscq(uid, dq, dqf);
170 for (i = 0; i < NMOUNT; i++) {
171 odq[i] = dq[i];
172 strcpy(odqf[i], dqf[i]);
173 }
174 if ((fd = fopen(tmpfil, "w")) == NULL) {
175 fprintf(stderr, "edquota: ");
176 perror(tmpfil);
177 exit(1);
178 }
179 for (i = 0; i < NMOUNT; i++) {
180 if (*dqf[i] == '\0')
181 continue;
182 fprintf(fd,
183"fs %s blocks (soft = %d, hard = %d) inodes (soft = %d, hard = %d)\n"
184 , dqf[i]
285a6d40
JB
185 , dbtob(dq[i].dq_bsoftlimit) / 1024
186 , dbtob(dq[i].dq_bhardlimit) / 1024
311ea057
KM
187 , dq[i].dq_isoftlimit
188 , dq[i].dq_ihardlimit
189 );
190 }
191 fclose(fd);
192}
193
194putprivs(uid)
195 register uid;
196{
197 register i, j;
198 int n;
199 FILE *fd;
200 char line[BUFSIZ];
201
202 fd = fopen(tmpfil, "r");
203 if (fd == NULL) {
204 fprintf(stderr, "Can't re-read temp file!!\n");
205 return;
206 }
207 for (i = 0; i < NMOUNT; i++) {
208 char *cp, *dp, *next();
209
210 if (fgets(line, sizeof (line), fd) == NULL)
211 break;
212 cp = next(line, " \t");
213 if (cp == NULL)
214 break;
215 *cp++ = '\0';
216 while (*cp && *cp == '\t' && *cp == ' ')
217 cp++;
218 dp = cp, cp = next(cp, " \t");
219 if (cp == NULL)
220 break;
221 *cp++ = '\0';
222 while (*cp && *cp == '\t' && *cp == ' ')
223 cp++;
224 strcpy(dqf[i], dp);
225 n = sscanf(cp,
226"blocks (soft = %d, hard = %d) inodes (soft = %hd, hard = %hd)\n"
227 , &dq[i].dq_bsoftlimit
228 , &dq[i].dq_bhardlimit
229 , &dq[i].dq_isoftlimit
230 , &dq[i].dq_ihardlimit
231 );
1cfb1c19
KM
232 if (n != 4) {
233 fprintf(stderr, "%s: bad format\n", cp);
234 continue;
235 }
285a6d40
JB
236 dq[i].dq_bsoftlimit = btodb(dq[i].dq_bsoftlimit * 1024);
237 dq[i].dq_bhardlimit = btodb(dq[i].dq_bhardlimit * 1024);
311ea057
KM
238 }
239 fclose(fd);
240 n = i;
241 for (i = 0; i < n; i++) {
242 if (*dqf[i] == '\0')
243 break;
244 for (j = 0; j < NMOUNT; j++) {
245 if (strcmp(dqf[i], odqf[j]) == 0)
246 break;
247 }
248 if (j >= NMOUNT)
249 continue;
250 *odqf[j] = '\0';
311ea057
KM
251 /*
252 * This isn't really good enough, it is quite likely
253 * to have changed while we have been away editing,
254 * but it's not important enough to worry about at
255 * the minute.
256 */
257 dq[i].dq_curblocks = odq[j].dq_curblocks;
258 dq[i].dq_curinodes = odq[j].dq_curinodes;
259 /*
260 * If we've upped the inode or disk block limits
261 * and the guy is out of warnings, reinitialize.
262 */
263 if (dq[i].dq_bsoftlimit > odq[j].dq_bsoftlimit &&
264 dq[i].dq_bwarn == 0)
265 dq[i].dq_bwarn = MAX_DQ_WARN;
266 if (dq[i].dq_isoftlimit > odq[j].dq_isoftlimit &&
267 dq[i].dq_iwarn == 0)
268 dq[i].dq_iwarn = MAX_IQ_WARN;
269 }
270 if (i < NMOUNT) {
271 for (j = 0; j < NMOUNT; j++) {
272 if (*odqf[j] == '\0')
273 continue;
274 strcpy(dqf[i], odqf[j]);
275 dq[i].dq_isoftlimit = 0;
276 dq[i].dq_ihardlimit = 0;
277 dq[i].dq_bsoftlimit = 0;
278 dq[i].dq_bhardlimit = 0;
279 /*
280 * Same applies as just above
281 * but matters not at all, as we are just
282 * turning quota'ing off for this filesys.
283 */
284 dq[i].dq_curblocks = odq[j].dq_curblocks;
285 dq[i].dq_curinodes = odq[j].dq_curinodes;
286 if (++i >= NMOUNT)
287 break;
288 }
289 }
290 if (*dqf[0])
291 putdiscq(uid, dq, dqf);
292}
293
294char *
295next(cp, match)
296 register char *cp;
297 char *match;
298{
299 register char *dp;
300
301 while (cp && *cp) {
302 for (dp = match; dp && *dp; dp++)
303 if (*dp == *cp)
304 return (cp);
305 cp++;
306 }
307 return ((char *)0);
308}
309
310alldigits(s)
311 register char *s;
312{
313 register c;
314
315 c = *s++;
316 do {
317 if (!isdigit(c))
318 return (0);
319 } while (c = *s++);
320 return (1);
321}
322
323getdiscq(uid, dq, dqf)
324 register uid;
325 register struct dquot *dq;
326 register char (*dqf)[MAXPATHLEN + 1];
327{
328 register struct fstab *fs;
1cfb1c19 329 char qfilename[MAXPATHLEN + 1];
1b102e0f
KM
330 struct stat statb;
331 struct dqblk dqblk;
332 dev_t fsdev;
333 int fd;
334 static int warned = 0;
335 extern int errno;
311ea057
KM
336
337 setfsent();
338 while (fs = getfsent()) {
311ea057
KM
339 if (stat(fs->fs_spec, &statb) < 0)
340 continue;
341 fsdev = statb.st_rdev;
1cfb1c19
KM
342 sprintf(qfilename, "%s/%s", fs->fs_file, qfname);
343 if (stat(qfilename, &statb) < 0 || statb.st_dev != fsdev)
311ea057
KM
344 continue;
345 if (quota(Q_GETDLIM, uid, fsdev, &dqblk) != 0) {
1b102e0f
KM
346 if (errno == EINVAL && !warned) {
347 warned++;
348 fprintf(stderr, "Warning: %s\n",
349 "Quotas are not compiled into this kernel");
350 sleep(3);
351 }
352 fd = open(qfilename, O_RDONLY);
311ea057
KM
353 if (fd < 0)
354 continue;
6f999543 355 lseek(fd, (long)(uid * sizeof dqblk), L_SET);
a1d76d07
S
356 switch (read(fd, &dqblk, sizeof dqblk)) {
357 case 0: /* EOF */
358 /*
359 * Convert implicit 0 quota (EOF)
360 * into an explicit one (zero'ed dqblk)
361 */
362 bzero((caddr_t)&dqblk, sizeof dqblk);
363 break;
364
365 case sizeof dqblk: /* OK */
366 break;
367
368 default: /* ERROR */
369 fprintf(stderr, "edquota: read error in ");
370 perror(qfilename);
311ea057
KM
371 close(fd);
372 continue;
373 }
374 close(fd);
311ea057
KM
375 }
376 dq->dq_dqb = dqblk;
377 dq->dq_dev = fsdev;
378 strcpy(*dqf, fs->fs_file);
379 dq++, dqf++;
380 }
381 endfsent();
382 **dqf = '\0';
383}
384
385putdiscq(uid, dq, dqf)
386 register uid;
387 register struct dquot *dq;
388 register char (*dqf)[MAXPATHLEN + 1];
389{
390 register fd, cnt;
391 struct stat sb;
392 struct fstab *fs;
393
394 cnt = 0;
395 for (cnt = 0; ++cnt <= NMOUNT && **dqf; dq++, dqf++) {
396 fs = getfsfile(*dqf);
1cfb1c19 397 if (fs == NULL) {
7abf8d65 398 fprintf(stderr, "%s: not in fstab\n", *dqf);
1cfb1c19
KM
399 continue;
400 }
401 strcat(*dqf, "/");
402 strcat(*dqf, qfname);
403 if (stat(*dqf, &sb) >= 0)
404 quota(Q_SETDLIM, uid, sb.st_dev, &dq->dq_dqb);
405 if ((fd = open(*dqf, 1)) < 0) {
406 perror(*dqf);
407 } else {
311ea057
KM
408 lseek(fd, (long)uid * (long)sizeof (struct dqblk), 0);
409 if (write(fd, &dq->dq_dqb, sizeof (struct dqblk)) !=
410 sizeof (struct dqblk)) {
411 fprintf(stderr, "edquota: ");
412 perror(*dqf);
413 }
414 close(fd);
415 }
311ea057
KM
416 }
417}