1
0
This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
TP-Link_Archer-XR500v/EN7526G_3.18Kernel_SDK/apps/public/tools/dmalloc-5.5.2/dmalloc.c
2024-07-22 01:58:46 -03:00

1094 lines
28 KiB
C
Executable File

/*
* program that handles the dmalloc variables.
*
* 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/dmalloc.c#1 $
*/
/*
* This is the dmalloc program which is designed to enable the user to
* easily set the environmental variables that control the dmalloc
* library capabilities.
*/
/*
* NOTE: all standard-output from this program is designed to be run
* through a shell evaluation command by default. Any messages for
* the user should therefore be send to stderr.
*/
#include <stdio.h> /* for stderr */
#define DMALLOC_DISABLE
#if HAVE_STRING_H
# include <string.h>
#endif
#if HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include "conf.h"
#include "dmalloc_argv.h" /* for argument processing */
#include "dmalloc.h"
#include "compat.h"
#include "debug_tok.h"
#include "debug_tok.h"
#include "env.h"
#include "error_val.h"
#include "dmalloc_loc.h"
#include "version.h"
#define HOME_ENVIRON "HOME" /* home directory */
#define SHELL_ENVIRON "SHELL" /* for the type of shell */
#define DEFAULT_CONFIG ".dmallocrc" /* default config file */
#define TOKENIZE_EQUALS " \t=" /* for tag lines */
#define TOKENIZE_CHARS " \t," /* for tag lines */
#define DEBUG_ARG 'd' /* debug argument */
#define INTERVAL_ARG 'i' /* interval argument */
#define THREAD_LOCK_ON_ARG 'o' /* lock-on argument */
#define LIMIT_ARG 'M' /* memory-limit argument */
#define LINE_WIDTH 75 /* num debug toks per line */
#define FILE_NOT_FOUND 1
#define FILE_FOUND 2
#define TOKEN_FOUND 3
/*
* default flag information
*/
typedef struct {
char *de_string; /* default name */
long de_flags; /* default settings */
} default_t;
#define RUNTIME_FLAGS (DEBUG_LOG_STATS | DEBUG_LOG_NONFREE | \
DEBUG_LOG_BAD_SPACE | \
DEBUG_CHECK_FENCE | \
DEBUG_CATCH_NULL)
#define LOW_FLAGS (RUNTIME_FLAGS | \
DEBUG_LOG_ELAPSED_TIME | \
DEBUG_CHECK_SHUTDOWN | \
DEBUG_FREE_BLANK | DEBUG_ERROR_ABORT | \
DEBUG_ALLOC_BLANK)
#define MEDIUM_FLAGS (LOW_FLAGS | \
DEBUG_CHECK_HEAP | \
DEBUG_REALLOC_COPY)
#define HIGH_FLAGS (MEDIUM_FLAGS | \
DEBUG_CHECK_BLANK | DEBUG_CHECK_FUNCS)
#define ALL_FLAGS (HIGH_FLAGS | \
DEBUG_LOG_TRANS | DEBUG_LOG_ADMIN | \
DEBUG_NEVER_REUSE)
/* NOTE: print-messages is not in this list because it is special */
static default_t defaults[] = {
{ "none", 0 },
{ "runtime", RUNTIME_FLAGS },
{ "run", RUNTIME_FLAGS },
{ "low", LOW_FLAGS },
{ "med", MEDIUM_FLAGS },
{ "medium", MEDIUM_FLAGS },
{ "high", HIGH_FLAGS },
{ "all", ALL_FLAGS },
{ NULL }
};
/* argument variables */
static int bourne_b = 0; /* set bourne shell output */
static int cshell_b = 0; /* set c-shell output */
static int gdb_b = 0; /* set gdb output */
static int rcshell_b = 0; /* set rc shell output */
static char *address = NULL; /* for ADDRESS */
static int clear_b = 0; /* clear variables */
static int debug = 0; /* for DEBUG */
static int errno_to_print = 0; /* to print the error string */
static int help_b = 0; /* print help message */
static char *inpath = NULL; /* for config-file path */
static unsigned long interval = 0; /* for setting INTERVAL */
static int thread_lock_on = 0; /* for setting LOCK_ON */
static int keep_b = 0; /* keep settings override -r */
static int list_tags_b = 0; /* list rc tags */
static int debug_tokens_b = 0; /* list debug tokens */
static char *logpath = NULL; /* for LOGFILE setting */
static int long_tokens_b = 0; /* long-tok output */
static argv_array_t minus; /* tokens to remove */
static unsigned long limit_arg = 0; /* memory limit */
static int make_changes_b = 1; /* make no changes to env */
static argv_array_t plus; /* tokens to add */
static int remove_auto_b = 0; /* auto-remove settings */
static char *start_file = NULL; /* for START settings */
static unsigned long start_iter = 0; /* for START settings */
static unsigned long start_size = 0; /* for START settings */
static int usage_b = 0; /* usage messages */
static int verbose_b = 0; /* verbose flag */
static int very_verbose_b = 0; /* very-verbose flag */
static int version_b = 0; /* print version string */
static char *tag = NULL; /* maybe a tag argument */
static argv_t args[] = {
{ 'b', "bourne-shell", ARGV_BOOL_INT, &bourne_b,
NULL, "set output for bourne shells" },
{ ARGV_OR },
{ 'C', "c-shell", ARGV_BOOL_INT, &cshell_b,
NULL, "set output for C-type shells" },
{ ARGV_OR },
{ 'g', "gdb", ARGV_BOOL_INT, &gdb_b,
NULL, "set output for gdb parsing" },
{ ARGV_OR },
{ 'R', "rc-shell", ARGV_BOOL_INT, &rcshell_b,
NULL, "set output for rc shell" },
{ 'a', "address", ARGV_CHAR_P, &address,
"address:#", "stop when malloc sees address" },
{ 'c', "clear", ARGV_BOOL_INT, &clear_b,
NULL, "clear all variables not set" },
{ DEBUG_ARG, "debug-mask", ARGV_HEX, &debug,
"value", "hex flag to set debug mask" },
{ 'D', "debug-tokens", ARGV_BOOL_INT, &debug_tokens_b,
NULL, "list debug tokens" },
{ 'e', "errno", ARGV_INT, &errno_to_print,
"errno", "print error string for errno" },
{ 'f', "file", ARGV_CHAR_P, &inpath,
"path", "config if not $HOME/.dmallocrc" },
{ 'h', "help", ARGV_BOOL_INT, &help_b,
NULL, "print help message" },
{ INTERVAL_ARG, "interval", ARGV_U_LONG, &interval,
"value", "check heap every number times" },
{ 'k', "keep", ARGV_BOOL_INT, &keep_b,
NULL, "keep settings (override -r)" },
{ 'l', "logfile", ARGV_CHAR_P, &logpath,
"path", "file to log messages to" },
{ 'L', "long-tokens", ARGV_BOOL_INT, &long_tokens_b,
NULL, "set env with tokens not 0x..." },
{ 'm', "minus", ARGV_CHAR_P | ARGV_FLAG_ARRAY, &minus,
"token(s)", "del tokens from current debug" },
{ LIMIT_ARG, "memory-limit", ARGV_U_SIZE, &limit_arg,
"value", "limit allocations to this amount" },
{ 'n', "no-changes", ARGV_BOOL_NEG, &make_changes_b,
NULL, "make no changes to the env" },
{ THREAD_LOCK_ON_ARG, "lock-on", ARGV_INT, &thread_lock_on,
"number", "number of times to not lock" },
{ 'p', "plus", ARGV_CHAR_P | ARGV_FLAG_ARRAY, &plus,
"token(s)", "add tokens to current debug" },
{ 'r', "remove", ARGV_BOOL_INT, &remove_auto_b,
NULL, "remove other settings if tag" },
{ 's', "start-file", ARGV_CHAR_P, &start_file,
"file:line", "check heap after this location" },
{ ARGV_OR },
{ 'S', "start-iter", ARGV_U_LONG, &start_iter,
"number", "check heap after this iteration" },
{ ARGV_OR },
{ '\0', "start-size", ARGV_U_SIZE, &start_size,
"size", "check heap after this mem size" },
{ 't', "list-tags", ARGV_BOOL_INT, &list_tags_b,
NULL, "list tags in rc file" },
{ 'u', "usage", ARGV_BOOL_INT, &usage_b,
NULL, "print usage messages" },
{ 'v', "verbose", ARGV_BOOL_INT, &verbose_b,
NULL, "turn on verbose output" },
{ 'V', "very-verbose", ARGV_BOOL_INT, &very_verbose_b,
NULL, "turn on very-verbose output" },
{ '\0', "version", ARGV_BOOL_INT, &version_b,
NULL, "display version string" },
{ ARGV_MAYBE, NULL, ARGV_CHAR_P, &tag,
"tag", "debug token, internal or from rc file" },
{ ARGV_LAST }
};
/*
* list of bourne shells
*/
static char *sh_shells[] = { "sh", "ash", "bash", "ksh", "zsh", NULL };
/*
* try a check out the shell env variable to see what form of shell
* commands we should output
*/
static void choose_shell(void)
{
const char *shell, *shell_p;
int shell_c;
shell = getenv(SHELL_ENVIRON);
if (shell == NULL) {
/* oh well, we just guess on c-shell */
cshell_b = 1;
return;
}
shell_p = strrchr(shell, '/');
if (shell_p == NULL) {
shell_p = shell;
}
else {
shell_p++;
}
/* look for the rc shell specifically */
if (strcmp("rc", shell_p) == 0) {
rcshell_b = 1;
return;
}
/* look for the shells which are bourne-shell compatible */
for (shell_c = 0; sh_shells[shell_c] != NULL; shell_c++) {
if (strcmp(sh_shells[shell_c], shell_p) == 0) {
bourne_b = 1;
return;
}
}
/* otherwise set to c-shell */
cshell_b = 1;
}
/*
* dump the current flags set in the debug variable VAL
*/
static void dump_debug(const unsigned long val)
{
attr_t *attr_p;
char *str;
unsigned long work = val;
int col_c = 0, len;
for (attr_p = attributes; attr_p->at_string != NULL; attr_p++) {
/* the below test for work == 0 is necessary to handle the 'none' token */
if ((work == 0 && attr_p->at_value == 0)
|| (attr_p->at_value != 0 && BIT_IS_SET(work, attr_p->at_value))) {
BIT_CLEAR(work, attr_p->at_value);
if (col_c == 0) {
(void)fprintf(stderr, " ");
col_c += 3;
}
if (very_verbose_b) {
(void)fprintf(stderr, "%s -- %s (%#lx)\n",
attr_p->at_string, attr_p->at_desc, attr_p->at_value);
col_c = 0;
}
else {
str = attr_p->at_string;
len = strlen(str);
if (col_c + len + 2 > LINE_WIDTH) {
(void)fprintf(stderr, "\n");
(void)fprintf(stderr, " ");
col_c = 3;
}
(void)fprintf(stderr, "%s", str);
col_c += len;
/* if we've got more to go then print the , */
if (work != 0) {
(void)fprintf(stderr, ", ");
col_c += 2;
}
}
if (work == 0) {
break;
}
}
}
if (col_c != 0) {
(void)fprintf(stderr, "\n");
}
if (work != 0) {
(void)fprintf(stderr, "%s: warning, unknown debug flag(s): %#lx\n",
argv_program, work);
}
}
/*
* translate TOK into its proper value which is returned
*/
static long token_to_value(const char *tok)
{
attr_t *attr_p;
/* find the matching attribute string */
for (attr_p = attributes; attr_p->at_string != NULL; attr_p++) {
if (strcmp(tok, attr_p->at_string) == 0) {
break;
}
}
if (attr_p->at_string == NULL) {
(void)fprintf(stderr, "%s: unknown token '%s'\n", argv_program, tok);
return 0;
}
/* if we have a 0 value and not none then this is a disabled token */
if (attr_p->at_value == 0 && strcmp(tok, "none") != 0) {
(void)fprintf(stderr, "%s: token '%s' has been disabled: %s\n",
argv_program, tok, attr_p->at_desc);
return 0;
}
return attr_p->at_value;
}
/*
* Read in the next token from INFILE. It passes back the returned
* debug value in DEBUG_P. Passes back the matching TOKEN of
* TOKEN_SIZE. Returns 1 if there was a next else 0.
*/
static int read_next_token(FILE *infile, long *debug_p,
char *token, const int token_size)
{
int cont_b = 0, found_b = 0;
long new_debug = 0;
char buf[1024], *tok_p, *buf_p;
while (fgets(buf, sizeof(buf), infile) != NULL) {
/* ignore comments and empty lines */
if (buf[0] == '#' || buf[0] == '\n') {
continue;
}
/* chop off the ending \n */
buf_p = strrchr(buf, '\n');
SET_POINTER(buf_p, '\0');
buf_p = buf;
/* if we're not continuing then we need to process a tag */
if (! cont_b) {
/* get the first token on the line */
tok_p = strsep(&buf_p, TOKENIZE_EQUALS);
if (tok_p == NULL) {
continue;
}
if (*tok_p == '\0') {
(void)fprintf(stderr, "Invalid start of line: %s\n", buf_p);
continue;
}
/* save the token */
if (token != NULL) {
(void)strncpy(token, tok_p, token_size);
token[token_size - 1] = '\0';
}
found_b = 1;
}
cont_b = 0;
while (1) {
/* get the next token */
tok_p = strsep(&buf_p, TOKENIZE_CHARS);
if (tok_p == NULL) {
break;
}
if (*tok_p == '\0') {
continue;
}
/* do we have a continuation character? */
if (strcmp(tok_p, "\\") == 0) {
cont_b = 1;
break;
}
new_debug |= token_to_value(tok_p);
}
/* are we done? */
if (! cont_b) {
break;
}
}
SET_POINTER(debug_p, new_debug);
if (found_b) {
return 1;
}
else {
return 0;
}
}
/*
* Read in a rc file from PATH and process it looking for the
* specified DEBUG_VALUE or TAG_FIND token. It passes back the
* returned debug value in DEBUG_P. Passes back the matching TOKEN of
* TOKEN_SIZE.
*
* Returns FILE_NOT_FOUND, FILE_FOUND, or TOKEN_FOUND.
*/
static int read_rc_file(const char *path, const long debug_value,
const char *tag_find, long *debug_p,
char *token, const int token_size)
{
FILE *infile;
int found_b = 0;
char next_token[64];
long new_debug;
/* open the path */
infile = fopen(path, "r");
if (infile == NULL) {
return FILE_NOT_FOUND;
}
/* run through the tokens, looking for a match */
while (read_next_token(infile, &new_debug, next_token,
sizeof(next_token)) == 1) {
/* are we looking for a tag? */
if (tag_find != NULL && strcmp(tag_find, next_token) == 0) {
found_b = 1;
break;
}
/* are we looking for a debug-value? */
if (debug_value > 0 && debug_value == new_debug) {
found_b = 1;
break;
}
}
(void)fclose(infile);
SET_POINTER(debug_p, new_debug);
if (token != NULL) {
(void)loc_snprintf(token, token_size, "config file token: %s",
next_token);
}
if (found_b) {
return TOKEN_FOUND;
}
else {
return FILE_FOUND;
}
}
/*
* Process the user configuration looking for the TAG_FIND. If it is
* null then look for DEBUG_VALUE in the file and copy the token found
* into TOKEN of TOKEN_SIZE. Routine returns the new debug value
* matching tag.
*/
static long find_tag(const long debug_value, const char *tag_find,
char *token, const int token_size)
{
char path[1024], *path_p;
default_t *def_p;
const char *home_p;
int ret;
long new_debug = 0;
/* do we need to have a home variable? */
if (inpath == NULL) {
/* first we try to read the RC file from the current directory */
ret = read_rc_file(DEFAULT_CONFIG, debug_value, tag_find, &new_debug,
token, token_size);
/* did we find the correct value in the file? */
if (ret == TOKEN_FOUND) {
return new_debug;
}
/* if we did not find the file, check the home directory */
if (ret == FILE_FOUND) {
path_p = DEFAULT_CONFIG;
}
else {
/* find our home directory */
home_p = getenv(HOME_ENVIRON);
if (home_p == NULL) {
(void)fprintf(stderr, "%s: could not find variable '%s'\n",
argv_program, HOME_ENVIRON);
exit(1);
}
(void)loc_snprintf(path, sizeof(path), "%s/%s", home_p, DEFAULT_CONFIG);
/* read in the file from our home directory */
ret = read_rc_file(path, debug_value, tag_find, &new_debug,
token, token_size);
/* did we find the correct value in the file? */
if (ret == TOKEN_FOUND) {
return new_debug;
}
if (ret == FILE_FOUND) {
path_p = path;
}
else {
path_p = NULL;
}
}
}
else {
/* read in the specified file */
ret = read_rc_file(inpath, debug_value, tag_find, &new_debug,
token, token_size);
/* did we find the correct value in the file? */
if (ret == TOKEN_FOUND) {
return new_debug;
}
/* if the specified was not found, return error */
if (ret != FILE_FOUND) {
(void)fprintf(stderr, "%s: could not read '%s': ",
argv_program, inpath);
perror("");
exit(1);
}
path_p = inpath;
}
/* if tag-find is NULL we assume we are looking for a debug-value */
if (tag_find == NULL) {
/* now look for the value in the default token list */
if (token != NULL) {
for (def_p = defaults; def_p->de_string != NULL; def_p++) {
if (def_p->de_flags == debug_value) {
(void)loc_snprintf(token, token_size, "internal token: %s",
def_p->de_string);
new_debug = def_p->de_flags;
break;
}
}
if (def_p->de_string == NULL) {
(void)loc_snprintf(token, token_size, "unknown token");
new_debug = 0;
}
}
}
else {
/* now look for the token in the default token list */
for (def_p = defaults; def_p->de_string != NULL; def_p++) {
if (strcmp(tag_find, def_p->de_string) == 0) {
new_debug = def_p->de_flags;
break;
}
}
/* did we not find the token? */
if (def_p->de_string == NULL) {
if (path_p == NULL) {
(void)fprintf(stderr, "%s: unknown tag '%s'\n",
argv_program, tag_find);
}
else {
(void)fprintf(stderr, "%s: could not find tag '%s' in '%s'\n",
argv_program, tag_find, path_p);
}
exit(1);
}
}
return new_debug;
}
/*
* List the tags that in the files.
*/
static void list_tags(void)
{
char path[1024], *path_p, token[80];
default_t *def_p;
const char *home_p;
long new_debug = 0;
FILE *rc_file;
/* do we need to have a home variable? */
if (inpath == NULL) {
/* first we try to read the RC file from the current directory */
rc_file = fopen(DEFAULT_CONFIG, "r");
if (rc_file == NULL) {
/* if no file in current directory, try home directory */
home_p = getenv(HOME_ENVIRON);
if (home_p == NULL) {
(void)fprintf(stderr, "%s: could not find variable '%s'\n",
argv_program, HOME_ENVIRON);
exit(1);
}
(void)loc_snprintf(path, sizeof(path), "%s/%s", home_p, DEFAULT_CONFIG);
path_p = path;
rc_file = fopen(path, "r");
/* we don't check for error right here */
}
else {
path_p = DEFAULT_CONFIG;
}
}
else {
/* open the specified file */
rc_file = fopen(inpath, "r");
/* we assume that if the file was specified, it must be there */
if (rc_file == NULL) {
(void)fprintf(stderr, "%s: could not read '%s': ",
argv_program, inpath);
perror("");
exit(1);
}
path_p = inpath;
}
if (rc_file != NULL) {
(void)fprintf(stderr, "Tags available from '%s':\n", path_p);
while (read_next_token(rc_file, &new_debug, token, sizeof(token)) == 1) {
if (verbose_b) {
(void)fprintf(stderr, "%s (%#lx):\n", token, new_debug);
dump_debug(new_debug);
}
else {
(void)fprintf(stderr, "%s\n", token);
}
}
(void)fclose(rc_file);
}
(void)fprintf(stderr, "\n");
(void)fprintf(stderr, "Tags available by default:\n");
for (def_p = defaults; def_p->de_string != NULL; def_p++) {
if (verbose_b) {
(void)fprintf(stderr, "%s (%#lx):\n",
def_p->de_string, def_p->de_flags);
dump_debug(def_p->de_flags);
}
else {
(void)fprintf(stderr, "%s\n", def_p->de_string);
}
}
}
/*
* dump the current settings of the malloc variables
*/
static void dump_current(void)
{
char *log_path, *loc_start_file, token[64];
const char *env_str;
DMALLOC_PNT addr;
unsigned long inter, limit_val, loc_start_size, loc_start_iter;
long addr_count;
int lock_on, loc_start_line;
unsigned int flags;
/* get the options flag */
env_str = getenv(OPTIONS_ENVIRON);
if (env_str == NULL) {
env_str = "";
}
_dmalloc_environ_process(env_str, &addr, &addr_count, &flags,
&inter, &lock_on, &log_path,
&loc_start_file, &loc_start_line, &loc_start_iter,
&loc_start_size, &limit_val);
if (flags == 0) {
(void)fprintf(stderr, "Debug-Flags not-set\n");
}
else {
(void)find_tag(flags, NULL, token, sizeof(token));
(void)fprintf(stderr, "Debug-Flags %#x (%u) (%s)\n",
flags, flags, token);
if (verbose_b) {
dump_debug(flags);
}
}
if (addr == NULL) {
(void)fprintf(stderr, "Address not-set\n");
}
else {
if (addr_count == 0) {
(void)fprintf(stderr, "Address %#lx\n", (long)addr);
}
else {
(void)fprintf(stderr, "Address %#lx, count = %lu\n",
(long)addr, addr_count);
}
}
if (inter == 0) {
(void)fprintf(stderr, "Interval not-set\n");
}
else {
(void)fprintf(stderr, "Interval %lu\n", inter);
}
if (lock_on == 0) {
(void)fprintf(stderr, "Lock-On not-set\n");
}
else {
(void)fprintf(stderr, "Lock-On %d\n", lock_on);
}
if (log_path == NULL) {
(void)fprintf(stderr, "Logpath not-set\n");
}
else {
(void)fprintf(stderr, "Logpath '%s'\n", log_path);
}
if (limit_val == 0) {
(void)fprintf(stderr, "Mem-Limit not-set\n");
}
else {
(void)fprintf(stderr, "Mem-Limit %lu\n", limit_val);
}
if (loc_start_file != NULL) {
(void)fprintf(stderr, "Start-File '%s', line = %d\n",
loc_start_file, loc_start_line);
}
else if (loc_start_iter > 0) {
(void)fprintf(stderr, "Start-Count %lu\n", loc_start_iter);
}
else if (loc_start_size > 0) {
(void)fprintf(stderr, "Start-Size %lu\n", loc_start_size);
}
else {
(void)fprintf(stderr, "Start not-set\n");
}
(void)fprintf(stderr, "\n");
(void)fprintf(stderr, "Debug Malloc Utility: http://dmalloc.com/\n");
(void)fprintf(stderr,
" For a list of the command-line options enter: %s --usage\n",
argv_argv[0]);
}
/*
* output the code to set env VAR to VALUE
*/
static void set_variable(const char *var, const char *value)
{
char comm[1024];
if (value == NULL || *value == '\0') {
(void)loc_snprintf(comm, sizeof(comm), "unset %s\n", var);
}
else if (bourne_b) {
(void)loc_snprintf(comm, sizeof(comm), "%s=%s\nexport %s\n",
var, value, var);
}
else if (rcshell_b) {
(void)loc_snprintf(comm, sizeof(comm), "%s='%s'\n", var, value);
}
else if (gdb_b) {
(void)loc_snprintf(comm, sizeof(comm), "set env %s %s\n", var, value);
}
else {
(void)loc_snprintf(comm, sizeof(comm), "setenv %s %s\n", var, value);
}
if (make_changes_b) {
(void)printf("%s", comm);
}
if ((! make_changes_b) || verbose_b) {
(void)fprintf(stderr, "Outputed:\n");
(void)fprintf(stderr, "%s", comm);
}
}
/*
* Returns the string for ERROR_NUM.
*/
static char *local_strerror(const int error_num)
{
error_str_t *err_p;
for (err_p = error_list; err_p->es_error != 0; err_p++) {
if (err_p->es_error == error_num) {
return err_p->es_string;
}
}
return INVALID_ERROR;
}
/*
* static void header
*
* DESCRIPTION:
*
* Print out a little usage header to the user.
*
* RETURNS:
*
* None.
*
* ARGUMENTS:
*
* None.
*/
static void header(void)
{
(void)fprintf(stderr,
"Debug Malloc Utility: http://dmalloc.com/\n");
(void)fprintf(stderr,
" This utility helps set the Debug Malloc environment variables.\n");
}
int main(int argc, char **argv)
{
char buf[1024];
int set_b = 0;
char *log_path, *loc_start_file;
const char *env_str;
DMALLOC_PNT addr;
unsigned long inter, limit_val, loc_start_size, loc_start_iter;
unsigned long addr_count;
int lock_on;
int loc_start_line;
unsigned int flags;
argv_help_string = "Sets dmalloc library env variables. Also try --usage.";
argv_version_string = dmalloc_version;
argv_usage_type = ARGV_USAGE_LONG;
argv_error_type = ARGV_USAGE_SHORT_REM;
argv_process(args, argc, argv);
if (help_b) {
header();
(void)fprintf(stderr,
" For a list of the command-line options enter: %s --usage\n",
argv_argv[0]);
exit(0);
}
if (usage_b) {
header();
argv_usage(args, argv_usage_type);
exit(0);
}
if (version_b) {
(void)fprintf(stderr, "Dmalloc utility version string is: %s\n",
argv_version_string);
(void)fprintf(stderr,
" NOTE: Library linked with your application may be a different version.\n");
(void)fprintf(stderr,
" Check top of logfile after application is run for library version.\n");
exit(0);
}
if (very_verbose_b) {
verbose_b = 1;
}
/* try to figure out the shell we are using */
if ((! bourne_b) && (! cshell_b) && (! gdb_b) && (! rcshell_b)) {
choose_shell();
}
/* get the current debug information from the env variable */
env_str = getenv(OPTIONS_ENVIRON);
if (env_str == NULL) {
env_str = "";
}
_dmalloc_environ_process(env_str, &addr, &addr_count, &flags, &inter,
&lock_on, &log_path, &loc_start_file,
&loc_start_line, &loc_start_iter, &loc_start_size,
&limit_val);
/*
* So, if a tag was specified on the command line then we set the
* debug from it. If it was not then we see if the debug flags were
* set as a hex value from the -d. If this was not used then take
* the current value.
*/
if (tag == NULL) {
if (argv_was_used(args, DEBUG_ARG)) {
set_b = 1;
/* should we clear the rest? */
if (remove_auto_b && (! keep_b)) {
clear_b = 1;
}
}
else {
debug = flags;
}
}
else {
if (argv_was_used(args, DEBUG_ARG)) {
(void)fprintf(stderr, "%s: warning -d ignored, processing tag '%s'\n",
argv_program, tag);
}
set_b = 1;
debug = find_tag(0L, tag, NULL, 0);
/* should we clear the rest? */
if (remove_auto_b && (! keep_b)) {
clear_b = 1;
}
}
if (plus.aa_entry_n > 0) {
int plus_c;
for (plus_c = 0; plus_c < plus.aa_entry_n; plus_c++) {
BIT_SET(debug, token_to_value(ARGV_ARRAY_ENTRY(plus, char *, plus_c)));
set_b = 1;
}
}
if (minus.aa_entry_n > 0) {
int minus_c;
for (minus_c = 0; minus_c < minus.aa_entry_n; minus_c++) {
BIT_CLEAR(debug,
token_to_value(ARGV_ARRAY_ENTRY(minus, char *, minus_c)));
set_b = 1;
}
}
if (address != NULL) {
_dmalloc_address_break(address, &addr, &addr_count);
set_b = 1;
}
else if (clear_b) {
addr = NULL;
}
if (argv_was_used(args, INTERVAL_ARG)) {
inter = interval;
set_b = 1;
}
else if (clear_b) {
inter = 0;
}
/*
* NOTE: this should be after the debug setting which this tests.
*/
if (argv_was_used(args, THREAD_LOCK_ON_ARG)) {
lock_on = thread_lock_on;
set_b = 1;
}
else if (clear_b) {
lock_on = 0;
}
if (logpath != NULL) {
log_path = logpath;
set_b = 1;
}
else if (clear_b) {
log_path = NULL;
}
if (start_file != NULL) {
_dmalloc_start_break(start_file, &loc_start_file, &loc_start_line,
&loc_start_iter, &loc_start_size);
set_b = 1;
}
else if (start_iter > 0) {
loc_start_file = NULL;
loc_start_line = 0;
loc_start_iter = start_iter;
loc_start_size = 0;
set_b = 1;
}
else if (start_size > 0) {
loc_start_file = NULL;
loc_start_line = 0;
loc_start_iter = 0;
loc_start_size = start_size;
set_b = 1;
}
else if (clear_b) {
loc_start_file = NULL;
loc_start_line = 0;
loc_start_iter = 0;
loc_start_size = 0;
}
if (argv_was_used(args, LIMIT_ARG)) {
limit_val = limit_arg;
set_b = 1;
}
if (errno_to_print > 0) {
(void)fprintf(stderr, "%s: dmalloc_errno value '%d' = \n",
argv_program, errno_to_print);
(void)fprintf(stderr, " '%s'\n", local_strerror(errno_to_print));
}
if (list_tags_b) {
list_tags();
}
if (debug_tokens_b) {
attr_t *attr_p;
unsigned int left = 0x7fffffff;
(void)fprintf(stderr, "Debug Tokens:\n");
for (attr_p = attributes; attr_p->at_string != NULL; attr_p++) {
/* skip any disabled tokens */
if (attr_p->at_value == 0 && strcmp(attr_p->at_string, "none") != 0) {
continue;
}
if (attr_p->at_value != 0 && (! BIT_IS_SET(left, attr_p->at_value))) {
/* skip any tokens we've seen before */
continue;
}
if (very_verbose_b) {
(void)fprintf(stderr, "%s -- %s (%#lx)\n",
attr_p->at_string, attr_p->at_desc, attr_p->at_value);
}
else if (verbose_b) {
(void)fprintf(stderr, "%s -- %s\n",
attr_p->at_string, attr_p->at_desc);
}
else {
(void)fprintf(stderr, "%s\n", attr_p->at_string);
}
BIT_CLEAR(left, attr_p->at_value);
}
}
if (clear_b || set_b) {
_dmalloc_environ_set(buf, sizeof(buf), long_tokens_b, addr, addr_count,
debug, inter, lock_on, log_path, loc_start_file,
loc_start_line, loc_start_iter, loc_start_size,
limit_val);
set_variable(OPTIONS_ENVIRON, buf);
}
else if (errno_to_print == 0
&& (! list_tags_b)
&& (! debug_tokens_b)) {
dump_current();
}
argv_cleanup(args);
exit(0);
}