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: }

Defined functions

alldigits defined in line 301; used 1 times
editit defined in line 113; used 1 times
  • in line 88
getdiscq defined in line 314; used 2 times
getentry defined in line 95; used 3 times
getprivs defined in line 154; used 2 times
main defined in line 43; never used
next defined in line 285; used 3 times
putdiscq defined in line 376; used 1 times
putprivs defined in line 185; used 2 times

Defined variables

copyright defined in line 8; never used
dq defined in line 34; used 39 times
dqf defined in line 36; used 27 times
odq defined in line 35; used 8 times
odqf defined in line 37; used 6 times
qfname defined in line 40; used 2 times
sccsid defined in line 14; never used
tmpfil defined in line 39; used 12 times

Defined macros

DEFEDITOR defined in line 32; used 1 times
mask defined in line 118; used 3 times
  • in line 119(3)
Last modified: 1985-11-11
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1838
Valid CSS Valid XHTML 1.0 Strict