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 (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 
  27 /*
  28  * Module:      zones.c
  29  * Group:       libinstzones
  30  * Description: Provide "zones" interface for install consolidation code
  31  *
  32  * Public Methods:
  33  *  z_create_zone_admin_file - Given a location to create the file, and
  34  *      optionally an existing administration file, generate an
  35  *      administration file that can be used to perform "non-interactive"
  36  *      operations in a non-global zone.
  37  *  z_free_zone_list - free contents of zoneList_t object
  38  *  z_get_nonglobal_zone_list - return zoneList_t object describing all
  39  *      non-global native zones
  40  *  z_get_nonglobal_zone_list_by_brand - return zoneList_t object describing
  41  *      all non-global zones matching the list of zone brands passed in.
  42  *  z_free_brand_list - free contents of a zoneBrandList_t object
  43  *  z_make_brand_list - return a zoneBrandList_t object describing the list
  44  *      of all zone brands passed in.
  45  *  z_get_zonename - return the name of the current zone
  46  *  z_global_only - Determine if the global zone is only zone on the spec list
  47  *  z_lock_this_zone - lock this zone
  48  *  z_lock_zones - lock specified zones
  49  *  z_mount_in_lz - Mount global zone directory in specified zone's root file
  50  *      system
  51  *  z_non_global_zones_exist - Determine if any non-global native zones exist
  52  *  z_on_zone_spec - Determine if named zone is on the zone_spec list
  53  *  z_running_in_global_zone - Determine if running in the "global" zone
  54  *  z_set_output_functions - Link program specific output functions
  55  *  z_set_zone_root - Set root for zones library operations
  56  *  z_set_zone_spec - Set list of zones on which actions will be performed
  57  *  z_umount_lz_mount - Unmount directory mounted with z_mount_in_lz
  58  *  z_unlock_this_zone - unlock this zone
  59  *  z_unlock_zones - unlock specified zones
  60  *  z_verify_zone_spec - Verify list of zones on which actions will be performed
  61  *  z_zlist_change_zone_state - Change the current state of the specified zone
  62  *  z_zlist_get_current_state - Determine the current kernel state of the
  63  *      specified zone
  64  *  z_zlist_get_original_state - Return the original kernal state of the
  65  *      specified zone
  66  *  z_zlist_get_scratch - Determine name of scratch zone
  67  *  z_zlist_get_zonename - Determine name of specified zone
  68  *  z_zlist_get_zonepath - Determine zonepath of specified zone
  69  *  z_zlist_restore_zone_state - Return the zone to the state it was originally
  70  *      in
  71  *  z_zone_exec - Execute a Unix command in a specified zone and return results
  72  *  z_zones_are_implemented - Determine if any zone operations can be performed
  73  *  z_is_zone_branded - determine if zone has a non-native brand
  74  *  z_is_zone_brand_in_list - determine if the zone's brand matches the
  75  *      brand list passed in.
  76  *  z_brands_are_implemented - determine if branded zones are implemented on
  77  *                      this system
  78  */
  79 
  80 /*
  81  * System includes
  82  */
  83 
  84 #include <stdio.h>
  85 #include <stdlib.h>
  86 #include <unistd.h>
  87 #include <fcntl.h>
  88 #include <ctype.h>
  89 #include <sys/types.h>
  90 #include <sys/param.h>
  91 #include <sys/sysmacros.h>
  92 #include <string.h>
  93 #include <strings.h>
  94 #include <sys/stat.h>
  95 #include <stdarg.h>
  96 #include <limits.h>
  97 #include <errno.h>
  98 #include <time.h>
  99 #include <signal.h>
 100 #include <stropts.h>
 101 #include <wait.h>
 102 #include <zone.h>
 103 #include <sys/brand.h>
 104 #include <libintl.h>
 105 #include <locale.h>
 106 #include <libzonecfg.h>
 107 #include <libcontract.h>
 108 #include <sys/contract/process.h>
 109 #include <sys/ctfs.h>
 110 #include <assert.h>
 111 #include <dlfcn.h>
 112 #include <link.h>
 113 #include <time.h>
 114 
 115 /*
 116  * local includes
 117  */
 118 
 119 /*
 120  * When _INSTZONES_LIB_Z_DEFINE_GLOBAL_DATA is defined,
 121  * instzones_lib.h will define the z_global_data structure.
 122  * Otherwise an extern to the structure is inserted.
 123  */
 124 
 125 #define _INSTZONES_LIB_Z_DEFINE_GLOBAL_DATA
 126 #include "instzones_lib.h"
 127 #include "zones_strings.h"
 128 
 129 /*
 130  * Private structures
 131  */
 132 
 133 #define CLUSTER_BRAND_NAME      "cluster"
 134 
 135 /* maximum number of arguments to exec() call */
 136 
 137 #define UUID_FORMAT     "%02d%02d%02d%03d-%02d%02d%02d%d-%016llx"
 138 
 139 /*
 140  * Library Function Prototypes
 141  */
 142 
 143 #define streq(a, b) (strcmp((a), (b)) == 0)
 144 
 145 /*
 146  * Local Function Prototypes
 147  */
 148 
 149 /*
 150  * global internal (private) declarations
 151  */
 152 
 153 /*
 154  * *****************************************************************************
 155  * global external (public) functions
 156  * *****************************************************************************
 157  */
 158 
 159 /*
 160  * Name:        z_create_zone_admin_file
 161  * Description: Given a location to create the file, and optionally an existing
 162  *              administration file, generate an administration file that
 163  *              can be used to perform "non-interactive" operations in a
 164  *              non-global zone.
 165  * Arguments:   a_zoneAdminFilename - pointer to string representing the
 166  *                      full path of zone admin file to create
 167  *              a_userAdminFilename - pointer to string representing the path
 168  *                      to an existing "user" administration file - the
 169  *                      administration file created will contain the
 170  *                      settings contained in this file, modified as
 171  *                      appropriate to supress any interaction;
 172  *                      If this is == NULL then the administration file
 173  *                      created will not contain any extra settings
 174  * Returns:     boolean_t
 175  *                      == B_TRUE - admin file created
 176  *                      == B_FALSE - failed to create admin file
 177  */
 178 
 179 boolean_t
 180 z_create_zone_admin_file(char *a_zoneAdminFilename, char *a_userAdminFilename)
 181 {
 182         FILE    *zFp;
 183         FILE    *uFp = (FILE *)NULL;
 184 
 185         /* entry assertions */
 186 
 187         assert(a_zoneAdminFilename != NULL);
 188         assert(*a_zoneAdminFilename != '\0');
 189 
 190         /* create temporary zone admin file */
 191 
 192         zFp = fopen(a_zoneAdminFilename, "w");
 193         if (zFp == (FILE *)NULL) {
 194                 return (B_FALSE);
 195         }
 196 
 197         /* open user admin file if specified */
 198 
 199         if (a_userAdminFilename != (char *)NULL) {
 200                 uFp = fopen(a_userAdminFilename, "r");
 201         }
 202 
 203         /* create default admin file for zone pkg ops if no user admin file */
 204 
 205         if (uFp == (FILE *)NULL) {
 206                 /* create default admin file */
 207                 (void) fprintf(zFp, "action=nocheck\nauthentication=nocheck\n"
 208                     "basedir=default\nconflict=nocheck\nidepend=nocheck\n"
 209                     "instance=unique\npartial=nocheck\nrdepend=nocheck\n"
 210                     "runlevel=nocheck\nsetuid=nocheck\nspace=nocheck\n"
 211                     "mail=\n");
 212         } else for (;;) {
 213                 /* copy user admin file substitute/change appropriate entries */
 214                 char    buf[LINE_MAX+1];
 215                 char    *p;
 216 
 217                 /* read next line of user admin file */
 218 
 219                 p = fgets(buf, sizeof (buf), uFp);
 220                 if (p == (char *)NULL) {
 221                         (void) fclose(uFp);
 222                         break;
 223                 }
 224 
 225                 /* modify / replace / accept as appropriate */
 226 
 227                 if (strncmp(buf, "instance=quit", 13) == 0) {
 228                         (void) fprintf(zFp, "%s", "instance=unique\n");
 229                         /*LINTED*/
 230                 } else if (strncmp(buf, "keystore=", 9) == 0) {
 231                 } else if (strncmp(buf, "action=", 7) == 0) {
 232                         (void) fprintf(zFp, "action=nocheck\n");
 233                 } else if (strncmp(buf, "authentication=", 15) == 0) {
 234                         (void) fprintf(zFp, "authentication=nocheck\n");
 235                 } else if (strncmp(buf, "conflict=", 9) == 0) {
 236                         (void) fprintf(zFp, "conflict=nocheck\n");
 237                 } else if (strncmp(buf, "idepend=", 8) == 0) {
 238                         (void) fprintf(zFp, "idepend=nocheck\n");
 239                 } else if (strncmp(buf, "mail=", 5) == 0) {
 240                         (void) fprintf(zFp, "mail=\n");
 241                 } else if (strncmp(buf, "partial=", 8) == 0) {
 242                         (void) fprintf(zFp, "partial=nocheck\n");
 243                 } else if (strncmp(buf, "rdepend=", 8) == 0) {
 244                         (void) fprintf(zFp, "rdepend=nocheck\n");
 245                 } else if (strncmp(buf, "runlevel=", 9) == 0) {
 246                         (void) fprintf(zFp, "runlevel=nocheck\n");
 247                 } else if (strncmp(buf, "setuid=", 7) == 0) {
 248                         (void) fprintf(zFp, "setuid=nocheck\n");
 249                 } else if (strncmp(buf, "space=", 6) == 0) {
 250                         (void) fprintf(zFp, "space=nocheck\n");
 251                 } else {
 252                         (void) fprintf(zFp, "%s", buf);
 253                 }
 254         }
 255 
 256         /* close admin file and return success */
 257 
 258         (void) fclose(zFp);
 259         return (B_TRUE);
 260 }
 261 
 262 /*
 263  * Name:        z_brands_are_implemented
 264  * Description: Determine if any branded zones may be present
 265  * Arguments:   void
 266  * Returns:     boolean_t
 267  *                      == B_TRUE - branded zones are supported
 268  *                      == B_FALSE - branded zones are not supported
 269  */
 270 
 271 boolean_t
 272 z_brands_are_implemented(void)
 273 {
 274 static  boolean_t       _brandsImplementedDetermined = B_FALSE;
 275 static  boolean_t       _brandsAreImplemented = B_FALSE;
 276 
 277         /* if availability has not been determined, cache it now */
 278 
 279         if (!_brandsImplementedDetermined) {
 280                 _brandsImplementedDetermined = B_TRUE;
 281                 _brandsAreImplemented = _z_brands_are_implemented();
 282                 if (_brandsAreImplemented) {
 283                         _z_echoDebug(DBG_BRANDS_ARE_IMPLEMENTED);
 284                 } else {
 285                         _z_echoDebug(DBG_BRANDS_NOT_IMPLEMENTED);
 286                 }
 287         }
 288 
 289         /* return cached answer */
 290 
 291         return (_brandsAreImplemented);
 292 }
 293 
 294 /*
 295  * Name:        z_free_zone_list
 296  * Description: free contents of zoneList_t object
 297  * Arguments:   a_zlst - handle to zoneList_t object to free
 298  * Returns:     void
 299  */
 300 
 301 void
 302 z_free_zone_list(zoneList_t a_zlst)
 303 {
 304         int     numzones;
 305 
 306         /* ignore empty list */
 307 
 308         if (a_zlst == (zoneList_t)NULL) {
 309                 return;
 310         }
 311 
 312         /* free each entry in the zone list */
 313 
 314         for (numzones = 0; a_zlst[numzones]._zlName != (char *)NULL;
 315             numzones++) {
 316                 zoneListElement_t *zelm = &a_zlst[numzones];
 317 
 318                 /* free zone name string */
 319 
 320                 free(zelm->_zlName);
 321 
 322                 /* free zonepath string */
 323 
 324                 if (zelm->_zlPath != (char *)NULL) {
 325                         free(zelm->_zlPath);
 326                 }
 327 
 328         }
 329 
 330         /* free handle to the list */
 331 
 332         free(a_zlst);
 333 }
 334 
 335 /*
 336  * Name:        z_get_nonglobal_zone_list
 337  * Description: return zoneList_t object describing all non-global
 338  *              native zones - branded zones are not included in list
 339  * Arguments:   None.
 340  * Returns:     zoneList_t
 341  *                      == NULL - error, list could not be generated
 342  *                      != NULL - success, list returned
 343  * NOTE:        Any zoneList_t returned is placed in new storage for the
 344  *              calling function. The caller must use 'z_free_zone_list' to
 345  *              dispose of the storage once the list is no longer needed.
 346  */
 347 
 348 zoneList_t
 349 z_get_nonglobal_zone_list(void)
 350 {
 351         zoneList_t zones;
 352         zoneBrandList_t *brands = NULL;
 353 
 354         if ((brands = z_make_brand_list("native cluster", " ")) == NULL)
 355                 return (NULL);
 356 
 357         zones = z_get_nonglobal_zone_list_by_brand(brands);
 358 
 359         z_free_brand_list(brands);
 360 
 361         return (zones);
 362 }
 363 
 364 /*
 365  * Name:        z_free_brand_list
 366  * Description: Free contents of zoneBrandList_t object
 367  * Arguments:   brands - pointer to zoneBrandList_t object to free
 368  * Returns:     void
 369  */
 370 void
 371 z_free_brand_list(zoneBrandList_t *brands)
 372 {
 373         while (brands != NULL) {
 374                 zoneBrandList_t *temp = brands;
 375                 free(brands->string_ptr);
 376                 brands = brands->next;
 377                 free(temp);
 378         }
 379 }
 380 
 381 /*
 382  * Name:        z_make_brand_list
 383  * Description: Given a string with a list of brand name delimited by
 384  *              the delimeter passed in, build a zoneBrandList_t structure
 385  *              with the list of brand names and return it to the caller.
 386  * Arguments:
 387  *              brands - const char pointer to string list of brand names
 388  *              delim - const char pointer to string representing the
 389  *                      delimeter for brands string.
 390  * Returns:     zoneBrandList_t *
 391  *                      == NULL - error, list could not be generated
 392  *                      != NULL - success, list returned
 393  * NOTE:        Any zoneBrandList_t returned is placed in new storage for the
 394  *              calling function.  The caller must use 'z_free_brand_list' to
 395  *              dispose of the storage once the list is no longer needed.
 396  */
 397 zoneBrandList_t *
 398 z_make_brand_list(const char *brands, const char *delim)
 399 {
 400         zoneBrandList_t *brand = NULL, *head = NULL;
 401         char            *blist = NULL;
 402         char            *str = NULL;
 403 
 404         if ((blist = strdup(brands)) == NULL)
 405                 return (NULL);
 406 
 407         if ((str = strtok(blist, delim)) != NULL) {
 408                 if ((brand = (zoneBrandList_t *)
 409                     malloc(sizeof (struct _zoneBrandList))) == NULL) {
 410                         return (NULL);
 411                 }
 412 
 413                 head = brand;
 414                 brand->string_ptr = strdup(str);
 415                 brand->next = NULL;
 416 
 417                 while ((str = strtok(NULL, delim)) != NULL) {
 418                         if ((brand->next = (zoneBrandList_t *)
 419                             malloc(sizeof (struct _zoneBrandList))) == NULL) {
 420                                 return (NULL);
 421                         }
 422 
 423                         brand = brand->next;
 424                         brand->string_ptr = strdup(str);
 425                         brand->next = NULL;
 426                 }
 427         }
 428 
 429         free(blist);
 430         return (head);
 431 }
 432 
 433 /*
 434  * Name:        z_get_nonglobal_zone_list_by_brand
 435  * Description: return zoneList_t object describing all non-global
 436  *              zones matching the list of brands passed in.
 437  * Arguments:   brands - The list of zone brands to look for.
 438  * Returns:     zoneList_t
 439  *                      == NULL - error, list could not be generated
 440  *                      != NULL - success, list returned
 441  * NOTE:        Any zoneList_t returned is placed in new storage for the
 442  *              calling function. The caller must use 'z_free_zone_list' to
 443  *              dispose of the storage once the list is no longer needed.
 444  */
 445 zoneList_t
 446 z_get_nonglobal_zone_list_by_brand(zoneBrandList_t *brands)
 447 {
 448         FILE            *zoneIndexFP;
 449         int             numzones = 0;
 450         struct zoneent  *ze;
 451         zoneList_t      zlst = NULL;
 452         FILE            *mapFP;
 453         char            zonename[ZONENAME_MAX];
 454         zone_spec_t     *zent;
 455 
 456         /* if zones are not implemented, return empty list */
 457 
 458         if (!z_zones_are_implemented()) {
 459                 return ((zoneList_t)NULL);
 460         }
 461 
 462         /*
 463          * Open the zone index file.  Note that getzoneent_private() handles
 464          * NULL.
 465          */
 466         zoneIndexFP = setzoneent();
 467 
 468         mapFP = zonecfg_open_scratch("", B_FALSE);
 469 
 470         /* index file open; scan all zones; see if any are at least installed */
 471 
 472         while ((ze = getzoneent_private(zoneIndexFP)) != NULL) {
 473                 zone_state_t    st;
 474 
 475                 /* skip the global zone */
 476 
 477                 if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0) {
 478                         free(ze);
 479                         continue;
 480                 }
 481 
 482                 /*
 483                  * skip any zones with brands not on the brand list
 484                  */
 485                 if (!z_is_zone_brand_in_list(ze->zone_name, brands)) {
 486                         free(ze);
 487                         continue;
 488                 }
 489 
 490                 /*
 491                  * If the user specified an explicit zone list, then ignore any
 492                  * zones that aren't on that list.
 493                  */
 494                 if ((zent = _z_global_data._zone_spec) != NULL) {
 495                         while (zent != NULL) {
 496                                 if (strcmp(zent->zl_name, ze->zone_name) == 0)
 497                                         break;
 498                                 zent = zent->zl_next;
 499                         }
 500                         if (zent == NULL) {
 501                                 free(ze);
 502                                 continue;
 503                         }
 504                 }
 505 
 506                 /* non-global zone: create entry for this zone */
 507 
 508                 if (numzones == 0) {
 509                         zlst = (zoneList_t)_z_calloc(
 510                             sizeof (zoneListElement_t)*2);
 511                 } else {
 512                         zlst = (zoneList_t)_z_realloc(zlst,
 513                             sizeof (zoneListElement_t)*(numzones+2));
 514                         (void) memset(&zlst[numzones], 0L,
 515                             sizeof (zoneListElement_t)*2);
 516                 }
 517 
 518                 /*
 519                  * remember the zone name, zonepath and the current
 520                  * zone state of the zone.
 521                  */
 522                 zlst[numzones]._zlName = _z_strdup(ze->zone_name);
 523                 zlst[numzones]._zlPath = _z_strdup(ze->zone_path);
 524                 zlst[numzones]._zlOrigInstallState = ze->zone_state;
 525                 zlst[numzones]._zlCurrInstallState = ze->zone_state;
 526 
 527                 /* get the zone kernel status */
 528 
 529                 if (zone_get_state(ze->zone_name, &st) != Z_OK) {
 530                         st = ZONE_STATE_INCOMPLETE;
 531                 }
 532 
 533                 _z_echoDebug(DBG_ZONES_NGZ_LIST_STATES,
 534                     ze->zone_name, ze->zone_state, st);
 535 
 536                 /*
 537                  * For a scratch zone, we need to know the kernel zone name.
 538                  */
 539                 if (zonecfg_in_alt_root() && mapFP != NULL &&
 540                     zonecfg_find_scratch(mapFP, ze->zone_name,
 541                     zonecfg_get_root(), zonename, sizeof (zonename)) != -1) {
 542                         free(zlst[numzones]._zlScratchName);
 543                         zlst[numzones]._zlScratchName = _z_strdup(zonename);
 544                 }
 545 
 546                 /*
 547                  * remember the current kernel status of the zone.
 548                  */
 549 
 550                 zlst[numzones]._zlOrigKernelStatus = st;
 551                 zlst[numzones]._zlCurrKernelStatus = st;
 552 
 553                 numzones++;
 554                 free(ze);
 555         }
 556 
 557         /* close the index file */
 558         endzoneent(zoneIndexFP);
 559 
 560         if (mapFP != NULL)
 561                 zonecfg_close_scratch(mapFP);
 562 
 563         /* return generated list */
 564 
 565         return (zlst);
 566 }
 567 
 568 /*
 569  * Name:        z_get_zonename
 570  * Description: return the name of the current zone
 571  * Arguments:   void
 572  * Returns:     char *
 573  *                      - pointer to string representing the name of the current
 574  *                      zone
 575  * NOTE:        Any string returned is placed in new storage for the
 576  *              calling function. The caller must use 'Free' to dispose
 577  *              of the storage once the string is no longer needed.
 578  */
 579 
 580 char *
 581 z_get_zonename(void)
 582 {
 583         ssize_t         zonenameLen;
 584         char            zonename[ZONENAME_MAX];
 585         zoneid_t        zoneid = (zoneid_t)-1;
 586 
 587         /* if zones are not implemented, return "" */
 588 
 589         if (!z_zones_are_implemented()) {
 590                 return (_z_strdup(""));
 591         }
 592 
 593         /* get the zone i.d. of the current zone */
 594 
 595         zoneid = getzoneid();
 596 
 597         /* get the name of the current zone */
 598 
 599         zonenameLen = getzonenamebyid(zoneid, zonename, sizeof (zonename));
 600 
 601         /* return "" if could not get zonename */
 602 
 603         if (zonenameLen < 1) {
 604                 return (_z_strdup(""));
 605         }
 606 
 607         return (_z_strdup(zonename));
 608 }
 609 
 610 /*
 611  * Name:        z_global_only
 612  * Description: Determine if the global zone is only zone on the spec list.
 613  * Arguments:   None
 614  * Returns:     B_TRUE if global zone is the only zone on the list,
 615  *              B_FALSE otherwise.
 616  */
 617 
 618 boolean_t
 619 z_global_only(void)
 620 {
 621         /* return true if zones are not implemented - treate as global zone */
 622 
 623         if (!z_zones_are_implemented()) {
 624                 return (B_TRUE);
 625         }
 626 
 627         /* return true if this is the global zone */
 628 
 629         if (_z_global_data._zone_spec != NULL &&
 630             _z_global_data._zone_spec->zl_next == NULL &&
 631             strcmp(_z_global_data._zone_spec->zl_name, GLOBAL_ZONENAME) == 0) {
 632                 return (B_TRUE);
 633         }
 634 
 635         /* return false - not the global zone */
 636 
 637         return (B_FALSE);
 638 }
 639 
 640 /*
 641  * Name:        z_lock_this_zone
 642  * Description: lock this zone
 643  * Arguments:   a_lflags - [RO, *RO] - (ZLOCKS_T)
 644  *                      Flags indicating which locks to acquire
 645  * Returns:     boolean_t
 646  *                      == B_TRUE - success specified locks acquired
 647  *                      == B_FALSE - failure specified locks not acquired
 648  * NOTE: the lock objects for "this zone" are maintained internally.
 649  */
 650 
 651 boolean_t
 652 z_lock_this_zone(ZLOCKS_T a_lflags)
 653 {
 654         boolean_t       b;
 655         char            *zoneName;
 656         pid_t           pid = (pid_t)0;
 657 
 658         /* entry assertions */
 659 
 660         assert(a_lflags != ZLOCKS_NONE);
 661 
 662         /* entry debugging info */
 663 
 664         _z_echoDebug(DBG_ZONES_LCK_THIS, a_lflags);
 665 
 666         zoneName = z_get_zonename();
 667         pid = getpid();
 668 
 669         /* lock zone administration */
 670 
 671         if (a_lflags & ZLOCKS_ZONE_ADMIN) {
 672                 b = _z_lock_zone_object(&_z_global_data._z_ObjectLocks,
 673                     zoneName, LOBJ_ZONEADMIN, pid,
 674                     MSG_ZONES_LCK_THIS_ZONEADM,
 675                     ERR_ZONES_LCK_THIS_ZONEADM);
 676                 if (!b) {
 677                         (void) free(zoneName);
 678                         return (B_FALSE);
 679                 }
 680         }
 681 
 682         /* lock package administration always */
 683 
 684         if (a_lflags & ZLOCKS_PKG_ADMIN) {
 685                 b = _z_lock_zone_object(&_z_global_data._z_ObjectLocks,
 686                     zoneName, LOBJ_PKGADMIN, pid,
 687                     MSG_ZONES_LCK_THIS_PKGADM,
 688                     ERR_ZONES_LCK_THIS_PKGADM);
 689                 if (!b) {
 690                         (void) z_unlock_this_zone(a_lflags);
 691                         (void) free(zoneName);
 692                         return (B_FALSE);
 693                 }
 694         }
 695 
 696         (void) free(zoneName);
 697 
 698         return (B_TRUE);
 699 }
 700 
 701 /*
 702  * Name:        z_lock_zones
 703  * Description: lock specified zones
 704  * Arguments:   a_zlst - zoneList_t object describing zones to lock
 705  *              a_lflags - [RO, *RO] - (ZLOCKS_T)
 706  *                      Flags indicating which locks to acquire
 707  * Returns:     boolean_t
 708  *                      == B_TRUE - success, zones locked
 709  *                      == B_FALSE - failure, zones not locked
 710  */
 711 
 712 boolean_t
 713 z_lock_zones(zoneList_t a_zlst, ZLOCKS_T a_lflags)
 714 {
 715         boolean_t       b;
 716         int             i;
 717 
 718         /* entry assertions */
 719 
 720         assert(a_lflags != ZLOCKS_NONE);
 721 
 722         /* entry debugging info */
 723 
 724         _z_echoDebug(DBG_ZONES_LCK_ZONES, a_lflags);
 725 
 726         /* if zones are not implemented, return TRUE */
 727 
 728         if (z_zones_are_implemented() == B_FALSE) {
 729                 _z_echoDebug(DBG_ZONES_LCK_ZONES_UNIMP);
 730                 return (B_TRUE);
 731         }
 732 
 733         /* lock this zone first before locking other zones */
 734 
 735         b = z_lock_this_zone(a_lflags);
 736         if (b == B_FALSE) {
 737                 return (b);
 738         }
 739 
 740         /* ignore empty list */
 741 
 742         if (a_zlst == (zoneList_t)NULL) {
 743                 _z_echoDebug(DBG_ZONES_LCK_ZONES_NOZONES);
 744                 return (B_FALSE);
 745         }
 746 
 747         /* zones exist */
 748 
 749         _z_echoDebug(DBG_ZONES_LCK_ZONES_EXIST);
 750 
 751         /*
 752          * lock each listed zone that is currently running
 753          */
 754 
 755         for (i = 0; (a_zlst[i]._zlName != (char *)NULL); i++) {
 756                 /* ignore zone if already locked */
 757                 if (a_zlst[i]._zlStatus & ZST_LOCKED) {
 758                         continue;
 759                 }
 760 
 761                 /* ignore zone if not running */
 762                 if (a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_RUNNING &&
 763                     a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_MOUNTED) {
 764                         continue;
 765                 }
 766 
 767                 /*
 768                  * mark zone locked - if interrupted out during lock, an attempt
 769                  * will be made to release the lock
 770                  */
 771                 a_zlst[i]._zlStatus |= ZST_LOCKED;
 772 
 773                 /* lock this zone */
 774                 b = _z_lock_zone(&a_zlst[i], a_lflags);
 775 
 776                 /* on failure unlock all zones and return error */
 777                 if (b != B_TRUE) {
 778                         _z_program_error(ERR_ZONES_LCK_ZONES_FAILED,
 779                             a_zlst[i]._zlName);
 780                         (void) z_unlock_zones(a_zlst, a_lflags);
 781                         return (B_FALSE);
 782                 }
 783         }
 784 
 785         /* success */
 786 
 787         return (B_TRUE);
 788 }
 789 
 790 /*
 791  * Name:        z_mount_in_lz
 792  * Description: Mount global zone directory in specified zone's root file system
 793  * Arguments:   r_lzMountPoint - pointer to handle to string - on success, the
 794  *                      full path to the mount point relative to the global zone
 795  *                      root file system is returned here - this is needed to
 796  *                      unmount the directory when it is no longer needed
 797  *              r_lzRootPath - pointer to handle to string - on success, the
 798  *                      full path to the mount point relative to the specified
 799  *                      zone's root file system is returned here - this is
 800  *                      passed to any command executing in the specified zone to
 801  *                      access the directory mounted
 802  *              a_zoneName - pointer to string representing the name of the zone
 803  *                      to mount the specified global zone directory in
 804  *              a_gzPath - pointer to string representing the full absolute path
 805  *                      of the global zone directory to LOFS mount inside of the
 806  *                      specified non-global zone
 807  *              a_mountPointPrefix - pointer to string representing the prefix
 808  *                      to be used when creating the mount point name in the
 809  *                      specified zone's root directory
 810  * Returns:     boolean_t
 811  *                      == B_TRUE - global zone directory mounted successfully
 812  *                      == B_FALSE - failed to mount directory in specified zone
 813  * NOTE:        Any strings returned is placed in new storage for the
 814  *              calling function. The caller must use 'Free' to dispose
 815  *              of the storage once the strings are no longer needed.
 816  */
 817 
 818 boolean_t
 819 z_mount_in_lz(char **r_lzMountPoint, char **r_lzRootPath, char *a_zoneName,
 820         char *a_gzPath, char *a_mountPointPrefix)
 821 {
 822         char            lzRootPath[MAXPATHLEN] = {'\0'};
 823         char            uuid[MAXPATHLEN] = {'\0'};
 824         char            gzMountPoint[MAXPATHLEN] = {'\0'};
 825         char            lzMountPoint[MAXPATHLEN] = {'\0'};
 826         hrtime_t        hretime;
 827         int             err;
 828         int             slen;
 829         struct tm       tstruct;
 830         time_t          thetime;
 831         zoneid_t        zid;
 832 
 833         /* entry assertions */
 834 
 835         assert(a_zoneName != (char *)NULL);
 836         assert(*a_zoneName != '\0');
 837         assert(a_gzPath != (char *)NULL);
 838         assert(*a_gzPath != '\0');
 839         assert(r_lzMountPoint != (char **)NULL);
 840         assert(r_lzRootPath != (char **)NULL);
 841 
 842         /* entry debugging info */
 843 
 844         _z_echoDebug(DBG_ZONES_MOUNT_IN_LZ_ENTRY, a_zoneName, a_gzPath);
 845 
 846         /* reset returned non-global zone mount point path handle */
 847 
 848         *r_lzMountPoint = (char *)NULL;
 849         *r_lzRootPath = (char *)NULL;
 850 
 851         /* if zones are not implemented, return FALSE */
 852 
 853         if (z_zones_are_implemented() == B_FALSE) {
 854                 return (B_FALSE);
 855         }
 856 
 857         /* error if global zone path is not absolute */
 858 
 859         if (*a_gzPath != '/') {
 860                 _z_program_error(ERR_GZPATH_NOT_ABSOLUTE, a_gzPath);
 861                 return (B_FALSE);
 862         }
 863 
 864         /* error if global zone path does not exist */
 865 
 866         if (_z_is_directory(a_gzPath) != 0) {
 867                 _z_program_error(ERR_GZPATH_NOT_DIR, a_gzPath, strerror(errno));
 868                 return (B_FALSE);
 869         }
 870 
 871         /* verify that specified non-global zone exists */
 872 
 873         err = zone_get_id(a_zoneName, &zid);
 874         if (err != Z_OK) {
 875                 _z_program_error(ERR_GET_ZONEID, a_zoneName,
 876                     zonecfg_strerror(err));
 877                 return (B_FALSE);
 878         }
 879 
 880         /* obtain global zone path to non-global zones root file system */
 881 
 882         err = zone_get_rootpath(a_zoneName, lzRootPath, sizeof (lzRootPath));
 883         if (err != Z_OK) {
 884                 _z_program_error(ERR_NO_ZONE_ROOTPATH, a_zoneName,
 885                     zonecfg_strerror(err));
 886                 return (B_FALSE);
 887         }
 888 
 889         if (lzRootPath[0] == '\0') {
 890                 _z_program_error(ERR_ROOTPATH_EMPTY, a_zoneName);
 891                 return (B_FALSE);
 892         }
 893 
 894         /*
 895          * lofs resolve the non-global zone's root path first in case
 896          * its in a path that's been lofs mounted read-only.
 897          */
 898         z_resolve_lofs(lzRootPath, sizeof (lzRootPath));
 899 
 900         /* verify that the root path exists */
 901 
 902         if (_z_is_directory(lzRootPath) != 0) {
 903                 _z_program_error(ERR_LZROOT_NOTDIR, lzRootPath,
 904                     strerror(errno));
 905                 return (B_FALSE);
 906         }
 907 
 908         /*
 909          * generate a unique key - the key is the same length as unique uid
 910          * but contains different information that is as unique as can be made;
 911          * include current hires time (nanosecond real timer). Such a unique
 912          * i.d. will look like:
 913          *              0203104092-1145345-0004e94d6af481a0
 914          */
 915 
 916         hretime = gethrtime();
 917 
 918         thetime = time((time_t *)NULL);
 919         (void) localtime_r(&thetime, &tstruct);
 920 
 921         slen = snprintf(uuid, sizeof (uuid),
 922             UUID_FORMAT,
 923             tstruct.tm_mday, tstruct.tm_mon, tstruct.tm_year,
 924             tstruct.tm_yday, tstruct.tm_hour, tstruct.tm_min,
 925             tstruct.tm_sec,     tstruct.tm_wday, hretime);
 926         if (slen > sizeof (uuid)) {
 927                 _z_program_error(ERR_GZMOUNT_SNPRINTFUUID_FAILED,
 928                     UUID_FORMAT, sizeof (uuid));
 929                 return (B_FALSE);
 930         }
 931 
 932         /* create the global zone mount point */
 933 
 934         slen = snprintf(gzMountPoint, sizeof (gzMountPoint), "%s/.SUNW_%s_%s",
 935             lzRootPath,
 936             a_mountPointPrefix ? a_mountPointPrefix : "zones", uuid);
 937         if (slen > sizeof (gzMountPoint)) {
 938                 _z_program_error(ERR_GZMOUNT_SNPRINTFGMP_FAILED,
 939                     "%s/.SUNW_%s_%s", lzRootPath,
 940                     a_mountPointPrefix ? a_mountPointPrefix : "zones",
 941                     uuid, sizeof (gzMountPoint));
 942                 return (B_FALSE);
 943         }
 944 
 945         slen = snprintf(lzMountPoint, sizeof (lzMountPoint), "%s",
 946             gzMountPoint+strlen(lzRootPath));
 947         if (slen > sizeof (lzMountPoint)) {
 948                 _z_program_error(ERR_GZMOUNT_SNPRINTFLMP_FAILED,
 949                     "%s", gzMountPoint+strlen(lzRootPath),
 950                     sizeof (lzMountPoint));
 951                 return (B_FALSE);
 952         }
 953 
 954         _z_echoDebug(DBG_MNTPT_NAMES, a_gzPath, a_zoneName, gzMountPoint,
 955             lzMountPoint);
 956 
 957         /* error if the mount point already exists */
 958 
 959         if (_z_is_directory(gzMountPoint) == 0) {
 960                 _z_program_error(ERR_ZONEROOT_NOTDIR, gzMountPoint,
 961                     a_zoneName, strerror(errno));
 962                 return (B_FALSE);
 963         }
 964 
 965         /* create the temporary mount point */
 966 
 967         if (mkdir(gzMountPoint, 0600) != 0) {
 968                 _z_program_error(ERR_MNTPT_MKDIR, gzMountPoint, a_zoneName,
 969                     strerror(errno));
 970                 return (B_FALSE);
 971         }
 972 
 973         /* mount the global zone path on the non-global zone root file system */
 974 
 975         err = mount(a_gzPath, gzMountPoint, MS_RDONLY|MS_DATA, "lofs",
 976             (char *)NULL, 0, (char *)NULL, 0);
 977         if (err != 0) {
 978                 _z_program_error(ERR_GZMOUNT_FAILED, a_gzPath,
 979                     gzMountPoint, a_zoneName, strerror(errno));
 980                 return (B_FALSE);
 981         }
 982 
 983         /* success - return both mountpoints to caller */
 984 
 985         *r_lzMountPoint = _z_strdup(gzMountPoint);
 986 
 987         *r_lzRootPath = _z_strdup(lzMountPoint);
 988 
 989         /* return success */
 990 
 991         return (B_TRUE);
 992 }
 993 
 994 /*
 995  * Name:        z_non_global_zones_exist
 996  * Description: Determine if any non-global native zones exist
 997  * Arguments:   None.
 998  * Returns:     boolean_t
 999  *      == B_TRUE - at least one non-global native zone exists
1000  *      == B_FALSE - no non-global native zone exists
1001  */
1002 
1003 boolean_t
1004 z_non_global_zones_exist(void)
1005 {
1006         FILE            *zoneIndexFP;
1007         boolean_t       anyExist = B_FALSE;
1008         struct zoneent  *ze;
1009         zone_spec_t     *zent;
1010 
1011         /* if zones are not implemented, return FALSE */
1012 
1013         if (z_zones_are_implemented() == B_FALSE) {
1014                 return (B_FALSE);
1015         }
1016 
1017         /* determine if any zones are configured */
1018         zoneIndexFP = setzoneent();
1019         if (zoneIndexFP == NULL) {
1020                 return (B_FALSE);
1021         }
1022 
1023         /* index file open; scan all zones; see if any are at least installed */
1024 
1025         while ((ze = getzoneent_private(zoneIndexFP)) != NULL) {
1026                 /*
1027                  * If the user specified an explicit zone list, then ignore any
1028                  * zones that aren't on that list.
1029                  */
1030                 if ((zent = _z_global_data._zone_spec) != NULL) {
1031                         while (zent != NULL) {
1032                                 if (strcmp(zent->zl_name, ze->zone_name) == 0)
1033                                         break;
1034                                 zent = zent->zl_next;
1035                         }
1036                         if (zent == NULL) {
1037                                 free(ze);
1038                                 continue;
1039                         }
1040                 }
1041 
1042                 /* skip the global zone */
1043                 if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0) {
1044                         free(ze);
1045                         continue;
1046                 }
1047 
1048                 /* skip any branded zones */
1049                 if (z_is_zone_branded(ze->zone_name)) {
1050                         free(ze);
1051                         continue;
1052                 }
1053 
1054                 /* is this zone installed? */
1055                 if (ze->zone_state >= ZONE_STATE_INSTALLED) {
1056                         free(ze);
1057                         anyExist = B_TRUE;
1058                         break;
1059                 }
1060                 free(ze);
1061         }
1062 
1063         /* close the index file */
1064 
1065         endzoneent(zoneIndexFP);
1066 
1067         /* return results */
1068 
1069         return (anyExist);
1070 }
1071 
1072 /*
1073  * Name:        z_on_zone_spec
1074  * Description: Determine if named zone is on the zone_spec list.
1075  * Arguments:   Pointer to name to test.
1076  * Returns:     B_TRUE if named zone is on the list or if the user specified
1077  *              no list at all (all zones is the default), B_FALSE otherwise.
1078  */
1079 
1080 boolean_t
1081 z_on_zone_spec(const char *zonename)
1082 {
1083         zone_spec_t     *zent;
1084 
1085         /* entry assertions */
1086 
1087         assert(zonename != NULL);
1088         assert(*zonename != '\0');
1089 
1090         /* return true if zones not implemented or no zone spec list defined */
1091 
1092         if (!z_zones_are_implemented() || _z_global_data._zone_spec == NULL) {
1093                 return (B_TRUE);
1094         }
1095 
1096         /* return true if named zone is on the zone spec list */
1097 
1098         for (zent = _z_global_data._zone_spec;
1099             zent != NULL; zent = zent->zl_next) {
1100                 if (strcmp(zent->zl_name, zonename) == 0)
1101                         return (B_TRUE);
1102         }
1103 
1104         /* named zone is not on the zone spec list */
1105 
1106         return (B_FALSE);
1107 }
1108 
1109 /*
1110  * Name:        z_running_in_global_zone
1111  * Description: Determine if running in the "global" zone
1112  * Arguments:   void
1113  * Returns:     boolean_t
1114  *                      == B_TRUE - running in global zone
1115  *                      == B_FALSE - not running in global zone
1116  */
1117 
1118 boolean_t
1119 z_running_in_global_zone(void)
1120 {
1121         static  boolean_t       _zoneIdDetermined = B_FALSE;
1122         static  boolean_t       _zoneIsGlobal = B_FALSE;
1123 
1124         /* if ID has not been determined, cache it now */
1125 
1126         if (!_zoneIdDetermined) {
1127                 _zoneIdDetermined = B_TRUE;
1128                 _zoneIsGlobal = _z_running_in_global_zone();
1129         }
1130 
1131         return (_zoneIsGlobal);
1132 }
1133 
1134 /*
1135  * Name:        z_set_output_functions
1136  * Description: Link program specific output functions to this library.
1137  * Arguments:   a_echo_fcn - (_z_printf_fcn_t)
1138  *                      Function to call to cause "normal operation" messages
1139  *                      to be output/displayed
1140  *              a_echo_debug_fcn - (_z_printf_fcn_t)
1141  *                      Function to call to cause "debugging" messages
1142  *                      to be output/displayed
1143  *              a_progerr_fcn - (_z_printf_fcn_t)
1144  *                      Function to call to cause "program error" messages
1145  *                      to be output/displayed
1146  * Returns:     void
1147  * NOTE:        If NULL is specified for any function, then the functionality
1148  *              associated with that function is disabled.
1149  * NOTE:        The function pointers provided must call a function that
1150  *              takes two arguments:
1151  *                      function(char *format, char *message)
1152  *              Any registered function will be called like:
1153  *                      function("%s", "message")
1154  */
1155 
1156 void
1157 z_set_output_functions(_z_printf_fcn_t a_echo_fcn,
1158     _z_printf_fcn_t a_echo_debug_fcn,
1159     _z_printf_fcn_t a_progerr_fcn)
1160 {
1161         _z_global_data._z_echo = a_echo_fcn;
1162         _z_global_data._z_echo_debug = a_echo_debug_fcn;
1163         _z_global_data._z_progerr = a_progerr_fcn;
1164 }
1165 
1166 /*
1167  * Name:        z_set_zone_root
1168  * Description: Set root for zones library operations
1169  * Arguments:   Path to root of boot environment containing zone; must be
1170  *              absolute.
1171  * Returns:     None.
1172  * NOTE:        Must be called before performing any zone-related operations.
1173  *              (Currently called directly by set_inst_root() during -R
1174  *              argument handling.)
1175  */
1176 
1177 void
1178 z_set_zone_root(const char *zroot)
1179 {
1180         char *rootdir;
1181 
1182         /* if zones are not implemented, just return */
1183 
1184         if (!z_zones_are_implemented())
1185                 return;
1186 
1187         /* entry assertions */
1188 
1189         assert(zroot != NULL);
1190 
1191         rootdir = _z_strdup((char *)zroot);
1192         z_canoninplace(rootdir);
1193 
1194         if (strcmp(rootdir, "/") == 0) {
1195                 rootdir[0] = '\0';
1196         }
1197 
1198         /* free any existing cached root path */
1199         if (*_z_global_data._z_root_dir != '\0') {
1200                 free(_z_global_data._z_root_dir);
1201                 _z_global_data._z_root_dir = NULL;
1202         }
1203 
1204         /* store duplicate of new zone root path */
1205 
1206         if (*rootdir != '\0') {
1207                 _z_global_data._z_root_dir = _z_strdup(rootdir);
1208         } else {
1209                 _z_global_data._z_root_dir = "";
1210         }
1211 
1212         /* set zone root path */
1213 
1214         zonecfg_set_root(rootdir);
1215 
1216         free(rootdir);
1217 }
1218 
1219 /*
1220  * Name:        z_set_zone_spec
1221  * Description: Set list of zones on which actions will be performed.
1222  * Arguments:   Whitespace-separated list of zone names.
1223  * Returns:     0 on success, -1 on error.
1224  * NOTES:       Will call _z_program_error if argument can't be parsed or
1225  *              memory not available.
1226  */
1227 
1228 int
1229 z_set_zone_spec(const char *zlist)
1230 {
1231         const char      *zend;
1232         ptrdiff_t       zlen;
1233         zone_spec_t     *zent;
1234         zone_spec_t     *zhead;
1235         zone_spec_t     **znextp = &zhead;
1236 
1237         /* entry assertions */
1238 
1239         assert(zlist != NULL);
1240 
1241         /* parse list to zone_spec_t list, store in global data */
1242 
1243         for (;;) {
1244                 while (isspace(*zlist)) {
1245                         zlist++;
1246                 }
1247                 if (*zlist == '\0') {
1248                         break;
1249                 }
1250                 for (zend = zlist; *zend != '\0'; zend++) {
1251                         if (isspace(*zend)) {
1252                                 break;
1253                         }
1254                 }
1255                 zlen = ((ptrdiff_t)zend) - ((ptrdiff_t)zlist);
1256                 if (zlen >= ZONENAME_MAX) {
1257                         _z_program_error(ERR_ZONE_NAME_ILLEGAL, zlen, zlist);
1258                         return (-1);
1259                 }
1260                 zent = _z_malloc(sizeof (*zent));
1261                 (void) memcpy(zent->zl_name, zlist, zlen);
1262                 zent->zl_name[zlen] = '\0';
1263                 zent->zl_used = B_FALSE;
1264                 *znextp = zent;
1265                 znextp = &zent->zl_next;
1266                 zlist = zend;
1267         }
1268         *znextp = NULL;
1269 
1270         if (zhead == NULL) {
1271                 _z_program_error(ERR_ZONE_LIST_EMPTY);
1272                 return (-1);
1273         }
1274 
1275         _z_global_data._zone_spec = zhead;
1276         return (0);
1277 }
1278 
1279 /*
1280  * Name:        z_umount_lz_mount
1281  * Description: Unmount directory mounted with z_mount_in_lz
1282  * Arguments:   a_lzMountPointer - pointer to string returned by z_mount_in_lz
1283  * Returns:     boolean_t
1284  *                      == B_TRUE - successfully unmounted directory
1285  *                      == B_FALSE - failed to unmount directory
1286  */
1287 
1288 boolean_t
1289 z_umount_lz_mount(char *a_lzMountPoint)
1290 {
1291         int     err;
1292 
1293         /* entry assertions */
1294 
1295         assert(a_lzMountPoint != (char *)NULL);
1296         assert(*a_lzMountPoint != '\0');
1297 
1298         /* entry debugging info */
1299 
1300         _z_echoDebug(DBG_ZONES_UNMOUNT_FROM_LZ_ENTRY, a_lzMountPoint);
1301 
1302         /* if zones are not implemented, return TRUE */
1303 
1304         if (z_zones_are_implemented() == B_FALSE) {
1305                 return (B_FALSE);
1306         }
1307 
1308         /* error if global zone path is not absolute */
1309 
1310         if (*a_lzMountPoint != '/') {
1311                 _z_program_error(ERR_LZMNTPT_NOT_ABSOLUTE, a_lzMountPoint);
1312                 return (B_FALSE);
1313         }
1314 
1315         /* verify mount point exists */
1316 
1317         if (_z_is_directory(a_lzMountPoint) != 0) {
1318                 _z_program_error(ERR_LZMNTPT_NOTDIR, a_lzMountPoint,
1319                     strerror(errno));
1320                 return (B_FALSE);
1321         }
1322 
1323         /* unmount */
1324 
1325         err = umount2(a_lzMountPoint, 0);
1326         if (err != 0) {
1327                 _z_program_error(ERR_GZUMOUNT_FAILED, a_lzMountPoint,
1328                     strerror(errno));
1329                 return (B_FALSE);
1330         }
1331 
1332         /* remove the mount point */
1333 
1334         (void) remove(a_lzMountPoint);
1335 
1336         /* return success */
1337 
1338         return (B_TRUE);
1339 }
1340 
1341 /*
1342  * Name:        z_unlock_this_zone
1343  * Description: unlock this zone
1344  * Arguments:   a_lflags - [RO, *RO] - (ZLOCKS_T)
1345  *                      Flags indicating which locks to release
1346  * Returns:     boolean_t
1347  *                      == B_TRUE - success specified locks released
1348  *                      == B_FALSE - failure specified locks may not be released
1349  * NOTE: the lock objects for "this zone" are maintained internally.
1350  */
1351 
1352 boolean_t
1353 z_unlock_this_zone(ZLOCKS_T a_lflags)
1354 {
1355         boolean_t       b;
1356         boolean_t       errors = B_FALSE;
1357         char            *zoneName;
1358 
1359         /* entry assertions */
1360 
1361         assert(a_lflags != ZLOCKS_NONE);
1362 
1363         /* entry debugging info */
1364 
1365         _z_echoDebug(DBG_ZONES_ULK_THIS, a_lflags);
1366 
1367         /* return if no objects locked */
1368 
1369         if ((_z_global_data._z_ObjectLocks == (char *)NULL) ||
1370             (*_z_global_data._z_ObjectLocks == '\0')) {
1371                 return (B_TRUE);
1372         }
1373 
1374         zoneName = z_get_zonename();
1375 
1376         /* unlock package administration */
1377 
1378         if (a_lflags & ZLOCKS_PKG_ADMIN) {
1379                 b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks,
1380                     zoneName, LOBJ_PKGADMIN, ERR_ZONES_ULK_THIS_PACKAGE);
1381                 if (!b) {
1382                         errors = B_TRUE;
1383                 }
1384         }
1385 
1386         /* unlock zone administration */
1387 
1388         if (a_lflags & ZLOCKS_ZONE_ADMIN) {
1389                 b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks,
1390                     zoneName, LOBJ_ZONEADMIN, ERR_ZONES_ULK_THIS_ZONES);
1391                 if (!b) {
1392                         errors = B_TRUE;
1393                 }
1394         }
1395 
1396         (void) free(zoneName);
1397         return (!errors);
1398 }
1399 
1400 /*
1401  * Name:        z_unlock_zones
1402  * Description: unlock specified zones
1403  * Arguments:   a_zlst - zoneList_t object describing zones to unlock
1404  *              a_lflags - [RO, *RO] - (ZLOCKS_T)
1405  *                      Flags indicating which locks to release
1406  * Returns:     boolean_t
1407  *                      == B_TRUE - success, zones unlocked
1408  *                      == B_FALSE - failure, zones not unlocked
1409  */
1410 
1411 boolean_t
1412 z_unlock_zones(zoneList_t a_zlst, ZLOCKS_T a_lflags)
1413 {
1414         boolean_t       b;
1415         boolean_t       errors = B_FALSE;
1416         int             i;
1417 
1418         /* entry assertions */
1419 
1420         assert(a_lflags != ZLOCKS_NONE);
1421 
1422         /* entry debugging info */
1423 
1424         _z_echoDebug(DBG_ZONES_ULK_ZONES, a_lflags);
1425 
1426         /* if zones are not implemented, return TRUE */
1427 
1428         if (z_zones_are_implemented() == B_FALSE) {
1429                 _z_echoDebug(DBG_ZONES_ULK_ZONES_UNIMP);
1430                 return (B_TRUE);
1431         }
1432 
1433         /* ignore empty list */
1434 
1435         if (a_zlst == (zoneList_t)NULL) {
1436                 _z_echoDebug(DBG_ZONES_ULK_ZONES_NOZONES);
1437                 /* unlock this zone before returning */
1438                 return (z_unlock_this_zone(a_lflags));
1439         }
1440 
1441         /* zones exist */
1442 
1443         _z_echoDebug(DBG_ZONES_ULK_ZONES_EXIST);
1444 
1445         /*
1446          * unlock each listed zone that is currently running
1447          */
1448 
1449         for (i = 0; (a_zlst[i]._zlName != (char *)NULL); i++) {
1450                 /* ignore zone if not locked */
1451                 if (!(a_zlst[i]._zlStatus & ZST_LOCKED)) {
1452                         continue;
1453                 }
1454 
1455                 /* ignore zone if not running */
1456                 if (a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_RUNNING &&
1457                     a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_MOUNTED) {
1458                         continue;
1459                 }
1460 
1461                 /* unlock this zone */
1462                 b = _z_unlock_zone(&a_zlst[i], a_lflags);
1463 
1464                 if (b != B_TRUE) {
1465                         errors = B_TRUE;
1466                 } else {
1467                         /* mark zone as unlocked */
1468                         a_zlst[i]._zlStatus &= ~ZST_LOCKED;
1469                 }
1470         }
1471 
1472         /* unlock this zone */
1473 
1474         if (z_unlock_this_zone(a_lflags) != B_TRUE) {
1475                 errors = B_TRUE;
1476         }
1477 
1478         return (errors);
1479 }
1480 
1481 /*
1482  * Name:        z_verify_zone_spec
1483  * Description: Verify list of zones on which actions will be performed.
1484  * Arguments:   None.
1485  * Returns:     0 on success, -1 on error.
1486  * NOTES:       Will call _z_program_error if there are zones on the specified
1487  *              list that don't exist on the system. Requires that
1488  *              z_set_zone_root is called first (if it is called at all).
1489  */
1490 
1491 int
1492 z_verify_zone_spec(void)
1493 {
1494         FILE            *zoneIndexFP;
1495         boolean_t       errors;
1496         char            zoneIndexPath[MAXPATHLEN];
1497         struct zoneent  *ze;
1498         zone_spec_t     *zent;
1499 
1500         if (!z_zones_are_implemented()) {
1501                 _z_program_error(ERR_ZONES_NOT_IMPLEMENTED);
1502                 return (-1);
1503         }
1504 
1505         zoneIndexFP = setzoneent();
1506         if (zoneIndexFP == NULL) {
1507                 _z_program_error(ERR_ZONEINDEX_OPEN, zoneIndexPath,
1508                     strerror(errno));
1509                 return (-1);
1510         }
1511 
1512         while ((ze = getzoneent_private(zoneIndexFP)) != NULL) {
1513                 for (zent = _z_global_data._zone_spec;
1514                     zent != NULL; zent = zent->zl_next) {
1515                         if (strcmp(zent->zl_name, ze->zone_name) == 0) {
1516                                 zent->zl_used = B_TRUE;
1517                                 break;
1518                         }
1519                 }
1520                 free(ze);
1521         }
1522         endzoneent(zoneIndexFP);
1523 
1524         errors = B_FALSE;
1525         for (zent = _z_global_data._zone_spec;
1526             zent != NULL; zent = zent->zl_next) {
1527                 if (!zent->zl_used) {
1528                         _z_program_error(ERR_ZONE_NONEXISTENT, zent->zl_name);
1529                         errors = B_TRUE;
1530                 }
1531         }
1532         return (errors ? -1 : 0);
1533 }
1534 
1535 /*
1536  * Name:        z_zlist_change_zone_state
1537  * Description: Change the current state of the specified zone
1538  * Arguments:   a_zlst - handle to zoneList_t object describing all zones
1539  *              a_zoneIndex - index into a_zlst of the zone to return the
1540  *              a_newState - the state to put the specified zone in
1541  * Returns:     boolean_t
1542  *                      == B_TRUE - the zone is in the new state
1543  *                      == B_FALSE - unable to transition the zone to the
1544  *                              specified state
1545  * NOTE:        This changes the "current kernel" state of the specified
1546  *              zone. For example, to boot the zone, change the state
1547  *              to "ZONE_STATE_RUNNING". To halt the zone, change the
1548  *              state to "ZONE_STATE_INSTALLED".
1549  */
1550 
1551 boolean_t
1552 z_zlist_change_zone_state(zoneList_t a_zlst, int a_zoneIndex,
1553         zone_state_t a_newState)
1554 {
1555         int     i;
1556 
1557         /* entry debugging info */
1558 
1559         _z_echoDebug(DBG_ZONES_CHG_Z_STATE_ENTRY, a_zoneIndex, a_newState);
1560 
1561         /* ignore empty list */
1562 
1563         if (a_zlst == (zoneList_t)NULL) {
1564                 return (B_FALSE);
1565         }
1566 
1567         /* find the specified zone in the list */
1568 
1569         for (i = 0; (i != a_zoneIndex) &&
1570             (a_zlst[i]._zlName != (char *)NULL); i++)
1571                 ;
1572 
1573         /* return error if the specified zone does not exist */
1574 
1575         if (a_zlst[i]._zlName == (char *)NULL) {
1576                 return (B_FALSE);
1577         }
1578 
1579         /* return success if the zone is already in this state */
1580 
1581         if (a_zlst[i]._zlCurrKernelStatus == a_newState) {
1582                 return (B_TRUE);
1583         }
1584 
1585         /* take action on new state to set zone to */
1586 
1587         _z_echoDebug(DBG_ZONES_CHG_Z_STATE, a_zlst[i]._zlName,
1588             a_zlst[i]._zlCurrKernelStatus, a_newState);
1589 
1590         switch (a_newState) {
1591         case ZONE_STATE_RUNNING:
1592         case ZONE_STATE_MOUNTED:
1593                 /* these states mean "boot the zone" */
1594                 return (_z_make_zone_running(&a_zlst[i]));
1595 
1596         case ZONE_STATE_DOWN:
1597         case ZONE_STATE_INSTALLED:
1598                 /* these states mean "halt the zone" */
1599                 return (_z_make_zone_down(&a_zlst[i]));
1600 
1601         case ZONE_STATE_READY:
1602                 return (_z_make_zone_ready(&a_zlst[i]));
1603 
1604         case ZONE_STATE_CONFIGURED:
1605         case ZONE_STATE_INCOMPLETE:
1606         case ZONE_STATE_SHUTTING_DOWN:
1607         default:
1608                 /* do not know how to change zone to this state */
1609                 return (B_FALSE);
1610         }
1611 }
1612 
1613 /*
1614  * Name:        z_is_zone_branded
1615  * Description: Determine whether zone has a non-native brand
1616  * Arguments:   a_zoneName - name of the zone to check for branding
1617  * Returns:     boolean_t
1618  *                      == B_TRUE - zone has a non-native brand
1619  *                      == B_FALSE - zone is native
1620  */
1621 boolean_t
1622 z_is_zone_branded(char *zoneName)
1623 {
1624         char                    brandname[MAXNAMELEN];
1625         int                     err;
1626 
1627         /* if zones are not implemented, return FALSE */
1628         if (!z_zones_are_implemented()) {
1629                 return (B_FALSE);
1630         }
1631 
1632         /* if brands are not implemented, return FALSE */
1633         if (!z_brands_are_implemented()) {
1634                 return (B_FALSE);
1635         }
1636 
1637         err = zone_get_brand(zoneName, brandname, sizeof (brandname));
1638         if (err != Z_OK) {
1639                 _z_program_error(ERR_BRAND_GETBRAND, zonecfg_strerror(err));
1640                 return (B_FALSE);
1641         }
1642 
1643         /*
1644          * Both "native" and "cluster" are native brands
1645          * that use the standard facilities in the areas
1646          * of packaging/installation/update.
1647          */
1648         if (streq(brandname, NATIVE_BRAND_NAME) ||
1649             streq(brandname, CLUSTER_BRAND_NAME)) {
1650                 return (B_FALSE);
1651         } else {
1652                 return (B_TRUE);
1653         }
1654 }
1655 
1656 /*
1657  * Name:        z_is_zone_brand_in_list
1658  * Description: Determine whether zone's brand has a match in the list
1659  *              brands passed in.
1660  * Arguments:   zoneName - name of the zone to check for branding
1661  *              list - list of brands to check the zone against
1662  * Returns:     boolean_t
1663  *                      == B_TRUE - zone has a matching brand
1664  *                      == B_FALSE - zone brand is not in list
1665  */
1666 boolean_t
1667 z_is_zone_brand_in_list(char *zoneName, zoneBrandList_t *list)
1668 {
1669         char                    brandname[MAXNAMELEN];
1670         int                     err;
1671         zoneBrandList_t         *sp;
1672 
1673         if (zoneName == NULL || list == NULL)
1674                 return (B_FALSE);
1675 
1676         /* if zones are not implemented, return FALSE */
1677         if (!z_zones_are_implemented()) {
1678                 return (B_FALSE);
1679         }
1680 
1681         /* if brands are not implemented, return FALSE */
1682         if (!z_brands_are_implemented()) {
1683                 return (B_FALSE);
1684         }
1685 
1686         err = zone_get_brand(zoneName, brandname, sizeof (brandname));
1687         if (err != Z_OK) {
1688                 _z_program_error(ERR_BRAND_GETBRAND, zonecfg_strerror(err));
1689                 return (B_FALSE);
1690         }
1691 
1692         for (sp = list; sp != NULL; sp = sp->next) {
1693                 if (sp->string_ptr != NULL &&
1694                     strcmp(sp->string_ptr, brandname) == 0) {
1695                         return (B_TRUE);
1696                 }
1697         }
1698 
1699         return (B_FALSE);
1700 }
1701 
1702 /*
1703  * Name:        z_zlist_get_current_state
1704  * Description: Determine the current kernel state of the specified zone
1705  * Arguments:   a_zlst - handle to zoneList_t object describing all zones
1706  *              a_zoneIndex - index into a_zlst of the zone to return
1707  * Returns:     zone_state_t
1708  *                      The current state of the specified zone is returned
1709  */
1710 
1711 zone_state_t
1712 z_zlist_get_current_state(zoneList_t a_zlst, int a_zoneIndex)
1713 {
1714         int     i;
1715 
1716         /* ignore empty list */
1717 
1718         if (a_zlst == (zoneList_t)NULL) {
1719                 return (ZONE_STATE_INCOMPLETE);
1720         }
1721 
1722         /* find the specified zone in the list */
1723 
1724         for (i = 0; (i != a_zoneIndex) &&
1725             (a_zlst[i]._zlName != (char *)NULL); i++)
1726                 ;
1727 
1728         /* return error if the specified zone does not exist */
1729 
1730         if (a_zlst[i]._zlName == (char *)NULL) {
1731                 return (ZONE_STATE_INCOMPLETE);
1732         }
1733 
1734         /* return selected zone's current kernel state */
1735 
1736         _z_echoDebug(DBG_ZONES_GET_ZONE_STATE,
1737             a_zlst[i]._zlName ? a_zlst[i]._zlName : "",
1738             a_zlst[i]._zlCurrKernelStatus);
1739 
1740         return (a_zlst[i]._zlCurrKernelStatus);
1741 }
1742 
1743 /*
1744  * Name:        z_zlist_get_original_state
1745  * Description: Return the original kernal state of the specified zone
1746  * Arguments:   a_zlst - handle to zoneList_t object describing all zones
1747  *              a_zoneIndex - index into a_zlst of the zone to return the
1748  * Returns:     zone_state_t
1749  *                      The original state of the specified zone is returned.
1750  *                      This is the state of the zone when the zoneList_t
1751  *                      object was first generated.
1752  */
1753 
1754 zone_state_t
1755 z_zlist_get_original_state(zoneList_t a_zlst, int a_zoneIndex)
1756 {
1757         int     i;
1758 
1759         /* ignore empty list */
1760 
1761         if (a_zlst == (zoneList_t)NULL) {
1762                 return (ZONE_STATE_INCOMPLETE);
1763         }
1764 
1765         /* find the specified zone in the list */
1766 
1767         for (i = 0; (i != a_zoneIndex) &&
1768             (a_zlst[i]._zlName != (char *)NULL); i++)
1769                 ;
1770 
1771         /* return error if the specified zone does not exist */
1772 
1773         if (a_zlst[i]._zlName == (char *)NULL) {
1774                 return (ZONE_STATE_INCOMPLETE);
1775         }
1776 
1777         /* return selected zone's original kernel state */
1778 
1779         return (a_zlst[i]._zlOrigKernelStatus);
1780 }
1781 
1782 /*
1783  * Name:        z_zlist_get_scratch
1784  * Description: Determine name of scratch zone
1785  * Arguments:   a_zlst - handle to zoneList_t object describing all zones
1786  *              a_zoneIndex - index into a_zlst of the zone to use
1787  * Return:      char *
1788  *                      == NULL - zone name could not be determined
1789  *                      != NULL - pointer to string representing scratch zone
1790  * NOTE:        Any name returned is placed in static storage that must
1791  *              NEVER be free()ed by the caller.
1792  */
1793 
1794 char *
1795 z_zlist_get_scratch(zoneList_t a_zlst, int a_zoneIndex)
1796 {
1797         int     i;
1798 
1799         /* ignore empty list */
1800 
1801         if (a_zlst == NULL)
1802                 return (NULL);
1803 
1804         /* find the specified zone in the list */
1805 
1806         for (i = 0; i != a_zoneIndex; i++) {
1807                 if (a_zlst[i]._zlName == NULL)
1808                         return (NULL);
1809         }
1810 
1811         /* return selected zone's scratch name */
1812 
1813         return (a_zlst[i]._zlScratchName == NULL ? a_zlst[i]._zlName :
1814             a_zlst[i]._zlScratchName);
1815 }
1816 
1817 /*
1818  * Name:        z_zlist_get_zonename
1819  * Description: Determine name of specified zone
1820  * Arguments:   a_zlst - handle to zoneList_t object describing all zones
1821  *              a_zoneIndex - index into a_zlst of the zone to return the
1822  * Return:      char *
1823  *                      == NULL - zone name could not be determined
1824  *                      != NULL - pointer to string representing zone name
1825  * NOTE:        Any zoneList_t returned is placed in static storage that must
1826  *              NEVER be free()ed by the caller.
1827  */
1828 
1829 char *
1830 z_zlist_get_zonename(zoneList_t a_zlst, int a_zoneIndex)
1831 {
1832         int     i;
1833 
1834         /* ignore empty list */
1835 
1836         if (a_zlst == (zoneList_t)NULL) {
1837                 return ((char *)NULL);
1838         }
1839 
1840         /* find the specified zone in the list */
1841 
1842         for (i = 0; (i != a_zoneIndex) &&
1843             (a_zlst[i]._zlName != (char *)NULL); i++)
1844                 ;
1845 
1846         /* return error if the specified zone does not exist */
1847 
1848         if (a_zlst[i]._zlName == (char *)NULL) {
1849                 return (NULL);
1850         }
1851 
1852         /* return selected zone's name */
1853 
1854         return (a_zlst[i]._zlName);
1855 }
1856 
1857 /*
1858  * Name:        z_zlist_get_zonepath
1859  * Description: Determine zonepath of specified zone
1860  * Arguments:   a_zlst - handle to zoneList_t object describing all zones
1861  *              a_zoneIndex - index into a_zlst of the zone to return
1862  * Return:      char *
1863  *                      == NULL - zonepath could not be determined
1864  *                      != NULL - pointer to string representing zonepath
1865  * NOTE:        Any zoneList_t returned is placed in static storage that must
1866  *              NEVER be free()ed by the caller.
1867  */
1868 
1869 char *
1870 z_zlist_get_zonepath(zoneList_t a_zlst, int a_zoneIndex)
1871 {
1872         int     i;
1873 
1874         /* ignore empty list */
1875 
1876         if (a_zlst == (zoneList_t)NULL) {
1877                 return ((char *)NULL);
1878         }
1879 
1880         /* find the specified zone in the list */
1881 
1882         for (i = 0; (i != a_zoneIndex) &&
1883             (a_zlst[i]._zlName != (char *)NULL); i++)
1884                 ;
1885 
1886         /* return error if the specified zone does not exist */
1887 
1888         if (a_zlst[i]._zlName == (char *)NULL) {
1889                 return (NULL);
1890         }
1891 
1892         /* return selected zone's zonepath */
1893 
1894         return (a_zlst[i]._zlPath);
1895 }
1896 
1897 boolean_t
1898 z_zlist_is_zone_runnable(zoneList_t a_zlst, int a_zoneIndex)
1899 {
1900         int     i;
1901 
1902         /* if zones are not implemented, return error */
1903 
1904         if (z_zones_are_implemented() == B_FALSE) {
1905                 return (B_FALSE);
1906         }
1907 
1908         /* ignore empty list */
1909 
1910         if (a_zlst == (zoneList_t)NULL) {
1911                 return (B_FALSE);
1912         }
1913 
1914         /* find the specified zone in the list */
1915 
1916         for (i = 0; (i != a_zoneIndex) &&
1917             (a_zlst[i]._zlName != (char *)NULL); i++)
1918                 ;
1919 
1920         /* return error if the specified zone does not exist */
1921 
1922         if (a_zlst[i]._zlName == (char *)NULL) {
1923                 return (B_FALSE);
1924         }
1925 
1926         /* choose based on current state */
1927 
1928         switch (a_zlst[i]._zlCurrKernelStatus) {
1929         case ZONE_STATE_RUNNING:
1930         case ZONE_STATE_MOUNTED:
1931                 /* already running */
1932                 return (B_TRUE);
1933 
1934         case ZONE_STATE_INSTALLED:
1935         case ZONE_STATE_DOWN:
1936         case ZONE_STATE_READY:
1937         case ZONE_STATE_SHUTTING_DOWN:
1938                 /* return false if the zone cannot be booted */
1939 
1940                 if (a_zlst[i]._zlStatus & ZST_NOT_BOOTABLE) {
1941                         return (B_FALSE);
1942                 }
1943 
1944                 return (B_TRUE);
1945 
1946         case ZONE_STATE_CONFIGURED:
1947         case ZONE_STATE_INCOMPLETE:
1948         default:
1949                 /* cannot transition (boot) these states */
1950                 return (B_FALSE);
1951         }
1952 }
1953 
1954 /*
1955  * Name:        z_zlist_restore_zone_state
1956  * Description: Return the zone to the state it was originally in
1957  * Arguments:   a_zlst - handle to zoneList_t object describing all zones
1958  *              a_zoneIndex - index into a_zlst of the zone to return the
1959  * Returns:     boolean_t
1960  *                      == B_TRUE - the zone's state has been restored
1961  *                      == B_FALSE - unable to transition the zone to its
1962  *                              original state
1963  */
1964 
1965 boolean_t
1966 z_zlist_restore_zone_state(zoneList_t a_zlst, int a_zoneIndex)
1967 {
1968         int             i;
1969 
1970         /* ignore empty list */
1971 
1972         if (a_zlst == (zoneList_t)NULL) {
1973                 return (B_FALSE);
1974         }
1975 
1976         /* find the specified zone in the list */
1977 
1978         for (i = 0; (i != a_zoneIndex) &&
1979             (a_zlst[i]._zlName != (char *)NULL); i++)
1980                 ;
1981 
1982         /* return error if the specified zone does not exist */
1983 
1984         if (a_zlst[i]._zlName == (char *)NULL) {
1985                 return (B_FALSE);
1986         }
1987 
1988         /* transition the zone back to its original state */
1989 
1990         return (z_zlist_change_zone_state(a_zlst,
1991             a_zoneIndex, a_zlst[i]._zlOrigKernelStatus));
1992 }
1993 
1994 /*
1995  * Name:        z_zone_exec
1996  * Description: Execute a Unix command in a specified zone and return results
1997  * Arguments:   a_zoneName - pointer to string representing the name of the zone
1998  *                      to execute the specified command in
1999  *              a_path - pointer to string representing the full path *in the
2000  *                      non-global zone named by a_zoneName* of the Unix command
2001  *                      to be executed
2002  *              a_argv[] - Pointer to array of character strings representing
2003  *                      the arguments to be passed to the Unix command. The list
2004  *                      must be termianted with an element that is (char *)NULL
2005  *              NOTE: a_argv[0] is the "command name" passed to the command
2006  *              a_stdoutPath - Pointer to string representing the path to a file
2007  *                      into which all output to "stdout" from the Unix command
2008  *                      is placed.
2009  *                      == (char *)NULL - leave stdout open and pass through
2010  *                      == "/dev/null" - discard stdout output
2011  *              a_strerrPath - Pointer to string representing the path to a file
2012  *                      into which all output to "stderr" from the Unix command
2013  *                      is placed.
2014  *                      == (char *)NULL - leave stderr open and pass through
2015  *                      == "/dev/null" - discard stderr output
2016  *              a_fds - Pointer to array of integers representing file
2017  *                      descriptors to remain open during the call - all
2018  *                      file descriptors above STDERR_FILENO not in this
2019  *                      list will be closed.
2020  * Returns:     int
2021  *                      The return (exit) code from the specified Unix command
2022  *                      Special return codes:
2023  *                      -1 : failure to exec process
2024  *                      -2 : could not create contract for greenline
2025  *                      -3 : fork() failed
2026  *                      -4 : could not open stdout capture file
2027  *                      -5 : error from 'waitpid' other than EINTR
2028  *                      -6 : zones are not supported
2029  * NOTE:        All file descriptores other than 0, 1 and 2 are closed except
2030  *              for those file descriptors listed in the a_fds array.
2031  */
2032 
2033 int
2034 z_zone_exec(const char *a_zoneName, const char *a_path, char *a_argv[],
2035         char *a_stdoutPath, char *a_stderrPath, int *a_fds)
2036 {
2037         int                     final_status;
2038         int                     lerrno;
2039         int                     status;
2040         int                     tmpl_fd;
2041         pid_t                   child_pid;
2042         pid_t                   result_pid;
2043         struct sigaction        nact;
2044         struct sigaction        oact;
2045         void                    (*funcSighup)();
2046         void                    (*funcSigint)();
2047 
2048         /* if zones are not implemented, return TRUE */
2049 
2050         if (z_zones_are_implemented() == B_FALSE) {
2051                 return (-6);    /* -6 : zones are not supported */
2052         }
2053 
2054         if ((tmpl_fd = _zexec_init_template()) == -1) {
2055                 _z_program_error(ERR_CANNOT_CREATE_CONTRACT, strerror(errno));
2056                 return (-2);    /* -2 : could not create greenline contract */
2057         }
2058 
2059         /*
2060          * hold SIGINT/SIGHUP signals and reset signal received counter;
2061          * after the fork1() the parent and child need to setup their respective
2062          * interrupt handling and release the hold on the signals
2063          */
2064 
2065         (void) sighold(SIGINT);
2066         (void) sighold(SIGHUP);
2067 
2068         _z_global_data._z_SigReceived = 0;      /* no signals received */
2069 
2070         /*
2071          * fork off a new process to execute command in;
2072          * fork1() is used instead of vfork() so the child process can
2073          * perform operations that would modify the parent process if
2074          * vfork() were used
2075          */
2076 
2077         child_pid = fork1();
2078 
2079         if (child_pid < 0) {
2080                 /*
2081                  * *************************************************************
2082                  * fork failed!
2083                  * *************************************************************
2084                  */
2085 
2086                 (void) ct_tmpl_clear(tmpl_fd);
2087                 (void) close(tmpl_fd);
2088                 _z_program_error(ERR_FORK, strerror(errno));
2089 
2090                 /* release hold on signals */
2091 
2092                 (void) sigrelse(SIGHUP);
2093                 (void) sigrelse(SIGINT);
2094 
2095                 return (-3);    /* -3 : fork() failed */
2096         }
2097 
2098         if (child_pid == 0) {
2099                 int     i;
2100 
2101                 /*
2102                  * *************************************************************
2103                  * This is the forked (child) process
2104                  * *************************************************************
2105                  */
2106 
2107                 (void) ct_tmpl_clear(tmpl_fd);
2108                 (void) close(tmpl_fd);
2109 
2110                 /* reset any signals to default */
2111 
2112                 for (i = 0; i < NSIG; i++) {
2113                         (void) sigset(i, SIG_DFL);
2114                 }
2115 
2116                 /*
2117                  * close all file descriptors not in the a_fds list
2118                  */
2119 
2120                 (void) fdwalk(&_z_close_file_descriptors, (void *)a_fds);
2121 
2122                 /*
2123                  * if a file for stdout is present, open the file and use the
2124                  * file to capture stdout from the _zexec process
2125                  */
2126 
2127                 if (a_stdoutPath != (char *)NULL) {
2128                         int     stdoutfd;
2129 
2130                         stdoutfd = open(a_stdoutPath,
2131                             O_WRONLY|O_CREAT|O_TRUNC, 0600);
2132                         if (stdoutfd < 0) {
2133                                 _z_program_error(ERR_CAPTURE_FILE, a_stdoutPath,
2134                                     strerror(errno));
2135                                 return (-4);
2136                         }
2137 
2138                         (void) dup2(stdoutfd, STDOUT_FILENO);
2139                         (void) close(stdoutfd);
2140                 }
2141 
2142                 /*
2143                  * if a file for stderr is present, open the file and use the
2144                  * file to capture stderr from the _zexec process
2145                  */
2146 
2147                 if (a_stderrPath != (char *)NULL) {
2148                         int     stderrfd;
2149 
2150                         stderrfd = open(a_stderrPath,
2151                             O_WRONLY|O_CREAT|O_TRUNC, 0600);
2152                         if (stderrfd < 0) {
2153                                 _z_program_error(ERR_CAPTURE_FILE, a_stderrPath,
2154                                     strerror(errno));
2155                                 return (-4);
2156                         }
2157 
2158                         (void) dup2(stderrfd, STDERR_FILENO);
2159                         (void) close(stderrfd);
2160                 }
2161 
2162                 /* release all held signals */
2163 
2164                 (void) sigrelse(SIGHUP);
2165                 (void) sigrelse(SIGINT);
2166 
2167                 /* execute command in the specified non-global zone */
2168 
2169                 _exit(_zexec(a_zoneName, a_path, a_argv));
2170         }
2171 
2172         /*
2173          * *********************************************************************
2174          * This is the forking (parent) process
2175          * *********************************************************************
2176          */
2177 
2178         /* register child process i.d. so signal handlers can pass signal on */
2179 
2180         _z_global_data._z_ChildProcessId = child_pid;
2181 
2182         /*
2183          * setup signal handlers for SIGINT and SIGHUP and release hold
2184          */
2185 
2186         /* hook SIGINT to _z_sig_trap() */
2187 
2188         nact.sa_handler = _z_sig_trap;
2189         nact.sa_flags = SA_RESTART;
2190         (void) sigemptyset(&nact.sa_mask);
2191 
2192         if (sigaction(SIGINT, &nact, &oact) < 0) {
2193                 funcSigint = SIG_DFL;
2194         } else {
2195                 funcSigint = oact.sa_handler;
2196         }
2197 
2198         /* hook SIGHUP to _z_sig_trap() */
2199 
2200         nact.sa_handler = _z_sig_trap;
2201         nact.sa_flags = SA_RESTART;
2202         (void) sigemptyset(&nact.sa_mask);
2203 
2204         if (sigaction(SIGHUP, &nact, &oact) < 0) {
2205                 funcSighup = SIG_DFL;
2206         } else {
2207                 funcSighup = oact.sa_handler;
2208         }
2209 
2210         /* release hold on signals */
2211 
2212         (void) sigrelse(SIGHUP);
2213         (void) sigrelse(SIGINT);
2214 
2215         (void) ct_tmpl_clear(tmpl_fd);
2216         (void) close(tmpl_fd);
2217 
2218         /*
2219          * wait for the process to exit, reap child exit status
2220          */
2221 
2222         for (;;) {
2223                 result_pid = waitpid(child_pid, &status, 0L);
2224                 lerrno = (result_pid == -1 ? errno : 0);
2225 
2226                 /* break loop if child process status reaped */
2227 
2228                 if (result_pid != -1) {
2229                         break;
2230                 }
2231 
2232                 /* break loop if not interrupted out of waitpid */
2233 
2234                 if (errno != EINTR) {
2235                         break;
2236                 }
2237         }
2238 
2239         /* reset child process i.d. so signal handlers do not pass signals on */
2240 
2241         _z_global_data._z_ChildProcessId = -1;
2242 
2243         /*
2244          * If the child process terminated due to a call to exit(), then
2245          * set results equal to the 8-bit exit status of the child process;
2246          * otherwise, set the exit status to "-1" indicating that the child
2247          * exited via a signal.
2248          */
2249 
2250         if (WIFEXITED(status)) {
2251                 final_status = WEXITSTATUS(status);
2252                 if ((_z_global_data._z_SigReceived != 0) &&
2253                     (final_status == 0)) {
2254                         final_status = 1;
2255                 }
2256         } else {
2257                 final_status = -1;      /* -1 : failure to exec process */
2258         }
2259 
2260         /* determine proper exit code */
2261 
2262         if (result_pid == -1) {
2263                 final_status = -5;      /* -5 : error from waitpid not EINTR */
2264         } else if (_z_global_data._z_SigReceived != 0) {
2265                 final_status = -7;      /* -7 : interrupt received */
2266         }
2267 
2268         /*
2269          * reset signal handlers
2270          */
2271 
2272         /* reset SIGINT */
2273 
2274         nact.sa_handler = funcSigint;
2275         nact.sa_flags = SA_RESTART;
2276         (void) sigemptyset(&nact.sa_mask);
2277 
2278         (void) sigaction(SIGINT, &nact, (struct sigaction *)NULL);
2279 
2280         /* reset SIGHUP */
2281 
2282         nact.sa_handler = funcSighup;
2283         nact.sa_flags = SA_RESTART;
2284         (void) sigemptyset(&nact.sa_mask);
2285 
2286         (void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL);
2287 
2288         /*
2289          * if signal received during command execution, interrupt
2290          * this process now.
2291          */
2292 
2293         if (_z_global_data._z_SigReceived != 0) {
2294                 (void) kill(getpid(), SIGINT);
2295         }
2296 
2297         /* set errno and return */
2298 
2299         errno = lerrno;
2300 
2301         return (final_status);
2302 }
2303 
2304 /*
2305  * Name:        z_zones_are_implemented
2306  * Description: Determine if any zone operations can be performed
2307  * Arguments:   void
2308  * Returns:     boolean_t
2309  *                      == B_TRUE - zone operations are available
2310  *                      == B_FALSE - no zone operations can be done
2311  */
2312 
2313 boolean_t
2314 z_zones_are_implemented(void)
2315 {
2316         static  boolean_t       _zonesImplementedDetermined = B_FALSE;
2317         static  boolean_t       _zonesAreImplemented = B_FALSE;
2318 
2319         /* if availability has not been determined, cache it now */
2320 
2321         if (!_zonesImplementedDetermined) {
2322                 _zonesImplementedDetermined = B_TRUE;
2323                 _zonesAreImplemented = _z_zones_are_implemented();
2324                 if (!_zonesAreImplemented) {
2325                         _z_echoDebug(DBG_ZONES_NOT_IMPLEMENTED);
2326                 } else {
2327                         _z_echoDebug(DBG_ZONES_ARE_IMPLEMENTED);
2328                 }
2329         }
2330 
2331         return (_zonesAreImplemented);
2332 }