Annotation of src/usr.bin/quota/quota.c, Revision 1.30
1.30 ! william 1: /* $OpenBSD: quota.c,v 1.29 2009/10/27 23:59: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: */
38: #include <sys/param.h>
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;
70: char fsname[MAXPATHLEN + 1];
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;
99: gid_t mygid, gidset[NGROUPS];
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':
108: gflag++;
109: break;
110: case 'u':
111: uflag++;
112: break;
113: case 'v':
114: vflag++;
115: break;
116: case 'q':
117: qflag++;
118: break;
119: default:
120: usage();
121: }
122: }
123: argc -= optind;
124: argv += optind;
125: if (!uflag && !gflag)
126: uflag++;
127: if (argc == 0) {
128: if (uflag)
129: showuid(getuid());
130: if (gflag) {
131: mygid = getgid();
132: ngroups = getgroups(NGROUPS, 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;
229: gid_t mygid, gidset[NGROUPS];
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();
238: ngroups = getgroups(NGROUPS, gidset);
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;
263: gid_t mygid, gidset[NGROUPS];
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();
271: ngroups = getgroups(NGROUPS, gidset);
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.20 fgsch 447: if ((qup =
448: (struct quotause *)malloc(sizeof *qup)) == NULL)
1.15 pjanzen 449: errx(2, "out of memory");
1.1 deraadt 450: }
451: if (strncmp(fst[i].f_fstypename, "nfs", MFSNAMELEN) == 0) {
452: if (getnfsquota(&fst[i], NULL, qup, id, quotatype) == 0)
453: continue;
1.4 deraadt 454: } else if (!strncmp(fst[i].f_fstypename, "ffs", MFSNAMELEN) ||
455: !strncmp(fst[i].f_fstypename, "ufs", MFSNAMELEN) ||
456: !strncmp(fst[i].f_fstypename, "mfs", MFSNAMELEN)) {
1.1 deraadt 457: /*
458: * XXX
459: * UFS filesystems must be in /etc/fstab, and must
460: * indicate that they have quotas on (?!) This is quite
461: * unlike SunOS where quotas can be enabled/disabled
462: * on a filesystem independent of /etc/fstab, and it
463: * will still print quotas for them.
464: */
465: if ((fs = getfsspec(fst[i].f_mntfromname)) == NULL)
466: continue;
467: if (getufsquota(&fst[i], fs, qup, id, quotatype) == 0)
468: continue;
469: } else
470: continue;
1.10 deraadt 471: strncpy(qup->fsname, fst[i].f_mntonname, sizeof qup->fsname-1);
472: qup->fsname[sizeof qup->fsname-1] = '\0';
1.1 deraadt 473: if (quphead == NULL)
474: quphead = qup;
475: else
476: quptail->next = qup;
477: quptail = qup;
478: quptail->next = 0;
479: qup = NULL;
480: }
481: if (qup)
482: free(qup);
483: endfsent();
484: return (quphead);
485: }
486:
487: /*
488: * Check to see if a particular quota is to be enabled.
489: */
1.15 pjanzen 490: int
1.23 deraadt 491: ufshasquota(struct fstab *fs, int type, char **qfnamep)
1.1 deraadt 492: {
493: static char initname, usrname[100], grpname[100];
494: static char buf[BUFSIZ];
495: char *opt, *cp;
496:
1.15 pjanzen 497: cp = NULL;
1.1 deraadt 498: if (!initname) {
1.15 pjanzen 499: (void)snprintf(usrname, sizeof usrname, "%s%s",
1.6 deraadt 500: qfextension[USRQUOTA], qfname);
1.15 pjanzen 501: (void)snprintf(grpname, sizeof grpname, "%s%s",
1.6 deraadt 502: qfextension[GRPQUOTA], qfname);
1.1 deraadt 503: initname = 1;
504: }
1.7 etheisen 505: strncpy(buf, fs->fs_mntops, sizeof buf);
1.15 pjanzen 506: buf[sizeof(buf) - 1] = '\0';
1.1 deraadt 507: for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
1.15 pjanzen 508: if ((cp = strchr(opt, '=')))
1.1 deraadt 509: *cp++ = '\0';
510: if (type == USRQUOTA && strcmp(opt, usrname) == 0)
511: break;
512: if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
513: break;
514: }
515: if (!opt)
516: return (0);
517: if (cp) {
518: *qfnamep = cp;
519: return (1);
520: }
1.15 pjanzen 521: (void)snprintf(buf, sizeof buf, "%s/%s.%s",
1.6 deraadt 522: fs->fs_file, qfname, qfextension[type]);
1.1 deraadt 523: *qfnamep = buf;
524: return (1);
525: }
526:
527: int
1.23 deraadt 528: getufsquota(struct statfs *fst, struct fstab *fs, struct quotause *qup,
529: long id, int quotatype)
1.1 deraadt 530: {
531: char *qfpathname;
532: int fd, qcmd;
533:
534: qcmd = QCMD(Q_GETQUOTA, quotatype);
535: if (!ufshasquota(fs, quotatype, &qfpathname))
536: return (0);
537:
1.16 pjanzen 538: if (quotactl(fs->fs_file, qcmd, id, (char *)&qup->dqblk) != 0) {
1.1 deraadt 539: if ((fd = open(qfpathname, O_RDONLY)) < 0) {
1.15 pjanzen 540: warn("%s", qfpathname);
1.1 deraadt 541: return (0);
542: }
1.15 pjanzen 543: (void)lseek(fd, (off_t)(id * sizeof(struct dqblk)), SEEK_SET);
1.1 deraadt 544: switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) {
545: case 0: /* EOF */
546: /*
547: * Convert implicit 0 quota (EOF)
548: * into an explicit one (zero'ed dqblk)
549: */
1.11 deraadt 550: memset((caddr_t)&qup->dqblk, 0, sizeof(struct dqblk));
1.1 deraadt 551: break;
552: case sizeof(struct dqblk): /* OK */
553: break;
554: default: /* ERROR */
1.24 mickey 555: warn("%s", qfpathname);
1.1 deraadt 556: close(fd);
557: return (0);
558: }
559: close(fd);
560: }
561: return (1);
562: }
563:
564: int
1.23 deraadt 565: getnfsquota(struct statfs *fst, struct fstab *fs, struct quotause *qup,
566: long id, int quotatype)
1.1 deraadt 567: {
568: struct getquota_args gq_args;
569: struct getquota_rslt gq_rslt;
570: struct dqblk *dqp = &qup->dqblk;
571: struct timeval tv;
572: char *cp;
573:
574: if (fst->f_flags & MNT_LOCAL)
575: return (0);
576:
577: /*
578: * rpc.rquotad does not support group quotas
579: */
580: if (quotatype != USRQUOTA)
581: return (0);
582:
583: /*
584: * must be some form of "hostname:/path"
585: */
586: cp = strchr(fst->f_mntfromname, ':');
587: if (cp == NULL) {
1.15 pjanzen 588: warnx("cannot find hostname for %s", fst->f_mntfromname);
1.1 deraadt 589: return (0);
590: }
591:
592: *cp = '\0';
1.11 deraadt 593: if (cp[1] != '/') {
1.1 deraadt 594: *cp = ':';
595: return (0);
596: }
597:
1.11 deraadt 598: gq_args.gqa_pathp = &cp[1];
1.1 deraadt 599: gq_args.gqa_uid = id;
600: if (callaurpc(fst->f_mntfromname, RQUOTAPROG, RQUOTAVERS,
601: RQUOTAPROC_GETQUOTA, xdr_getquota_args, &gq_args,
602: xdr_getquota_rslt, &gq_rslt) != 0) {
603: *cp = ':';
604: return (0);
605: }
606:
607: switch (gq_rslt.status) {
608: case Q_NOQUOTA:
609: break;
610: case Q_EPERM:
1.15 pjanzen 611: warnx("permission error, host: %s", fst->f_mntfromname);
1.1 deraadt 612: break;
613: case Q_OK:
614: gettimeofday(&tv, NULL);
615: /* blocks*/
616: dqp->dqb_bhardlimit =
617: gq_rslt.getquota_rslt_u.gqr_rquota.rq_bhardlimit *
1.30 ! william 618: (gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize / DEV_BSIZE);
1.1 deraadt 619: dqp->dqb_bsoftlimit =
620: gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsoftlimit *
1.30 ! william 621: (gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize / DEV_BSIZE);
1.1 deraadt 622: dqp->dqb_curblocks =
623: gq_rslt.getquota_rslt_u.gqr_rquota.rq_curblocks *
1.30 ! william 624: (gq_rslt.getquota_rslt_u.gqr_rquota.rq_bsize / DEV_BSIZE);
1.1 deraadt 625: /* inodes */
626: dqp->dqb_ihardlimit =
627: gq_rslt.getquota_rslt_u.gqr_rquota.rq_fhardlimit;
628: dqp->dqb_isoftlimit =
629: gq_rslt.getquota_rslt_u.gqr_rquota.rq_fsoftlimit;
630: dqp->dqb_curinodes =
631: gq_rslt.getquota_rslt_u.gqr_rquota.rq_curfiles;
632: /* grace times */
633: dqp->dqb_btime =
634: tv.tv_sec + gq_rslt.getquota_rslt_u.gqr_rquota.rq_btimeleft;
635: dqp->dqb_itime =
636: tv.tv_sec + gq_rslt.getquota_rslt_u.gqr_rquota.rq_ftimeleft;
637: *cp = ':';
638: return (1);
639: default:
1.15 pjanzen 640: warnx("bad rpc result, host: %s", fst->f_mntfromname);
1.1 deraadt 641: break;
642: }
643: *cp = ':';
644: return (0);
645: }
646:
647: int
1.23 deraadt 648: callaurpc(char *host, int prognum, int versnum, int procnum,
649: xdrproc_t inproc, void *in, xdrproc_t outproc, void *out)
1.1 deraadt 650: {
651: struct sockaddr_in server_addr;
652: enum clnt_stat clnt_stat;
653: struct hostent *hp;
654: struct timeval timeout, tottimeout;
655:
656: CLIENT *client = NULL;
657: int socket = RPC_ANYSOCK;
658:
659: if ((hp = gethostbyname(host)) == NULL)
660: return ((int) RPC_UNKNOWNHOST);
661: timeout.tv_usec = 0;
662: timeout.tv_sec = 6;
1.11 deraadt 663:
664: memset(&server_addr, 0, sizeof server_addr);
665: memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
1.1 deraadt 666: server_addr.sin_family = AF_INET;
667: server_addr.sin_port = 0;
668:
669: if ((client = clntudp_create(&server_addr, prognum,
670: versnum, timeout, &socket)) == NULL)
671: return ((int) rpc_createerr.cf_stat);
672:
673: client->cl_auth = authunix_create_default();
674: tottimeout.tv_sec = 25;
675: tottimeout.tv_usec = 0;
676: clnt_stat = clnt_call(client, procnum, inproc, in,
677: outproc, out, tottimeout);
678:
679: return ((int) clnt_stat);
680: }
681:
1.15 pjanzen 682: int
1.23 deraadt 683: alldigits(char *s)
1.1 deraadt 684: {
1.15 pjanzen 685: int c;
1.1 deraadt 686:
687: c = *s++;
688: do {
689: if (!isdigit(c))
690: return (0);
1.15 pjanzen 691: } while ((c = *s++));
1.1 deraadt 692: return (1);
693: }