Annotation of src/usr.bin/quota/quota.c, Revision 1.1
1.1 ! deraadt 1: /*
! 2: * Copyright (c) 1980, 1990, 1993
! 3: * The Regents of the University of California. 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, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. All advertising materials mentioning features or use of this software
! 17: * must display the following acknowledgement:
! 18: * This product includes software developed by the University of
! 19: * California, Berkeley and its contributors.
! 20: * 4. Neither the name of the University nor the names of its contributors
! 21: * may be used to endorse or promote products derived from this software
! 22: * without specific prior written permission.
! 23: *
! 24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 34: * SUCH DAMAGE.
! 35: */
! 36:
! 37: #ifndef lint
! 38: static char copyright[] =
! 39: "@(#) Copyright (c) 1980, 1990, 1993\n\
! 40: The Regents of the University of California. All rights reserved.\n";
! 41: #endif /* not lint */
! 42:
! 43: #ifndef lint
! 44: /*static char sccsid[] = "from: @(#)quota.c 8.1 (Berkeley) 6/6/93";*/
! 45: static char rcsid[] = "$Id: quota.c,v 1.9 1995/06/18 11:00:49 cgd Exp $";
! 46: #endif /* not lint */
! 47:
! 48: /*
! 49: * Disk quota reporting program.
! 50: */
! 51: #include <sys/param.h>
! 52: #include <sys/types.h>
! 53: #include <sys/file.h>
! 54: #include <sys/stat.h>
! 55: #include <sys/mount.h>
! 56: #include <sys/socket.h>
! 57: #include <ufs/ufs/quota.h>
! 58: #include <stdio.h>
! 59: #include <stdlib.h>
! 60: #include <fstab.h>
! 61: #include <ctype.h>
! 62: #include <string.h>
! 63: #include <pwd.h>
! 64: #include <grp.h>
! 65: #include <errno.h>
! 66:
! 67: #include <netdb.h>
! 68: #include <rpc/rpc.h>
! 69: #include <rpc/pmap_prot.h>
! 70: #include <rpcsvc/rquota.h>
! 71:
! 72: char *qfname = QUOTAFILENAME;
! 73: char *qfextension[] = INITQFNAMES;
! 74:
! 75: struct quotause {
! 76: struct quotause *next;
! 77: long flags;
! 78: struct dqblk dqblk;
! 79: char fsname[MAXPATHLEN + 1];
! 80: };
! 81: #define FOUND 0x01
! 82:
! 83: char *timeprt __P((time_t seconds));
! 84: struct quotause *getprivs __P((long id, int quotatype));
! 85:
! 86: int qflag;
! 87: int vflag;
! 88:
! 89: main(argc, argv)
! 90: char *argv[];
! 91: {
! 92: int ngroups;
! 93: gid_t mygid, gidset[NGROUPS];
! 94: int i, gflag = 0, uflag = 0;
! 95: char ch;
! 96: extern char *optarg;
! 97: extern int optind, errno;
! 98:
! 99: while ((ch = getopt(argc, argv, "ugvq")) != EOF) {
! 100: switch(ch) {
! 101: case 'g':
! 102: gflag++;
! 103: break;
! 104: case 'u':
! 105: uflag++;
! 106: break;
! 107: case 'v':
! 108: vflag++;
! 109: break;
! 110: case 'q':
! 111: qflag++;
! 112: break;
! 113: default:
! 114: usage();
! 115: }
! 116: }
! 117: argc -= optind;
! 118: argv += optind;
! 119: if (!uflag && !gflag)
! 120: uflag++;
! 121: if (argc == 0) {
! 122: if (uflag)
! 123: showuid(getuid());
! 124: if (gflag) {
! 125: mygid = getgid();
! 126: ngroups = getgroups(NGROUPS, gidset);
! 127: if (ngroups < 0) {
! 128: perror("quota: getgroups");
! 129: exit(1);
! 130: }
! 131: showgid(mygid);
! 132: for (i = 0; i < ngroups; i++)
! 133: if (gidset[i] != mygid)
! 134: showgid(gidset[i]);
! 135: }
! 136: exit(0);
! 137: }
! 138: if (uflag && gflag)
! 139: usage();
! 140: if (uflag) {
! 141: for (; argc > 0; argc--, argv++) {
! 142: if (alldigits(*argv))
! 143: showuid(atoi(*argv));
! 144: else
! 145: showusrname(*argv);
! 146: }
! 147: exit(0);
! 148: }
! 149: if (gflag) {
! 150: for (; argc > 0; argc--, argv++) {
! 151: if (alldigits(*argv))
! 152: showgid(atoi(*argv));
! 153: else
! 154: showgrpname(*argv);
! 155: }
! 156: exit(0);
! 157: }
! 158: }
! 159:
! 160: usage()
! 161: {
! 162:
! 163: fprintf(stderr, "%s\n%s\n%s\n",
! 164: "Usage: quota [-guqv]",
! 165: "\tquota [-qv] -u username ...",
! 166: "\tquota [-qv] -g groupname ...");
! 167: exit(1);
! 168: }
! 169:
! 170: /*
! 171: * Print out quotas for a specified user identifier.
! 172: */
! 173: showuid(uid)
! 174: u_long uid;
! 175: {
! 176: struct passwd *pwd = getpwuid(uid);
! 177: u_long myuid;
! 178: char *name;
! 179:
! 180: if (pwd == NULL)
! 181: name = "(no account)";
! 182: else
! 183: name = pwd->pw_name;
! 184: myuid = getuid();
! 185: if (uid != myuid && myuid != 0) {
! 186: printf("quota: %s (uid %d): permission denied\n", name, uid);
! 187: return;
! 188: }
! 189: showquotas(USRQUOTA, uid, name);
! 190: }
! 191:
! 192: /*
! 193: * Print out quotas for a specifed user name.
! 194: */
! 195: showusrname(name)
! 196: char *name;
! 197: {
! 198: struct passwd *pwd = getpwnam(name);
! 199: u_long myuid;
! 200:
! 201: if (pwd == NULL) {
! 202: fprintf(stderr, "quota: %s: unknown user\n", name);
! 203: return;
! 204: }
! 205: myuid = getuid();
! 206: if (pwd->pw_uid != myuid && myuid != 0) {
! 207: fprintf(stderr, "quota: %s (uid %d): permission denied\n",
! 208: name, pwd->pw_uid);
! 209: return;
! 210: }
! 211: showquotas(USRQUOTA, pwd->pw_uid, name);
! 212: }
! 213:
! 214: /*
! 215: * Print out quotas for a specified group identifier.
! 216: */
! 217: showgid(gid)
! 218: u_long gid;
! 219: {
! 220: struct group *grp = getgrgid(gid);
! 221: int ngroups;
! 222: gid_t mygid, gidset[NGROUPS];
! 223: register int i;
! 224: char *name;
! 225:
! 226: if (grp == NULL)
! 227: name = "(no entry)";
! 228: else
! 229: name = grp->gr_name;
! 230: mygid = getgid();
! 231: ngroups = getgroups(NGROUPS, gidset);
! 232: if (ngroups < 0) {
! 233: perror("quota: getgroups");
! 234: return;
! 235: }
! 236: if (gid != mygid) {
! 237: for (i = 0; i < ngroups; i++)
! 238: if (gid == gidset[i])
! 239: break;
! 240: if (i >= ngroups && getuid() != 0) {
! 241: fprintf(stderr,
! 242: "quota: %s (gid %d): permission denied\n",
! 243: name, gid);
! 244: return;
! 245: }
! 246: }
! 247: showquotas(GRPQUOTA, gid, name);
! 248: }
! 249:
! 250: /*
! 251: * Print out quotas for a specifed group name.
! 252: */
! 253: showgrpname(name)
! 254: char *name;
! 255: {
! 256: struct group *grp = getgrnam(name);
! 257: int ngroups;
! 258: gid_t mygid, gidset[NGROUPS];
! 259: register int i;
! 260:
! 261: if (grp == NULL) {
! 262: fprintf(stderr, "quota: %s: unknown group\n", name);
! 263: return;
! 264: }
! 265: mygid = getgid();
! 266: ngroups = getgroups(NGROUPS, gidset);
! 267: if (ngroups < 0) {
! 268: perror("quota: getgroups");
! 269: return;
! 270: }
! 271: if (grp->gr_gid != mygid) {
! 272: for (i = 0; i < ngroups; i++)
! 273: if (grp->gr_gid == gidset[i])
! 274: break;
! 275: if (i >= ngroups && getuid() != 0) {
! 276: fprintf(stderr,
! 277: "quota: %s (gid %d): permission denied\n",
! 278: name, grp->gr_gid);
! 279: return;
! 280: }
! 281: }
! 282: showquotas(GRPQUOTA, grp->gr_gid, name);
! 283: }
! 284:
! 285: showquotas(type, id, name)
! 286: int type;
! 287: u_long id;
! 288: char *name;
! 289: {
! 290: register struct quotause *qup;
! 291: struct quotause *quplist;
! 292: char *msgi, *msgb, *nam;
! 293: int myuid, fd, lines = 0;
! 294: static int first;
! 295: static time_t now;
! 296:
! 297: if (now == 0)
! 298: time(&now);
! 299: quplist = getprivs(id, type);
! 300: for (qup = quplist; qup; qup = qup->next) {
! 301: if (!vflag &&
! 302: qup->dqblk.dqb_isoftlimit == 0 &&
! 303: qup->dqblk.dqb_ihardlimit == 0 &&
! 304: qup->dqblk.dqb_bsoftlimit == 0 &&
! 305: qup->dqblk.dqb_bhardlimit == 0)
! 306: continue;
! 307: msgi = (char *)0;
! 308: if (qup->dqblk.dqb_ihardlimit &&
! 309: qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_ihardlimit)
! 310: msgi = "File limit reached on";
! 311: else if (qup->dqblk.dqb_isoftlimit &&
! 312: qup->dqblk.dqb_curinodes >= qup->dqblk.dqb_isoftlimit)
! 313: if (qup->dqblk.dqb_itime > now)
! 314: msgi = "In file grace period on";
! 315: else
! 316: msgi = "Over file quota on";
! 317: msgb = (char *)0;
! 318: if (qup->dqblk.dqb_bhardlimit &&
! 319: qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bhardlimit)
! 320: msgb = "Block limit reached on";
! 321: else if (qup->dqblk.dqb_bsoftlimit &&
! 322: qup->dqblk.dqb_curblocks >= qup->dqblk.dqb_bsoftlimit)
! 323: if (qup->dqblk.dqb_btime > now)
! 324: msgb = "In block grace period on";
! 325: else
! 326: msgb = "Over block quota on";
! 327: if (qflag) {
! 328: if ((msgi != (char *)0 || msgb != (char *)0) &&
! 329: lines++ == 0)
! 330: heading(type, id, name, "");
! 331: if (msgi != (char *)0)
! 332: printf("\t%s %s\n", msgi, qup->fsname);
! 333: if (msgb != (char *)0)
! 334: printf("\t%s %s\n", msgb, qup->fsname);
! 335: continue;
! 336: }
! 337: if (vflag ||
! 338: qup->dqblk.dqb_curblocks ||
! 339: qup->dqblk.dqb_curinodes) {
! 340: if (lines++ == 0)
! 341: heading(type, id, name, "");
! 342: nam = qup->fsname;
! 343: if (strlen(qup->fsname) > 15) {
! 344: printf("%s\n", qup->fsname);
! 345: nam = "";
! 346: }
! 347: printf("%15s%8d%c%7d%8d%8s"
! 348: , nam
! 349: , dbtob(qup->dqblk.dqb_curblocks) / 1024
! 350: , (msgb == (char *)0) ? ' ' : '*'
! 351: , dbtob(qup->dqblk.dqb_bsoftlimit) / 1024
! 352: , dbtob(qup->dqblk.dqb_bhardlimit) / 1024
! 353: , (msgb == (char *)0) ? ""
! 354: : timeprt(qup->dqblk.dqb_btime));
! 355: printf("%8d%c%7d%8d%8s\n"
! 356: , qup->dqblk.dqb_curinodes
! 357: , (msgi == (char *)0) ? ' ' : '*'
! 358: , qup->dqblk.dqb_isoftlimit
! 359: , qup->dqblk.dqb_ihardlimit
! 360: , (msgi == (char *)0) ? ""
! 361: : timeprt(qup->dqblk.dqb_itime)
! 362: );
! 363: continue;
! 364: }
! 365: }
! 366: if (!qflag && lines == 0)
! 367: heading(type, id, name, "none");
! 368: }
! 369:
! 370: heading(type, id, name, tag)
! 371: int type;
! 372: u_long id;
! 373: char *name, *tag;
! 374: {
! 375:
! 376: printf("Disk quotas for %s %s (%cid %d): %s\n", qfextension[type],
! 377: name, *qfextension[type], id, tag);
! 378: if (!qflag && tag[0] == '\0') {
! 379: printf("%15s%8s %7s%8s%8s%8s %7s%8s%8s\n"
! 380: , "Filesystem"
! 381: , "blocks"
! 382: , "quota"
! 383: , "limit"
! 384: , "grace"
! 385: , "files"
! 386: , "quota"
! 387: , "limit"
! 388: , "grace"
! 389: );
! 390: }
! 391: }
! 392:
! 393: /*
! 394: * Calculate the grace period and return a printable string for it.
! 395: */
! 396: char *
! 397: timeprt(seconds)
! 398: time_t seconds;
! 399: {
! 400: time_t hours, minutes;
! 401: static char buf[20];
! 402: static time_t now;
! 403:
! 404: if (now == 0)
! 405: time(&now);
! 406: if (now > seconds)
! 407: return ("none");
! 408: seconds -= now;
! 409: minutes = (seconds + 30) / 60;
! 410: hours = (minutes + 30) / 60;
! 411: if (hours >= 36) {
! 412: sprintf(buf, "%ddays", (hours + 12) / 24);
! 413: return (buf);
! 414: }
! 415: if (minutes >= 60) {
! 416: sprintf(buf, "%2d:%d", minutes / 60, minutes % 60);
! 417: return (buf);
! 418: }
! 419: sprintf(buf, "%2d", minutes);
! 420: return (buf);
! 421: }
! 422:
! 423: /*
! 424: * Collect the requested quota information.
! 425: */
! 426: struct quotause *
! 427: getprivs(id, quotatype)
! 428: register long id;
! 429: int quotatype;
! 430: {
! 431: register struct quotause *qup, *quptail;
! 432: register struct fstab *fs;
! 433: struct quotause *quphead;
! 434: struct statfs *fst;
! 435: int nfst, i;
! 436:
! 437: qup = quphead = (struct quotause *)0;
! 438:
! 439: nfst = getmntinfo(&fst, MNT_WAIT);
! 440: if (nfst == 0) {
! 441: fprintf(stderr, "quota: no filesystems mounted!\n");
! 442: exit(2);
! 443: }
! 444: setfsent();
! 445: for (i=0; i<nfst; i++) {
! 446: if (qup == NULL) {
! 447: if ((qup = (struct quotause *)malloc(sizeof *qup)) == NULL) {
! 448: fprintf(stderr, "quota: out of memory\n");
! 449: exit(2);
! 450: }
! 451: }
! 452: if (strncmp(fst[i].f_fstypename, "nfs", MFSNAMELEN) == 0) {
! 453: if (getnfsquota(&fst[i], NULL, qup, id, quotatype) == 0)
! 454: continue;
! 455: } else if (strncmp(fst[i].f_fstypename, "ufs",
! 456: MFSNAMELEN) == 0) {
! 457: /*
! 458: * XXX
! 459: * UFS filesystems must be in /etc/fstab, and must
! 460: * indicate that they have quotas on (?!) This is quite
! 461: * unlike SunOS where quotas can be enabled/disabled
! 462: * on a filesystem independent of /etc/fstab, and it
! 463: * will still print quotas for them.
! 464: */
! 465: if ((fs = getfsspec(fst[i].f_mntfromname)) == NULL)
! 466: continue;
! 467: if (getufsquota(&fst[i], fs, qup, id, quotatype) == 0)
! 468: continue;
! 469: } else
! 470: continue;
! 471: strcpy(qup->fsname, fst[i].f_mntonname);
! 472: if (quphead == NULL)
! 473: quphead = qup;
! 474: else
! 475: quptail->next = qup;
! 476: quptail = qup;
! 477: quptail->next = 0;
! 478: qup = NULL;
! 479: }
! 480: if (qup)
! 481: free(qup);
! 482: endfsent();
! 483: return (quphead);
! 484: }
! 485:
! 486: /*
! 487: * Check to see if a particular quota is to be enabled.
! 488: */
! 489: ufshasquota(fs, type, qfnamep)
! 490: register struct fstab *fs;
! 491: int type;
! 492: char **qfnamep;
! 493: {
! 494: static char initname, usrname[100], grpname[100];
! 495: static char buf[BUFSIZ];
! 496: char *opt, *cp;
! 497:
! 498: if (!initname) {
! 499: sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname);
! 500: sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname);
! 501: initname = 1;
! 502: }
! 503: strcpy(buf, fs->fs_mntops);
! 504: for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
! 505: if (cp = index(opt, '='))
! 506: *cp++ = '\0';
! 507: if (type == USRQUOTA && strcmp(opt, usrname) == 0)
! 508: break;
! 509: if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
! 510: break;
! 511: }
! 512: if (!opt)
! 513: return (0);
! 514: if (cp) {
! 515: *qfnamep = cp;
! 516: return (1);
! 517: }
! 518: (void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
! 519: *qfnamep = buf;
! 520: return (1);
! 521: }
! 522:
! 523: int
! 524: getufsquota(fst, fs, qup, id, quotatype)
! 525: struct statfs *fst;
! 526: struct fstab *fs;
! 527: struct quotause *qup;
! 528: long id;
! 529: int quotatype;
! 530: {
! 531: char *qfpathname;
! 532: int fd, qcmd;
! 533:
! 534: qcmd = QCMD(Q_GETQUOTA, quotatype);
! 535: if (!ufshasquota(fs, quotatype, &qfpathname))
! 536: return (0);
! 537:
! 538: if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) {
! 539: if ((fd = open(qfpathname, O_RDONLY)) < 0) {
! 540: perror(qfpathname);
! 541: return (0);
! 542: }
! 543: (void) lseek(fd, (off_t)(id * sizeof(struct dqblk)), L_SET);
! 544: switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) {
! 545: case 0: /* EOF */
! 546: /*
! 547: * Convert implicit 0 quota (EOF)
! 548: * into an explicit one (zero'ed dqblk)
! 549: */
! 550: bzero((caddr_t)&qup->dqblk, sizeof(struct dqblk));
! 551: break;
! 552: case sizeof(struct dqblk): /* OK */
! 553: break;
! 554: default: /* ERROR */
! 555: fprintf(stderr, "quota: read error");
! 556: perror(qfpathname);
! 557: close(fd);
! 558: return (0);
! 559: }
! 560: close(fd);
! 561: }
! 562: return (1);
! 563: }
! 564:
! 565: int
! 566: getnfsquota(fst, fs, qup, id, quotatype)
! 567: struct statfs *fst;
! 568: struct fstab *fs;
! 569: struct quotause *qup;
! 570: long id;
! 571: int quotatype;
! 572: {
! 573: struct getquota_args gq_args;
! 574: struct getquota_rslt gq_rslt;
! 575: struct dqblk *dqp = &qup->dqblk;
! 576: struct timeval tv;
! 577: char *cp;
! 578:
! 579: if (fst->f_flags & MNT_LOCAL)
! 580: return (0);
! 581:
! 582: /*
! 583: * rpc.rquotad does not support group quotas
! 584: */
! 585: if (quotatype != USRQUOTA)
! 586: return (0);
! 587:
! 588: /*
! 589: * must be some form of "hostname:/path"
! 590: */
! 591: cp = strchr(fst->f_mntfromname, ':');
! 592: if (cp == NULL) {
! 593: fprintf(stderr, "cannot find hostname for %s\n",
! 594: fst->f_mntfromname);
! 595: return (0);
! 596: }
! 597:
! 598: *cp = '\0';
! 599: if (*(cp+1) != '/') {
! 600: *cp = ':';
! 601: return (0);
! 602: }
! 603:
! 604: gq_args.gqa_pathp = cp + 1;
! 605: gq_args.gqa_uid = id;
! 606: if (callaurpc(fst->f_mntfromname, RQUOTAPROG, RQUOTAVERS,
! 607: RQUOTAPROC_GETQUOTA, xdr_getquota_args, &gq_args,
! 608: xdr_getquota_rslt, &gq_rslt) != 0) {
! 609: *cp = ':';
! 610: return (0);
! 611: }
! 612:
! 613: switch (gq_rslt.status) {
! 614: case Q_NOQUOTA:
! 615: break;
! 616: case Q_EPERM:
! 617: fprintf(stderr, "quota permission error, host: %s\n",
! 618: fst->f_mntfromname);
! 619: break;
! 620: case Q_OK:
! 621: gettimeofday(&tv, NULL);
! 622: /* blocks*/
! 623: dqp->dqb_bhardlimit =
! 624: gq_rslt.getquota_rslt_u.gqr_rquota.rq_bhardlimit *
! 625: gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize / DEV_BSIZE;
! 626: dqp->dqb_bsoftlimit =
! 627: gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsoftlimit *
! 628: gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize / DEV_BSIZE;
! 629: dqp->dqb_curblocks =
! 630: gq_rslt.getquota_rslt_u.gqr_rquota.rq_curblocks *
! 631: gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize / DEV_BSIZE;
! 632: /* inodes */
! 633: dqp->dqb_ihardlimit =
! 634: gq_rslt.getquota_rslt_u.gqr_rquota.rq_fhardlimit;
! 635: dqp->dqb_isoftlimit =
! 636: gq_rslt.getquota_rslt_u.gqr_rquota.rq_fsoftlimit;
! 637: dqp->dqb_curinodes =
! 638: gq_rslt.getquota_rslt_u.gqr_rquota.rq_curfiles;
! 639: /* grace times */
! 640: dqp->dqb_btime =
! 641: tv.tv_sec + gq_rslt.getquota_rslt_u.gqr_rquota.rq_btimeleft;
! 642: dqp->dqb_itime =
! 643: tv.tv_sec + gq_rslt.getquota_rslt_u.gqr_rquota.rq_ftimeleft;
! 644: *cp = ':';
! 645: return (1);
! 646: default:
! 647: fprintf(stderr, "bad rpc result, host: %s\n",
! 648: fst->f_mntfromname);
! 649: break;
! 650: }
! 651: *cp = ':';
! 652: return (0);
! 653: }
! 654:
! 655: int
! 656: callaurpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
! 657: char *host;
! 658: xdrproc_t inproc, outproc;
! 659: char *in, *out;
! 660: {
! 661: struct sockaddr_in server_addr;
! 662: enum clnt_stat clnt_stat;
! 663: struct hostent *hp;
! 664: struct timeval timeout, tottimeout;
! 665:
! 666: CLIENT *client = NULL;
! 667: int socket = RPC_ANYSOCK;
! 668:
! 669: if ((hp = gethostbyname(host)) == NULL)
! 670: return ((int) RPC_UNKNOWNHOST);
! 671: timeout.tv_usec = 0;
! 672: timeout.tv_sec = 6;
! 673: bcopy(hp->h_addr, &server_addr.sin_addr, hp->h_length);
! 674: server_addr.sin_family = AF_INET;
! 675: server_addr.sin_port = 0;
! 676:
! 677: if ((client = clntudp_create(&server_addr, prognum,
! 678: versnum, timeout, &socket)) == NULL)
! 679: return ((int) rpc_createerr.cf_stat);
! 680:
! 681: client->cl_auth = authunix_create_default();
! 682: tottimeout.tv_sec = 25;
! 683: tottimeout.tv_usec = 0;
! 684: clnt_stat = clnt_call(client, procnum, inproc, in,
! 685: outproc, out, tottimeout);
! 686:
! 687: return ((int) clnt_stat);
! 688: }
! 689:
! 690: alldigits(s)
! 691: register char *s;
! 692: {
! 693: register c;
! 694:
! 695: c = *s++;
! 696: do {
! 697: if (!isdigit(c))
! 698: return (0);
! 699: } while (c = *s++);
! 700: return (1);
! 701: }