599 lines
14 KiB
C
599 lines
14 KiB
C
#include <stdlib.h>
|
|
#include <check.h>
|
|
#include <time.h>
|
|
#include <stdio.h>
|
|
#include "logger.h"
|
|
|
|
pyfcgi_conf_logger_t *conf = &PyFCGI_conf.logs;
|
|
|
|
char tmpdir[] = "/tmp/tmp_PyFCGI_checksXXXXXX";
|
|
|
|
/*
|
|
TC logger init
|
|
*/
|
|
START_TEST(test_logger_init)
|
|
{
|
|
|
|
pyfcgi_logger_init();
|
|
ck_assert_ptr_eq(conf->syslog_ident, NULL);
|
|
ck_assert_ptr_eq(conf->ident, NULL);
|
|
/*
|
|
ck_assert_ptr_eq(conf->formats, NULL);
|
|
ck_assert_ptr_eq(conf->loggers, NULL);
|
|
*/
|
|
ck_assert_int_eq(conf->logger_sz, 0);
|
|
ck_assert_int_eq(conf->format_sz, 0);
|
|
ck_assert_int_eq(conf->flags, 0);
|
|
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_logger_format_add)
|
|
{
|
|
int ret;
|
|
size_t s;
|
|
pyfcgi_logger_init();
|
|
const char *fmt = "{datetime} {level} {ident}[{pid}] {msg}";
|
|
const char *fmt2 = "{datetime} {level} {ident} {msg}";
|
|
|
|
ret = pyfcgi_logger_format_add(fmt, &s);
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(conf->format_sz, 1);
|
|
ck_assert_int_eq(s, 0);
|
|
ck_assert_str_eq(conf->formats[s].fmt, fmt);
|
|
ret = pyfcgi_logger_format_add(fmt2, &s);
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(conf->format_sz, 2);
|
|
ck_assert_int_eq(s, 1);
|
|
ck_assert_str_eq(conf->formats[s].fmt, fmt2);
|
|
ret = pyfcgi_logger_format_add(fmt, &s);
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(conf->format_sz, 2);
|
|
ck_assert_int_eq(s, 0);
|
|
ck_assert_str_eq(conf->formats[s].fmt, fmt);
|
|
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_logger_add)
|
|
{
|
|
char tmplog[128];
|
|
char logfmt[] = "{level} {ident} {pid} {msg}";
|
|
char expected[] = " Alert 0 Hello world ! foobar 04\n";
|
|
int ret;
|
|
pyfcgi_conf_logger_t *conf;
|
|
pyfcgi_logger_t *logger;
|
|
pyfcgi_logger_format_t *fmt;
|
|
char buf[128];
|
|
size_t sz;
|
|
|
|
memset(buf, 0, 128);
|
|
|
|
pyfcgi_logger_init();
|
|
|
|
conf = &PyFCGI_conf.logs;
|
|
logger = &(conf->loggers[0]);
|
|
|
|
snprintf(tmplog, 128, "%s/%s", tmpdir, "format_add.log");
|
|
ret = pyfcgi_logger_add(tmplog, 0xFF, 0xFF, logfmt);
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(conf->logger_sz, 1);
|
|
ck_assert_str_eq(logger->filename, tmplog);
|
|
fmt = &(conf->formats[logger->fmt_id]);
|
|
ck_assert_str_eq(fmt->fmt, logfmt);
|
|
|
|
pyfcgi_log(LOG_ALERT, "Hello world ! %s %02d", "foobar", 4);
|
|
//pyfcgi_log(LOG_DEBUG, "Hello world 2 %s\n", tmplog);
|
|
|
|
pyfcgi_logger_stop();
|
|
|
|
ret = open(tmplog, O_RDONLY);
|
|
sz = read(ret, buf, 128);
|
|
|
|
ck_assert_str_eq(expected, buf);
|
|
|
|
unlink(tmplog);
|
|
|
|
}
|
|
END_TEST
|
|
|
|
/*
|
|
TC logger default values
|
|
*/
|
|
|
|
START_TEST(test_logger_parse_field_dtfmt_default)
|
|
{
|
|
int ret;
|
|
char *ptr, *orig, *fmt;
|
|
|
|
orig = "}";
|
|
ptr = orig;
|
|
fmt = NULL;
|
|
|
|
ret = pyfcgi_logger_parse_field_dtfmt((const char**)&ptr, &fmt);
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_str_eq(fmt, PYFCGI_LOGGER_TIME_FMT_DEFAULT);
|
|
ck_assert_ptr_eq(ptr, orig);
|
|
free(fmt);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_logger_parse_field_sz_default)
|
|
{
|
|
int ret;
|
|
size_t val;
|
|
char *ptr, **orig;
|
|
char *vals[] = {":%F}", ":}", "}", NULL};
|
|
|
|
orig = vals;
|
|
while(*orig)
|
|
{
|
|
ptr = *orig;
|
|
|
|
ret = pyfcgi_logger_parse_field_sz((const char**)&ptr, &val);
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(val, 0);
|
|
ck_assert_ptr_eq(ptr, (*orig));
|
|
orig++;
|
|
}
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_logger_parse_field_datetime_default)
|
|
{
|
|
int ret;
|
|
char *ptr, **orig, err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
|
|
pyfcgi_logger_fmt_field_t field;
|
|
char *vals[] = {"datetime}", "datetime::}", "datetime:}", NULL};
|
|
|
|
memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
|
|
|
|
orig = vals;
|
|
while(*orig)
|
|
{
|
|
ptr = *orig;
|
|
|
|
ret = pyfcgi_logger_parse_field((const char**)&ptr,
|
|
(const char*)ptr, &field,
|
|
err);
|
|
if(ret)
|
|
{
|
|
dprintf(2, "ERROR : '%s'\n", err);
|
|
}
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(field.type, pyfcgi_logger_field_datetime);
|
|
ck_assert_int_ne(field.known_length, 0);
|
|
ck_assert_int_eq(field.len, PYFCGI_LOG_DTM_LEN);
|
|
ck_assert_ptr_eq(field.val, strftime);
|
|
ck_assert_str_eq(field.args.datetime.format,
|
|
PYFCGI_LOGGER_TIME_FMT_DEFAULT);
|
|
ck_assert_ptr_eq(field.buf_ptr, NULL);
|
|
orig++;
|
|
}
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_logger_format_add_default)
|
|
{
|
|
int ret;
|
|
size_t s;
|
|
pyfcgi_logger_init();
|
|
|
|
ret = pyfcgi_logger_format_add(NULL, &s);
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(conf->format_sz, 1);
|
|
ck_assert_int_eq(s, 0);
|
|
ck_assert_str_eq(conf->formats[s].fmt, PYFCGI_LOGGER_FMT_DEFAULT);
|
|
}
|
|
END_TEST
|
|
|
|
/*
|
|
TC logger field parsing
|
|
*/
|
|
|
|
START_TEST(test_logger_parse_field_sz)
|
|
{
|
|
int ret, *res;
|
|
size_t val;
|
|
char *ptr, **orig, **eptr;
|
|
char *vals[] = {"42:%F}", "1337:}", "0}", ":}", NULL};
|
|
int _res[] = {42,1337,0, 0};
|
|
char *_eptr[] = {vals[0]+2, vals[1]+4, vals[2]+1, vals[3]};
|
|
|
|
orig = vals;
|
|
eptr = _eptr;
|
|
res = _res;
|
|
while(*orig)
|
|
{
|
|
ptr = *orig;
|
|
|
|
ret = pyfcgi_logger_parse_field_sz((const char**)&ptr, &val);
|
|
ck_assert_int_eq(val, *res);
|
|
ck_assert_ptr_eq(ptr, *eptr);
|
|
orig++;
|
|
res++;
|
|
eptr++;
|
|
}
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_logger_parse_field_dtfmt)
|
|
{
|
|
int ret;
|
|
size_t len;
|
|
char **val, **ptr, *fmt;
|
|
char *_vals[] = {"%fdc}", "123}", "4}}foo}", NULL};
|
|
|
|
val = _vals;
|
|
while(*val)
|
|
{
|
|
ptr = val;
|
|
len = strlen(*val);
|
|
|
|
ret = pyfcgi_logger_parse_field_dtfmt((const char**)&ptr, &fmt);
|
|
*val[len-1] = '\0'; //deleting leading '}' to get expected result
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_ptr_ne(fmt, *val);
|
|
ck_assert_str_eq(fmt, *val);
|
|
ck_assert_ptr_eq(ptr, *val+len-1);
|
|
free(fmt);
|
|
val++;
|
|
}
|
|
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_logger_parse_field_datetime)
|
|
{
|
|
int ret, *len;
|
|
char *ptr, **orig, **fmt, err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
|
|
pyfcgi_logger_fmt_field_t field;
|
|
char *vals[] = {"datetime:42}", "datetime::%s%F}",
|
|
"datetime:42:COUCOU}",
|
|
"dat:32:FOO}", "d::BAR}",
|
|
"datetime}{level}", "datetime} {level}",
|
|
"datetime}:{level}",
|
|
NULL};
|
|
int _len[] = {42, PYFCGI_LOG_DTM_LEN, 42, 32, PYFCGI_LOG_DTM_LEN,
|
|
PYFCGI_LOG_DTM_LEN, PYFCGI_LOG_DTM_LEN, PYFCGI_LOG_DTM_LEN};
|
|
char *_fmt[] = {PYFCGI_LOGGER_TIME_FMT_DEFAULT, "%s%F", "COUCOU", "FOO",
|
|
"BAR", PYFCGI_LOGGER_TIME_FMT_DEFAULT,
|
|
PYFCGI_LOGGER_TIME_FMT_DEFAULT,
|
|
PYFCGI_LOGGER_TIME_FMT_DEFAULT};
|
|
|
|
memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
|
|
|
|
len = _len;
|
|
fmt = _fmt;
|
|
orig = vals;
|
|
while(*orig)
|
|
{
|
|
ptr = *orig;
|
|
|
|
ret = pyfcgi_logger_parse_field((const char**)&ptr,
|
|
(const char*)ptr, &field,
|
|
err);
|
|
if(ret)
|
|
{
|
|
dprintf(2, "ERROR : '%s'\n", err);
|
|
}
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(field.type, pyfcgi_logger_field_datetime);
|
|
ck_assert_int_ne(field.known_length, 0);
|
|
ck_assert_int_eq(field.len, *len);
|
|
ck_assert_ptr_eq(field.val, strftime);
|
|
ck_assert_str_eq(field.args.datetime.format, *fmt);
|
|
ck_assert_ptr_eq(field.buf_ptr, NULL);
|
|
orig++;
|
|
len++;
|
|
fmt++;
|
|
}
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_logger_parse_field_level)
|
|
{
|
|
int ret;
|
|
char **val, **ptr;
|
|
char err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
|
|
char *vals[] = {"level}", "l}", "leve}", NULL};
|
|
pyfcgi_logger_fmt_field_t field;
|
|
|
|
val = vals;
|
|
memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
|
|
|
|
while(*val)
|
|
{
|
|
ptr = val;
|
|
ret = pyfcgi_logger_parse_field((const char**)ptr,
|
|
(const char*)*ptr, &field,
|
|
err);
|
|
if(ret)
|
|
{
|
|
dprintf(2, "ERROR : '%s'\n", err);
|
|
}
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(field.type, pyfcgi_logger_field_level);
|
|
ck_assert_int_ne(field.known_length, 0);
|
|
ck_assert_int_eq(field.len, PYFCGI_LOG_LVL_LEN);
|
|
ck_assert_ptr_eq(field.val, pyfcgi_logger_value_level);
|
|
val++;
|
|
}
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_logger_parse_field_facility)
|
|
{
|
|
int ret;
|
|
char **val, **ptr;
|
|
char err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
|
|
char *vals[] = {"facility}", "f}", "fac}", NULL};
|
|
pyfcgi_logger_fmt_field_t field;
|
|
|
|
val = vals;
|
|
memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
|
|
|
|
while(*val)
|
|
{
|
|
ptr = val;
|
|
ret = pyfcgi_logger_parse_field((const char**)ptr,
|
|
(const char*)*ptr, &field,
|
|
err);
|
|
if(ret)
|
|
{
|
|
dprintf(2, "ERROR : '%s'\n", err);
|
|
}
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(field.type, pyfcgi_logger_field_facility);
|
|
ck_assert_int_ne(field.known_length, 0);
|
|
ck_assert_int_eq(field.len, PYFCGI_LOG_TYP_LEN);
|
|
ck_assert_ptr_eq(field.val, pyfcgi_logger_value_facility);
|
|
val++;
|
|
}
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_logger_parse_field_pid)
|
|
{
|
|
int ret;
|
|
char **val, **ptr;
|
|
char err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
|
|
char *vals[] = {"pid}", "p}", "pi}", NULL};
|
|
pyfcgi_logger_fmt_field_t field;
|
|
|
|
val = vals;
|
|
memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
|
|
|
|
while(*val)
|
|
{
|
|
ptr = val;
|
|
ret = pyfcgi_logger_parse_field((const char**)ptr,
|
|
(const char*)*ptr, &field,
|
|
err);
|
|
if(ret)
|
|
{
|
|
dprintf(2, "ERROR : '%s'\n", err);
|
|
}
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(field.type, pyfcgi_logger_field_pid);
|
|
ck_assert_int_ne(field.known_length, 0);
|
|
ck_assert_int_eq(field.len, PYFCGI_LOG_PID_LEN);
|
|
ck_assert_ptr_eq(field.val, (&PyFCGI_conf.context.pid));
|
|
val++;
|
|
}
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_logger_parse_field_ident)
|
|
{
|
|
int ret;
|
|
char **val, **ptr;
|
|
char err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
|
|
char *vals[] = {"ident}", "i}", "id}", NULL};
|
|
pyfcgi_logger_fmt_field_t field;
|
|
|
|
val = vals;
|
|
memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
|
|
|
|
while(*val)
|
|
{
|
|
ptr = val;
|
|
ret = pyfcgi_logger_parse_field((const char**)ptr,
|
|
(const char*)*ptr, &field,
|
|
err);
|
|
if(ret)
|
|
{
|
|
dprintf(2, "ERROR : '%s'\n", err);
|
|
}
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(field.type, pyfcgi_logger_field_ident);
|
|
ck_assert_int_ne(field.known_length, 0);
|
|
ck_assert_int_eq(field.len, 0);
|
|
ck_assert_ptr_eq(field.val, (&PyFCGI_conf.logs.ident));
|
|
val++;
|
|
}
|
|
}
|
|
END_TEST
|
|
|
|
|
|
START_TEST(test_logger_parse_field_msg)
|
|
{
|
|
int ret;
|
|
char **val, **ptr;
|
|
char err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
|
|
pyfcgi_logger_fmt_field_t field;
|
|
char *vals[] = {"msg}", "m}", "ms}", NULL};
|
|
|
|
|
|
val = vals;
|
|
memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
|
|
|
|
while(*val)
|
|
{
|
|
ptr = val;
|
|
ret = pyfcgi_logger_parse_field((const char**)ptr,
|
|
(const char*)*ptr, &field,
|
|
err);
|
|
if(ret)
|
|
{
|
|
dprintf(2, "ERROR : '%s'\n", err);
|
|
}
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(field.type, pyfcgi_logger_field_msg);
|
|
ck_assert_int_eq(field.known_length, 0);
|
|
ck_assert_int_eq(field.len, 0);
|
|
ck_assert_ptr_eq(field.val, NULL);
|
|
val++;
|
|
}
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_logger_format_parse1)
|
|
{
|
|
int ret, i;
|
|
size_t s;
|
|
pyfcgi_logger_init();
|
|
const char *fmt = "{datetime} {level} {ident}[{pid}] {msg}";
|
|
pyfcgi_logger_field_type_e types[] = {
|
|
pyfcgi_logger_field_datetime, pyfcgi_logger_field_const,
|
|
pyfcgi_logger_field_level, pyfcgi_logger_field_const,
|
|
pyfcgi_logger_field_ident, pyfcgi_logger_field_const,
|
|
pyfcgi_logger_field_pid, pyfcgi_logger_field_const,
|
|
pyfcgi_logger_field_msg};
|
|
|
|
|
|
ret = pyfcgi_logger_format_add(fmt, &s);
|
|
ck_assert_int_eq(ret, 0);
|
|
ck_assert_int_eq(conf->format_sz, 1);
|
|
ck_assert_int_eq(s, 0);
|
|
ck_assert_str_eq(conf->formats[s].fmt, fmt);
|
|
ck_assert_int_eq(conf->formats[s].nfield, 9);
|
|
for(i=0; i<9; i++)
|
|
{
|
|
ck_assert_int_eq(conf->formats[s].fields[i].type, types[i]);
|
|
}
|
|
ck_assert_str_eq(conf->formats[s].fields[1].val, " ");
|
|
ck_assert_str_eq(conf->formats[s].fields[3].val, " ");
|
|
ck_assert_str_eq(conf->formats[s].fields[5].val, "[");
|
|
ck_assert_str_eq(conf->formats[s].fields[7].val, "] ");
|
|
ck_assert_str_eq(conf->formats[s].fields[0].args.datetime.format,
|
|
PYFCGI_LOGGER_TIME_FMT_DEFAULT);
|
|
|
|
}
|
|
END_TEST
|
|
|
|
/*
|
|
TC logger format parsing error
|
|
*/
|
|
START_TEST(test_logger_parse_field_sz_err)
|
|
{
|
|
int ret, *res;
|
|
size_t val;
|
|
char **ptr, **orig;
|
|
char *vals[] = {"-42:%F}", "abc:}", "", "", NULL};
|
|
|
|
orig = vals;
|
|
while(*orig)
|
|
{
|
|
ptr = orig;
|
|
|
|
ret = pyfcgi_logger_parse_field_sz((const char**)ptr, &val);
|
|
ck_assert_int_eq(val, 0);
|
|
ck_assert_int_ne(ret, 0);
|
|
orig++;
|
|
res++;
|
|
}
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_logger_parse_field_parse_err)
|
|
{
|
|
int ret;
|
|
char **val, **ptr;
|
|
char err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
|
|
char *vals[] = {"foobar}", "::}", "ident", "",
|
|
"level", "pid", "42}", ":ident:", ":ident}", NULL};
|
|
pyfcgi_logger_fmt_field_t field;
|
|
|
|
val = vals;
|
|
memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
|
|
while(*val)
|
|
{
|
|
ptr = val;
|
|
*err = '\0';
|
|
|
|
ret = pyfcgi_logger_parse_field((const char**)ptr,
|
|
(const char*)*ptr, &field,
|
|
err);
|
|
ck_assert_int_ne(ret, 0);
|
|
ck_assert_int_ne(*err, '\0');
|
|
ck_assert_int_eq(field.type, pyfcgi_logger_field_null);
|
|
val++;
|
|
}
|
|
}
|
|
END_TEST
|
|
|
|
/* Suite, runner & main */
|
|
|
|
Suite * logger_suite(void)
|
|
{
|
|
Suite *s;
|
|
TCase *tc_init, *tc_field, *tc_field_default, *tc_parse_err;
|
|
|
|
s = suite_create("Logger");
|
|
|
|
tc_field_default = tcase_create("Logger format parsing default values");
|
|
tcase_add_test(tc_field_default, test_logger_parse_field_dtfmt_default);
|
|
tcase_add_test(tc_field_default, test_logger_parse_field_sz_default);
|
|
tcase_add_test(tc_field_default, test_logger_parse_field_datetime_default);
|
|
tcase_add_test(tc_field_default, test_logger_format_add_default);
|
|
suite_add_tcase(s, tc_field_default);
|
|
|
|
tc_field = tcase_create("Logger format parsing");
|
|
tcase_add_test(tc_field, test_logger_parse_field_sz);
|
|
tcase_add_test(tc_field, test_logger_parse_field_datetime);
|
|
tcase_add_test(tc_field, test_logger_parse_field_level);
|
|
tcase_add_test(tc_field, test_logger_parse_field_facility);
|
|
tcase_add_test(tc_field, test_logger_parse_field_pid);
|
|
tcase_add_test(tc_field, test_logger_parse_field_ident);
|
|
tcase_add_test(tc_field, test_logger_parse_field_msg);
|
|
tcase_add_test(tc_field, test_logger_format_parse1);
|
|
suite_add_tcase(s, tc_field);
|
|
|
|
tc_parse_err = tcase_create("Logger format parsing errors handling");
|
|
tcase_add_test(tc_parse_err, test_logger_parse_field_sz_err);
|
|
tcase_add_test(tc_parse_err, test_logger_parse_field_parse_err);
|
|
suite_add_tcase(s, tc_parse_err);
|
|
|
|
tc_init = tcase_create("Initialisation");
|
|
tcase_add_test(tc_init, test_logger_init);
|
|
tcase_add_test(tc_init, test_logger_format_add);
|
|
tcase_add_test(tc_init, test_logger_add);
|
|
suite_add_tcase(s, tc_init);
|
|
|
|
|
|
return s;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
int nfailed;
|
|
Suite *s;
|
|
SRunner *sr;
|
|
|
|
mkdtemp(tmpdir);
|
|
|
|
s = logger_suite();
|
|
sr = srunner_create(s);
|
|
|
|
//srunner_set_fork_status(sr, CK_NOFORK);
|
|
//srunner_run_all(sr, CK_NORMAL);
|
|
//srunner_run_all(sr, CK_ENV);
|
|
srunner_run_all(sr, CK_VERBOSE);
|
|
nfailed = srunner_ntests_failed(sr);
|
|
srunner_free(sr);
|
|
|
|
rmdir(tmpdir);
|
|
|
|
return (!nfailed)?EXIT_SUCCESS:EXIT_FAILURE;
|
|
}
|