/* * 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; } } }
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; 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_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_ALL); 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); }