|
|
1.1 ! root 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 ! 8: char copyright[] = ! 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ ! 10: All rights reserved.\n"; ! 11: #endif not lint ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)edquota.c 5.3 (Berkeley) 11/4/85"; ! 15: #endif not lint ! 16: ! 17: /* ! 18: * Disk quota editor. ! 19: */ ! 20: #include <stdio.h> ! 21: #include <signal.h> ! 22: #include <errno.h> ! 23: #include <pwd.h> ! 24: #include <ctype.h> ! 25: #include <fstab.h> ! 26: ! 27: #include <sys/param.h> ! 28: #include <sys/stat.h> ! 29: #include <sys/file.h> ! 30: #include <sys/quota.h> ! 31: ! 32: #define DEFEDITOR "/usr/ucb/vi" ! 33: ! 34: struct dquot dq[NMOUNT]; ! 35: struct dquot odq[NMOUNT]; ! 36: char dqf[NMOUNT][MAXPATHLEN + 1]; ! 37: char odqf[NMOUNT][MAXPATHLEN + 1]; ! 38: ! 39: char tmpfil[] = "/tmp/EdP.aXXXXX"; ! 40: char *qfname = "quotas"; ! 41: char *getenv(); ! 42: ! 43: main(argc, argv) ! 44: char **argv; ! 45: { ! 46: int uid; ! 47: char *arg0; ! 48: ! 49: mktemp(tmpfil); ! 50: close(creat(tmpfil, 0600)); ! 51: chown(tmpfil, getuid(), getgid()); ! 52: arg0 = *argv++; ! 53: if (argc < 2) { ! 54: fprintf(stderr, "Usage: %s [-p username] username ...\n", arg0); ! 55: unlink(tmpfil); ! 56: exit(1); ! 57: } ! 58: --argc; ! 59: if (getuid()) { ! 60: fprintf(stderr, "%s: permission denied\n", arg0); ! 61: unlink(tmpfil); ! 62: exit(1); ! 63: } ! 64: if (argc > 2 && strcmp(*argv, "-p") == 0) { ! 65: argc--, argv++; ! 66: uid = getentry(*argv++); ! 67: if (uid < 0) { ! 68: unlink(tmpfil); ! 69: exit(1); ! 70: } ! 71: getprivs(uid); ! 72: argc--; ! 73: while (argc-- > 0) { ! 74: uid = getentry(*argv++); ! 75: if (uid < 0) ! 76: continue; ! 77: getdiscq(uid, odq, odqf); ! 78: putprivs(uid); ! 79: } ! 80: unlink(tmpfil); ! 81: exit(0); ! 82: } ! 83: while (--argc >= 0) { ! 84: uid = getentry(*argv++); ! 85: if (uid < 0) ! 86: continue; ! 87: getprivs(uid); ! 88: if (editit()) ! 89: putprivs(uid); ! 90: } ! 91: unlink(tmpfil); ! 92: exit(0); ! 93: } ! 94: ! 95: getentry(name) ! 96: char *name; ! 97: { ! 98: struct passwd *pw; ! 99: int uid; ! 100: ! 101: if (alldigits(name)) ! 102: uid = atoi(name); ! 103: else if (pw = getpwnam(name)) ! 104: uid = pw->pw_uid; ! 105: else { ! 106: fprintf(stderr, "%s: no such user\n", name); ! 107: sleep(1); ! 108: return (-1); ! 109: } ! 110: return (uid); ! 111: } ! 112: ! 113: editit() ! 114: { ! 115: register pid, xpid; ! 116: int stat, omask; ! 117: ! 118: #define mask(s) (1<<((s)-1)) ! 119: omask = sigblock(mask(SIGINT)|mask(SIGQUIT)|mask(SIGHUP)); ! 120: top: ! 121: if ((pid = fork()) < 0) { ! 122: extern errno; ! 123: ! 124: if (errno == EPROCLIM) { ! 125: fprintf(stderr, "You have too many processes\n"); ! 126: return(0); ! 127: } ! 128: if (errno == EAGAIN) { ! 129: sleep(1); ! 130: goto top; ! 131: } ! 132: perror("fork"); ! 133: return (0); ! 134: } ! 135: if (pid == 0) { ! 136: register char *ed; ! 137: ! 138: sigsetmask(omask); ! 139: setgid(getgid()); ! 140: setuid(getuid()); ! 141: if ((ed = getenv("EDITOR")) == (char *)0) ! 142: ed = DEFEDITOR; ! 143: execlp(ed, ed, tmpfil, 0); ! 144: perror(ed); ! 145: exit(1); ! 146: } ! 147: while ((xpid = wait(&stat)) >= 0) ! 148: if (xpid == pid) ! 149: break; ! 150: sigsetmask(omask); ! 151: return (!stat); ! 152: } ! 153: ! 154: getprivs(uid) ! 155: register uid; ! 156: { ! 157: register i; ! 158: FILE *fd; ! 159: ! 160: getdiscq(uid, dq, dqf); ! 161: for (i = 0; i < NMOUNT; i++) { ! 162: odq[i] = dq[i]; ! 163: strcpy(odqf[i], dqf[i]); ! 164: } ! 165: if ((fd = fopen(tmpfil, "w")) == NULL) { ! 166: fprintf(stderr, "edquota: "); ! 167: perror(tmpfil); ! 168: exit(1); ! 169: } ! 170: for (i = 0; i < NMOUNT; i++) { ! 171: if (*dqf[i] == '\0') ! 172: continue; ! 173: fprintf(fd, ! 174: "fs %s blocks (soft = %d, hard = %d) inodes (soft = %d, hard = %d)\n" ! 175: , dqf[i] ! 176: , dbtob(dq[i].dq_bsoftlimit) / 1024 ! 177: , dbtob(dq[i].dq_bhardlimit) / 1024 ! 178: , dq[i].dq_isoftlimit ! 179: , dq[i].dq_ihardlimit ! 180: ); ! 181: } ! 182: fclose(fd); ! 183: } ! 184: ! 185: putprivs(uid) ! 186: register uid; ! 187: { ! 188: register i, j; ! 189: int n; ! 190: FILE *fd; ! 191: char line[BUFSIZ]; ! 192: ! 193: fd = fopen(tmpfil, "r"); ! 194: if (fd == NULL) { ! 195: fprintf(stderr, "Can't re-read temp file!!\n"); ! 196: return; ! 197: } ! 198: for (i = 0; i < NMOUNT; i++) { ! 199: char *cp, *dp, *next(); ! 200: ! 201: if (fgets(line, sizeof (line), fd) == NULL) ! 202: break; ! 203: cp = next(line, " \t"); ! 204: if (cp == NULL) ! 205: break; ! 206: *cp++ = '\0'; ! 207: while (*cp && *cp == '\t' && *cp == ' ') ! 208: cp++; ! 209: dp = cp, cp = next(cp, " \t"); ! 210: if (cp == NULL) ! 211: break; ! 212: *cp++ = '\0'; ! 213: while (*cp && *cp == '\t' && *cp == ' ') ! 214: cp++; ! 215: strcpy(dqf[i], dp); ! 216: n = sscanf(cp, ! 217: "blocks (soft = %d, hard = %d) inodes (soft = %hd, hard = %hd)\n" ! 218: , &dq[i].dq_bsoftlimit ! 219: , &dq[i].dq_bhardlimit ! 220: , &dq[i].dq_isoftlimit ! 221: , &dq[i].dq_ihardlimit ! 222: ); ! 223: if (n != 4) { ! 224: fprintf(stderr, "%s: bad format\n", cp); ! 225: continue; ! 226: } ! 227: dq[i].dq_bsoftlimit = btodb(dq[i].dq_bsoftlimit * 1024); ! 228: dq[i].dq_bhardlimit = btodb(dq[i].dq_bhardlimit * 1024); ! 229: } ! 230: fclose(fd); ! 231: n = i; ! 232: for (i = 0; i < n; i++) { ! 233: if (*dqf[i] == '\0') ! 234: break; ! 235: for (j = 0; j < NMOUNT; j++) { ! 236: if (strcmp(dqf[i], odqf[j]) == 0) ! 237: break; ! 238: } ! 239: if (j >= NMOUNT) ! 240: continue; ! 241: *odqf[j] = '\0'; ! 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: struct stat statb; ! 322: struct dqblk dqblk; ! 323: dev_t fsdev; ! 324: int fd; ! 325: static int warned = 0; ! 326: extern int errno; ! 327: ! 328: setfsent(); ! 329: while (fs = getfsent()) { ! 330: if (stat(fs->fs_spec, &statb) < 0) ! 331: continue; ! 332: fsdev = statb.st_rdev; ! 333: sprintf(qfilename, "%s/%s", fs->fs_file, qfname); ! 334: if (stat(qfilename, &statb) < 0 || statb.st_dev != fsdev) ! 335: continue; ! 336: if (quota(Q_GETDLIM, uid, fsdev, &dqblk) != 0) { ! 337: if (errno == EINVAL && !warned) { ! 338: warned++; ! 339: fprintf(stderr, "Warning: %s\n", ! 340: "Quotas are not compiled into this kernel"); ! 341: sleep(3); ! 342: } ! 343: fd = open(qfilename, O_RDONLY); ! 344: if (fd < 0) ! 345: continue; ! 346: lseek(fd, (long)(uid * sizeof dqblk), L_SET); ! 347: switch (read(fd, &dqblk, sizeof dqblk)) { ! 348: case 0: /* EOF */ ! 349: /* ! 350: * Convert implicit 0 quota (EOF) ! 351: * into an explicit one (zero'ed dqblk) ! 352: */ ! 353: bzero((caddr_t)&dqblk, sizeof dqblk); ! 354: break; ! 355: ! 356: case sizeof dqblk: /* OK */ ! 357: break; ! 358: ! 359: default: /* ERROR */ ! 360: fprintf(stderr, "edquota: read error in "); ! 361: perror(qfilename); ! 362: close(fd); ! 363: continue; ! 364: } ! 365: close(fd); ! 366: } ! 367: dq->dq_dqb = dqblk; ! 368: dq->dq_dev = fsdev; ! 369: strcpy(*dqf, fs->fs_file); ! 370: dq++, dqf++; ! 371: } ! 372: endfsent(); ! 373: **dqf = '\0'; ! 374: } ! 375: ! 376: putdiscq(uid, dq, dqf) ! 377: register uid; ! 378: register struct dquot *dq; ! 379: register char (*dqf)[MAXPATHLEN + 1]; ! 380: { ! 381: register fd, cnt; ! 382: struct stat sb; ! 383: struct fstab *fs; ! 384: ! 385: cnt = 0; ! 386: for (cnt = 0; ++cnt <= NMOUNT && **dqf; dq++, dqf++) { ! 387: fs = getfsfile(*dqf); ! 388: if (fs == NULL) { ! 389: fprintf(stderr, "%s: not in /etc/fstab\n", *dqf); ! 390: continue; ! 391: } ! 392: strcat(*dqf, "/"); ! 393: strcat(*dqf, qfname); ! 394: if (stat(*dqf, &sb) >= 0) ! 395: quota(Q_SETDLIM, uid, sb.st_dev, &dq->dq_dqb); ! 396: if ((fd = open(*dqf, 1)) < 0) { ! 397: perror(*dqf); ! 398: } else { ! 399: lseek(fd, (long)uid * (long)sizeof (struct dqblk), 0); ! 400: if (write(fd, &dq->dq_dqb, sizeof (struct dqblk)) != ! 401: sizeof (struct dqblk)) { ! 402: fprintf(stderr, "edquota: "); ! 403: perror(*dqf); ! 404: } ! 405: close(fd); ! 406: } ! 407: } ! 408: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.