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