xref: /netbsd-src/external/bsd/openldap/dist/libraries/librewrite/config.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1*549b59edSchristos /*	$NetBSD: config.c,v 1.3 2021/08/14 16:14:58 christos Exp $	*/
24e6df137Slukem 
3d11b170bStron /* $OpenLDAP$ */
42de962bdSlukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
52de962bdSlukem  *
6*549b59edSchristos  * Copyright 2000-2021 The OpenLDAP Foundation.
72de962bdSlukem  * All rights reserved.
82de962bdSlukem  *
92de962bdSlukem  * Redistribution and use in source and binary forms, with or without
102de962bdSlukem  * modification, are permitted only as authorized by the OpenLDAP
112de962bdSlukem  * Public License.
122de962bdSlukem  *
132de962bdSlukem  * A copy of this license is available in the file LICENSE in the
142de962bdSlukem  * top-level directory of the distribution or, alternatively, at
152de962bdSlukem  * <http://www.OpenLDAP.org/license.html>.
162de962bdSlukem  */
172de962bdSlukem /* ACKNOWLEDGEMENT:
182de962bdSlukem  * This work was initially developed by Pierangelo Masarati for
192de962bdSlukem  * inclusion in OpenLDAP Software.
202de962bdSlukem  */
212de962bdSlukem 
222de962bdSlukem #include <portable.h>
232de962bdSlukem 
242de962bdSlukem #include "rewrite-int.h"
252de962bdSlukem #include "rewrite-map.h"
262de962bdSlukem 
272de962bdSlukem /*
282de962bdSlukem  * Parses a plugin map
292de962bdSlukem  */
302de962bdSlukem static int
312de962bdSlukem rewrite_parse_builtin_map(
322de962bdSlukem 		struct rewrite_info *info,
332de962bdSlukem 		const char *fname,
342de962bdSlukem 		int lineno,
352de962bdSlukem 		int argc,
362de962bdSlukem 		char **argv
372de962bdSlukem );
382de962bdSlukem 
392de962bdSlukem /*
402de962bdSlukem  * Parses a config line and takes actions to fit content in rewrite structure;
412de962bdSlukem  * lines handled are of the form:
422de962bdSlukem  *
432de962bdSlukem  *      rewriteEngine 		{on|off}
442de962bdSlukem  *      rewriteMaxPasses        numPasses [numPassesPerRule]
452de962bdSlukem  *      rewriteContext 		contextName [alias aliasedContextName]
462de962bdSlukem  *      rewriteRule 		pattern substPattern [ruleFlags]
472de962bdSlukem  *      rewriteMap 		mapType mapName [mapArgs]
482de962bdSlukem  *      rewriteParam		paramName paramValue
492de962bdSlukem  */
502de962bdSlukem int
rewrite_parse(struct rewrite_info * info,const char * fname,int lineno,int argc,char ** argv)512de962bdSlukem rewrite_parse(
522de962bdSlukem 		struct rewrite_info *info,
532de962bdSlukem 		const char *fname,
542de962bdSlukem 		int lineno,
552de962bdSlukem 		int argc,
562de962bdSlukem 		char **argv
572de962bdSlukem )
582de962bdSlukem {
592de962bdSlukem 	int rc = -1;
602de962bdSlukem 
612de962bdSlukem 	assert( info != NULL );
622de962bdSlukem 	assert( fname != NULL );
632de962bdSlukem 	assert( argv != NULL );
642de962bdSlukem 	assert( argc > 0 );
652de962bdSlukem 
662de962bdSlukem 	/*
672de962bdSlukem 	 * Switch on the rewrite engine
682de962bdSlukem 	 */
692de962bdSlukem 	if ( strcasecmp( argv[ 0 ], "rewriteEngine" ) == 0 ) {
702de962bdSlukem 		if ( argc < 2 ) {
712de962bdSlukem 			Debug( LDAP_DEBUG_ANY,
72*549b59edSchristos 					"[%s:%d] rewriteEngine needs 'state'\n",
73*549b59edSchristos 					fname, lineno );
742de962bdSlukem 			return -1;
752de962bdSlukem 
762de962bdSlukem 		} else if ( argc > 2 ) {
772de962bdSlukem 			Debug( LDAP_DEBUG_ANY,
782de962bdSlukem 					"[%s:%d] extra fields in rewriteEngine"
79*549b59edSchristos 					" will be discarded\n",
80*549b59edSchristos 					fname, lineno );
812de962bdSlukem 		}
822de962bdSlukem 
832de962bdSlukem 		if ( strcasecmp( argv[ 1 ], "on" ) == 0 ) {
842de962bdSlukem 			info->li_state = REWRITE_ON;
852de962bdSlukem 
862de962bdSlukem 		} else if ( strcasecmp( argv[ 1 ], "off" ) == 0 ) {
872de962bdSlukem 			info->li_state = REWRITE_OFF;
882de962bdSlukem 
892de962bdSlukem 		} else {
902de962bdSlukem 			Debug( LDAP_DEBUG_ANY,
912de962bdSlukem 					"[%s:%d] unknown 'state' in rewriteEngine;"
92*549b59edSchristos 					" assuming 'on'\n",
93*549b59edSchristos 					fname, lineno );
942de962bdSlukem 			info->li_state = REWRITE_ON;
952de962bdSlukem 		}
962de962bdSlukem 		rc = REWRITE_SUCCESS;
972de962bdSlukem 
982de962bdSlukem 	/*
992de962bdSlukem 	 * Alter max passes
1002de962bdSlukem 	 */
1012de962bdSlukem 	} else if ( strcasecmp( argv[ 0 ], "rewriteMaxPasses" ) == 0 ) {
1022de962bdSlukem 		if ( argc < 2 ) {
1032de962bdSlukem 			Debug( LDAP_DEBUG_ANY,
104*549b59edSchristos 					"[%s:%d] rewriteMaxPasses needs 'value'\n",
105*549b59edSchristos 					fname, lineno );
1062de962bdSlukem 			return -1;
1072de962bdSlukem 		}
1082de962bdSlukem 
1092de962bdSlukem 		if ( lutil_atoi( &info->li_max_passes, argv[ 1 ] ) != 0 ) {
1102de962bdSlukem 			Debug( LDAP_DEBUG_ANY,
1112de962bdSlukem 					"[%s:%d] unable to parse rewriteMaxPasses=\"%s\"\n",
1122de962bdSlukem 					fname, lineno, argv[ 1 ] );
1132de962bdSlukem 			return -1;
1142de962bdSlukem 		}
1152de962bdSlukem 
1162de962bdSlukem 		if ( info->li_max_passes <= 0 ) {
1172de962bdSlukem 			Debug( LDAP_DEBUG_ANY,
1182de962bdSlukem 					"[%s:%d] negative or null rewriteMaxPasses\n",
119*549b59edSchristos 					fname, lineno );
1202de962bdSlukem 			return -1;
1212de962bdSlukem 		}
1222de962bdSlukem 
1232de962bdSlukem 		if ( argc > 2 ) {
1242de962bdSlukem 			if ( lutil_atoi( &info->li_max_passes_per_rule, argv[ 2 ] ) != 0 ) {
1252de962bdSlukem 				Debug( LDAP_DEBUG_ANY,
1262de962bdSlukem 						"[%s:%d] unable to parse rewriteMaxPassesPerRule=\"%s\"\n",
1272de962bdSlukem 						fname, lineno, argv[ 2 ] );
1282de962bdSlukem 				return -1;
1292de962bdSlukem 			}
1302de962bdSlukem 
1312de962bdSlukem 			if ( info->li_max_passes_per_rule <= 0 ) {
1322de962bdSlukem 				Debug( LDAP_DEBUG_ANY,
1332de962bdSlukem 						"[%s:%d] negative or null rewriteMaxPassesPerRule\n",
134*549b59edSchristos 						fname, lineno );
1352de962bdSlukem 				return -1;
1362de962bdSlukem 			}
1372de962bdSlukem 
1382de962bdSlukem 		} else {
1392de962bdSlukem 			info->li_max_passes_per_rule = info->li_max_passes;
1402de962bdSlukem 		}
1412de962bdSlukem 		rc = REWRITE_SUCCESS;
1422de962bdSlukem 
1432de962bdSlukem 	/*
1442de962bdSlukem 	 * Start a new rewrite context and set current context
1452de962bdSlukem 	 */
1462de962bdSlukem 	} else if ( strcasecmp( argv[ 0 ], "rewriteContext" ) == 0 ) {
1472de962bdSlukem 		if ( argc < 2 ) {
1482de962bdSlukem 			Debug( LDAP_DEBUG_ANY,
149*549b59edSchristos 					"[%s:%d] rewriteContext needs 'name'\n",
150*549b59edSchristos 					fname, lineno );
1512de962bdSlukem 			return -1;
1522de962bdSlukem 		}
1532de962bdSlukem 
1542de962bdSlukem 		/*
1552de962bdSlukem 		 * Checks for existence (lots of contexts should be
1562de962bdSlukem 		 * available by default ...)
1572de962bdSlukem 		 */
1582de962bdSlukem 		 rewrite_int_curr_context = rewrite_context_find( info, argv[ 1 ] );
1592de962bdSlukem 		 if ( rewrite_int_curr_context == NULL ) {
1602de962bdSlukem 			 rewrite_int_curr_context = rewrite_context_create( info,
1612de962bdSlukem 					 argv[ 1 ] );
1622de962bdSlukem 		 }
1632de962bdSlukem 		 if ( rewrite_int_curr_context == NULL ) {
1642de962bdSlukem 			 return -1;
1652de962bdSlukem 		 }
1662de962bdSlukem 
1672de962bdSlukem 		 if ( argc > 2 ) {
1682de962bdSlukem 
1692de962bdSlukem 			 /*
1702de962bdSlukem 			  * A context can alias another (e.g., the `builtin'
1712de962bdSlukem 			  * contexts for backend operations, if not defined,
1722de962bdSlukem 			  * alias the `default' rewrite context (with the
1732de962bdSlukem 			  * notable exception of the searchResult context,
1742de962bdSlukem 			  * which can be undefined)
1752de962bdSlukem 			  */
1762de962bdSlukem 			 if ( strcasecmp( argv[ 2 ], "alias" ) == 0 ) {
1772de962bdSlukem 				 struct rewrite_context *aliased;
1782de962bdSlukem 
1792de962bdSlukem 				 if ( argc == 3 ) {
1802de962bdSlukem 					 Debug( LDAP_DEBUG_ANY,
1812de962bdSlukem 							 "[%s:%d] rewriteContext"
1822de962bdSlukem 							 " needs 'name' after"
183*549b59edSchristos 							 " 'alias'\n",
184*549b59edSchristos 							 fname, lineno );
1852de962bdSlukem 					 return -1;
1862de962bdSlukem 
1872de962bdSlukem 				 } else if ( argc > 4 ) {
1882de962bdSlukem 					 Debug( LDAP_DEBUG_ANY,
1892de962bdSlukem 							 "[%s:%d] extra fields in"
1902de962bdSlukem 							 " rewriteContext"
1912de962bdSlukem 							 " after aliased name"
1922de962bdSlukem 							 " will be"
193*549b59edSchristos 							 " discarded\n",
194*549b59edSchristos 							 fname, lineno );
1952de962bdSlukem 				 }
1962de962bdSlukem 
1972de962bdSlukem 				 aliased = rewrite_context_find( info,
1982de962bdSlukem 						 argv[ 3 ] );
1992de962bdSlukem 				 if ( aliased == NULL ) {
2002de962bdSlukem 					 Debug( LDAP_DEBUG_ANY,
2012de962bdSlukem 							 "[%s:%d] aliased"
2022de962bdSlukem 							 " rewriteContext '%s'"
2032de962bdSlukem 							 " does not exists\n",
2042de962bdSlukem 							 fname, lineno,
2052de962bdSlukem 							 argv[ 3 ] );
2062de962bdSlukem 					 return -1;
2072de962bdSlukem 				 }
2082de962bdSlukem 
2092de962bdSlukem 				 rewrite_int_curr_context->lc_alias = aliased;
2102de962bdSlukem 				 rewrite_int_curr_context = aliased;
2112de962bdSlukem 
2122de962bdSlukem 			 } else {
2132de962bdSlukem 				 Debug( LDAP_DEBUG_ANY,
2142de962bdSlukem 						 "[%s:%d] extra fields"
2152de962bdSlukem 						 " in rewriteContext"
216*549b59edSchristos 						 " will be discarded\n",
217*549b59edSchristos 						 fname, lineno );
2182de962bdSlukem 			 }
2192de962bdSlukem 		 }
2202de962bdSlukem 		 rc = REWRITE_SUCCESS;
2212de962bdSlukem 
2222de962bdSlukem 	/*
2232de962bdSlukem 	 * Compile a rule in current context
2242de962bdSlukem 	 */
2252de962bdSlukem 	} else if ( strcasecmp( argv[ 0 ], "rewriteRule" ) == 0 ) {
2262de962bdSlukem 		if ( argc < 3 ) {
2272de962bdSlukem 			Debug( LDAP_DEBUG_ANY,
2282de962bdSlukem 					"[%s:%d] rewriteRule needs 'pattern'"
229*549b59edSchristos 					" 'subst' ['flags']\n",
230*549b59edSchristos 					fname, lineno );
2312de962bdSlukem 			return -1;
2322de962bdSlukem 
2332de962bdSlukem 		} else if ( argc > 4 ) {
2342de962bdSlukem 			Debug( LDAP_DEBUG_ANY,
2352de962bdSlukem 					"[%s:%d] extra fields in rewriteRule"
236*549b59edSchristos 					" will be discarded\n",
237*549b59edSchristos 					fname, lineno );
2382de962bdSlukem 		}
2392de962bdSlukem 
2402de962bdSlukem 		if ( rewrite_int_curr_context == NULL ) {
2412de962bdSlukem 			Debug( LDAP_DEBUG_ANY,
2422de962bdSlukem 					"[%s:%d] rewriteRule outside a"
243*549b59edSchristos 					" context; will add to default\n",
244*549b59edSchristos 					fname, lineno );
2452de962bdSlukem 			rewrite_int_curr_context = rewrite_context_find( info,
2462de962bdSlukem 					REWRITE_DEFAULT_CONTEXT );
2472de962bdSlukem 
2482de962bdSlukem 			/*
2492de962bdSlukem 			 * Default context MUST exist in a properly initialized
2502de962bdSlukem 			 * struct rewrite_info
2512de962bdSlukem 			 */
2522de962bdSlukem 			assert( rewrite_int_curr_context != NULL );
2532de962bdSlukem 		}
2542de962bdSlukem 
2552de962bdSlukem 		rc = rewrite_rule_compile( info, rewrite_int_curr_context, argv[ 1 ],
2562de962bdSlukem 				argv[ 2 ], ( argc == 4 ? argv[ 3 ] : "" ) );
2572de962bdSlukem 
2582de962bdSlukem 	/*
2592de962bdSlukem 	 * Add a plugin map to the map tree
2602de962bdSlukem 	 */
2612de962bdSlukem 	} else if ( strcasecmp( argv[ 0 ], "rewriteMap" ) == 0 ) {
2622de962bdSlukem 		if ( argc < 3 ) {
2632de962bdSlukem 			Debug( LDAP_DEBUG_ANY,
2642de962bdSlukem 					"[%s:%d] rewriteMap needs at least 'type'"
265*549b59edSchristos 					" and 'name' ['args']\n",
266*549b59edSchristos 					fname, lineno );
2672de962bdSlukem 			return -1;
2682de962bdSlukem 		}
2692de962bdSlukem 
2702de962bdSlukem 		rc = rewrite_parse_builtin_map( info, fname, lineno,
2712de962bdSlukem 				argc, argv );
2722de962bdSlukem 
2732de962bdSlukem 	/*
2742de962bdSlukem 	 * Set the value of a global scope parameter
2752de962bdSlukem 	 */
2762de962bdSlukem 	} else if ( strcasecmp( argv[ 0 ], "rewriteParam" ) == 0 ) {
2772de962bdSlukem 		if ( argc < 3 ) {
2782de962bdSlukem 			Debug( LDAP_DEBUG_ANY,
2792de962bdSlukem 					"[%s:%d] rewriteParam needs 'name'"
280*549b59edSchristos 					" and 'value'\n",
281*549b59edSchristos 					fname, lineno );
2822de962bdSlukem 			return -1;
2832de962bdSlukem 		}
2842de962bdSlukem 
2852de962bdSlukem 		rc = rewrite_param_set( info, argv[ 1 ], argv[ 2 ] );
2862de962bdSlukem 
2872de962bdSlukem 	/*
2882de962bdSlukem 	 * Error
2892de962bdSlukem 	 */
2902de962bdSlukem 	} else {
2912de962bdSlukem 		Debug( LDAP_DEBUG_ANY,
2922de962bdSlukem 				"[%s:%d] unknown command '%s'\n",
293*549b59edSchristos 				fname, lineno, argv[ 0 ] );
2942de962bdSlukem 		return -1;
2952de962bdSlukem 	}
2962de962bdSlukem 
2972de962bdSlukem 	return rc;
2982de962bdSlukem }
2992de962bdSlukem 
3002de962bdSlukem /*
3012de962bdSlukem  * Compares two maps
3022de962bdSlukem  */
3032de962bdSlukem static int
rewrite_builtin_map_cmp(const void * c1,const void * c2)3042de962bdSlukem rewrite_builtin_map_cmp(
3052de962bdSlukem 		const void *c1,
3062de962bdSlukem                 const void *c2
3072de962bdSlukem )
3082de962bdSlukem {
3092de962bdSlukem 	const struct rewrite_builtin_map *m1, *m2;
3102de962bdSlukem 
3112de962bdSlukem         m1 = ( const struct rewrite_builtin_map * )c1;
3122de962bdSlukem         m2 = ( const struct rewrite_builtin_map * )c2;
3132de962bdSlukem 
3142de962bdSlukem         assert( m1 != NULL );
3152de962bdSlukem         assert( m2 != NULL );
3162de962bdSlukem         assert( m1->lb_name != NULL );
3172de962bdSlukem         assert( m2->lb_name != NULL );
3182de962bdSlukem 
3192de962bdSlukem         return strcasecmp( m1->lb_name, m2->lb_name );
3202de962bdSlukem }
3212de962bdSlukem 
3222de962bdSlukem /*
3232de962bdSlukem  * Duplicate map ?
3242de962bdSlukem  */
3252de962bdSlukem static int
rewrite_builtin_map_dup(void * c1,void * c2)3262de962bdSlukem rewrite_builtin_map_dup(
3272de962bdSlukem 	                void *c1,
3282de962bdSlukem 	                void *c2
3292de962bdSlukem )
3302de962bdSlukem {
3312de962bdSlukem         struct rewrite_builtin_map *m1, *m2;
3322de962bdSlukem 
3332de962bdSlukem         m1 = ( struct rewrite_builtin_map * )c1;
3342de962bdSlukem         m2 = ( struct rewrite_builtin_map * )c2;
3352de962bdSlukem 
3362de962bdSlukem         assert( m1 != NULL );
3372de962bdSlukem         assert( m2 != NULL );
3382de962bdSlukem         assert( m1->lb_name != NULL );
3392de962bdSlukem         assert( m2->lb_name != NULL );
3402de962bdSlukem 
3412de962bdSlukem         return ( strcasecmp( m1->lb_name, m2->lb_name ) == 0 ? -1 : 0 );
3422de962bdSlukem }
3432de962bdSlukem 
3442de962bdSlukem /*
3452de962bdSlukem  * Adds a map to the info map tree
3462de962bdSlukem  */
3472de962bdSlukem static int
rewrite_builtin_map_insert(struct rewrite_info * info,struct rewrite_builtin_map * map)3482de962bdSlukem rewrite_builtin_map_insert(
3492de962bdSlukem 		struct rewrite_info *info,
3502de962bdSlukem 		struct rewrite_builtin_map *map
3512de962bdSlukem )
3522de962bdSlukem {
3532de962bdSlukem 	/*
3542de962bdSlukem 	 * May need a mutex?
3552de962bdSlukem 	 */
356*549b59edSchristos 	return ldap_avl_insert( &info->li_maps, ( caddr_t )map,
3572de962bdSlukem 			rewrite_builtin_map_cmp,
3582de962bdSlukem 		       	rewrite_builtin_map_dup );
3592de962bdSlukem }
3602de962bdSlukem 
3612de962bdSlukem /*
3622de962bdSlukem  * Retrieves a map
3632de962bdSlukem  */
3642de962bdSlukem struct rewrite_builtin_map *
rewrite_builtin_map_find(struct rewrite_info * info,const char * name)3652de962bdSlukem rewrite_builtin_map_find(
3662de962bdSlukem 		struct rewrite_info *info,
3672de962bdSlukem 		const char *name
3682de962bdSlukem )
3692de962bdSlukem {
3702de962bdSlukem 	struct rewrite_builtin_map tmp;
3712de962bdSlukem 
3722de962bdSlukem 	assert( info != NULL );
3732de962bdSlukem 	assert( name != NULL );
3742de962bdSlukem 
3752de962bdSlukem 	tmp.lb_name = ( char * )name;
3762de962bdSlukem 
377*549b59edSchristos 	return ( struct rewrite_builtin_map * )ldap_avl_find( info->li_maps,
3782de962bdSlukem 			( caddr_t )&tmp, rewrite_builtin_map_cmp );
3792de962bdSlukem }
3802de962bdSlukem 
3812de962bdSlukem /*
3822de962bdSlukem  * Parses a plugin map
3832de962bdSlukem  */
3842de962bdSlukem static int
rewrite_parse_builtin_map(struct rewrite_info * info,const char * fname,int lineno,int argc,char ** argv)3852de962bdSlukem rewrite_parse_builtin_map(
3862de962bdSlukem 		struct rewrite_info *info,
3872de962bdSlukem 		const char *fname,
3882de962bdSlukem 		int lineno,
3892de962bdSlukem 		int argc,
3902de962bdSlukem 		char **argv
3912de962bdSlukem )
3922de962bdSlukem {
3932de962bdSlukem 	struct rewrite_builtin_map *map;
3942de962bdSlukem 
3952de962bdSlukem #define MAP_TYPE	1
3962de962bdSlukem #define MAP_NAME	2
3972de962bdSlukem 
3982de962bdSlukem 	assert( info != NULL );
3992de962bdSlukem 	assert( fname != NULL );
4002de962bdSlukem 	assert( argc > 2 );
4012de962bdSlukem 	assert( argv != NULL );
4022de962bdSlukem 	assert( strcasecmp( argv[ 0 ], "rewriteMap" ) == 0 );
4032de962bdSlukem 
4042de962bdSlukem 	map = calloc( sizeof( struct rewrite_builtin_map ), 1 );
4052de962bdSlukem 	if ( map == NULL ) {
4062de962bdSlukem 		return REWRITE_ERR;
4072de962bdSlukem 	}
4082de962bdSlukem 
4092de962bdSlukem 	map->lb_name = strdup( argv[ MAP_NAME ] );
4102de962bdSlukem 	if ( map->lb_name == NULL ) {
4112de962bdSlukem 		free( map );
4122de962bdSlukem 		return REWRITE_ERR;
4132de962bdSlukem 	}
4142de962bdSlukem 
4152de962bdSlukem 	/*
4162de962bdSlukem 	 * Built-in ldap map
4172de962bdSlukem 	 */
4182de962bdSlukem 	if (( map->lb_mapper = rewrite_mapper_find( argv[ MAP_TYPE ] ))) {
4192de962bdSlukem 		map->lb_type = REWRITE_BUILTIN_MAP;
4202de962bdSlukem 
4212de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
4222de962bdSlukem 		if ( ldap_pvt_thread_mutex_init( & map->lb_mutex ) ) {
4232de962bdSlukem 			free( map->lb_name );
4242de962bdSlukem 			free( map );
4252de962bdSlukem 			return REWRITE_ERR;
4262de962bdSlukem 		}
4272de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
4282de962bdSlukem 
4292de962bdSlukem 		map->lb_private = map->lb_mapper->rm_config( fname, lineno,
4302de962bdSlukem 				argc - 3, argv + 3 );
4312de962bdSlukem 
4322de962bdSlukem 	/*
4332de962bdSlukem 	 * Error
4342de962bdSlukem 	 */
4352de962bdSlukem 	} else {
4362de962bdSlukem 		free( map );
437*549b59edSchristos 		Debug( LDAP_DEBUG_ANY, "[%s:%d] unknown map type\n",
438*549b59edSchristos 				fname, lineno );
4392de962bdSlukem 		return -1;
4402de962bdSlukem 	}
4412de962bdSlukem 
4422de962bdSlukem 	return rewrite_builtin_map_insert( info, map );
4432de962bdSlukem }
444