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 pid = 0; 133 while ((fsname = getfs(dfp)) != NULL) { 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 } else { 164 exit(err); 165 } 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)) != NULL) /* 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)) != NULL) /* 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 char *s; 223 224 while ((s = fgets(buf, BUFSIZ, fp)) != NULL) { 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