121156Sdist /* 261503Sbostic * Copyright (c) 1980, 1989, 1993 361503Sbostic * The Regents of the University of California. All rights reserved. 439322Smckusick * 542702Sbostic * %sccs.include.redist.c% 621156Sdist */ 721156Sdist 810811Ssam #ifndef lint 961503Sbostic static char copyright[] = 1061503Sbostic "@(#) Copyright (c) 1980, 1989, 1993\n\ 1161503Sbostic The Regents of the University of California. All rights reserved.\n"; 1239322Smckusick #endif /* not lint */ 131057Sbill 1421156Sdist #ifndef lint 15*66133Spendry static char sccsid[] = "@(#)mount.c 8.9 (Berkeley) 02/17/94"; 1639322Smckusick #endif /* not lint */ 1721156Sdist 1866131Spendry 1966131Spendry #include <stdio.h> 2066131Spendry #include <stdlib.h> 2166131Spendry #include <unistd.h> 2266131Spendry #include <string.h> 2366131Spendry #include <errno.h> 2466131Spendry #include <signal.h> 2566131Spendry #include <fstab.h> 2612808Ssam #include <sys/param.h> 2739133Smckusick #include <sys/wait.h> 2838445Smckusick #include <sys/mount.h> 2945524Sbostic #include "pathnames.h" 301057Sbill 3140369Smckusick #define DEFAULT_ROOTUID -2 3240369Smckusick 3335339Sbostic #define BADTYPE(type) \ 3435339Sbostic (strcmp(type, FSTAB_RO) && strcmp(type, FSTAB_RW) && \ 3535339Sbostic strcmp(type, FSTAB_RQ)) 3635339Sbostic #define SETTYPE(type) \ 3735339Sbostic (!strcmp(type, FSTAB_RW) || !strcmp(type, FSTAB_RQ)) 381057Sbill 3956841Smckusick int debug, force, verbose, updateflg, mnttype; 4066130Spendry char *mntname; 4166130Spendry char **vfslist; 4266130Spendry static int badvfstype __P((int, char **)); 4366130Spendry static int badvfsname __P((char *, char **)); 4466130Spendry static int getexecopts __P((char *, char **)); 4566130Spendry static struct statfs *getmntpt __P((char *)); 4666130Spendry static int getmnttype __P((char *)); 4766130Spendry static void getstdopts __P((char *, int *)); 4866130Spendry static void getufsopts __P((char *, int *)); 4966130Spendry static char **makevfslist __P((char *)); 5066130Spendry static int mountfs __P((char *, char *, int, char *, char *, char *)); 5166130Spendry static void prmount __P((char *, char *, int)); 5266130Spendry static void usage __P((void)); 5339131Smckusick 5466130Spendry int 5566130Spendry main(argc, argv) 565073Sroot int argc; 575073Sroot char **argv; 581057Sbill { 5966130Spendry struct fstab *fs; 6040496Smckusick int all, ch, rval, flags, ret, pid, i; 6138632Smckusick long mntsize; 6266130Spendry struct statfs *mntbuf; 6339131Smckusick char *type, *options = NULL; 6440496Smckusick FILE *pidfile; 651057Sbill 6635339Sbostic all = 0; 6735339Sbostic type = NULL; 6838445Smckusick mnttype = MOUNT_UFS; 6939322Smckusick mntname = "ufs"; 7056841Smckusick while ((ch = getopt(argc, argv, "adfrwuvt:o:")) != EOF) 7135339Sbostic switch((char)ch) { 7235339Sbostic case 'a': 7335339Sbostic all = 1; 7435339Sbostic break; 7556841Smckusick case 'd': 7656841Smckusick debug = 1; 7756841Smckusick break; 7835339Sbostic case 'f': 7956841Smckusick force = 1; 8035339Sbostic break; 8135339Sbostic case 'r': 8212808Ssam type = FSTAB_RO; 8335339Sbostic break; 8439333Smckusick case 'u': 8541403Smckusick updateflg = MNT_UPDATE; 8639333Smckusick break; 8735339Sbostic case 'v': 8835339Sbostic verbose = 1; 8935339Sbostic break; 9035339Sbostic case 'w': 9135339Sbostic type = FSTAB_RW; 9235339Sbostic break; 9339131Smckusick case 'o': 9439131Smckusick options = optarg; 9539131Smckusick break; 9638445Smckusick case 't': 9740051Smckusick vfslist = makevfslist(optarg); 9839322Smckusick mnttype = getmnttype(optarg); 9939322Smckusick break; 10035339Sbostic case '?': 10135339Sbostic default: 10235339Sbostic usage(); 10339131Smckusick /* NOTREACHED */ 1045073Sroot } 10535339Sbostic argc -= optind; 10635339Sbostic argv += optind; 10735339Sbostic 10835339Sbostic /* NOSTRICT */ 10935339Sbostic 1104460Sroot if (all) { 11135369Sbostic rval = 0; 11239333Smckusick while (fs = getfsent()) { 11335372Sbostic if (BADTYPE(fs->fs_type)) 11435372Sbostic continue; 11540844Smckusick if (badvfsname(fs->fs_vfstype, vfslist)) 11640051Smckusick continue; 11735372Sbostic /* `/' is special, it's always mounted */ 11839333Smckusick mnttype = getmnttype(fs->fs_vfstype); 11966131Spendry rval |= mountfs(fs->fs_spec, fs->fs_file, updateflg, 12039333Smckusick type, options, fs->fs_mntops); 12135372Sbostic } 12235341Sbostic exit(rval); 12335339Sbostic } 1245073Sroot 12535339Sbostic if (argc == 0) { 12656841Smckusick if (verbose || debug || type) 12735339Sbostic usage(); 12840337Smckusick if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) { 12966131Spendry errx(1, "cannot get mount information"); 13038632Smckusick } 13140844Smckusick for (i = 0; i < mntsize; i++) { 13240844Smckusick if (badvfstype(mntbuf[i].f_type, vfslist)) 13340844Smckusick continue; 13438632Smckusick prmount(mntbuf[i].f_mntfromname, mntbuf[i].f_mntonname, 13539316Smckusick mntbuf[i].f_flags); 13640844Smckusick } 1374460Sroot exit(0); 1381057Sbill } 13912808Ssam 14066131Spendry if (argc == 1 && vfslist) { 14166131Spendry usage(); 14266131Spendry } 14366131Spendry 14439465Smckusick if (argc == 1 && updateflg) { 14539465Smckusick if ((mntbuf = getmntpt(*argv)) == NULL) { 14666131Spendry errx(1, "unknown special file or file system %s.", 14739465Smckusick *argv); 14839465Smckusick } 14939465Smckusick mnttype = mntbuf->f_type; 15053711Smckusick if ((fs = getfsfile(mntbuf->f_mntonname)) == NULL) { 15166131Spendry errx(1, "can't find fstab entry for %s.", *argv); 15240124Smckusick } 15353711Smckusick mntname = fs->fs_vfstype; 15453711Smckusick 15553711Smckusick /* 15653711Smckusick * Default type to fstab version if none specified on the 15753711Smckusick * command line. 15853711Smckusick */ 15953711Smckusick if (type == NULL) 16053711Smckusick type = fs->fs_type; 16153711Smckusick 16253711Smckusick /* 16353711Smckusick * Default options to fstab version if none specified on the 16453711Smckusick * command line. 16553711Smckusick */ 16653711Smckusick if (options == NULL) 16753711Smckusick options = fs->fs_mntops; 16853711Smckusick else { 16966130Spendry char *cp; 17053711Smckusick 17153711Smckusick /* 17253711Smckusick * Concat the two strings with the command line 17353711Smckusick * options last so that they will override the 17453711Smckusick * fstab options. 17553711Smckusick */ 17653711Smckusick i = strlen(fs->fs_mntops) + strlen(options) + 2; 17753711Smckusick if ((cp = malloc((size_t)i)) == NULL) { 17866131Spendry errx(1, "-u malloc failed"); 17953711Smckusick } 18053711Smckusick sprintf(cp, "%s,%s", fs->fs_mntops, options); 18153711Smckusick options = cp; 18253711Smckusick } 18353711Smckusick ret = mountfs(fs->fs_spec, mntbuf->f_mntonname, 18442253Sbostic updateflg, type, options, (char *)NULL); 18540496Smckusick } else if (argc == 1) { 18635339Sbostic if (!(fs = getfsfile(*argv)) && !(fs = getfsspec(*argv))) { 18766131Spendry errx(1, "unknown special file or file system %s.\n", 18835339Sbostic *argv); 18935339Sbostic } 19035339Sbostic if (BADTYPE(fs->fs_type)) { 19166131Spendry errx(1, "%s has unknown file system type.\n", *argv); 19235339Sbostic } 19339333Smckusick mnttype = getmnttype(fs->fs_vfstype); 19440496Smckusick ret = mountfs(fs->fs_spec, fs->fs_file, updateflg, 19540496Smckusick type, options, fs->fs_mntops); 19640496Smckusick } else if (argc != 2) { 19740496Smckusick usage(); 19840496Smckusick ret = 1; 19940496Smckusick } else { 20042857Smckusick /* 20142857Smckusick * If -t flag has not been specified, and spec 20242857Smckusick * contains either a ':' or a '@' then assume that 20342857Smckusick * an NFS filesystem is being specified ala Sun. 20442857Smckusick */ 20542857Smckusick if (vfslist == (char **)0 && 20666131Spendry (strchr(argv[0], ':') || strchr(argv[0], '@'))) { 20742857Smckusick mnttype = MOUNT_NFS; 20852182Smckusick mntname = "nfs"; 20952182Smckusick } 21042253Sbostic ret = mountfs(argv[0], argv[1], updateflg, type, options, 21142253Sbostic (char *)NULL); 21212808Ssam } 21340496Smckusick if ((pidfile = fopen(_PATH_MOUNTDPID, "r")) != NULL) { 21440496Smckusick pid = 0; 21540496Smckusick fscanf(pidfile, "%d", &pid); 21640496Smckusick fclose(pidfile); 21740496Smckusick if (pid > 0) 21840496Smckusick kill(pid, SIGHUP); 21940496Smckusick } 22066131Spendry exit(ret); 22112808Ssam } 22212808Ssam 22366130Spendry static int 22439333Smckusick mountfs(spec, name, flags, type, options, mntopts) 22539131Smckusick char *spec, *name, *type, *options, *mntopts; 22639333Smckusick int flags; 22712808Ssam { 22866130Spendry int status; 22942253Sbostic pid_t pid; 23042253Sbostic int argc, i; 23138070Smckusick struct ufs_args args; 23239131Smckusick char *argp, *argv[50]; 23339322Smckusick char execname[MAXPATHLEN + 1], flagval[12]; 234*66133Spendry char mntpath[MAXPATHLEN]; 2351057Sbill 23639333Smckusick if (mntopts) 23739333Smckusick getstdopts(mntopts, &flags); 23839316Smckusick if (options) 23939316Smckusick getstdopts(options, &flags); 24039333Smckusick if (type) 24139333Smckusick getstdopts(type, &flags); 24256841Smckusick if (force) 24356841Smckusick flags |= MNT_FORCE; 244*66133Spendry 245*66133Spendry if (realpath(name, mntpath) == 0) { 246*66133Spendry warn("%s", mntpath); 247*66133Spendry return (1); 248*66133Spendry } 249*66133Spendry 250*66133Spendry name = mntpath; 251*66133Spendry 25266131Spendry if (strcmp(name, "/") == 0) 25366131Spendry flags |= MNT_UPDATE; 25466131Spendry 25539316Smckusick switch (mnttype) { 25639316Smckusick case MOUNT_UFS: 25739333Smckusick if (mntopts) 25839333Smckusick getufsopts(mntopts, &flags); 25939316Smckusick if (options) 26039316Smckusick getufsopts(options, &flags); 26139316Smckusick args.fspec = spec; 26265714Shibler args.export.ex_root = DEFAULT_ROOTUID; 26341403Smckusick if (flags & MNT_RDONLY) 26465714Shibler args.export.ex_flags = MNT_EXRDONLY; 26540496Smckusick else 26665714Shibler args.export.ex_flags = 0; 26739316Smckusick argp = (caddr_t)&args; 26839316Smckusick break; 26938632Smckusick 27052110Smckusick case MOUNT_MFS: 27139316Smckusick case MOUNT_NFS: 27239322Smckusick default: 27339322Smckusick argv[0] = mntname; 27439329Smckusick argc = 1; 27539322Smckusick if (flags) { 27639322Smckusick argv[argc++] = "-F"; 27739322Smckusick sprintf(flagval, "%d", flags); 27839322Smckusick argv[argc++] = flagval; 27939322Smckusick } 28039333Smckusick if (mntopts) 28139333Smckusick argc += getexecopts(mntopts, &argv[argc]); 28239329Smckusick if (options) 28339329Smckusick argc += getexecopts(options, &argv[argc]); 28439316Smckusick argv[argc++] = spec; 28539316Smckusick argv[argc++] = name; 28639521Smckusick argv[argc++] = NULL; 28739603Smckusick sprintf(execname, "%s/mount_%s", _PATH_EXECDIR, mntname); 28839316Smckusick if (verbose) { 28942253Sbostic (void)printf("exec: %s", execname); 29042253Sbostic for (i = 1; i < argc - 1; i++) 29142253Sbostic (void)printf(" %s", argv[i]); 29242253Sbostic (void)printf("\n"); 29339316Smckusick } 29456841Smckusick if (debug) 29539316Smckusick break; 29642253Sbostic if (pid = vfork()) { 29742253Sbostic if (pid == -1) { 29866131Spendry warn("vfork starting file system"); 29939316Smckusick return (1); 30039131Smckusick } 30166130Spendry if (waitpid(pid, &status, 0) != -1 && 30239316Smckusick WIFEXITED(status) && 30339316Smckusick WEXITSTATUS(status) != 0) 30439316Smckusick return (WEXITSTATUS(status)); 30539322Smckusick spec = mntname; 30639316Smckusick goto out; 30739316Smckusick } 30866130Spendry execv(execname, argv); 30966131Spendry err(1, "cannot exec %s for %s", execname, name); 31039316Smckusick /* NOTREACHED */ 31138632Smckusick 31239316Smckusick } 31356841Smckusick if (!debug && mount(mnttype, name, flags, argp)) { 31445689Smckusick (void) fprintf(stderr, "%s on %s: ", spec, name); 31539316Smckusick switch (errno) { 31639316Smckusick case EMFILE: 31745689Smckusick (void) fprintf(stderr, "Mount table full\n"); 31839316Smckusick break; 31939316Smckusick case EINVAL: 32041403Smckusick if (flags & MNT_UPDATE) 32145689Smckusick (void) fprintf(stderr, "Specified device %s\n", 32245689Smckusick "does not match mounted device"); 32345569Skarels else if (mnttype == MOUNT_UFS) 32445689Smckusick (void) fprintf(stderr, "Bogus super block\n"); 32539333Smckusick else 32645569Skarels perror((char *)NULL); 32739316Smckusick break; 32839316Smckusick default: 32939316Smckusick perror((char *)NULL); 33039316Smckusick break; 3314460Sroot } 33266130Spendry return (1); 3334460Sroot } 33435339Sbostic 33539131Smckusick out: 33612808Ssam if (verbose) 33739316Smckusick prmount(spec, name, flags); 33835339Sbostic 33966130Spendry return (0); 3401057Sbill } 34135339Sbostic 34246708Sbostic static void 34339316Smckusick prmount(spec, name, flags) 34439316Smckusick char *spec, *name; 34566130Spendry int flags; 34635339Sbostic { 34766130Spendry int first; 34838632Smckusick 34942253Sbostic (void)printf("%s on %s", spec, name); 35042253Sbostic if (!(flags & MNT_VISFLAGMASK)) { 35142253Sbostic (void)printf("\n"); 35242253Sbostic return; 35342253Sbostic } 35442253Sbostic first = 0; 35542253Sbostic #define PR(msg) (void)printf("%s%s", !first++ ? " (" : ", ", msg) 35641403Smckusick if (flags & MNT_RDONLY) 35742253Sbostic PR("read-only"); 35841403Smckusick if (flags & MNT_NOEXEC) 35942253Sbostic PR("noexec"); 36041403Smckusick if (flags & MNT_NOSUID) 36142253Sbostic PR("nosuid"); 36241403Smckusick if (flags & MNT_NODEV) 36342253Sbostic PR("nodev"); 36441403Smckusick if (flags & MNT_SYNCHRONOUS) 36542253Sbostic PR("synchronous"); 36665609Smckusick if (flags & MNT_ASYNC) 36765609Smckusick PR("asynchronous"); 36841403Smckusick if (flags & MNT_QUOTA) 36942253Sbostic PR("with quotas"); 37041403Smckusick if (flags & MNT_LOCAL) 37142253Sbostic PR("local"); 37255394Spendry if (flags & MNT_UNION) 37355394Spendry PR("union"); 37441403Smckusick if (flags & MNT_EXPORTED) 37552110Smckusick PR("NFS exported"); 37642253Sbostic (void)printf(")\n"); 37735339Sbostic } 37835339Sbostic 37966130Spendry static int 38039133Smckusick getmnttype(fstype) 38139133Smckusick char *fstype; 38239133Smckusick { 38339133Smckusick 38439322Smckusick mntname = fstype; 38539133Smckusick if (!strcmp(fstype, "ufs")) 38639133Smckusick return (MOUNT_UFS); 38739133Smckusick return (0); 38839133Smckusick } 38939133Smckusick 39066130Spendry static void 39138632Smckusick usage() 39235339Sbostic { 39340871Smckusick 39445689Smckusick (void) fprintf(stderr, 39545689Smckusick "usage:\n mount %s %s\n mount %s\n mount %s\n", 39652110Smckusick "[ -frwu ] [ -t ufs | external_type ]", 39740871Smckusick "[ -o options ] special node", 39852110Smckusick "[ -afrwu ] [ -t ufs | external_type ]", 39940871Smckusick "[ -frwu ] special | node"); 40035339Sbostic exit(1); 40135339Sbostic } 40235339Sbostic 40366130Spendry static void 40439316Smckusick getstdopts(options, flagp) 40539316Smckusick char *options; 40642253Sbostic int *flagp; 40739316Smckusick { 40866130Spendry char *opt; 40939316Smckusick int negative; 41042253Sbostic char optbuf[BUFSIZ]; 41139316Smckusick 41242253Sbostic (void)strcpy(optbuf, options); 41342253Sbostic for (opt = strtok(optbuf, ","); opt; opt = strtok((char *)NULL, ",")) { 41465852Smckusick if (opt[0] == '-') 41565852Smckusick continue; 41639316Smckusick if (opt[0] == 'n' && opt[1] == 'o') { 41739316Smckusick negative++; 41839316Smckusick opt += 2; 41939316Smckusick } else { 42039316Smckusick negative = 0; 42139316Smckusick } 42239333Smckusick if (!negative && !strcasecmp(opt, FSTAB_RO)) { 42341403Smckusick *flagp |= MNT_RDONLY; 42439333Smckusick continue; 42539333Smckusick } 42639333Smckusick if (!negative && !strcasecmp(opt, FSTAB_RW)) { 42741403Smckusick *flagp &= ~MNT_RDONLY; 42839333Smckusick continue; 42939333Smckusick } 43039316Smckusick if (!strcasecmp(opt, "exec")) { 43139316Smckusick if (negative) 43241403Smckusick *flagp |= MNT_NOEXEC; 43339333Smckusick else 43441403Smckusick *flagp &= ~MNT_NOEXEC; 43539316Smckusick continue; 43639316Smckusick } 43739316Smckusick if (!strcasecmp(opt, "suid")) { 43839316Smckusick if (negative) 43941403Smckusick *flagp |= MNT_NOSUID; 44039333Smckusick else 44141403Smckusick *flagp &= ~MNT_NOSUID; 44239316Smckusick continue; 44339316Smckusick } 44439316Smckusick if (!strcasecmp(opt, "dev")) { 44539316Smckusick if (negative) 44641403Smckusick *flagp |= MNT_NODEV; 44739333Smckusick else 44841403Smckusick *flagp &= ~MNT_NODEV; 44939316Smckusick continue; 45039316Smckusick } 45139316Smckusick if (!strcasecmp(opt, "synchronous")) { 45239316Smckusick if (!negative) 45341403Smckusick *flagp |= MNT_SYNCHRONOUS; 45439333Smckusick else 45541403Smckusick *flagp &= ~MNT_SYNCHRONOUS; 45639316Smckusick continue; 45739316Smckusick } 45865609Smckusick if (!strcasecmp(opt, "asynchronous")) { 45965609Smckusick if (!negative) 46065609Smckusick *flagp |= MNT_ASYNC; 46165609Smckusick else 46265609Smckusick *flagp &= ~MNT_ASYNC; 46365609Smckusick continue; 46465609Smckusick } 46555394Spendry if (!strcasecmp(opt, "union")) { 46655394Spendry if (!negative) 46755394Spendry *flagp |= MNT_UNION; 46855394Spendry else 46955394Spendry *flagp &= ~MNT_UNION; 47055394Spendry continue; 47155394Spendry } 47265852Smckusick (void) fprintf(stderr, "mount: %s: unknown option\n", opt); 47339316Smckusick } 47439316Smckusick } 47539316Smckusick 47642253Sbostic /* ARGSUSED */ 47766130Spendry static void 47839131Smckusick getufsopts(options, flagp) 47939131Smckusick char *options; 48042253Sbostic int *flagp; 48139131Smckusick { 48266130Spendry 48339131Smckusick return; 48439131Smckusick } 48539131Smckusick 48666130Spendry static int 48739329Smckusick getexecopts(options, argv) 48839131Smckusick char *options; 48939131Smckusick char **argv; 49039131Smckusick { 49166130Spendry int argc = 0; 49266130Spendry char *opt; 49339131Smckusick 49442253Sbostic for (opt = strtok(options, ","); opt; opt = strtok((char *)NULL, ",")) { 49539131Smckusick if (opt[0] != '-') 49639131Smckusick continue; 49739131Smckusick argv[argc++] = opt; 49839131Smckusick if (opt[2] == '\0' || opt[2] != '=') 49939131Smckusick continue; 50039131Smckusick opt[2] = '\0'; 50139131Smckusick argv[argc++] = &opt[3]; 50239131Smckusick } 50339131Smckusick return (argc); 50439131Smckusick } 50539131Smckusick 50666130Spendry static struct statfs * 50739465Smckusick getmntpt(name) 50839465Smckusick char *name; 50939465Smckusick { 51039465Smckusick long mntsize; 51166130Spendry long i; 51239465Smckusick struct statfs *mntbuf; 51339465Smckusick 51440337Smckusick mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 51539465Smckusick for (i = 0; i < mntsize; i++) { 51639465Smckusick if (!strcmp(mntbuf[i].f_mntfromname, name) || 51739465Smckusick !strcmp(mntbuf[i].f_mntonname, name)) 51839465Smckusick return (&mntbuf[i]); 51939465Smckusick } 52039465Smckusick return ((struct statfs *)0); 52139465Smckusick } 52239465Smckusick 52340051Smckusick static int skipvfs; 52440051Smckusick 52566130Spendry static int 52640051Smckusick badvfstype(vfstype, vfslist) 52766130Spendry int vfstype; 52840051Smckusick char **vfslist; 52940051Smckusick { 53040051Smckusick 53140051Smckusick if (vfslist == 0) 53266130Spendry return (0); 53340051Smckusick while (*vfslist) { 53440844Smckusick if (vfstype == getmnttype(*vfslist)) 53566130Spendry return (skipvfs); 53640051Smckusick vfslist++; 53740051Smckusick } 53840051Smckusick return (!skipvfs); 53940051Smckusick } 54040051Smckusick 54166130Spendry static int 54240844Smckusick badvfsname(vfsname, vfslist) 54340844Smckusick char *vfsname; 54440844Smckusick char **vfslist; 54540844Smckusick { 54640844Smckusick 54740844Smckusick if (vfslist == 0) 54866130Spendry return (0); 54940844Smckusick while (*vfslist) { 55040844Smckusick if (strcmp(vfsname, *vfslist) == 0) 55166130Spendry return (skipvfs); 55240844Smckusick vfslist++; 55340844Smckusick } 55440844Smckusick return (!skipvfs); 55540844Smckusick } 55640844Smckusick 55766130Spendry static char ** 55840051Smckusick makevfslist(fslist) 55940051Smckusick char *fslist; 56040051Smckusick { 56166130Spendry char **av, *nextcp; 56266130Spendry int i; 56340051Smckusick 56440051Smckusick if (fslist == NULL) 56540051Smckusick return (NULL); 56640051Smckusick if (fslist[0] == 'n' && fslist[1] == 'o') { 56740051Smckusick fslist += 2; 56840051Smckusick skipvfs = 1; 56940051Smckusick } 57040051Smckusick for (i = 0, nextcp = fslist; *nextcp; nextcp++) 57140051Smckusick if (*nextcp == ',') 57240051Smckusick i++; 57342253Sbostic av = (char **)malloc((size_t)(i+2) * sizeof(char *)); 57440051Smckusick if (av == NULL) 57540051Smckusick return (NULL); 57640051Smckusick nextcp = fslist; 57740051Smckusick i = 0; 57840051Smckusick av[i++] = nextcp; 57940051Smckusick while (nextcp = index(nextcp, ',')) { 58040051Smckusick *nextcp++ = '\0'; 58140051Smckusick av[i++] = nextcp; 58240051Smckusick } 58340051Smckusick av[i++] = 0; 58440051Smckusick return (av); 58540051Smckusick } 586