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 59 static char *getfs(); 60 void perror(); 61 62 int 63 main(argc, argv) 64 int argc; 65 char **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 156 static int 157 invalid(name, f) 158 char *name; /* file system name */ 159 FILE *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 176 static char buf[BUFSIZ]; 177 178 static char * 179 getfs(fp) 180 FILE *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