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