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