#include <stdio.h>
#include <stdarg.h>
#include <stdlib.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 <errno.h>
#include <nfs/nfs.h>
#include <rpcsvc/mount.h>
#include <locale.h>
#include <unistd.h>
#include <clnt_subr.h>
int sorthost(const void *, const void *);
int sortpath(const void *, const void *);
void printex(CLIENT *, char *);
void usage(void);
static struct mountbody **table;
struct timeval rpc_totout_new = {15, 0};
int
main(int argc, char *argv[])
{
int aflg = 0, dflg = 0, eflg = 0;
int err;
struct mountbody *result_list = NULL;
struct mountbody *ml = NULL;
struct mountbody **tb;
char *host, hostbuf[256];
char *last;
CLIENT *cl;
int c;
struct timeval tout, rpc_totout_old;
int numentries;
(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
while ((c = getopt(argc, argv, "ade")) != EOF) {
switch (c) {
case 'a':
aflg++;
break;
case 'd':
dflg++;
break;
case 'e':
eflg++;
break;
default:
usage();
exit(1);
}
}
switch (argc - optind) {
case 0:
if (gethostname(hostbuf, sizeof (hostbuf)) < 0) {
pr_err("gethostname: %s\n", strerror(errno));
exit(1);
}
host = hostbuf;
break;
case 1:
host = argv[optind];
break;
default:
usage();
exit(1);
}
(void) __rpc_control(CLCR_GET_RPCB_TIMEOUT, &rpc_totout_old);
(void) __rpc_control(CLCR_SET_RPCB_TIMEOUT, &rpc_totout_new);
cl = mountprog_client_create(host, &rpc_totout_old);
if (cl == NULL) {
exit(1);
}
(void) __rpc_control(CLCR_SET_RPCB_TIMEOUT, &rpc_totout_old);
if (eflg) {
printex(cl, host);
if (aflg + dflg == 0) {
exit(0);
}
}
tout.tv_sec = 10;
tout.tv_usec = 0;
err = clnt_call(cl, MOUNTPROC_DUMP, xdr_void, 0, xdr_mountlist,
(caddr_t)&result_list, tout);
if (err != 0) {
pr_err("%s\n", clnt_sperrno(err));
exit(1);
}
numentries = 0;
for (ml = result_list; ml != NULL; ml = ml->ml_next)
numentries++;
if (numentries == 0)
exit(0);
table = calloc(numentries, sizeof (struct mountbody *));
if (table == NULL) {
pr_err(gettext("not enough memory for %d entries\n"),
numentries);
exit(1);
}
for (ml = result_list, tb = &table[0];
ml != NULL;
ml = ml->ml_next, tb++) {
*tb = ml;
}
if (dflg)
qsort(table, numentries, sizeof (struct mountbody *), sortpath);
else
qsort(table, numentries, sizeof (struct mountbody *), sorthost);
if (aflg) {
for (tb = table; tb < table + numentries; tb++)
printf("%s:%s\n", (*tb)->ml_hostname,
(*tb)->ml_directory);
} else if (dflg) {
last = "";
for (tb = table; tb < table + numentries; tb++) {
if (strcmp(last, (*tb)->ml_directory))
printf("%s\n", (*tb)->ml_directory);
last = (*tb)->ml_directory;
}
} else {
last = "";
for (tb = table; tb < table + numentries; tb++) {
if (strcmp(last, (*tb)->ml_hostname))
printf("%s\n", (*tb)->ml_hostname);
last = (*tb)->ml_hostname;
}
}
return (0);
}
int
sorthost(const void *_a, const void *_b)
{
struct mountbody **a = (struct mountbody **)_a;
struct mountbody **b = (struct mountbody **)_b;
return (strcmp((*a)->ml_hostname, (*b)->ml_hostname));
}
int
sortpath(const void *_a, const void *_b)
{
struct mountbody **a = (struct mountbody **)_a;
struct mountbody **b = (struct mountbody **)_b;
return (strcmp((*a)->ml_directory, (*b)->ml_directory));
}
void
usage(void)
{
(void) fprintf(stderr,
gettext("Usage: showmount [-a] [-d] [-e] [host]\n"));
}
void
pr_err(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
(void) fprintf(stderr, "showmount: ");
(void) vfprintf(stderr, fmt, ap);
va_end(ap);
}
void
printex(CLIENT *cl, char *host)
{
struct exportnode *ex = NULL;
struct exportnode *e;
struct groupnode *gr;
enum clnt_stat err;
int max;
struct timeval tout;
tout.tv_sec = 10;
tout.tv_usec = 0;
err = clnt_call(cl, MOUNTPROC_EXPORT, xdr_void, 0, xdr_exports,
(caddr_t)&ex, tout);
if (err != 0) {
pr_err("%s\n", clnt_sperrno(err));
exit(1);
}
if (ex == NULL) {
printf(gettext("no exported file systems for %s\n"), host);
} else {
printf(gettext("export list for %s:\n"), host);
}
max = 0;
for (e = ex; e != NULL; e = e->ex_next) {
if (strlen(e->ex_dir) > max) {
max = strlen(e->ex_dir);
}
}
while (ex) {
printf("%-*s ", max, ex->ex_dir);
gr = ex->ex_groups;
if (gr == NULL) {
printf(gettext("(everyone)"));
}
while (gr) {
printf("%s", gr->gr_name);
gr = gr->gr_next;
if (gr) {
printf(",");
}
}
printf("\n");
ex = ex->ex_next;
}
}