#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <wait.h>
#include <stdlib.h>
#define DFSTYPES "/etc/dfs/fstypes"
#define FSCMD "/usr/lib/fs/%s/%s"
#define ARGVPAD 5
static char *getfs(FILE *);
static int invalid(const char *, FILE *);
int
main(int argc, char **argv)
{
FILE *dfp;
int c, err = 0;
char subcmd[BUFSIZ];
char *cmd;
char *fsname = NULL;
char *opts = NULL;
char **nargv;
int hflag = 0;
int nargc = 0;
pid_t pid;
int retval;
int showall = (argc <= 1);
static char usage[] =
"usage: %s [-F fstype] [-h] [-o fs_options ] [arg ...]\n";
cmd = strrchr(argv[0], '/');
if (cmd)
++cmd;
else
cmd = argv[0];
while ((c = getopt(argc, argv, "hF:o:")) != -1)
switch (c) {
case 'h':
hflag = 1;
break;
case 'F':
err |= (fsname != NULL);
fsname = optarg;
break;
case 'o':
err |= (opts != NULL);
opts = optarg;
break;
case '?':
err = 1;
break;
}
if (err) {
(void) fprintf(stderr, usage, cmd);
exit(1);
}
if ((dfp = fopen(DFSTYPES, "r")) == NULL) {
(void) fprintf(stderr, "%s: cannot open %s\n", cmd, DFSTYPES);
exit(1);
}
if (!(nargv = (char **)malloc(sizeof (char *)*(argc-optind+ARGVPAD)))) {
(void) fprintf(stderr, "%s: malloc failed.\n", cmd);
exit(1);
}
nargv[nargc++] = cmd;
if (hflag)
nargv[nargc++] = "-h";
if (opts) {
nargv[nargc++] = "-o";
nargv[nargc++] = opts;
}
for (; optind <= argc; ++optind)
nargv[nargc++] = argv[optind];
if (showall) {
pid = 0;
while ((fsname = getfs(dfp)) != NULL) {
(void) snprintf(subcmd, sizeof (subcmd),
FSCMD, fsname, cmd);
switch (pid = fork()) {
case 0:
(void) execvp(subcmd, nargv);
if (errno != ENOENT)
perror(subcmd);
_exit(1);
default:
while (wait(&retval) != pid)
;
err |= (retval & 0xff00) >> 8;
break;
case -1:
(void) fprintf(stderr,
"%s: fork failed - try again later.\n",
cmd);
exit(1);
}
}
(void) fclose(dfp);
if (pid == 0) {
(void) fprintf(stderr,
"%s: no file systems in %s\n",
cmd, DFSTYPES);
(void) fprintf(stderr, usage, cmd);
exit(1);
} else {
exit(err);
}
}
if (fsname) {
if (invalid(fsname, dfp)) {
(void) fprintf(stderr,
"%s: invalid file system name\n", cmd);
(void) fprintf(stderr, usage, cmd);
exit(1);
}
else
(void) snprintf(subcmd, sizeof (subcmd),
FSCMD, fsname, cmd);
} else if ((fsname = getfs(dfp)) != NULL)
(void) snprintf(subcmd, sizeof (subcmd), FSCMD, fsname, cmd);
else {
(void) fprintf(stderr,
"%s: no file systems in %s\n", cmd, DFSTYPES);
(void) fprintf(stderr, usage, cmd);
exit(1);
}
(void) execvp(subcmd, nargv);
perror(subcmd);
return (1);
}
static int
invalid(const char *name,
FILE *f)
{
char *s;
while ((s = getfs(f)) != NULL)
if (strcmp(s, name) == 0)
return (0);
return (1);
}
static char buf[BUFSIZ];
static char *
getfs(FILE *fp)
{
char *s;
while ((s = fgets(buf, BUFSIZ, fp)) != NULL) {
while (isspace(*s))
++s;
if (*s != '#') {
char *t = s;
while (!isspace(*t))
++t;
*t = '\0';
return (s);
}
}
return (NULL);
}