コード例 #1
0
static void _process_start(List job_list, char *f[], int lc,
			   int show_full, int len)
{
	filetxt_job_rec_t *job = NULL;
	filetxt_job_rec_t *temp = NULL;

	_parse_line(f, (void **)&temp, len);
	job = _find_job_record(job_list, temp->header, JOB_START);
	if (job) {
		/* in slurm we can get 2 start records one for submit
		 * and one for start, so look at the last one */
		xfree(job->jobname);
		job->jobname = xstrdup(temp->jobname);
		job->track_steps = temp->track_steps;
		job->priority = temp->priority;
		job->ncpus = temp->ncpus;
		xfree(job->nodes);
		job->nodes = xstrdup(temp->nodes);
		xfree(job->account);
		job->account = xstrdup(temp->account);

		_destroy_filetxt_job_rec(temp);
		return;
	}

	job = temp;
	job->show_full = show_full;
	list_append(job_list, job);
	job->job_start_seen = 1;

}
コード例 #2
0
static void _process_terminated(List job_list, char *f[], int lc,
				int show_full, int len)
{
	filetxt_job_rec_t *job = NULL;
	filetxt_job_rec_t *temp = NULL;

	_parse_line(f, (void **)&temp, len);

	if (temp == NULL) {
		error("Unknown proccess terminated");
		return;
	}

	job = _find_job_record(job_list, temp->header, JOB_TERMINATED);
	if (!job) {	/* fake it for now */
		job = _create_filetxt_job_rec(temp->header);
		job->jobname = xstrdup("(unknown)");
		debug("Note: JOB_TERMINATED record for job "
		      "%u preceded "
		      "other job records at line %d\n",
		      temp->header.jobnum, lc);
	} else if (job->job_terminated_seen) {
		if (temp->status == JOB_NODE_FAIL) {
			/* multiple node failures - extra TERMINATED records */
			debug("Note: Duplicate JOB_TERMINATED "
			      "record (nf) for job %u at "
			      "line %d\n",
			      temp->header.jobnum, lc);
			/* JOB_TERMINATED/NF records may be preceded
			 * by a JOB_TERMINATED/CA record; NF is much
			 * more interesting.
			 */
			job->status = temp->status;
			goto finished;
		}

		fprintf(stderr,
			"Conflicting JOB_TERMINATED record (%s) for "
			"job %u at line %d -- ignoring it\n",
			job_state_string(temp->status),
			job->header.jobnum, lc);
		goto finished;
	}
	job->job_terminated_seen = 1;
	job->elapsed = temp->elapsed;
	job->end = temp->header.timestamp;
	job->status = temp->status;
	job->requid = temp->requid;
	job->exitcode = temp->exitcode;
	if (list_count(job->steps) > 1)
		job->track_steps = 1;
	job->show_full = show_full;

finished:
	_destroy_filetxt_job_rec(temp);
}
コード例 #3
0
static void _process_suspend(List job_list, char *f[], int lc,
			     int show_full, int len)
{
	filetxt_job_rec_t *job = NULL;
	filetxt_job_rec_t *temp = NULL;

	_parse_line(f, (void **)&temp, len);
	job = _find_job_record(job_list, temp->header, JOB_SUSPEND);
	if (!job)  {	/* fake it for now */
		job = _create_filetxt_job_rec(temp->header);
		job->jobname = xstrdup("(unknown)");
	}

	job->show_full = show_full;
	if (job->status == JOB_SUSPENDED)
		job->elapsed -= temp->elapsed;

	//job->header.timestamp = temp->header.timestamp;
	job->status = temp->status;
	_destroy_filetxt_job_rec(temp);
}
コード例 #4
0
static void _process_step(List job_list, char *f[], int lc,
			  int show_full, int len)
{
	filetxt_job_rec_t *job = NULL;

	filetxt_step_rec_t *step = NULL;
	filetxt_step_rec_t *temp = NULL;

	_parse_line(f, (void **)&temp, len);

	job = _find_job_record(job_list, temp->header, JOB_STEP);

	if (temp->stepnum == -2) {
		_destroy_filetxt_step_rec(temp);
		return;
	}
	if (!job) {	/* fake it for now */
		job = _create_filetxt_job_rec(temp->header);
		job->jobname = xstrdup("(unknown)");
		debug2("Note: JOB_STEP record %u.%u preceded "
		       "JOB_START record at line %d\n",
		       temp->header.jobnum, temp->stepnum, lc);
	}
	job->show_full = show_full;

	if ((step = _find_step_record(job, temp->stepnum))) {

		if (temp->status == JOB_RUNNING) {
			_destroy_filetxt_step_rec(temp);
			return;/* if "R" record preceded by F or CD; unusual */
		}
		if (step->status != JOB_RUNNING) { /* if not JOB_RUNNING */
			fprintf(stderr,
				"Conflicting JOB_STEP record for "
				"jobstep %u.%u at line %d "
				"-- ignoring it\n",
				step->header.jobnum,
				step->stepnum, lc);
			_destroy_filetxt_step_rec(temp);
			return;
		}
		step->status = temp->status;
		step->exitcode = temp->exitcode;
		step->ntasks = temp->ntasks;
		step->ncpus = temp->ncpus;
		step->elapsed = temp->elapsed;
		step->tot_cpu_sec = temp->tot_cpu_sec;
		step->tot_cpu_usec = temp->tot_cpu_usec;
		job->requid = temp->requid;
		step->requid = temp->requid;
		memcpy(&step->rusage, &temp->rusage, sizeof(struct rusage));
		memcpy(&step->stats, &temp->stats, sizeof(slurmdb_stats_t));
		xfree(step->stepname);
		step->stepname = xstrdup(temp->stepname);
		step->end = temp->header.timestamp;
		_destroy_filetxt_step_rec(temp);
		goto got_step;
	}
	step = temp;
	temp = NULL;
	list_append(job->steps, step);
	if (!job->track_steps) {
		/* If we don't have track_steps we want to see
		   if we have multiple steps.  If we only have
		   1 step check the job name against the step
		   name in most all cases it will be
		   different.  If it is different print out
		   the step separate.
		*/
		if (list_count(job->steps) > 1)
			job->track_steps = 1;
		else if (step && step->stepname && job->jobname) {
			if (strcmp(step->stepname, job->jobname))
				job->track_steps = 1;
		}
	}

	if (job->header.timestamp == 0)
		job->header.timestamp = step->header.timestamp;
	job->job_step_seen = 1;
	job->ntasks += step->ntasks;
	if (!job->nodes || !strcmp(job->nodes, "(unknown)")) {
		xfree(job->nodes);
		job->nodes = xstrdup(step->nodes);
	}

got_step:

	if (job->job_terminated_seen == 0) {	/* If the job is still running,
						   this is the most recent
						   status */
		if ( job->exitcode == 0 )
			job->exitcode = step->exitcode;
		job->status = JOB_RUNNING;
		job->elapsed = step->header.timestamp - job->header.timestamp;
	}
}
コード例 #5
0
ファイル: filetxt_jobcomp_process.c プロジェクト: VURM/slurm
extern List filetxt_jobcomp_process_get_jobs(slurmdb_job_cond_t *job_cond)
{
	char line[BUFFER_SIZE];
	char *fptr = NULL, *filein = NULL;
	int jobid = 0;
	char *partition = NULL;
	FILE *fd = NULL;
	int lc = 0;
	jobcomp_job_rec_t *job = NULL;
	slurmdb_selected_step_t *selected_step = NULL;
	char *selected_part = NULL;
	ListIterator itr = NULL;
	List job_info_list = NULL;
	filetxt_jobcomp_info_t *jobcomp_info = NULL;
	List job_list = list_create(jobcomp_destroy_job);
	int fdump_flag = 0;

	/* we grab the fdump only for the filetxt plug through the
	   FDUMP_FLAG on the job_cond->duplicates variable.  We didn't
	   add this extra field to the structure since it only applies
	   to this plugin.
	*/
	if(job_cond) {
		fdump_flag = job_cond->duplicates & FDUMP_FLAG;
		job_cond->duplicates &= (~FDUMP_FLAG);
	}

	filein = slurm_get_jobcomp_loc();
	fd = _open_log_file(filein);

	while (fgets(line, BUFFER_SIZE, fd)) {
		lc++;
		fptr = line;	/* break the record into NULL-
				   terminated strings */
		if(job_info_list)
			list_destroy(job_info_list);
		jobid = 0;
		partition = NULL;
		job_info_list = list_create(_destroy_filetxt_jobcomp_info);
		while(fptr) {
			jobcomp_info =
				xmalloc(sizeof(filetxt_jobcomp_info_t));
			list_append(job_info_list, jobcomp_info);
			jobcomp_info->name = fptr;
			fptr = strstr(fptr, "=");
			*fptr++ = 0;
			jobcomp_info->val = fptr;
			fptr = strstr(fptr, " ");
			if(!strcasecmp("JobId", jobcomp_info->name))
				jobid = atoi(jobcomp_info->val);
			else if(!strcasecmp("Partition",
					    jobcomp_info->name))
				partition = jobcomp_info->val;


			if(!fptr) {
				fptr = strstr(jobcomp_info->val, "\n");
				if (fptr)
					*fptr = 0;
				break;
			} else {
				*fptr++ = 0;
				if(*fptr == '\n') {
					*fptr = 0;
					break;
				}
			}
		}

		if (job_cond->step_list && list_count(job_cond->step_list)) {
			if(!jobid)
				continue;
			itr = list_iterator_create(job_cond->step_list);
			while((selected_step = list_next(itr))) {
				if (selected_step->jobid == jobid)
					continue;
				/* job matches */
				list_iterator_destroy(itr);
				goto foundjob;
			}
			list_iterator_destroy(itr);
			continue;	/* no match */
		}
	foundjob:

		if (job_cond->partition_list
		    && list_count(job_cond->partition_list)) {
			if(!partition)
				continue;
			itr = list_iterator_create(job_cond->partition_list);
			while((selected_part = list_next(itr)))
				if (!strcasecmp(selected_part, partition)) {
					list_iterator_destroy(itr);
					goto foundp;
				}
			list_iterator_destroy(itr);
			continue;	/* no match */
		}
	foundp:

		if (fdump_flag) {
			_do_fdump(job_info_list, lc);
			continue;
		}


		job = _parse_line(job_info_list);

		if(job)
			list_append(job_list, job);
	}

	if(job_info_list)
		list_destroy(job_info_list);

	if (ferror(fd)) {
		perror(filein);
		xfree(filein);
		exit(1);
	}
	fclose(fd);
	xfree(filein);

	return job_list;
}
コード例 #6
0
ファイル: env_cache_builder.c プロジェクト: A1ve5/slurm
main (int argc, char **argv)
{
	FILE *passwd_fd;
	char cache_dir[256], in_line[256], *user_name;
	int i, failures = 0, user_cnt = 0, user_id;
	long int delta_t;
	struct stat buf;

	if (geteuid() != (uid_t) 0) {
		printf("Need to run as user root\n");
		exit(1);
	}

	if (_get_cache_dir(cache_dir, sizeof(cache_dir)))
		exit(1);
	strncat(cache_dir, "/env_cache", sizeof(cache_dir));
	if (mkdir(cache_dir, 0500) && (errno != EEXIST)) {
		printf("Could not create cache directory %s: %s\n", cache_dir,
			strerror(errno));
		exit(1);
	}

	if (stat("/bgl", &buf) == 0) {
		printf("BlueGene Note: Execute only a a front-end node, "
			"not the service node\n");
		printf("               User logins to the service node are "
			"disabled\n\n");
	}
	if (stat("/bin/su", &buf)) {
		printf("Could not locate command: /bin/su\n");
		exit(1);
	}
	if (stat("/bin/echo", &buf)) {
		printf("Could not locate command: /bin/echo\n");
		exit(1);
	}
	if (stat("/bin/env", &buf) == 0)
		env_loc = "/bin/env";
	else if (stat("/usr/bin/env", &buf) == 0)
		env_loc = "/usr/bin/env";
	else {
		printf("Could not location command: env\n");
		exit(1);
	}

	printf("Building user environment cache files for Moab/Slurm.\n");
	printf("This will take a while.\n\n");

	for (i=1; i<argc; i++) {
		delta_t = _build_cache(argv[i], cache_dir);
		if (delta_t == -1)
			failures++;
		if (delta_t < ((SU_WAIT_MSEC * 0.8) * 1000))
			continue;
		printf("WARNING: user %-8s time %ld usec\n", argv[i], delta_t);
	}
	if (i > 1) {
		_log_failures(failures, cache_dir);
		exit(0);
	}

	passwd_fd = fopen("/etc/passwd", "r");
	if (!passwd_fd) {
		perror("fopen(/etc/passwd)");
		exit(1);
	}

	while (fgets(in_line, sizeof(in_line), passwd_fd)) {
		if (_parse_line(in_line, &user_name, &user_id) < 0)
			continue;
		if (user_id <= 100)
			continue;
		delta_t = _build_cache(user_name, cache_dir);
		if (delta_t == -1)
			failures++;
		user_cnt++;
		if ((user_cnt % 100) == 0)
			printf("Processed %d users...\n", user_cnt);
		if (delta_t < ((SU_WAIT_MSEC * 0.8) * 1000))
			continue;
		printf("WARNING: user %-8s time %ld usec\n", user_name, delta_t);
	}
	fclose(passwd_fd);
	_log_failures(failures, cache_dir);
}
コード例 #7
0
ファイル: filetxt_jobcomp_process.c プロジェクト: IFCA/slurm
extern List filetxt_jobcomp_process_get_jobs(slurmdb_job_cond_t *job_cond)
{
	char line[BUFFER_SIZE];
	char *fptr = NULL, *filein = NULL;
	int jobid = 0;
	char *partition = NULL;
	FILE *fd = NULL;
	int lc = 0;
	jobcomp_job_rec_t *job = NULL;
	slurmdb_selected_step_t *selected_step = NULL;
	char *selected_part = NULL;
	ListIterator itr = NULL;
	List job_info_list = NULL;
	filetxt_jobcomp_info_t *jobcomp_info = NULL;
	List job_list = list_create(jobcomp_destroy_job);

	filein = slurm_get_jobcomp_loc();
	fd = _open_log_file(filein);

	while (fgets(line, BUFFER_SIZE, fd)) {
		lc++;
		fptr = line;	/* break the record into NULL-
				   terminated strings */
		if (job_info_list)
			list_destroy(job_info_list);
		jobid = 0;
		partition = NULL;
		job_info_list = list_create(_destroy_filetxt_jobcomp_info);
		while(fptr) {
			jobcomp_info =
				xmalloc(sizeof(filetxt_jobcomp_info_t));
			list_append(job_info_list, jobcomp_info);
			jobcomp_info->name = fptr;
			fptr = strstr(fptr, "=");
			*fptr++ = 0;
			jobcomp_info->val = fptr;
			fptr = strstr(fptr, " ");
			if (!strcasecmp("JobId", jobcomp_info->name))
				jobid = atoi(jobcomp_info->val);
			else if (!strcasecmp("Partition",
					    jobcomp_info->name))
				partition = jobcomp_info->val;


			if (!fptr) {
				fptr = strstr(jobcomp_info->val, "\n");
				if (fptr)
					*fptr = 0;
				break;
			} else {
				*fptr++ = 0;
				if (*fptr == '\n') {
					*fptr = 0;
					break;
				}
			}
		}

		if (job_cond->step_list && list_count(job_cond->step_list)) {
			if (!jobid)
				continue;
			itr = list_iterator_create(job_cond->step_list);
			while((selected_step = list_next(itr))) {
				if (selected_step->jobid == jobid)
					continue;
				/* job matches */
				list_iterator_destroy(itr);
				goto foundjob;
			}
			list_iterator_destroy(itr);
			continue;	/* no match */
		}
	foundjob:

		if (job_cond->partition_list
		    && list_count(job_cond->partition_list)) {
			if (!partition)
				continue;
			itr = list_iterator_create(job_cond->partition_list);
			while((selected_part = list_next(itr)))
				if (!strcasecmp(selected_part, partition)) {
					list_iterator_destroy(itr);
					goto foundp;
				}
			list_iterator_destroy(itr);
			continue;	/* no match */
		}
	foundp:

		job = _parse_line(job_info_list);

		if (job)
			list_append(job_list, job);
	}

	if (job_info_list)
		list_destroy(job_info_list);

	if (ferror(fd)) {
		perror(filein);
		xfree(filein);
		exit(1);
	}
	fclose(fd);
	xfree(filein);

	return job_list;
}
コード例 #8
0
ファイル: smf_settings.c プロジェクト: drobin/spmfilter
int smf_settings_parse_config(SMFSettings_T **settings, char *alternate_file) {
    FILE *in = NULL;
    char line[MAX_LINE+1];
    char section[MAX_LINE+1];
    char key[MAX_LINE+1];
    char val[MAX_LINE+1];
    SMFList_T *list = NULL;
    SMFListElem_T *elem = NULL;
    char *s = NULL;
    int last=0;
    int len=0;
    int lineno=0;
    int errs=0;
    char *clean_section = NULL;
    char *clean_key = NULL;
    char *clean_val = NULL;
    char *tmp = NULL;
    SMFModule_T *mod = NULL;

    assert(*settings);

    /* fallback to default config path,
     * if config file is not defined as
     * command argument */
    if (alternate_file != NULL) {
        (*settings)->config_file = strdup(alternate_file);
    } else {
        (*settings)->config_file = strdup("/etc/spmfilter.conf");
    }

    if ((in=fopen((*settings)->config_file, "r")) == NULL) {
        TRACE(TRACE_ERR,"Error loading config: %s (%d)",strerror(errno), errno);
        perror("spmfilter: failed to load config file");
        return -1;
    }

    memset(line, 0, MAX_LINE);
    memset(section, 0, MAX_LINE);
    memset(key, 0, MAX_LINE);
    memset(val, 0, MAX_LINE);

    while (fgets(line+last, MAX_LINE-last, in) != NULL) {
        lineno++ ;
        len = (int)strlen(line)-1;
        if (len==0)
            continue;
        
        if (len > MAX_LINE) {
            TRACE(TRACE_ERR,"input line too long in %s (%d)\n", (*settings)->config_file, lineno);
            fclose(in);
            return -1;
        }

        /* Detect multi-line */
        if (line[len]=='\\') {
            /* Multi-line value */
            last=len;
            continue;
        } else {
            last=0;
        }
        switch (_parse_line(line, section, key, val)) {
            case LINE_EMPTY:
            case LINE_COMMENT:
                break;

            case LINE_SECTION:
                clean_section = smf_core_strstrip(section);
                break;

            case LINE_VALUE:
                clean_key = smf_core_strstrip(key);
                clean_val = smf_core_strstrip(val);

                if ((strcmp(clean_section,"global")==0)
                        ||(strcmp(clean_section,"smtpd")==0)
                        ||(strcmp(clean_section,"sql")==0)
                        ||(strcmp(clean_section,"ldap")==0)) {
                    _set_config_value(settings,clean_section,clean_key,clean_val);
                } else {
                    asprintf(&tmp,"%s:%s",clean_section,clean_key);
                    if (smf_dict_set((*settings)->groups,tmp,clean_val)!=0) {
                        errs++;
                        TRACE(TRACE_ERR,"failed to set config value: %s:%s=>%s");
                    }
                    free(tmp);
                }
                break;

            case LINE_ERROR:
                TRACE(TRACE_ERR, "syntax error in %s (%d): %s",
                    (*settings)->config_file,
                    lineno,line);
                errs++;
                break;

            default:
                break;
        }
        memset(line, 0, MAX_LINE);

        last=0;
        if (errs<0) {
            TRACE(TRACE_ERR, "memory allocation failure");
            break ;
        }
    }

    if (fclose(in)!=0)
        TRACE(TRACE_ERR,"failed to close config file: %s (%d)",strerror(errno), errno);

    // check defaults
    if ((*settings)->queue_dir == NULL) {
        (*settings)->queue_dir = strdup("/var/spool/spmfilter");
        TRACE(TRACE_DEBUG,"config value queue_dir not set, using default");
    }

    if ((*settings)->engine == NULL) {
        TRACE(TRACE_ERR,"config value engine not set");
        return -1;
    }

    if ((*settings)->backend_connection == NULL) 
        (*settings)->backend_connection = strdup("failover");

    if ((*settings)->backend != NULL) {
        /** sql checks **/
        if (strcmp((*settings)->backend,"sql")==0) {
            if ((*settings)->sql_driver==NULL) {
                TRACE(TRACE_ERR, "no database driver set");
                return -1;
            }
            if ((*settings)->sql_name==NULL) {
                TRACE(TRACE_ERR, "config value sql name not set");
                return -1;
            }

            if ((strcmp((*settings)->sql_driver,"mysql")==0)||(strcmp((*settings)->sql_driver,"pgsql")==0)) {
                if (smf_list_size((*settings)->sql_host)==0){
                    TRACE(TRACE_ERR, "no sql host set");
                    return -1;
                }
            }

            if (strcmp((*settings)->sql_driver,"mysql")==0) {
                if ((*settings)->sql_port == 0)
                    (*settings)->sql_port = 3306;
            }

            if (strcmp((*settings)->sql_driver,"pgsql")==0) {
                if ((*settings)->sql_port == 0)
                    (*settings)->sql_port = 5432;
            }        
        }

        /** ldap checks **/
        if (strcmp((*settings)->backend,"ldap")==0) {
            if ((*settings)->ldap_port == 0)
                (*settings)->ldap_port = 389;

            if ((*settings)->ldap_base == NULL) {
                TRACE(TRACE_ERR, "no ldap search base set");
                return -1;
            }

            if ((*settings)->ldap_scope != NULL) {
                if ((strcmp((*settings)->ldap_scope,"base")!=0)
                        && (strcmp((*settings)->ldap_scope,"onlevel")!=0)
                        && (strcmp((*settings)->ldap_scope,"subtree")!=0)) {
                    TRACE(TRACE_ERR, "invalid ldap search scope");
                    return -1;
                }
            } else
                (*settings)->ldap_scope = strdup("subtree");
        }
    }

    TRACE(TRACE_DEBUG, "settings->queue_dir: [%s]", (*settings)->queue_dir);
    TRACE(TRACE_DEBUG, "settings->engine: [%s]", (*settings)->engine);
    elem = smf_list_head((*settings)->modules);
    while(elem != NULL) {
        mod = (SMFModule_T *)smf_list_data(elem);
        TRACE(TRACE_DEBUG, "settings->modules: [%s]", mod->name);
        elem = elem->next;
    }
    TRACE(TRACE_DEBUG, "settings->module_fail [%d]",(*settings)->module_fail);
    TRACE(TRACE_DEBUG, "settings->nexthop: [%s]", (*settings)->nexthop);
    TRACE(TRACE_DEBUG, "settings->backend: [%s]", (*settings)->backend);
    TRACE(TRACE_DEBUG, "settings->backend_connection: [%s]", (*settings)->backend_connection);
    TRACE(TRACE_DEBUG, "settings->add_header: [%d]", (*settings)->add_header);
    TRACE(TRACE_DEBUG, "settings->max_size: [%d]", (*settings)->max_size);
    TRACE(TRACE_DEBUG, "settings->tls: [%d]", (*settings)->tls);
    TRACE(TRACE_DEBUG, "settings->lib_dir: [%s]", (*settings)->lib_dir);
    TRACE(TRACE_DEBUG, "settings->pid_file: [%s]", (*settings)->pid_file);
    TRACE(TRACE_DEBUG, "settings->bind_ip: [%s]", (*settings)->bind_ip);
    TRACE(TRACE_DEBUG, "settings->bind_port: [%d]", (*settings)->bind_port);
    TRACE(TRACE_DEBUG, "settings->listen_backlog: [%d]", (*settings)->listen_backlog);
    TRACE(TRACE_DEBUG, "settings->foreground: [%d]", (*settings)->foreground);
    TRACE(TRACE_DEBUG, "settings->user: [%s]", (*settings)->user);
    TRACE(TRACE_DEBUG, "settings->group: [%s]", (*settings)->group);
    TRACE(TRACE_DEBUG, "settings->max_childs: [%d]", (*settings)->max_childs);
    TRACE(TRACE_DEBUG, "settings->spare_childs: [%d]", (*settings)->spare_childs);
    TRACE(TRACE_DEBUG, "settings->lookup_persistent: [%d]", (*settings)->lookup_persistent);
    TRACE(TRACE_DEBUG, "settings->syslog_facility: [%d]", (*settings)->syslog_facility);

    TRACE(TRACE_DEBUG, "settings->sql_driver: [%s]", (*settings)->sql_driver);
    TRACE(TRACE_DEBUG, "settings->sql_name: [%s]", (*settings)->sql_name);
    elem = smf_list_head((*settings)->sql_host);
    while(elem != NULL) {
        s = (char *)smf_list_data(elem);
        TRACE(TRACE_DEBUG, "settings->sql_host: [%s]", s);
        elem = elem->next;
    }
    TRACE(TRACE_DEBUG, "settings->sql_user: [%s]", (*settings)->sql_user);
    TRACE(TRACE_DEBUG, "settings->sql_pass: [%s]", (*settings)->sql_pass);
    TRACE(TRACE_DEBUG, "settings->sql_user_query: [%s]", (*settings)->sql_user_query);
    TRACE(TRACE_DEBUG, "settings->encoding: [%s]", (*settings)->sql_encoding);
    TRACE(TRACE_DEBUG, "settings->max_connections: [%d]", (*settings)->sql_max_connections);
    TRACE(TRACE_DEBUG, "settings->port: [%d]", (*settings)->sql_port);

    TRACE(TRACE_DEBUG, "settings->ldap_uri: [%s]", (*settings)->ldap_uri);
    elem = smf_list_head((*settings)->ldap_host);
    while(elem != NULL) {
        s = (char *)smf_list_data(elem);
        TRACE(TRACE_DEBUG, "settings->ldap_host: [%s]", s);
        elem = elem->next;
    }
    TRACE(TRACE_DEBUG, "settings->ldap_port: [%d]", (*settings)->ldap_port);
    TRACE(TRACE_DEBUG, "settings->ldap_binddn: [%s]", (*settings)->ldap_binddn);
    TRACE(TRACE_DEBUG, "settings->ldap_bindpw: [%s]", (*settings)->ldap_bindpw);
    TRACE(TRACE_DEBUG, "settings->ldap_base: [%s]", (*settings)->ldap_base);
    TRACE(TRACE_DEBUG, "settings->ldap_user_query: [%s]", (*settings)->ldap_user_query);
    TRACE(TRACE_DEBUG, "settings->ldap_scope: [%s]", (*settings)->ldap_scope);
    TRACE(TRACE_DEBUG, "settings->ldap_referrals: [%d]", (*settings)->ldap_referrals);

    /** smtpd checks **/
    if ((*settings)->nexthop_fail_msg == NULL)
        (*settings)->nexthop_fail_msg = strdup("Requested action aborted: local error in processing");

    TRACE(TRACE_DEBUG, "settings->nexthop_fail_code: [%d]", (*settings)->nexthop_fail_code);
    TRACE(TRACE_DEBUG, "settings->nexthop_fail_msg: [%s]", (*settings)->nexthop_fail_msg);
    TRACE(TRACE_DEBUG, "settings->smtpd_timeout: [%d]\n", (*settings)->smtpd_timeout);

    list = smf_dict_get_keys((*settings)->smtp_codes);
    elem = smf_list_head(list);
    while(elem != NULL) {
        s = (char *)smf_list_data(elem);
        TRACE(TRACE_DEBUG, "settings->smtp_codes: append %s=%s",s,smf_dict_get((*settings)->smtp_codes,s));
        elem = elem->next;
    }
    smf_list_free(list);
    return 0;
}