400 lines
11 KiB
C
Executable File
400 lines
11 KiB
C
Executable File
/*
|
|
* Environment handling routines
|
|
*
|
|
* Copyright 2000 by Gray Watson
|
|
*
|
|
* This file is part of the dmalloc package.
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for
|
|
* any purpose and without fee is hereby granted, provided that the
|
|
* above copyright notice and this permission notice appear in all
|
|
* copies, and that the name of Gray Watson not be used in advertising
|
|
* or publicity pertaining to distribution of the document or software
|
|
* without specific, written prior permission.
|
|
*
|
|
* Gray Watson makes no representations about the suitability of the
|
|
* software described herein for any purpose. It is provided "as is"
|
|
* without express or implied warranty.
|
|
*
|
|
* The author may be contacted via http://dmalloc.com/
|
|
*
|
|
* $Id: //BBN_Linux/Branch/Branch_for_Rel_TP_ASEAN_20161216/tclinux_phoenix/apps/public/tools/dmalloc-5.5.2/env.c#1 $
|
|
*/
|
|
|
|
/*
|
|
* This file contains short routine(s) to process the environment
|
|
* variable(s) used by the library to get the runtime option(s).
|
|
*/
|
|
|
|
#define DMALLOC_DISABLE
|
|
|
|
#if HAVE_STDLIB_H
|
|
# include <stdlib.h>
|
|
#endif
|
|
#if HAVE_STRING_H
|
|
# include <string.h>
|
|
#endif
|
|
#if HAVE_UNISTD_H
|
|
# include <unistd.h> /* for getpid */
|
|
#endif
|
|
|
|
#include "conf.h"
|
|
#include "dmalloc.h"
|
|
|
|
#include "compat.h"
|
|
#include "dmalloc_loc.h"
|
|
#include "debug_tok.h"
|
|
#include "env.h"
|
|
#include "error.h"
|
|
|
|
/*
|
|
* Environmental labels.
|
|
*
|
|
* NOTE: the decision has been made _not_ to do the sizeof() hack for
|
|
* portability reasons.
|
|
*/
|
|
#define ADDRESS_LABEL "addr"
|
|
#define DEBUG_LABEL "debug"
|
|
#define INTERVAL_LABEL "inter"
|
|
#define LOCK_ON_LABEL "lockon"
|
|
#define LOGFILE_LABEL "log"
|
|
#define START_LABEL "start"
|
|
#define LIMIT_LABEL "limit"
|
|
|
|
#define ASSIGNMENT_CHAR '='
|
|
|
|
/* local variables */
|
|
static char log_path[512] = { '\0' }; /* storage for env path */
|
|
static char start_file[512] = { '\0' }; /* file to start at */
|
|
|
|
/****************************** local utilities ******************************/
|
|
|
|
/*
|
|
* Hexadecimal STR to int translation
|
|
*/
|
|
static long hex_to_long(const char *str)
|
|
{
|
|
long ret;
|
|
|
|
/* strip off spaces */
|
|
for (; *str == ' ' || *str == '\t'; str++) {
|
|
}
|
|
|
|
/* skip a leading 0[xX] */
|
|
if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) {
|
|
str += 2;
|
|
}
|
|
|
|
for (ret = 0;; str++) {
|
|
if (*str >= '0' && *str <= '9') {
|
|
ret = ret * 16 + (*str - '0');
|
|
}
|
|
else if (*str >= 'a' && *str <= 'f') {
|
|
ret = ret * 16 + (*str - 'a' + 10);
|
|
}
|
|
else if (*str >= 'A' && *str <= 'F') {
|
|
ret = ret * 16 + (*str - 'A' + 10);
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/***************************** exported routines *****************************/
|
|
|
|
/*
|
|
* Break up ADDR_ALL into ADDR_P and ADDR_COUNT_P
|
|
*/
|
|
void _dmalloc_address_break(const char *addr_all, DMALLOC_PNT *addr_p,
|
|
unsigned long *addr_count_p)
|
|
{
|
|
char *colon_p;
|
|
|
|
SET_POINTER(addr_p, (DMALLOC_PNT)hex_to_long(addr_all));
|
|
if (addr_count_p != NULL) {
|
|
colon_p = strchr(addr_all, ':');
|
|
if (colon_p != NULL) {
|
|
*addr_count_p = loc_atoul(colon_p + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Break up START_ALL into SFILE_P, SLINE_P, and SCOUNT_P
|
|
*/
|
|
void _dmalloc_start_break(char *start_all, char **start_file_p,
|
|
int *start_line_p, unsigned long *start_iter_p,
|
|
unsigned long *start_size_p)
|
|
{
|
|
char *start_p;
|
|
|
|
start_p = strchr(start_all, ':');
|
|
if (start_p != NULL) {
|
|
(void)strncpy(start_file, start_all, sizeof(start_file));
|
|
start_file[sizeof(start_file) - 1] = '\0';
|
|
SET_POINTER(start_file_p, start_file);
|
|
start_p = start_file + (start_p - start_all);
|
|
*start_p = '\0';
|
|
SET_POINTER(start_line_p, atoi(start_p + 1));
|
|
SET_POINTER(start_iter_p, 0);
|
|
SET_POINTER(start_size_p, 0);
|
|
}
|
|
else if (start_all[0] == 's') {
|
|
SET_POINTER(start_file_p, NULL);
|
|
SET_POINTER(start_line_p, 0);
|
|
SET_POINTER(start_iter_p, 0);
|
|
SET_POINTER(start_size_p, loc_atoul(start_all + 1));
|
|
}
|
|
else {
|
|
SET_POINTER(start_file_p, NULL);
|
|
SET_POINTER(start_line_p, 0);
|
|
if (start_all[0] == 'c') {
|
|
SET_POINTER(start_iter_p, loc_atoul(start_all + 1));
|
|
}
|
|
else {
|
|
SET_POINTER(start_iter_p, loc_atoul(start_all));
|
|
}
|
|
SET_POINTER(start_size_p, 0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Process the values of dmalloc environ variable(s) from ENVIRON
|
|
* string.
|
|
*/
|
|
void _dmalloc_environ_process(const char *env_str, DMALLOC_PNT *addr_p,
|
|
unsigned long *addr_count_p,
|
|
unsigned int *debug_p,
|
|
unsigned long *interval_p, int *lock_on_p,
|
|
char **logpath_p, char **start_file_p,
|
|
int *start_line_p,
|
|
unsigned long *start_iter_p,
|
|
unsigned long *start_size_p,
|
|
unsigned long *limit_p)
|
|
{
|
|
char *env_p, *this_p;
|
|
char buf[1024];
|
|
int len, done_b = 0;
|
|
unsigned int flags = 0;
|
|
attr_t *attr_p;
|
|
|
|
SET_POINTER(addr_p, NULL);
|
|
SET_POINTER(addr_count_p, 0);
|
|
SET_POINTER(debug_p, 0);
|
|
SET_POINTER(interval_p, 0);
|
|
SET_POINTER(lock_on_p, 0);
|
|
SET_POINTER(logpath_p, NULL);
|
|
SET_POINTER(start_file_p, NULL);
|
|
SET_POINTER(start_line_p, 0);
|
|
SET_POINTER(start_iter_p, 0);
|
|
SET_POINTER(start_size_p, 0);
|
|
SET_POINTER(limit_p, 0);
|
|
|
|
/* make a copy */
|
|
(void)strncpy(buf, env_str, sizeof(buf));
|
|
buf[sizeof(buf) - 1] = '\0';
|
|
|
|
/* handle each of tokens, in turn */
|
|
for (env_p = buf, this_p = buf; ! done_b; env_p++, this_p = env_p) {
|
|
|
|
/* find the comma of end */
|
|
for (;; env_p++) {
|
|
if (*env_p == '\0') {
|
|
done_b = 1;
|
|
break;
|
|
}
|
|
if (*env_p == ',' && (env_p == buf || *(env_p - 1) != '\\')) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* should we strip ' ' or '\t' here? */
|
|
|
|
if (this_p == env_p) {
|
|
continue;
|
|
}
|
|
|
|
*env_p = '\0';
|
|
|
|
len = strlen(ADDRESS_LABEL);
|
|
if (strncmp(this_p, ADDRESS_LABEL, len) == 0
|
|
&& *(this_p + len) == ASSIGNMENT_CHAR) {
|
|
this_p += len + 1;
|
|
_dmalloc_address_break(this_p, addr_p, addr_count_p);
|
|
continue;
|
|
}
|
|
|
|
len = strlen(DEBUG_LABEL);
|
|
if (strncmp(this_p, DEBUG_LABEL, len) == 0
|
|
&& *(this_p + len) == ASSIGNMENT_CHAR) {
|
|
this_p += len + 1;
|
|
SET_POINTER(debug_p, hex_to_long(this_p));
|
|
continue;
|
|
}
|
|
|
|
len = strlen(INTERVAL_LABEL);
|
|
if (strncmp(this_p, INTERVAL_LABEL, len) == 0
|
|
&& *(this_p + len) == ASSIGNMENT_CHAR) {
|
|
this_p += len + 1;
|
|
SET_POINTER(interval_p, loc_atoul(this_p));
|
|
continue;
|
|
}
|
|
|
|
len = strlen(LOCK_ON_LABEL);
|
|
if (strncmp(this_p, LOCK_ON_LABEL, len) == 0
|
|
&& *(this_p + len) == ASSIGNMENT_CHAR) {
|
|
this_p += len + 1;
|
|
SET_POINTER(lock_on_p, atoi(this_p));
|
|
continue;
|
|
}
|
|
|
|
/* get the dmalloc logfile name into a holding variable */
|
|
len = strlen(LOGFILE_LABEL);
|
|
if (strncmp(this_p, LOGFILE_LABEL, len) == 0
|
|
&& *(this_p + len) == ASSIGNMENT_CHAR) {
|
|
this_p += len + 1;
|
|
(void)strncpy(log_path, this_p, sizeof(log_path));
|
|
log_path[sizeof(log_path) - 1] = '\0';
|
|
SET_POINTER(logpath_p, log_path);
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* start checking the heap after X iterations OR
|
|
* start at a file:line combination
|
|
*/
|
|
len = strlen(START_LABEL);
|
|
if (strncmp(this_p, START_LABEL, len) == 0
|
|
&& *(this_p + len) == ASSIGNMENT_CHAR) {
|
|
this_p += len + 1;
|
|
_dmalloc_start_break(this_p, start_file_p, start_line_p, start_iter_p,
|
|
start_size_p);
|
|
continue;
|
|
}
|
|
|
|
/* set the memory limit to the library */
|
|
len = strlen(LIMIT_LABEL);
|
|
if (strncmp(this_p, LIMIT_LABEL, len) == 0
|
|
&& *(this_p + len) == ASSIGNMENT_CHAR) {
|
|
this_p += len + 1;
|
|
SET_POINTER(limit_p, loc_atoul(this_p));
|
|
continue;
|
|
}
|
|
|
|
/* need to check the short/long debug options */
|
|
for (attr_p = attributes; attr_p->at_string != NULL; attr_p++) {
|
|
if (strcmp(this_p, attr_p->at_string) == 0) {
|
|
flags |= attr_p->at_value;
|
|
break;
|
|
}
|
|
}
|
|
if (attr_p->at_string != NULL) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* append the token settings to the debug setting */
|
|
if (debug_p != NULL) {
|
|
if (*debug_p == 0) {
|
|
*debug_p = flags;
|
|
}
|
|
else {
|
|
*debug_p |= flags;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set dmalloc environ variable(s) with the values (maybe SHORT debug
|
|
* info) into BUF.
|
|
*/
|
|
void _dmalloc_environ_set(char *buf, const int buf_size,
|
|
const int long_tokens_b,
|
|
const DMALLOC_PNT address,
|
|
const unsigned long addr_count,
|
|
const unsigned int debug,
|
|
const unsigned long interval, const int lock_on,
|
|
const char *logpath, const char *start_file_p,
|
|
const int start_line,
|
|
const unsigned long start_iter,
|
|
const unsigned long start_size,
|
|
const unsigned long limit_val)
|
|
{
|
|
char *buf_p = buf, *bounds_p = buf + buf_size;
|
|
|
|
if (debug > 0) {
|
|
if (long_tokens_b) {
|
|
attr_t *attr_p;
|
|
|
|
for (attr_p = attributes; attr_p->at_string != NULL; attr_p++) {
|
|
if (debug & attr_p->at_value) {
|
|
buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s,",
|
|
attr_p->at_string);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%#x,",
|
|
DEBUG_LABEL, ASSIGNMENT_CHAR, debug);
|
|
}
|
|
}
|
|
if (address != NULL) {
|
|
if (addr_count > 0) {
|
|
buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%#lx:%lu,",
|
|
ADDRESS_LABEL, ASSIGNMENT_CHAR, (long)address,
|
|
addr_count);
|
|
}
|
|
else {
|
|
buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%#lx,",
|
|
ADDRESS_LABEL, ASSIGNMENT_CHAR, (long)address);
|
|
}
|
|
}
|
|
if (interval > 0) {
|
|
buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%lu,",
|
|
INTERVAL_LABEL, ASSIGNMENT_CHAR, interval);
|
|
}
|
|
if (lock_on > 0) {
|
|
buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%d,",
|
|
LOCK_ON_LABEL, ASSIGNMENT_CHAR, lock_on);
|
|
}
|
|
if (logpath != NULL) {
|
|
buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%s,",
|
|
LOGFILE_LABEL, ASSIGNMENT_CHAR, logpath);
|
|
}
|
|
if (start_file_p != NULL) {
|
|
if (start_line > 0) {
|
|
buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%s:%d,",
|
|
START_LABEL, ASSIGNMENT_CHAR, start_file_p,
|
|
start_line);
|
|
}
|
|
else {
|
|
buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%s,",
|
|
START_LABEL, ASSIGNMENT_CHAR, start_file_p);
|
|
}
|
|
}
|
|
else if (start_iter > 0) {
|
|
/* NOTE: there is an 'c' (for count) before the iter variable here */
|
|
buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%cc%lu,",
|
|
START_LABEL, ASSIGNMENT_CHAR, start_iter);
|
|
}
|
|
else if (start_size > 0) {
|
|
/* NOTE: there is an 's' before the size variable here */
|
|
buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%cs%lu,",
|
|
START_LABEL, ASSIGNMENT_CHAR, start_size);
|
|
}
|
|
if (limit_val > 0) {
|
|
buf_p += loc_snprintf(buf_p, bounds_p - buf_p, "%s%c%lu,",
|
|
LIMIT_LABEL, ASSIGNMENT_CHAR, limit_val);
|
|
}
|
|
|
|
/* cut off the last comma */
|
|
if (buf_p > buf) {
|
|
buf_p--;
|
|
}
|
|
|
|
*buf_p = '\0';
|
|
}
|