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 dfshares, dfmounts. 35 * 36 * usage: dfshares [-F fstype] [-o fs_options] [-h] [ 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 <dirent.h> 49 #include <string.h> 50 #include <errno.h> 51 #include <unistd.h> 52 #include <wait.h> 53 #include <stdlib.h> 54 55 #define DFSTYPES "/etc/dfs/fstypes" /* dfs list */ 56 #define FSCMD "/usr/lib/fs/%s/%s" 57 58 /* 59 * non-[arg...] elements in new argv list: 60 * cmd name, , -h, -o, opts, (char *)0 terminator 61 */ 62 #define ARGVPAD 5 63 64 static char *getfs(FILE *); 65 static int invalid(const char *, FILE *); 66 67 main(int argc, char **argv) 68 { 69 FILE *dfp; /* fp for dfs list */ 70 int c, err = 0; 71 char subcmd[BUFSIZ]; /* fs specific command */ 72 char *cmd; /* basename of this command */ 73 char *fsname = NULL; /* file system name */ 74 char *opts = NULL; /* -o options */ 75 char **nargv; /* new argv list */ 76 int hflag = 0; 77 int nargc = 0; /* new argc */ 78 pid_t pid; /* pid for fork */ 79 int retval; /* exit status from exec'd commad */ 80 int showall = (argc <= 1); /* show all resources */ 81 static char usage[] = 82 "usage: %s [-F fstype] [-h] [-o fs_options ] [arg ...]\n"; 83 84 cmd = strrchr(argv[0], '/'); /* find the basename */ 85 if (cmd) 86 ++cmd; 87 else 88 cmd = argv[0]; 89 90 while ((c = getopt(argc, argv, "hF:o:")) != -1) 91 switch (c) { 92 case 'h': 93 hflag = 1; /* no header ... pass to subcommand */ 94 break; 95 case 'F': 96 err |= (fsname != NULL); /* at most one -F */ 97 fsname = optarg; 98 break; 99 case 'o': /* fs specific options */ 100 err |= (opts != NULL); /* at most one -o */ 101 opts = optarg; 102 break; 103 case '?': 104 err = 1; 105 break; 106 } 107 if (err) { 108 (void) fprintf(stderr, usage, cmd); 109 exit(1); 110 } 111 112 if ((dfp = fopen(DFSTYPES, "r")) == NULL) { 113 (void) fprintf(stderr, "%s: cannot open %s\n", cmd, DFSTYPES); 114 exit(1); 115 } 116 117 /* allocate a block for the new argv list */ 118 if (!(nargv = (char **)malloc(sizeof (char *)*(argc-optind+ARGVPAD)))) { 119 (void) fprintf(stderr, "%s: malloc failed.\n", cmd); 120 exit(1); 121 } 122 nargv[nargc++] = cmd; 123 if (hflag) 124 nargv[nargc++] = "-h"; 125 if (opts) { 126 nargv[nargc++] = "-o"; 127 nargv[nargc++] = opts; 128 } 129 for (; optind <= argc; ++optind) /* this copies the last NULL */ 130 nargv[nargc++] = argv[optind]; 131 132 if (showall) { /* command with no args -- show all dfs's */ 133 while (fsname = getfs(dfp)) { 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 } 164 else 165 exit(err); 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)) /* 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 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)) /* 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 * 220 getfs(FILE *fp) 221 { 222 register char *s; 223 224 while (s = fgets(buf, BUFSIZ, fp)) { 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