1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <stdio.h> 34*7c478bd9Sstevel@tonic-gate #include <limits.h> 35*7c478bd9Sstevel@tonic-gate #include <unistd.h> 36*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 37*7c478bd9Sstevel@tonic-gate #include <string.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/signal.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 40*7c478bd9Sstevel@tonic-gate #include <errno.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/vfstab.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/fcntl.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/resource.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/ctfs.h> 50*7c478bd9Sstevel@tonic-gate #include <locale.h> 51*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/mount.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/objfs.h> 54*7c478bd9Sstevel@tonic-gate #include "fslib.h" 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #define FS_PATH "/usr/lib/fs" 57*7c478bd9Sstevel@tonic-gate #define ALT_PATH "/etc/fs" 58*7c478bd9Sstevel@tonic-gate #define FULLPATH_MAX 32 59*7c478bd9Sstevel@tonic-gate #define FSTYPE_MAX 8 60*7c478bd9Sstevel@tonic-gate #define ARGV_MAX 16 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate int aflg, oflg, Vflg, dashflg, dflg, fflg; 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate extern void rpterr(), usage(), mnterror(); 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate extern char *optarg; /* used by getopt */ 67*7c478bd9Sstevel@tonic-gate extern int optind, opterr; 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate static char *myname; 70*7c478bd9Sstevel@tonic-gate char fs_path[] = FS_PATH; 71*7c478bd9Sstevel@tonic-gate char alt_path[] = ALT_PATH; 72*7c478bd9Sstevel@tonic-gate char mnttab[MAXPATHLEN + 1]; 73*7c478bd9Sstevel@tonic-gate char *oarg, *farg; 74*7c478bd9Sstevel@tonic-gate int maxrun, nrun; 75*7c478bd9Sstevel@tonic-gate int no_mnttab; 76*7c478bd9Sstevel@tonic-gate int lofscnt; /* presence of lofs prohibits parallel */ 77*7c478bd9Sstevel@tonic-gate /* umounting */ 78*7c478bd9Sstevel@tonic-gate int exitcode; 79*7c478bd9Sstevel@tonic-gate char resolve[MAXPATHLEN]; 80*7c478bd9Sstevel@tonic-gate static char ibuf[BUFSIZ]; 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate /* 83*7c478bd9Sstevel@tonic-gate * Currently, mounting cachefs's simultaneous uncovers various problems. 84*7c478bd9Sstevel@tonic-gate * For the short term, we serialize cachefs activity while we fix 85*7c478bd9Sstevel@tonic-gate * these cachefs bugs. 86*7c478bd9Sstevel@tonic-gate */ 87*7c478bd9Sstevel@tonic-gate #define CACHEFS_BUG 88*7c478bd9Sstevel@tonic-gate #ifdef CACHEFS_BUG 89*7c478bd9Sstevel@tonic-gate #include <sys/fs/cachefs_fs.h> /* for BACKMNT_NAME */ 90*7c478bd9Sstevel@tonic-gate int cachefs_running; /* parallel cachefs not supported yet */ 91*7c478bd9Sstevel@tonic-gate #endif 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate /* 94*7c478bd9Sstevel@tonic-gate * The basic mount struct that describes an mnttab entry. 95*7c478bd9Sstevel@tonic-gate * It is used both in an array and as a linked list elem. 96*7c478bd9Sstevel@tonic-gate */ 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate typedef struct mountent { 99*7c478bd9Sstevel@tonic-gate struct mnttab ment; /* the mnttab data */ 100*7c478bd9Sstevel@tonic-gate int mlevel; /* mount level of the mount pt */ 101*7c478bd9Sstevel@tonic-gate pid_t pid; /* the pid of this mount process */ 102*7c478bd9Sstevel@tonic-gate #define RDPIPE 0 103*7c478bd9Sstevel@tonic-gate #define WRPIPE 1 104*7c478bd9Sstevel@tonic-gate int sopipe[2]; /* pipe attached to child's stdout */ 105*7c478bd9Sstevel@tonic-gate int sepipe[2]; /* pipe attached to child's stderr */ 106*7c478bd9Sstevel@tonic-gate struct mountent *link; /* used when in linked list */ 107*7c478bd9Sstevel@tonic-gate } mountent_t; 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate static mountent_t *mntll; /* head of global linked list of */ 110*7c478bd9Sstevel@tonic-gate /* mountents */ 111*7c478bd9Sstevel@tonic-gate int listlength; /* # of elems in this list */ 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate /* 114*7c478bd9Sstevel@tonic-gate * If the automatic flag (-a) is given and mount points are not specified 115*7c478bd9Sstevel@tonic-gate * on the command line, then do not attempt to umount these. These 116*7c478bd9Sstevel@tonic-gate * generally need to be kept mounted until system shutdown. 117*7c478bd9Sstevel@tonic-gate */ 118*7c478bd9Sstevel@tonic-gate static const char *keeplist[] = { 119*7c478bd9Sstevel@tonic-gate "/", 120*7c478bd9Sstevel@tonic-gate "/dev", 121*7c478bd9Sstevel@tonic-gate "/dev/fd", 122*7c478bd9Sstevel@tonic-gate "/devices", 123*7c478bd9Sstevel@tonic-gate "/etc/mnttab", 124*7c478bd9Sstevel@tonic-gate "/etc/svc/volatile", 125*7c478bd9Sstevel@tonic-gate "/lib", 126*7c478bd9Sstevel@tonic-gate "/proc", 127*7c478bd9Sstevel@tonic-gate "/sbin", 128*7c478bd9Sstevel@tonic-gate CTFS_ROOT, 129*7c478bd9Sstevel@tonic-gate OBJFS_ROOT, 130*7c478bd9Sstevel@tonic-gate "/tmp", 131*7c478bd9Sstevel@tonic-gate "/usr", 132*7c478bd9Sstevel@tonic-gate "/var", 133*7c478bd9Sstevel@tonic-gate "/var/adm", 134*7c478bd9Sstevel@tonic-gate "/var/run", 135*7c478bd9Sstevel@tonic-gate NULL 136*7c478bd9Sstevel@tonic-gate }; 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate static void nomem(); 139*7c478bd9Sstevel@tonic-gate static void doexec(struct mnttab *); 140*7c478bd9Sstevel@tonic-gate static int setup_iopipe(mountent_t *); 141*7c478bd9Sstevel@tonic-gate static void setup_output(mountent_t *); 142*7c478bd9Sstevel@tonic-gate static void doio(mountent_t *); 143*7c478bd9Sstevel@tonic-gate static void do_umounts(mountent_t **); 144*7c478bd9Sstevel@tonic-gate static int dowait(); 145*7c478bd9Sstevel@tonic-gate static int parumount(); 146*7c478bd9Sstevel@tonic-gate static int mcompar(const void *, const void *); 147*7c478bd9Sstevel@tonic-gate static void cleanup(int); 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate static mountent_t **make_mntarray(char **, int); 150*7c478bd9Sstevel@tonic-gate static mountent_t *getmntall(); 151*7c478bd9Sstevel@tonic-gate static mountent_t *new_mountent(struct mnttab *); 152*7c478bd9Sstevel@tonic-gate static mountent_t *getmntlast(mountent_t *, char *, char *); 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate main(argc, argv) 155*7c478bd9Sstevel@tonic-gate int argc; 156*7c478bd9Sstevel@tonic-gate char **argv; 157*7c478bd9Sstevel@tonic-gate { 158*7c478bd9Sstevel@tonic-gate int cc; 159*7c478bd9Sstevel@tonic-gate struct mnttab mget; 160*7c478bd9Sstevel@tonic-gate char *mname, *is_special; 161*7c478bd9Sstevel@tonic-gate int fscnt; 162*7c478bd9Sstevel@tonic-gate mountent_t *mp; 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 167*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 168*7c478bd9Sstevel@tonic-gate #endif 169*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate myname = strrchr(argv[0], '/'); 172*7c478bd9Sstevel@tonic-gate if (myname) 173*7c478bd9Sstevel@tonic-gate myname++; 174*7c478bd9Sstevel@tonic-gate else 175*7c478bd9Sstevel@tonic-gate myname = argv[0]; 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate /* 178*7c478bd9Sstevel@tonic-gate * Process the args. 179*7c478bd9Sstevel@tonic-gate * "-d" for compatibility 180*7c478bd9Sstevel@tonic-gate */ 181*7c478bd9Sstevel@tonic-gate while ((cc = getopt(argc, argv, "ado:Vf?")) != -1) 182*7c478bd9Sstevel@tonic-gate switch (cc) { 183*7c478bd9Sstevel@tonic-gate case 'a': 184*7c478bd9Sstevel@tonic-gate aflg++; 185*7c478bd9Sstevel@tonic-gate break; 186*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 187*7c478bd9Sstevel@tonic-gate case 'd': 188*7c478bd9Sstevel@tonic-gate dflg++; 189*7c478bd9Sstevel@tonic-gate break; 190*7c478bd9Sstevel@tonic-gate #endif 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate case '?': 193*7c478bd9Sstevel@tonic-gate usage(); 194*7c478bd9Sstevel@tonic-gate break; 195*7c478bd9Sstevel@tonic-gate case 'o': 196*7c478bd9Sstevel@tonic-gate if (oflg) 197*7c478bd9Sstevel@tonic-gate usage(); 198*7c478bd9Sstevel@tonic-gate else { 199*7c478bd9Sstevel@tonic-gate oflg++; 200*7c478bd9Sstevel@tonic-gate oarg = optarg; 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate break; 203*7c478bd9Sstevel@tonic-gate case 'f': 204*7c478bd9Sstevel@tonic-gate fflg++; 205*7c478bd9Sstevel@tonic-gate break; 206*7c478bd9Sstevel@tonic-gate case 'V': 207*7c478bd9Sstevel@tonic-gate if (Vflg) 208*7c478bd9Sstevel@tonic-gate usage(); 209*7c478bd9Sstevel@tonic-gate else 210*7c478bd9Sstevel@tonic-gate Vflg++; 211*7c478bd9Sstevel@tonic-gate break; 212*7c478bd9Sstevel@tonic-gate default: 213*7c478bd9Sstevel@tonic-gate usage(); 214*7c478bd9Sstevel@tonic-gate break; 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate fscnt = argc - optind; 218*7c478bd9Sstevel@tonic-gate if (!aflg && fscnt != 1) 219*7c478bd9Sstevel@tonic-gate usage(); 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate /* copy '--' to specific */ 222*7c478bd9Sstevel@tonic-gate if (strcmp(argv[optind-1], "--") == 0) 223*7c478bd9Sstevel@tonic-gate dashflg++; 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate /* 226*7c478bd9Sstevel@tonic-gate * mnttab may be a symlink to a file in another file system. 227*7c478bd9Sstevel@tonic-gate * This happens during install when / is mounted read-only 228*7c478bd9Sstevel@tonic-gate * and /etc/mnttab is symlinked to a file in /tmp. 229*7c478bd9Sstevel@tonic-gate * If this is the case, we need to follow the symlink to the 230*7c478bd9Sstevel@tonic-gate * read-write file itself so that the subsequent mnttab.temp 231*7c478bd9Sstevel@tonic-gate * open and rename will work. 232*7c478bd9Sstevel@tonic-gate */ 233*7c478bd9Sstevel@tonic-gate if (realpath(MNTTAB, mnttab) == NULL) { 234*7c478bd9Sstevel@tonic-gate strcpy(mnttab, MNTTAB); 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate /* 238*7c478bd9Sstevel@tonic-gate * bugid 1205242 239*7c478bd9Sstevel@tonic-gate * call the realpath() here, so that if the user is 240*7c478bd9Sstevel@tonic-gate * trying to umount an autofs directory, the directory 241*7c478bd9Sstevel@tonic-gate * is forced to mount. 242*7c478bd9Sstevel@tonic-gate */ 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate mname = argv[optind]; 245*7c478bd9Sstevel@tonic-gate is_special = realpath(mname, resolve); 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate /* 248*7c478bd9Sstevel@tonic-gate * Read the whole mnttab into memory. 249*7c478bd9Sstevel@tonic-gate */ 250*7c478bd9Sstevel@tonic-gate mntll = getmntall(); 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate if (aflg && fscnt != 1) 253*7c478bd9Sstevel@tonic-gate exit(parumount(argv + optind, fscnt)); 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate aflg = 0; 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate mntnull(&mget); 258*7c478bd9Sstevel@tonic-gate if (listlength == 0) { 259*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 260*7c478bd9Sstevel@tonic-gate "%s: warning: no entries found in %s\n"), 261*7c478bd9Sstevel@tonic-gate myname, mnttab); 262*7c478bd9Sstevel@tonic-gate mget.mnt_mountp = mname; /* assume mount point */ 263*7c478bd9Sstevel@tonic-gate no_mnttab++; 264*7c478bd9Sstevel@tonic-gate doexec(&mget); 265*7c478bd9Sstevel@tonic-gate exit(0); 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate mp = NULL; 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate /* 271*7c478bd9Sstevel@tonic-gate * if realpath fails, it can't be a mount point, so we'll 272*7c478bd9Sstevel@tonic-gate * go straight to the code that treats the arg as a special. 273*7c478bd9Sstevel@tonic-gate * if realpath succeeds, it could be a special or a mount point; 274*7c478bd9Sstevel@tonic-gate * we'll start by assuming it's a mount point, and if it's not, 275*7c478bd9Sstevel@tonic-gate * try to treat it as a special. 276*7c478bd9Sstevel@tonic-gate */ 277*7c478bd9Sstevel@tonic-gate if (is_special != NULL) { 278*7c478bd9Sstevel@tonic-gate /* 279*7c478bd9Sstevel@tonic-gate * if this succeeds, 280*7c478bd9Sstevel@tonic-gate * we'll have the appropriate record; if it fails 281*7c478bd9Sstevel@tonic-gate * we'll assume the arg is a special of some sort 282*7c478bd9Sstevel@tonic-gate */ 283*7c478bd9Sstevel@tonic-gate mp = getmntlast(mntll, NULL, resolve); 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate /* 286*7c478bd9Sstevel@tonic-gate * Since stackable mount is allowed (RFE 2001535), 287*7c478bd9Sstevel@tonic-gate * we will un-mount the last entry in the MNTTAB that matches. 288*7c478bd9Sstevel@tonic-gate */ 289*7c478bd9Sstevel@tonic-gate if (mp == NULL) { 290*7c478bd9Sstevel@tonic-gate /* 291*7c478bd9Sstevel@tonic-gate * Perhaps there is a bogus mnttab entry that 292*7c478bd9Sstevel@tonic-gate * can't be resolved: 293*7c478bd9Sstevel@tonic-gate */ 294*7c478bd9Sstevel@tonic-gate if ((mp = getmntlast(mntll, NULL, mname)) == NULL) 295*7c478bd9Sstevel@tonic-gate /* 296*7c478bd9Sstevel@tonic-gate * assume it's a device (special) now 297*7c478bd9Sstevel@tonic-gate */ 298*7c478bd9Sstevel@tonic-gate mp = getmntlast(mntll, mname, NULL); 299*7c478bd9Sstevel@tonic-gate if (mp) { 300*7c478bd9Sstevel@tonic-gate /* 301*7c478bd9Sstevel@tonic-gate * Found it. 302*7c478bd9Sstevel@tonic-gate * This is a device. Now we want to know if 303*7c478bd9Sstevel@tonic-gate * it stackmounted on by something else. 304*7c478bd9Sstevel@tonic-gate * The original fix for bug 1103850 has a 305*7c478bd9Sstevel@tonic-gate * problem with lockfs (bug 1119731). This 306*7c478bd9Sstevel@tonic-gate * is a revised method. 307*7c478bd9Sstevel@tonic-gate */ 308*7c478bd9Sstevel@tonic-gate mountent_t *lmp; 309*7c478bd9Sstevel@tonic-gate lmp = getmntlast(mntll, NULL, mp->ment.mnt_mountp); 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate if (lmp && strcmp(lmp->ment.mnt_special, 312*7c478bd9Sstevel@tonic-gate mp->ment.mnt_special)) { 313*7c478bd9Sstevel@tonic-gate errno = EBUSY; 314*7c478bd9Sstevel@tonic-gate rpterr(mname); 315*7c478bd9Sstevel@tonic-gate exit(1); 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate } else { 318*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 319*7c478bd9Sstevel@tonic-gate "%s: warning: %s not in mnttab\n"), 320*7c478bd9Sstevel@tonic-gate myname, mname); 321*7c478bd9Sstevel@tonic-gate if (Vflg) 322*7c478bd9Sstevel@tonic-gate exit(1); 323*7c478bd9Sstevel@tonic-gate /* 324*7c478bd9Sstevel@tonic-gate * same error as mount -V 325*7c478bd9Sstevel@tonic-gate * would give for unknown 326*7c478bd9Sstevel@tonic-gate * mount point 327*7c478bd9Sstevel@tonic-gate */ 328*7c478bd9Sstevel@tonic-gate mget.mnt_special = mget.mnt_mountp = mname; 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate if (mp) 333*7c478bd9Sstevel@tonic-gate doexec(&mp->ment); 334*7c478bd9Sstevel@tonic-gate else 335*7c478bd9Sstevel@tonic-gate doexec(&mget); 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate exit(0); 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate void 341*7c478bd9Sstevel@tonic-gate doexec(struct mnttab *ment) 342*7c478bd9Sstevel@tonic-gate { 343*7c478bd9Sstevel@tonic-gate int ret; 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 346*7c478bd9Sstevel@tonic-gate if (dflg) 347*7c478bd9Sstevel@tonic-gate fprintf(stderr, "%d: umounting %s\n", 348*7c478bd9Sstevel@tonic-gate getpid(), ment->mnt_mountp); 349*7c478bd9Sstevel@tonic-gate #endif 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate /* try to exec the dependent portion */ 352*7c478bd9Sstevel@tonic-gate if ((ment->mnt_fstype != NULL) || Vflg) { 353*7c478bd9Sstevel@tonic-gate char full_path[FULLPATH_MAX]; 354*7c478bd9Sstevel@tonic-gate char alter_path[FULLPATH_MAX]; 355*7c478bd9Sstevel@tonic-gate char *newargv[ARGV_MAX]; 356*7c478bd9Sstevel@tonic-gate int ii; 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate if (strlen(ment->mnt_fstype) > (size_t)FSTYPE_MAX) { 359*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 360*7c478bd9Sstevel@tonic-gate "%s: FSType %s exceeds %d characters\n"), 361*7c478bd9Sstevel@tonic-gate myname, ment->mnt_fstype, FSTYPE_MAX); 362*7c478bd9Sstevel@tonic-gate exit(1); 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* build the full pathname of the fstype dependent command. */ 366*7c478bd9Sstevel@tonic-gate sprintf(full_path, "%s/%s/%s", fs_path, ment->mnt_fstype, 367*7c478bd9Sstevel@tonic-gate myname); 368*7c478bd9Sstevel@tonic-gate sprintf(alter_path, "%s/%s/%s", alt_path, ment->mnt_fstype, 369*7c478bd9Sstevel@tonic-gate myname); 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate /* 372*7c478bd9Sstevel@tonic-gate * create the new arg list, and end the list with a 373*7c478bd9Sstevel@tonic-gate * null pointer 374*7c478bd9Sstevel@tonic-gate */ 375*7c478bd9Sstevel@tonic-gate ii = 2; 376*7c478bd9Sstevel@tonic-gate if (oflg) { 377*7c478bd9Sstevel@tonic-gate newargv[ii++] = "-o"; 378*7c478bd9Sstevel@tonic-gate newargv[ii++] = oarg; 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate if (dashflg) { 381*7c478bd9Sstevel@tonic-gate newargv[ii++] = "--"; 382*7c478bd9Sstevel@tonic-gate } 383*7c478bd9Sstevel@tonic-gate if (fflg) { 384*7c478bd9Sstevel@tonic-gate newargv[ii++] = "-f"; 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate newargv[ii++] = (ment->mnt_mountp) 387*7c478bd9Sstevel@tonic-gate ? ment->mnt_mountp : ment->mnt_special; 388*7c478bd9Sstevel@tonic-gate newargv[ii] = NULL; 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate /* set the new argv[0] to the filename */ 391*7c478bd9Sstevel@tonic-gate newargv[1] = myname; 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate if (Vflg) { 394*7c478bd9Sstevel@tonic-gate printf("%s", myname); 395*7c478bd9Sstevel@tonic-gate for (ii = 2; newargv[ii]; ii++) 396*7c478bd9Sstevel@tonic-gate printf(" %s", newargv[ii]); 397*7c478bd9Sstevel@tonic-gate printf("\n"); 398*7c478bd9Sstevel@tonic-gate fflush(stdout); 399*7c478bd9Sstevel@tonic-gate exit(0); 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate /* Try to exec the fstype dependent umount. */ 403*7c478bd9Sstevel@tonic-gate execv(full_path, &newargv[1]); 404*7c478bd9Sstevel@tonic-gate if (errno == ENOEXEC) { 405*7c478bd9Sstevel@tonic-gate newargv[0] = "sh"; 406*7c478bd9Sstevel@tonic-gate newargv[1] = full_path; 407*7c478bd9Sstevel@tonic-gate execv("/sbin/sh", &newargv[0]); 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate newargv[1] = myname; 410*7c478bd9Sstevel@tonic-gate execv(alter_path, &newargv[1]); 411*7c478bd9Sstevel@tonic-gate if (errno == ENOEXEC) { 412*7c478bd9Sstevel@tonic-gate newargv[0] = "sh"; 413*7c478bd9Sstevel@tonic-gate newargv[1] = alter_path; 414*7c478bd9Sstevel@tonic-gate execv("/sbin/sh", &newargv[0]); 415*7c478bd9Sstevel@tonic-gate } 416*7c478bd9Sstevel@tonic-gate /* exec failed */ 417*7c478bd9Sstevel@tonic-gate if (errno != ENOENT) { 418*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("umount: cannot execute %s\n"), 419*7c478bd9Sstevel@tonic-gate full_path); 420*7c478bd9Sstevel@tonic-gate exit(1); 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate /* 424*7c478bd9Sstevel@tonic-gate * No fstype independent executable then. We'll go generic 425*7c478bd9Sstevel@tonic-gate * from here. 426*7c478bd9Sstevel@tonic-gate */ 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate /* don't use -o with generic */ 429*7c478bd9Sstevel@tonic-gate if (oflg) { 430*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 431*7c478bd9Sstevel@tonic-gate "%s: %s specific umount does not exist; -o suboption ignored\n"), 432*7c478bd9Sstevel@tonic-gate myname, ment->mnt_fstype ? ment->mnt_fstype : "<null>"); 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate signal(SIGHUP, SIG_IGN); 436*7c478bd9Sstevel@tonic-gate signal(SIGQUIT, SIG_IGN); 437*7c478bd9Sstevel@tonic-gate signal(SIGINT, SIG_IGN); 438*7c478bd9Sstevel@tonic-gate /* 439*7c478bd9Sstevel@tonic-gate * Try to umount the mountpoint. 440*7c478bd9Sstevel@tonic-gate * If that fails, try the corresponding special. 441*7c478bd9Sstevel@tonic-gate * (This ordering is necessary for nfs umounts.) 442*7c478bd9Sstevel@tonic-gate * (for remote resources: if the first umount returns EBUSY 443*7c478bd9Sstevel@tonic-gate * don't call umount again - umount() with a resource name 444*7c478bd9Sstevel@tonic-gate * will return a misleading error to the user 445*7c478bd9Sstevel@tonic-gate */ 446*7c478bd9Sstevel@tonic-gate if (fflg) { 447*7c478bd9Sstevel@tonic-gate if (((ret = umount2(ment->mnt_mountp, MS_FORCE)) < 0) && 448*7c478bd9Sstevel@tonic-gate (errno != EBUSY && errno != ENOTSUP && 449*7c478bd9Sstevel@tonic-gate errno != EPERM)) 450*7c478bd9Sstevel@tonic-gate ret = umount2(ment->mnt_special, MS_FORCE); 451*7c478bd9Sstevel@tonic-gate } else { 452*7c478bd9Sstevel@tonic-gate if (((ret = umount2(ment->mnt_mountp, 0)) < 0) && 453*7c478bd9Sstevel@tonic-gate (errno != EBUSY) && (errno != EPERM)) 454*7c478bd9Sstevel@tonic-gate ret = umount2(ment->mnt_special, 0); 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate if (ret < 0) { 458*7c478bd9Sstevel@tonic-gate rpterr(ment->mnt_mountp); 459*7c478bd9Sstevel@tonic-gate if (errno != EINVAL && errno != EFAULT) 460*7c478bd9Sstevel@tonic-gate exit(1); 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate exitcode = 1; 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate exit(exitcode); 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate 468*7c478bd9Sstevel@tonic-gate void 469*7c478bd9Sstevel@tonic-gate rpterr(sp) 470*7c478bd9Sstevel@tonic-gate char *sp; 471*7c478bd9Sstevel@tonic-gate { 472*7c478bd9Sstevel@tonic-gate switch (errno) { 473*7c478bd9Sstevel@tonic-gate case EPERM: 474*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: permission denied\n"), myname); 475*7c478bd9Sstevel@tonic-gate break; 476*7c478bd9Sstevel@tonic-gate case ENXIO: 477*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: %s no device\n"), myname, sp); 478*7c478bd9Sstevel@tonic-gate break; 479*7c478bd9Sstevel@tonic-gate case ENOENT: 480*7c478bd9Sstevel@tonic-gate fprintf(stderr, 481*7c478bd9Sstevel@tonic-gate gettext("%s: %s no such file or directory\n"), 482*7c478bd9Sstevel@tonic-gate myname, sp); 483*7c478bd9Sstevel@tonic-gate break; 484*7c478bd9Sstevel@tonic-gate case EINVAL: 485*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: %s not mounted\n"), myname, sp); 486*7c478bd9Sstevel@tonic-gate break; 487*7c478bd9Sstevel@tonic-gate case EBUSY: 488*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: %s busy\n"), myname, sp); 489*7c478bd9Sstevel@tonic-gate break; 490*7c478bd9Sstevel@tonic-gate case ENOTBLK: 491*7c478bd9Sstevel@tonic-gate fprintf(stderr, 492*7c478bd9Sstevel@tonic-gate gettext("%s: %s block device required\n"), myname, sp); 493*7c478bd9Sstevel@tonic-gate break; 494*7c478bd9Sstevel@tonic-gate case ECOMM: 495*7c478bd9Sstevel@tonic-gate fprintf(stderr, 496*7c478bd9Sstevel@tonic-gate gettext("%s: warning: broken link detected\n"), myname); 497*7c478bd9Sstevel@tonic-gate break; 498*7c478bd9Sstevel@tonic-gate default: 499*7c478bd9Sstevel@tonic-gate perror(myname); 500*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: cannot unmount %s\n"), myname, sp); 501*7c478bd9Sstevel@tonic-gate } 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate void 505*7c478bd9Sstevel@tonic-gate usage() 506*7c478bd9Sstevel@tonic-gate { 507*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 508*7c478bd9Sstevel@tonic-gate "Usage:\n%s [-f] [-V] [-o specific_options] {special | mount-point}\n"), 509*7c478bd9Sstevel@tonic-gate myname); 510*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 511*7c478bd9Sstevel@tonic-gate "%s -a [-f] [-V] [-o specific_options] [mount_point ...]\n"), myname); 512*7c478bd9Sstevel@tonic-gate exit(1); 513*7c478bd9Sstevel@tonic-gate } 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate void 516*7c478bd9Sstevel@tonic-gate mnterror(flag) 517*7c478bd9Sstevel@tonic-gate int flag; 518*7c478bd9Sstevel@tonic-gate { 519*7c478bd9Sstevel@tonic-gate switch (flag) { 520*7c478bd9Sstevel@tonic-gate case MNT_TOOLONG: 521*7c478bd9Sstevel@tonic-gate fprintf(stderr, 522*7c478bd9Sstevel@tonic-gate gettext("%s: line in mnttab exceeds %d characters\n"), 523*7c478bd9Sstevel@tonic-gate myname, MNT_LINE_MAX-2); 524*7c478bd9Sstevel@tonic-gate break; 525*7c478bd9Sstevel@tonic-gate case MNT_TOOFEW: 526*7c478bd9Sstevel@tonic-gate fprintf(stderr, 527*7c478bd9Sstevel@tonic-gate gettext("%s: line in mnttab has too few entries\n"), 528*7c478bd9Sstevel@tonic-gate myname); 529*7c478bd9Sstevel@tonic-gate break; 530*7c478bd9Sstevel@tonic-gate default: 531*7c478bd9Sstevel@tonic-gate break; 532*7c478bd9Sstevel@tonic-gate } 533*7c478bd9Sstevel@tonic-gate } 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate /* 536*7c478bd9Sstevel@tonic-gate * Search the mlist linked list for the 537*7c478bd9Sstevel@tonic-gate * first match of specp or mntp. The list is expected to be in reverse 538*7c478bd9Sstevel@tonic-gate * order of /etc/mnttab. 539*7c478bd9Sstevel@tonic-gate * If both are specified, then both have to match. 540*7c478bd9Sstevel@tonic-gate * Returns the (mountent_t *) of the match, otherwise returns NULL. 541*7c478bd9Sstevel@tonic-gate */ 542*7c478bd9Sstevel@tonic-gate mountent_t * 543*7c478bd9Sstevel@tonic-gate getmntlast(mountent_t *mlist, char *specp, char *mntp) 544*7c478bd9Sstevel@tonic-gate { 545*7c478bd9Sstevel@tonic-gate int mfound, sfound; 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate for (/* */; mlist; mlist = mlist->link) { 548*7c478bd9Sstevel@tonic-gate mfound = sfound = 0; 549*7c478bd9Sstevel@tonic-gate if (mntp && (strcmp(mlist->ment.mnt_mountp, mntp) == 0)) { 550*7c478bd9Sstevel@tonic-gate if (specp == NULL) 551*7c478bd9Sstevel@tonic-gate return (mlist); 552*7c478bd9Sstevel@tonic-gate mfound++; 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate if (specp && (strcmp(mlist->ment.mnt_special, specp) == 0)) { 555*7c478bd9Sstevel@tonic-gate if (mntp == NULL) 556*7c478bd9Sstevel@tonic-gate return (mlist); 557*7c478bd9Sstevel@tonic-gate sfound++; 558*7c478bd9Sstevel@tonic-gate } 559*7c478bd9Sstevel@tonic-gate if (mfound && sfound) 560*7c478bd9Sstevel@tonic-gate return (mlist); 561*7c478bd9Sstevel@tonic-gate } 562*7c478bd9Sstevel@tonic-gate return (NULL); 563*7c478bd9Sstevel@tonic-gate } 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate /* 568*7c478bd9Sstevel@tonic-gate * Perform the parallel version of umount. Returns 0 if no errors occurred, 569*7c478bd9Sstevel@tonic-gate * non zero otherwise. 570*7c478bd9Sstevel@tonic-gate */ 571*7c478bd9Sstevel@tonic-gate int 572*7c478bd9Sstevel@tonic-gate parumount(char **mntlist, int count) 573*7c478bd9Sstevel@tonic-gate { 574*7c478bd9Sstevel@tonic-gate int maxfd = OPEN_MAX; 575*7c478bd9Sstevel@tonic-gate struct rlimit rl; 576*7c478bd9Sstevel@tonic-gate mountent_t **mntarray, **ml, *mp; 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate /* 579*7c478bd9Sstevel@tonic-gate * If no mount points are specified and none were found in mnttab, 580*7c478bd9Sstevel@tonic-gate * then end it all here. 581*7c478bd9Sstevel@tonic-gate */ 582*7c478bd9Sstevel@tonic-gate if (count == 0 && mntll == NULL) 583*7c478bd9Sstevel@tonic-gate return (0); 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate /* 586*7c478bd9Sstevel@tonic-gate * This is the process scaling section. After running a series 587*7c478bd9Sstevel@tonic-gate * of tests based on the number of simultaneous processes and 588*7c478bd9Sstevel@tonic-gate * processors available, optimum performance was achieved near or 589*7c478bd9Sstevel@tonic-gate * at (PROCN * 2). 590*7c478bd9Sstevel@tonic-gate */ 591*7c478bd9Sstevel@tonic-gate if ((maxrun = sysconf(_SC_NPROCESSORS_ONLN)) == -1) 592*7c478bd9Sstevel@tonic-gate maxrun = 4; 593*7c478bd9Sstevel@tonic-gate else 594*7c478bd9Sstevel@tonic-gate maxrun = maxrun * 2 + 1; 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { 597*7c478bd9Sstevel@tonic-gate rl.rlim_cur = rl.rlim_max; 598*7c478bd9Sstevel@tonic-gate if (setrlimit(RLIMIT_NOFILE, &rl) == 0) 599*7c478bd9Sstevel@tonic-gate maxfd = (int)rl.rlim_cur; 600*7c478bd9Sstevel@tonic-gate } 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate /* 603*7c478bd9Sstevel@tonic-gate * The parent needs to maintain 3 of its own fd's, plus 2 for 604*7c478bd9Sstevel@tonic-gate * each child (the stdout and stderr pipes). 605*7c478bd9Sstevel@tonic-gate */ 606*7c478bd9Sstevel@tonic-gate maxfd = (maxfd / 2) - 6; /* 6 takes care of temporary */ 607*7c478bd9Sstevel@tonic-gate /* periods of open fds */ 608*7c478bd9Sstevel@tonic-gate if (maxfd < maxrun) 609*7c478bd9Sstevel@tonic-gate maxrun = maxfd; 610*7c478bd9Sstevel@tonic-gate if (maxrun < 4) 611*7c478bd9Sstevel@tonic-gate maxrun = 4; /* sanity check */ 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate mntarray = make_mntarray(mntlist, count); 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate if (listlength == 0) { 616*7c478bd9Sstevel@tonic-gate if (count == 0) /* not an error, just none found */ 617*7c478bd9Sstevel@tonic-gate return (0); 618*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: no valid entries found in %s\n"), 619*7c478bd9Sstevel@tonic-gate myname, mnttab); 620*7c478bd9Sstevel@tonic-gate return (1); 621*7c478bd9Sstevel@tonic-gate } 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate /* 624*7c478bd9Sstevel@tonic-gate * Sort the entries based on their mount level only if lofs's are 625*7c478bd9Sstevel@tonic-gate * not present. 626*7c478bd9Sstevel@tonic-gate */ 627*7c478bd9Sstevel@tonic-gate if (lofscnt == 0) { 628*7c478bd9Sstevel@tonic-gate qsort((void *)mntarray, listlength, sizeof (mountent_t *), 629*7c478bd9Sstevel@tonic-gate mcompar); 630*7c478bd9Sstevel@tonic-gate /* 631*7c478bd9Sstevel@tonic-gate * If we do not detect a lofs by now, we never will. 632*7c478bd9Sstevel@tonic-gate */ 633*7c478bd9Sstevel@tonic-gate lofscnt = -1; 634*7c478bd9Sstevel@tonic-gate } 635*7c478bd9Sstevel@tonic-gate /* 636*7c478bd9Sstevel@tonic-gate * Now link them up so that a given pid is easier to find when 637*7c478bd9Sstevel@tonic-gate * we go to clean up after they are done. 638*7c478bd9Sstevel@tonic-gate */ 639*7c478bd9Sstevel@tonic-gate mntll = mntarray[0]; 640*7c478bd9Sstevel@tonic-gate for (ml = mntarray; mp = *ml; /* */) 641*7c478bd9Sstevel@tonic-gate mp->link = *++ml; 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate /* 644*7c478bd9Sstevel@tonic-gate * Try to handle interrupts in a reasonable way. 645*7c478bd9Sstevel@tonic-gate */ 646*7c478bd9Sstevel@tonic-gate sigset(SIGHUP, cleanup); 647*7c478bd9Sstevel@tonic-gate sigset(SIGQUIT, cleanup); 648*7c478bd9Sstevel@tonic-gate sigset(SIGINT, cleanup); 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate do_umounts(mntarray); /* do the umounts */ 651*7c478bd9Sstevel@tonic-gate return (exitcode); 652*7c478bd9Sstevel@tonic-gate } 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate /* 655*7c478bd9Sstevel@tonic-gate * Returns a mountent_t array based on mntlist. If mntlist is NULL, then 656*7c478bd9Sstevel@tonic-gate * it returns all mnttab entries with a few exceptions. Sets the global 657*7c478bd9Sstevel@tonic-gate * variable listlength to the number of entries in the array. 658*7c478bd9Sstevel@tonic-gate */ 659*7c478bd9Sstevel@tonic-gate mountent_t ** 660*7c478bd9Sstevel@tonic-gate make_mntarray(char **mntlist, int count) 661*7c478bd9Sstevel@tonic-gate { 662*7c478bd9Sstevel@tonic-gate mountent_t *mp, **mpp; 663*7c478bd9Sstevel@tonic-gate int ndx; 664*7c478bd9Sstevel@tonic-gate char *cp; 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate if (count > 0) 667*7c478bd9Sstevel@tonic-gate listlength = count; 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate mpp = (mountent_t **)malloc(sizeof (*mp) * (listlength + 1)); 670*7c478bd9Sstevel@tonic-gate if (mpp == NULL) 671*7c478bd9Sstevel@tonic-gate nomem(); 672*7c478bd9Sstevel@tonic-gate 673*7c478bd9Sstevel@tonic-gate if (count == 0) { 674*7c478bd9Sstevel@tonic-gate if (mntll == NULL) { /* no entries? */ 675*7c478bd9Sstevel@tonic-gate listlength = 0; 676*7c478bd9Sstevel@tonic-gate return (NULL); 677*7c478bd9Sstevel@tonic-gate } 678*7c478bd9Sstevel@tonic-gate /* 679*7c478bd9Sstevel@tonic-gate * No mount list specified: take all mnttab mount points 680*7c478bd9Sstevel@tonic-gate * except for a few cases. 681*7c478bd9Sstevel@tonic-gate */ 682*7c478bd9Sstevel@tonic-gate for (ndx = 0, mp = mntll; mp; mp = mp->link) { 683*7c478bd9Sstevel@tonic-gate if (fsstrinlist(mp->ment.mnt_mountp, keeplist)) 684*7c478bd9Sstevel@tonic-gate continue; 685*7c478bd9Sstevel@tonic-gate mp->mlevel = fsgetmlevel(mp->ment.mnt_mountp); 686*7c478bd9Sstevel@tonic-gate if (mp->ment.mnt_fstype && 687*7c478bd9Sstevel@tonic-gate (strcmp(mp->ment.mnt_fstype, MNTTYPE_LOFS) == 0)) 688*7c478bd9Sstevel@tonic-gate lofscnt++; 689*7c478bd9Sstevel@tonic-gate 690*7c478bd9Sstevel@tonic-gate mpp[ndx++] = mp; 691*7c478bd9Sstevel@tonic-gate } 692*7c478bd9Sstevel@tonic-gate mpp[ndx] = NULL; 693*7c478bd9Sstevel@tonic-gate listlength = ndx; 694*7c478bd9Sstevel@tonic-gate return (mpp); 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate /* 698*7c478bd9Sstevel@tonic-gate * A list of mount points was specified on the command line. 699*7c478bd9Sstevel@tonic-gate * Build an array out of these. 700*7c478bd9Sstevel@tonic-gate */ 701*7c478bd9Sstevel@tonic-gate for (ndx = 0; count--; ) { 702*7c478bd9Sstevel@tonic-gate cp = *mntlist++; 703*7c478bd9Sstevel@tonic-gate if (realpath(cp, resolve) == NULL) { 704*7c478bd9Sstevel@tonic-gate fprintf(stderr, 705*7c478bd9Sstevel@tonic-gate gettext("%s: warning: can't resolve %s\n"), 706*7c478bd9Sstevel@tonic-gate myname, cp); 707*7c478bd9Sstevel@tonic-gate exitcode = 1; 708*7c478bd9Sstevel@tonic-gate mp = getmntlast(mntll, NULL, cp); /* try anyways */ 709*7c478bd9Sstevel@tonic-gate } else 710*7c478bd9Sstevel@tonic-gate mp = getmntlast(mntll, NULL, resolve); 711*7c478bd9Sstevel@tonic-gate if (mp == NULL) { 712*7c478bd9Sstevel@tonic-gate struct mnttab mnew; 713*7c478bd9Sstevel@tonic-gate /* 714*7c478bd9Sstevel@tonic-gate * Then we've reached the end without finding 715*7c478bd9Sstevel@tonic-gate * what we are looking for, but we still have to 716*7c478bd9Sstevel@tonic-gate * try to umount it: append it to mntarray. 717*7c478bd9Sstevel@tonic-gate */ 718*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 719*7c478bd9Sstevel@tonic-gate "%s: warning: %s not found in %s\n"), 720*7c478bd9Sstevel@tonic-gate myname, resolve, mnttab); 721*7c478bd9Sstevel@tonic-gate exitcode = 1; 722*7c478bd9Sstevel@tonic-gate mntnull(&mnew); 723*7c478bd9Sstevel@tonic-gate mnew.mnt_special = mnew.mnt_mountp = strdup(resolve); 724*7c478bd9Sstevel@tonic-gate if (mnew.mnt_special == NULL) 725*7c478bd9Sstevel@tonic-gate nomem(); 726*7c478bd9Sstevel@tonic-gate mp = new_mountent(&mnew); 727*7c478bd9Sstevel@tonic-gate } 728*7c478bd9Sstevel@tonic-gate if (mp->ment.mnt_fstype && 729*7c478bd9Sstevel@tonic-gate (strcmp(mp->ment.mnt_fstype, MNTTYPE_LOFS) == 0)) 730*7c478bd9Sstevel@tonic-gate lofscnt++; 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate mp->mlevel = fsgetmlevel(mp->ment.mnt_mountp); 733*7c478bd9Sstevel@tonic-gate mpp[ndx++] = mp; 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate mpp[ndx] = NULL; 736*7c478bd9Sstevel@tonic-gate listlength = ndx; 737*7c478bd9Sstevel@tonic-gate return (mpp); 738*7c478bd9Sstevel@tonic-gate } 739*7c478bd9Sstevel@tonic-gate 740*7c478bd9Sstevel@tonic-gate /* 741*7c478bd9Sstevel@tonic-gate * Returns the tail of a linked list of all mnttab entries. I.e, it's faster 742*7c478bd9Sstevel@tonic-gate * to return the mnttab in reverse order. 743*7c478bd9Sstevel@tonic-gate * Sets listlength to the number of entries in the list. 744*7c478bd9Sstevel@tonic-gate * Returns NULL if none are found. 745*7c478bd9Sstevel@tonic-gate */ 746*7c478bd9Sstevel@tonic-gate mountent_t * 747*7c478bd9Sstevel@tonic-gate getmntall() 748*7c478bd9Sstevel@tonic-gate { 749*7c478bd9Sstevel@tonic-gate FILE *fp; 750*7c478bd9Sstevel@tonic-gate mountent_t *mtail; 751*7c478bd9Sstevel@tonic-gate int cnt = 0, ret; 752*7c478bd9Sstevel@tonic-gate struct mnttab mget; 753*7c478bd9Sstevel@tonic-gate 754*7c478bd9Sstevel@tonic-gate if ((fp = fopen(mnttab, "r")) == NULL) { 755*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: warning cannot open %s\n"), 756*7c478bd9Sstevel@tonic-gate myname, mnttab); 757*7c478bd9Sstevel@tonic-gate return (0); 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate mtail = NULL; 760*7c478bd9Sstevel@tonic-gate 761*7c478bd9Sstevel@tonic-gate while ((ret = getmntent(fp, &mget)) != -1) { 762*7c478bd9Sstevel@tonic-gate mountent_t *mp; 763*7c478bd9Sstevel@tonic-gate 764*7c478bd9Sstevel@tonic-gate if (ret > 0) { 765*7c478bd9Sstevel@tonic-gate mnterror(ret); 766*7c478bd9Sstevel@tonic-gate continue; 767*7c478bd9Sstevel@tonic-gate } 768*7c478bd9Sstevel@tonic-gate 769*7c478bd9Sstevel@tonic-gate mp = new_mountent(&mget); 770*7c478bd9Sstevel@tonic-gate mp->link = mtail; 771*7c478bd9Sstevel@tonic-gate mtail = mp; 772*7c478bd9Sstevel@tonic-gate cnt++; 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate fclose(fp); 775*7c478bd9Sstevel@tonic-gate if (mtail == NULL) { 776*7c478bd9Sstevel@tonic-gate listlength = 0; 777*7c478bd9Sstevel@tonic-gate return (NULL); 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate listlength = cnt; 780*7c478bd9Sstevel@tonic-gate return (mtail); 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate void 784*7c478bd9Sstevel@tonic-gate do_umounts(mountent_t **mntarray) 785*7c478bd9Sstevel@tonic-gate { 786*7c478bd9Sstevel@tonic-gate mountent_t *mp, *mpprev, **ml = mntarray; 787*7c478bd9Sstevel@tonic-gate int cnt = listlength; 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate /* 790*7c478bd9Sstevel@tonic-gate * Main loop for the forked children: 791*7c478bd9Sstevel@tonic-gate */ 792*7c478bd9Sstevel@tonic-gate for (mpprev = *ml; mp = *ml; mpprev = mp, ml++, cnt--) { 793*7c478bd9Sstevel@tonic-gate pid_t pid; 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate /* 796*7c478bd9Sstevel@tonic-gate * Check to see if we cross a mount level: e.g., 797*7c478bd9Sstevel@tonic-gate * /a/b/c -> /a/b. If so, we need to wait for all current 798*7c478bd9Sstevel@tonic-gate * umounts to finish before umounting the rest. 799*7c478bd9Sstevel@tonic-gate * 800*7c478bd9Sstevel@tonic-gate * Also, we unmount serially as long as there are lofs's 801*7c478bd9Sstevel@tonic-gate * to mount to avoid improper umount ordering. 802*7c478bd9Sstevel@tonic-gate */ 803*7c478bd9Sstevel@tonic-gate if (mp->mlevel < mpprev->mlevel || lofscnt > 0) 804*7c478bd9Sstevel@tonic-gate while (nrun > 0 && (dowait() != -1)) 805*7c478bd9Sstevel@tonic-gate ; 806*7c478bd9Sstevel@tonic-gate 807*7c478bd9Sstevel@tonic-gate if (lofscnt == 0) { 808*7c478bd9Sstevel@tonic-gate /* 809*7c478bd9Sstevel@tonic-gate * We can now go to parallel umounting. 810*7c478bd9Sstevel@tonic-gate */ 811*7c478bd9Sstevel@tonic-gate qsort((void *)ml, cnt, sizeof (mountent_t *), mcompar); 812*7c478bd9Sstevel@tonic-gate mp = *ml; /* possible first entry */ 813*7c478bd9Sstevel@tonic-gate lofscnt--; /* so we don't do this again */ 814*7c478bd9Sstevel@tonic-gate } 815*7c478bd9Sstevel@tonic-gate 816*7c478bd9Sstevel@tonic-gate while (setup_iopipe(mp) == -1 && (dowait() != -1)) 817*7c478bd9Sstevel@tonic-gate ; 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate while (nrun >= maxrun && (dowait() != -1)) /* throttle */ 820*7c478bd9Sstevel@tonic-gate ; 821*7c478bd9Sstevel@tonic-gate 822*7c478bd9Sstevel@tonic-gate #ifdef CACHEFS_BUG 823*7c478bd9Sstevel@tonic-gate /* 824*7c478bd9Sstevel@tonic-gate * If this is the back file system, then let cachefs/umount 825*7c478bd9Sstevel@tonic-gate * unmount it. 826*7c478bd9Sstevel@tonic-gate */ 827*7c478bd9Sstevel@tonic-gate if (strstr(mp->ment.mnt_mountp, BACKMNT_NAME)) 828*7c478bd9Sstevel@tonic-gate continue; 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate 831*7c478bd9Sstevel@tonic-gate if (mp->ment.mnt_fstype && 832*7c478bd9Sstevel@tonic-gate (strcmp(mp->ment.mnt_fstype, "cachefs") == 0)) { 833*7c478bd9Sstevel@tonic-gate while (cachefs_running && (dowait() != -1)) 834*7c478bd9Sstevel@tonic-gate ; 835*7c478bd9Sstevel@tonic-gate cachefs_running = 1; 836*7c478bd9Sstevel@tonic-gate } 837*7c478bd9Sstevel@tonic-gate #endif 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate if ((pid = fork()) == -1) { 840*7c478bd9Sstevel@tonic-gate perror("fork"); 841*7c478bd9Sstevel@tonic-gate cleanup(-1); 842*7c478bd9Sstevel@tonic-gate /* not reached */ 843*7c478bd9Sstevel@tonic-gate } 844*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 845*7c478bd9Sstevel@tonic-gate if (dflg && pid > 0) { 846*7c478bd9Sstevel@tonic-gate fprintf(stderr, "parent %d: umounting %d %s\n", 847*7c478bd9Sstevel@tonic-gate getpid(), pid, mp->ment.mnt_mountp); 848*7c478bd9Sstevel@tonic-gate } 849*7c478bd9Sstevel@tonic-gate #endif 850*7c478bd9Sstevel@tonic-gate if (pid == 0) { /* child */ 851*7c478bd9Sstevel@tonic-gate signal(SIGHUP, SIG_IGN); 852*7c478bd9Sstevel@tonic-gate signal(SIGQUIT, SIG_IGN); 853*7c478bd9Sstevel@tonic-gate signal(SIGINT, SIG_IGN); 854*7c478bd9Sstevel@tonic-gate setup_output(mp); 855*7c478bd9Sstevel@tonic-gate doexec(&mp->ment); 856*7c478bd9Sstevel@tonic-gate perror("exec"); 857*7c478bd9Sstevel@tonic-gate exit(1); 858*7c478bd9Sstevel@tonic-gate } 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate /* parent */ 861*7c478bd9Sstevel@tonic-gate (void) close(mp->sopipe[WRPIPE]); 862*7c478bd9Sstevel@tonic-gate (void) close(mp->sepipe[WRPIPE]); 863*7c478bd9Sstevel@tonic-gate mp->pid = pid; 864*7c478bd9Sstevel@tonic-gate nrun++; 865*7c478bd9Sstevel@tonic-gate } 866*7c478bd9Sstevel@tonic-gate cleanup(0); 867*7c478bd9Sstevel@tonic-gate } 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate /* 870*7c478bd9Sstevel@tonic-gate * cleanup the existing children and exit with an error 871*7c478bd9Sstevel@tonic-gate * if asig != 0. 872*7c478bd9Sstevel@tonic-gate */ 873*7c478bd9Sstevel@tonic-gate void 874*7c478bd9Sstevel@tonic-gate cleanup(int asig) 875*7c478bd9Sstevel@tonic-gate { 876*7c478bd9Sstevel@tonic-gate /* 877*7c478bd9Sstevel@tonic-gate * Let the stragglers finish. 878*7c478bd9Sstevel@tonic-gate */ 879*7c478bd9Sstevel@tonic-gate while (nrun > 0 && (dowait() != -1)) 880*7c478bd9Sstevel@tonic-gate ; 881*7c478bd9Sstevel@tonic-gate if (asig != 0) 882*7c478bd9Sstevel@tonic-gate exit(1); 883*7c478bd9Sstevel@tonic-gate } 884*7c478bd9Sstevel@tonic-gate 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate /* 887*7c478bd9Sstevel@tonic-gate * Waits for 1 child to die. 888*7c478bd9Sstevel@tonic-gate * 889*7c478bd9Sstevel@tonic-gate * Returns -1 if no children are left to wait for. 890*7c478bd9Sstevel@tonic-gate * Returns 0 if a child died without an error. 891*7c478bd9Sstevel@tonic-gate * Returns 1 if a child died with an error. 892*7c478bd9Sstevel@tonic-gate * Sets the global exitcode if an error occurred. 893*7c478bd9Sstevel@tonic-gate */ 894*7c478bd9Sstevel@tonic-gate int 895*7c478bd9Sstevel@tonic-gate dowait() 896*7c478bd9Sstevel@tonic-gate { 897*7c478bd9Sstevel@tonic-gate int wstat, child, ret; 898*7c478bd9Sstevel@tonic-gate mountent_t *mp, *prevp; 899*7c478bd9Sstevel@tonic-gate 900*7c478bd9Sstevel@tonic-gate if ((child = wait(&wstat)) == -1) 901*7c478bd9Sstevel@tonic-gate return (-1); 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate if (WIFEXITED(wstat)) /* this should always be true */ 904*7c478bd9Sstevel@tonic-gate ret = WEXITSTATUS(wstat); 905*7c478bd9Sstevel@tonic-gate else 906*7c478bd9Sstevel@tonic-gate ret = 1; /* assume some kind of error */ 907*7c478bd9Sstevel@tonic-gate nrun--; 908*7c478bd9Sstevel@tonic-gate if (ret) 909*7c478bd9Sstevel@tonic-gate exitcode = 1; 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate /* 912*7c478bd9Sstevel@tonic-gate * Find our child so we can process its std output, if any. 913*7c478bd9Sstevel@tonic-gate * This search gets smaller and smaller as children are cleaned 914*7c478bd9Sstevel@tonic-gate * up. 915*7c478bd9Sstevel@tonic-gate */ 916*7c478bd9Sstevel@tonic-gate for (prevp = NULL, mp = mntll; mp; mp = mp->link) { 917*7c478bd9Sstevel@tonic-gate if (mp->pid != child) { 918*7c478bd9Sstevel@tonic-gate prevp = mp; 919*7c478bd9Sstevel@tonic-gate continue; 920*7c478bd9Sstevel@tonic-gate } 921*7c478bd9Sstevel@tonic-gate /* 922*7c478bd9Sstevel@tonic-gate * Found: let's remove it from this list. 923*7c478bd9Sstevel@tonic-gate */ 924*7c478bd9Sstevel@tonic-gate if (prevp) { 925*7c478bd9Sstevel@tonic-gate prevp->link = mp->link; 926*7c478bd9Sstevel@tonic-gate mp->link = NULL; 927*7c478bd9Sstevel@tonic-gate } 928*7c478bd9Sstevel@tonic-gate break; 929*7c478bd9Sstevel@tonic-gate } 930*7c478bd9Sstevel@tonic-gate 931*7c478bd9Sstevel@tonic-gate if (mp == NULL) { 932*7c478bd9Sstevel@tonic-gate /* 933*7c478bd9Sstevel@tonic-gate * This should never happen. 934*7c478bd9Sstevel@tonic-gate */ 935*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 936*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 937*7c478bd9Sstevel@tonic-gate "%s: unknown child %d\n"), myname, child); 938*7c478bd9Sstevel@tonic-gate #endif 939*7c478bd9Sstevel@tonic-gate exitcode = 1; 940*7c478bd9Sstevel@tonic-gate return (1); 941*7c478bd9Sstevel@tonic-gate } 942*7c478bd9Sstevel@tonic-gate doio(mp); /* Any output? */ 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate if (mp->ment.mnt_fstype && 945*7c478bd9Sstevel@tonic-gate (strcmp(mp->ment.mnt_fstype, MNTTYPE_LOFS) == 0)) 946*7c478bd9Sstevel@tonic-gate lofscnt--; 947*7c478bd9Sstevel@tonic-gate 948*7c478bd9Sstevel@tonic-gate #ifdef CACHEFS_BUG 949*7c478bd9Sstevel@tonic-gate if (mp->ment.mnt_fstype && 950*7c478bd9Sstevel@tonic-gate (strcmp(mp->ment.mnt_fstype, "cachefs") == 0)) 951*7c478bd9Sstevel@tonic-gate cachefs_running = 0; 952*7c478bd9Sstevel@tonic-gate #endif 953*7c478bd9Sstevel@tonic-gate 954*7c478bd9Sstevel@tonic-gate return (ret); 955*7c478bd9Sstevel@tonic-gate } 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate static const mountent_t zmount = { 0 }; 958*7c478bd9Sstevel@tonic-gate 959*7c478bd9Sstevel@tonic-gate mountent_t * 960*7c478bd9Sstevel@tonic-gate new_mountent(struct mnttab *ment) 961*7c478bd9Sstevel@tonic-gate { 962*7c478bd9Sstevel@tonic-gate mountent_t *new; 963*7c478bd9Sstevel@tonic-gate 964*7c478bd9Sstevel@tonic-gate new = (mountent_t *)malloc(sizeof (*new)); 965*7c478bd9Sstevel@tonic-gate if (new == NULL) 966*7c478bd9Sstevel@tonic-gate nomem(); 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate *new = zmount; 969*7c478bd9Sstevel@tonic-gate if (ment->mnt_special && 970*7c478bd9Sstevel@tonic-gate (new->ment.mnt_special = strdup(ment->mnt_special)) == NULL) 971*7c478bd9Sstevel@tonic-gate nomem(); 972*7c478bd9Sstevel@tonic-gate if (ment->mnt_mountp && 973*7c478bd9Sstevel@tonic-gate (new->ment.mnt_mountp = strdup(ment->mnt_mountp)) == NULL) 974*7c478bd9Sstevel@tonic-gate nomem(); 975*7c478bd9Sstevel@tonic-gate if (ment->mnt_fstype && 976*7c478bd9Sstevel@tonic-gate (new->ment.mnt_fstype = strdup(ment->mnt_fstype)) == NULL) 977*7c478bd9Sstevel@tonic-gate nomem(); 978*7c478bd9Sstevel@tonic-gate return (new); 979*7c478bd9Sstevel@tonic-gate } 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate 982*7c478bd9Sstevel@tonic-gate /* 983*7c478bd9Sstevel@tonic-gate * Sort in descending order of "mount level". For example, /a/b/c is 984*7c478bd9Sstevel@tonic-gate * placed before /a/b . 985*7c478bd9Sstevel@tonic-gate */ 986*7c478bd9Sstevel@tonic-gate int 987*7c478bd9Sstevel@tonic-gate mcompar(const void *a, const void *b) 988*7c478bd9Sstevel@tonic-gate { 989*7c478bd9Sstevel@tonic-gate mountent_t *a1, *b1; 990*7c478bd9Sstevel@tonic-gate 991*7c478bd9Sstevel@tonic-gate a1 = *(mountent_t **)a; 992*7c478bd9Sstevel@tonic-gate b1 = *(mountent_t **)b; 993*7c478bd9Sstevel@tonic-gate return (b1->mlevel - a1->mlevel); 994*7c478bd9Sstevel@tonic-gate } 995*7c478bd9Sstevel@tonic-gate 996*7c478bd9Sstevel@tonic-gate /* 997*7c478bd9Sstevel@tonic-gate * The purpose of this routine is to form stdout and stderr 998*7c478bd9Sstevel@tonic-gate * pipes for the children's output. The parent then reads and writes it 999*7c478bd9Sstevel@tonic-gate * out it serially in order to ensure that the output is 1000*7c478bd9Sstevel@tonic-gate * not garbled. 1001*7c478bd9Sstevel@tonic-gate */ 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate int 1004*7c478bd9Sstevel@tonic-gate setup_iopipe(mountent_t *mp) 1005*7c478bd9Sstevel@tonic-gate { 1006*7c478bd9Sstevel@tonic-gate /* 1007*7c478bd9Sstevel@tonic-gate * Make a stdout and stderr pipe. This should never fail. 1008*7c478bd9Sstevel@tonic-gate */ 1009*7c478bd9Sstevel@tonic-gate if (pipe(mp->sopipe) == -1) 1010*7c478bd9Sstevel@tonic-gate return (-1); 1011*7c478bd9Sstevel@tonic-gate if (pipe(mp->sepipe) == -1) { 1012*7c478bd9Sstevel@tonic-gate (void) close(mp->sopipe[RDPIPE]); 1013*7c478bd9Sstevel@tonic-gate (void) close(mp->sopipe[WRPIPE]); 1014*7c478bd9Sstevel@tonic-gate return (-1); 1015*7c478bd9Sstevel@tonic-gate } 1016*7c478bd9Sstevel@tonic-gate /* 1017*7c478bd9Sstevel@tonic-gate * Don't block on an empty pipe. 1018*7c478bd9Sstevel@tonic-gate */ 1019*7c478bd9Sstevel@tonic-gate (void) fcntl(mp->sopipe[RDPIPE], F_SETFL, O_NDELAY|O_NONBLOCK); 1020*7c478bd9Sstevel@tonic-gate (void) fcntl(mp->sepipe[RDPIPE], F_SETFL, O_NDELAY|O_NONBLOCK); 1021*7c478bd9Sstevel@tonic-gate return (0); 1022*7c478bd9Sstevel@tonic-gate } 1023*7c478bd9Sstevel@tonic-gate 1024*7c478bd9Sstevel@tonic-gate /* 1025*7c478bd9Sstevel@tonic-gate * Called by a child to attach its stdout and stderr to the write side of 1026*7c478bd9Sstevel@tonic-gate * the pipes. 1027*7c478bd9Sstevel@tonic-gate */ 1028*7c478bd9Sstevel@tonic-gate void 1029*7c478bd9Sstevel@tonic-gate setup_output(mountent_t *mp) 1030*7c478bd9Sstevel@tonic-gate { 1031*7c478bd9Sstevel@tonic-gate (void) close(fileno(stdout)); 1032*7c478bd9Sstevel@tonic-gate (void) dup(mp->sopipe[WRPIPE]); 1033*7c478bd9Sstevel@tonic-gate (void) close(mp->sopipe[WRPIPE]); 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate (void) close(fileno(stderr)); 1036*7c478bd9Sstevel@tonic-gate (void) dup(mp->sepipe[WRPIPE]); 1037*7c478bd9Sstevel@tonic-gate (void) close(mp->sepipe[WRPIPE]); 1038*7c478bd9Sstevel@tonic-gate } 1039*7c478bd9Sstevel@tonic-gate 1040*7c478bd9Sstevel@tonic-gate /* 1041*7c478bd9Sstevel@tonic-gate * Parent uses this to print any stdout or stderr output issued by 1042*7c478bd9Sstevel@tonic-gate * the child. 1043*7c478bd9Sstevel@tonic-gate */ 1044*7c478bd9Sstevel@tonic-gate static void 1045*7c478bd9Sstevel@tonic-gate doio(mountent_t *mp) 1046*7c478bd9Sstevel@tonic-gate { 1047*7c478bd9Sstevel@tonic-gate int bytes; 1048*7c478bd9Sstevel@tonic-gate 1049*7c478bd9Sstevel@tonic-gate while ((bytes = read(mp->sepipe[RDPIPE], ibuf, sizeof (ibuf))) > 0) 1050*7c478bd9Sstevel@tonic-gate write(fileno(stderr), ibuf, bytes); 1051*7c478bd9Sstevel@tonic-gate while ((bytes = read(mp->sopipe[RDPIPE], ibuf, sizeof (ibuf))) > 0) 1052*7c478bd9Sstevel@tonic-gate write(fileno(stdout), ibuf, bytes); 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate (void) close(mp->sopipe[RDPIPE]); 1055*7c478bd9Sstevel@tonic-gate (void) close(mp->sepipe[RDPIPE]); 1056*7c478bd9Sstevel@tonic-gate } 1057*7c478bd9Sstevel@tonic-gate 1058*7c478bd9Sstevel@tonic-gate void 1059*7c478bd9Sstevel@tonic-gate nomem() 1060*7c478bd9Sstevel@tonic-gate { 1061*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: out of memory\n"), myname); 1062*7c478bd9Sstevel@tonic-gate /* 1063*7c478bd9Sstevel@tonic-gate * Let the stragglers finish. 1064*7c478bd9Sstevel@tonic-gate */ 1065*7c478bd9Sstevel@tonic-gate while (nrun > 0 && (dowait() != -1)) 1066*7c478bd9Sstevel@tonic-gate ; 1067*7c478bd9Sstevel@tonic-gate exit(1); 1068*7c478bd9Sstevel@tonic-gate } 1069