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 #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 int 68 main(int argc, char **argv) 69 { 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 hflag = 0; 78 int nargc = 0; /* new argc */ 79 pid_t pid; /* pid for fork */ 80 int retval; /* exit status from exec'd commad */ 81 int showall = (argc <= 1); /* show all resources */ 82 static char usage[] = 83 "usage: %s [-F fstype] [-h] [-o fs_options ] [arg ...]\n"; 84 85 cmd = strrchr(argv[0], '/'); /* find the basename */ 86 if (cmd) 87 ++cmd; 88 else 89 cmd = argv[0]; 90 91 while ((c = getopt(argc, argv, "hF:o:")) != -1) 92 switch (c) { 93 case 'h': 94 hflag = 1; /* no header ... pass to subcommand */ 95 break; 96 case 'F': 97 err |= (fsname != NULL); /* at most one -F */ 98 fsname = optarg; 99 break; 100 case 'o': /* fs specific options */ 101 err |= (opts != NULL); /* at most one -o */ 102 opts = optarg; 103 break; 104 case '?': 105 err = 1; 106 break; 107 } 108 if (err) { 109 (void) fprintf(stderr, usage, cmd); 110 exit(1); 111 } 112 113 if ((dfp = fopen(DFSTYPES, "r")) == NULL) { 114 (void) fprintf(stderr, "%s: cannot open %s\n", cmd, DFSTYPES); 115 exit(1); 116 } 117 118 /* allocate a block for the new argv list */ 119 if (!(nargv = (char **)malloc(sizeof (char *)*(argc-optind+ARGVPAD)))) { 120 (void) fprintf(stderr, "%s: malloc failed.\n", cmd); 121 exit(1); 122 } 123 nargv[nargc++] = cmd; 124 if (hflag) 125 nargv[nargc++] = "-h"; 126 if (opts) { 127 nargv[nargc++] = "-o"; 128 nargv[nargc++] = opts; 129 } 130 for (; optind <= argc; ++optind) /* this copies the last NULL */ 131 nargv[nargc++] = argv[optind]; 132 133 if (showall) { /* command with no args -- show all dfs's */ 134 while (fsname = getfs(dfp)) { 135 (void) snprintf(subcmd, sizeof (subcmd), 136 FSCMD, fsname, cmd); 137 switch (pid = fork()) { /* do the subcommand */ 138 case 0: 139 (void) execvp(subcmd, nargv); 140 if (errno != ENOENT) 141 perror(subcmd); 142 _exit(1); 143 /*NOTREACHED*/ 144 default: 145 while (wait(&retval) != pid) 146 ; 147 /* take exit status into account */ 148 err |= (retval & 0xff00) >> 8; 149 break; 150 case -1: 151 (void) fprintf(stderr, 152 "%s: fork failed - try again later.\n", 153 cmd); 154 exit(1); 155 } 156 } 157 (void) fclose(dfp); 158 if (pid == 0) { /* we never got into the loop! */ 159 (void) fprintf(stderr, 160 "%s: no file systems in %s\n", 161 cmd, DFSTYPES); 162 (void) fprintf(stderr, usage, cmd); 163 exit(1); 164 } 165 else 166 exit(err); 167 } 168 169 if (fsname) { /* generate fs specific command name */ 170 if (invalid(fsname, dfp)) { /* valid ? */ 171 (void) fprintf(stderr, 172 "%s: invalid file system name\n", cmd); 173 (void) fprintf(stderr, usage, cmd); 174 exit(1); 175 } 176 else 177 (void) snprintf(subcmd, sizeof (subcmd), 178 FSCMD, fsname, cmd); 179 } else if (fsname = getfs(dfp)) /* use 1st line in dfstypes */ 180 (void) snprintf(subcmd, sizeof (subcmd), FSCMD, fsname, cmd); 181 else { 182 (void) fprintf(stderr, 183 "%s: no file systems in %s\n", cmd, DFSTYPES); 184 (void) fprintf(stderr, usage, cmd); 185 exit(1); 186 } 187 188 (void) execvp(subcmd, nargv); 189 perror(subcmd); /* execvp failed */ 190 return (1); 191 } 192 193 194 /* 195 * invalid(name, f) - return non-zero if name is not in 196 * the list of fs names in file f 197 */ 198 199 static int 200 invalid(const char *name, /* file system name */ 201 FILE *f) /* file of list of file system types */ 202 { 203 char *s; 204 205 while (s = getfs(f)) /* while there's still hope ... */ 206 if (strcmp(s, name) == 0) 207 return (0); /* we got it! */ 208 return (1); 209 } 210 211 212 /* 213 * getfs(fp) - get the next file system name from fp 214 * ignoring lines starting with a #. 215 * All leading whitespace is discarded. 216 */ 217 218 static char buf[BUFSIZ]; 219 220 static char * 221 getfs(FILE *fp) 222 { 223 register char *s; 224 225 while (s = fgets(buf, BUFSIZ, fp)) { 226 while (isspace(*s)) /* leading whitespace doesn't count */ 227 ++s; 228 if (*s != '#') { /* not a comment */ 229 char *t = s; 230 231 while (!isspace(*t)) /* get the token */ 232 ++t; 233 *t = '\0'; /* ignore rest of line */ 234 return (s); 235 } 236 } 237 return (NULL); /* that's all, folks! */ 238 } 239