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