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 while (fsname = getfs(dfp)) {
133 (void) snprintf(subcmd, sizeof (subcmd),
134 FSCMD, fsname, cmd);
135 switch (pid = fork()) { /* do the subcommand */
136 case 0:
137 (void) execvp(subcmd, nargv);
138 if (errno != ENOENT)
139 perror(subcmd);
140 _exit(1);
141 /*NOTREACHED*/
142 default:
143 while (wait(&retval) != pid)
144 ;
145 /* take exit status into account */
146 err |= (retval & 0xff00) >> 8;
147 break;
148 case -1:
149 (void) fprintf(stderr,
150 "%s: fork failed - try again later.\n",
151 cmd);
152 exit(1);
153 }
154 }
155 (void) fclose(dfp);
156 if (pid == 0) { /* we never got into the loop! */
157 (void) fprintf(stderr,
158 "%s: no file systems in %s\n",
159 cmd, DFSTYPES);
160 (void) fprintf(stderr, usage, cmd);
161 exit(1);
162 }
163 else
164 exit(err);
165 }
166
167 if (fsname) { /* generate fs specific command name */
168 if (invalid(fsname, dfp)) { /* valid ? */
169 (void) fprintf(stderr,
170 "%s: invalid file system name\n", cmd);
171 (void) fprintf(stderr, usage, cmd);
172 exit(1);
173 }
174 else
175 (void) snprintf(subcmd, sizeof (subcmd),
176 FSCMD, fsname, cmd);
177 } else if (fsname = getfs(dfp)) /* use 1st line in dfstypes */
178 (void) snprintf(subcmd, sizeof (subcmd), FSCMD, fsname, cmd);
179 else {
180 (void) fprintf(stderr,
181 "%s: no file systems in %s\n", cmd, DFSTYPES);
182 (void) fprintf(stderr, usage, cmd);
183 exit(1);
184 }
185
186 (void) execvp(subcmd, nargv);
187 perror(subcmd); /* execvp failed */
188 return (1);
189 }
190
191
192 /*
193 * invalid(name, f) - return non-zero if name is not in
194 * the list of fs names in file f
195 */
196
197 static int
invalid(const char * name,FILE * f)198 invalid(const char *name, /* file system name */
199 FILE *f) /* file of list of file system types */
200 {
201 char *s;
202
203 while (s = getfs(f)) /* while there's still hope ... */
204 if (strcmp(s, name) == 0)
205 return (0); /* we got it! */
206 return (1);
207 }
208
209
210 /*
211 * getfs(fp) - get the next file system name from fp
212 * ignoring lines starting with a #.
213 * All leading whitespace is discarded.
214 */
215
216 static char buf[BUFSIZ];
217
218 static char *
getfs(FILE * fp)219 getfs(FILE *fp)
220 {
221 register char *s;
222
223 while (s = fgets(buf, BUFSIZ, fp)) {
224 while (isspace(*s)) /* leading whitespace doesn't count */
225 ++s;
226 if (*s != '#') { /* not a comment */
227 char *t = s;
228
229 while (!isspace(*t)) /* get the token */
230 ++t;
231 *t = '\0'; /* ignore rest of line */
232 return (s);
233 }
234 }
235 return (NULL); /* that's all, folks! */
236 }
237