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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
22 /* All Rights Reserved */
23
24
25 /*
26 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
28 */
29
30 /*
31 * generic interface to dfs commands.
32 *
33 * usage: cmd [-F fstype] [-o fs_options] [ args ]
34 *
35 * exec's /usr/lib/fs/<fstype>/<cmd>
36 * <cmd> is the basename of the command.
37 *
38 * if -F is missing, fstype is the first entry in /etc/dfs/fstypes
39 */
40
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <ctype.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <dirent.h>
48 #include <string.h>
49
50 #define DFSTYPES "/etc/dfs/fstypes" /* dfs list */
51 #define FSCMD "/usr/lib/fs/%s/%s"
52
53 #define ARGVPAD 4 /* non-[arg...] elements in new argv list: */
54 /* cmd name, -o, opts, (char *)0 terminator */
55
56 static char *getfs();
57 static int invalid();
58 void perror();
59
60 int
main(argc,argv)61 main(argc, argv)
62 int argc;
63 char **argv;
64 {
65 extern char *optarg;
66 extern int optind;
67 FILE *dfp; /* fp for dfs list */
68 int c, err = 0;
69 char subcmd[BUFSIZ]; /* fs specific command */
70 char *cmd; /* basename of this command */
71 char *fsname = NULL; /* file system name */
72 char *opts = NULL; /* -o options */
73 char **nargv; /* new argv list */
74 int nargc = 0; /* new argc */
75 static char usage[] =
76 "usage: %s [-F fstype] [-o fs_options ] [arg ...]\n";
77
78 cmd = strrchr(argv[0], '/'); /* find the basename */
79 if (cmd)
80 ++cmd;
81 else
82 cmd = argv[0];
83
84 while ((c = getopt(argc, argv, "F:o:")) != -1)
85 switch (c) {
86 case 'F':
87 err |= (fsname != NULL); /* at most one -F */
88 fsname = optarg;
89 break;
90 case 'o': /* fs specific options */
91 err |= (opts != NULL); /* at most one -o */
92 opts = optarg;
93 break;
94 case '?':
95 err = 1;
96 break;
97 }
98 if (err) {
99 (void) fprintf(stderr, usage, cmd);
100 exit(1);
101 }
102
103 if ((dfp = fopen(DFSTYPES, "r")) == NULL) {
104 (void) fprintf(stderr, "%s: cannot open %s\n",
105 cmd, DFSTYPES);
106 exit(1);
107 }
108
109 if (fsname) { /* generate fs specific command name */
110 if (invalid(fsname, dfp)) { /* valid ? */
111 (void) fprintf(stderr,
112 "%s: invalid file system name\n", cmd);
113 (void) fprintf(stderr, usage, cmd);
114 exit(1);
115 } else {
116 (void) snprintf(subcmd, sizeof (subcmd),
117 FSCMD, fsname, cmd);
118 }
119 } else if (fsname = getfs(dfp)) { /* use 1st line in dfstypes */
120 (void) snprintf(subcmd, sizeof (subcmd), FSCMD, fsname, cmd);
121 } else {
122 (void) fprintf(stderr,
123 "%s: no file systems in %s\n", cmd, DFSTYPES);
124 (void) fprintf(stderr, usage, cmd);
125 exit(1);
126 }
127
128 /* allocate a block for the new argv list */
129 if (!(nargv = (char **)malloc(sizeof (char *)*(argc-optind+ARGVPAD)))) {
130 (void) fprintf(stderr, "%s: malloc failed.\n", cmd);
131 exit(1);
132 /*NOTREACHED*/
133 }
134 nargv[nargc++] = cmd;
135 if (opts) {
136 nargv[nargc++] = "-o";
137 nargv[nargc++] = opts;
138 }
139 for (; optind <= argc; ++optind) /* this copies the last NULL */
140 nargv[nargc++] = argv[optind];
141
142 (void) execvp(subcmd, nargv);
143 perror(subcmd);
144 return (1);
145 }
146
147
148 /*
149 * invalid(name, f) - return non-zero if name is not in
150 * the list of fs names in file f
151 */
152
153 static int
invalid(name,f)154 invalid(name, f)
155 char *name; /* file system name */
156 FILE *f; /* file of list of systems */
157 {
158 char *s;
159
160 while (s = getfs(f)) /* while there's still hope ... */
161 if (strcmp(s, name) == 0)
162 return (0); /* we got it! */
163 return (1);
164 }
165
166
167 /*
168 * getfs(fp) - get the next file system name from fp
169 * ignoring lines starting with a #.
170 * All leading whitespace is discarded.
171 */
172
173 static char buf[BUFSIZ];
174
175 static char *
getfs(fp)176 getfs(fp)
177 FILE *fp;
178 {
179 char *s;
180
181 while (s = fgets(buf, BUFSIZ, fp)) {
182 while (isspace(*s)) /* leading whitespace doesn't count */
183 ++s;
184 if (*s != '#') { /* not a comment */
185 char *t = s;
186
187 while (!isspace(*t)) /* get the token */
188 ++t;
189 *t = '\0'; /* ignore rest of line */
190 return (s);
191 }
192 }
193 return (NULL); /* that's all, folks! */
194 }
195