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