config.c revision 2352:9cdfed81bb1c
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28#include	<stdlib.h>
29#include	<sys/types.h>
30#include	<string.h>
31#include	"rtc.h"
32#include	"_conv.h"
33#include	"config_msg.h"
34
35#define	FEATSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
36		MSG_CONF_EDLIBPATH_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
37		MSG_CONF_ESLIBPATH_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
38		MSG_CONF_ADLIBPATH_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
39		MSG_CONF_ASLIBPATH_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
40		MSG_CONF_DIRCFG_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
41		MSG_CONF_OBJALT_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
42		MSG_CONF_MEMRESV_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
43		MSG_CONF_ENVS_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
44		MSG_CONF_FLTR_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
45		CONV_INV_STRSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
46
47/*
48 * String conversion routine for configuration file information.
49 */
50const char *
51conv_config_feat(int features)
52{
53	static	char	string[FEATSZ];
54	static Val_desc	vda[] = {
55		{ CONF_EDLIBPATH,	MSG_ORIG(MSG_CONF_EDLIBPATH) },
56		{ CONF_ESLIBPATH,	MSG_ORIG(MSG_CONF_ESLIBPATH) },
57		{ CONF_ADLIBPATH,	MSG_ORIG(MSG_CONF_ADLIBPATH) },
58		{ CONF_ASLIBPATH,	MSG_ORIG(MSG_CONF_ASLIBPATH) },
59		{ CONF_DIRCFG,		MSG_ORIG(MSG_CONF_DIRCFG) },
60		{ CONF_OBJALT,		MSG_ORIG(MSG_CONF_OBJALT) },
61		{ CONF_MEMRESV,		MSG_ORIG(MSG_CONF_MEMRESV) },
62		{ CONF_ENVS,		MSG_ORIG(MSG_CONF_ENVS) },
63		{ CONF_FLTR,		MSG_ORIG(MSG_CONF_FLTR) },
64		{ 0,			0 }
65	};
66	static CONV_EXPN_FIELD_ARG conv_arg = { string, sizeof (string), vda };
67
68	conv_arg.oflags = conv_arg.rflags = features;
69	(void) conv_expn_field(&conv_arg);
70
71	return ((const char *)string);
72}
73
74#define	FLAGSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
75		MSG_CONF_DIRENT_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
76		MSG_CONF_ALLENTS_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
77		MSG_CONF_NOEXIST_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
78		MSG_CONF_EXEC_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
79		MSG_CONF_ALTER_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
80		MSG_CONF_OPTIONAL_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
81		MSG_CONF_DUMP_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
82		MSG_CONF_REALPATH_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
83		MSG_CONF_NOALTER_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
84		MSG_CONF_GROUP_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
85		MSG_CONF_APP_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
86		MSG_CONF_CMDLINE_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
87		MSG_CONF_FILTER_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
88		MSG_CONF_FILTEE_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
89		CONV_INV_STRSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
90
91/*
92 * String conversion routine for object flags.
93 */
94const char *
95conv_config_obj(ushort_t flags)
96{
97	static char	string[FLAGSZ];
98	static Val_desc vda[] = {
99		{ RTC_OBJ_DIRENT,	MSG_ORIG(MSG_CONF_DIRENT) },
100		{ RTC_OBJ_ALLENTS,	MSG_ORIG(MSG_CONF_ALLENTS) },
101		{ RTC_OBJ_NOEXIST,	MSG_ORIG(MSG_CONF_NOEXIST) },
102		{ RTC_OBJ_EXEC,		MSG_ORIG(MSG_CONF_EXEC) },
103		{ RTC_OBJ_ALTER,	MSG_ORIG(MSG_CONF_ALTER) },
104		{ RTC_OBJ_DUMP,		MSG_ORIG(MSG_CONF_DUMP) },
105		{ RTC_OBJ_NOALTER,	MSG_ORIG(MSG_CONF_NOALTER) },
106		{ RTC_OBJ_REALPTH,	MSG_ORIG(MSG_CONF_REALPATH) },
107		{ RTC_OBJ_GROUP,	MSG_ORIG(MSG_CONF_GROUP) },
108		{ RTC_OBJ_APP,		MSG_ORIG(MSG_CONF_APP) },
109		{ RTC_OBJ_CMDLINE,	MSG_ORIG(MSG_CONF_CMDLINE) },
110		{ RTC_OBJ_FILTER,	MSG_ORIG(MSG_CONF_FILTER) },
111		{ RTC_OBJ_FILTEE,	MSG_ORIG(MSG_CONF_FILTEE) },
112		{ 0,			0 }
113	};
114	static const char *leading_str_arr[2];
115	static CONV_EXPN_FIELD_ARG conv_arg = { string, sizeof (string), vda,
116		leading_str_arr };
117
118	const char **lstr = leading_str_arr;
119
120	if ((flags == 0) || (flags == RTC_OBJ_OPTINAL))
121		return (MSG_ORIG(MSG_GBL_NULL));
122
123	conv_arg.rflags = flags;
124
125	/*
126	 * Print an alternative-optional object simply as optional.
127	 */
128	if ((flags & (RTC_OBJ_ALTER | RTC_OBJ_OPTINAL)) ==
129	    (RTC_OBJ_ALTER | RTC_OBJ_OPTINAL)) {
130		*lstr++ = MSG_ORIG(MSG_CONF_OPTIONAL);
131		conv_arg.rflags &= ~(RTC_OBJ_ALTER | RTC_OBJ_OPTINAL);
132	}
133	*lstr = NULL;
134	conv_arg.oflags = conv_arg.rflags &= ~RTC_OBJ_OPTINAL;
135
136	(void) conv_expn_field(&conv_arg);
137
138	return ((const char *)string);
139}
140
141/*
142 * Determine whether and old pathname exists within a search path string,
143 * without a new pathname, i.e., does the search path string contain "/usr/lib"
144 * but not "/lib".  If so, add the new pathname before the old pathname.  For
145 * example, convert:
146 *
147 *	/local/lib:/opt/sfw/lib:/usr/lib
148 * to:
149 *	/local/lib:/opt/sfw/lib:/lib:/usr/lib
150 */
151const char *
152conv_config_upm(const char *str, const char *old, const char *new,
153    size_t newlen)
154{
155	const char	*curstr, *ptr;
156	const char	*curold = 0, *curnew = 0;
157	const char	*ptrold = old, * ptrnew = new;
158	int		chkold = 1, chknew = 1;
159
160	for (curstr = ptr = str; *ptr; ptr++) {
161		if (*ptr == ':') {
162			/*
163			 * We've come to the end of a token within the string.
164			 */
165			if ((uintptr_t)ptr - (uintptr_t)curstr) {
166				/*
167				 * If the old or new string checking is still
168				 * enabled, we've found a match.
169				 */
170				if (chkold)
171					curold = curstr;
172				if (chknew)
173					curnew = curstr;
174			}
175			curstr = (char *)(ptr + 1);
176
177			/*
178			 * If an old or new string hasn't yet been matched,
179			 * re-enable the checking for either.
180			 */
181			if (curold == 0) {
182				ptrold = old;
183				chkold = 1;
184			}
185			if (curnew == 0) {
186				ptrnew = new;
187				chknew = 1;
188			}
189			continue;
190		}
191
192		/*
193		 * Determine if the current token matches the old or new string.
194		 * If not, disable the checking for each string.
195		 */
196		if (chkold && (*ptr != *ptrold++))
197			chkold = 0;
198		if (chknew && (*ptr != *ptrnew++))
199			chknew = 0;
200	}
201
202	/*
203	 * We've come to the end of the string, if the old or new string
204	 * checking is still enabled, we've found a match.
205	 */
206	if ((uintptr_t)ptr - (uintptr_t)curstr) {
207		if (chkold)
208			curold = curstr;
209		if (chknew)
210			curnew = curstr;
211	}
212
213	/*
214	 * If an old string hasn't been found, or it has and a new string has
215	 * been found, return the original string.
216	 */
217	if ((curold == 0) || curnew)
218		return (str);
219	else {
220		char	*newstr;
221		size_t	len;
222
223		/*
224		 * Allocate a new string, enlarged to accommodate the new string
225		 * that will be inserted, and an associated separator.
226		 */
227		if ((curstr = malloc(newlen + 2 +
228		    (uintptr_t)ptr - (uintptr_t)str)) == 0)
229			return (str);
230
231		newstr = (char *)curstr;
232		for (len = (uintptr_t)curold - (uintptr_t)str; len; len--)
233			*(newstr++) = *(str++);		/* copy up to */
234							/*    insertion point */
235		for (len = newlen; len; len--)
236			*(newstr++) = *(new++);		/* add new string and */
237		*(newstr++) = ':';			/*    separator */
238		for (len = (uintptr_t)ptr - (uintptr_t)str; len; len--)
239			*(newstr++) = *(str++);		/* add remaining */
240		*(newstr++) = '\0';			/*	string */
241
242		return (curstr);
243	}
244}
245