1 /*
2 * CDDL HEADER START
3 *
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.
8 *
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.
13 *
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]
19 *
20 * CDDL HEADER END
21 */
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
24
25
26 /*
27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
29 */
30
31 #pragma ident "%Z%%M% %I% %E% SMI"
32
33 /*
34 * generic interface to dfshares, dfmounts.
35 *
36 * usage: dfshares [-F fstype] [-o fs_options] [-h] [ args ]
37 *
38 * exec's /usr/lib/fs/<fstype>/<cmd>
39 * <cmd> is the basename of the command.
40 *
41 * if -F is missing, fstype is the first entry in /etc/dfs/fstypes
42 */
43
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <ctype.h>
47 #include <stdio.h>
48 #include <dirent.h>
49 #include <string.h>
50 #include <errno.h>
51 #include <unistd.h>
52 #include <wait.h>
53 #include <stdlib.h>
54
55 #define DFSTYPES "/etc/dfs/fstypes" /* dfs list */
56 #define FSCMD "/usr/lib/fs/%s/%s"
57
58 /*
59 * non-[arg...] elements in new argv list:
60 * cmd name, , -h, -o, opts, (char *)0 terminator
61 */
62 #define ARGVPAD 5
63
64 static char *getfs(FILE *);
65 static int invalid(const char *, FILE *);
66
67 int
main(int argc,char ** argv)68 main(int argc, char **argv)
69 {
70 FILE *dfp; /* fp for dfs list */
71 int c, err = 0;
72 char subcmd[BUFSIZ]; /* fs specific command */
73 char *cmd; /* basename of this command */
74 char *fsname = NULL; /* file system name */
75 char *opts = NULL; /* -o options */
76 char **nargv; /* new argv list */
77 int hflag = 0;
78 int nargc = 0; /* new argc */
79 pid_t pid; /* pid for fork */
80 int retval; /* exit status from exec'd commad */
81 int showall = (argc <= 1); /* show all resources */
82 static char usage[] =
83 "usage: %s [-F fstype] [-h] [-o fs_options ] [arg ...]\n";
84
85 cmd = strrchr(argv[0], '/'); /* find the basename */
86 if (cmd)
87 ++cmd;
88 else
89 cmd = argv[0];
90
91 while ((c = getopt(argc, argv, "hF:o:")) != -1)
92 switch (c) {
93 case 'h':
94 hflag = 1; /* no header ... pass to subcommand */
95 break;
96 case 'F':
97 err |= (fsname != NULL); /* at most one -F */
98 fsname = optarg;
99 break;
100 case 'o': /* fs specific options */
101 err |= (opts != NULL); /* at most one -o */
102 opts = optarg;
103 break;
104 case '?':
105 err = 1;
106 break;
107 }
108 if (err) {
109 (void) fprintf(stderr, usage, cmd);
110 exit(1);
111 }
112
113 if ((dfp = fopen(DFSTYPES, "r")) == NULL) {
114 (void) fprintf(stderr, "%s: cannot open %s\n", cmd, DFSTYPES);
115 exit(1);
116 }
117
118 /* allocate a block for the new argv list */
119 if (!(nargv = (char **)malloc(sizeof (char *)*(argc-optind+ARGVPAD)))) {
120 (void) fprintf(stderr, "%s: malloc failed.\n", cmd);
121 exit(1);
122 }
123 nargv[nargc++] = cmd;
124 if (hflag)
125 nargv[nargc++] = "-h";
126 if (opts) {
127 nargv[nargc++] = "-o";
128 nargv[nargc++] = opts;
129 }
130 for (; optind <= argc; ++optind) /* this copies the last NULL */
131 nargv[nargc++] = argv[optind];
132
133 if (showall) { /* command with no args -- show all dfs's */
134 while (fsname = getfs(dfp)) {
135 (void) snprintf(subcmd, sizeof (subcmd),
136 FSCMD, fsname, cmd);
137 switch (pid = fork()) { /* do the subcommand */
138 case 0:
139 (void) execvp(subcmd, nargv);
140 if (errno != ENOENT)
141 perror(subcmd);
142 _exit(1);
143 /*NOTREACHED*/
144 default:
145 while (wait(&retval) != pid)
146 ;
147 /* take exit status into account */
148 err |= (retval & 0xff00) >> 8;
149 break;
150 case -1:
151 (void) fprintf(stderr,
152 "%s: fork failed - try again later.\n",
153 cmd);
154 exit(1);
155 }
156 }
157 (void) fclose(dfp);
158 if (pid == 0) { /* we never got into the loop! */
159 (void) fprintf(stderr,
160 "%s: no file systems in %s\n",
161 cmd, DFSTYPES);
162 (void) fprintf(stderr, usage, cmd);
163 exit(1);
164 }
165 else
166 exit(err);
167 }
168
169 if (fsname) { /* generate fs specific command name */
170 if (invalid(fsname, dfp)) { /* valid ? */
171 (void) fprintf(stderr,
172 "%s: invalid file system name\n", cmd);
173 (void) fprintf(stderr, usage, cmd);
174 exit(1);
175 }
176 else
177 (void) snprintf(subcmd, sizeof (subcmd),
178 FSCMD, fsname, cmd);
179 } else if (fsname = getfs(dfp)) /* use 1st line in dfstypes */
180 (void) snprintf(subcmd, sizeof (subcmd), FSCMD, fsname, cmd);
181 else {
182 (void) fprintf(stderr,
183 "%s: no file systems in %s\n", cmd, DFSTYPES);
184 (void) fprintf(stderr, usage, cmd);
185 exit(1);
186 }
187
188 (void) execvp(subcmd, nargv);
189 perror(subcmd); /* execvp failed */
190 return (1);
191 }
192
193
194 /*
195 * invalid(name, f) - return non-zero if name is not in
196 * the list of fs names in file f
197 */
198
199 static int
invalid(const char * name,FILE * f)200 invalid(const char *name, /* file system name */
201 FILE *f) /* file of list of file system types */
202 {
203 char *s;
204
205 while (s = getfs(f)) /* while there's still hope ... */
206 if (strcmp(s, name) == 0)
207 return (0); /* we got it! */
208 return (1);
209 }
210
211
212 /*
213 * getfs(fp) - get the next file system name from fp
214 * ignoring lines starting with a #.
215 * All leading whitespace is discarded.
216 */
217
218 static char buf[BUFSIZ];
219
220 static char *
getfs(FILE * fp)221 getfs(FILE *fp)
222 {
223 register char *s;
224
225 while (s = fgets(buf, BUFSIZ, fp)) {
226 while (isspace(*s)) /* leading whitespace doesn't count */
227 ++s;
228 if (*s != '#') { /* not a comment */
229 char *t = s;
230
231 while (!isspace(*t)) /* get the token */
232 ++t;
233 *t = '\0'; /* ignore rest of line */
234 return (s);
235 }
236 }
237 return (NULL); /* that's all, folks! */
238 }
239