|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 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. ! 16: */ ! 17: ! 18: #ifndef lint ! 19: char copyright[] = ! 20: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ ! 21: All rights reserved.\n"; ! 22: #endif /* not lint */ ! 23: ! 24: #ifndef lint ! 25: static char sccsid[] = "@(#)edquota.c 5.6 (Berkeley) 6/18/88"; ! 26: #endif /* not lint */ ! 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> ! 39: #include <sys/stat.h> ! 40: #include <sys/file.h> ! 41: #include <sys/quota.h> ! 42: ! 43: #define DEFEDITOR "/usr/ucb/vi" ! 44: ! 45: struct dquot dq[NMOUNT]; ! 46: struct dquot odq[NMOUNT]; ! 47: char dqf[NMOUNT][MAXPATHLEN + 1]; ! 48: char odqf[NMOUNT][MAXPATHLEN + 1]; ! 49: ! 50: char tmpfil[] = "/tmp/EdP.aXXXXX"; ! 51: char *qfname = "quotas"; ! 52: char *getenv(); ! 53: ! 54: main(argc, argv) ! 55: char **argv; ! 56: { ! 57: int uid; ! 58: char *arg0; ! 59: ! 60: mktemp(tmpfil); ! 61: close(creat(tmpfil, 0600)); ! 62: chown(tmpfil, getuid(), getgid()); ! 63: arg0 = *argv++; ! 64: if (argc < 2) { ! 65: fprintf(stderr, "Usage: %s [-p username] username ...\n", arg0); ! 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: } ! 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: } ! 102: unlink(tmpfil); ! 103: exit(0); ! 104: } ! 105: ! 106: getentry(name) ! 107: char *name; ! 108: { ! 109: struct passwd *pw; ! 110: int uid; ! 111: ! 112: if (alldigits(name)) ! 113: uid = atoi(name); ! 114: else if (pw = getpwnam(name)) ! 115: uid = pw->pw_uid; ! 116: else { ! 117: fprintf(stderr, "%s: no such user\n", name); ! 118: sleep(1); ! 119: return (-1); ! 120: } ! 121: return (uid); ! 122: } ! 123: ! 124: editit() ! 125: { ! 126: register int pid, xpid; ! 127: long omask; ! 128: int stat; ! 129: ! 130: omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); ! 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: ! 149: sigsetmask(omask); ! 150: setgid(getgid()); ! 151: setuid(getuid()); ! 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; ! 161: sigsetmask(omask); ! 162: return (!stat); ! 163: } ! 164: ! 165: getprivs(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] ! 187: , dbtob(dq[i].dq_bsoftlimit) / 1024 ! 188: , dbtob(dq[i].dq_bhardlimit) / 1024 ! 189: , dq[i].dq_isoftlimit ! 190: , dq[i].dq_ihardlimit ! 191: ); ! 192: } ! 193: fclose(fd); ! 194: } ! 195: ! 196: putprivs(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: ); ! 234: if (n != 4) { ! 235: fprintf(stderr, "%s: bad format\n", cp); ! 236: continue; ! 237: } ! 238: dq[i].dq_bsoftlimit = btodb(dq[i].dq_bsoftlimit * 1024); ! 239: dq[i].dq_bhardlimit = btodb(dq[i].dq_bhardlimit * 1024); ! 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'; ! 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: ! 296: char * ! 297: next(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: ! 312: alldigits(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: ! 325: getdiscq(uid, dq, dqf) ! 326: register uid; ! 327: register struct dquot *dq; ! 328: register char (*dqf)[MAXPATHLEN + 1]; ! 329: { ! 330: register struct fstab *fs; ! 331: char qfilename[MAXPATHLEN + 1]; ! 332: struct stat statb; ! 333: struct dqblk dqblk; ! 334: dev_t fsdev; ! 335: int fd; ! 336: static int warned = 0; ! 337: extern int errno; ! 338: ! 339: setfsent(); ! 340: while (fs = getfsent()) { ! 341: if (stat(fs->fs_spec, &statb) < 0) ! 342: continue; ! 343: fsdev = statb.st_rdev; ! 344: sprintf(qfilename, "%s/%s", fs->fs_file, qfname); ! 345: if (stat(qfilename, &statb) < 0 || statb.st_dev != fsdev) ! 346: continue; ! 347: if (quota(Q_GETDLIM, uid, fsdev, &dqblk) != 0) { ! 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); ! 355: if (fd < 0) ! 356: continue; ! 357: lseek(fd, (long)(uid * sizeof dqblk), L_SET); ! 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); ! 373: close(fd); ! 374: continue; ! 375: } ! 376: close(fd); ! 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: ! 387: putdiscq(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); ! 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 { ! 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: } ! 418: } ! 419: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.