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 /*
2257ef7aa9SRod 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
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate * Establish a structure for maintaining current object directory attributes.
1007c478bd9Sstevel@tonic-gate * We wish to validate the access of any object directory that will be written
1017c478bd9Sstevel@tonic-gate * to (dldump(3dl), and thus by maintaining a current object directory and its
1027c478bd9Sstevel@tonic-gate * intended use we can perform this validation later.
1037c478bd9Sstevel@tonic-gate */
1047c478bd9Sstevel@tonic-gate typedef struct {
1057c478bd9Sstevel@tonic-gate char *o_objdir;
10657ef7aa9SRod Evans uint_t o_flags;
1077c478bd9Sstevel@tonic-gate } Objdir;
1087c478bd9Sstevel@tonic-gate
109587032cfSab196087 /*ARGSUSED2*/
110b3fbe5e6Sseizo int
main(int argc,char ** argv,char ** envp)111c13de8f6Sab196087 main(int argc, char **argv, char **envp)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate Crle_desc crle = { 0 };
1147c478bd9Sstevel@tonic-gate int c, error = 0;
1157c478bd9Sstevel@tonic-gate char **lib;
11657ef7aa9SRod Evans Alist *objdirs = NULL;
11757ef7aa9SRod Evans Objdir *objdir, *iobjdir;
1187c478bd9Sstevel@tonic-gate struct stat ostatus, nstatus;
119c13de8f6Sab196087 int c_class;
1207c478bd9Sstevel@tonic-gate
12157ef7aa9SRod Evans if ((objdir = iobjdir = alist_append(&objdirs, NULL, sizeof (Objdir),
12257ef7aa9SRod Evans AL_CNT_CRLE)) == NULL)
1237c478bd9Sstevel@tonic-gate return (1);
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate /*
1267c478bd9Sstevel@tonic-gate * Establish locale.
1277c478bd9Sstevel@tonic-gate */
1287c478bd9Sstevel@tonic-gate (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY));
1297c478bd9Sstevel@tonic-gate (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS));
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate * Initialization configuration information.
1337c478bd9Sstevel@tonic-gate */
1347c478bd9Sstevel@tonic-gate crle.c_name = argv[0];
135c13de8f6Sab196087 crle.c_flags |= CRLE_ADDID;
1367c478bd9Sstevel@tonic-gate crle.c_strbkts = 503;
1377c478bd9Sstevel@tonic-gate crle.c_inobkts = 251;
138c13de8f6Sab196087 c_class = M_CLASS;
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate /*
1417c478bd9Sstevel@tonic-gate * First argument pass.
1427c478bd9Sstevel@tonic-gate */
1437c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, MSG_ORIG(MSG_ARG_OPTIONS))) != -1) {
1447c478bd9Sstevel@tonic-gate switch (c) {
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate case '6': /* operate on 64-bit objects */
1477c478bd9Sstevel@tonic-gate if (optarg[0] != '4') {
1487c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
1497c478bd9Sstevel@tonic-gate MSG_INTL(MSG_ARG_ILLEGAL), crle.c_name,
1507c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_ARG_6), optarg);
1517c478bd9Sstevel@tonic-gate error = 1;
1527c478bd9Sstevel@tonic-gate }
153c13de8f6Sab196087
154c13de8f6Sab196087 c_class = ELFCLASS64;
1557c478bd9Sstevel@tonic-gate break;
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate case 'A': /* create optional */
1587c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ /* alternative */
1597c478bd9Sstevel@tonic-gate case 'a': /* create alternative */
1607c478bd9Sstevel@tonic-gate crle.c_flags |= (CRLE_CREAT | CRLE_ALTER);
16157ef7aa9SRod Evans objdir->o_flags |= (CRLE_CREAT | CRLE_ALTER);
1627c478bd9Sstevel@tonic-gate break;
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate case 'c': /* define the config file */
1657c478bd9Sstevel@tonic-gate if (crle.c_confil) {
1667c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_MULT),
1677c478bd9Sstevel@tonic-gate crle.c_name, MSG_ORIG(MSG_ARG_C));
1687c478bd9Sstevel@tonic-gate error = 1;
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate crle.c_confil = optarg;
1717c478bd9Sstevel@tonic-gate break;
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate case 'e': /* replaceable env variable */
1747c478bd9Sstevel@tonic-gate crle.c_flags |= (CRLE_RPLENV | CRLE_CREAT);
1757c478bd9Sstevel@tonic-gate break;
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate case 'E': /* permanent env variable */
1787c478bd9Sstevel@tonic-gate crle.c_flags |= (CRLE_PRMENV | CRLE_CREAT);
1797c478bd9Sstevel@tonic-gate break;
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate case 'f': /* dldump(3dl) flags */
1827c478bd9Sstevel@tonic-gate if (crle.c_dlflags) {
1837c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_MULT),
1847c478bd9Sstevel@tonic-gate crle.c_name, MSG_ORIG(MSG_ARG_F));
1857c478bd9Sstevel@tonic-gate error = 1;
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate if ((crle.c_dlflags = dlflags(&crle,
1887c478bd9Sstevel@tonic-gate (const char *)optarg)) == 0)
1897c478bd9Sstevel@tonic-gate error = 1;
1907c478bd9Sstevel@tonic-gate break;
1917c478bd9Sstevel@tonic-gate
1927c478bd9Sstevel@tonic-gate case 'G': /* group object */
1937c478bd9Sstevel@tonic-gate crle.c_flags |= (CRLE_DUMP | CRLE_ALTER);
19457ef7aa9SRod Evans objdir->o_flags |= (CRLE_DUMP | CRLE_ALTER);
1957c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
1967c478bd9Sstevel@tonic-gate case 'g':
1977c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT;
19857ef7aa9SRod Evans objdir->o_flags |= CRLE_CREAT;
1997c478bd9Sstevel@tonic-gate break;
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate case 'I': /* individual object */
2027c478bd9Sstevel@tonic-gate crle.c_flags |= (CRLE_DUMP | CRLE_ALTER);
20357ef7aa9SRod Evans objdir->o_flags |= (CRLE_DUMP | CRLE_ALTER);
2047c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
2057c478bd9Sstevel@tonic-gate case 'i':
2067c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_CREAT;
20757ef7aa9SRod Evans objdir->o_flags |= CRLE_CREAT;
2087c478bd9Sstevel@tonic-gate break;
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate case 'l': /* library search path */
211*fec04708SRichard Lowe crle.c_flags |= (CRLE_EDLIB | CRLE_CREAT);
2127c478bd9Sstevel@tonic-gate break;
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate case 'o': /* define an object directory */
21557ef7aa9SRod Evans if (objdir->o_objdir) {
21657ef7aa9SRod Evans if ((objdir = alist_append(&objdirs, NULL,
21757ef7aa9SRod Evans sizeof (Objdir), AL_CNT_CRLE)) == NULL)
2187c478bd9Sstevel@tonic-gate return (1);
2197c478bd9Sstevel@tonic-gate }
22057ef7aa9SRod Evans objdir->o_objdir = optarg;
2217c478bd9Sstevel@tonic-gate break;
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate case 's': /* trusted (secure) path */
224*fec04708SRichard Lowe crle.c_flags |= (CRLE_ESLIB | CRLE_CREAT);
2257c478bd9Sstevel@tonic-gate break;
2267c478bd9Sstevel@tonic-gate
227*fec04708SRichard Lowe /*
228*fec04708SRichard Lowe * Search path type, undocumented but left for compatibility.
229*fec04708SRichard Lowe * Previously used to select between AOUT and ELF, now
230*fec04708SRichard Lowe * anything other than ELF is an error.
231*fec04708SRichard Lowe */
232*fec04708SRichard Lowe case 't':
2337c478bd9Sstevel@tonic-gate if (strcmp((const char *)optarg,
234*fec04708SRichard Lowe MSG_ORIG(MSG_STR_ELF)) != 0) {
2357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_TYPE),
2367c478bd9Sstevel@tonic-gate crle.c_name, optarg);
2377c478bd9Sstevel@tonic-gate error = 1;
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate break;
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate case 'u': /* update mode */
2427c478bd9Sstevel@tonic-gate crle.c_flags |= (CRLE_CREAT | CRLE_UPDATE);
2437c478bd9Sstevel@tonic-gate break;
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate case 'v': /* verbose mode */
2467c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_VERBOSE;
2477c478bd9Sstevel@tonic-gate break;
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate default:
2507c478bd9Sstevel@tonic-gate error = 2;
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate
2547c478bd9Sstevel@tonic-gate if (optind != argc)
2557c478bd9Sstevel@tonic-gate error = 2;
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate /*
2587c478bd9Sstevel@tonic-gate * Determine the configuration file, which in the case of an existing
2597c478bd9Sstevel@tonic-gate * error condition is required in the final error message.
2607c478bd9Sstevel@tonic-gate */
26157ef7aa9SRod Evans if (crle.c_confil == NULL) {
2627c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_CONFDEF;
263c13de8f6Sab196087 if (c_class == ELFCLASS32) {
2647c478bd9Sstevel@tonic-gate crle.c_confil = (char *)MSG_ORIG(MSG_PTH_CONFIG);
265c13de8f6Sab196087 } else {
2667c478bd9Sstevel@tonic-gate crle.c_confil = (char *)MSG_ORIG(MSG_PTH_CONFIG_64);
2677c478bd9Sstevel@tonic-gate }
268c13de8f6Sab196087 }
2697c478bd9Sstevel@tonic-gate
2707c478bd9Sstevel@tonic-gate /*
2717c478bd9Sstevel@tonic-gate * Now that we've generated as many file/directory processing errors
2727c478bd9Sstevel@tonic-gate * as we can, return if any fatal error conditions occurred.
2737c478bd9Sstevel@tonic-gate */
2747c478bd9Sstevel@tonic-gate if (error) {
2757c478bd9Sstevel@tonic-gate if (error == 2) {
2767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_USAGE),
2777c478bd9Sstevel@tonic-gate crle.c_name);
2787c478bd9Sstevel@tonic-gate } else if (crle.c_flags & CRLE_CREAT) {
2797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_CREATE),
2807c478bd9Sstevel@tonic-gate crle.c_name, crle.c_confil);
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate return (1);
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate
2857c478bd9Sstevel@tonic-gate /*
2867c478bd9Sstevel@tonic-gate * Apply any additional defaults.
2877c478bd9Sstevel@tonic-gate */
2887c478bd9Sstevel@tonic-gate if (crle.c_dlflags == 0)
2897c478bd9Sstevel@tonic-gate crle.c_dlflags = RTLD_REL_RELATIVE;
2907c478bd9Sstevel@tonic-gate
2917c478bd9Sstevel@tonic-gate crle.c_audit = (char *)MSG_ORIG(MSG_ENV_LD_AUDIT);
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate (void) elf_version(EV_CURRENT);
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate /*
2967c478bd9Sstevel@tonic-gate * If we're updating an existing file or not creating a configuration
2977c478bd9Sstevel@tonic-gate * file at all, investigate the original.
2987c478bd9Sstevel@tonic-gate */
2997c478bd9Sstevel@tonic-gate if ((crle.c_flags & CRLE_UPDATE) ||
3007c478bd9Sstevel@tonic-gate ((crle.c_flags & CRLE_CREAT) == 0)) {
301587032cfSab196087 switch (inspectconfig(&crle, c_class)) {
302c13de8f6Sab196087 case INSCFG_RET_OK:
3037c478bd9Sstevel@tonic-gate if ((crle.c_flags & CRLE_UPDATE) == 0)
3047c478bd9Sstevel@tonic-gate return (0);
305c13de8f6Sab196087 break;
306c13de8f6Sab196087 case INSCFG_RET_FAIL:
307c13de8f6Sab196087 return (1);
308c13de8f6Sab196087 case INSCFG_RET_NEED64:
309c13de8f6Sab196087 c_class = ELFCLASS64;
310c13de8f6Sab196087 break;
3117c478bd9Sstevel@tonic-gate }
312c13de8f6Sab196087 }
313c13de8f6Sab196087
314c13de8f6Sab196087 /*
315c13de8f6Sab196087 * Ensure that the right version (32 or 64-bit) of this program
316c13de8f6Sab196087 * is running. The 32 and 64-bit compilers may align fields within
317c13de8f6Sab196087 * structures differently. Using the right version of crle for
318c13de8f6Sab196087 * the config file ensures that all linker components will see
319c13de8f6Sab196087 * the same layout, without the need for special code.
320c13de8f6Sab196087 */
321c13de8f6Sab196087 #ifdef _ELF64
322c13de8f6Sab196087 if (c_class == ELFCLASS32) {
323c13de8f6Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ARG_CLASS),
324c13de8f6Sab196087 crle.c_name, crle.c_confil);
325c13de8f6Sab196087 return (1);
326c13de8f6Sab196087 }
327c13de8f6Sab196087 #else
328c13de8f6Sab196087 if (c_class == ELFCLASS64) {
3297010c12aSrie (void) conv_check_native(argv, envp);
330c13de8f6Sab196087
331c13de8f6Sab196087 /*
332c13de8f6Sab196087 * conv_check_native() should not return, as we expect
333c13de8f6Sab196087 * the 64-bit version to have executed on top of us.
334c13de8f6Sab196087 * If it does, it means there is no 64-bit support
335c13de8f6Sab196087 * available on this system.
336c13de8f6Sab196087 */
337c13de8f6Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ISA32_NO64SUP),
338c13de8f6Sab196087 crle.c_name);
339c13de8f6Sab196087 return (1);
340c13de8f6Sab196087 }
341c13de8f6Sab196087 #endif
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_VERBOSE)
3447c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_CONFILE), crle.c_confil);
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate /*
3477c478bd9Sstevel@tonic-gate * Make sure the configuration file is accessible. Stat the file to
3487c478bd9Sstevel@tonic-gate * determine its dev number - this is used to determine whether the
3497c478bd9Sstevel@tonic-gate * temporary configuration file we're about to build can be renamed or
3507c478bd9Sstevel@tonic-gate * must be copied to its final destination.
3517c478bd9Sstevel@tonic-gate */
3527c478bd9Sstevel@tonic-gate (void) umask(022);
3537c478bd9Sstevel@tonic-gate if (access(crle.c_confil, (R_OK | W_OK)) == 0) {
3547c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_EXISTS;
3557c478bd9Sstevel@tonic-gate
3567c478bd9Sstevel@tonic-gate if (stat(crle.c_confil, &ostatus) != 0) {
3577c478bd9Sstevel@tonic-gate int err = errno;
3587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
3597c478bd9Sstevel@tonic-gate crle.c_name, crle.c_confil, strerror(err));
3607c478bd9Sstevel@tonic-gate return (1);
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate } else if (errno != ENOENT) {
3637c478bd9Sstevel@tonic-gate int err = errno;
3647c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_ACCESS), crle.c_name,
3657c478bd9Sstevel@tonic-gate crle.c_confil, strerror(err));
3667c478bd9Sstevel@tonic-gate return (1);
3677c478bd9Sstevel@tonic-gate } else {
3687c478bd9Sstevel@tonic-gate int fd;
3697c478bd9Sstevel@tonic-gate
3707c478bd9Sstevel@tonic-gate /*
3717c478bd9Sstevel@tonic-gate * Try opening the file now, if it works delete it, there may
3727c478bd9Sstevel@tonic-gate * be a lot of processing ahead of us, so we'll come back and
3737c478bd9Sstevel@tonic-gate * create the real thing later.
3747c478bd9Sstevel@tonic-gate */
3757c478bd9Sstevel@tonic-gate if ((fd = open(crle.c_confil, (O_RDWR | O_CREAT | O_TRUNC),
3767c478bd9Sstevel@tonic-gate 0666)) == -1) {
3777c478bd9Sstevel@tonic-gate int err = errno;
3787c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
3797c478bd9Sstevel@tonic-gate crle.c_name, crle.c_confil, strerror(err));
3807c478bd9Sstevel@tonic-gate return (1);
3817c478bd9Sstevel@tonic-gate }
3827c478bd9Sstevel@tonic-gate if (fstat(fd, &ostatus) != 0) {
3837c478bd9Sstevel@tonic-gate int err = errno;
3847c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
3857c478bd9Sstevel@tonic-gate crle.c_name, crle.c_confil, strerror(err));
3867c478bd9Sstevel@tonic-gate return (1);
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate (void) close(fd);
3897c478bd9Sstevel@tonic-gate (void) unlink(crle.c_confil);
3907c478bd9Sstevel@tonic-gate }
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate /*
3937c478bd9Sstevel@tonic-gate * If an object directory is required to hold dldump(3dl) output assign
3947c478bd9Sstevel@tonic-gate * a default if necessary and insure we're able to write there.
3957c478bd9Sstevel@tonic-gate */
3967c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_ALTER) {
39757ef7aa9SRod Evans if (objdir->o_objdir == NULL) {
3987c478bd9Sstevel@tonic-gate char *str;
3997c478bd9Sstevel@tonic-gate
4007c478bd9Sstevel@tonic-gate /*
4017c478bd9Sstevel@tonic-gate * Use the configuration files directory.
4027c478bd9Sstevel@tonic-gate */
4037c478bd9Sstevel@tonic-gate if ((str = strrchr(crle.c_confil, '/')) == NULL)
40457ef7aa9SRod Evans objdir->o_objdir =
4057c478bd9Sstevel@tonic-gate (char *)MSG_ORIG(MSG_DIR_DOT);
4067c478bd9Sstevel@tonic-gate else {
4077c478bd9Sstevel@tonic-gate int len = str - crle.c_confil;
4087c478bd9Sstevel@tonic-gate
40957ef7aa9SRod Evans if ((objdir->o_objdir =
41057ef7aa9SRod Evans malloc(len + 1)) == NULL) {
4117c478bd9Sstevel@tonic-gate int err = errno;
4127c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
4137c478bd9Sstevel@tonic-gate MSG_INTL(MSG_SYS_MALLOC),
4147c478bd9Sstevel@tonic-gate crle.c_name, strerror(err));
4157c478bd9Sstevel@tonic-gate return (1);
4167c478bd9Sstevel@tonic-gate }
41757ef7aa9SRod Evans (void) strncpy(objdir->o_objdir,
4187c478bd9Sstevel@tonic-gate crle.c_confil, len);
41957ef7aa9SRod Evans objdir->o_objdir[len] = '\0';
4207c478bd9Sstevel@tonic-gate }
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate
4237c478bd9Sstevel@tonic-gate /*
4247c478bd9Sstevel@tonic-gate * If we're going to dldump(3dl) images ourself make sure we
4257c478bd9Sstevel@tonic-gate * can access any directories.
4267c478bd9Sstevel@tonic-gate */
4277c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_DUMP) {
4287879e8a6SToomas Soome Objdir *objdir = NULL;
42957ef7aa9SRod Evans Aliste idx;
4307c478bd9Sstevel@tonic-gate int err = 0;
4317c478bd9Sstevel@tonic-gate
43257ef7aa9SRod Evans for (ALIST_TRAVERSE(objdirs, idx, objdir)) {
4337c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_VERBOSE)
4347c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_OBJDIR),
4357c478bd9Sstevel@tonic-gate objdir->o_objdir);
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate if ((objdir->o_flags & CRLE_DUMP) == 0)
4387c478bd9Sstevel@tonic-gate continue;
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate if (access(objdir->o_objdir,
4417c478bd9Sstevel@tonic-gate (R_OK | W_OK)) != 0) {
4427c478bd9Sstevel@tonic-gate err = errno;
4437c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
4447c478bd9Sstevel@tonic-gate MSG_INTL(MSG_SYS_ACCESS),
4457c478bd9Sstevel@tonic-gate crle.c_name, objdir->o_objdir,
4467c478bd9Sstevel@tonic-gate strerror(err));
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate }
4497c478bd9Sstevel@tonic-gate if (err)
4507c478bd9Sstevel@tonic-gate return (1);
4517c478bd9Sstevel@tonic-gate }
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate /*
4557c478bd9Sstevel@tonic-gate * Establish any initial object directory.
4567c478bd9Sstevel@tonic-gate */
45757ef7aa9SRod Evans crle.c_objdir = iobjdir->o_objdir;
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate /*
4607c478bd9Sstevel@tonic-gate * Create a temporary file name in which to build the configuration
4617c478bd9Sstevel@tonic-gate * information.
4627c478bd9Sstevel@tonic-gate */
4637c478bd9Sstevel@tonic-gate if ((crle.c_tempname = tempnam(MSG_ORIG(MSG_TMP_DIR),
4647c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_TMP_PFX))) == NULL) {
4657c478bd9Sstevel@tonic-gate int err = errno;
4667c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_TEMPNAME),
4677c478bd9Sstevel@tonic-gate crle.c_name, strerror(err));
4687c478bd9Sstevel@tonic-gate return (1);
4697c478bd9Sstevel@tonic-gate }
4707c478bd9Sstevel@tonic-gate if ((crle.c_tempfd = open(crle.c_tempname, (O_RDWR | O_CREAT),
4717c478bd9Sstevel@tonic-gate 0666)) == -1) {
4727c478bd9Sstevel@tonic-gate int err = errno;
4737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
4747c478bd9Sstevel@tonic-gate crle.c_name, crle.c_tempname, strerror(err));
4757c478bd9Sstevel@tonic-gate return (1);
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate if (stat(crle.c_tempname, &nstatus) != 0) {
4787c478bd9Sstevel@tonic-gate int err = errno;
4797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
4807c478bd9Sstevel@tonic-gate crle.c_name, crle.c_tempname, strerror(err));
4817c478bd9Sstevel@tonic-gate return (1);
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate if (ostatus.st_dev != nstatus.st_dev)
4847c478bd9Sstevel@tonic-gate crle.c_flags |= CRLE_DIFFDEV;
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate /*
4877c478bd9Sstevel@tonic-gate * Second pass.
4887c478bd9Sstevel@tonic-gate */
4897c478bd9Sstevel@tonic-gate error = 0;
4907c478bd9Sstevel@tonic-gate optind = 1;
4917c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, MSG_ORIG(MSG_ARG_OPTIONS))) != -1) {
4927c478bd9Sstevel@tonic-gate const char *str;
4937c478bd9Sstevel@tonic-gate int flag = 0;
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate switch (c) {
4967c478bd9Sstevel@tonic-gate
4977c478bd9Sstevel@tonic-gate case '6':
4987c478bd9Sstevel@tonic-gate break;
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate case 'A': /* alternative is optional */
5017c478bd9Sstevel@tonic-gate flag = RTC_OBJ_OPTINAL;
5027c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
5037c478bd9Sstevel@tonic-gate case 'a': /* alternative required */
5047c478bd9Sstevel@tonic-gate flag |= (RTC_OBJ_ALTER | RTC_OBJ_CMDLINE);
5057c478bd9Sstevel@tonic-gate if (inspect(&crle, (const char *)optarg, flag) != 0)
5067c478bd9Sstevel@tonic-gate error = 1;
5077c478bd9Sstevel@tonic-gate break;
5087c478bd9Sstevel@tonic-gate
5097c478bd9Sstevel@tonic-gate case 'c':
5107c478bd9Sstevel@tonic-gate break;
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate case 'e':
5137c478bd9Sstevel@tonic-gate if ((flag = addenv(&crle, (const char *)optarg,
5147c478bd9Sstevel@tonic-gate RTC_ENV_REPLACE)) == 0)
5157c478bd9Sstevel@tonic-gate error = 1;
5167c478bd9Sstevel@tonic-gate else if ((crle.c_flags & CRLE_VERBOSE) && (flag == 1))
5177c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_RPLENV),
5187c478bd9Sstevel@tonic-gate (const char *)optarg);
5197c478bd9Sstevel@tonic-gate break;
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate case 'E':
5227c478bd9Sstevel@tonic-gate if ((flag = addenv(&crle, (const char *)optarg,
5237c478bd9Sstevel@tonic-gate RTC_ENV_PERMANT)) == 0)
5247c478bd9Sstevel@tonic-gate error = 1;
5257c478bd9Sstevel@tonic-gate else if ((crle.c_flags & CRLE_VERBOSE) && (flag == 1))
5267c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_PRMENV),
5277c478bd9Sstevel@tonic-gate (const char *)optarg);
5287c478bd9Sstevel@tonic-gate break;
5297c478bd9Sstevel@tonic-gate
5307c478bd9Sstevel@tonic-gate case 'f':
5317c478bd9Sstevel@tonic-gate break;
5327c478bd9Sstevel@tonic-gate
5337c478bd9Sstevel@tonic-gate case 'G': /* group object */
5347c478bd9Sstevel@tonic-gate flag = (RTC_OBJ_DUMP | RTC_OBJ_ALTER);
5357c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
5367c478bd9Sstevel@tonic-gate case 'g':
5377c478bd9Sstevel@tonic-gate flag |= (RTC_OBJ_GROUP | RTC_OBJ_CMDLINE);
5387c478bd9Sstevel@tonic-gate if (inspect(&crle, (const char *)optarg, flag) != 0)
5397c478bd9Sstevel@tonic-gate error = 1;
5407c478bd9Sstevel@tonic-gate break;
5417c478bd9Sstevel@tonic-gate
5427c478bd9Sstevel@tonic-gate case 'I': /* individual object */
5437c478bd9Sstevel@tonic-gate flag = (RTC_OBJ_DUMP | RTC_OBJ_ALTER);
5447c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
5457c478bd9Sstevel@tonic-gate case 'i':
5467c478bd9Sstevel@tonic-gate flag |= RTC_OBJ_CMDLINE;
5477c478bd9Sstevel@tonic-gate if (inspect(&crle, (const char *)optarg, flag) != 0)
5487c478bd9Sstevel@tonic-gate error = 1;
5497c478bd9Sstevel@tonic-gate break;
5507c478bd9Sstevel@tonic-gate
5517c478bd9Sstevel@tonic-gate case 'l': /* library search path */
5527c478bd9Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_ELF);
5537c478bd9Sstevel@tonic-gate lib = &crle.c_edlibpath;
5547c478bd9Sstevel@tonic-gate if (addlib(&crle, lib, (const char *)optarg) != 0)
5557c478bd9Sstevel@tonic-gate error = 1;
5567c478bd9Sstevel@tonic-gate else if (crle.c_flags & CRLE_VERBOSE)
5577c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_DLIBPTH),
5587c478bd9Sstevel@tonic-gate str, (const char *)optarg);
5597c478bd9Sstevel@tonic-gate break;
5607c478bd9Sstevel@tonic-gate
5617c478bd9Sstevel@tonic-gate case 'o':
5627c478bd9Sstevel@tonic-gate crle.c_objdir = optarg;
5637c478bd9Sstevel@tonic-gate break;
5647c478bd9Sstevel@tonic-gate
5657c478bd9Sstevel@tonic-gate case 's': /* trusted (secure) path */
5667c478bd9Sstevel@tonic-gate str = MSG_ORIG(MSG_STR_ELF);
5677c478bd9Sstevel@tonic-gate lib = &crle.c_eslibpath;
5687c478bd9Sstevel@tonic-gate if (addlib(&crle, lib, (const char *)optarg) != 0)
5697c478bd9Sstevel@tonic-gate error = 1;
5707c478bd9Sstevel@tonic-gate else if (crle.c_flags & CRLE_VERBOSE)
5717c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_TLIBPTH),
5727c478bd9Sstevel@tonic-gate str, (const char *)optarg);
5737c478bd9Sstevel@tonic-gate break;
5747c478bd9Sstevel@tonic-gate
575*fec04708SRichard Lowe case 't':
5767c478bd9Sstevel@tonic-gate break;
5777c478bd9Sstevel@tonic-gate
5787c478bd9Sstevel@tonic-gate case 'u':
5797c478bd9Sstevel@tonic-gate break;
5807c478bd9Sstevel@tonic-gate
5817c478bd9Sstevel@tonic-gate case 'v':
5827c478bd9Sstevel@tonic-gate break;
5837c478bd9Sstevel@tonic-gate }
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate
5867c478bd9Sstevel@tonic-gate /*
5877c478bd9Sstevel@tonic-gate * Now that we've generated as many file/directory processing errors
5887c478bd9Sstevel@tonic-gate * as we can, return if any fatal error conditions occurred.
5897c478bd9Sstevel@tonic-gate */
5907c478bd9Sstevel@tonic-gate if (error) {
5917c478bd9Sstevel@tonic-gate (void) unlink(crle.c_tempname);
5927c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_CREAT) {
5937c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_CREATE),
5947c478bd9Sstevel@tonic-gate crle.c_name, crle.c_confil);
5957c478bd9Sstevel@tonic-gate }
5967c478bd9Sstevel@tonic-gate return (1);
5977c478bd9Sstevel@tonic-gate }
5987c478bd9Sstevel@tonic-gate
5997c478bd9Sstevel@tonic-gate /*
6007c478bd9Sstevel@tonic-gate * Create a temporary configuration file.
6017c478bd9Sstevel@tonic-gate */
6027c478bd9Sstevel@tonic-gate if (genconfig(&crle) != 0) {
6037c478bd9Sstevel@tonic-gate (void) unlink(crle.c_tempname);
6047c478bd9Sstevel@tonic-gate return (1);
6057c478bd9Sstevel@tonic-gate }
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate /*
6087c478bd9Sstevel@tonic-gate * If dldump(3dl) images are required spawn a process to create them.
6097c478bd9Sstevel@tonic-gate */
6107c478bd9Sstevel@tonic-gate if (crle.c_flags & CRLE_DUMP) {
6117c478bd9Sstevel@tonic-gate if (dump(&crle) != 0) {
6127c478bd9Sstevel@tonic-gate (void) unlink(crle.c_tempname);
6137c478bd9Sstevel@tonic-gate return (1);
6147c478bd9Sstevel@tonic-gate }
6157c478bd9Sstevel@tonic-gate }
6167c478bd9Sstevel@tonic-gate
6177c478bd9Sstevel@tonic-gate /*
6187c478bd9Sstevel@tonic-gate * Copy the finished temporary configuration file to its final home.
6197c478bd9Sstevel@tonic-gate */
6207c478bd9Sstevel@tonic-gate if (updateconfig(&crle) != 0)
6217c478bd9Sstevel@tonic-gate return (1);
6227c478bd9Sstevel@tonic-gate
6237c478bd9Sstevel@tonic-gate return (0);
6247c478bd9Sstevel@tonic-gate }
625