10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 23*238Sseizo * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <sys/types.h> 290Sstevel@tonic-gate #include <sys/stat.h> 300Sstevel@tonic-gate #include <fcntl.h> 310Sstevel@tonic-gate #include <stdio.h> 320Sstevel@tonic-gate #include <string.h> 330Sstevel@tonic-gate #include <unistd.h> 340Sstevel@tonic-gate #include <locale.h> 350Sstevel@tonic-gate #include <dlfcn.h> 360Sstevel@tonic-gate #include <errno.h> 370Sstevel@tonic-gate #include "_crle.h" 380Sstevel@tonic-gate #include "msg.h" 390Sstevel@tonic-gate 400Sstevel@tonic-gate 410Sstevel@tonic-gate /* 420Sstevel@tonic-gate * crle(1) entry point and argument processing. 430Sstevel@tonic-gate * 440Sstevel@tonic-gate * Two passes of the arguments are carried out; the first collects any single 450Sstevel@tonic-gate * instance options and establishes defaults that might be appropriate for 460Sstevel@tonic-gate * other arguments: 470Sstevel@tonic-gate * 480Sstevel@tonic-gate * -64 operate on, or apply, 64-bit objects (default is 32-bit). 490Sstevel@tonic-gate * 500Sstevel@tonic-gate * -c file defines the output configuration file. 510Sstevel@tonic-gate * 520Sstevel@tonic-gate * -f flag flags for dldump(3dl). 530Sstevel@tonic-gate * 540Sstevel@tonic-gate * -o dir defines the output directory for any dldump(3dl) objects 550Sstevel@tonic-gate * that follow. For backward compatibility (RTC_VER_ONE only 560Sstevel@tonic-gate * allowed one output directory) allow the first occurrence of this 570Sstevel@tonic-gate * specification to catch any previous files. If not specified, 580Sstevel@tonic-gate * the configuration files parent directory is used). 590Sstevel@tonic-gate * 600Sstevel@tonic-gate * -u update any existing configuration file. Any additional 610Sstevel@tonic-gate * arguments supplied will be added to the new configuration 620Sstevel@tonic-gate * information. 630Sstevel@tonic-gate * 640Sstevel@tonic-gate * -v verbose mode. 650Sstevel@tonic-gate * 660Sstevel@tonic-gate * The second pass collects all other options and constructs an internal 670Sstevel@tonic-gate * string table which will be used to create the eventual configuration file. 680Sstevel@tonic-gate * 690Sstevel@tonic-gate * -a name add the individual name, with an alternative to the 700Sstevel@tonic-gate * configuration cache. No alternative is created via dldump(3dl), 710Sstevel@tonic-gate * it is the users responsibility to furnish the alternative. 720Sstevel@tonic-gate * 730Sstevel@tonic-gate * -A name add the individual name, with an optional alternative to the 740Sstevel@tonic-gate * configuration cache. No alternative is created via dldump(3dl), 750Sstevel@tonic-gate * it is the users responsibility to furnish the alternative. 760Sstevel@tonic-gate * 770Sstevel@tonic-gate * -e envar replaceable environment variable 780Sstevel@tonic-gate * 790Sstevel@tonic-gate * -E envar permanent environment variable 800Sstevel@tonic-gate * 810Sstevel@tonic-gate * -i name add the individual name to the configuration cache. If name 820Sstevel@tonic-gate * is a directory each shared object within the directory is added 830Sstevel@tonic-gate * to the cache. 840Sstevel@tonic-gate * 850Sstevel@tonic-gate * -I name same as -i, but in addition any ELF objects are dldump(3dl)'ed. 860Sstevel@tonic-gate * 870Sstevel@tonic-gate * -g name add the group name to the configuration cache. Each object is 880Sstevel@tonic-gate * expanded to determine its dependencies and these are added to 890Sstevel@tonic-gate * the cache. If name is a directory each shared object within the 900Sstevel@tonic-gate * directory and its dependencies are added to the cache. 910Sstevel@tonic-gate * 920Sstevel@tonic-gate * -G app same as -g, but in addition any ELF objects are dldump(3dl)'ed. 930Sstevel@tonic-gate * 940Sstevel@tonic-gate * -l dir library search directory 950Sstevel@tonic-gate * 960Sstevel@tonic-gate * -s dir trusted (secure) directory 970Sstevel@tonic-gate * 980Sstevel@tonic-gate * -t type search directory type (ELF or AOUT). 990Sstevel@tonic-gate */ 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate /* 1020Sstevel@tonic-gate * Establish a structure for maintaining current object directory attributes. 1030Sstevel@tonic-gate * We wish to validate the access of any object directory that will be written 1040Sstevel@tonic-gate * to (dldump(3dl), and thus by maintaining a current object directory and its 1050Sstevel@tonic-gate * intended use we can perform this validation later. 1060Sstevel@tonic-gate */ 1070Sstevel@tonic-gate typedef struct { 1080Sstevel@tonic-gate char *o_objdir; 1090Sstevel@tonic-gate unsigned int o_flags; 1100Sstevel@tonic-gate } Objdir; 1110Sstevel@tonic-gate 112*238Sseizo int 1130Sstevel@tonic-gate main(int argc, char ** argv) 1140Sstevel@tonic-gate { 1150Sstevel@tonic-gate Crle_desc crle = { 0 }; 1160Sstevel@tonic-gate int c, error = 0; 1170Sstevel@tonic-gate char ** lib; 1180Sstevel@tonic-gate List objdirs = { 0, 0 }; 1190Sstevel@tonic-gate Objdir _lobjdir = { 0, 0 }, * lobjdir = &_lobjdir; 1200Sstevel@tonic-gate struct stat ostatus, nstatus; 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate if (list_append(&objdirs, lobjdir) == 0) 1230Sstevel@tonic-gate return (1); 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate /* 1260Sstevel@tonic-gate * Establish locale. 1270Sstevel@tonic-gate */ 1280Sstevel@tonic-gate (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 1290Sstevel@tonic-gate (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate /* 1320Sstevel@tonic-gate * Initialization configuration information. 1330Sstevel@tonic-gate */ 1340Sstevel@tonic-gate crle.c_name = argv[0]; 1350Sstevel@tonic-gate crle.c_strbkts = 503; 1360Sstevel@tonic-gate crle.c_inobkts = 251; 1370Sstevel@tonic-gate crle.c_class = ELFCLASS32; 1380Sstevel@tonic-gate crle.c_machine = M_MACH; 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate /* 1410Sstevel@tonic-gate * First argument pass. 1420Sstevel@tonic-gate */ 1430Sstevel@tonic-gate while ((c = getopt(argc, argv, MSG_ORIG(MSG_ARG_OPTIONS))) != -1) { 1440Sstevel@tonic-gate switch (c) { 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate case '6': /* operate on 64-bit objects */ 1470Sstevel@tonic-gate if (optarg[0] != '4') { 1480Sstevel@tonic-gate (void) fprintf(stderr, 1490Sstevel@tonic-gate MSG_INTL(MSG_ARG_ILLEGAL), crle.c_name, 1500Sstevel@tonic-gate MSG_ORIG(MSG_ARG_6), optarg); 1510Sstevel@tonic-gate error = 1; 1520Sstevel@tonic-gate } 1530Sstevel@tonic-gate crle.c_class = ELFCLASS64; 1540Sstevel@tonic-gate #if defined(sparc) 1550Sstevel@tonic-gate crle.c_machine = EM_SPARCV9; 1560Sstevel@tonic-gate #elif defined(i386) 1570Sstevel@tonic-gate crle.c_machine = EM_IA_64; 1580Sstevel@tonic-gate #endif 1590Sstevel@tonic-gate break; 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate case 'A': /* create optional */ 1620Sstevel@tonic-gate /* FALLTHROUGH */ /* alternative */ 1630Sstevel@tonic-gate case 'a': /* create alternative */ 1640Sstevel@tonic-gate crle.c_flags |= (CRLE_CREAT | CRLE_ALTER); 1650Sstevel@tonic-gate lobjdir->o_flags |= (CRLE_CREAT | CRLE_ALTER); 1660Sstevel@tonic-gate break; 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate case 'c': /* define the config file */ 1690Sstevel@tonic-gate if (crle.c_confil) { 1700Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_MULT), 1710Sstevel@tonic-gate crle.c_name, MSG_ORIG(MSG_ARG_C)); 1720Sstevel@tonic-gate error = 1; 1730Sstevel@tonic-gate } 1740Sstevel@tonic-gate crle.c_confil = optarg; 1750Sstevel@tonic-gate break; 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate case 'e': /* replaceable env variable */ 1780Sstevel@tonic-gate crle.c_flags |= (CRLE_RPLENV | CRLE_CREAT); 1790Sstevel@tonic-gate break; 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate case 'E': /* permanent env variable */ 1820Sstevel@tonic-gate crle.c_flags |= (CRLE_PRMENV | CRLE_CREAT); 1830Sstevel@tonic-gate break; 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate case 'f': /* dldump(3dl) flags */ 1860Sstevel@tonic-gate if (crle.c_dlflags) { 1870Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_MULT), 1880Sstevel@tonic-gate crle.c_name, MSG_ORIG(MSG_ARG_F)); 1890Sstevel@tonic-gate error = 1; 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate if ((crle.c_dlflags = dlflags(&crle, 1920Sstevel@tonic-gate (const char *)optarg)) == 0) 1930Sstevel@tonic-gate error = 1; 1940Sstevel@tonic-gate break; 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate case 'G': /* group object */ 1970Sstevel@tonic-gate crle.c_flags |= (CRLE_DUMP | CRLE_ALTER); 1980Sstevel@tonic-gate lobjdir->o_flags |= (CRLE_DUMP | CRLE_ALTER); 1990Sstevel@tonic-gate /* FALLTHROUGH */ 2000Sstevel@tonic-gate case 'g': 2010Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT; 2020Sstevel@tonic-gate lobjdir->o_flags |= CRLE_CREAT; 2030Sstevel@tonic-gate break; 2040Sstevel@tonic-gate 2050Sstevel@tonic-gate case 'I': /* individual object */ 2060Sstevel@tonic-gate crle.c_flags |= (CRLE_DUMP | CRLE_ALTER); 2070Sstevel@tonic-gate lobjdir->o_flags |= (CRLE_DUMP | CRLE_ALTER); 2080Sstevel@tonic-gate /* FALLTHROUGH */ 2090Sstevel@tonic-gate case 'i': 2100Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT; 2110Sstevel@tonic-gate lobjdir->o_flags |= CRLE_CREAT; 2120Sstevel@tonic-gate break; 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate case 'l': /* library search path */ 2150Sstevel@tonic-gate if (crle.c_flags & CRLE_AOUT) 2160Sstevel@tonic-gate crle.c_flags |= CRLE_ADLIB; 2170Sstevel@tonic-gate else 2180Sstevel@tonic-gate crle.c_flags |= CRLE_EDLIB; 2190Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT; 2200Sstevel@tonic-gate break; 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate case 'o': /* define an object directory */ 2230Sstevel@tonic-gate if (lobjdir->o_objdir) { 2240Sstevel@tonic-gate if ((lobjdir = calloc(sizeof (Objdir), 1)) == 0) 2250Sstevel@tonic-gate return (1); 2260Sstevel@tonic-gate if (list_append(&objdirs, lobjdir) == 0) 2270Sstevel@tonic-gate return (1); 2280Sstevel@tonic-gate } 2290Sstevel@tonic-gate lobjdir->o_objdir = optarg; 2300Sstevel@tonic-gate break; 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate case 's': /* trusted (secure) path */ 2330Sstevel@tonic-gate if (crle.c_flags & CRLE_AOUT) 2340Sstevel@tonic-gate crle.c_flags |= CRLE_ASLIB; 2350Sstevel@tonic-gate else 2360Sstevel@tonic-gate crle.c_flags |= CRLE_ESLIB; 2370Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT; 2380Sstevel@tonic-gate break; 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate case 't': /* search path type */ 2410Sstevel@tonic-gate if (strcmp((const char *)optarg, 2420Sstevel@tonic-gate MSG_ORIG(MSG_STR_ELF)) == 0) 2430Sstevel@tonic-gate crle.c_flags &= ~CRLE_AOUT; 2440Sstevel@tonic-gate else if (strcmp((const char *)optarg, 2450Sstevel@tonic-gate MSG_ORIG(MSG_STR_AOUT)) == 0) 2460Sstevel@tonic-gate crle.c_flags |= CRLE_AOUT; 2470Sstevel@tonic-gate else { 2480Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_TYPE), 2490Sstevel@tonic-gate crle.c_name, optarg); 2500Sstevel@tonic-gate error = 1; 2510Sstevel@tonic-gate } 2520Sstevel@tonic-gate break; 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate case 'u': /* update mode */ 2550Sstevel@tonic-gate crle.c_flags |= (CRLE_CREAT | CRLE_UPDATE); 2560Sstevel@tonic-gate break; 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate case 'v': /* verbose mode */ 2590Sstevel@tonic-gate crle.c_flags |= CRLE_VERBOSE; 2600Sstevel@tonic-gate break; 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate default: 2630Sstevel@tonic-gate error = 2; 2640Sstevel@tonic-gate } 2650Sstevel@tonic-gate } 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate if (optind != argc) 2680Sstevel@tonic-gate error = 2; 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate /* 2710Sstevel@tonic-gate * Determine the configuration file, which in the case of an existing 2720Sstevel@tonic-gate * error condition is required in the final error message. 2730Sstevel@tonic-gate */ 2740Sstevel@tonic-gate if (crle.c_confil == 0) { 2750Sstevel@tonic-gate crle.c_flags |= CRLE_CONFDEF; 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate if (crle.c_class == ELFCLASS32) 2780Sstevel@tonic-gate crle.c_confil = (char *)MSG_ORIG(MSG_PTH_CONFIG); 2790Sstevel@tonic-gate else 2800Sstevel@tonic-gate crle.c_confil = (char *)MSG_ORIG(MSG_PTH_CONFIG_64); 2810Sstevel@tonic-gate } 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate /* 2840Sstevel@tonic-gate * Now that we've generated as many file/directory processing errors 2850Sstevel@tonic-gate * as we can, return if any fatal error conditions occurred. 2860Sstevel@tonic-gate */ 2870Sstevel@tonic-gate if (error) { 2880Sstevel@tonic-gate if (error == 2) { 2890Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_USAGE), 2900Sstevel@tonic-gate crle.c_name); 2910Sstevel@tonic-gate } else if (crle.c_flags & CRLE_CREAT) { 2920Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_CREATE), 2930Sstevel@tonic-gate crle.c_name, crle.c_confil); 2940Sstevel@tonic-gate } 2950Sstevel@tonic-gate return (1); 2960Sstevel@tonic-gate } 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate /* 2990Sstevel@tonic-gate * Apply any additional defaults. 3000Sstevel@tonic-gate */ 3010Sstevel@tonic-gate if (crle.c_dlflags == 0) 3020Sstevel@tonic-gate crle.c_dlflags = RTLD_REL_RELATIVE; 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate crle.c_audit = (char *)MSG_ORIG(MSG_ENV_LD_AUDIT); 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate (void) elf_version(EV_CURRENT); 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate /* 3090Sstevel@tonic-gate * If we're updating an existing file or not creating a configuration 3100Sstevel@tonic-gate * file at all, investigate the original. 3110Sstevel@tonic-gate */ 3120Sstevel@tonic-gate if ((crle.c_flags & CRLE_UPDATE) || 3130Sstevel@tonic-gate ((crle.c_flags & CRLE_CREAT) == 0)) { 3140Sstevel@tonic-gate if (inspectconfig(&crle)) 3150Sstevel@tonic-gate return (1); 3160Sstevel@tonic-gate if ((crle.c_flags & CRLE_UPDATE) == 0) 3170Sstevel@tonic-gate return (0); 3180Sstevel@tonic-gate } 3190Sstevel@tonic-gate 3200Sstevel@tonic-gate if (crle.c_flags & CRLE_VERBOSE) 3210Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_CONFILE), crle.c_confil); 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate /* 3240Sstevel@tonic-gate * Make sure the configuration file is accessible. Stat the file to 3250Sstevel@tonic-gate * determine its dev number - this is used to determine whether the 3260Sstevel@tonic-gate * temporary configuration file we're about to build can be renamed or 3270Sstevel@tonic-gate * must be copied to its final destination. 3280Sstevel@tonic-gate */ 3290Sstevel@tonic-gate (void) umask(022); 3300Sstevel@tonic-gate if (access(crle.c_confil, (R_OK | W_OK)) == 0) { 3310Sstevel@tonic-gate crle.c_flags |= CRLE_EXISTS; 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate if (stat(crle.c_confil, &ostatus) != 0) { 3340Sstevel@tonic-gate int err = errno; 3350Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 3360Sstevel@tonic-gate crle.c_name, crle.c_confil, strerror(err)); 3370Sstevel@tonic-gate return (1); 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate } else if (errno != ENOENT) { 3400Sstevel@tonic-gate int err = errno; 3410Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_ACCESS), crle.c_name, 3420Sstevel@tonic-gate crle.c_confil, strerror(err)); 3430Sstevel@tonic-gate return (1); 3440Sstevel@tonic-gate } else { 3450Sstevel@tonic-gate int fd; 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate /* 3480Sstevel@tonic-gate * Try opening the file now, if it works delete it, there may 3490Sstevel@tonic-gate * be a lot of processing ahead of us, so we'll come back and 3500Sstevel@tonic-gate * create the real thing later. 3510Sstevel@tonic-gate */ 3520Sstevel@tonic-gate if ((fd = open(crle.c_confil, (O_RDWR | O_CREAT | O_TRUNC), 3530Sstevel@tonic-gate 0666)) == -1) { 3540Sstevel@tonic-gate int err = errno; 3550Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 3560Sstevel@tonic-gate crle.c_name, crle.c_confil, strerror(err)); 3570Sstevel@tonic-gate return (1); 3580Sstevel@tonic-gate } 3590Sstevel@tonic-gate if (fstat(fd, &ostatus) != 0) { 3600Sstevel@tonic-gate int err = errno; 3610Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 3620Sstevel@tonic-gate crle.c_name, crle.c_confil, strerror(err)); 3630Sstevel@tonic-gate return (1); 3640Sstevel@tonic-gate } 3650Sstevel@tonic-gate (void) close(fd); 3660Sstevel@tonic-gate (void) unlink(crle.c_confil); 3670Sstevel@tonic-gate } 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate /* 3700Sstevel@tonic-gate * If an object directory is required to hold dldump(3dl) output assign 3710Sstevel@tonic-gate * a default if necessary and insure we're able to write there. 3720Sstevel@tonic-gate */ 3730Sstevel@tonic-gate if (crle.c_flags & CRLE_ALTER) { 3740Sstevel@tonic-gate if (lobjdir->o_objdir == 0) { 3750Sstevel@tonic-gate char *str; 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate /* 3780Sstevel@tonic-gate * Use the configuration files directory. 3790Sstevel@tonic-gate */ 3800Sstevel@tonic-gate if ((str = strrchr(crle.c_confil, '/')) == NULL) 3810Sstevel@tonic-gate lobjdir->o_objdir = 3820Sstevel@tonic-gate (char *)MSG_ORIG(MSG_DIR_DOT); 3830Sstevel@tonic-gate else { 3840Sstevel@tonic-gate int len = str - crle.c_confil; 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate if ((lobjdir->o_objdir = 3870Sstevel@tonic-gate malloc(len + 1)) == 0) { 3880Sstevel@tonic-gate int err = errno; 3890Sstevel@tonic-gate (void) fprintf(stderr, 3900Sstevel@tonic-gate MSG_INTL(MSG_SYS_MALLOC), 3910Sstevel@tonic-gate crle.c_name, strerror(err)); 3920Sstevel@tonic-gate return (1); 3930Sstevel@tonic-gate } 3940Sstevel@tonic-gate (void) strncpy(lobjdir->o_objdir, 3950Sstevel@tonic-gate crle.c_confil, len); 3960Sstevel@tonic-gate lobjdir->o_objdir[len] = '\0'; 3970Sstevel@tonic-gate } 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate /* 4010Sstevel@tonic-gate * If we're going to dldump(3dl) images ourself make sure we 4020Sstevel@tonic-gate * can access any directories. 4030Sstevel@tonic-gate */ 4040Sstevel@tonic-gate if (crle.c_flags & CRLE_DUMP) { 4050Sstevel@tonic-gate Objdir * objdir; 4060Sstevel@tonic-gate Listnode * lnp; 4070Sstevel@tonic-gate int err = 0; 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate for (LIST_TRAVERSE(&objdirs, lnp, objdir)) { 4100Sstevel@tonic-gate if (crle.c_flags & CRLE_VERBOSE) 4110Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_OBJDIR), 4120Sstevel@tonic-gate objdir->o_objdir); 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate if ((objdir->o_flags & CRLE_DUMP) == 0) 4150Sstevel@tonic-gate continue; 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate if (access(objdir->o_objdir, 4180Sstevel@tonic-gate (R_OK | W_OK)) != 0) { 4190Sstevel@tonic-gate err = errno; 4200Sstevel@tonic-gate (void) fprintf(stderr, 4210Sstevel@tonic-gate MSG_INTL(MSG_SYS_ACCESS), 4220Sstevel@tonic-gate crle.c_name, objdir->o_objdir, 4230Sstevel@tonic-gate strerror(err)); 4240Sstevel@tonic-gate } 4250Sstevel@tonic-gate } 4260Sstevel@tonic-gate if (err) 4270Sstevel@tonic-gate return (1); 4280Sstevel@tonic-gate } 4290Sstevel@tonic-gate } 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate /* 4320Sstevel@tonic-gate * Establish any initial object directory. 4330Sstevel@tonic-gate */ 4340Sstevel@tonic-gate crle.c_objdir = _lobjdir.o_objdir; 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate /* 4370Sstevel@tonic-gate * Create a temporary file name in which to build the configuration 4380Sstevel@tonic-gate * information. 4390Sstevel@tonic-gate */ 4400Sstevel@tonic-gate if ((crle.c_tempname = tempnam(MSG_ORIG(MSG_TMP_DIR), 4410Sstevel@tonic-gate MSG_ORIG(MSG_TMP_PFX))) == NULL) { 4420Sstevel@tonic-gate int err = errno; 4430Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_TEMPNAME), 4440Sstevel@tonic-gate crle.c_name, strerror(err)); 4450Sstevel@tonic-gate return (1); 4460Sstevel@tonic-gate } 4470Sstevel@tonic-gate if ((crle.c_tempfd = open(crle.c_tempname, (O_RDWR | O_CREAT), 4480Sstevel@tonic-gate 0666)) == -1) { 4490Sstevel@tonic-gate int err = errno; 4500Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 4510Sstevel@tonic-gate crle.c_name, crle.c_tempname, strerror(err)); 4520Sstevel@tonic-gate return (1); 4530Sstevel@tonic-gate } 4540Sstevel@tonic-gate if (stat(crle.c_tempname, &nstatus) != 0) { 4550Sstevel@tonic-gate int err = errno; 4560Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 4570Sstevel@tonic-gate crle.c_name, crle.c_tempname, strerror(err)); 4580Sstevel@tonic-gate return (1); 4590Sstevel@tonic-gate } 4600Sstevel@tonic-gate if (ostatus.st_dev != nstatus.st_dev) 4610Sstevel@tonic-gate crle.c_flags |= CRLE_DIFFDEV; 4620Sstevel@tonic-gate 4630Sstevel@tonic-gate /* 4640Sstevel@tonic-gate * Second pass. 4650Sstevel@tonic-gate */ 4660Sstevel@tonic-gate error = 0; 4670Sstevel@tonic-gate optind = 1; 4680Sstevel@tonic-gate while ((c = getopt(argc, argv, MSG_ORIG(MSG_ARG_OPTIONS))) != -1) { 4690Sstevel@tonic-gate const char *str; 4700Sstevel@tonic-gate int flag = 0; 4710Sstevel@tonic-gate 4720Sstevel@tonic-gate switch (c) { 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate case '6': 4750Sstevel@tonic-gate break; 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate case 'A': /* alternative is optional */ 4780Sstevel@tonic-gate flag = RTC_OBJ_OPTINAL; 4790Sstevel@tonic-gate /* FALLTHROUGH */ 4800Sstevel@tonic-gate case 'a': /* alternative required */ 4810Sstevel@tonic-gate flag |= (RTC_OBJ_ALTER | RTC_OBJ_CMDLINE); 4820Sstevel@tonic-gate if (inspect(&crle, (const char *)optarg, flag) != 0) 4830Sstevel@tonic-gate error = 1; 4840Sstevel@tonic-gate break; 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate case 'c': 4870Sstevel@tonic-gate break; 4880Sstevel@tonic-gate 4890Sstevel@tonic-gate case 'e': 4900Sstevel@tonic-gate if ((flag = addenv(&crle, (const char *)optarg, 4910Sstevel@tonic-gate RTC_ENV_REPLACE)) == 0) 4920Sstevel@tonic-gate error = 1; 4930Sstevel@tonic-gate else if ((crle.c_flags & CRLE_VERBOSE) && (flag == 1)) 4940Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_RPLENV), 4950Sstevel@tonic-gate (const char *)optarg); 4960Sstevel@tonic-gate break; 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate case 'E': 4990Sstevel@tonic-gate if ((flag = addenv(&crle, (const char *)optarg, 5000Sstevel@tonic-gate RTC_ENV_PERMANT)) == 0) 5010Sstevel@tonic-gate error = 1; 5020Sstevel@tonic-gate else if ((crle.c_flags & CRLE_VERBOSE) && (flag == 1)) 5030Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_PRMENV), 5040Sstevel@tonic-gate (const char *)optarg); 5050Sstevel@tonic-gate break; 5060Sstevel@tonic-gate 5070Sstevel@tonic-gate case 'f': 5080Sstevel@tonic-gate break; 5090Sstevel@tonic-gate 5100Sstevel@tonic-gate case 'G': /* group object */ 5110Sstevel@tonic-gate flag = (RTC_OBJ_DUMP | RTC_OBJ_ALTER); 5120Sstevel@tonic-gate /* FALLTHROUGH */ 5130Sstevel@tonic-gate case 'g': 5140Sstevel@tonic-gate flag |= (RTC_OBJ_GROUP | RTC_OBJ_CMDLINE); 5150Sstevel@tonic-gate if (inspect(&crle, (const char *)optarg, flag) != 0) 5160Sstevel@tonic-gate error = 1; 5170Sstevel@tonic-gate break; 5180Sstevel@tonic-gate 5190Sstevel@tonic-gate case 'I': /* individual object */ 5200Sstevel@tonic-gate flag = (RTC_OBJ_DUMP | RTC_OBJ_ALTER); 5210Sstevel@tonic-gate /* FALLTHROUGH */ 5220Sstevel@tonic-gate case 'i': 5230Sstevel@tonic-gate flag |= RTC_OBJ_CMDLINE; 5240Sstevel@tonic-gate if (inspect(&crle, (const char *)optarg, flag) != 0) 5250Sstevel@tonic-gate error = 1; 5260Sstevel@tonic-gate break; 5270Sstevel@tonic-gate 5280Sstevel@tonic-gate case 'l': /* library search path */ 5290Sstevel@tonic-gate if (crle.c_flags & CRLE_AOUT) { 5300Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_AOUT); 5310Sstevel@tonic-gate lib = &crle.c_adlibpath; 5320Sstevel@tonic-gate } else { 5330Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_ELF); 5340Sstevel@tonic-gate lib = &crle.c_edlibpath; 5350Sstevel@tonic-gate } 5360Sstevel@tonic-gate if (addlib(&crle, lib, (const char *)optarg) != 0) 5370Sstevel@tonic-gate error = 1; 5380Sstevel@tonic-gate else if (crle.c_flags & CRLE_VERBOSE) 5390Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_DLIBPTH), 5400Sstevel@tonic-gate str, (const char *)optarg); 5410Sstevel@tonic-gate break; 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate case 'o': 5440Sstevel@tonic-gate crle.c_objdir = optarg; 5450Sstevel@tonic-gate break; 5460Sstevel@tonic-gate 5470Sstevel@tonic-gate case 's': /* trusted (secure) path */ 5480Sstevel@tonic-gate if (crle.c_flags & CRLE_AOUT) { 5490Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_AOUT); 5500Sstevel@tonic-gate lib = &crle.c_aslibpath; 5510Sstevel@tonic-gate } else { 5520Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_ELF); 5530Sstevel@tonic-gate lib = &crle.c_eslibpath; 5540Sstevel@tonic-gate } 5550Sstevel@tonic-gate if (addlib(&crle, lib, (const char *)optarg) != 0) 5560Sstevel@tonic-gate error = 1; 5570Sstevel@tonic-gate else if (crle.c_flags & CRLE_VERBOSE) 5580Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_TLIBPTH), 5590Sstevel@tonic-gate str, (const char *)optarg); 5600Sstevel@tonic-gate break; 5610Sstevel@tonic-gate 5620Sstevel@tonic-gate case 't': /* search path type */ 5630Sstevel@tonic-gate if (strcmp((const char *)optarg, 5640Sstevel@tonic-gate MSG_ORIG(MSG_STR_ELF)) == 0) 5650Sstevel@tonic-gate crle.c_flags &= ~CRLE_AOUT; 5660Sstevel@tonic-gate else 5670Sstevel@tonic-gate crle.c_flags |= CRLE_AOUT; 5680Sstevel@tonic-gate break; 5690Sstevel@tonic-gate 5700Sstevel@tonic-gate case 'u': 5710Sstevel@tonic-gate break; 5720Sstevel@tonic-gate 5730Sstevel@tonic-gate case 'v': 5740Sstevel@tonic-gate break; 5750Sstevel@tonic-gate } 5760Sstevel@tonic-gate } 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate /* 5790Sstevel@tonic-gate * Now that we've generated as many file/directory processing errors 5800Sstevel@tonic-gate * as we can, return if any fatal error conditions occurred. 5810Sstevel@tonic-gate */ 5820Sstevel@tonic-gate if (error) { 5830Sstevel@tonic-gate (void) unlink(crle.c_tempname); 5840Sstevel@tonic-gate if (crle.c_flags & CRLE_CREAT) { 5850Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_CREATE), 5860Sstevel@tonic-gate crle.c_name, crle.c_confil); 5870Sstevel@tonic-gate } 5880Sstevel@tonic-gate return (1); 5890Sstevel@tonic-gate } 5900Sstevel@tonic-gate 5910Sstevel@tonic-gate /* 5920Sstevel@tonic-gate * Create a temporary configuration file. 5930Sstevel@tonic-gate */ 5940Sstevel@tonic-gate if (genconfig(&crle) != 0) { 5950Sstevel@tonic-gate (void) unlink(crle.c_tempname); 5960Sstevel@tonic-gate return (1); 5970Sstevel@tonic-gate } 5980Sstevel@tonic-gate 5990Sstevel@tonic-gate /* 6000Sstevel@tonic-gate * If dldump(3dl) images are required spawn a process to create them. 6010Sstevel@tonic-gate */ 6020Sstevel@tonic-gate if (crle.c_flags & CRLE_DUMP) { 6030Sstevel@tonic-gate if (dump(&crle) != 0) { 6040Sstevel@tonic-gate (void) unlink(crle.c_tempname); 6050Sstevel@tonic-gate return (1); 6060Sstevel@tonic-gate } 6070Sstevel@tonic-gate } 6080Sstevel@tonic-gate 6090Sstevel@tonic-gate /* 6100Sstevel@tonic-gate * Copy the finished temporary configuration file to its final home. 6110Sstevel@tonic-gate */ 6120Sstevel@tonic-gate if (updateconfig(&crle) != 0) 6130Sstevel@tonic-gate return (1); 6140Sstevel@tonic-gate 6150Sstevel@tonic-gate return (0); 6160Sstevel@tonic-gate } 617