|
|
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.