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