general.c revision 9521:b061a79d3d1a
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 2004 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 dfs commands.
35 *
36 *	usage:	cmd [-F fstype] [-o fs_options] [ 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 <stdlib.h>
49#include <unistd.h>
50#include <dirent.h>
51#include <string.h>
52
53#define	DFSTYPES	"/etc/dfs/fstypes"		/* dfs list */
54#define	FSCMD		"/usr/lib/fs/%s/%s"
55
56#define	ARGVPAD		4	/* non-[arg...] elements in new argv list: */
57				/* cmd name, -o, opts, (char *)0 terminator */
58
59static char *getfs();
60void perror();
61
62int
63main(argc, argv)
64int argc;
65char **argv;
66{
67	static int invalid();
68	extern char *optarg;
69	extern int optind;
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 nargc = 0;		/* new argc */
78	static char usage[] =
79		"usage: %s [-F fstype] [-o fs_options ] [arg ...]\n";
80
81	cmd = strrchr(argv[0], '/');	/* find the basename */
82	if (cmd)
83		++cmd;
84	else
85		cmd = argv[0];
86
87	while ((c = getopt(argc, argv, "F:o:")) != -1)
88		switch (c) {
89		case 'F':
90			err |= (fsname != NULL);	/* at most one -F */
91			fsname = optarg;
92			break;
93		case 'o':			/* fs specific options */
94			err |= (opts != NULL);		/* at most one -o */
95			opts = optarg;
96			break;
97		case '?':
98			err = 1;
99			break;
100		}
101	if (err) {
102		(void) fprintf(stderr, usage, cmd);
103		exit(1);
104	}
105
106	if ((dfp = fopen(DFSTYPES, "r")) == NULL) {
107		(void) fprintf(stderr, "%s: cannot open %s\n",
108			cmd, DFSTYPES);
109		exit(1);
110	}
111
112	if (fsname) {		/* generate fs specific command name */
113		if (invalid(fsname, dfp)) {	/* valid ? */
114			(void) fprintf(stderr,
115			    "%s: invalid file system name\n", cmd);
116			(void) fprintf(stderr, usage, cmd);
117			exit(1);
118		} else {
119			(void) snprintf(subcmd, sizeof (subcmd),
120			    FSCMD, fsname, cmd);
121		}
122	} else if (fsname = getfs(dfp)) {	/* use 1st line in dfstypes */
123		(void) snprintf(subcmd, sizeof (subcmd), FSCMD, fsname, cmd);
124	} else {
125		(void) fprintf(stderr,
126		    "%s: no file systems in %s\n", cmd, DFSTYPES);
127		(void) fprintf(stderr, usage, cmd);
128		exit(1);
129	}
130
131	/* allocate a block for the new argv list */
132	if (!(nargv = (char **)malloc(sizeof (char *)*(argc-optind+ARGVPAD)))) {
133		(void) fprintf(stderr, "%s: malloc failed.\n", cmd);
134		exit(1);
135		/*NOTREACHED*/
136	}
137	nargv[nargc++] = cmd;
138	if (opts) {
139		nargv[nargc++] = "-o";
140		nargv[nargc++] = opts;
141	}
142	for (; optind <= argc; ++optind)	/* this copies the last NULL */
143		nargv[nargc++] = argv[optind];
144
145	(void) execvp(subcmd, nargv);
146	perror(subcmd);
147	return (1);
148}
149
150
151/*
152 *	invalid(name, f)  -  return non-zero if name is not in
153 *			     the list of fs names in file f
154 */
155
156static int
157invalid(name, f)
158char *name;		/* file system name */
159FILE *f;		/* file of list of systems */
160{
161	char *s;
162
163	while (s = getfs(f))	/* while there's still hope ... */
164		if (strcmp(s, name) == 0)
165			return (0);	/* we got it! */
166	return (1);
167}
168
169
170/*
171 *	getfs(fp) - get the next file system name from fp
172 *		ignoring lines starting with a #.
173 *		All leading whitespace is discarded.
174 */
175
176static char buf[BUFSIZ];
177
178static char *
179getfs(fp)
180FILE *fp;
181{
182	char *s;
183
184	while (s = fgets(buf, BUFSIZ, fp)) {
185		while (isspace(*s))	/* leading whitespace doesn't count */
186			++s;
187		if (*s != '#') {	/* not a comment */
188			char *t = s;
189
190			while (!isspace(*t))	/* get the token */
191				++t;
192			*t = '\0';		/* ignore rest of line */
193			return (s);
194		}
195	}
196	return (NULL);	/* that's all, folks! */
197}
198