/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* University Copyright- Copyright (c) 1982, 1986, 1988
* The Regents of the University of California
* All Rights Reserved
*
* University Acknowledgment- Portions of this document are derived from
* software developed by the University of California, Berkeley, and its
* contributors.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* nfs dfshares
*/
#include <stdio.h>
#include <string.h>
#include <rpc/rpc.h>
#include <rpc/rpcb_clnt.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/time.h>
#include <sys/errno.h>
#include <nfs/nfs.h>
#include <rpcsvc/mount.h>
int hflg;
void pr_exports();
void free_ex();
void usage();
int
main(int argc, char *argv[])
{
char hostbuf[256];
extern int optind;
extern char *optarg;
int i, c;
while ((c = getopt(argc, argv, "h")) != EOF) {
switch (c) {
case 'h':
hflg++;
break;
default:
usage();
exit(1);
}
}
if (optind < argc) {
for (i = optind; i < argc; i++)
pr_exports(argv[i]);
} else {
if (gethostname(hostbuf, sizeof (hostbuf)) < 0) {
perror("nfs dfshares: gethostname");
exit(1);
}
pr_exports(hostbuf);
}
return (0);
}
struct timeval rpc_totout_new = {15, 0};
void
pr_exports(host)
char *host;
{
CLIENT *cl;
struct exportnode *ex = NULL;
enum clnt_stat err;
struct timeval tout, rpc_totout_old;
(void) __rpc_control(CLCR_GET_RPCB_TIMEOUT, &rpc_totout_old);
(void) __rpc_control(CLCR_SET_RPCB_TIMEOUT, &rpc_totout_new);
/*
* First try circuit, then drop back to datagram if
* circuit is unavailable (an old version of mountd perhaps)
* Using circuit is preferred because it can handle
* arbitrarily long export lists.
*/
cl = clnt_create(host, MOUNTPROG, MOUNTVERS, "circuit_n");
if (cl == NULL) {
if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED)
cl = clnt_create(host, MOUNTPROG, MOUNTVERS,
"datagram_n");
if (cl == NULL) {
(void) fprintf(stderr, "nfs dfshares:");
clnt_pcreateerror(host);
(void) __rpc_control(CLCR_SET_RPCB_TIMEOUT,
&rpc_totout_old);
exit(1);
}
}
(void) __rpc_control(CLCR_SET_RPCB_TIMEOUT, &rpc_totout_old);
tout.tv_sec = 10;
tout.tv_usec = 0;
if (err = clnt_call(cl, MOUNTPROC_EXPORT, xdr_void,
0, xdr_exports, (caddr_t)&ex, tout)) {
(void) fprintf(stderr, "nfs dfshares: %s\n", clnt_sperrno(err));
clnt_destroy(cl);
exit(1);
}
if (ex == NULL) {
clnt_destroy(cl);
exit(1);
}
if (!hflg) {
printf("%-35s %12s %-8s %s\n",
"RESOURCE", "SERVER", "ACCESS", "TRANSPORT");
hflg++;
}
while (ex) {
printf("%10s:%-24s %12s %-8s %s\n",
host, ex->ex_dir, host, " -", " -");
ex = ex->ex_next;
}
free_ex(ex);
clnt_destroy(cl);
}
void
free_ex(ex)
struct exportnode *ex;
{
struct groupnode *gr, *tmpgr;
struct exportnode *tmpex;
while (ex) {
free(ex->ex_dir);
gr = ex->ex_groups;
while (gr) {
tmpgr = gr->gr_next;
free((char *)gr);
gr = tmpgr;
}
tmpex = ex;
ex = ex->ex_next;
free((char *)tmpex);
}
}
void
usage()
{
(void) fprintf(stderr, "Usage: dfshares [-h] [host ...]\n");
}