Exemple #1
0
void *
malloc(size_t size)
{
  void * (* libc_malloc)(size_t) = (void *(*)(size_t))dlsym(RTLD_NEXT, "malloc");
  if (enabled.load()) {
    return custom_malloc(size);
  }
  return libc_malloc(size);
}
Exemple #2
0
extern "C" void* malloc(size_t sz) {
    static void *(*libc_malloc)(size_t) = (void* (*)(size_t))dlsym(RTLD_NEXT, "malloc");
    void* r = libc_malloc(sz);
    if (!recursive) {
        recursive = true;
        printf("\nmalloc %p\n", r);
        recursive = false;
    }
    return r;
}
Exemple #3
0
void *malloc(size_t size)
{
	if (inside_init)
		return libc_malloc(size);
	
	if (!alloc_handle)
		contest_alloc_init();

	void *addr = alloc_malloc(size);
	contest_tracking();

	return addr;
}
Exemple #4
0
/* add to the front: LRU */
static int
add_concell(struct __nsw_switchconfig *cfp)
{
	struct cons_cell *cp;

	if (cfp == NULL)
		return (1);
	if ((cp = libc_malloc(sizeof (struct cons_cell))) == NULL)
		return (1);
	cp->sw = cfp;
	cp->next = concell_list;
	concell_list = cp;
	return (0);
}
List* createList(){
	if (libc_malloc == NULL){
		libc_malloc = dlsym(RTLD_NEXT,"malloc");
		if ((error = dlerror()) != NULL)  {
        fprintf(stderr, "%s\n", error);
        exit(EXIT_FAILURE);
    }
	}
	List * list = libc_malloc(sizeof(List));
	if (list != NULL){
		list -> first = NULL;
	}
	return list;
}
Node* createNode(void* ptr, size_t size){
	if (libc_malloc == NULL){
		libc_malloc = dlsym(RTLD_NEXT,"malloc");
		if ((error = dlerror()) != NULL)  {
        fprintf(stderr, "%s\n", error);
        exit(EXIT_FAILURE);
    }
	}
	Node* n = libc_malloc(sizeof(Node));
	n -> ptr = ptr;
	n -> size = size;
	n -> next = NULL;
	//printf("Saved %p : %zd\n", ptr, size);
	return n;
}
Exemple #7
0
void* malloc(size_t sz)
{
	cpu_AtomicAdd(&alloc_count, 1);

	static void *(*libc_malloc)(size_t);
	if (libc_malloc == NULL)
	{
		alloc_has_called_dlsym = true;
		libc_malloc = (void *(*)(size_t)) dlsym(RTLD_NEXT, "malloc");
	}
	void* ret = libc_malloc(sz);
#ifdef ALLOC_DEBUG
	printf("### malloc(%d) = %p\n", sz, ret);
#endif
	return ret;
}
Exemple #8
0
struct locdata *
__locdata_alloc(const char *name, size_t memsz)
{
	struct locdata *ldata;

	if ((ldata = lmalloc(sizeof (*ldata))) == NULL) {
		return (NULL);
	}
	if ((ldata->l_data[0] = libc_malloc(memsz)) == NULL) {
		lfree(ldata, sizeof (*ldata));
		errno = ENOMEM;
		return (NULL);
	}
	(void) strlcpy(ldata->l_lname, name, sizeof (ldata->l_lname));

	return (ldata);
}
Exemple #9
0
static void
_mnewblock(void)
{
	struct hdr *hdrp;
	ANCHOR	*newanchp;
	ANCHOR	*p;

					/* get anchor And block, together */
	p = libc_malloc(GETTHISMUCH);
	if (p == NULL) {
		perror("mcount(mnewblock)");
		return;
	}

	newanchp = p;
	hdrp = (struct hdr *)(p + 1);

					/* initialize 1st region to dflts */
	hdrp->lpc = 0;
	hdrp->hpc = 0;
	hdrp->nfns = THISMANYFCNS;

					/* link anchor+block into chain */
	newanchp->monBuffer = hdrp;		/* new, down. */
	newanchp->next  = NULL;			/* new, forward to NULL. */
	newanchp->prior = curAnchor;		/* new, backward. */
	if (curAnchor != NULL)
		curAnchor->next = newanchp;	/* old, forward to new. */
	newanchp->flags = 0;		/* note that it has NO histgm area */

					/* got it - enable use by mcount() */
	countbase  = (char *)hdrp + sizeof (struct hdr);
	_countlimit = countbase + (THISMANYFCNS * sizeof (struct cnt));

	newanchp->histSize = 0;	/* (set size of region 3.. to 0) */


	curAnchor = newanchp;		/* make latest addition, cur anchor */
}
Node * findInList(List * list, void * ptr){
	if (list == NULL || ptr == NULL){
		return NULL;
	}

	Node * curr = list -> first;
	while(curr != NULL){
		if (curr -> ptr == ptr){
			return curr;
		}
		// Could paging affect this?
		else if ((ptr - curr -> ptr) > 0 && ((ptr - curr -> ptr) < curr -> size)){
			// pointer falls within range. return a node with ptr and remaining size
			Node * tempNode = libc_malloc(sizeof(Node));
			tempNode -> ptr = ptr;
			tempNode -> size = curr -> size - (ptr - curr -> ptr);
			return tempNode;
		}
		curr = curr -> next;
	}
	return curr;
}
void *malloc(size_t size)
{
	void *p = NULL;

	if (libc_malloc == NULL) 
		SAVE_LIBC_FUNC(libc_malloc, "malloc");

	init_env();

	if (mem_allocated + size <= mem_threshold) {
		p = libc_malloc(size);
	} else {
		log("Restricting malloc of %zu bytes\n", size);
		errno = ENOMEM;
		return NULL;
	}

	if (!no_hook) 
		account_alloc(p, size);

	return p;
}
Exemple #12
0
/*
 * int (*alowpc)(), (*ahighpc)(); boundaries of text to be monitored
 * WORD *buffer;	ptr to space for monitor data(WORDs)
 * size_t bufsize;	size of above space(in WORDs)
 * size_t nfunc;	max no. of functions whose calls are counted
 *			(default nfunc is 300 on PDP11, 600 on others)
 */
void
monitor(int (*alowpc)(void), int (*ahighpc)(void), WORD *buffer,
	size_t bufsize, size_t nfunc)
{
	uint_t scale;
	long text;
	char *s;
	struct hdr *hdrp;
	ANCHOR  *newanchp;
	size_t	ssiz;
	int error;
	char	*lowpc = (char *)alowpc;
	char	*highpc = (char *)ahighpc;

	lmutex_lock(&mon_lock);

	if (lowpc == NULL) {		/* true only at the end */
		error = 0;
		if (curAnchor != NULL) { /* if anything was collected!.. */
			profil(NULL, 0, 0, 0);
			if (writeBlocks() == 0)
				error = errno;
		}
		lmutex_unlock(&mon_lock);
		if (error) {
			errno = error;
			perror(mon_out);
		}
		return;
	}

	/*
	 * Ok - they want to submit a block for immediate use, for
	 *	function call count consumption, and execution profile
	 *	histogram computation.
	 * If the block fails sanity tests, just bag it.
	 * Next thing - get name to use. If PROFDIR is NULL, let's
	 *	get out now - they want No Profiling done.
	 *
	 * Otherwise:
	 * Set the block hdr cells.
	 * Get an anchor for the block, and link the anchor+block onto
	 *	the end of the chain.
	 * Init the grabba-cell externs (countbase/limit) for this block.
	 * Finally, call profil and return.
	 */

	ssiz = ((sizeof (struct hdr) + nfunc * sizeof (struct cnt)) /
	    sizeof (WORD));
	if (ssiz >= bufsize || lowpc >= highpc) {
		lmutex_unlock(&mon_lock);
		return;
	}

	if ((s = getenv(PROFDIR)) == NULL) { /* PROFDIR not in environment */
		mon_out = MON_OUT; /* use default "mon.out" */
	} else if (*s == '\0') { /* value of PROFDIR is NULL */
		lmutex_unlock(&mon_lock);
		return; /* no profiling on this run */
	} else { /* construct "PROFDIR/pid.progname" */
		int n;
		pid_t pid;
		char *name;
		size_t len;

		len = strlen(s);
		/* 15 is space for /pid.mon.out\0, if necessary */
		if ((mon_out = libc_malloc(len + strlen(___Argv[0]) + 15))
		    == NULL) {
			lmutex_unlock(&mon_lock);
			perror("");
			return;
		}
		(void) strcpy(mon_out, s);
		name = mon_out + len;
		*name++ = '/'; /* two slashes won't hurt */

		if ((pid = getpid()) <= 0) /* extra test just in case */
			pid = 1; /* getpid returns something inappropriate */

		/* suppress leading zeros */
		for (n = 10000; n > pid; n /= 10)
			;
		for (; ; n /= 10) {
			*name++ = pid/n + '0';
			if (n == 1)
			    break;
			pid %= n;
		}
		*name++ = '.';

		if (___Argv != NULL) {	/* mcrt0.s executed */
			if ((s = strrchr(___Argv[0], '/')) != NULL)
				(void) strcpy(name, s + 1);
			else
				(void) strcpy(name, ___Argv[0]);
		} else {
			(void) strcpy(name, MON_OUT);
		}
	}


	hdrp = (struct hdr *)(uintptr_t)buffer;	/* initialize 1st region */
	hdrp->lpc = lowpc;
	hdrp->hpc = highpc;
	hdrp->nfns = nfunc;

	/* get an anchor for the block */
	newanchp = (curAnchor == NULL) ? &firstAnchor :
	    (ANCHOR *)libc_malloc(sizeof (ANCHOR));

	if (newanchp == NULL) {
		lmutex_unlock(&mon_lock);
		perror("monitor");
		return;
	}

	/* link anchor+block into chain */
	newanchp->monBuffer = hdrp;		/* new, down. */
	newanchp->next  = NULL;			/* new, forward to NULL. */
	newanchp->prior = curAnchor;		/* new, backward. */
	if (curAnchor != NULL)
		curAnchor->next = newanchp;	/* old, forward to new. */
	newanchp->flags = HAS_HISTOGRAM;	/* note it has a histgm area */

	/* got it - enable use by mcount() */
	countbase  = (char *)buffer + sizeof (struct hdr);
	_countlimit = countbase + (nfunc * sizeof (struct cnt));

	/* (set size of region 3) */
	newanchp->histSize = (int)
	    (bufsize * sizeof (WORD) - (_countlimit - (char *)buffer));


	/* done w/regions 1 + 2: setup 3  to activate profil processing. */
	buffer += ssiz;			/* move ptr past 2'nd region */
	bufsize -= ssiz;		/* no. WORDs in third region */
					/* no. WORDs of text */
	text = (highpc - lowpc + sizeof (WORD) - 1) / sizeof (WORD);

	/*
	 * scale is a 16 bit fixed point fraction with the decimal
	 * point at the left
	 */
	if (bufsize < text) {
		/* make sure cast is done first! */
		double temp = (double)bufsize;
		scale = (uint_t)((temp * (long)0200000L) / text);
	} else {
		/* scale must be less than 1 */
		scale = 0xffff;
	}
	bufsize *= sizeof (WORD);	/* bufsize into # bytes */
	profil(buffer, bufsize, (ulong_t)lowpc, scale);


	curAnchor = newanchp;	/* make latest addition, the cur anchor */
	lmutex_unlock(&mon_lock);
}
Exemple #13
0
/*
 * load a message catalog which specified with current locale,
 * and catalog name.
 */
static struct db_info *
load_db(const char *curloc, const char *catname, int *err)
{
	char pathname[PATH_MAX];
	struct	stat64 sb;
	caddr_t	addr;
	struct db_info *db;
	int fd;
	int i;

	*err = 0;

	/* First time called, allocate space */
	if (!db_info) {
		if ((db_info =
		    libc_malloc(MINDB * sizeof (struct db_info))) == NULL) {
			*err = 1;
			return (NULL);
		}
		maxdb = MINDB;
	}

	for (i = 0; i < db_count; i++) {
		if (db_info[i].flag == 0)
			break;
	}
	/* New catalogue */
	if (i == db_count) {
		if (db_count == maxdb) {
			if ((db = libc_realloc(db_info,
			    ++maxdb * sizeof (struct db_info))) == NULL) {
				*err = 1;
				return (NULL);
			}
			db_info = db;
		}
		db_count++;
	}
	db = &db_info[i];
	db->flag = 0;
	(void) strcpy(db->db_name, catname);
	db->saved_locale = libc_strdup(curloc);
	if (db->saved_locale == NULL) {
		*err = 1;
		return (NULL);
	}
	db->flag = DB_OPEN;
	if (snprintf(pathname, sizeof (pathname),
	    _DFLT_LOC_PATH "%s" MESSAGES "%s",
	    db->saved_locale, db->db_name) >= sizeof (pathname)) {
		/*
		 * We won't set err here, because an invalid locale is not
		 * the fatal condition, but we can fall back to "C"
		 * locale.
		 */
		return (NULL);
	}
	if ((fd = open(pathname, O_RDONLY)) != -1 &&
	    fstat64(fd, &sb) != -1 &&
	    (addr = mmap(0, (size_t)sb.st_size, PROT_READ, MAP_SHARED,
	    fd, 0)) != MAP_FAILED) {
		db->flag |= DB_EXIST;
		db->addr = (uintptr_t)addr;
		db->length = (size_t)sb.st_size;
	}
	if (fd != -1)
		(void) close(fd);
	return (db);
}
Exemple #14
0
/*
 * Private interface used by nss_common.c, hence this function is not static
 */
struct __nsw_switchconfig *
_nsw_getoneconfig(const char *name, char *linep, enum __nsw_parse_err *errp)
	/* linep   Nota Bene: not const char *	*/
	/* errp  Meanings are abused a bit	*/
{
	struct __nsw_switchconfig *cfp;
	struct __nsw_lookup *lkp, **lkq;
	int end_crit, dup_fail = 0;
	action_t act;
	char *p, *tokenp;

	*errp = __NSW_CONF_PARSE_SUCCESS;

	if ((cfp = libc_malloc(sizeof (struct __nsw_switchconfig)))
	    == NULL) {
		*errp = __NSW_CONF_PARSE_SYSERR;
		return (NULL);
	}
	LIBC_STRDUP(cfp->dbase, name);
	lkq = &cfp->lookups;

	/* linep points to a naming service name */
	for (;;) {
		int i;

		/* white space following the last service */
		if (*linep == '\0' || *linep == '\n') {
			return (cfp);
		}
		if ((lkp = libc_malloc(sizeof (struct __nsw_lookup)))
		    == NULL) {
			*errp = __NSW_CONF_PARSE_SYSERR;
			freeconf(cfp);
			return (NULL);
		}

		*lkq = lkp;
		lkq = &lkp->next;

		for (i = 0; i < __NSW_STD_ERRS; i++)
			if (i == __NSW_SUCCESS)
				lkp->actions[i] = 1;
			else
				lkp->actions[i] = 0;

		/* get criteria for the naming service */
		if (tokenp = skip(&linep, '[')) { /* got criteria */

			/* premature end, illegal char following [ */
			if (!islabel(*linep))
				goto barf_line;
			LIBC_STRDUP(lkp->service_name, tokenp);
			cfp->num_lookups++;
			end_crit = 0;

			/* linep points to a switch_err */
			for (;;) {
				if ((tokenp = skip(&linep, '=')) == NULL) {
					goto barf_line;
				}

				/* premature end, ill char following = */
				if (!islabel(*linep))
					goto barf_line;

				/* linep points to the string following '=' */
				p = labelskip(linep);
				if (*p == ']')
					end_crit = 1;
				else if (*p != ' ' && *p != '\t')
					goto barf_line;
				*p++ = '\0'; /* null terminate linep */
				p = spaceskip(p);
				if (!end_crit) {
					if (*p == ']') {
					end_crit = 1;
					*p++ = '\0';
					} else if (*p == '\0' || *p == '\n')
						return (cfp);
					else if (!islabel(*p))
					/* p better be the next switch_err */
						goto barf_line;
				}
				if (strcasecmp(linep, __NSW_STR_RETURN) == 0)
					act = __NSW_RETURN;
				else if (strcasecmp(linep,
					    __NSW_STR_CONTINUE) == 0)
					act = __NSW_CONTINUE;
				else if (strcasecmp(linep,
					    __NSW_STR_FOREVER) == 0)
					/*
					 * =forever or =N might be in conf file
					 * but old progs won't expect it.
					 */
					act = __NSW_RETURN;
				else if (alldigits(linep))
					act = __NSW_CONTINUE;
				else
					goto barf_line;
				if (strcasecmp(tokenp,
					    __NSW_STR_SUCCESS) == 0) {
					lkp->actions[__NSW_SUCCESS] = act;
				} else if (strcasecmp(tokenp,
					    __NSW_STR_NOTFOUND) == 0) {
					lkp->actions[__NSW_NOTFOUND] = act;
				} else if (strcasecmp(tokenp,
					    __NSW_STR_UNAVAIL) == 0) {
					lkp->actions[__NSW_UNAVAIL] = act;
				} else if (strcasecmp(tokenp,
					    __NSW_STR_TRYAGAIN) == 0) {
					lkp->actions[__NSW_TRYAGAIN] = act;
				} else {
					/*EMPTY*/
					/*
					 * convert string tokenp to integer
					 * and put in long_errs
					 */
				}
				if (end_crit) {
					linep = spaceskip(p);
					if (*linep == '\0' || *linep == '\n')
						return (cfp);
					break; /* process next naming service */
				}
				linep = p;
			} /* end of while loop for a name service's criteria */
		} else {
			/*
			 * no criteria for this naming service.
			 * linep points to name service, but not null
			 * terminated.
			 */
			p = labelskip(linep);
			if (*p == '\0' || *p == '\n') {
				*p = '\0';
				LIBC_STRDUP(lkp->service_name, linep);
				cfp->num_lookups++;
				return (cfp);
			}
			if (*p != ' ' && *p != '\t')
				goto barf_line;
			*p++ = '\0';
			LIBC_STRDUP(lkp->service_name, linep);
			cfp->num_lookups++;
			linep = spaceskip(p);
		}
	} /* end of while(1) loop for a name service */

barf_line:
	freeconf(cfp);
	*errp = dup_fail ? __NSW_CONF_PARSE_SYSERR : __NSW_CONF_PARSE_NOPOLICY;
	return (NULL);
}
Exemple #15
0
/*
 * Private interface used by nss_common.c, hence this function is not static
 */
struct __nsw_switchconfig_v1 *
_nsw_getoneconfig_v1(const char *name, char *linep, enum __nsw_parse_err *errp)
	/* linep   Nota Bene: not const char *	*/
	/* errp  Meanings are abused a bit	*/
{
	struct __nsw_switchconfig_v1 *cfp;
	struct __nsw_lookup_v1 *lkp, **lkq;
	int end_crit, dup_fail = 0;
	action_t act;
	char *p, *tokenp;

	*errp = __NSW_CONF_PARSE_SUCCESS;

	if ((cfp = libc_malloc(sizeof (struct __nsw_switchconfig_v1)))
	    == NULL) {
		*errp = __NSW_CONF_PARSE_SYSERR;
		return (NULL);
	}
	LIBC_STRDUP(cfp->dbase, name);
	lkq = &cfp->lookups;

	/* linep points to a naming service name */
	for (;;) {
		int i;

		/* white space following the last service */
		if (*linep == '\0' || *linep == '\n') {
			return (cfp);
		}
		if ((lkp = libc_malloc(sizeof (struct __nsw_lookup_v1)))
		    == NULL) {
			*errp = __NSW_CONF_PARSE_SYSERR;
			freeconf_v1(cfp);
			return (NULL);
		}

		*lkq = lkp;
		lkq = &lkp->next;

		for (i = 0; i < __NSW_STD_ERRS_V1; i++)
			if (i == __NSW_SUCCESS)
				lkp->actions[i] = __NSW_RETURN;
			else if (i == __NSW_TRYAGAIN)
				lkp->actions[i] = __NSW_TRYAGAIN_FOREVER;
			else
				lkp->actions[i] = __NSW_CONTINUE;

		/* get criteria for the naming service */
		if (tokenp = skip(&linep, '[')) { /* got criteria */

			/* premature end, illegal char following [ */
			if (!islabel(*linep))
				goto barf_line;
			LIBC_STRDUP(lkp->service_name, tokenp);
			cfp->num_lookups++;

			set_dns_default_lkp(lkp);

			end_crit = 0;

			/* linep points to a switch_err */
			for (;;) {
				int ntimes = 0; /* try again max N times */
				int dns_continue = 0;

				if ((tokenp = skip(&linep, '=')) == NULL) {
					goto barf_line;
				}

				/* premature end, ill char following = */
				if (!islabel(*linep))
					goto barf_line;

				/* linep points to the string following '=' */
				p = labelskip(linep);
				if (*p == ']')
					end_crit = 1;
				else if (*p != ' ' && *p != '\t')
					goto barf_line;
				*p++ = '\0'; /* null terminate linep */
				p = spaceskip(p);
				if (!end_crit) {
					if (*p == ']') {
					end_crit = 1;
					*p++ = '\0';
					} else if (*p == '\0' || *p == '\n') {
						return (cfp);
					} else if (!islabel(*p))
					/* p better be the next switch_err */
						goto barf_line;
				}
				if (strcasecmp(linep, __NSW_STR_RETURN) == 0)
					act = __NSW_RETURN;
				else if (strcasecmp(linep,
						    __NSW_STR_CONTINUE) == 0) {
					if (strcasecmp(lkp->service_name,
						    "dns") == 0 &&
						strcasecmp(tokenp,
							__NSW_STR_TRYAGAIN)
							== 0) {
						/*
						 * Add one more condition
						 * so it retries only if it's
						 * "dns [TRYAGAIN=continue]"
						 */
						dns_continue = 1;
						act = __NSW_TRYAGAIN_NTIMES;
					} else
						act = __NSW_CONTINUE;
				} else if (strcasecmp(linep,
					    __NSW_STR_FOREVER) == 0)
					act = __NSW_TRYAGAIN_FOREVER;
				else if (alldigits(linep)) {
					act = __NSW_TRYAGAIN_NTIMES;
					ntimes = atoi(linep);
					if (ntimes < 0 || ntimes > INT_MAX)
						ntimes = 0;
				}
				else
					goto barf_line;

				if (__NSW_SUCCESS_ACTION(act) &&
				    strcasecmp(tokenp,
					    __NSW_STR_SUCCESS) == 0) {
					lkp->actions[__NSW_SUCCESS] = act;
				} else if (__NSW_NOTFOUND_ACTION(act) &&
					strcasecmp(tokenp,
					    __NSW_STR_NOTFOUND) == 0) {
					lkp->actions[__NSW_NOTFOUND] = act;
				} else if (__NSW_UNAVAIL_ACTION(act) &&
					strcasecmp(tokenp,
					    __NSW_STR_UNAVAIL) == 0) {
					lkp->actions[__NSW_UNAVAIL] = act;
				} else if (__NSW_TRYAGAIN_ACTION(act) &&
					strcasecmp(tokenp,
					    __NSW_STR_TRYAGAIN) == 0) {
					lkp->actions[__NSW_TRYAGAIN] = act;
					if (strcasecmp(lkp->service_name,
						    "nis") == 0)
						lkp->actions[
						    __NSW_NISSERVDNS_TRYAGAIN]
						    = act;
					if (act == __NSW_TRYAGAIN_NTIMES)
						lkp->max_retries =
						dns_continue ?
						dns_tryagain_retry : ntimes;
				} else {
					/*EMPTY*/
					/*
					 * convert string tokenp to integer
					 * and put in long_errs
					 */
				}
				if (end_crit) {
					linep = spaceskip(p);
					if (*linep == '\0' || *linep == '\n')
						return (cfp);
					break; /* process next naming service */
				}
				linep = p;
			} /* end of while loop for a name service's criteria */
		} else {
			/*
			 * no criteria for this naming service.
			 * linep points to name service, but not null
			 * terminated.
			 */
			p = labelskip(linep);
			if (*p == '\0' || *p == '\n') {
				*p = '\0';
				LIBC_STRDUP(lkp->service_name, linep);
				set_dns_default_lkp(lkp);
				cfp->num_lookups++;
				return (cfp);
			}
			if (*p != ' ' && *p != '\t')
				goto barf_line;
			*p++ = '\0';
			LIBC_STRDUP(lkp->service_name, linep);
			set_dns_default_lkp(lkp);
			cfp->num_lookups++;
			linep = spaceskip(p);
		}
	} /* end of while(1) loop for a name service */

barf_line:
	freeconf_v1(cfp);
	*errp = dup_fail ? __NSW_CONF_PARSE_SYSERR : __NSW_CONF_PARSE_NOPOLICY;
	return (NULL);
}
Exemple #16
0
struct locdata *
__lc_monetary_load(const char *name)
{
	int ret;
	int clen;
	struct lc_monetary	*lmon;
	struct locdata		*ldata;

	if ((ldata = __locdata_alloc(name, sizeof (*lmon))) == NULL) {
		return (NULL);
	}
	lmon = ldata->l_data[0];

	ret = __part_load_locale(name, (char **)&ldata->l_data[1],
	    "LC_MONETARY", LCMONETARY_SIZE_FULL, LCMONETARY_SIZE_MIN,
	    (const char **)lmon);

	if (ret != _LDP_LOADED) {
		__locdata_free(ldata);
		errno = EINVAL;
		return (NULL);
	}

	/* special storage for currency string */
	clen = strlen(lmon->currency_symbol) + 2;
	ldata->l_data[2] = libc_malloc(clen);
	lmon->crncystr = ldata->l_data[2];

	lmon->mon_grouping = __fix_locale_grouping_str(lmon->mon_grouping);

#define	M_ASSIGN_CHAR(NAME) \
	(((char *)lmon->NAME)[0] = cnv(lmon->NAME))

	M_ASSIGN_CHAR(int_frac_digits);
	M_ASSIGN_CHAR(frac_digits);
	M_ASSIGN_CHAR(p_cs_precedes);
	M_ASSIGN_CHAR(p_sep_by_space);
	M_ASSIGN_CHAR(n_cs_precedes);
	M_ASSIGN_CHAR(n_sep_by_space);
	M_ASSIGN_CHAR(p_sign_posn);
	M_ASSIGN_CHAR(n_sign_posn);

	/*
	 * The six additional C99 international monetary formatting
	 * parameters default to the national parameters when
	 * reading FreeBSD LC_MONETARY data files.
	 */
#define	M_ASSIGN_ICHAR(NAME)				\
	if (lmon->int_##NAME == NULL)			\
		lmon->int_##NAME = lmon->NAME;		\
	else						\
		M_ASSIGN_CHAR(int_##NAME);

	M_ASSIGN_ICHAR(p_cs_precedes);
	M_ASSIGN_ICHAR(n_cs_precedes);
	M_ASSIGN_ICHAR(p_sep_by_space);
	M_ASSIGN_ICHAR(n_sep_by_space);
	M_ASSIGN_ICHAR(p_sign_posn);
	M_ASSIGN_ICHAR(n_sign_posn);

	/*
	 * Now calculate the currency string (CRNCYSTR) for nl_langinfo.
	 * This is a legacy SUSv2 interface.
	 */
	if ((lmon->p_cs_precedes[0] == lmon->n_cs_precedes[0]) &&
	    (lmon->currency_symbol[0] != '\0')) {
		char sign = '\0';
		switch (lmon->p_cs_precedes[0]) {
		case 0:
			sign = '+';
			break;
		case 1:
			sign = '-';
			break;
		case CHAR_MAX:
			/*
			 * Substitute currency string for radix character.
			 * To the best of my knowledge, no locale uses this.
			 */
			if (strcmp(lmon->mon_decimal_point,
			    lmon->currency_symbol) == 0)
				sign = '.';
			break;
		}
		(void) snprintf(lmon->crncystr, clen, "%c%s", sign,
		    lmon->currency_symbol);
	}

	return (ldata);
}