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