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