|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980, 1990 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Robert Elz at The University of Melbourne. ! 7: * ! 8: * Redistribution and use in source and binary forms are permitted provided ! 9: * that: (1) source distributions retain this entire copyright notice and ! 10: * comment, and (2) distributions including binaries display the following ! 11: * acknowledgement: ``This product includes software developed by the ! 12: * University of California, Berkeley and its contributors'' in the ! 13: * documentation or other materials provided with the distribution and in ! 14: * all advertising materials mentioning features or use of this software. ! 15: * Neither the name of the University nor the names of its contributors may ! 16: * be used to endorse or promote products derived from this software without ! 17: * specific prior written permission. ! 18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 19: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 20: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 21: */ ! 22: ! 23: #ifndef lint ! 24: char copyright[] = ! 25: "@(#) Copyright (c) 1980, 1990 Regents of the University of California.\n\ ! 26: All rights reserved.\n"; ! 27: #endif /* not lint */ ! 28: ! 29: #ifndef lint ! 30: static char sccsid[] = "@(#)edquota.c 5.14 (Berkeley) 6/19/90"; ! 31: #endif /* not lint */ ! 32: ! 33: /* ! 34: * Disk quota editor. ! 35: */ ! 36: #include <sys/param.h> ! 37: #include <sys/stat.h> ! 38: #include <sys/file.h> ! 39: #include <sys/wait.h> ! 40: #include <ufs/quota.h> ! 41: #include <errno.h> ! 42: #include <fstab.h> ! 43: #include <pwd.h> ! 44: #include <grp.h> ! 45: #include <ctype.h> ! 46: #include <stdio.h> ! 47: #include <string.h> ! 48: #include "pathnames.h" ! 49: ! 50: char tmpfil[] = _PATH_TMP; ! 51: ! 52: struct quotause { ! 53: struct quotause *next; ! 54: long flags; ! 55: struct dqblk dqblk; ! 56: char fsname[MAXPATHLEN + 1]; ! 57: char qfname[1]; /* actually longer */ ! 58: } *getprivs(); ! 59: #define FOUND 0x01 ! 60: ! 61: main(argc, argv) ! 62: register char **argv; ! 63: int argc; ! 64: { ! 65: register struct quotause *qup, *protoprivs, *curprivs; ! 66: extern char *optarg; ! 67: extern int optind; ! 68: register long id, protoid; ! 69: register int quotatype, tmpfd; ! 70: char *protoname, ch; ! 71: int tflag = 0, pflag = 0; ! 72: ! 73: if (argc < 2) ! 74: usage(); ! 75: if (getuid()) { ! 76: fprintf(stderr, "edquota: permission denied\n"); ! 77: exit(1); ! 78: } ! 79: quotatype = USRQUOTA; ! 80: while ((ch = getopt(argc, argv, "ugtp:")) != EOF) { ! 81: switch(ch) { ! 82: case 'p': ! 83: protoname = optarg; ! 84: pflag++; ! 85: break; ! 86: case 'g': ! 87: quotatype = GRPQUOTA; ! 88: break; ! 89: case 'u': ! 90: quotatype = USRQUOTA; ! 91: break; ! 92: case 't': ! 93: tflag++; ! 94: break; ! 95: default: ! 96: usage(); ! 97: } ! 98: } ! 99: argc -= optind; ! 100: argv += optind; ! 101: if (pflag) { ! 102: if ((protoid = getentry(protoname, quotatype)) == -1) ! 103: exit(1); ! 104: protoprivs = getprivs(protoid, quotatype); ! 105: for (qup = protoprivs; qup; qup = qup->next) { ! 106: qup->dqblk.dqb_btime = 0; ! 107: qup->dqblk.dqb_itime = 0; ! 108: } ! 109: while (argc-- > 0) { ! 110: if ((id = getentry(*argv++, quotatype)) < 0) ! 111: continue; ! 112: putprivs(id, quotatype, protoprivs); ! 113: } ! 114: exit(0); ! 115: } ! 116: tmpfd = mkstemp(tmpfil); ! 117: fchown(tmpfd, getuid(), getgid()); ! 118: if (tflag) { ! 119: protoprivs = getprivs(0, quotatype); ! 120: if (writetimes(protoprivs, tmpfd, quotatype) == 0) ! 121: exit(1); ! 122: if (editit(tmpfil) && readtimes(protoprivs, tmpfd)) ! 123: putprivs(0, quotatype, protoprivs); ! 124: freeprivs(protoprivs); ! 125: exit(0); ! 126: } ! 127: for ( ; argc > 0; argc--, argv++) { ! 128: if ((id = getentry(*argv, quotatype)) == -1) ! 129: continue; ! 130: curprivs = getprivs(id, quotatype); ! 131: if (writeprivs(curprivs, tmpfd, *argv, quotatype) == 0) ! 132: continue; ! 133: if (editit(tmpfil) && readprivs(curprivs, tmpfd)) ! 134: putprivs(id, quotatype, curprivs); ! 135: freeprivs(curprivs); ! 136: } ! 137: close(tmpfd); ! 138: unlink(tmpfil); ! 139: exit(0); ! 140: } ! 141: ! 142: usage() ! 143: { ! 144: fprintf(stderr, "%s%s%s%s", ! 145: "Usage: edquota [-u] [-p username] username ...\n", ! 146: "\tedquota -g [-p groupname] groupname ...\n", ! 147: "\tedquota [-u] -t\n", "\tedquota -g -t\n"); ! 148: exit(1); ! 149: } ! 150: ! 151: /* ! 152: * This routine converts a name for a particular quota type to ! 153: * an identifier. This routine must agree with the kernel routine ! 154: * getinoquota as to the interpretation of quota types. ! 155: */ ! 156: getentry(name, quotatype) ! 157: char *name; ! 158: int quotatype; ! 159: { ! 160: struct passwd *pw; ! 161: struct group *gr; ! 162: ! 163: if (alldigits(name)) ! 164: return (atoi(name)); ! 165: switch(quotatype) { ! 166: case USRQUOTA: ! 167: if (pw = getpwnam(name)) ! 168: return (pw->pw_uid); ! 169: fprintf(stderr, "%s: no such user\n", name); ! 170: break; ! 171: case GRPQUOTA: ! 172: if (gr = getgrnam(name)) ! 173: return (gr->gr_gid); ! 174: fprintf(stderr, "%s: no such group\n", name); ! 175: break; ! 176: default: ! 177: fprintf(stderr, "%d: unknown quota type\n", quotatype); ! 178: break; ! 179: } ! 180: sleep(1); ! 181: return (-1); ! 182: } ! 183: ! 184: /* ! 185: * Collect the requested quota information. ! 186: */ ! 187: struct quotause * ! 188: getprivs(id, quotatype) ! 189: register long id; ! 190: int quotatype; ! 191: { ! 192: register struct fstab *fs; ! 193: register struct quotause *qup, *quptail; ! 194: struct quotause *quphead; ! 195: int qcmd, qupsize, fd; ! 196: char *qfpathname; ! 197: static int warned = 0; ! 198: extern int errno; ! 199: ! 200: setfsent(); ! 201: quphead = (struct quotause *)0; ! 202: qcmd = QCMD(Q_GETQUOTA, quotatype); ! 203: while (fs = getfsent()) { ! 204: if (strcmp(fs->fs_vfstype, "ufs")) ! 205: continue; ! 206: if (!hasquota(fs, quotatype, &qfpathname)) ! 207: continue; ! 208: qupsize = sizeof(*qup) + strlen(qfpathname); ! 209: if ((qup = (struct quotause *)malloc(qupsize)) == NULL) { ! 210: fprintf(stderr, "edquota: out of memory\n"); ! 211: exit(2); ! 212: } ! 213: if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) { ! 214: if (errno == EOPNOTSUPP && !warned) { ! 215: warned++; ! 216: fprintf(stderr, "Warning: %s\n", ! 217: "Quotas are not compiled into this kernel"); ! 218: sleep(3); ! 219: } ! 220: if ((fd = open(qfpathname, O_RDONLY)) < 0) { ! 221: fd = open(qfpathname, O_RDWR|O_CREAT, 0640); ! 222: if (fd < 0 && errno != ENOENT) { ! 223: perror(qfpathname); ! 224: free(qup); ! 225: continue; ! 226: } ! 227: fprintf(stderr, "Creating quota file %s\n", ! 228: qfpathname); ! 229: sleep(3); ! 230: (void) fchown(fd, getuid(), ! 231: getentry(quotagroup, GRPQUOTA)); ! 232: (void) fchmod(fd, 0640); ! 233: } ! 234: lseek(fd, (long)(id * sizeof(struct dqblk)), L_SET); ! 235: switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) { ! 236: case 0: /* EOF */ ! 237: /* ! 238: * Convert implicit 0 quota (EOF) ! 239: * into an explicit one (zero'ed dqblk) ! 240: */ ! 241: bzero((caddr_t)&qup->dqblk, ! 242: sizeof(struct dqblk)); ! 243: break; ! 244: ! 245: case sizeof(struct dqblk): /* OK */ ! 246: break; ! 247: ! 248: default: /* ERROR */ ! 249: fprintf(stderr, "edquota: read error in "); ! 250: perror(qfpathname); ! 251: close(fd); ! 252: free(qup); ! 253: continue; ! 254: } ! 255: close(fd); ! 256: } ! 257: strcpy(qup->qfname, qfpathname); ! 258: strcpy(qup->fsname, fs->fs_file); ! 259: if (quphead == NULL) ! 260: quphead = qup; ! 261: else ! 262: quptail->next = qup; ! 263: quptail = qup; ! 264: qup->next = 0; ! 265: } ! 266: endfsent(); ! 267: return (quphead); ! 268: } ! 269: ! 270: /* ! 271: * Store the requested quota information. ! 272: */ ! 273: putprivs(id, quotatype, quplist) ! 274: long id; ! 275: int quotatype; ! 276: struct quotause *quplist; ! 277: { ! 278: register struct quotause *qup; ! 279: int qcmd, fd; ! 280: ! 281: qcmd = QCMD(Q_SETQUOTA, quotatype); ! 282: for (qup = quplist; qup; qup = qup->next) { ! 283: if (quotactl(qup->fsname, qcmd, id, &qup->dqblk) == 0) ! 284: continue; ! 285: if ((fd = open(qup->qfname, O_WRONLY)) < 0) { ! 286: perror(qup->qfname); ! 287: } else { ! 288: lseek(fd, (long)id * (long)sizeof (struct dqblk), 0); ! 289: if (write(fd, &qup->dqblk, sizeof (struct dqblk)) != ! 290: sizeof (struct dqblk)) { ! 291: fprintf(stderr, "edquota: "); ! 292: perror(qup->qfname); ! 293: } ! 294: close(fd); ! 295: } ! 296: } ! 297: } ! 298: ! 299: /* ! 300: * Take a list of priviledges and get it edited. ! 301: */ ! 302: editit(tmpfile) ! 303: char *tmpfile; ! 304: { ! 305: long omask; ! 306: int pid, stat; ! 307: extern char *getenv(); ! 308: ! 309: omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); ! 310: top: ! 311: if ((pid = fork()) < 0) { ! 312: extern errno; ! 313: ! 314: if (errno == EPROCLIM) { ! 315: fprintf(stderr, "You have too many processes\n"); ! 316: return(0); ! 317: } ! 318: if (errno == EAGAIN) { ! 319: sleep(1); ! 320: goto top; ! 321: } ! 322: perror("fork"); ! 323: return (0); ! 324: } ! 325: if (pid == 0) { ! 326: register char *ed; ! 327: ! 328: sigsetmask(omask); ! 329: setgid(getgid()); ! 330: setuid(getuid()); ! 331: if ((ed = getenv("EDITOR")) == (char *)0) ! 332: ed = _PATH_VI; ! 333: execlp(ed, ed, tmpfile, 0); ! 334: perror(ed); ! 335: exit(1); ! 336: } ! 337: waitpid(pid, &stat, 0); ! 338: sigsetmask(omask); ! 339: if (!WIFEXITED(stat) || WEXITSTATUS(stat) != 0) ! 340: return (0); ! 341: return (1); ! 342: } ! 343: ! 344: /* ! 345: * Convert a quotause list to an ASCII file. ! 346: */ ! 347: writeprivs(quplist, outfd, name, quotatype) ! 348: struct quotause *quplist; ! 349: int outfd; ! 350: char *name; ! 351: int quotatype; ! 352: { ! 353: register struct quotause *qup; ! 354: FILE *fd; ! 355: ! 356: ftruncate(outfd, 0); ! 357: lseek(outfd, 0, L_SET); ! 358: if ((fd = fdopen(dup(outfd), "w")) == NULL) { ! 359: fprintf(stderr, "edquota: "); ! 360: perror(tmpfil); ! 361: exit(1); ! 362: } ! 363: fprintf(fd, "Quotas for %s %s:\n", qfextension[quotatype], name); ! 364: for (qup = quplist; qup; qup = qup->next) { ! 365: fprintf(fd, "%s: %s %d, limits (soft = %d, hard = %d)\n", ! 366: qup->fsname, "blocks in use:", ! 367: dbtob(qup->dqblk.dqb_curblocks) / 1024, ! 368: dbtob(qup->dqblk.dqb_bsoftlimit) / 1024, ! 369: dbtob(qup->dqblk.dqb_bhardlimit) / 1024); ! 370: fprintf(fd, "%s %d, limits (soft = %d, hard = %d)\n", ! 371: "\tinodes in use:", qup->dqblk.dqb_curinodes, ! 372: qup->dqblk.dqb_isoftlimit, qup->dqblk.dqb_ihardlimit); ! 373: } ! 374: fclose(fd); ! 375: return (1); ! 376: } ! 377: ! 378: /* ! 379: * Merge changes to an ASCII file into a quotause list. ! 380: */ ! 381: readprivs(quplist, infd) ! 382: struct quotause *quplist; ! 383: int infd; ! 384: { ! 385: register struct quotause *qup; ! 386: FILE *fd; ! 387: int cnt; ! 388: register char *cp; ! 389: struct dqblk dqblk; ! 390: char *fsp, line1[BUFSIZ], line2[BUFSIZ]; ! 391: ! 392: lseek(infd, 0, L_SET); ! 393: fd = fdopen(dup(infd), "r"); ! 394: if (fd == NULL) { ! 395: fprintf(stderr, "Can't re-read temp file!!\n"); ! 396: return (0); ! 397: } ! 398: /* ! 399: * Discard title line, then read pairs of lines to process. ! 400: */ ! 401: (void) fgets(line1, sizeof (line1), fd); ! 402: while (fgets(line1, sizeof (line1), fd) != NULL && ! 403: fgets(line2, sizeof (line2), fd) != NULL) { ! 404: if ((fsp = strtok(line1, " \t:")) == NULL) { ! 405: fprintf(stderr, "%s: bad format\n", line1); ! 406: return (0); ! 407: } ! 408: if ((cp = strtok((char *)0, "\n")) == NULL) { ! 409: fprintf(stderr, "%s: %s: bad format\n", fsp, ! 410: &fsp[strlen(fsp) + 1]); ! 411: return (0); ! 412: } ! 413: cnt = sscanf(cp, ! 414: " blocks in use: %d, limits (soft = %d, hard = %d)", ! 415: &dqblk.dqb_curblocks, &dqblk.dqb_bsoftlimit, ! 416: &dqblk.dqb_bhardlimit); ! 417: if (cnt != 3) { ! 418: fprintf(stderr, "%s:%s: bad format\n", fsp, cp); ! 419: return (0); ! 420: } ! 421: dqblk.dqb_curblocks = btodb(dqblk.dqb_curblocks * 1024); ! 422: dqblk.dqb_bsoftlimit = btodb(dqblk.dqb_bsoftlimit * 1024); ! 423: dqblk.dqb_bhardlimit = btodb(dqblk.dqb_bhardlimit * 1024); ! 424: if ((cp = strtok(line2, "\n")) == NULL) { ! 425: fprintf(stderr, "%s: %s: bad format\n", fsp, line2); ! 426: return (0); ! 427: } ! 428: cnt = sscanf(cp, ! 429: "\tinodes in use: %d, limits (soft = %d, hard = %d)", ! 430: &dqblk.dqb_curinodes, &dqblk.dqb_isoftlimit, ! 431: &dqblk.dqb_ihardlimit); ! 432: if (cnt != 3) { ! 433: fprintf(stderr, "%s: %s: bad format\n", fsp, line2); ! 434: return (0); ! 435: } ! 436: for (qup = quplist; qup; qup = qup->next) { ! 437: if (strcmp(fsp, qup->fsname)) ! 438: continue; ! 439: /* ! 440: * Cause time limit to be reset when the quota ! 441: * is next used if previously had no soft limit ! 442: * or were under it, but now have a soft limit ! 443: * and are over it. ! 444: */ ! 445: if (dqblk.dqb_bsoftlimit && ! 446: qup->dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit && ! 447: (qup->dqblk.dqb_bsoftlimit == 0 || ! 448: qup->dqblk.dqb_curblocks < ! 449: qup->dqblk.dqb_bsoftlimit)) ! 450: qup->dqblk.dqb_btime = 0; ! 451: if (dqblk.dqb_isoftlimit && ! 452: qup->dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit && ! 453: (qup->dqblk.dqb_isoftlimit == 0 || ! 454: qup->dqblk.dqb_curinodes < ! 455: qup->dqblk.dqb_isoftlimit)) ! 456: qup->dqblk.dqb_itime = 0; ! 457: qup->dqblk.dqb_bsoftlimit = dqblk.dqb_bsoftlimit; ! 458: qup->dqblk.dqb_bhardlimit = dqblk.dqb_bhardlimit; ! 459: qup->dqblk.dqb_isoftlimit = dqblk.dqb_isoftlimit; ! 460: qup->dqblk.dqb_ihardlimit = dqblk.dqb_ihardlimit; ! 461: qup->flags |= FOUND; ! 462: if (dqblk.dqb_curblocks == qup->dqblk.dqb_curblocks && ! 463: dqblk.dqb_curinodes == qup->dqblk.dqb_curinodes) ! 464: break; ! 465: fprintf(stderr, ! 466: "%s: cannot change current allocation\n", fsp); ! 467: break; ! 468: } ! 469: } ! 470: fclose(fd); ! 471: /* ! 472: * Disable quotas for any filesystems that have not been found. ! 473: */ ! 474: for (qup = quplist; qup; qup = qup->next) { ! 475: if (qup->flags & FOUND) { ! 476: qup->flags &= ~FOUND; ! 477: continue; ! 478: } ! 479: qup->dqblk.dqb_bsoftlimit = 0; ! 480: qup->dqblk.dqb_bhardlimit = 0; ! 481: qup->dqblk.dqb_isoftlimit = 0; ! 482: qup->dqblk.dqb_ihardlimit = 0; ! 483: } ! 484: return (1); ! 485: } ! 486: ! 487: /* ! 488: * Convert a quotause list to an ASCII file of grace times. ! 489: */ ! 490: writetimes(quplist, outfd, quotatype) ! 491: struct quotause *quplist; ! 492: int outfd; ! 493: int quotatype; ! 494: { ! 495: register struct quotause *qup; ! 496: char *cvtstoa(); ! 497: FILE *fd; ! 498: ! 499: ftruncate(outfd, 0); ! 500: lseek(outfd, 0, L_SET); ! 501: if ((fd = fdopen(dup(outfd), "w")) == NULL) { ! 502: fprintf(stderr, "edquota: "); ! 503: perror(tmpfil); ! 504: exit(1); ! 505: } ! 506: fprintf(fd, "Time units may be: days, hours, minutes, or seconds\n"); ! 507: fprintf(fd, "Grace period before enforcing soft limits for %ss:\n", ! 508: qfextension[quotatype]); ! 509: for (qup = quplist; qup; qup = qup->next) { ! 510: fprintf(fd, "%s: block grace period: %s, ", ! 511: qup->fsname, cvtstoa(qup->dqblk.dqb_btime)); ! 512: fprintf(fd, "file grace period: %s\n", ! 513: cvtstoa(qup->dqblk.dqb_itime)); ! 514: } ! 515: fclose(fd); ! 516: return (1); ! 517: } ! 518: ! 519: /* ! 520: * Merge changes of grace times in an ASCII file into a quotause list. ! 521: */ ! 522: readtimes(quplist, infd) ! 523: struct quotause *quplist; ! 524: int infd; ! 525: { ! 526: register struct quotause *qup; ! 527: FILE *fd; ! 528: int cnt; ! 529: register char *cp; ! 530: time_t itime, btime, iseconds, bseconds; ! 531: char *fsp, bunits[10], iunits[10], line1[BUFSIZ]; ! 532: ! 533: lseek(infd, 0, L_SET); ! 534: fd = fdopen(dup(infd), "r"); ! 535: if (fd == NULL) { ! 536: fprintf(stderr, "Can't re-read temp file!!\n"); ! 537: return (0); ! 538: } ! 539: /* ! 540: * Discard two title lines, then read lines to process. ! 541: */ ! 542: (void) fgets(line1, sizeof (line1), fd); ! 543: (void) fgets(line1, sizeof (line1), fd); ! 544: while (fgets(line1, sizeof (line1), fd) != NULL) { ! 545: if ((fsp = strtok(line1, " \t:")) == NULL) { ! 546: fprintf(stderr, "%s: bad format\n", line1); ! 547: return (0); ! 548: } ! 549: if ((cp = strtok((char *)0, "\n")) == NULL) { ! 550: fprintf(stderr, "%s: %s: bad format\n", fsp, ! 551: &fsp[strlen(fsp) + 1]); ! 552: return (0); ! 553: } ! 554: cnt = sscanf(cp, ! 555: " block grace period: %d %s file grace period: %d %s", ! 556: &btime, bunits, &itime, iunits); ! 557: if (cnt != 4) { ! 558: fprintf(stderr, "%s:%s: bad format\n", fsp, cp); ! 559: return (0); ! 560: } ! 561: if (cvtatos(btime, bunits, &bseconds) == 0) ! 562: return (0); ! 563: if (cvtatos(itime, iunits, &iseconds) == 0) ! 564: return (0); ! 565: for (qup = quplist; qup; qup = qup->next) { ! 566: if (strcmp(fsp, qup->fsname)) ! 567: continue; ! 568: qup->dqblk.dqb_btime = bseconds; ! 569: qup->dqblk.dqb_itime = iseconds; ! 570: qup->flags |= FOUND; ! 571: break; ! 572: } ! 573: } ! 574: fclose(fd); ! 575: /* ! 576: * reset default grace periods for any filesystems ! 577: * that have not been found. ! 578: */ ! 579: for (qup = quplist; qup; qup = qup->next) { ! 580: if (qup->flags & FOUND) { ! 581: qup->flags &= ~FOUND; ! 582: continue; ! 583: } ! 584: qup->dqblk.dqb_btime = 0; ! 585: qup->dqblk.dqb_itime = 0; ! 586: } ! 587: return (1); ! 588: } ! 589: ! 590: /* ! 591: * Convert seconds to ASCII times. ! 592: */ ! 593: char * ! 594: cvtstoa(time) ! 595: time_t time; ! 596: { ! 597: static char buf[20]; ! 598: ! 599: if (time % (24 * 60 * 60) == 0) { ! 600: time /= 24 * 60 * 60; ! 601: sprintf(buf, "%d day%s", time, time == 1 ? "" : "s"); ! 602: } else if (time % (60 * 60) == 0) { ! 603: time /= 60 * 60; ! 604: sprintf(buf, "%d hour%s", time, time == 1 ? "" : "s"); ! 605: } else if (time % 60 == 0) { ! 606: time /= 60; ! 607: sprintf(buf, "%d minute%s", time, time == 1 ? "" : "s"); ! 608: } else ! 609: sprintf(buf, "%d second%s", time, time == 1 ? "" : "s"); ! 610: return (buf); ! 611: } ! 612: ! 613: /* ! 614: * Convert ASCII input times to seconds. ! 615: */ ! 616: cvtatos(time, units, seconds) ! 617: time_t time; ! 618: char *units; ! 619: time_t *seconds; ! 620: { ! 621: ! 622: if (bcmp(units, "second", 6) == 0) ! 623: *seconds = time; ! 624: else if (bcmp(units, "minute", 6) == 0) ! 625: *seconds = time * 60; ! 626: else if (bcmp(units, "hour", 4) == 0) ! 627: *seconds = time * 60 * 60; ! 628: else if (bcmp(units, "day", 3) == 0) ! 629: *seconds = time * 24 * 60 * 60; ! 630: else { ! 631: printf("%s: bad units, specify %s\n", units, ! 632: "days, hours, minutes, or seconds"); ! 633: return (0); ! 634: } ! 635: return (1); ! 636: } ! 637: ! 638: /* ! 639: * Free a list of quotause structures. ! 640: */ ! 641: freeprivs(quplist) ! 642: struct quotause *quplist; ! 643: { ! 644: register struct quotause *qup, *nextqup; ! 645: ! 646: for (qup = quplist; qup; qup = nextqup) { ! 647: nextqup = qup->next; ! 648: free(qup); ! 649: } ! 650: } ! 651: ! 652: /* ! 653: * Check whether a string is completely composed of digits. ! 654: */ ! 655: alldigits(s) ! 656: register char *s; ! 657: { ! 658: register c; ! 659: ! 660: c = *s++; ! 661: do { ! 662: if (!isdigit(c)) ! 663: return (0); ! 664: } while (c = *s++); ! 665: return (1); ! 666: } ! 667: ! 668: /* ! 669: * Check to see if a particular quota is to be enabled. ! 670: */ ! 671: hasquota(fs, type, qfnamep) ! 672: register struct fstab *fs; ! 673: int type; ! 674: char **qfnamep; ! 675: { ! 676: register char *opt; ! 677: char *cp, *index(), *strtok(); ! 678: static char initname, usrname[100], grpname[100]; ! 679: static char buf[BUFSIZ]; ! 680: ! 681: if (!initname) { ! 682: sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname); ! 683: sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname); ! 684: initname = 1; ! 685: } ! 686: strcpy(buf, fs->fs_mntops); ! 687: for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { ! 688: if (cp = index(opt, '=')) ! 689: *cp++ = '\0'; ! 690: if (type == USRQUOTA && strcmp(opt, usrname) == 0) ! 691: break; ! 692: if (type == GRPQUOTA && strcmp(opt, grpname) == 0) ! 693: break; ! 694: } ! 695: if (!opt) ! 696: return (0); ! 697: if (cp) { ! 698: *qfnamep = cp; ! 699: return (1); ! 700: } ! 701: (void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]); ! 702: *qfnamep = buf; ! 703: return (1); ! 704: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.