xref: /onnv-gate/usr/src/cmd/sgs/crle/common/crle.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate #include	<sys/types.h>
29*0Sstevel@tonic-gate #include	<sys/stat.h>
30*0Sstevel@tonic-gate #include	<fcntl.h>
31*0Sstevel@tonic-gate #include	<stdio.h>
32*0Sstevel@tonic-gate #include	<string.h>
33*0Sstevel@tonic-gate #include	<unistd.h>
34*0Sstevel@tonic-gate #include	<locale.h>
35*0Sstevel@tonic-gate #include	<dlfcn.h>
36*0Sstevel@tonic-gate #include	<errno.h>
37*0Sstevel@tonic-gate #include	"_crle.h"
38*0Sstevel@tonic-gate #include	"msg.h"
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate /*
42*0Sstevel@tonic-gate  * crle(1) entry point and argument processing.
43*0Sstevel@tonic-gate  *
44*0Sstevel@tonic-gate  * Two passes of the arguments are carried out; the first collects any single
45*0Sstevel@tonic-gate  * instance options and establishes defaults that might be appropriate for
46*0Sstevel@tonic-gate  * other arguments:
47*0Sstevel@tonic-gate  *
48*0Sstevel@tonic-gate  *  -64		operate on, or apply, 64-bit objects (default is 32-bit).
49*0Sstevel@tonic-gate  *
50*0Sstevel@tonic-gate  *  -c file	defines the output configuration file.
51*0Sstevel@tonic-gate  *
52*0Sstevel@tonic-gate  *  -f flag	flags for dldump(3dl).
53*0Sstevel@tonic-gate  *
54*0Sstevel@tonic-gate  *  -o dir	defines the output directory for any dldump(3dl) objects
55*0Sstevel@tonic-gate  *		that follow.  For backward compatibility (RTC_VER_ONE only
56*0Sstevel@tonic-gate  * 		allowed one output directory) allow the first occurrence of this
57*0Sstevel@tonic-gate  *		specification to catch any previous files.  If not specified,
58*0Sstevel@tonic-gate  *		the configuration files parent directory is used).
59*0Sstevel@tonic-gate  *
60*0Sstevel@tonic-gate  *  -u		update any existing configuration file.  Any additional
61*0Sstevel@tonic-gate  *		arguments supplied will be added to the new configuration
62*0Sstevel@tonic-gate  *		information.
63*0Sstevel@tonic-gate  *
64*0Sstevel@tonic-gate  *  -v		verbose mode.
65*0Sstevel@tonic-gate  *
66*0Sstevel@tonic-gate  * The second pass collects all other options and constructs an internal
67*0Sstevel@tonic-gate  * string table which will be used to create the eventual configuration file.
68*0Sstevel@tonic-gate  *
69*0Sstevel@tonic-gate  *  -a name	add the individual name, with an alternative to the
70*0Sstevel@tonic-gate  *		configuration cache.  No alternative is created via dldump(3dl),
71*0Sstevel@tonic-gate  *		it is the users responsibility to furnish the alternative.
72*0Sstevel@tonic-gate  *
73*0Sstevel@tonic-gate  *  -A name	add the individual name, with an optional alternative to the
74*0Sstevel@tonic-gate  *		configuration cache.  No alternative is created via dldump(3dl),
75*0Sstevel@tonic-gate  *		it is the users responsibility to furnish the alternative.
76*0Sstevel@tonic-gate  *
77*0Sstevel@tonic-gate  *  -e envar	replaceable environment variable
78*0Sstevel@tonic-gate  *
79*0Sstevel@tonic-gate  *  -E envar	permanent environment variable
80*0Sstevel@tonic-gate  *
81*0Sstevel@tonic-gate  *  -i name	add the individual name to the configuration cache.  If name
82*0Sstevel@tonic-gate  *		is a directory each shared object within the directory is added
83*0Sstevel@tonic-gate  *		to the cache.
84*0Sstevel@tonic-gate  *
85*0Sstevel@tonic-gate  *  -I name	same as -i, but in addition any ELF objects are dldump(3dl)'ed.
86*0Sstevel@tonic-gate  *
87*0Sstevel@tonic-gate  *  -g name	add the group name to the configuration cache.  Each object is
88*0Sstevel@tonic-gate  * 		expanded to determine its dependencies and these are added to
89*0Sstevel@tonic-gate  *		the cache.  If name is a directory each shared object within the
90*0Sstevel@tonic-gate  *		directory and its dependencies are added to the cache.
91*0Sstevel@tonic-gate  *
92*0Sstevel@tonic-gate  *  -G app	same as -g, but in addition any ELF objects are dldump(3dl)'ed.
93*0Sstevel@tonic-gate  *
94*0Sstevel@tonic-gate  *  -l dir	library search directory
95*0Sstevel@tonic-gate  *
96*0Sstevel@tonic-gate  *  -s dir	trusted (secure) directory
97*0Sstevel@tonic-gate  *
98*0Sstevel@tonic-gate  *  -t type	search directory type (ELF or AOUT).
99*0Sstevel@tonic-gate  */
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate /*
102*0Sstevel@tonic-gate  * Establish a structure for maintaining current object directory attributes.
103*0Sstevel@tonic-gate  * We wish to validate the access of any object directory that will be written
104*0Sstevel@tonic-gate  * to (dldump(3dl), and thus by maintaining a current object directory and its
105*0Sstevel@tonic-gate  * intended use we can perform this validation later.
106*0Sstevel@tonic-gate  */
107*0Sstevel@tonic-gate typedef struct {
108*0Sstevel@tonic-gate 	char		*o_objdir;
109*0Sstevel@tonic-gate 	unsigned int	o_flags;
110*0Sstevel@tonic-gate } Objdir;
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate main(int argc, char ** argv)
113*0Sstevel@tonic-gate {
114*0Sstevel@tonic-gate 	Crle_desc	crle = { 0 };
115*0Sstevel@tonic-gate 	int		c, error = 0;
116*0Sstevel@tonic-gate 	char **		lib;
117*0Sstevel@tonic-gate 	List		objdirs = { 0, 0 };
118*0Sstevel@tonic-gate 	Objdir		_lobjdir = { 0, 0 }, * lobjdir = &_lobjdir;
119*0Sstevel@tonic-gate 	struct stat	ostatus, nstatus;
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate 	if (list_append(&objdirs, lobjdir) == 0)
122*0Sstevel@tonic-gate 		return (1);
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 	/*
125*0Sstevel@tonic-gate 	 * Establish locale.
126*0Sstevel@tonic-gate 	 */
127*0Sstevel@tonic-gate 	(void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY));
128*0Sstevel@tonic-gate 	(void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS));
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 	/*
131*0Sstevel@tonic-gate 	 * Initialization configuration information.
132*0Sstevel@tonic-gate 	 */
133*0Sstevel@tonic-gate 	crle.c_name = argv[0];
134*0Sstevel@tonic-gate 	crle.c_strbkts = 503;
135*0Sstevel@tonic-gate 	crle.c_inobkts = 251;
136*0Sstevel@tonic-gate 	crle.c_class = ELFCLASS32;
137*0Sstevel@tonic-gate 	crle.c_machine = M_MACH;
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate 	/*
140*0Sstevel@tonic-gate 	 * First argument pass.
141*0Sstevel@tonic-gate 	 */
142*0Sstevel@tonic-gate 	while ((c = getopt(argc, argv, MSG_ORIG(MSG_ARG_OPTIONS))) != -1) {
143*0Sstevel@tonic-gate 		switch (c) {
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate 		case '6':			/* operate on 64-bit objects */
146*0Sstevel@tonic-gate 			if (optarg[0] != '4') {
147*0Sstevel@tonic-gate 				(void) fprintf(stderr,
148*0Sstevel@tonic-gate 				    MSG_INTL(MSG_ARG_ILLEGAL), crle.c_name,
149*0Sstevel@tonic-gate 				    MSG_ORIG(MSG_ARG_6), optarg);
150*0Sstevel@tonic-gate 				error = 1;
151*0Sstevel@tonic-gate 			}
152*0Sstevel@tonic-gate 			crle.c_class = ELFCLASS64;
153*0Sstevel@tonic-gate #if	defined(sparc)
154*0Sstevel@tonic-gate 			crle.c_machine = EM_SPARCV9;
155*0Sstevel@tonic-gate #elif	defined(i386)
156*0Sstevel@tonic-gate 			crle.c_machine = EM_IA_64;
157*0Sstevel@tonic-gate #endif
158*0Sstevel@tonic-gate 			break;
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate 		case 'A':			/* create optional */
161*0Sstevel@tonic-gate 			/* FALLTHROUGH */	/*	alternative */
162*0Sstevel@tonic-gate 		case 'a':			/* create alternative */
163*0Sstevel@tonic-gate 			crle.c_flags |= (CRLE_CREAT | CRLE_ALTER);
164*0Sstevel@tonic-gate 			lobjdir->o_flags |= (CRLE_CREAT | CRLE_ALTER);
165*0Sstevel@tonic-gate 			break;
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate 		case 'c':			/* define the config file */
168*0Sstevel@tonic-gate 			if (crle.c_confil) {
169*0Sstevel@tonic-gate 				(void) fprintf(stderr, MSG_INTL(MSG_ARG_MULT),
170*0Sstevel@tonic-gate 				    crle.c_name, MSG_ORIG(MSG_ARG_C));
171*0Sstevel@tonic-gate 				error = 1;
172*0Sstevel@tonic-gate 			}
173*0Sstevel@tonic-gate 			crle.c_confil = optarg;
174*0Sstevel@tonic-gate 			break;
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 		case 'e':			/* replaceable env variable */
177*0Sstevel@tonic-gate 			crle.c_flags |= (CRLE_RPLENV | CRLE_CREAT);
178*0Sstevel@tonic-gate 			break;
179*0Sstevel@tonic-gate 
180*0Sstevel@tonic-gate 		case 'E':			/* permanent env variable */
181*0Sstevel@tonic-gate 			crle.c_flags |= (CRLE_PRMENV | CRLE_CREAT);
182*0Sstevel@tonic-gate 			break;
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate 		case 'f':			/* dldump(3dl) flags */
185*0Sstevel@tonic-gate 			if (crle.c_dlflags) {
186*0Sstevel@tonic-gate 				(void) fprintf(stderr, MSG_INTL(MSG_ARG_MULT),
187*0Sstevel@tonic-gate 				    crle.c_name, MSG_ORIG(MSG_ARG_F));
188*0Sstevel@tonic-gate 				error = 1;
189*0Sstevel@tonic-gate 			}
190*0Sstevel@tonic-gate 			if ((crle.c_dlflags = dlflags(&crle,
191*0Sstevel@tonic-gate 			    (const char *)optarg)) == 0)
192*0Sstevel@tonic-gate 				error = 1;
193*0Sstevel@tonic-gate 			break;
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate 		case 'G':			/* group object */
196*0Sstevel@tonic-gate 			crle.c_flags |= (CRLE_DUMP | CRLE_ALTER);
197*0Sstevel@tonic-gate 			lobjdir->o_flags |= (CRLE_DUMP | CRLE_ALTER);
198*0Sstevel@tonic-gate 			/* FALLTHROUGH */
199*0Sstevel@tonic-gate 		case 'g':
200*0Sstevel@tonic-gate 			crle.c_flags |= CRLE_CREAT;
201*0Sstevel@tonic-gate 			lobjdir->o_flags |= CRLE_CREAT;
202*0Sstevel@tonic-gate 			break;
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate 		case 'I':			/* individual object */
205*0Sstevel@tonic-gate 			crle.c_flags |= (CRLE_DUMP | CRLE_ALTER);
206*0Sstevel@tonic-gate 			lobjdir->o_flags |= (CRLE_DUMP | CRLE_ALTER);
207*0Sstevel@tonic-gate 			/* FALLTHROUGH */
208*0Sstevel@tonic-gate 		case 'i':
209*0Sstevel@tonic-gate 			crle.c_flags |= CRLE_CREAT;
210*0Sstevel@tonic-gate 			lobjdir->o_flags |= CRLE_CREAT;
211*0Sstevel@tonic-gate 			break;
212*0Sstevel@tonic-gate 
213*0Sstevel@tonic-gate 		case 'l':			/* library search path */
214*0Sstevel@tonic-gate 			if (crle.c_flags & CRLE_AOUT)
215*0Sstevel@tonic-gate 				crle.c_flags |= CRLE_ADLIB;
216*0Sstevel@tonic-gate 			else
217*0Sstevel@tonic-gate 				crle.c_flags |= CRLE_EDLIB;
218*0Sstevel@tonic-gate 			crle.c_flags |= CRLE_CREAT;
219*0Sstevel@tonic-gate 			break;
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate 		case 'o':			/* define an object directory */
222*0Sstevel@tonic-gate 			if (lobjdir->o_objdir) {
223*0Sstevel@tonic-gate 				if ((lobjdir = calloc(sizeof (Objdir), 1)) == 0)
224*0Sstevel@tonic-gate 					return (1);
225*0Sstevel@tonic-gate 				if (list_append(&objdirs, lobjdir) == 0)
226*0Sstevel@tonic-gate 					return (1);
227*0Sstevel@tonic-gate 			}
228*0Sstevel@tonic-gate 			lobjdir->o_objdir = optarg;
229*0Sstevel@tonic-gate 			break;
230*0Sstevel@tonic-gate 
231*0Sstevel@tonic-gate 		case 's':			/* trusted (secure) path */
232*0Sstevel@tonic-gate 			if (crle.c_flags & CRLE_AOUT)
233*0Sstevel@tonic-gate 				crle.c_flags |= CRLE_ASLIB;
234*0Sstevel@tonic-gate 			else
235*0Sstevel@tonic-gate 				crle.c_flags |= CRLE_ESLIB;
236*0Sstevel@tonic-gate 			crle.c_flags |= CRLE_CREAT;
237*0Sstevel@tonic-gate 			break;
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 		case 't':			/* search path type */
240*0Sstevel@tonic-gate 			if (strcmp((const char *)optarg,
241*0Sstevel@tonic-gate 			    MSG_ORIG(MSG_STR_ELF)) == 0)
242*0Sstevel@tonic-gate 				crle.c_flags &= ~CRLE_AOUT;
243*0Sstevel@tonic-gate 			else if (strcmp((const char *)optarg,
244*0Sstevel@tonic-gate 			    MSG_ORIG(MSG_STR_AOUT)) == 0)
245*0Sstevel@tonic-gate 				crle.c_flags |= CRLE_AOUT;
246*0Sstevel@tonic-gate 			else {
247*0Sstevel@tonic-gate 				(void) fprintf(stderr, MSG_INTL(MSG_ARG_TYPE),
248*0Sstevel@tonic-gate 				    crle.c_name, optarg);
249*0Sstevel@tonic-gate 				error = 1;
250*0Sstevel@tonic-gate 			}
251*0Sstevel@tonic-gate 			break;
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 		case 'u':			/* update mode */
254*0Sstevel@tonic-gate 			crle.c_flags |= (CRLE_CREAT | CRLE_UPDATE);
255*0Sstevel@tonic-gate 			break;
256*0Sstevel@tonic-gate 
257*0Sstevel@tonic-gate 		case 'v':			/* verbose mode */
258*0Sstevel@tonic-gate 			crle.c_flags |= CRLE_VERBOSE;
259*0Sstevel@tonic-gate 			break;
260*0Sstevel@tonic-gate 
261*0Sstevel@tonic-gate 		default:
262*0Sstevel@tonic-gate 			error = 2;
263*0Sstevel@tonic-gate 		}
264*0Sstevel@tonic-gate 	}
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate 	if (optind != argc)
267*0Sstevel@tonic-gate 		error = 2;
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate 	/*
270*0Sstevel@tonic-gate 	 * Determine the configuration file, which in the case of an existing
271*0Sstevel@tonic-gate 	 * error condition is required in the final error message.
272*0Sstevel@tonic-gate 	 */
273*0Sstevel@tonic-gate 	if (crle.c_confil == 0) {
274*0Sstevel@tonic-gate 		crle.c_flags |= CRLE_CONFDEF;
275*0Sstevel@tonic-gate 
276*0Sstevel@tonic-gate 		if (crle.c_class == ELFCLASS32)
277*0Sstevel@tonic-gate 			crle.c_confil = (char *)MSG_ORIG(MSG_PTH_CONFIG);
278*0Sstevel@tonic-gate 		else
279*0Sstevel@tonic-gate 			crle.c_confil = (char *)MSG_ORIG(MSG_PTH_CONFIG_64);
280*0Sstevel@tonic-gate 	}
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 	/*
283*0Sstevel@tonic-gate 	 * Now that we've generated as many file/directory processing errors
284*0Sstevel@tonic-gate 	 * as we can, return if any fatal error conditions occurred.
285*0Sstevel@tonic-gate 	 */
286*0Sstevel@tonic-gate 	if (error) {
287*0Sstevel@tonic-gate 		if (error == 2) {
288*0Sstevel@tonic-gate 			(void) fprintf(stderr, MSG_INTL(MSG_ARG_USAGE),
289*0Sstevel@tonic-gate 			    crle.c_name);
290*0Sstevel@tonic-gate 		} else if (crle.c_flags & CRLE_CREAT) {
291*0Sstevel@tonic-gate 			(void) fprintf(stderr, MSG_INTL(MSG_GEN_CREATE),
292*0Sstevel@tonic-gate 			    crle.c_name, crle.c_confil);
293*0Sstevel@tonic-gate 		}
294*0Sstevel@tonic-gate 		return (1);
295*0Sstevel@tonic-gate 	}
296*0Sstevel@tonic-gate 
297*0Sstevel@tonic-gate 	/*
298*0Sstevel@tonic-gate 	 * Apply any additional defaults.
299*0Sstevel@tonic-gate 	 */
300*0Sstevel@tonic-gate 	if (crle.c_dlflags == 0)
301*0Sstevel@tonic-gate 		crle.c_dlflags = RTLD_REL_RELATIVE;
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate 	crle.c_audit = (char *)MSG_ORIG(MSG_ENV_LD_AUDIT);
304*0Sstevel@tonic-gate 
305*0Sstevel@tonic-gate 	(void) elf_version(EV_CURRENT);
306*0Sstevel@tonic-gate 
307*0Sstevel@tonic-gate 	/*
308*0Sstevel@tonic-gate 	 * If we're updating an existing file or not creating a configuration
309*0Sstevel@tonic-gate 	 * file at all, investigate the original.
310*0Sstevel@tonic-gate 	 */
311*0Sstevel@tonic-gate 	if ((crle.c_flags & CRLE_UPDATE) ||
312*0Sstevel@tonic-gate 	    ((crle.c_flags & CRLE_CREAT) == 0)) {
313*0Sstevel@tonic-gate 		if (inspectconfig(&crle))
314*0Sstevel@tonic-gate 			return (1);
315*0Sstevel@tonic-gate 		if ((crle.c_flags & CRLE_UPDATE) == 0)
316*0Sstevel@tonic-gate 			return (0);
317*0Sstevel@tonic-gate 	}
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 	if (crle.c_flags & CRLE_VERBOSE)
320*0Sstevel@tonic-gate 		(void) printf(MSG_INTL(MSG_DIA_CONFILE), crle.c_confil);
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate 	/*
323*0Sstevel@tonic-gate 	 * Make sure the configuration file is accessible.  Stat the file to
324*0Sstevel@tonic-gate 	 * determine its dev number - this is used to determine whether the
325*0Sstevel@tonic-gate 	 * temporary configuration file we're about to build can be renamed or
326*0Sstevel@tonic-gate 	 * must be copied to its final destination.
327*0Sstevel@tonic-gate 	 */
328*0Sstevel@tonic-gate 	(void) umask(022);
329*0Sstevel@tonic-gate 	if (access(crle.c_confil, (R_OK | W_OK)) == 0) {
330*0Sstevel@tonic-gate 		crle.c_flags |= CRLE_EXISTS;
331*0Sstevel@tonic-gate 
332*0Sstevel@tonic-gate 		if (stat(crle.c_confil, &ostatus) != 0) {
333*0Sstevel@tonic-gate 			int err = errno;
334*0Sstevel@tonic-gate 			(void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
335*0Sstevel@tonic-gate 			    crle.c_name, crle.c_confil, strerror(err));
336*0Sstevel@tonic-gate 			return (1);
337*0Sstevel@tonic-gate 		}
338*0Sstevel@tonic-gate 	} else if (errno != ENOENT) {
339*0Sstevel@tonic-gate 		int err = errno;
340*0Sstevel@tonic-gate 		(void) fprintf(stderr, MSG_INTL(MSG_SYS_ACCESS), crle.c_name,
341*0Sstevel@tonic-gate 		    crle.c_confil, strerror(err));
342*0Sstevel@tonic-gate 		return (1);
343*0Sstevel@tonic-gate 	} else {
344*0Sstevel@tonic-gate 		int	fd;
345*0Sstevel@tonic-gate 
346*0Sstevel@tonic-gate 		/*
347*0Sstevel@tonic-gate 		 * Try opening the file now, if it works delete it, there may
348*0Sstevel@tonic-gate 		 * be a lot of processing ahead of us, so we'll come back and
349*0Sstevel@tonic-gate 		 * create the real thing later.
350*0Sstevel@tonic-gate 		 */
351*0Sstevel@tonic-gate 		if ((fd = open(crle.c_confil, (O_RDWR | O_CREAT | O_TRUNC),
352*0Sstevel@tonic-gate 		    0666)) == -1) {
353*0Sstevel@tonic-gate 			int err = errno;
354*0Sstevel@tonic-gate 			(void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
355*0Sstevel@tonic-gate 			    crle.c_name, crle.c_confil, strerror(err));
356*0Sstevel@tonic-gate 			return (1);
357*0Sstevel@tonic-gate 		}
358*0Sstevel@tonic-gate 		if (fstat(fd, &ostatus) != 0) {
359*0Sstevel@tonic-gate 			int err = errno;
360*0Sstevel@tonic-gate 			(void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
361*0Sstevel@tonic-gate 			    crle.c_name, crle.c_confil, strerror(err));
362*0Sstevel@tonic-gate 			return (1);
363*0Sstevel@tonic-gate 		}
364*0Sstevel@tonic-gate 		(void) close(fd);
365*0Sstevel@tonic-gate 		(void) unlink(crle.c_confil);
366*0Sstevel@tonic-gate 	}
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate 	/*
369*0Sstevel@tonic-gate 	 * If an object directory is required to hold dldump(3dl) output assign
370*0Sstevel@tonic-gate 	 * a default if necessary and insure we're able to write there.
371*0Sstevel@tonic-gate 	 */
372*0Sstevel@tonic-gate 	if (crle.c_flags & CRLE_ALTER) {
373*0Sstevel@tonic-gate 		if (lobjdir->o_objdir == 0) {
374*0Sstevel@tonic-gate 			char	*str;
375*0Sstevel@tonic-gate 
376*0Sstevel@tonic-gate 			/*
377*0Sstevel@tonic-gate 			 * Use the configuration files directory.
378*0Sstevel@tonic-gate 			 */
379*0Sstevel@tonic-gate 			if ((str = strrchr(crle.c_confil, '/')) == NULL)
380*0Sstevel@tonic-gate 				lobjdir->o_objdir =
381*0Sstevel@tonic-gate 				    (char *)MSG_ORIG(MSG_DIR_DOT);
382*0Sstevel@tonic-gate 			else {
383*0Sstevel@tonic-gate 				int	len = str - crle.c_confil;
384*0Sstevel@tonic-gate 
385*0Sstevel@tonic-gate 				if ((lobjdir->o_objdir =
386*0Sstevel@tonic-gate 				    malloc(len + 1)) == 0) {
387*0Sstevel@tonic-gate 					int err = errno;
388*0Sstevel@tonic-gate 					(void) fprintf(stderr,
389*0Sstevel@tonic-gate 					    MSG_INTL(MSG_SYS_MALLOC),
390*0Sstevel@tonic-gate 					    crle.c_name, strerror(err));
391*0Sstevel@tonic-gate 					return (1);
392*0Sstevel@tonic-gate 				}
393*0Sstevel@tonic-gate 				(void) strncpy(lobjdir->o_objdir,
394*0Sstevel@tonic-gate 				    crle.c_confil, len);
395*0Sstevel@tonic-gate 				lobjdir->o_objdir[len] = '\0';
396*0Sstevel@tonic-gate 			}
397*0Sstevel@tonic-gate 		}
398*0Sstevel@tonic-gate 
399*0Sstevel@tonic-gate 		/*
400*0Sstevel@tonic-gate 		 * If we're going to dldump(3dl) images ourself make sure we
401*0Sstevel@tonic-gate 		 * can access any directories.
402*0Sstevel@tonic-gate 		 */
403*0Sstevel@tonic-gate 		if (crle.c_flags & CRLE_DUMP) {
404*0Sstevel@tonic-gate 			Objdir *	objdir;
405*0Sstevel@tonic-gate 			Listnode *	lnp;
406*0Sstevel@tonic-gate 			int		err = 0;
407*0Sstevel@tonic-gate 
408*0Sstevel@tonic-gate 			for (LIST_TRAVERSE(&objdirs, lnp, objdir)) {
409*0Sstevel@tonic-gate 				if (crle.c_flags & CRLE_VERBOSE)
410*0Sstevel@tonic-gate 					(void) printf(MSG_INTL(MSG_DIA_OBJDIR),
411*0Sstevel@tonic-gate 					    objdir->o_objdir);
412*0Sstevel@tonic-gate 
413*0Sstevel@tonic-gate 				if ((objdir->o_flags & CRLE_DUMP) == 0)
414*0Sstevel@tonic-gate 					continue;
415*0Sstevel@tonic-gate 
416*0Sstevel@tonic-gate 				if (access(objdir->o_objdir,
417*0Sstevel@tonic-gate 				    (R_OK | W_OK)) != 0) {
418*0Sstevel@tonic-gate 					err = errno;
419*0Sstevel@tonic-gate 					(void) fprintf(stderr,
420*0Sstevel@tonic-gate 					    MSG_INTL(MSG_SYS_ACCESS),
421*0Sstevel@tonic-gate 					    crle.c_name, objdir->o_objdir,
422*0Sstevel@tonic-gate 					    strerror(err));
423*0Sstevel@tonic-gate 				}
424*0Sstevel@tonic-gate 			}
425*0Sstevel@tonic-gate 			if (err)
426*0Sstevel@tonic-gate 				return (1);
427*0Sstevel@tonic-gate 		}
428*0Sstevel@tonic-gate 	}
429*0Sstevel@tonic-gate 
430*0Sstevel@tonic-gate 	/*
431*0Sstevel@tonic-gate 	 * Establish any initial object directory.
432*0Sstevel@tonic-gate 	 */
433*0Sstevel@tonic-gate 	crle.c_objdir = _lobjdir.o_objdir;
434*0Sstevel@tonic-gate 
435*0Sstevel@tonic-gate 	/*
436*0Sstevel@tonic-gate 	 * Create a temporary file name in which to build the configuration
437*0Sstevel@tonic-gate 	 * information.
438*0Sstevel@tonic-gate 	 */
439*0Sstevel@tonic-gate 	if ((crle.c_tempname = tempnam(MSG_ORIG(MSG_TMP_DIR),
440*0Sstevel@tonic-gate 	    MSG_ORIG(MSG_TMP_PFX))) == NULL) {
441*0Sstevel@tonic-gate 		int err = errno;
442*0Sstevel@tonic-gate 		(void) fprintf(stderr, MSG_INTL(MSG_SYS_TEMPNAME),
443*0Sstevel@tonic-gate 		    crle.c_name, strerror(err));
444*0Sstevel@tonic-gate 		return (1);
445*0Sstevel@tonic-gate 	}
446*0Sstevel@tonic-gate 	if ((crle.c_tempfd = open(crle.c_tempname, (O_RDWR | O_CREAT),
447*0Sstevel@tonic-gate 	    0666)) == -1) {
448*0Sstevel@tonic-gate 		int err = errno;
449*0Sstevel@tonic-gate 		(void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
450*0Sstevel@tonic-gate 		    crle.c_name, crle.c_tempname, strerror(err));
451*0Sstevel@tonic-gate 		return (1);
452*0Sstevel@tonic-gate 	}
453*0Sstevel@tonic-gate 	if (stat(crle.c_tempname, &nstatus) != 0) {
454*0Sstevel@tonic-gate 		int err = errno;
455*0Sstevel@tonic-gate 		(void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
456*0Sstevel@tonic-gate 		    crle.c_name, crle.c_tempname, strerror(err));
457*0Sstevel@tonic-gate 		return (1);
458*0Sstevel@tonic-gate 	}
459*0Sstevel@tonic-gate 	if (ostatus.st_dev != nstatus.st_dev)
460*0Sstevel@tonic-gate 		crle.c_flags |= CRLE_DIFFDEV;
461*0Sstevel@tonic-gate 
462*0Sstevel@tonic-gate 	/*
463*0Sstevel@tonic-gate 	 * Second pass.
464*0Sstevel@tonic-gate 	 */
465*0Sstevel@tonic-gate 	error = 0;
466*0Sstevel@tonic-gate 	optind = 1;
467*0Sstevel@tonic-gate 	while ((c = getopt(argc, argv, MSG_ORIG(MSG_ARG_OPTIONS))) != -1) {
468*0Sstevel@tonic-gate 		const char	*str;
469*0Sstevel@tonic-gate 		int		flag = 0;
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate 		switch (c) {
472*0Sstevel@tonic-gate 
473*0Sstevel@tonic-gate 		case '6':
474*0Sstevel@tonic-gate 			break;
475*0Sstevel@tonic-gate 
476*0Sstevel@tonic-gate 		case 'A':			/* alternative is optional */
477*0Sstevel@tonic-gate 			flag = RTC_OBJ_OPTINAL;
478*0Sstevel@tonic-gate 			/* FALLTHROUGH */
479*0Sstevel@tonic-gate 		case 'a':			/* alternative required */
480*0Sstevel@tonic-gate 			flag |= (RTC_OBJ_ALTER | RTC_OBJ_CMDLINE);
481*0Sstevel@tonic-gate 			if (inspect(&crle, (const char *)optarg, flag) != 0)
482*0Sstevel@tonic-gate 				error = 1;
483*0Sstevel@tonic-gate 			break;
484*0Sstevel@tonic-gate 
485*0Sstevel@tonic-gate 		case 'c':
486*0Sstevel@tonic-gate 			break;
487*0Sstevel@tonic-gate 
488*0Sstevel@tonic-gate 		case 'e':
489*0Sstevel@tonic-gate 			if ((flag = addenv(&crle, (const char *)optarg,
490*0Sstevel@tonic-gate 			    RTC_ENV_REPLACE)) == 0)
491*0Sstevel@tonic-gate 				error = 1;
492*0Sstevel@tonic-gate 			else if ((crle.c_flags & CRLE_VERBOSE) && (flag == 1))
493*0Sstevel@tonic-gate 				(void) printf(MSG_INTL(MSG_DIA_RPLENV),
494*0Sstevel@tonic-gate 				    (const char *)optarg);
495*0Sstevel@tonic-gate 			break;
496*0Sstevel@tonic-gate 
497*0Sstevel@tonic-gate 		case 'E':
498*0Sstevel@tonic-gate 			if ((flag = addenv(&crle, (const char *)optarg,
499*0Sstevel@tonic-gate 			    RTC_ENV_PERMANT)) == 0)
500*0Sstevel@tonic-gate 				error = 1;
501*0Sstevel@tonic-gate 			else if ((crle.c_flags & CRLE_VERBOSE) && (flag == 1))
502*0Sstevel@tonic-gate 				(void) printf(MSG_INTL(MSG_DIA_PRMENV),
503*0Sstevel@tonic-gate 				    (const char *)optarg);
504*0Sstevel@tonic-gate 			break;
505*0Sstevel@tonic-gate 
506*0Sstevel@tonic-gate 		case 'f':
507*0Sstevel@tonic-gate 			break;
508*0Sstevel@tonic-gate 
509*0Sstevel@tonic-gate 		case 'G':			/* group object */
510*0Sstevel@tonic-gate 			flag = (RTC_OBJ_DUMP | RTC_OBJ_ALTER);
511*0Sstevel@tonic-gate 			/* FALLTHROUGH */
512*0Sstevel@tonic-gate 		case 'g':
513*0Sstevel@tonic-gate 			flag |= (RTC_OBJ_GROUP | RTC_OBJ_CMDLINE);
514*0Sstevel@tonic-gate 			if (inspect(&crle, (const char *)optarg, flag) != 0)
515*0Sstevel@tonic-gate 				error = 1;
516*0Sstevel@tonic-gate 			break;
517*0Sstevel@tonic-gate 
518*0Sstevel@tonic-gate 		case 'I':			/* individual object */
519*0Sstevel@tonic-gate 			flag = (RTC_OBJ_DUMP | RTC_OBJ_ALTER);
520*0Sstevel@tonic-gate 			/* FALLTHROUGH */
521*0Sstevel@tonic-gate 		case 'i':
522*0Sstevel@tonic-gate 			flag |= RTC_OBJ_CMDLINE;
523*0Sstevel@tonic-gate 			if (inspect(&crle, (const char *)optarg, flag) != 0)
524*0Sstevel@tonic-gate 				error = 1;
525*0Sstevel@tonic-gate 			break;
526*0Sstevel@tonic-gate 
527*0Sstevel@tonic-gate 		case 'l':			/* library search path */
528*0Sstevel@tonic-gate 			if (crle.c_flags & CRLE_AOUT) {
529*0Sstevel@tonic-gate 				str = MSG_ORIG(MSG_STR_AOUT);
530*0Sstevel@tonic-gate 				lib = &crle.c_adlibpath;
531*0Sstevel@tonic-gate 			} else {
532*0Sstevel@tonic-gate 				str = MSG_ORIG(MSG_STR_ELF);
533*0Sstevel@tonic-gate 				lib = &crle.c_edlibpath;
534*0Sstevel@tonic-gate 			}
535*0Sstevel@tonic-gate 			if (addlib(&crle, lib, (const char *)optarg) != 0)
536*0Sstevel@tonic-gate 				error = 1;
537*0Sstevel@tonic-gate 			else if (crle.c_flags & CRLE_VERBOSE)
538*0Sstevel@tonic-gate 				(void) printf(MSG_INTL(MSG_DIA_DLIBPTH),
539*0Sstevel@tonic-gate 				    str, (const char *)optarg);
540*0Sstevel@tonic-gate 			break;
541*0Sstevel@tonic-gate 
542*0Sstevel@tonic-gate 		case 'o':
543*0Sstevel@tonic-gate 			crle.c_objdir = optarg;
544*0Sstevel@tonic-gate 			break;
545*0Sstevel@tonic-gate 
546*0Sstevel@tonic-gate 		case 's':			/* trusted (secure) path */
547*0Sstevel@tonic-gate 			if (crle.c_flags & CRLE_AOUT) {
548*0Sstevel@tonic-gate 				str = MSG_ORIG(MSG_STR_AOUT);
549*0Sstevel@tonic-gate 				lib = &crle.c_aslibpath;
550*0Sstevel@tonic-gate 			} else {
551*0Sstevel@tonic-gate 				str = MSG_ORIG(MSG_STR_ELF);
552*0Sstevel@tonic-gate 				lib = &crle.c_eslibpath;
553*0Sstevel@tonic-gate 			}
554*0Sstevel@tonic-gate 			if (addlib(&crle, lib, (const char *)optarg) != 0)
555*0Sstevel@tonic-gate 				error = 1;
556*0Sstevel@tonic-gate 			else if (crle.c_flags & CRLE_VERBOSE)
557*0Sstevel@tonic-gate 				(void) printf(MSG_INTL(MSG_DIA_TLIBPTH),
558*0Sstevel@tonic-gate 				    str, (const char *)optarg);
559*0Sstevel@tonic-gate 			break;
560*0Sstevel@tonic-gate 
561*0Sstevel@tonic-gate 		case 't':			/* search path type */
562*0Sstevel@tonic-gate 			if (strcmp((const char *)optarg,
563*0Sstevel@tonic-gate 			    MSG_ORIG(MSG_STR_ELF)) == 0)
564*0Sstevel@tonic-gate 				crle.c_flags &= ~CRLE_AOUT;
565*0Sstevel@tonic-gate 			else
566*0Sstevel@tonic-gate 				crle.c_flags |= CRLE_AOUT;
567*0Sstevel@tonic-gate 			break;
568*0Sstevel@tonic-gate 
569*0Sstevel@tonic-gate 		case 'u':
570*0Sstevel@tonic-gate 			break;
571*0Sstevel@tonic-gate 
572*0Sstevel@tonic-gate 		case 'v':
573*0Sstevel@tonic-gate 			break;
574*0Sstevel@tonic-gate 		}
575*0Sstevel@tonic-gate 	}
576*0Sstevel@tonic-gate 
577*0Sstevel@tonic-gate 	/*
578*0Sstevel@tonic-gate 	 * Now that we've generated as many file/directory processing errors
579*0Sstevel@tonic-gate 	 * as we can, return if any fatal error conditions occurred.
580*0Sstevel@tonic-gate 	 */
581*0Sstevel@tonic-gate 	if (error) {
582*0Sstevel@tonic-gate 		(void) unlink(crle.c_tempname);
583*0Sstevel@tonic-gate 		if (crle.c_flags & CRLE_CREAT) {
584*0Sstevel@tonic-gate 			(void) fprintf(stderr, MSG_INTL(MSG_GEN_CREATE),
585*0Sstevel@tonic-gate 			    crle.c_name, crle.c_confil);
586*0Sstevel@tonic-gate 		}
587*0Sstevel@tonic-gate 		return (1);
588*0Sstevel@tonic-gate 	}
589*0Sstevel@tonic-gate 
590*0Sstevel@tonic-gate 	/*
591*0Sstevel@tonic-gate 	 * Create a temporary configuration file.
592*0Sstevel@tonic-gate 	 */
593*0Sstevel@tonic-gate 	if (genconfig(&crle) != 0) {
594*0Sstevel@tonic-gate 		(void) unlink(crle.c_tempname);
595*0Sstevel@tonic-gate 		return (1);
596*0Sstevel@tonic-gate 	}
597*0Sstevel@tonic-gate 
598*0Sstevel@tonic-gate 	/*
599*0Sstevel@tonic-gate 	 * If dldump(3dl) images are required spawn a process to create them.
600*0Sstevel@tonic-gate 	 */
601*0Sstevel@tonic-gate 	if (crle.c_flags & CRLE_DUMP) {
602*0Sstevel@tonic-gate 		if (dump(&crle) != 0) {
603*0Sstevel@tonic-gate 			(void) unlink(crle.c_tempname);
604*0Sstevel@tonic-gate 			return (1);
605*0Sstevel@tonic-gate 		}
606*0Sstevel@tonic-gate 	}
607*0Sstevel@tonic-gate 
608*0Sstevel@tonic-gate 	/*
609*0Sstevel@tonic-gate 	 * Copy the finished temporary configuration file to its final home.
610*0Sstevel@tonic-gate 	 */
611*0Sstevel@tonic-gate 	if (updateconfig(&crle) != 0)
612*0Sstevel@tonic-gate 		return (1);
613*0Sstevel@tonic-gate 
614*0Sstevel@tonic-gate 	return (0);
615*0Sstevel@tonic-gate }
616