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 /*
22*9131SRod.Evans@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/stat.h>
280Sstevel@tonic-gate #include <fcntl.h>
290Sstevel@tonic-gate #include <stdio.h>
300Sstevel@tonic-gate #include <string.h>
310Sstevel@tonic-gate #include <unistd.h>
320Sstevel@tonic-gate #include <locale.h>
330Sstevel@tonic-gate #include <dlfcn.h>
340Sstevel@tonic-gate #include <errno.h>
350Sstevel@tonic-gate #include "_crle.h"
361976Sab196087 #include "conv.h"
370Sstevel@tonic-gate #include "msg.h"
380Sstevel@tonic-gate
390Sstevel@tonic-gate
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate * crle(1) entry point and argument processing.
420Sstevel@tonic-gate *
430Sstevel@tonic-gate * Two passes of the arguments are carried out; the first collects any single
440Sstevel@tonic-gate * instance options and establishes defaults that might be appropriate for
450Sstevel@tonic-gate * other arguments:
460Sstevel@tonic-gate *
470Sstevel@tonic-gate * -64 operate on, or apply, 64-bit objects (default is 32-bit).
480Sstevel@tonic-gate *
490Sstevel@tonic-gate * -c file defines the output configuration file.
500Sstevel@tonic-gate *
510Sstevel@tonic-gate * -f flag flags for dldump(3dl).
520Sstevel@tonic-gate *
530Sstevel@tonic-gate * -o dir defines the output directory for any dldump(3dl) objects
540Sstevel@tonic-gate * that follow. For backward compatibility (RTC_VER_ONE only
550Sstevel@tonic-gate * allowed one output directory) allow the first occurrence of this
560Sstevel@tonic-gate * specification to catch any previous files. If not specified,
570Sstevel@tonic-gate * the configuration files parent directory is used).
580Sstevel@tonic-gate *
590Sstevel@tonic-gate * -u update any existing configuration file. Any additional
600Sstevel@tonic-gate * arguments supplied will be added to the new configuration
610Sstevel@tonic-gate * information.
620Sstevel@tonic-gate *
630Sstevel@tonic-gate * -v verbose mode.
640Sstevel@tonic-gate *
650Sstevel@tonic-gate * The second pass collects all other options and constructs an internal
660Sstevel@tonic-gate * string table which will be used to create the eventual configuration file.
670Sstevel@tonic-gate *
680Sstevel@tonic-gate * -a name add the individual name, with an alternative to the
690Sstevel@tonic-gate * configuration cache. No alternative is created via dldump(3dl),
700Sstevel@tonic-gate * it is the users responsibility to furnish the alternative.
710Sstevel@tonic-gate *
720Sstevel@tonic-gate * -A name add the individual name, with an optional alternative to the
730Sstevel@tonic-gate * configuration cache. No alternative is created via dldump(3dl),
740Sstevel@tonic-gate * it is the users responsibility to furnish the alternative.
750Sstevel@tonic-gate *
760Sstevel@tonic-gate * -e envar replaceable environment variable
770Sstevel@tonic-gate *
780Sstevel@tonic-gate * -E envar permanent environment variable
790Sstevel@tonic-gate *
800Sstevel@tonic-gate * -i name add the individual name to the configuration cache. If name
810Sstevel@tonic-gate * is a directory each shared object within the directory is added
820Sstevel@tonic-gate * to the cache.
830Sstevel@tonic-gate *
840Sstevel@tonic-gate * -I name same as -i, but in addition any ELF objects are dldump(3dl)'ed.
850Sstevel@tonic-gate *
860Sstevel@tonic-gate * -g name add the group name to the configuration cache. Each object is
870Sstevel@tonic-gate * expanded to determine its dependencies and these are added to
880Sstevel@tonic-gate * the cache. If name is a directory each shared object within the
890Sstevel@tonic-gate * directory and its dependencies are added to the cache.
900Sstevel@tonic-gate *
910Sstevel@tonic-gate * -G app same as -g, but in addition any ELF objects are dldump(3dl)'ed.
920Sstevel@tonic-gate *
930Sstevel@tonic-gate * -l dir library search directory
940Sstevel@tonic-gate *
950Sstevel@tonic-gate * -s dir trusted (secure) directory
960Sstevel@tonic-gate *
970Sstevel@tonic-gate * -t type search directory type (ELF or AOUT).
980Sstevel@tonic-gate */
990Sstevel@tonic-gate
1000Sstevel@tonic-gate /*
1010Sstevel@tonic-gate * Establish a structure for maintaining current object directory attributes.
1020Sstevel@tonic-gate * We wish to validate the access of any object directory that will be written
1030Sstevel@tonic-gate * to (dldump(3dl), and thus by maintaining a current object directory and its
1040Sstevel@tonic-gate * intended use we can perform this validation later.
1050Sstevel@tonic-gate */
1060Sstevel@tonic-gate typedef struct {
107*9131SRod.Evans@Sun.COM char *o_objdir;
108*9131SRod.Evans@Sun.COM uint_t o_flags;
1090Sstevel@tonic-gate } Objdir;
1100Sstevel@tonic-gate
1112056Sab196087 /*ARGSUSED2*/
112238Sseizo int
main(int argc,char ** argv,char ** envp)1131976Sab196087 main(int argc, char **argv, char **envp)
1140Sstevel@tonic-gate {
1150Sstevel@tonic-gate Crle_desc crle = { 0 };
1160Sstevel@tonic-gate int c, error = 0;
117*9131SRod.Evans@Sun.COM char **lib;
118*9131SRod.Evans@Sun.COM Alist *objdirs = NULL;
119*9131SRod.Evans@Sun.COM Objdir *objdir, *iobjdir;
1200Sstevel@tonic-gate struct stat ostatus, nstatus;
1211976Sab196087 int c_class;
1220Sstevel@tonic-gate
123*9131SRod.Evans@Sun.COM if ((objdir = iobjdir = alist_append(&objdirs, NULL, sizeof (Objdir),
124*9131SRod.Evans@Sun.COM AL_CNT_CRLE)) == NULL)
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);
163*9131SRod.Evans@Sun.COM objdir->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);
196*9131SRod.Evans@Sun.COM objdir->o_flags |= (CRLE_DUMP | CRLE_ALTER);
1970Sstevel@tonic-gate /* FALLTHROUGH */
1980Sstevel@tonic-gate case 'g':
1990Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT;
200*9131SRod.Evans@Sun.COM objdir->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);
205*9131SRod.Evans@Sun.COM objdir->o_flags |= (CRLE_DUMP | CRLE_ALTER);
2060Sstevel@tonic-gate /* FALLTHROUGH */
2070Sstevel@tonic-gate case 'i':
2080Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT;
209*9131SRod.Evans@Sun.COM objdir->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 */
221*9131SRod.Evans@Sun.COM if (objdir->o_objdir) {
222*9131SRod.Evans@Sun.COM if ((objdir = alist_append(&objdirs, NULL,
223*9131SRod.Evans@Sun.COM sizeof (Objdir), AL_CNT_CRLE)) == NULL)
2240Sstevel@tonic-gate return (1);
2250Sstevel@tonic-gate }
226*9131SRod.Evans@Sun.COM objdir->o_objdir = optarg;
2270Sstevel@tonic-gate break;
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate case 's': /* trusted (secure) path */
2300Sstevel@tonic-gate if (crle.c_flags & CRLE_AOUT)
2310Sstevel@tonic-gate crle.c_flags |= CRLE_ASLIB;
2320Sstevel@tonic-gate else
2330Sstevel@tonic-gate crle.c_flags |= CRLE_ESLIB;
2340Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT;
2350Sstevel@tonic-gate break;
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate case 't': /* search path type */
2380Sstevel@tonic-gate if (strcmp((const char *)optarg,
2390Sstevel@tonic-gate MSG_ORIG(MSG_STR_ELF)) == 0)
2400Sstevel@tonic-gate crle.c_flags &= ~CRLE_AOUT;
2410Sstevel@tonic-gate else if (strcmp((const char *)optarg,
2420Sstevel@tonic-gate MSG_ORIG(MSG_STR_AOUT)) == 0)
2430Sstevel@tonic-gate crle.c_flags |= CRLE_AOUT;
2440Sstevel@tonic-gate else {
2450Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_TYPE),
2460Sstevel@tonic-gate crle.c_name, optarg);
2470Sstevel@tonic-gate error = 1;
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate break;
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate case 'u': /* update mode */
2520Sstevel@tonic-gate crle.c_flags |= (CRLE_CREAT | CRLE_UPDATE);
2530Sstevel@tonic-gate break;
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate case 'v': /* verbose mode */
2560Sstevel@tonic-gate crle.c_flags |= CRLE_VERBOSE;
2570Sstevel@tonic-gate break;
2580Sstevel@tonic-gate
2590Sstevel@tonic-gate default:
2600Sstevel@tonic-gate error = 2;
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate }
2630Sstevel@tonic-gate
2640Sstevel@tonic-gate if (optind != argc)
2650Sstevel@tonic-gate error = 2;
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate /*
2680Sstevel@tonic-gate * Determine the configuration file, which in the case of an existing
2690Sstevel@tonic-gate * error condition is required in the final error message.
2700Sstevel@tonic-gate */
271*9131SRod.Evans@Sun.COM if (crle.c_confil == NULL) {
2720Sstevel@tonic-gate crle.c_flags |= CRLE_CONFDEF;
2731976Sab196087 if (c_class == ELFCLASS32) {
2740Sstevel@tonic-gate crle.c_confil = (char *)MSG_ORIG(MSG_PTH_CONFIG);
2751976Sab196087 } else {
2760Sstevel@tonic-gate crle.c_confil = (char *)MSG_ORIG(MSG_PTH_CONFIG_64);
2771976Sab196087 }
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate /*
2810Sstevel@tonic-gate * Now that we've generated as many file/directory processing errors
2820Sstevel@tonic-gate * as we can, return if any fatal error conditions occurred.
2830Sstevel@tonic-gate */
2840Sstevel@tonic-gate if (error) {
2850Sstevel@tonic-gate if (error == 2) {
2860Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_USAGE),
2870Sstevel@tonic-gate crle.c_name);
2880Sstevel@tonic-gate } else if (crle.c_flags & CRLE_CREAT) {
2890Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_CREATE),
2900Sstevel@tonic-gate crle.c_name, crle.c_confil);
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate return (1);
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate /*
2960Sstevel@tonic-gate * Apply any additional defaults.
2970Sstevel@tonic-gate */
2980Sstevel@tonic-gate if (crle.c_dlflags == 0)
2990Sstevel@tonic-gate crle.c_dlflags = RTLD_REL_RELATIVE;
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate crle.c_audit = (char *)MSG_ORIG(MSG_ENV_LD_AUDIT);
3020Sstevel@tonic-gate
3030Sstevel@tonic-gate (void) elf_version(EV_CURRENT);
3040Sstevel@tonic-gate
3050Sstevel@tonic-gate /*
3060Sstevel@tonic-gate * If we're updating an existing file or not creating a configuration
3070Sstevel@tonic-gate * file at all, investigate the original.
3080Sstevel@tonic-gate */
3090Sstevel@tonic-gate if ((crle.c_flags & CRLE_UPDATE) ||
3100Sstevel@tonic-gate ((crle.c_flags & CRLE_CREAT) == 0)) {
3112056Sab196087 switch (inspectconfig(&crle, c_class)) {
3121976Sab196087 case INSCFG_RET_OK:
3131976Sab196087 if ((crle.c_flags & CRLE_UPDATE) == 0)
3141976Sab196087 return (0);
3151976Sab196087 break;
3161976Sab196087 case INSCFG_RET_FAIL:
3170Sstevel@tonic-gate return (1);
3181976Sab196087 case INSCFG_RET_NEED64:
3191976Sab196087 c_class = ELFCLASS64;
3201976Sab196087 break;
3211976Sab196087 }
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate
3241976Sab196087 /*
3251976Sab196087 * Ensure that the right version (32 or 64-bit) of this program
3261976Sab196087 * is running. The 32 and 64-bit compilers may align fields within
3271976Sab196087 * structures differently. Using the right version of crle for
3281976Sab196087 * the config file ensures that all linker components will see
3291976Sab196087 * the same layout, without the need for special code.
3301976Sab196087 */
3311976Sab196087 #ifdef _ELF64
3321976Sab196087 if (c_class == ELFCLASS32) {
3331976Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ARG_CLASS),
334*9131SRod.Evans@Sun.COM crle.c_name, crle.c_confil);
3351976Sab196087 return (1);
3361976Sab196087 }
3371976Sab196087 #else
3381976Sab196087 if (c_class == ELFCLASS64) {
3392647Srie (void) conv_check_native(argv, envp);
3401976Sab196087
3411976Sab196087 /*
3421976Sab196087 * conv_check_native() should not return, as we expect
3431976Sab196087 * the 64-bit version to have executed on top of us.
3441976Sab196087 * If it does, it means there is no 64-bit support
3451976Sab196087 * available on this system.
3461976Sab196087 */
3471976Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ISA32_NO64SUP),
3482647Srie crle.c_name);
3491976Sab196087 return (1);
3501976Sab196087 }
3511976Sab196087 #endif
3521976Sab196087
3530Sstevel@tonic-gate if (crle.c_flags & CRLE_VERBOSE)
3540Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_CONFILE), crle.c_confil);
3550Sstevel@tonic-gate
3560Sstevel@tonic-gate /*
3570Sstevel@tonic-gate * Make sure the configuration file is accessible. Stat the file to
3580Sstevel@tonic-gate * determine its dev number - this is used to determine whether the
3590Sstevel@tonic-gate * temporary configuration file we're about to build can be renamed or
3600Sstevel@tonic-gate * must be copied to its final destination.
3610Sstevel@tonic-gate */
3620Sstevel@tonic-gate (void) umask(022);
3630Sstevel@tonic-gate if (access(crle.c_confil, (R_OK | W_OK)) == 0) {
3640Sstevel@tonic-gate crle.c_flags |= CRLE_EXISTS;
3650Sstevel@tonic-gate
3660Sstevel@tonic-gate if (stat(crle.c_confil, &ostatus) != 0) {
3670Sstevel@tonic-gate int err = errno;
3680Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
3690Sstevel@tonic-gate crle.c_name, crle.c_confil, strerror(err));
3700Sstevel@tonic-gate return (1);
3710Sstevel@tonic-gate }
3720Sstevel@tonic-gate } else if (errno != ENOENT) {
3730Sstevel@tonic-gate int err = errno;
3740Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_ACCESS), crle.c_name,
3750Sstevel@tonic-gate crle.c_confil, strerror(err));
3760Sstevel@tonic-gate return (1);
3770Sstevel@tonic-gate } else {
3780Sstevel@tonic-gate int fd;
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate /*
3810Sstevel@tonic-gate * Try opening the file now, if it works delete it, there may
3820Sstevel@tonic-gate * be a lot of processing ahead of us, so we'll come back and
3830Sstevel@tonic-gate * create the real thing later.
3840Sstevel@tonic-gate */
3850Sstevel@tonic-gate if ((fd = open(crle.c_confil, (O_RDWR | O_CREAT | O_TRUNC),
3860Sstevel@tonic-gate 0666)) == -1) {
3870Sstevel@tonic-gate int err = errno;
3880Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
3890Sstevel@tonic-gate crle.c_name, crle.c_confil, strerror(err));
3900Sstevel@tonic-gate return (1);
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate if (fstat(fd, &ostatus) != 0) {
3930Sstevel@tonic-gate int err = errno;
3940Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
3950Sstevel@tonic-gate crle.c_name, crle.c_confil, strerror(err));
3960Sstevel@tonic-gate return (1);
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate (void) close(fd);
3990Sstevel@tonic-gate (void) unlink(crle.c_confil);
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate /*
4030Sstevel@tonic-gate * If an object directory is required to hold dldump(3dl) output assign
4040Sstevel@tonic-gate * a default if necessary and insure we're able to write there.
4050Sstevel@tonic-gate */
4060Sstevel@tonic-gate if (crle.c_flags & CRLE_ALTER) {
407*9131SRod.Evans@Sun.COM if (objdir->o_objdir == NULL) {
4080Sstevel@tonic-gate char *str;
4090Sstevel@tonic-gate
4100Sstevel@tonic-gate /*
4110Sstevel@tonic-gate * Use the configuration files directory.
4120Sstevel@tonic-gate */
4130Sstevel@tonic-gate if ((str = strrchr(crle.c_confil, '/')) == NULL)
414*9131SRod.Evans@Sun.COM objdir->o_objdir =
4150Sstevel@tonic-gate (char *)MSG_ORIG(MSG_DIR_DOT);
4160Sstevel@tonic-gate else {
4170Sstevel@tonic-gate int len = str - crle.c_confil;
4180Sstevel@tonic-gate
419*9131SRod.Evans@Sun.COM if ((objdir->o_objdir =
420*9131SRod.Evans@Sun.COM malloc(len + 1)) == NULL) {
4210Sstevel@tonic-gate int err = errno;
4220Sstevel@tonic-gate (void) fprintf(stderr,
4230Sstevel@tonic-gate MSG_INTL(MSG_SYS_MALLOC),
4240Sstevel@tonic-gate crle.c_name, strerror(err));
4250Sstevel@tonic-gate return (1);
4260Sstevel@tonic-gate }
427*9131SRod.Evans@Sun.COM (void) strncpy(objdir->o_objdir,
4280Sstevel@tonic-gate crle.c_confil, len);
429*9131SRod.Evans@Sun.COM objdir->o_objdir[len] = '\0';
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate /*
4340Sstevel@tonic-gate * If we're going to dldump(3dl) images ourself make sure we
4350Sstevel@tonic-gate * can access any directories.
4360Sstevel@tonic-gate */
4370Sstevel@tonic-gate if (crle.c_flags & CRLE_DUMP) {
438*9131SRod.Evans@Sun.COM Objdir *objdir;
439*9131SRod.Evans@Sun.COM Aliste idx;
440*9131SRod.Evans@Sun.COM int err = 0;
4410Sstevel@tonic-gate
442*9131SRod.Evans@Sun.COM for (ALIST_TRAVERSE(objdirs, idx, objdir)) {
4430Sstevel@tonic-gate if (crle.c_flags & CRLE_VERBOSE)
4440Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_OBJDIR),
4450Sstevel@tonic-gate objdir->o_objdir);
4460Sstevel@tonic-gate
4470Sstevel@tonic-gate if ((objdir->o_flags & CRLE_DUMP) == 0)
4480Sstevel@tonic-gate continue;
4490Sstevel@tonic-gate
4500Sstevel@tonic-gate if (access(objdir->o_objdir,
4510Sstevel@tonic-gate (R_OK | W_OK)) != 0) {
4520Sstevel@tonic-gate err = errno;
4530Sstevel@tonic-gate (void) fprintf(stderr,
4540Sstevel@tonic-gate MSG_INTL(MSG_SYS_ACCESS),
4550Sstevel@tonic-gate crle.c_name, objdir->o_objdir,
4560Sstevel@tonic-gate strerror(err));
4570Sstevel@tonic-gate }
4580Sstevel@tonic-gate }
4590Sstevel@tonic-gate if (err)
4600Sstevel@tonic-gate return (1);
4610Sstevel@tonic-gate }
4620Sstevel@tonic-gate }
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate /*
4650Sstevel@tonic-gate * Establish any initial object directory.
4660Sstevel@tonic-gate */
467*9131SRod.Evans@Sun.COM crle.c_objdir = iobjdir->o_objdir;
4680Sstevel@tonic-gate
4690Sstevel@tonic-gate /*
4700Sstevel@tonic-gate * Create a temporary file name in which to build the configuration
4710Sstevel@tonic-gate * information.
4720Sstevel@tonic-gate */
4730Sstevel@tonic-gate if ((crle.c_tempname = tempnam(MSG_ORIG(MSG_TMP_DIR),
4740Sstevel@tonic-gate MSG_ORIG(MSG_TMP_PFX))) == NULL) {
4750Sstevel@tonic-gate int err = errno;
4760Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_TEMPNAME),
4770Sstevel@tonic-gate crle.c_name, strerror(err));
4780Sstevel@tonic-gate return (1);
4790Sstevel@tonic-gate }
4800Sstevel@tonic-gate if ((crle.c_tempfd = open(crle.c_tempname, (O_RDWR | O_CREAT),
4810Sstevel@tonic-gate 0666)) == -1) {
4820Sstevel@tonic-gate int err = errno;
4830Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
4840Sstevel@tonic-gate crle.c_name, crle.c_tempname, strerror(err));
4850Sstevel@tonic-gate return (1);
4860Sstevel@tonic-gate }
4870Sstevel@tonic-gate if (stat(crle.c_tempname, &nstatus) != 0) {
4880Sstevel@tonic-gate int err = errno;
4890Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
4900Sstevel@tonic-gate crle.c_name, crle.c_tempname, strerror(err));
4910Sstevel@tonic-gate return (1);
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate if (ostatus.st_dev != nstatus.st_dev)
4940Sstevel@tonic-gate crle.c_flags |= CRLE_DIFFDEV;
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate /*
4970Sstevel@tonic-gate * Second pass.
4980Sstevel@tonic-gate */
4990Sstevel@tonic-gate error = 0;
5000Sstevel@tonic-gate optind = 1;
5010Sstevel@tonic-gate while ((c = getopt(argc, argv, MSG_ORIG(MSG_ARG_OPTIONS))) != -1) {
5020Sstevel@tonic-gate const char *str;
5030Sstevel@tonic-gate int flag = 0;
5040Sstevel@tonic-gate
5050Sstevel@tonic-gate switch (c) {
5060Sstevel@tonic-gate
5070Sstevel@tonic-gate case '6':
5080Sstevel@tonic-gate break;
5090Sstevel@tonic-gate
5100Sstevel@tonic-gate case 'A': /* alternative is optional */
5110Sstevel@tonic-gate flag = RTC_OBJ_OPTINAL;
5120Sstevel@tonic-gate /* FALLTHROUGH */
5130Sstevel@tonic-gate case 'a': /* alternative required */
5140Sstevel@tonic-gate flag |= (RTC_OBJ_ALTER | 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 'c':
5200Sstevel@tonic-gate break;
5210Sstevel@tonic-gate
5220Sstevel@tonic-gate case 'e':
5230Sstevel@tonic-gate if ((flag = addenv(&crle, (const char *)optarg,
5240Sstevel@tonic-gate RTC_ENV_REPLACE)) == 0)
5250Sstevel@tonic-gate error = 1;
5260Sstevel@tonic-gate else if ((crle.c_flags & CRLE_VERBOSE) && (flag == 1))
5270Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_RPLENV),
5280Sstevel@tonic-gate (const char *)optarg);
5290Sstevel@tonic-gate break;
5300Sstevel@tonic-gate
5310Sstevel@tonic-gate case 'E':
5320Sstevel@tonic-gate if ((flag = addenv(&crle, (const char *)optarg,
5330Sstevel@tonic-gate RTC_ENV_PERMANT)) == 0)
5340Sstevel@tonic-gate error = 1;
5350Sstevel@tonic-gate else if ((crle.c_flags & CRLE_VERBOSE) && (flag == 1))
5360Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_PRMENV),
5370Sstevel@tonic-gate (const char *)optarg);
5380Sstevel@tonic-gate break;
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate case 'f':
5410Sstevel@tonic-gate break;
5420Sstevel@tonic-gate
5430Sstevel@tonic-gate case 'G': /* group object */
5440Sstevel@tonic-gate flag = (RTC_OBJ_DUMP | RTC_OBJ_ALTER);
5450Sstevel@tonic-gate /* FALLTHROUGH */
5460Sstevel@tonic-gate case 'g':
5470Sstevel@tonic-gate flag |= (RTC_OBJ_GROUP | RTC_OBJ_CMDLINE);
5480Sstevel@tonic-gate if (inspect(&crle, (const char *)optarg, flag) != 0)
5490Sstevel@tonic-gate error = 1;
5500Sstevel@tonic-gate break;
5510Sstevel@tonic-gate
5520Sstevel@tonic-gate case 'I': /* individual object */
5530Sstevel@tonic-gate flag = (RTC_OBJ_DUMP | RTC_OBJ_ALTER);
5540Sstevel@tonic-gate /* FALLTHROUGH */
5550Sstevel@tonic-gate case 'i':
5560Sstevel@tonic-gate flag |= RTC_OBJ_CMDLINE;
5570Sstevel@tonic-gate if (inspect(&crle, (const char *)optarg, flag) != 0)
5580Sstevel@tonic-gate error = 1;
5590Sstevel@tonic-gate break;
5600Sstevel@tonic-gate
5610Sstevel@tonic-gate case 'l': /* library search path */
5620Sstevel@tonic-gate if (crle.c_flags & CRLE_AOUT) {
5630Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_AOUT);
5640Sstevel@tonic-gate lib = &crle.c_adlibpath;
5650Sstevel@tonic-gate } else {
5660Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_ELF);
5670Sstevel@tonic-gate lib = &crle.c_edlibpath;
5680Sstevel@tonic-gate }
5690Sstevel@tonic-gate if (addlib(&crle, lib, (const char *)optarg) != 0)
5700Sstevel@tonic-gate error = 1;
5710Sstevel@tonic-gate else if (crle.c_flags & CRLE_VERBOSE)
5720Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_DLIBPTH),
5730Sstevel@tonic-gate str, (const char *)optarg);
5740Sstevel@tonic-gate break;
5750Sstevel@tonic-gate
5760Sstevel@tonic-gate case 'o':
5770Sstevel@tonic-gate crle.c_objdir = optarg;
5780Sstevel@tonic-gate break;
5790Sstevel@tonic-gate
5800Sstevel@tonic-gate case 's': /* trusted (secure) path */
5810Sstevel@tonic-gate if (crle.c_flags & CRLE_AOUT) {
5820Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_AOUT);
5830Sstevel@tonic-gate lib = &crle.c_aslibpath;
5840Sstevel@tonic-gate } else {
5850Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_ELF);
5860Sstevel@tonic-gate lib = &crle.c_eslibpath;
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate if (addlib(&crle, lib, (const char *)optarg) != 0)
5890Sstevel@tonic-gate error = 1;
5900Sstevel@tonic-gate else if (crle.c_flags & CRLE_VERBOSE)
5910Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_TLIBPTH),
5920Sstevel@tonic-gate str, (const char *)optarg);
5930Sstevel@tonic-gate break;
5940Sstevel@tonic-gate
5950Sstevel@tonic-gate case 't': /* search path type */
5960Sstevel@tonic-gate if (strcmp((const char *)optarg,
5970Sstevel@tonic-gate MSG_ORIG(MSG_STR_ELF)) == 0)
5980Sstevel@tonic-gate crle.c_flags &= ~CRLE_AOUT;
5990Sstevel@tonic-gate else
6000Sstevel@tonic-gate crle.c_flags |= CRLE_AOUT;
6010Sstevel@tonic-gate break;
6020Sstevel@tonic-gate
6030Sstevel@tonic-gate case 'u':
6040Sstevel@tonic-gate break;
6050Sstevel@tonic-gate
6060Sstevel@tonic-gate case 'v':
6070Sstevel@tonic-gate break;
6080Sstevel@tonic-gate }
6090Sstevel@tonic-gate }
6100Sstevel@tonic-gate
6110Sstevel@tonic-gate /*
6120Sstevel@tonic-gate * Now that we've generated as many file/directory processing errors
6130Sstevel@tonic-gate * as we can, return if any fatal error conditions occurred.
6140Sstevel@tonic-gate */
6150Sstevel@tonic-gate if (error) {
6160Sstevel@tonic-gate (void) unlink(crle.c_tempname);
6170Sstevel@tonic-gate if (crle.c_flags & CRLE_CREAT) {
6180Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_CREATE),
6190Sstevel@tonic-gate crle.c_name, crle.c_confil);
6200Sstevel@tonic-gate }
6210Sstevel@tonic-gate return (1);
6220Sstevel@tonic-gate }
6230Sstevel@tonic-gate
6240Sstevel@tonic-gate /*
6250Sstevel@tonic-gate * Create a temporary configuration file.
6260Sstevel@tonic-gate */
6270Sstevel@tonic-gate if (genconfig(&crle) != 0) {
6280Sstevel@tonic-gate (void) unlink(crle.c_tempname);
6290Sstevel@tonic-gate return (1);
6300Sstevel@tonic-gate }
6310Sstevel@tonic-gate
6320Sstevel@tonic-gate /*
6330Sstevel@tonic-gate * If dldump(3dl) images are required spawn a process to create them.
6340Sstevel@tonic-gate */
6350Sstevel@tonic-gate if (crle.c_flags & CRLE_DUMP) {
6360Sstevel@tonic-gate if (dump(&crle) != 0) {
6370Sstevel@tonic-gate (void) unlink(crle.c_tempname);
6380Sstevel@tonic-gate return (1);
6390Sstevel@tonic-gate }
6400Sstevel@tonic-gate }
6410Sstevel@tonic-gate
6420Sstevel@tonic-gate /*
6430Sstevel@tonic-gate * Copy the finished temporary configuration file to its final home.
6440Sstevel@tonic-gate */
6450Sstevel@tonic-gate if (updateconfig(&crle) != 0)
6460Sstevel@tonic-gate return (1);
6470Sstevel@tonic-gate
6480Sstevel@tonic-gate return (0);
6490Sstevel@tonic-gate }
650