17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5c13de8f6Sab196087 * Common Development and Distribution License (the "License"). 6c13de8f6Sab196087 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*57ef7aa9SRod Evans * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/types.h> 277c478bd9Sstevel@tonic-gate #include <sys/stat.h> 287c478bd9Sstevel@tonic-gate #include <fcntl.h> 297c478bd9Sstevel@tonic-gate #include <stdio.h> 307c478bd9Sstevel@tonic-gate #include <string.h> 317c478bd9Sstevel@tonic-gate #include <unistd.h> 327c478bd9Sstevel@tonic-gate #include <locale.h> 337c478bd9Sstevel@tonic-gate #include <dlfcn.h> 347c478bd9Sstevel@tonic-gate #include <errno.h> 357c478bd9Sstevel@tonic-gate #include "_crle.h" 36c13de8f6Sab196087 #include "conv.h" 377c478bd9Sstevel@tonic-gate #include "msg.h" 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate /* 417c478bd9Sstevel@tonic-gate * crle(1) entry point and argument processing. 427c478bd9Sstevel@tonic-gate * 437c478bd9Sstevel@tonic-gate * Two passes of the arguments are carried out; the first collects any single 447c478bd9Sstevel@tonic-gate * instance options and establishes defaults that might be appropriate for 457c478bd9Sstevel@tonic-gate * other arguments: 467c478bd9Sstevel@tonic-gate * 477c478bd9Sstevel@tonic-gate * -64 operate on, or apply, 64-bit objects (default is 32-bit). 487c478bd9Sstevel@tonic-gate * 497c478bd9Sstevel@tonic-gate * -c file defines the output configuration file. 507c478bd9Sstevel@tonic-gate * 517c478bd9Sstevel@tonic-gate * -f flag flags for dldump(3dl). 527c478bd9Sstevel@tonic-gate * 537c478bd9Sstevel@tonic-gate * -o dir defines the output directory for any dldump(3dl) objects 547c478bd9Sstevel@tonic-gate * that follow. For backward compatibility (RTC_VER_ONE only 557c478bd9Sstevel@tonic-gate * allowed one output directory) allow the first occurrence of this 567c478bd9Sstevel@tonic-gate * specification to catch any previous files. If not specified, 577c478bd9Sstevel@tonic-gate * the configuration files parent directory is used). 587c478bd9Sstevel@tonic-gate * 597c478bd9Sstevel@tonic-gate * -u update any existing configuration file. Any additional 607c478bd9Sstevel@tonic-gate * arguments supplied will be added to the new configuration 617c478bd9Sstevel@tonic-gate * information. 627c478bd9Sstevel@tonic-gate * 637c478bd9Sstevel@tonic-gate * -v verbose mode. 647c478bd9Sstevel@tonic-gate * 657c478bd9Sstevel@tonic-gate * The second pass collects all other options and constructs an internal 667c478bd9Sstevel@tonic-gate * string table which will be used to create the eventual configuration file. 677c478bd9Sstevel@tonic-gate * 687c478bd9Sstevel@tonic-gate * -a name add the individual name, with an alternative to the 697c478bd9Sstevel@tonic-gate * configuration cache. No alternative is created via dldump(3dl), 707c478bd9Sstevel@tonic-gate * it is the users responsibility to furnish the alternative. 717c478bd9Sstevel@tonic-gate * 727c478bd9Sstevel@tonic-gate * -A name add the individual name, with an optional alternative to the 737c478bd9Sstevel@tonic-gate * configuration cache. No alternative is created via dldump(3dl), 747c478bd9Sstevel@tonic-gate * it is the users responsibility to furnish the alternative. 757c478bd9Sstevel@tonic-gate * 767c478bd9Sstevel@tonic-gate * -e envar replaceable environment variable 777c478bd9Sstevel@tonic-gate * 787c478bd9Sstevel@tonic-gate * -E envar permanent environment variable 797c478bd9Sstevel@tonic-gate * 807c478bd9Sstevel@tonic-gate * -i name add the individual name to the configuration cache. If name 817c478bd9Sstevel@tonic-gate * is a directory each shared object within the directory is added 827c478bd9Sstevel@tonic-gate * to the cache. 837c478bd9Sstevel@tonic-gate * 847c478bd9Sstevel@tonic-gate * -I name same as -i, but in addition any ELF objects are dldump(3dl)'ed. 857c478bd9Sstevel@tonic-gate * 867c478bd9Sstevel@tonic-gate * -g name add the group name to the configuration cache. Each object is 877c478bd9Sstevel@tonic-gate * expanded to determine its dependencies and these are added to 887c478bd9Sstevel@tonic-gate * the cache. If name is a directory each shared object within the 897c478bd9Sstevel@tonic-gate * directory and its dependencies are added to the cache. 907c478bd9Sstevel@tonic-gate * 917c478bd9Sstevel@tonic-gate * -G app same as -g, but in addition any ELF objects are dldump(3dl)'ed. 927c478bd9Sstevel@tonic-gate * 937c478bd9Sstevel@tonic-gate * -l dir library search directory 947c478bd9Sstevel@tonic-gate * 957c478bd9Sstevel@tonic-gate * -s dir trusted (secure) directory 967c478bd9Sstevel@tonic-gate * 977c478bd9Sstevel@tonic-gate * -t type search directory type (ELF or AOUT). 987c478bd9Sstevel@tonic-gate */ 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /* 1017c478bd9Sstevel@tonic-gate * Establish a structure for maintaining current object directory attributes. 1027c478bd9Sstevel@tonic-gate * We wish to validate the access of any object directory that will be written 1037c478bd9Sstevel@tonic-gate * to (dldump(3dl), and thus by maintaining a current object directory and its 1047c478bd9Sstevel@tonic-gate * intended use we can perform this validation later. 1057c478bd9Sstevel@tonic-gate */ 1067c478bd9Sstevel@tonic-gate typedef struct { 1077c478bd9Sstevel@tonic-gate char *o_objdir; 108*57ef7aa9SRod Evans uint_t o_flags; 1097c478bd9Sstevel@tonic-gate } Objdir; 1107c478bd9Sstevel@tonic-gate 111587032cfSab196087 /*ARGSUSED2*/ 112b3fbe5e6Sseizo int 113c13de8f6Sab196087 main(int argc, char **argv, char **envp) 1147c478bd9Sstevel@tonic-gate { 1157c478bd9Sstevel@tonic-gate Crle_desc crle = { 0 }; 1167c478bd9Sstevel@tonic-gate int c, error = 0; 1177c478bd9Sstevel@tonic-gate char **lib; 118*57ef7aa9SRod Evans Alist *objdirs = NULL; 119*57ef7aa9SRod Evans Objdir *objdir, *iobjdir; 1207c478bd9Sstevel@tonic-gate struct stat ostatus, nstatus; 121c13de8f6Sab196087 int c_class; 1227c478bd9Sstevel@tonic-gate 123*57ef7aa9SRod Evans if ((objdir = iobjdir = alist_append(&objdirs, NULL, sizeof (Objdir), 124*57ef7aa9SRod Evans AL_CNT_CRLE)) == NULL) 1257c478bd9Sstevel@tonic-gate return (1); 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate /* 1287c478bd9Sstevel@tonic-gate * Establish locale. 1297c478bd9Sstevel@tonic-gate */ 1307c478bd9Sstevel@tonic-gate (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY)); 1317c478bd9Sstevel@tonic-gate (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* 1347c478bd9Sstevel@tonic-gate * Initialization configuration information. 1357c478bd9Sstevel@tonic-gate */ 1367c478bd9Sstevel@tonic-gate crle.c_name = argv[0]; 137c13de8f6Sab196087 crle.c_flags |= CRLE_ADDID; 1387c478bd9Sstevel@tonic-gate crle.c_strbkts = 503; 1397c478bd9Sstevel@tonic-gate crle.c_inobkts = 251; 140c13de8f6Sab196087 c_class = M_CLASS; 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * First argument pass. 1447c478bd9Sstevel@tonic-gate */ 1457c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, MSG_ORIG(MSG_ARG_OPTIONS))) != -1) { 1467c478bd9Sstevel@tonic-gate switch (c) { 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate case '6': /* operate on 64-bit objects */ 1497c478bd9Sstevel@tonic-gate if (optarg[0] != '4') { 1507c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1517c478bd9Sstevel@tonic-gate MSG_INTL(MSG_ARG_ILLEGAL), crle.c_name, 1527c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_ARG_6), optarg); 1537c478bd9Sstevel@tonic-gate error = 1; 1547c478bd9Sstevel@tonic-gate } 155c13de8f6Sab196087 156c13de8f6Sab196087 c_class = ELFCLASS64; 1577c478bd9Sstevel@tonic-gate break; 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate case 'A': /* create optional */ 1607c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ /* alternative */ 1617c478bd9Sstevel@tonic-gate case 'a': /* create alternative */ 1627c478bd9Sstevel@tonic-gate crle.c_flags |= (CRLE_CREAT | CRLE_ALTER); 163*57ef7aa9SRod Evans objdir->o_flags |= (CRLE_CREAT | CRLE_ALTER); 1647c478bd9Sstevel@tonic-gate break; 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate case 'c': /* define the config file */ 1677c478bd9Sstevel@tonic-gate if (crle.c_confil) { 1687c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_MULT), 1697c478bd9Sstevel@tonic-gate crle.c_name, MSG_ORIG(MSG_ARG_C)); 1707c478bd9Sstevel@tonic-gate error = 1; 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate crle.c_confil = optarg; 1737c478bd9Sstevel@tonic-gate break; 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate case 'e': /* replaceable env variable */ 1767c478bd9Sstevel@tonic-gate crle.c_flags |= (CRLE_RPLENV | CRLE_CREAT); 1777c478bd9Sstevel@tonic-gate break; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate case 'E': /* permanent env variable */ 1807c478bd9Sstevel@tonic-gate crle.c_flags |= (CRLE_PRMENV | CRLE_CREAT); 1817c478bd9Sstevel@tonic-gate break; 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate case 'f': /* dldump(3dl) flags */ 1847c478bd9Sstevel@tonic-gate if (crle.c_dlflags) { 1857c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_MULT), 1867c478bd9Sstevel@tonic-gate crle.c_name, MSG_ORIG(MSG_ARG_F)); 1877c478bd9Sstevel@tonic-gate error = 1; 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate if ((crle.c_dlflags = dlflags(&crle, 1907c478bd9Sstevel@tonic-gate (const char *)optarg)) == 0) 1917c478bd9Sstevel@tonic-gate error = 1; 1927c478bd9Sstevel@tonic-gate break; 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate case 'G': /* group object */ 1957c478bd9Sstevel@tonic-gate crle.c_flags |= (CRLE_DUMP | CRLE_ALTER); 196*57ef7aa9SRod Evans objdir->o_flags |= (CRLE_DUMP | CRLE_ALTER); 1977c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 1987c478bd9Sstevel@tonic-gate case 'g': 1997c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT; 200*57ef7aa9SRod Evans objdir->o_flags |= CRLE_CREAT; 2017c478bd9Sstevel@tonic-gate break; 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate case 'I': /* individual object */ 2047c478bd9Sstevel@tonic-gate crle.c_flags |= (CRLE_DUMP | CRLE_ALTER); 205*57ef7aa9SRod Evans objdir->o_flags |= (CRLE_DUMP | CRLE_ALTER); 2067c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 2077c478bd9Sstevel@tonic-gate case 'i': 2087c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT; 209*57ef7aa9SRod Evans objdir->o_flags |= CRLE_CREAT; 2107c478bd9Sstevel@tonic-gate break; 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate case 'l': /* library search path */ 2137c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_AOUT) 2147c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_ADLIB; 2157c478bd9Sstevel@tonic-gate else 2167c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_EDLIB; 2177c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT; 2187c478bd9Sstevel@tonic-gate break; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate case 'o': /* define an object directory */ 221*57ef7aa9SRod Evans if (objdir->o_objdir) { 222*57ef7aa9SRod Evans if ((objdir = alist_append(&objdirs, NULL, 223*57ef7aa9SRod Evans sizeof (Objdir), AL_CNT_CRLE)) == NULL) 2247c478bd9Sstevel@tonic-gate return (1); 2257c478bd9Sstevel@tonic-gate } 226*57ef7aa9SRod Evans objdir->o_objdir = optarg; 2277c478bd9Sstevel@tonic-gate break; 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate case 's': /* trusted (secure) path */ 2307c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_AOUT) 2317c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_ASLIB; 2327c478bd9Sstevel@tonic-gate else 2337c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_ESLIB; 2347c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT; 2357c478bd9Sstevel@tonic-gate break; 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate case 't': /* search path type */ 2387c478bd9Sstevel@tonic-gate if (strcmp((const char *)optarg, 2397c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_STR_ELF)) == 0) 2407c478bd9Sstevel@tonic-gate crle.c_flags &= ~CRLE_AOUT; 2417c478bd9Sstevel@tonic-gate else if (strcmp((const char *)optarg, 2427c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_STR_AOUT)) == 0) 2437c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_AOUT; 2447c478bd9Sstevel@tonic-gate else { 2457c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_TYPE), 2467c478bd9Sstevel@tonic-gate crle.c_name, optarg); 2477c478bd9Sstevel@tonic-gate error = 1; 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate break; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate case 'u': /* update mode */ 2527c478bd9Sstevel@tonic-gate crle.c_flags |= (CRLE_CREAT | CRLE_UPDATE); 2537c478bd9Sstevel@tonic-gate break; 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate case 'v': /* verbose mode */ 2567c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_VERBOSE; 2577c478bd9Sstevel@tonic-gate break; 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate default: 2607c478bd9Sstevel@tonic-gate error = 2; 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate if (optind != argc) 2657c478bd9Sstevel@tonic-gate error = 2; 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /* 2687c478bd9Sstevel@tonic-gate * Determine the configuration file, which in the case of an existing 2697c478bd9Sstevel@tonic-gate * error condition is required in the final error message. 2707c478bd9Sstevel@tonic-gate */ 271*57ef7aa9SRod Evans if (crle.c_confil == NULL) { 2727c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_CONFDEF; 273c13de8f6Sab196087 if (c_class == ELFCLASS32) { 2747c478bd9Sstevel@tonic-gate crle.c_confil = (char *)MSG_ORIG(MSG_PTH_CONFIG); 275c13de8f6Sab196087 } else { 2767c478bd9Sstevel@tonic-gate crle.c_confil = (char *)MSG_ORIG(MSG_PTH_CONFIG_64); 2777c478bd9Sstevel@tonic-gate } 278c13de8f6Sab196087 } 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate /* 2817c478bd9Sstevel@tonic-gate * Now that we've generated as many file/directory processing errors 2827c478bd9Sstevel@tonic-gate * as we can, return if any fatal error conditions occurred. 2837c478bd9Sstevel@tonic-gate */ 2847c478bd9Sstevel@tonic-gate if (error) { 2857c478bd9Sstevel@tonic-gate if (error == 2) { 2867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_USAGE), 2877c478bd9Sstevel@tonic-gate crle.c_name); 2887c478bd9Sstevel@tonic-gate } else if (crle.c_flags & CRLE_CREAT) { 2897c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_CREATE), 2907c478bd9Sstevel@tonic-gate crle.c_name, crle.c_confil); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate return (1); 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate /* 2967c478bd9Sstevel@tonic-gate * Apply any additional defaults. 2977c478bd9Sstevel@tonic-gate */ 2987c478bd9Sstevel@tonic-gate if (crle.c_dlflags == 0) 2997c478bd9Sstevel@tonic-gate crle.c_dlflags = RTLD_REL_RELATIVE; 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate crle.c_audit = (char *)MSG_ORIG(MSG_ENV_LD_AUDIT); 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate (void) elf_version(EV_CURRENT); 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate /* 3067c478bd9Sstevel@tonic-gate * If we're updating an existing file or not creating a configuration 3077c478bd9Sstevel@tonic-gate * file at all, investigate the original. 3087c478bd9Sstevel@tonic-gate */ 3097c478bd9Sstevel@tonic-gate if ((crle.c_flags & CRLE_UPDATE) || 3107c478bd9Sstevel@tonic-gate ((crle.c_flags & CRLE_CREAT) == 0)) { 311587032cfSab196087 switch (inspectconfig(&crle, c_class)) { 312c13de8f6Sab196087 case INSCFG_RET_OK: 3137c478bd9Sstevel@tonic-gate if ((crle.c_flags & CRLE_UPDATE) == 0) 3147c478bd9Sstevel@tonic-gate return (0); 315c13de8f6Sab196087 break; 316c13de8f6Sab196087 case INSCFG_RET_FAIL: 317c13de8f6Sab196087 return (1); 318c13de8f6Sab196087 case INSCFG_RET_NEED64: 319c13de8f6Sab196087 c_class = ELFCLASS64; 320c13de8f6Sab196087 break; 3217c478bd9Sstevel@tonic-gate } 322c13de8f6Sab196087 } 323c13de8f6Sab196087 324c13de8f6Sab196087 /* 325c13de8f6Sab196087 * Ensure that the right version (32 or 64-bit) of this program 326c13de8f6Sab196087 * is running. The 32 and 64-bit compilers may align fields within 327c13de8f6Sab196087 * structures differently. Using the right version of crle for 328c13de8f6Sab196087 * the config file ensures that all linker components will see 329c13de8f6Sab196087 * the same layout, without the need for special code. 330c13de8f6Sab196087 */ 331c13de8f6Sab196087 #ifdef _ELF64 332c13de8f6Sab196087 if (c_class == ELFCLASS32) { 333c13de8f6Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ARG_CLASS), 334c13de8f6Sab196087 crle.c_name, crle.c_confil); 335c13de8f6Sab196087 return (1); 336c13de8f6Sab196087 } 337c13de8f6Sab196087 #else 338c13de8f6Sab196087 if (c_class == ELFCLASS64) { 3397010c12aSrie (void) conv_check_native(argv, envp); 340c13de8f6Sab196087 341c13de8f6Sab196087 /* 342c13de8f6Sab196087 * conv_check_native() should not return, as we expect 343c13de8f6Sab196087 * the 64-bit version to have executed on top of us. 344c13de8f6Sab196087 * If it does, it means there is no 64-bit support 345c13de8f6Sab196087 * available on this system. 346c13de8f6Sab196087 */ 347c13de8f6Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ISA32_NO64SUP), 348c13de8f6Sab196087 crle.c_name); 349c13de8f6Sab196087 return (1); 350c13de8f6Sab196087 } 351c13de8f6Sab196087 #endif 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_VERBOSE) 3547c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_CONFILE), crle.c_confil); 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate /* 3577c478bd9Sstevel@tonic-gate * Make sure the configuration file is accessible. Stat the file to 3587c478bd9Sstevel@tonic-gate * determine its dev number - this is used to determine whether the 3597c478bd9Sstevel@tonic-gate * temporary configuration file we're about to build can be renamed or 3607c478bd9Sstevel@tonic-gate * must be copied to its final destination. 3617c478bd9Sstevel@tonic-gate */ 3627c478bd9Sstevel@tonic-gate (void) umask(022); 3637c478bd9Sstevel@tonic-gate if (access(crle.c_confil, (R_OK | W_OK)) == 0) { 3647c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_EXISTS; 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate if (stat(crle.c_confil, &ostatus) != 0) { 3677c478bd9Sstevel@tonic-gate int err = errno; 3687c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 3697c478bd9Sstevel@tonic-gate crle.c_name, crle.c_confil, strerror(err)); 3707c478bd9Sstevel@tonic-gate return (1); 3717c478bd9Sstevel@tonic-gate } 3727c478bd9Sstevel@tonic-gate } else if (errno != ENOENT) { 3737c478bd9Sstevel@tonic-gate int err = errno; 3747c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_ACCESS), crle.c_name, 3757c478bd9Sstevel@tonic-gate crle.c_confil, strerror(err)); 3767c478bd9Sstevel@tonic-gate return (1); 3777c478bd9Sstevel@tonic-gate } else { 3787c478bd9Sstevel@tonic-gate int fd; 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate /* 3817c478bd9Sstevel@tonic-gate * Try opening the file now, if it works delete it, there may 3827c478bd9Sstevel@tonic-gate * be a lot of processing ahead of us, so we'll come back and 3837c478bd9Sstevel@tonic-gate * create the real thing later. 3847c478bd9Sstevel@tonic-gate */ 3857c478bd9Sstevel@tonic-gate if ((fd = open(crle.c_confil, (O_RDWR | O_CREAT | O_TRUNC), 3867c478bd9Sstevel@tonic-gate 0666)) == -1) { 3877c478bd9Sstevel@tonic-gate int err = errno; 3887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 3897c478bd9Sstevel@tonic-gate crle.c_name, crle.c_confil, strerror(err)); 3907c478bd9Sstevel@tonic-gate return (1); 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate if (fstat(fd, &ostatus) != 0) { 3937c478bd9Sstevel@tonic-gate int err = errno; 3947c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 3957c478bd9Sstevel@tonic-gate crle.c_name, crle.c_confil, strerror(err)); 3967c478bd9Sstevel@tonic-gate return (1); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate (void) close(fd); 3997c478bd9Sstevel@tonic-gate (void) unlink(crle.c_confil); 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate /* 4037c478bd9Sstevel@tonic-gate * If an object directory is required to hold dldump(3dl) output assign 4047c478bd9Sstevel@tonic-gate * a default if necessary and insure we're able to write there. 4057c478bd9Sstevel@tonic-gate */ 4067c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_ALTER) { 407*57ef7aa9SRod Evans if (objdir->o_objdir == NULL) { 4087c478bd9Sstevel@tonic-gate char *str; 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate /* 4117c478bd9Sstevel@tonic-gate * Use the configuration files directory. 4127c478bd9Sstevel@tonic-gate */ 4137c478bd9Sstevel@tonic-gate if ((str = strrchr(crle.c_confil, '/')) == NULL) 414*57ef7aa9SRod Evans objdir->o_objdir = 4157c478bd9Sstevel@tonic-gate (char *)MSG_ORIG(MSG_DIR_DOT); 4167c478bd9Sstevel@tonic-gate else { 4177c478bd9Sstevel@tonic-gate int len = str - crle.c_confil; 4187c478bd9Sstevel@tonic-gate 419*57ef7aa9SRod Evans if ((objdir->o_objdir = 420*57ef7aa9SRod Evans malloc(len + 1)) == NULL) { 4217c478bd9Sstevel@tonic-gate int err = errno; 4227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4237c478bd9Sstevel@tonic-gate MSG_INTL(MSG_SYS_MALLOC), 4247c478bd9Sstevel@tonic-gate crle.c_name, strerror(err)); 4257c478bd9Sstevel@tonic-gate return (1); 4267c478bd9Sstevel@tonic-gate } 427*57ef7aa9SRod Evans (void) strncpy(objdir->o_objdir, 4287c478bd9Sstevel@tonic-gate crle.c_confil, len); 429*57ef7aa9SRod Evans objdir->o_objdir[len] = '\0'; 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate } 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate /* 4347c478bd9Sstevel@tonic-gate * If we're going to dldump(3dl) images ourself make sure we 4357c478bd9Sstevel@tonic-gate * can access any directories. 4367c478bd9Sstevel@tonic-gate */ 4377c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_DUMP) { 4387c478bd9Sstevel@tonic-gate Objdir *objdir; 439*57ef7aa9SRod Evans Aliste idx; 4407c478bd9Sstevel@tonic-gate int err = 0; 4417c478bd9Sstevel@tonic-gate 442*57ef7aa9SRod Evans for (ALIST_TRAVERSE(objdirs, idx, objdir)) { 4437c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_VERBOSE) 4447c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_OBJDIR), 4457c478bd9Sstevel@tonic-gate objdir->o_objdir); 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate if ((objdir->o_flags & CRLE_DUMP) == 0) 4487c478bd9Sstevel@tonic-gate continue; 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate if (access(objdir->o_objdir, 4517c478bd9Sstevel@tonic-gate (R_OK | W_OK)) != 0) { 4527c478bd9Sstevel@tonic-gate err = errno; 4537c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4547c478bd9Sstevel@tonic-gate MSG_INTL(MSG_SYS_ACCESS), 4557c478bd9Sstevel@tonic-gate crle.c_name, objdir->o_objdir, 4567c478bd9Sstevel@tonic-gate strerror(err)); 4577c478bd9Sstevel@tonic-gate } 4587c478bd9Sstevel@tonic-gate } 4597c478bd9Sstevel@tonic-gate if (err) 4607c478bd9Sstevel@tonic-gate return (1); 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate /* 4657c478bd9Sstevel@tonic-gate * Establish any initial object directory. 4667c478bd9Sstevel@tonic-gate */ 467*57ef7aa9SRod Evans crle.c_objdir = iobjdir->o_objdir; 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate /* 4707c478bd9Sstevel@tonic-gate * Create a temporary file name in which to build the configuration 4717c478bd9Sstevel@tonic-gate * information. 4727c478bd9Sstevel@tonic-gate */ 4737c478bd9Sstevel@tonic-gate if ((crle.c_tempname = tempnam(MSG_ORIG(MSG_TMP_DIR), 4747c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_TMP_PFX))) == NULL) { 4757c478bd9Sstevel@tonic-gate int err = errno; 4767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_TEMPNAME), 4777c478bd9Sstevel@tonic-gate crle.c_name, strerror(err)); 4787c478bd9Sstevel@tonic-gate return (1); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate if ((crle.c_tempfd = open(crle.c_tempname, (O_RDWR | O_CREAT), 4817c478bd9Sstevel@tonic-gate 0666)) == -1) { 4827c478bd9Sstevel@tonic-gate int err = errno; 4837c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 4847c478bd9Sstevel@tonic-gate crle.c_name, crle.c_tempname, strerror(err)); 4857c478bd9Sstevel@tonic-gate return (1); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate if (stat(crle.c_tempname, &nstatus) != 0) { 4887c478bd9Sstevel@tonic-gate int err = errno; 4897c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 4907c478bd9Sstevel@tonic-gate crle.c_name, crle.c_tempname, strerror(err)); 4917c478bd9Sstevel@tonic-gate return (1); 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate if (ostatus.st_dev != nstatus.st_dev) 4947c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_DIFFDEV; 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate /* 4977c478bd9Sstevel@tonic-gate * Second pass. 4987c478bd9Sstevel@tonic-gate */ 4997c478bd9Sstevel@tonic-gate error = 0; 5007c478bd9Sstevel@tonic-gate optind = 1; 5017c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, MSG_ORIG(MSG_ARG_OPTIONS))) != -1) { 5027c478bd9Sstevel@tonic-gate const char *str; 5037c478bd9Sstevel@tonic-gate int flag = 0; 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate switch (c) { 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate case '6': 5087c478bd9Sstevel@tonic-gate break; 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate case 'A': /* alternative is optional */ 5117c478bd9Sstevel@tonic-gate flag = RTC_OBJ_OPTINAL; 5127c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 5137c478bd9Sstevel@tonic-gate case 'a': /* alternative required */ 5147c478bd9Sstevel@tonic-gate flag |= (RTC_OBJ_ALTER | RTC_OBJ_CMDLINE); 5157c478bd9Sstevel@tonic-gate if (inspect(&crle, (const char *)optarg, flag) != 0) 5167c478bd9Sstevel@tonic-gate error = 1; 5177c478bd9Sstevel@tonic-gate break; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate case 'c': 5207c478bd9Sstevel@tonic-gate break; 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate case 'e': 5237c478bd9Sstevel@tonic-gate if ((flag = addenv(&crle, (const char *)optarg, 5247c478bd9Sstevel@tonic-gate RTC_ENV_REPLACE)) == 0) 5257c478bd9Sstevel@tonic-gate error = 1; 5267c478bd9Sstevel@tonic-gate else if ((crle.c_flags & CRLE_VERBOSE) && (flag == 1)) 5277c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_RPLENV), 5287c478bd9Sstevel@tonic-gate (const char *)optarg); 5297c478bd9Sstevel@tonic-gate break; 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate case 'E': 5327c478bd9Sstevel@tonic-gate if ((flag = addenv(&crle, (const char *)optarg, 5337c478bd9Sstevel@tonic-gate RTC_ENV_PERMANT)) == 0) 5347c478bd9Sstevel@tonic-gate error = 1; 5357c478bd9Sstevel@tonic-gate else if ((crle.c_flags & CRLE_VERBOSE) && (flag == 1)) 5367c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_PRMENV), 5377c478bd9Sstevel@tonic-gate (const char *)optarg); 5387c478bd9Sstevel@tonic-gate break; 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate case 'f': 5417c478bd9Sstevel@tonic-gate break; 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate case 'G': /* group object */ 5447c478bd9Sstevel@tonic-gate flag = (RTC_OBJ_DUMP | RTC_OBJ_ALTER); 5457c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 5467c478bd9Sstevel@tonic-gate case 'g': 5477c478bd9Sstevel@tonic-gate flag |= (RTC_OBJ_GROUP | RTC_OBJ_CMDLINE); 5487c478bd9Sstevel@tonic-gate if (inspect(&crle, (const char *)optarg, flag) != 0) 5497c478bd9Sstevel@tonic-gate error = 1; 5507c478bd9Sstevel@tonic-gate break; 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate case 'I': /* individual object */ 5537c478bd9Sstevel@tonic-gate flag = (RTC_OBJ_DUMP | RTC_OBJ_ALTER); 5547c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 5557c478bd9Sstevel@tonic-gate case 'i': 5567c478bd9Sstevel@tonic-gate flag |= RTC_OBJ_CMDLINE; 5577c478bd9Sstevel@tonic-gate if (inspect(&crle, (const char *)optarg, flag) != 0) 5587c478bd9Sstevel@tonic-gate error = 1; 5597c478bd9Sstevel@tonic-gate break; 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate case 'l': /* library search path */ 5627c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_AOUT) { 5637c478bd9Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_AOUT); 5647c478bd9Sstevel@tonic-gate lib = &crle.c_adlibpath; 5657c478bd9Sstevel@tonic-gate } else { 5667c478bd9Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_ELF); 5677c478bd9Sstevel@tonic-gate lib = &crle.c_edlibpath; 5687c478bd9Sstevel@tonic-gate } 5697c478bd9Sstevel@tonic-gate if (addlib(&crle, lib, (const char *)optarg) != 0) 5707c478bd9Sstevel@tonic-gate error = 1; 5717c478bd9Sstevel@tonic-gate else if (crle.c_flags & CRLE_VERBOSE) 5727c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_DLIBPTH), 5737c478bd9Sstevel@tonic-gate str, (const char *)optarg); 5747c478bd9Sstevel@tonic-gate break; 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate case 'o': 5777c478bd9Sstevel@tonic-gate crle.c_objdir = optarg; 5787c478bd9Sstevel@tonic-gate break; 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate case 's': /* trusted (secure) path */ 5817c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_AOUT) { 5827c478bd9Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_AOUT); 5837c478bd9Sstevel@tonic-gate lib = &crle.c_aslibpath; 5847c478bd9Sstevel@tonic-gate } else { 5857c478bd9Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_ELF); 5867c478bd9Sstevel@tonic-gate lib = &crle.c_eslibpath; 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate if (addlib(&crle, lib, (const char *)optarg) != 0) 5897c478bd9Sstevel@tonic-gate error = 1; 5907c478bd9Sstevel@tonic-gate else if (crle.c_flags & CRLE_VERBOSE) 5917c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_TLIBPTH), 5927c478bd9Sstevel@tonic-gate str, (const char *)optarg); 5937c478bd9Sstevel@tonic-gate break; 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate case 't': /* search path type */ 5967c478bd9Sstevel@tonic-gate if (strcmp((const char *)optarg, 5977c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_STR_ELF)) == 0) 5987c478bd9Sstevel@tonic-gate crle.c_flags &= ~CRLE_AOUT; 5997c478bd9Sstevel@tonic-gate else 6007c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_AOUT; 6017c478bd9Sstevel@tonic-gate break; 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate case 'u': 6047c478bd9Sstevel@tonic-gate break; 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate case 'v': 6077c478bd9Sstevel@tonic-gate break; 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate /* 6127c478bd9Sstevel@tonic-gate * Now that we've generated as many file/directory processing errors 6137c478bd9Sstevel@tonic-gate * as we can, return if any fatal error conditions occurred. 6147c478bd9Sstevel@tonic-gate */ 6157c478bd9Sstevel@tonic-gate if (error) { 6167c478bd9Sstevel@tonic-gate (void) unlink(crle.c_tempname); 6177c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_CREAT) { 6187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_CREATE), 6197c478bd9Sstevel@tonic-gate crle.c_name, crle.c_confil); 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate return (1); 6227c478bd9Sstevel@tonic-gate } 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate /* 6257c478bd9Sstevel@tonic-gate * Create a temporary configuration file. 6267c478bd9Sstevel@tonic-gate */ 6277c478bd9Sstevel@tonic-gate if (genconfig(&crle) != 0) { 6287c478bd9Sstevel@tonic-gate (void) unlink(crle.c_tempname); 6297c478bd9Sstevel@tonic-gate return (1); 6307c478bd9Sstevel@tonic-gate } 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate /* 6337c478bd9Sstevel@tonic-gate * If dldump(3dl) images are required spawn a process to create them. 6347c478bd9Sstevel@tonic-gate */ 6357c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_DUMP) { 6367c478bd9Sstevel@tonic-gate if (dump(&crle) != 0) { 6377c478bd9Sstevel@tonic-gate (void) unlink(crle.c_tempname); 6387c478bd9Sstevel@tonic-gate return (1); 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate /* 6437c478bd9Sstevel@tonic-gate * Copy the finished temporary configuration file to its final home. 6447c478bd9Sstevel@tonic-gate */ 6457c478bd9Sstevel@tonic-gate if (updateconfig(&crle) != 0) 6467c478bd9Sstevel@tonic-gate return (1); 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate return (0); 6497c478bd9Sstevel@tonic-gate } 650