dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / fs.d / nfs / dfmounts / dfmounts.c
blob82bbc7e303f23bff88a420c8071f16a004ced0a1
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
41 * nfs dfmounts
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <stdarg.h>
46 #include <string.h>
47 #include <rpc/rpc.h>
48 #include <rpc/rpcb_clnt.h>
49 #include <sys/socket.h>
50 #include <netdb.h>
51 #include <sys/time.h>
52 #include <sys/errno.h>
53 #include <nfs/nfs.h>
54 #include <rpcsvc/mount.h>
55 #include <locale.h>
57 static int hflg;
59 static void pr_mounts(char *);
60 static void freemntlist(struct mountbody *);
61 static int sortpath(const void *, const void *);
62 static void usage(void);
63 static void pr_err(char *, ...);
65 int
66 main(int argc, char *argv[])
69 char hostbuf[256];
70 extern int optind;
71 int i, c;
73 (void) setlocale(LC_ALL, "");
75 #if !defined(TEXT_DOMAIN)
76 #define TEXT_DOMAIN "SYS_TEST"
77 #endif
78 (void) textdomain(TEXT_DOMAIN);
80 while ((c = getopt(argc, argv, "h")) != EOF) {
81 switch (c) {
82 case 'h':
83 hflg++;
84 break;
85 default:
86 usage();
87 exit(1);
91 if (optind < argc) {
92 for (i = optind; i < argc; i++)
93 pr_mounts(argv[i]);
94 } else {
95 if (gethostname(hostbuf, sizeof (hostbuf)) < 0) {
96 perror("nfs dfmounts: gethostname");
97 exit(1);
99 pr_mounts(hostbuf);
102 return (0);
105 #define NTABLEENTRIES 2048
106 static struct mountbody *table[NTABLEENTRIES];
107 static struct timeval rpc_totout_new = {15, 0};
110 * Print the filesystems on "host" that are currently mounted by a client.
113 static void
114 pr_mounts(host)
115 char *host;
117 CLIENT *cl;
118 struct mountbody *ml = NULL;
119 struct mountbody **tb, **endtb;
120 enum clnt_stat err;
121 char *lastpath;
122 char *lastclient;
123 int tail = 0;
124 struct timeval tout, rpc_totout_old;
126 (void) __rpc_control(CLCR_GET_RPCB_TIMEOUT, &rpc_totout_old);
127 (void) __rpc_control(CLCR_SET_RPCB_TIMEOUT, &rpc_totout_new);
130 * First try circuit, then drop back to datagram if
131 * circuit is unavailable (an old version of mountd perhaps)
132 * Using circuit is preferred because it can handle
133 * arbitrarily long export lists.
135 cl = clnt_create(host, MOUNTPROG, MOUNTVERS, "circuit_n");
136 if (cl == NULL) {
137 if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED)
138 cl = clnt_create(host, MOUNTPROG, MOUNTVERS,
139 "datagram_n");
140 if (cl == NULL) {
141 pr_err(gettext("can't contact server: %s\n"),
142 clnt_spcreateerror(host));
143 (void) __rpc_control(CLCR_SET_RPCB_TIMEOUT,
144 &rpc_totout_old);
145 return;
149 (void) __rpc_control(CLCR_SET_RPCB_TIMEOUT, &rpc_totout_old);
150 tout.tv_sec = 10;
151 tout.tv_usec = 0;
153 if (err = clnt_call(cl, MOUNTPROC_DUMP, xdr_void,
154 0, xdr_mountlist, (caddr_t)&ml, tout)) {
155 pr_err("%s\n", clnt_sperrno(err));
156 clnt_destroy(cl);
157 return;
160 if (ml == NULL)
161 return; /* no mounts */
163 if (!hflg) {
164 printf("%-8s %10s %-24s %s",
165 gettext("RESOURCE"), gettext("SERVER"),
166 gettext("PATHNAME"), gettext("CLIENTS"));
167 hflg++;
171 * Create an array describing the mounts, so that we can sort them.
173 tb = table;
174 for (; ml != NULL && tb < &table[NTABLEENTRIES]; ml = ml->ml_next)
175 *tb++ = ml;
176 if (ml != NULL && tb == &table[NTABLEENTRIES])
177 pr_err(gettext("table overflow: only %d entries shown\n"),
178 NTABLEENTRIES);
179 endtb = tb;
180 qsort(table, endtb - table, sizeof (struct mountbody *), sortpath);
183 * Print out the sorted array. Group entries for the same
184 * filesystem together, and ignore duplicate entries.
186 lastpath = "";
187 lastclient = "";
188 for (tb = table; tb < endtb; tb++) {
189 if (*((*tb)->ml_directory) == '\0' ||
190 *((*tb)->ml_hostname) == '\0')
191 continue;
192 if (strcmp(lastpath, (*tb)->ml_directory) == 0) {
193 if (strcmp(lastclient, (*tb)->ml_hostname) == 0) {
194 continue; /* ignore duplicate */
196 } else {
197 printf("\n%-8s %10s %-24s ",
198 " -", host, (*tb)->ml_directory);
199 lastpath = (*tb)->ml_directory;
200 tail = 0;
202 if (tail++)
203 printf(",");
204 printf("%s", (*tb)->ml_hostname);
205 lastclient = (*tb)->ml_hostname;
207 printf("\n");
209 freemntlist(ml);
210 clnt_destroy(cl);
213 static void
214 freemntlist(ml)
215 struct mountbody *ml;
217 register struct mountbody *old;
219 while (ml) {
220 free(ml->ml_hostname);
221 free(ml->ml_directory);
222 old = ml;
223 ml = ml->ml_next;
224 free(old);
229 * Compare two structs for mounted filesystems. The primary sort key is
230 * the name of the exported filesystem. There is also a secondary sort on
231 * the name of the client, so that duplicate entries (same path and
232 * hostname) will sort together.
234 * Returns < 0 if the first entry sorts before the second entry, 0 if they
235 * sort the same, and > 0 if the first entry sorts after the second entry.
238 static int
239 sortpath(a, b)
240 const void *a, *b;
242 const struct mountbody **m1, **m2;
243 int result;
245 m1 = (const struct mountbody **)a;
246 m2 = (const struct mountbody **)b;
248 result = strcmp((*m1)->ml_directory, (*m2)->ml_directory);
249 if (result == 0) {
250 result = strcmp((*m1)->ml_hostname, (*m2)->ml_hostname);
253 return (result);
256 static void
257 usage()
259 (void) fprintf(stderr, gettext("Usage: dfmounts [-h] [host ...]\n"));
262 /* VARARGS1 */
263 static void
264 pr_err(char *fmt, ...)
266 va_list ap;
268 va_start(ap, fmt);
269 (void) fprintf(stderr, "nfs dfmounts: ");
270 (void) vfprintf(stderr, fmt, ap);
271 va_end(ap);