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 51976Sab196087 * Common Development and Distribution License (the "License"). 61976Sab196087 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 221976Sab196087 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 260Sstevel@tonic-gate 270Sstevel@tonic-gate #include <sys/types.h> 280Sstevel@tonic-gate #include <sys/stat.h> 290Sstevel@tonic-gate #include <fcntl.h> 300Sstevel@tonic-gate #include <stdio.h> 310Sstevel@tonic-gate #include <string.h> 320Sstevel@tonic-gate #include <unistd.h> 330Sstevel@tonic-gate #include <locale.h> 340Sstevel@tonic-gate #include <dlfcn.h> 350Sstevel@tonic-gate #include <errno.h> 360Sstevel@tonic-gate #include "_crle.h" 371976Sab196087 #include "conv.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 1122056Sab196087 /*ARGSUSED2*/ 113238Sseizo int 1141976Sab196087 main(int argc, char **argv, char **envp) 1150Sstevel@tonic-gate { 1160Sstevel@tonic-gate Crle_desc crle = { 0 }; 1170Sstevel@tonic-gate int c, error = 0; 1180Sstevel@tonic-gate char ** lib; 1190Sstevel@tonic-gate List objdirs = { 0, 0 }; 1200Sstevel@tonic-gate Objdir _lobjdir = { 0, 0 }, * lobjdir = &_lobjdir; 1210Sstevel@tonic-gate struct stat ostatus, nstatus; 1221976Sab196087 int c_class; 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate if (list_append(&objdirs, lobjdir) == 0) 1250Sstevel@tonic-gate return (1); 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate /* 1280Sstevel@tonic-gate * Establish locale. 1290Sstevel@tonic-gate */ 1300Sstevel@tonic-gate (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 1310Sstevel@tonic-gate (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate /* 1340Sstevel@tonic-gate * Initialization configuration information. 1350Sstevel@tonic-gate */ 1360Sstevel@tonic-gate crle.c_name = argv[0]; 1371976Sab196087 crle.c_flags |= CRLE_ADDID; 1380Sstevel@tonic-gate crle.c_strbkts = 503; 1390Sstevel@tonic-gate crle.c_inobkts = 251; 1401976Sab196087 c_class = M_CLASS; 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate /* 1430Sstevel@tonic-gate * First argument pass. 1440Sstevel@tonic-gate */ 1450Sstevel@tonic-gate while ((c = getopt(argc, argv, MSG_ORIG(MSG_ARG_OPTIONS))) != -1) { 1460Sstevel@tonic-gate switch (c) { 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate case '6': /* operate on 64-bit objects */ 1490Sstevel@tonic-gate if (optarg[0] != '4') { 1500Sstevel@tonic-gate (void) fprintf(stderr, 1510Sstevel@tonic-gate MSG_INTL(MSG_ARG_ILLEGAL), crle.c_name, 1520Sstevel@tonic-gate MSG_ORIG(MSG_ARG_6), optarg); 1530Sstevel@tonic-gate error = 1; 1540Sstevel@tonic-gate } 1551976Sab196087 1561976Sab196087 c_class = ELFCLASS64; 1570Sstevel@tonic-gate break; 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate case 'A': /* create optional */ 1600Sstevel@tonic-gate /* FALLTHROUGH */ /* alternative */ 1610Sstevel@tonic-gate case 'a': /* create alternative */ 1620Sstevel@tonic-gate crle.c_flags |= (CRLE_CREAT | CRLE_ALTER); 1630Sstevel@tonic-gate lobjdir->o_flags |= (CRLE_CREAT | CRLE_ALTER); 1640Sstevel@tonic-gate break; 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate case 'c': /* define the config file */ 1670Sstevel@tonic-gate if (crle.c_confil) { 1680Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_MULT), 1690Sstevel@tonic-gate crle.c_name, MSG_ORIG(MSG_ARG_C)); 1700Sstevel@tonic-gate error = 1; 1710Sstevel@tonic-gate } 1720Sstevel@tonic-gate crle.c_confil = optarg; 1730Sstevel@tonic-gate break; 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate case 'e': /* replaceable env variable */ 1760Sstevel@tonic-gate crle.c_flags |= (CRLE_RPLENV | CRLE_CREAT); 1770Sstevel@tonic-gate break; 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate case 'E': /* permanent env variable */ 1800Sstevel@tonic-gate crle.c_flags |= (CRLE_PRMENV | CRLE_CREAT); 1810Sstevel@tonic-gate break; 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate case 'f': /* dldump(3dl) flags */ 1840Sstevel@tonic-gate if (crle.c_dlflags) { 1850Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_MULT), 1860Sstevel@tonic-gate crle.c_name, MSG_ORIG(MSG_ARG_F)); 1870Sstevel@tonic-gate error = 1; 1880Sstevel@tonic-gate } 1890Sstevel@tonic-gate if ((crle.c_dlflags = dlflags(&crle, 1900Sstevel@tonic-gate (const char *)optarg)) == 0) 1910Sstevel@tonic-gate error = 1; 1920Sstevel@tonic-gate break; 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate case 'G': /* group object */ 1950Sstevel@tonic-gate crle.c_flags |= (CRLE_DUMP | CRLE_ALTER); 1960Sstevel@tonic-gate lobjdir->o_flags |= (CRLE_DUMP | CRLE_ALTER); 1970Sstevel@tonic-gate /* FALLTHROUGH */ 1980Sstevel@tonic-gate case 'g': 1990Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT; 2000Sstevel@tonic-gate lobjdir->o_flags |= CRLE_CREAT; 2010Sstevel@tonic-gate break; 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate case 'I': /* individual object */ 2040Sstevel@tonic-gate crle.c_flags |= (CRLE_DUMP | CRLE_ALTER); 2050Sstevel@tonic-gate lobjdir->o_flags |= (CRLE_DUMP | CRLE_ALTER); 2060Sstevel@tonic-gate /* FALLTHROUGH */ 2070Sstevel@tonic-gate case 'i': 2080Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT; 2090Sstevel@tonic-gate lobjdir->o_flags |= CRLE_CREAT; 2100Sstevel@tonic-gate break; 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate case 'l': /* library search path */ 2130Sstevel@tonic-gate if (crle.c_flags & CRLE_AOUT) 2140Sstevel@tonic-gate crle.c_flags |= CRLE_ADLIB; 2150Sstevel@tonic-gate else 2160Sstevel@tonic-gate crle.c_flags |= CRLE_EDLIB; 2170Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT; 2180Sstevel@tonic-gate break; 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate case 'o': /* define an object directory */ 2210Sstevel@tonic-gate if (lobjdir->o_objdir) { 2220Sstevel@tonic-gate if ((lobjdir = calloc(sizeof (Objdir), 1)) == 0) 2230Sstevel@tonic-gate return (1); 2240Sstevel@tonic-gate if (list_append(&objdirs, lobjdir) == 0) 2250Sstevel@tonic-gate return (1); 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate lobjdir->o_objdir = optarg; 2280Sstevel@tonic-gate break; 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate case 's': /* trusted (secure) path */ 2310Sstevel@tonic-gate if (crle.c_flags & CRLE_AOUT) 2320Sstevel@tonic-gate crle.c_flags |= CRLE_ASLIB; 2330Sstevel@tonic-gate else 2340Sstevel@tonic-gate crle.c_flags |= CRLE_ESLIB; 2350Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT; 2360Sstevel@tonic-gate break; 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate case 't': /* search path type */ 2390Sstevel@tonic-gate if (strcmp((const char *)optarg, 2400Sstevel@tonic-gate MSG_ORIG(MSG_STR_ELF)) == 0) 2410Sstevel@tonic-gate crle.c_flags &= ~CRLE_AOUT; 2420Sstevel@tonic-gate else if (strcmp((const char *)optarg, 2430Sstevel@tonic-gate MSG_ORIG(MSG_STR_AOUT)) == 0) 2440Sstevel@tonic-gate crle.c_flags |= CRLE_AOUT; 2450Sstevel@tonic-gate else { 2460Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_TYPE), 2470Sstevel@tonic-gate crle.c_name, optarg); 2480Sstevel@tonic-gate error = 1; 2490Sstevel@tonic-gate } 2500Sstevel@tonic-gate break; 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate case 'u': /* update mode */ 2530Sstevel@tonic-gate crle.c_flags |= (CRLE_CREAT | CRLE_UPDATE); 2540Sstevel@tonic-gate break; 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate case 'v': /* verbose mode */ 2570Sstevel@tonic-gate crle.c_flags |= CRLE_VERBOSE; 2580Sstevel@tonic-gate break; 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate default: 2610Sstevel@tonic-gate error = 2; 2620Sstevel@tonic-gate } 2630Sstevel@tonic-gate } 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate if (optind != argc) 2660Sstevel@tonic-gate error = 2; 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate /* 2690Sstevel@tonic-gate * Determine the configuration file, which in the case of an existing 2700Sstevel@tonic-gate * error condition is required in the final error message. 2710Sstevel@tonic-gate */ 2720Sstevel@tonic-gate if (crle.c_confil == 0) { 2730Sstevel@tonic-gate crle.c_flags |= CRLE_CONFDEF; 2741976Sab196087 if (c_class == ELFCLASS32) { 2750Sstevel@tonic-gate crle.c_confil = (char *)MSG_ORIG(MSG_PTH_CONFIG); 2761976Sab196087 } else { 2770Sstevel@tonic-gate crle.c_confil = (char *)MSG_ORIG(MSG_PTH_CONFIG_64); 2781976Sab196087 } 2790Sstevel@tonic-gate } 2800Sstevel@tonic-gate 2810Sstevel@tonic-gate /* 2820Sstevel@tonic-gate * Now that we've generated as many file/directory processing errors 2830Sstevel@tonic-gate * as we can, return if any fatal error conditions occurred. 2840Sstevel@tonic-gate */ 2850Sstevel@tonic-gate if (error) { 2860Sstevel@tonic-gate if (error == 2) { 2870Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_USAGE), 2880Sstevel@tonic-gate crle.c_name); 2890Sstevel@tonic-gate } else if (crle.c_flags & CRLE_CREAT) { 2900Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_CREATE), 2910Sstevel@tonic-gate crle.c_name, crle.c_confil); 2920Sstevel@tonic-gate } 2930Sstevel@tonic-gate return (1); 2940Sstevel@tonic-gate } 2950Sstevel@tonic-gate 2960Sstevel@tonic-gate /* 2970Sstevel@tonic-gate * Apply any additional defaults. 2980Sstevel@tonic-gate */ 2990Sstevel@tonic-gate if (crle.c_dlflags == 0) 3000Sstevel@tonic-gate crle.c_dlflags = RTLD_REL_RELATIVE; 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate crle.c_audit = (char *)MSG_ORIG(MSG_ENV_LD_AUDIT); 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate (void) elf_version(EV_CURRENT); 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate /* 3070Sstevel@tonic-gate * If we're updating an existing file or not creating a configuration 3080Sstevel@tonic-gate * file at all, investigate the original. 3090Sstevel@tonic-gate */ 3100Sstevel@tonic-gate if ((crle.c_flags & CRLE_UPDATE) || 3110Sstevel@tonic-gate ((crle.c_flags & CRLE_CREAT) == 0)) { 3122056Sab196087 switch (inspectconfig(&crle, c_class)) { 3131976Sab196087 case INSCFG_RET_OK: 3141976Sab196087 if ((crle.c_flags & CRLE_UPDATE) == 0) 3151976Sab196087 return (0); 3161976Sab196087 break; 3171976Sab196087 case INSCFG_RET_FAIL: 3180Sstevel@tonic-gate return (1); 3191976Sab196087 case INSCFG_RET_NEED64: 3201976Sab196087 c_class = ELFCLASS64; 3211976Sab196087 break; 3221976Sab196087 } 3230Sstevel@tonic-gate } 3240Sstevel@tonic-gate 3251976Sab196087 /* 3261976Sab196087 * Ensure that the right version (32 or 64-bit) of this program 3271976Sab196087 * is running. The 32 and 64-bit compilers may align fields within 3281976Sab196087 * structures differently. Using the right version of crle for 3291976Sab196087 * the config file ensures that all linker components will see 3301976Sab196087 * the same layout, without the need for special code. 3311976Sab196087 */ 3321976Sab196087 #ifdef _ELF64 3331976Sab196087 if (c_class == ELFCLASS32) { 3341976Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ARG_CLASS), 3351976Sab196087 crle.c_name, crle.c_confil); 3361976Sab196087 return (1); 3371976Sab196087 } 3381976Sab196087 #else 3391976Sab196087 if (c_class == ELFCLASS64) { 340*2647Srie (void) conv_check_native(argv, envp); 3411976Sab196087 3421976Sab196087 /* 3431976Sab196087 * conv_check_native() should not return, as we expect 3441976Sab196087 * the 64-bit version to have executed on top of us. 3451976Sab196087 * If it does, it means there is no 64-bit support 3461976Sab196087 * available on this system. 3471976Sab196087 */ 3481976Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ISA32_NO64SUP), 349*2647Srie crle.c_name); 3501976Sab196087 return (1); 3511976Sab196087 } 3521976Sab196087 #endif 3531976Sab196087 3540Sstevel@tonic-gate if (crle.c_flags & CRLE_VERBOSE) 3550Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_CONFILE), crle.c_confil); 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate /* 3580Sstevel@tonic-gate * Make sure the configuration file is accessible. Stat the file to 3590Sstevel@tonic-gate * determine its dev number - this is used to determine whether the 3600Sstevel@tonic-gate * temporary configuration file we're about to build can be renamed or 3610Sstevel@tonic-gate * must be copied to its final destination. 3620Sstevel@tonic-gate */ 3630Sstevel@tonic-gate (void) umask(022); 3640Sstevel@tonic-gate if (access(crle.c_confil, (R_OK | W_OK)) == 0) { 3650Sstevel@tonic-gate crle.c_flags |= CRLE_EXISTS; 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate if (stat(crle.c_confil, &ostatus) != 0) { 3680Sstevel@tonic-gate int err = errno; 3690Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 3700Sstevel@tonic-gate crle.c_name, crle.c_confil, strerror(err)); 3710Sstevel@tonic-gate return (1); 3720Sstevel@tonic-gate } 3730Sstevel@tonic-gate } else if (errno != ENOENT) { 3740Sstevel@tonic-gate int err = errno; 3750Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_ACCESS), crle.c_name, 3760Sstevel@tonic-gate crle.c_confil, strerror(err)); 3770Sstevel@tonic-gate return (1); 3780Sstevel@tonic-gate } else { 3790Sstevel@tonic-gate int fd; 3800Sstevel@tonic-gate 3810Sstevel@tonic-gate /* 3820Sstevel@tonic-gate * Try opening the file now, if it works delete it, there may 3830Sstevel@tonic-gate * be a lot of processing ahead of us, so we'll come back and 3840Sstevel@tonic-gate * create the real thing later. 3850Sstevel@tonic-gate */ 3860Sstevel@tonic-gate if ((fd = open(crle.c_confil, (O_RDWR | O_CREAT | O_TRUNC), 3870Sstevel@tonic-gate 0666)) == -1) { 3880Sstevel@tonic-gate int err = errno; 3890Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 3900Sstevel@tonic-gate crle.c_name, crle.c_confil, strerror(err)); 3910Sstevel@tonic-gate return (1); 3920Sstevel@tonic-gate } 3930Sstevel@tonic-gate if (fstat(fd, &ostatus) != 0) { 3940Sstevel@tonic-gate int err = errno; 3950Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 3960Sstevel@tonic-gate crle.c_name, crle.c_confil, strerror(err)); 3970Sstevel@tonic-gate return (1); 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate (void) close(fd); 4000Sstevel@tonic-gate (void) unlink(crle.c_confil); 4010Sstevel@tonic-gate } 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate /* 4040Sstevel@tonic-gate * If an object directory is required to hold dldump(3dl) output assign 4050Sstevel@tonic-gate * a default if necessary and insure we're able to write there. 4060Sstevel@tonic-gate */ 4070Sstevel@tonic-gate if (crle.c_flags & CRLE_ALTER) { 4080Sstevel@tonic-gate if (lobjdir->o_objdir == 0) { 4090Sstevel@tonic-gate char *str; 4100Sstevel@tonic-gate 4110Sstevel@tonic-gate /* 4120Sstevel@tonic-gate * Use the configuration files directory. 4130Sstevel@tonic-gate */ 4140Sstevel@tonic-gate if ((str = strrchr(crle.c_confil, '/')) == NULL) 4150Sstevel@tonic-gate lobjdir->o_objdir = 4160Sstevel@tonic-gate (char *)MSG_ORIG(MSG_DIR_DOT); 4170Sstevel@tonic-gate else { 4180Sstevel@tonic-gate int len = str - crle.c_confil; 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate if ((lobjdir->o_objdir = 4210Sstevel@tonic-gate malloc(len + 1)) == 0) { 4220Sstevel@tonic-gate int err = errno; 4230Sstevel@tonic-gate (void) fprintf(stderr, 4240Sstevel@tonic-gate MSG_INTL(MSG_SYS_MALLOC), 4250Sstevel@tonic-gate crle.c_name, strerror(err)); 4260Sstevel@tonic-gate return (1); 4270Sstevel@tonic-gate } 4280Sstevel@tonic-gate (void) strncpy(lobjdir->o_objdir, 4290Sstevel@tonic-gate crle.c_confil, len); 4300Sstevel@tonic-gate lobjdir->o_objdir[len] = '\0'; 4310Sstevel@tonic-gate } 4320Sstevel@tonic-gate } 4330Sstevel@tonic-gate 4340Sstevel@tonic-gate /* 4350Sstevel@tonic-gate * If we're going to dldump(3dl) images ourself make sure we 4360Sstevel@tonic-gate * can access any directories. 4370Sstevel@tonic-gate */ 4380Sstevel@tonic-gate if (crle.c_flags & CRLE_DUMP) { 4390Sstevel@tonic-gate Objdir * objdir; 4400Sstevel@tonic-gate Listnode * lnp; 4410Sstevel@tonic-gate int err = 0; 4420Sstevel@tonic-gate 4430Sstevel@tonic-gate for (LIST_TRAVERSE(&objdirs, lnp, objdir)) { 4440Sstevel@tonic-gate if (crle.c_flags & CRLE_VERBOSE) 4450Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_OBJDIR), 4460Sstevel@tonic-gate objdir->o_objdir); 4470Sstevel@tonic-gate 4480Sstevel@tonic-gate if ((objdir->o_flags & CRLE_DUMP) == 0) 4490Sstevel@tonic-gate continue; 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate if (access(objdir->o_objdir, 4520Sstevel@tonic-gate (R_OK | W_OK)) != 0) { 4530Sstevel@tonic-gate err = errno; 4540Sstevel@tonic-gate (void) fprintf(stderr, 4550Sstevel@tonic-gate MSG_INTL(MSG_SYS_ACCESS), 4560Sstevel@tonic-gate crle.c_name, objdir->o_objdir, 4570Sstevel@tonic-gate strerror(err)); 4580Sstevel@tonic-gate } 4590Sstevel@tonic-gate } 4600Sstevel@tonic-gate if (err) 4610Sstevel@tonic-gate return (1); 4620Sstevel@tonic-gate } 4630Sstevel@tonic-gate } 4640Sstevel@tonic-gate 4650Sstevel@tonic-gate /* 4660Sstevel@tonic-gate * Establish any initial object directory. 4670Sstevel@tonic-gate */ 4680Sstevel@tonic-gate crle.c_objdir = _lobjdir.o_objdir; 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate /* 4710Sstevel@tonic-gate * Create a temporary file name in which to build the configuration 4720Sstevel@tonic-gate * information. 4730Sstevel@tonic-gate */ 4740Sstevel@tonic-gate if ((crle.c_tempname = tempnam(MSG_ORIG(MSG_TMP_DIR), 4750Sstevel@tonic-gate MSG_ORIG(MSG_TMP_PFX))) == NULL) { 4760Sstevel@tonic-gate int err = errno; 4770Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_TEMPNAME), 4780Sstevel@tonic-gate crle.c_name, strerror(err)); 4790Sstevel@tonic-gate return (1); 4800Sstevel@tonic-gate } 4810Sstevel@tonic-gate if ((crle.c_tempfd = open(crle.c_tempname, (O_RDWR | O_CREAT), 4820Sstevel@tonic-gate 0666)) == -1) { 4830Sstevel@tonic-gate int err = errno; 4840Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 4850Sstevel@tonic-gate crle.c_name, crle.c_tempname, strerror(err)); 4860Sstevel@tonic-gate return (1); 4870Sstevel@tonic-gate } 4880Sstevel@tonic-gate if (stat(crle.c_tempname, &nstatus) != 0) { 4890Sstevel@tonic-gate int err = errno; 4900Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 4910Sstevel@tonic-gate crle.c_name, crle.c_tempname, strerror(err)); 4920Sstevel@tonic-gate return (1); 4930Sstevel@tonic-gate } 4940Sstevel@tonic-gate if (ostatus.st_dev != nstatus.st_dev) 4950Sstevel@tonic-gate crle.c_flags |= CRLE_DIFFDEV; 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate /* 4980Sstevel@tonic-gate * Second pass. 4990Sstevel@tonic-gate */ 5000Sstevel@tonic-gate error = 0; 5010Sstevel@tonic-gate optind = 1; 5020Sstevel@tonic-gate while ((c = getopt(argc, argv, MSG_ORIG(MSG_ARG_OPTIONS))) != -1) { 5030Sstevel@tonic-gate const char *str; 5040Sstevel@tonic-gate int flag = 0; 5050Sstevel@tonic-gate 5060Sstevel@tonic-gate switch (c) { 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate case '6': 5090Sstevel@tonic-gate break; 5100Sstevel@tonic-gate 5110Sstevel@tonic-gate case 'A': /* alternative is optional */ 5120Sstevel@tonic-gate flag = RTC_OBJ_OPTINAL; 5130Sstevel@tonic-gate /* FALLTHROUGH */ 5140Sstevel@tonic-gate case 'a': /* alternative required */ 5150Sstevel@tonic-gate flag |= (RTC_OBJ_ALTER | RTC_OBJ_CMDLINE); 5160Sstevel@tonic-gate if (inspect(&crle, (const char *)optarg, flag) != 0) 5170Sstevel@tonic-gate error = 1; 5180Sstevel@tonic-gate break; 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate case 'c': 5210Sstevel@tonic-gate break; 5220Sstevel@tonic-gate 5230Sstevel@tonic-gate case 'e': 5240Sstevel@tonic-gate if ((flag = addenv(&crle, (const char *)optarg, 5250Sstevel@tonic-gate RTC_ENV_REPLACE)) == 0) 5260Sstevel@tonic-gate error = 1; 5270Sstevel@tonic-gate else if ((crle.c_flags & CRLE_VERBOSE) && (flag == 1)) 5280Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_RPLENV), 5290Sstevel@tonic-gate (const char *)optarg); 5300Sstevel@tonic-gate break; 5310Sstevel@tonic-gate 5320Sstevel@tonic-gate case 'E': 5330Sstevel@tonic-gate if ((flag = addenv(&crle, (const char *)optarg, 5340Sstevel@tonic-gate RTC_ENV_PERMANT)) == 0) 5350Sstevel@tonic-gate error = 1; 5360Sstevel@tonic-gate else if ((crle.c_flags & CRLE_VERBOSE) && (flag == 1)) 5370Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_PRMENV), 5380Sstevel@tonic-gate (const char *)optarg); 5390Sstevel@tonic-gate break; 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate case 'f': 5420Sstevel@tonic-gate break; 5430Sstevel@tonic-gate 5440Sstevel@tonic-gate case 'G': /* group object */ 5450Sstevel@tonic-gate flag = (RTC_OBJ_DUMP | RTC_OBJ_ALTER); 5460Sstevel@tonic-gate /* FALLTHROUGH */ 5470Sstevel@tonic-gate case 'g': 5480Sstevel@tonic-gate flag |= (RTC_OBJ_GROUP | RTC_OBJ_CMDLINE); 5490Sstevel@tonic-gate if (inspect(&crle, (const char *)optarg, flag) != 0) 5500Sstevel@tonic-gate error = 1; 5510Sstevel@tonic-gate break; 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate case 'I': /* individual object */ 5540Sstevel@tonic-gate flag = (RTC_OBJ_DUMP | RTC_OBJ_ALTER); 5550Sstevel@tonic-gate /* FALLTHROUGH */ 5560Sstevel@tonic-gate case 'i': 5570Sstevel@tonic-gate flag |= RTC_OBJ_CMDLINE; 5580Sstevel@tonic-gate if (inspect(&crle, (const char *)optarg, flag) != 0) 5590Sstevel@tonic-gate error = 1; 5600Sstevel@tonic-gate break; 5610Sstevel@tonic-gate 5620Sstevel@tonic-gate case 'l': /* library search path */ 5630Sstevel@tonic-gate if (crle.c_flags & CRLE_AOUT) { 5640Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_AOUT); 5650Sstevel@tonic-gate lib = &crle.c_adlibpath; 5660Sstevel@tonic-gate } else { 5670Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_ELF); 5680Sstevel@tonic-gate lib = &crle.c_edlibpath; 5690Sstevel@tonic-gate } 5700Sstevel@tonic-gate if (addlib(&crle, lib, (const char *)optarg) != 0) 5710Sstevel@tonic-gate error = 1; 5720Sstevel@tonic-gate else if (crle.c_flags & CRLE_VERBOSE) 5730Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_DLIBPTH), 5740Sstevel@tonic-gate str, (const char *)optarg); 5750Sstevel@tonic-gate break; 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate case 'o': 5780Sstevel@tonic-gate crle.c_objdir = optarg; 5790Sstevel@tonic-gate break; 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate case 's': /* trusted (secure) path */ 5820Sstevel@tonic-gate if (crle.c_flags & CRLE_AOUT) { 5830Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_AOUT); 5840Sstevel@tonic-gate lib = &crle.c_aslibpath; 5850Sstevel@tonic-gate } else { 5860Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_ELF); 5870Sstevel@tonic-gate lib = &crle.c_eslibpath; 5880Sstevel@tonic-gate } 5890Sstevel@tonic-gate if (addlib(&crle, lib, (const char *)optarg) != 0) 5900Sstevel@tonic-gate error = 1; 5910Sstevel@tonic-gate else if (crle.c_flags & CRLE_VERBOSE) 5920Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_TLIBPTH), 5930Sstevel@tonic-gate str, (const char *)optarg); 5940Sstevel@tonic-gate break; 5950Sstevel@tonic-gate 5960Sstevel@tonic-gate case 't': /* search path type */ 5970Sstevel@tonic-gate if (strcmp((const char *)optarg, 5980Sstevel@tonic-gate MSG_ORIG(MSG_STR_ELF)) == 0) 5990Sstevel@tonic-gate crle.c_flags &= ~CRLE_AOUT; 6000Sstevel@tonic-gate else 6010Sstevel@tonic-gate crle.c_flags |= CRLE_AOUT; 6020Sstevel@tonic-gate break; 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate case 'u': 6050Sstevel@tonic-gate break; 6060Sstevel@tonic-gate 6070Sstevel@tonic-gate case 'v': 6080Sstevel@tonic-gate break; 6090Sstevel@tonic-gate } 6100Sstevel@tonic-gate } 6110Sstevel@tonic-gate 6120Sstevel@tonic-gate /* 6130Sstevel@tonic-gate * Now that we've generated as many file/directory processing errors 6140Sstevel@tonic-gate * as we can, return if any fatal error conditions occurred. 6150Sstevel@tonic-gate */ 6160Sstevel@tonic-gate if (error) { 6170Sstevel@tonic-gate (void) unlink(crle.c_tempname); 6180Sstevel@tonic-gate if (crle.c_flags & CRLE_CREAT) { 6190Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_CREATE), 6200Sstevel@tonic-gate crle.c_name, crle.c_confil); 6210Sstevel@tonic-gate } 6220Sstevel@tonic-gate return (1); 6230Sstevel@tonic-gate } 6240Sstevel@tonic-gate 6250Sstevel@tonic-gate /* 6260Sstevel@tonic-gate * Create a temporary configuration file. 6270Sstevel@tonic-gate */ 6280Sstevel@tonic-gate if (genconfig(&crle) != 0) { 6290Sstevel@tonic-gate (void) unlink(crle.c_tempname); 6300Sstevel@tonic-gate return (1); 6310Sstevel@tonic-gate } 6320Sstevel@tonic-gate 6330Sstevel@tonic-gate /* 6340Sstevel@tonic-gate * If dldump(3dl) images are required spawn a process to create them. 6350Sstevel@tonic-gate */ 6360Sstevel@tonic-gate if (crle.c_flags & CRLE_DUMP) { 6370Sstevel@tonic-gate if (dump(&crle) != 0) { 6380Sstevel@tonic-gate (void) unlink(crle.c_tempname); 6390Sstevel@tonic-gate return (1); 6400Sstevel@tonic-gate } 6410Sstevel@tonic-gate } 6420Sstevel@tonic-gate 6430Sstevel@tonic-gate /* 6440Sstevel@tonic-gate * Copy the finished temporary configuration file to its final home. 6450Sstevel@tonic-gate */ 6460Sstevel@tonic-gate if (updateconfig(&crle) != 0) 6470Sstevel@tonic-gate return (1); 6480Sstevel@tonic-gate 6490Sstevel@tonic-gate return (0); 6500Sstevel@tonic-gate } 651