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