Пример #1
0
void loop()
{
    int i = 0;
    while ((!terminate || i++ < 200) && !done)
    {
        mapper_monitor_poll(mon, 0);
        usleep(polltime_ms * 1000);

        if (update++ < 0)
            continue;
        update = -10;

        // clear screen & cursor to home
        printf("\e[2J\e[0;0H");
        fflush(stdout);

        printf("Registered devices:\n");
        mapper_db_device *pdev = mapper_db_get_all_devices(db);
        while (pdev) {
            printdevice(*pdev);
            pdev = mapper_db_device_next(pdev);
        }

        printf("------------------------------\n");

        printf("Registered signals:\n");
        mapper_db_signal *psig =
            mapper_db_get_all_inputs(db);
        while (psig) {
            printsignal(*psig);
            psig = mapper_db_signal_next(psig);
        }
        psig = mapper_db_get_all_outputs(db);
        while (psig) {
            printsignal(*psig);
            psig = mapper_db_signal_next(psig);
        }

        printf("------------------------------\n");

        printf("Registered links:\n");
        mapper_db_link *plink = mapper_db_get_all_links(db);
        while (plink) {
            printlink(*plink);
            plink = mapper_db_link_next(plink);
        }

        printf("------------------------------\n");

        printf("Registered connections:\n");
        mapper_db_connection *pcon = mapper_db_get_all_connections(db);
        while (pcon) {
            printconnection(*pcon);
            pcon = mapper_db_connection_next(pcon);
        }

        printf("------------------------------\n");
    }
}
Пример #2
0
static void
print_sigqueueinfo(struct tcb *tcp, int sig, unsigned long uinfo)
{
	printsignal(sig);
	tprints(", ");
	printsiginfo_at(tcp, uinfo);
}
Пример #3
0
static void
print_sigqueueinfo(struct tcb *const tcp, const int sig,
		   const kernel_ulong_t addr)
{
	printsignal(sig);
	tprints(", ");
	printsiginfo_at(tcp, addr);
}
Пример #4
0
int
sys_sigaction(struct tcb *tcp)
{
	if (entering(tcp)) {
		printsignal(tcp->u_arg[0]);
		tprints(", ");
		decode_old_sigaction(tcp, tcp->u_arg[1]);
		tprints(", ");
	} else
		decode_old_sigaction(tcp, tcp->u_arg[2]);
	return 0;
}
Пример #5
0
int
sys_sigaction(struct tcb *tcp)
{
	long addr;
	sigset_t sigset;
	struct old_sigaction sa;

	if (entering(tcp)) {
		printsignal(tcp->u_arg[0]);
		tprints(", ");
		addr = tcp->u_arg[1];
	} else
		addr = tcp->u_arg[2];
	if (addr == 0)
		tprints("NULL");
	else if (!verbose(tcp))
		tprintf("%#lx", addr);
	else if (umove(tcp, addr, &sa) < 0)
		tprints("{...}");
	else {
		/* Architectures using function pointers, like
		 * hppa, may need to manipulate the function pointer
		 * to compute the result of a comparison. However,
		 * the __sa_handler function pointer exists only in
		 * the address space of the traced process, and can't
		 * be manipulated by strace. In order to prevent the
		 * compiler from generating code to manipulate
		 * __sa_handler we cast the function pointers to long. */
		if ((long)sa.__sa_handler == (long)SIG_ERR)
			tprints("{SIG_ERR, ");
		else if ((long)sa.__sa_handler == (long)SIG_DFL)
			tprints("{SIG_DFL, ");
		else if ((long)sa.__sa_handler == (long)SIG_IGN)
			tprints("{SIG_IGN, ");
		else
			tprintf("{%#lx, ", (long) sa.__sa_handler);
		long_to_sigset(sa.sa_mask, &sigset);
		printsigmask(&sigset, 0);
		tprints(", ");
		printflags(sigact_flags, sa.sa_flags, "SA_???");
#ifdef SA_RESTORER
		if (sa.sa_flags & SA_RESTORER)
			tprintf(", %p", sa.sa_restorer);
#endif
		tprints("}");
	}
	if (entering(tcp))
		tprints(", ");
	else
		tprintf(", %#lx", (unsigned long) sa.sa_restorer);
	return 0;
}
Пример #6
0
int
sys_rt_sigaction(struct tcb *tcp)
{
	if (entering(tcp)) {
		printsignal(tcp->u_arg[0]);
		tprints(", ");
		decode_new_sigaction(tcp, tcp->u_arg[1]);
		tprints(", ");
	} else {
		decode_new_sigaction(tcp, tcp->u_arg[2]);
#if defined(SPARC) || defined(SPARC64)
		tprintf(", %#lx, %lu", tcp->u_arg[3], tcp->u_arg[4]);
#elif defined(ALPHA)
		tprintf(", %lu, %#lx", tcp->u_arg[3], tcp->u_arg[4]);
#else
		tprintf(", %lu", tcp->u_arg[3]);
#endif
	}
	return 0;
}
Пример #7
0
static
#endif
void
printsiginfo(const siginfo_t *sip)
{
	if (sip->si_signo == 0) {
		tprints("{}");
		return;
	}
	tprints("{si_signo=");
	printsignal(sip->si_signo);

	tprints(", si_code=");
	print_si_code(sip->si_signo, sip->si_code);

#ifdef SI_NOINFO
	if (sip->si_code != SI_NOINFO)
#endif
		print_si_info(sip);

	tprints("}");
}
Пример #8
0
int
sys_signal(struct tcb *tcp)
{
	if (entering(tcp)) {
		printsignal(tcp->u_arg[0]);
		tprints(", ");
		switch (tcp->u_arg[1]) {
		case (long) SIG_ERR:
			tprints("SIG_ERR");
			break;
		case (long) SIG_DFL:
			tprints("SIG_DFL");
			break;
		case (long) SIG_IGN:
			tprints("SIG_IGN");
			break;
		default:
			tprintf("%#lx", tcp->u_arg[1]);
		}
		return 0;
	}
	else if (!syserror(tcp)) {
		switch (tcp->u_rval) {
		case (long) SIG_ERR:
			tcp->auxstr = "SIG_ERR"; break;
		case (long) SIG_DFL:
			tcp->auxstr = "SIG_DFL"; break;
		case (long) SIG_IGN:
			tcp->auxstr = "SIG_IGN"; break;
		default:
			tcp->auxstr = NULL;
		}
		return RVAL_HEX | RVAL_STR;
	}
	return 0;
}
Пример #9
0
int main()
{
    lo_arg *args[20];
    mapper_message_t msg;
    int port=1234;
    int zero=0, one=1;
    mapper_db_t db_t, *db = &db_t;
    memset(db, 0, sizeof(db_t));

    /* Test the database functions */

    args[0] = (lo_arg*)"@port";
    args[1] = (lo_arg*)&port;
    args[2] = (lo_arg*)"@IP";
    args[3] = (lo_arg*)"localhost";

    if (mapper_msg_parse_params(&msg, "/registered", "siss", 4, args))
    {
        printf("1: Error, parsing failed.\n");
        return 1;
    }

    mapper_db_add_or_update_device_params(db, "/testdb.1", &msg);
    mapper_db_add_or_update_device_params(db, "/testdb__.2", &msg);
    mapper_db_add_or_update_device_params(db, "/testdb.3", &msg);
    mapper_db_add_or_update_device_params(db, "/testdb__.4", &msg);

    args[0] = (lo_arg*)"@direction";
    args[1] = (lo_arg*)"input";
    args[2] = (lo_arg*)"@type";
    args[3] = (lo_arg*)"f";
    args[4] = (lo_arg*)"@IP";
    args[5] = (lo_arg*)"localhost";

    if (mapper_msg_parse_params(&msg, "/testdb.1/signal",
                                "sc", 2, args))
    {
        printf("2: Error, parsing failed.\n");
        return 1;
    }

    mapper_db_add_or_update_signal_params(db, "/in1", "/testdb.1", &msg);
    mapper_db_add_or_update_signal_params(db, "/in2", "/testdb.1", &msg);
    mapper_db_add_or_update_signal_params(db, "/in2", "/testdb.1", &msg);

    args[1] = (lo_arg*)"output";

    if (mapper_msg_parse_params(&msg, "/testdb.1/signal",
                                "sc", 2, args))
    {
        printf("2: Error, parsing failed.\n");
        return 1;
    }

    mapper_db_add_or_update_signal_params(db, "/out1", "/testdb.1", &msg);
    mapper_db_add_or_update_signal_params(db, "/out2", "/testdb.1", &msg);
    mapper_db_add_or_update_signal_params(db, "/out1", "/testdb__.2", &msg);

    args[0] = (lo_arg*)"@mode";
    args[1] = (lo_arg*)"bypass";
    args[2] = (lo_arg*)"@clipMin";
    args[3] = (lo_arg*)"none";

    if (mapper_msg_parse_params(&msg, "/connected",
                                "ssss", 4, args))
    {
        printf("4: Error, parsing failed.\n");
        return 1;
    }

    mapper_db_add_or_update_connection_params(db, "/testdb.1/out2",
            "/testdb__.2/in1", &msg);
    mapper_db_add_or_update_connection_params(db, "/testdb__.2/out1",
            "/testdb.1/in1", &msg);

    args[0] = (lo_arg*)"@mode";
    args[1] = (lo_arg*)"expression";
    args[2] = (lo_arg*)"@expression";
    args[3] = (lo_arg*)"(x-10)*80";
    args[4] = (lo_arg*)"@clipMin";
    args[5] = (lo_arg*)"none";
    args[6] = (lo_arg*)"@range";
    args[7] = (lo_arg*)&zero;
    args[8] = (lo_arg*)&one;
    args[9] = (lo_arg*)&zero;
    args[10] = (lo_arg*)&one;

    if (mapper_msg_parse_params(&msg, "/connected",
                                "sssssssiiii", 11, args))
    {
        printf("5: Error, parsing failed.\n");
        return 1;
    }

    mapper_db_add_or_update_connection_params(db, "/testdb.1/out1",
            "/testdb__.2/in2", &msg);
    mapper_db_add_or_update_connection_params(db, "/testdb.1/out1",
            "/testdb__.2/in1", &msg);
    mapper_db_add_or_update_connection_params(db, "/testdb__.2/out2",
            "/testdb.1/in2", &msg);

    if (mapper_msg_parse_params(&msg, "/linked",
                                "", 0, args))
    {
        printf("6: Error, parsing failed (on no args!)\n");
        return 1;
    }

    mapper_db_add_or_update_link_params(db, "/testdb.1", "/testdb__.2", &msg);
    mapper_db_add_or_update_link_params(db, "/testdb__.2", "/testdb.3", &msg);
    mapper_db_add_or_update_link_params(db, "/testdb__.2", "/testdb.3", &msg);
    mapper_db_add_or_update_link_params(db, "/testdb.3", "/testdb.1", &msg);
    mapper_db_add_or_update_link_params(db, "/testdb__.2", "/testdb__.4", &msg);

    /*********/

    trace("Dump:\n");
    mapper_db_dump(db);

    /*********/

    printf("\n--- Devices ---\n");

    printf("\nWalk the whole database:\n");
    mapper_db_device *pdev = mapper_db_get_all_devices(db);
    int count=0;
    if (!pdev) {
        printf("mapper_db_get_all_devices() returned 0.\n");
        return 1;
    }
    if (!*pdev) {
        printf("mapper_db_get_all_devices() returned something "
               "which pointed to 0.\n");
        return 1;
    }

    while (pdev) {
        count ++;
        printf("  name=%s, host=%s, port=%d\n",
               (*pdev)->name, (*pdev)->host, (*pdev)->port);
        pdev = mapper_db_device_next(pdev);
    }

    if (count != 4) {
        printf("Expected 4 records, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\nFind /testdb.3:\n");

    mapper_db_device dev = mapper_db_get_device_by_name(db, "/testdb.3");
    if (!dev) {
        printf("Not found.\n");
        return 1;
    }

    printf("  name=%s, host=%s, port=%d\n",
           dev->name, dev->host, dev->port);

    /*********/

    printf("\nFind /dummy:\n");

    dev = mapper_db_get_device_by_name(db, "/dummy");
    if (dev) {
        printf("unexpected found /dummy: %p\n", dev);
        return 1;
    }
    printf("  not found, good.\n");

    /*********/

    printf("\nFind matching '__':\n");

    pdev = mapper_db_match_devices_by_name(db, "__");

    count=0;
    if (!pdev) {
        printf("mapper_db_match_device_by_name() returned 0.\n");
        return 1;
    }
    if (!*pdev) {
        printf("mapper_db_match_device_by_name() returned something "
               "which pointed to 0.\n");
        return 1;
    }

    while (pdev) {
        count ++;
        printf("  name=%s, host=%s, port=%d\n",
               (*pdev)->name, (*pdev)->host, (*pdev)->port);
        pdev = mapper_db_device_next(pdev);
    }

    if (count != 2) {
        printf("Expected 2 records, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\n--- Signals ---\n");

    printf("\nFind all inputs for device '/testdb.1':\n");

    mapper_db_signal *psig =
        mapper_db_get_inputs_by_device_name(db, "/testdb.1");

    count=0;
    if (!psig) {
        printf("mapper_db_get_inputs_by_device_name() returned 0.\n");
        return 1;
    }
    if (!*psig) {
        printf("mapper_db_get_inputs_by_device_name() returned something "
               "which pointed to 0.\n");
        return 1;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_db_signal_next(psig);
    }

    if (count != 2) {
        printf("Expected 2 records, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\nFind all outputs for device '/testdb.1':\n");

    psig = mapper_db_get_outputs_by_device_name(db, "/testdb.1");

    count=0;
    if (!psig) {
        printf("mapper_db_get_outputs_by_device_name() returned 0.\n");
        return 1;
    }
    if (!*psig) {
        printf("mapper_db_get_outputs_by_device_name() returned something "
               "which pointed to 0.\n");
        return 1;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_db_signal_next(psig);
    }

    if (count != 2) {
        printf("Expected 2 records, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\nFind all inputs for device '/testdb__.2':\n");

    psig = mapper_db_get_inputs_by_device_name(db, "/testdb__.2");

    count=0;
    if (psig) {
        printf("mapper_db_get_inputs_by_device_name() "
               "incorrectly found something.\n");
        printsignal(*psig);
        return 1;
    }
    else
        printf("  correctly returned 0.\n");

    /*********/

    printf("\nFind all outputs for device '/testdb__.2':\n");

    psig = mapper_db_get_outputs_by_device_name(db, "/testdb__.2");

    count=0;
    if (!psig) {
        printf("mapper_db_get_outputs_by_device_name() returned 0.\n");
        return 1;
    }
    if (!*psig) {
        printf("mapper_db_get_outputs_by_device_name() returned something "
               "which pointed to 0.\n");
        return 1;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_db_signal_next(psig);
    }

    if (count != 1) {
        printf("Expected 1 record, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\nFind matching input 'in' for device '/testdb.1':\n");

    psig = mapper_db_match_inputs_by_device_name(db, "/testdb.1", "in");

    count=0;
    if (!psig) {
        printf("mapper_db_match_inputs_by_device_name() returned 0.\n");
        return 1;
    }
    if (!*psig) {
        printf("mapper_db_match_inputs_by_device_name() returned something "
               "which pointed to 0.\n");
        return 1;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_db_signal_next(psig);
    }

    if (count != 2) {
        printf("Expected 2 records, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\nFind matching output 'out' for device '/testdb.1':\n");

    psig = mapper_db_match_outputs_by_device_name(db, "/testdb.1", "out");

    count=0;
    if (!psig) {
        printf("mapper_db_match_outputs_by_device_name() returned 0.\n");
        return 1;
    }
    if (!*psig) {
        printf("mapper_db_match_outputs_by_device_name() returned something "
               "which pointed to 0.\n");
        return 1;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_db_signal_next(psig);
    }

    if (count != 2) {
        printf("Expected 2 records, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\nFind matching output 'out' for device '/testdb__.2':\n");

    psig = mapper_db_match_outputs_by_device_name(db, "/testdb__.2", "out");

    count=0;
    if (!psig) {
        printf("mapper_db_match_outputs_by_device_name() returned 0.\n");
        return 1;
    }
    if (!*psig) {
        printf("mapper_db_match_outputs_by_device_name() returned something "
               "which pointed to 0.\n");
        return 1;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_db_signal_next(psig);
    }

    if (count != 1) {
        printf("Expected 1 record, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\n--- connections ---\n");

    printf("\nFind connections with source 'out1':\n");

    mapper_db_connection* pcon =
        mapper_db_get_connections_by_src_signal_name(db, "out1");

    count=0;
    if (!pcon) {
        printf("mapper_db_get_connections_by_src_signal_name() returned 0.\n");
        return 1;
    }
    if (!*pcon) {
        printf("mapper_db_get_connections_by_src_signal_name() returned something "
               "which pointed to 0.\n");
        return 1;
    }

    while (pcon) {
        count ++;
        printf("  source=%s, dest=%s\n",
               (*pcon)->src_name, (*pcon)->dest_name);
        pcon = mapper_db_connection_next(pcon);
    }

    if (count != 3) {
        printf("Expected 3 records, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\nFind connections for device 'testdb.1', "
           "source 'out1':\n");

    pcon = mapper_db_get_connections_by_src_device_and_signal_names(db, "testdb.1",
            "/out1");

    count=0;
    if (!pcon) {
        printf("mapper_db_get_connections_by_src_device_and_signal_names() "
               "returned 0.\n");
        return 1;
    }
    if (!*pcon) {
        printf("mapper_db_get_connections_by_src_device_and_signal_names() "
               "returned something which pointed to 0.\n");
        return 1;
    }

    while (pcon) {
        count ++;
        printf("  source=%s, dest=%s\n",
               (*pcon)->src_name, (*pcon)->dest_name);
        pcon = mapper_db_connection_next(pcon);
    }

    if (count != 2) {
        printf("Expected 2 records, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\nFind connections with destination 'in2':\n");

    pcon = mapper_db_get_connections_by_dest_signal_name(db, "in2");

    count=0;
    if (!pcon) {
        printf("mapper_db_get_connections_by_dest_signal_name() returned 0.\n");
        return 1;
    }
    if (!*pcon) {
        printf("mapper_db_get_connections_by_dest_signal_name() returned something "
               "which pointed to 0.\n");
        return 1;
    }

    while (pcon) {
        count ++;
        printf("  source=%s, dest=%s\n",
               (*pcon)->src_name, (*pcon)->dest_name);
        pcon = mapper_db_connection_next(pcon);
    }

    if (count != 2) {
        printf("Expected 2 records, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\nFind connections for device 'testdb__.2', "
           "destination 'in1':\n");

    pcon = mapper_db_get_connections_by_dest_device_and_signal_names(db,
            "testdb__.2",
            "/in1");

    count=0;
    if (!pcon) {
        printf("mapper_db_get_connections_by_dest_device_and_signal_names() "
               "returned 0.\n");
        return 1;
    }
    if (!*pcon) {
        printf("mapper_db_get_connections_by_dest_device_and_signal_names() "
               "returned something which pointed to 0.\n");
        return 1;
    }

    while (pcon) {
        count ++;
        printf("  source=%s, dest=%s\n",
               (*pcon)->src_name, (*pcon)->dest_name);
        pcon = mapper_db_connection_next(pcon);
    }

    if (count != 2) {
        printf("Expected 2 records, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\nFind connections for input device 'testdb__.2', signal 'out1',"
           "\n                 and output device 'testdb.1', signal 'in1':\n");

    pcon = mapper_db_get_connections_by_device_and_signal_names(
               db, "testdb__.2", "out1", "testdb.1", "in1");

    count=0;
    if (!pcon) {
        printf("mapper_db_get_connections_by_device_and_signal_names() "
               "returned 0.\n");
        return 1;
    }
    if (!*pcon) {
        printf("mapper_db_get_connections_by_device_and_signal_names() "
               "returned something which pointed to 0.\n");
        return 1;
    }

    while (pcon) {
        count ++;
        printf("  source=%s, dest=%s\n",
               (*pcon)->src_name, (*pcon)->dest_name);
        pcon = mapper_db_connection_next(pcon);
    }

    if (count != 1) {
        printf("Expected 1 records, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\nFind connections for input device 'testdb__.2', signals "
           "matching 'out',"
           "\n                 and output device 'testdb.1', all signals:\n");

    pcon = mapper_db_get_connections_by_signal_queries(db,
            mapper_db_match_outputs_by_device_name(db, "/testdb__.2", "out"),
            mapper_db_get_inputs_by_device_name(db, "/testdb.1"));

    count=0;
    if (!pcon) {
        printf("mapper_db_get_connections_by_signal_queries() "
               "returned 0.\n");
        return 1;
    }
    if (!*pcon) {
        printf("mapper_db_get_connections_by_signal_queries() "
               "returned something which pointed to 0.\n");
        return 1;
    }

    while (pcon) {
        count ++;
        printf("  source=%s, dest=%s\n",
               (*pcon)->src_name, (*pcon)->dest_name);
        pcon = mapper_db_connection_next(pcon);
    }

    if (count != 1) {
        printf("Expected 1 records, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\n--- Links ---\n");

    printf("\nFind matching links with source '/testdb__.2':\n");

    mapper_db_link* plink =
        mapper_db_get_links_by_src_device_name(db, "/testdb__.2");

    count=0;
    if (!plink) {
        printf("mapper_db_get_links_by_src_device_name() returned 0.\n");
        return 1;
    }
    if (!*plink) {
        printf("mapper_db_get_links_by_src_device_name() returned something "
               "which pointed to 0.\n");
        return 1;
    }

    while (plink) {
        count ++;
        printf("  source=%s, dest=%s\n",
               (*plink)->src_name, (*plink)->dest_name);
        plink = mapper_db_link_next(plink);
    }

    if (count != 2) {
        printf("Expected 2 records, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\nFind matching links with destination '/testdb__.4':\n");

    plink = mapper_db_get_links_by_dest_device_name(db, "/testdb__.4");

    count=0;
    if (!plink) {
        printf("mapper_db_get_links_by_dest_device_name() returned 0.\n");
        return 1;
    }
    if (!*plink) {
        printf("mapper_db_get_links_by_dest_device_name() returned something "
               "which pointed to 0.\n");
        return 1;
    }

    while (plink) {
        count ++;
        printf("  source=%s, dest=%s\n",
               (*plink)->src_name, (*plink)->dest_name);
        plink = mapper_db_link_next(plink);
    }

    if (count != 1) {
        printf("Expected 1 record, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\nFind links with source matching 'db' and "
           "destination matching '__':\n");

    pdev = mapper_db_match_devices_by_name(db, "db");

    if (!pdev) {
        printf("mapper_db_match_device_by_name() returned 0.\n");
        return 1;
    }

    mapper_db_device_t **pdev2 = mapper_db_match_devices_by_name(db, "__");

    if (!pdev2) {
        printf("mapper_db_match_device_by_name() returned 0.\n");
        return 1;
    }

    plink = mapper_db_get_links_by_src_dest_devices(db, pdev, pdev2);

    count=0;
    if (!plink) {
        printf("mapper_db_get_links_by_src_dest_devices() returned 0.\n");
        return 1;
    }
    if (!*plink) {
        printf("mapper_db_get_links_by_src_dest_devices() "
               "returned something which pointed to 0.\n");
        return 1;
    }

    while (plink) {
        count ++;
        printf("  source=%s, dest=%s\n",
               (*plink)->src_name, (*plink)->dest_name);
        plink = mapper_db_link_next(plink);
    }

    if (count != 2) {
        printf("Expected 2 records, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\nFind any links with source matching '2':\n");

    pdev = mapper_db_match_devices_by_name(db, "2");

    if (!pdev) {
        printf("mapper_db_match_device_by_name() returned 0.\n");
        return 1;
    }

    pdev2 = mapper_db_get_all_devices(db);

    if (!pdev2) {
        printf("mapper_db_get_all_devices() returned 0.\n");
        return 1;
    }

    plink = mapper_db_get_links_by_src_dest_devices(db, pdev, pdev2);

    count=0;
    if (!plink) {
        printf("mapper_db_get_links_by_src_dest_devices() returned 0.\n");
        return 1;
    }
    if (!*plink) {
        printf("mapper_db_get_links_by_src_dest_devices() "
               "returned something which pointed to 0.\n");
        return 1;
    }

    while (plink) {
        count ++;
        printf("  source=%s, dest=%s\n",
               (*plink)->src_name, (*plink)->dest_name);
        plink = mapper_db_link_next(plink);
    }

    if (count != 2) {
        printf("Expected 2 records, but counted %d.\n", count);
        return 1;
    }

    /*********/

    printf("\nTest PASSED.\n");
    return 0;
}
Пример #10
0
int
proc_ioctl(struct tcb *tcp, int code, int arg)
{
	int val;
	prstatus_t status;
	prrun_t run;

	if (entering(tcp))
		return 0;

	switch (code) {
	case PIOCSTATUS:
	case PIOCSTOP:
	case PIOCWSTOP:
		if (arg == 0)
			tprintf(", NULL");
		else if (syserror(tcp))
			tprintf(", %#x", arg);
		else if (umove(tcp, arg, &status) < 0)
			tprintf(", {...}");
		else {
			tprintf(", {pr_flags=");
			printflags(proc_status_flags, status.pr_flags, "PR_???");
			if (status.pr_why) {
				tprintf(", pr_why=");
				printxval(proc_status_why, status.pr_why,
					  "PR_???");
			}
			switch (status.pr_why) {
			case PR_SIGNALLED:
			case PR_JOBCONTROL:
				tprintf(", pr_what=");
				printsignal(status.pr_what);
				break;
			case PR_FAULTED:
				tprintf(", pr_what=%d", status.pr_what);
				break;
			case PR_SYSENTRY:
			case PR_SYSEXIT:
				tprintf(", pr_what=SYS_%s",
					sysent[status.pr_what].sys_name);
				break;
			}
			tprintf(", ...}");
		}
		return 1;
	case PIOCRUN:
		if (arg == 0)
			tprintf(", NULL");
		else if (umove(tcp, arg, &run) < 0)
			tprintf(", {...}");
		else {
			tprintf(", {pr_flags=");
			printflags(proc_run_flags, run.pr_flags, "PR???");
			tprintf(", ...}");
		}
		return 1;
#ifdef PIOCSET
	case PIOCSET:
	case PIOCRESET:
		if (umove(tcp, arg, &val) < 0)
			tprintf(", [?]");
		else {
			tprintf(", [");
			printflags(proc_status_flags, val, "PR_???");
			tprintf("]");
		}
		return 1;
#endif /* PIOCSET */
	case PIOCKILL:
	case PIOCUNKILL:
		/* takes a pointer to a signal */
		if (umove(tcp, arg, &val) < 0)
			tprintf(", [?]");
		else {
			tprintf(", [");
			printsignal(val);
			tprintf("]");
		}
		return 1;
	case PIOCSFORK:
	case PIOCRFORK:
	case PIOCSRLC:
	case PIOCRRLC:
		/* doesn't take an arg */
		return 1;
	default:
		/* ad naseum */
		return 0;
	}
}
Пример #11
0
void
printsiginfo(siginfo_t *sip, int verbose)
{
	const char *code;

	if (sip->si_signo == 0) {
		tprints("{}");
		return;
	}
	tprints("{si_signo=");
	printsignal(sip->si_signo);
	code = xlookup(siginfo_codes, sip->si_code);
	if (!code) {
		switch (sip->si_signo) {
		case SIGTRAP:
			code = xlookup(sigtrap_codes, sip->si_code);
			break;
		case SIGCHLD:
			code = xlookup(sigchld_codes, sip->si_code);
			break;
		case SIGPOLL:
			code = xlookup(sigpoll_codes, sip->si_code);
			break;
		case SIGPROF:
			code = xlookup(sigprof_codes, sip->si_code);
			break;
		case SIGILL:
			code = xlookup(sigill_codes, sip->si_code);
			break;
#ifdef SIGEMT
		case SIGEMT:
			code = xlookup(sigemt_codes, sip->si_code);
			break;
#endif
		case SIGFPE:
			code = xlookup(sigfpe_codes, sip->si_code);
			break;
		case SIGSEGV:
			code = xlookup(sigsegv_codes, sip->si_code);
			break;
		case SIGBUS:
			code = xlookup(sigbus_codes, sip->si_code);
			break;
		}
	}
	if (code)
		tprintf(", si_code=%s", code);
	else
		tprintf(", si_code=%#x", sip->si_code);
#ifdef SI_NOINFO
	if (sip->si_code != SI_NOINFO)
#endif
	{
		if (sip->si_errno) {
			if (sip->si_errno < 0 || sip->si_errno >= nerrnos)
				tprintf(", si_errno=%d", sip->si_errno);
			else
				tprintf(", si_errno=%s",
					errnoent[sip->si_errno]);
		}
#ifdef SI_FROMUSER
		if (SI_FROMUSER(sip)) {
			tprintf(", si_pid=%lu, si_uid=%lu",
				(unsigned long) sip->si_pid,
				(unsigned long) sip->si_uid);
			switch (sip->si_code) {
#ifdef SI_USER
			case SI_USER:
				break;
#endif
#ifdef SI_TKILL
			case SI_TKILL:
				break;
#endif
#ifdef SI_TIMER
			case SI_TIMER:
				tprintf(", si_value=%d", sip->si_int);
				break;
#endif
			default:
				if (!sip->si_ptr)
					break;
				if (!verbose)
					tprints(", ...");
				else
					tprintf(", si_value={int=%u, ptr=%#lx}",
						sip->si_int,
						(unsigned long) sip->si_ptr);
				break;
			}
		}
		else
#endif /* SI_FROMUSER */
		{
			switch (sip->si_signo) {
			case SIGCHLD:
				tprintf(", si_pid=%ld, si_status=",
					(long) sip->si_pid);
				if (sip->si_code == CLD_EXITED)
					tprintf("%d", sip->si_status);
				else
					printsignal(sip->si_status);
				if (!verbose)
					tprints(", ...");
				else
					tprintf(", si_utime=%llu, si_stime=%llu",
						(unsigned long long) sip->si_utime,
						(unsigned long long) sip->si_stime);
				break;
			case SIGILL: case SIGFPE:
			case SIGSEGV: case SIGBUS:
				tprintf(", si_addr=%#lx",
					(unsigned long) sip->si_addr);
				break;
			case SIGPOLL:
				switch (sip->si_code) {
				case POLL_IN: case POLL_OUT: case POLL_MSG:
					tprintf(", si_band=%ld",
						(long) sip->si_band);
					break;
				}
				break;
			default:
				if (sip->si_pid || sip->si_uid)
				        tprintf(", si_pid=%lu, si_uid=%lu",
						(unsigned long) sip->si_pid,
						(unsigned long) sip->si_uid);
				if (!sip->si_ptr)
					break;
				if (!verbose)
					tprints(", ...");
				else {
					tprintf(", si_value={int=%u, ptr=%#lx}",
						sip->si_int,
						(unsigned long) sip->si_ptr);
				}

			}
		}
	}
	tprints("}");
}
Пример #12
0
int
sys_rt_sigaction(struct tcb *tcp)
{
	struct new_sigaction sa;
	sigset_t sigset;
	long addr;
	int r;

	if (entering(tcp)) {
		printsignal(tcp->u_arg[0]);
		tprints(", ");
		addr = tcp->u_arg[1];
	} else
		addr = tcp->u_arg[2];

	if (addr == 0) {
		tprints("NULL");
		goto after_sa;
	}
	if (!verbose(tcp)) {
		tprintf("%#lx", addr);
		goto after_sa;
	}
#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
	if (current_wordsize != sizeof(sa.sa_flags) && current_wordsize == 4) {
		struct new_sigaction32 sa32;
		r = umove(tcp, addr, &sa32);
		if (r >= 0) {
			memset(&sa, 0, sizeof(sa));
			sa.__sa_handler = (void*)(unsigned long)sa32.__sa_handler;
			sa.sa_flags     = sa32.sa_flags;
			sa.sa_restorer  = (void*)(unsigned long)sa32.sa_restorer;
			/* Kernel treats sa_mask as an array of longs.
			 * For 32-bit process, "long" is uint32_t, thus, for example,
			 * 32th bit in sa_mask will end up as bit 0 in sa_mask[1].
			 * But for (64-bit) kernel, 32th bit in sa_mask is
			 * 32th bit in 0th (64-bit) long!
			 * For little-endian, it's the same.
			 * For big-endian, we swap 32-bit words.
			 */
			sa.sa_mask[0] = sa32.sa_mask[0] + ((long)(sa32.sa_mask[1]) << 32);
		}
	} else
#endif
	{
		r = umove(tcp, addr, &sa);
	}
	if (r < 0) {
		tprints("{...}");
		goto after_sa;
	}
	/* Architectures using function pointers, like
	 * hppa, may need to manipulate the function pointer
	 * to compute the result of a comparison. However,
	 * the __sa_handler function pointer exists only in
	 * the address space of the traced process, and can't
	 * be manipulated by strace. In order to prevent the
	 * compiler from generating code to manipulate
	 * __sa_handler we cast the function pointers to long. */
	if ((long)sa.__sa_handler == (long)SIG_ERR)
		tprints("{SIG_ERR, ");
	else if ((long)sa.__sa_handler == (long)SIG_DFL)
		tprints("{SIG_DFL, ");
	else if ((long)sa.__sa_handler == (long)SIG_IGN)
		tprints("{SIG_IGN, ");
	else
		tprintf("{%#lx, ", (long) sa.__sa_handler);
	/* Questionable code below.
	 * Kernel won't handle sys_rt_sigaction
	 * with wrong sigset size (just returns EINVAL)
	 * therefore tcp->u_arg[3(4)] _must_ be NSIG / 8 here,
	 * and we always use smaller memcpy. */
	sigemptyset(&sigset);
#if defined(SPARC) || defined(SPARC64)
	if (tcp->u_arg[4] <= sizeof(sigset))
		memcpy(&sigset, &sa.sa_mask, tcp->u_arg[4]);
#else
	if (tcp->u_arg[3] <= sizeof(sigset))
		memcpy(&sigset, &sa.sa_mask, tcp->u_arg[3]);
#endif
	else
		memcpy(&sigset, &sa.sa_mask, sizeof(sigset));
	printsigmask(&sigset, 1);
	tprints(", ");
	printflags(sigact_flags, sa.sa_flags, "SA_???");
#ifdef SA_RESTORER
	if (sa.sa_flags & SA_RESTORER)
		tprintf(", %p", sa.sa_restorer);
#endif
	tprints("}");

 after_sa:
	if (entering(tcp))
		tprints(", ");
	else
#if defined(SPARC) || defined(SPARC64)
		tprintf(", %#lx, %lu", tcp->u_arg[3], tcp->u_arg[4]);
#elif defined(ALPHA)
		tprintf(", %lu, %#lx", tcp->u_arg[3], tcp->u_arg[4]);
#else
		tprintf(", %lu", tcp->u_arg[3]);
#endif
	return 0;
}
Пример #13
0
static void
print_si_info(const siginfo_t *sip)
{
	if (sip->si_errno) {
		tprints(", si_errno=");
		if ((unsigned) sip->si_errno < nerrnos
		    && errnoent[sip->si_errno])
			tprints(errnoent[sip->si_errno]);
		else
			tprintf("%d", sip->si_errno);
	}

	if (SI_FROMUSER(sip)) {
		switch (sip->si_code) {
		case SI_USER:
			printsigsource(sip);
			break;
		case SI_TKILL:
			printsigsource(sip);
			break;
#if defined HAVE_SIGINFO_T_SI_TIMERID && defined HAVE_SIGINFO_T_SI_OVERRUN
		case SI_TIMER:
			tprintf(", si_timerid=%#x, si_overrun=%d",
				sip->si_timerid, sip->si_overrun);
			printsigval(sip);
			break;
#endif
		default:
			printsigsource(sip);
			if (sip->si_ptr)
				printsigval(sip);
			break;
		}
	} else {
		switch (sip->si_signo) {
		case SIGCHLD:
			printsigsource(sip);
			tprints(", si_status=");
			if (sip->si_code == CLD_EXITED)
				tprintf("%d", sip->si_status);
			else
				printsignal(sip->si_status);
			tprintf(", si_utime=%llu, si_stime=%llu",
				zero_extend_signed_to_ull(sip->si_utime),
				zero_extend_signed_to_ull(sip->si_stime));
			break;
		case SIGILL: case SIGFPE:
		case SIGSEGV: case SIGBUS:
			tprints(", si_addr=");
			printaddr(ptr_to_kulong(sip->si_addr));
			break;
		case SIGPOLL:
			switch (sip->si_code) {
			case POLL_IN: case POLL_OUT: case POLL_MSG:
				tprintf(", si_band=%ld",
					(long) sip->si_band);
				break;
			}
			break;
#ifdef HAVE_SIGINFO_T_SI_SYSCALL
		case SIGSYS: {
			const char *scname =
				syscall_name((unsigned) sip->si_syscall);

			tprints(", si_call_addr=");
			printaddr(ptr_to_kulong(sip->si_call_addr));
			tprints(", si_syscall=");
			if (scname)
				tprintf("__NR_%s", scname);
			else
				tprintf("%u", (unsigned) sip->si_syscall);
			tprints(", si_arch=");
			printxval(audit_arch, sip->si_arch, "AUDIT_ARCH_???");
			break;
		}
#endif
		default:
			if (sip->si_pid || sip->si_uid)
				printsigsource(sip);
			if (sip->si_ptr)
				printsigval(sip);
		}
	}
}
Пример #14
0
void
printsiginfo(const siginfo_t *sip, int verbose)
{
	const char *code;

	if (sip->si_signo == 0) {
		tprints("{}");
		return;
	}
	tprints("{si_signo=");
	printsignal(sip->si_signo);
	code = xlookup(siginfo_codes, sip->si_code);
	if (!code) {
		switch (sip->si_signo) {
		case SIGTRAP:
			code = xlookup(sigtrap_codes, sip->si_code);
			break;
		case SIGCHLD:
			code = xlookup(sigchld_codes, sip->si_code);
			break;
		case SIGPOLL:
			code = xlookup(sigpoll_codes, sip->si_code);
			break;
		case SIGPROF:
			code = xlookup(sigprof_codes, sip->si_code);
			break;
		case SIGILL:
			code = xlookup(sigill_codes, sip->si_code);
			break;
#ifdef SIGEMT
		case SIGEMT:
			code = xlookup(sigemt_codes, sip->si_code);
			break;
#endif
		case SIGFPE:
			code = xlookup(sigfpe_codes, sip->si_code);
			break;
		case SIGSEGV:
			code = xlookup(sigsegv_codes, sip->si_code);
			break;
		case SIGBUS:
			code = xlookup(sigbus_codes, sip->si_code);
			break;
		case SIGSYS:
			code = xlookup(sigsys_codes, sip->si_code);
			break;
		}
	}
	if (code)
		tprintf(", si_code=%s", code);
	else
		tprintf(", si_code=%#x", sip->si_code);
#ifdef SI_NOINFO
	if (sip->si_code != SI_NOINFO)
#endif
	{
		if (sip->si_errno) {
			tprints(", si_errno=");
			if ((unsigned) sip->si_errno < nerrnos
			    && errnoent[sip->si_errno])
				tprints(errnoent[sip->si_errno]);
			else
				tprintf("%d", sip->si_errno);
		}
#ifdef SI_FROMUSER
		if (SI_FROMUSER(sip)) {
			switch (sip->si_code) {
#ifdef SI_USER
			case SI_USER:
				printsigsource(sip);
				break;
#endif
#ifdef SI_TKILL
			case SI_TKILL:
				printsigsource(sip);
				break;
#endif
#if defined SI_TIMER \
 && defined HAVE_SIGINFO_T_SI_TIMERID && defined HAVE_SIGINFO_T_SI_OVERRUN
			case SI_TIMER:
				tprintf(", si_timerid=%#x, si_overrun=%d",
					sip->si_timerid, sip->si_overrun);
				printsigval(sip, verbose);
				break;
#endif
			default:
				printsigsource(sip);
				if (sip->si_ptr)
					printsigval(sip, verbose);
				break;
			}
		}
		else
#endif /* SI_FROMUSER */
		{
			switch (sip->si_signo) {
			case SIGCHLD:
				printsigsource(sip);
				tprints(", si_status=");
				if (sip->si_code == CLD_EXITED)
					tprintf("%d", sip->si_status);
				else
					printsignal(sip->si_status);
				if (!verbose)
					tprints(", ...");
				else
					tprintf(", si_utime=%llu, si_stime=%llu",
						(unsigned long long) sip->si_utime,
						(unsigned long long) sip->si_stime);
				break;
			case SIGILL: case SIGFPE:
			case SIGSEGV: case SIGBUS:
				tprintf(", si_addr=%#lx",
					(unsigned long) sip->si_addr);
				break;
			case SIGPOLL:
				switch (sip->si_code) {
				case POLL_IN: case POLL_OUT: case POLL_MSG:
					tprintf(", si_band=%ld",
						(long) sip->si_band);
					break;
				}
				break;
#ifdef HAVE_SIGINFO_T_SI_SYSCALL
			case SIGSYS:
				tprintf(", si_call_addr=%#lx, si_syscall=%d, si_arch=%u",
					(unsigned long) sip->si_call_addr,
					sip->si_syscall, sip->si_arch);
				break;
#endif
			default:
				if (sip->si_pid || sip->si_uid)
				        printsigsource(sip);
				if (sip->si_ptr)
					printsigval(sip, verbose);
			}
		}
	}
	tprints("}");
}
Пример #15
0
int
sys_ptrace(struct tcb *tcp)
{
	const struct xlat *x;
	unsigned long addr;

	if (entering(tcp)) {
		printxval(ptrace_cmds, tcp->u_arg[0], "PTRACE_???");
		tprintf(", %lu, ", tcp->u_arg[1]);

		addr = tcp->u_arg[2];
		if (tcp->u_arg[0] == PTRACE_PEEKUSER
		 || tcp->u_arg[0] == PTRACE_POKEUSER
		) {
			for (x = struct_user_offsets; x->str; x++) {
				if (x->val >= addr)
					break;
			}
			if (!x->str)
				tprintf("%#lx, ", addr);
			else if (x->val > addr && x != struct_user_offsets) {
				x--;
				tprintf("%s + %ld, ", x->str, addr - x->val);
			}
			else
				tprintf("%s, ", x->str);
		} else
		if (tcp->u_arg[0] == PTRACE_GETREGSET
		 || tcp->u_arg[0] == PTRACE_SETREGSET
		) {
			printxval(nt_descriptor_types, tcp->u_arg[2], "NT_???");
			tprints(", ");
		} else
			tprintf("%#lx, ", addr);


		switch (tcp->u_arg[0]) {
#ifndef IA64
		case PTRACE_PEEKDATA:
		case PTRACE_PEEKTEXT:
		case PTRACE_PEEKUSER:
			break;
#endif
		case PTRACE_CONT:
		case PTRACE_SINGLESTEP:
		case PTRACE_SYSCALL:
		case PTRACE_DETACH:
			printsignal(tcp->u_arg[3]);
			break;
		case PTRACE_SETOPTIONS:
			printflags(ptrace_setoptions_flags, tcp->u_arg[3], "PTRACE_O_???");
			break;
		case PTRACE_SETSIGINFO: {
			printsiginfo_at(tcp, tcp->u_arg[3]);
			break;
		}
		case PTRACE_SETREGSET:
			tprint_iov(tcp, /*len:*/ 1, tcp->u_arg[3], /*as string:*/ 0);
			break;
		case PTRACE_GETSIGINFO:
		case PTRACE_GETREGSET:
			/* Don't print anything, do it at syscall return. */
			break;
		default:
			tprintf("%#lx", tcp->u_arg[3]);
			break;
		}
	} else {
		switch (tcp->u_arg[0]) {
		case PTRACE_PEEKDATA:
		case PTRACE_PEEKTEXT:
		case PTRACE_PEEKUSER:
#ifdef IA64
			return RVAL_HEX;
#else
			printnum_long(tcp, tcp->u_arg[3], "%#lx");
			break;
#endif
		case PTRACE_GETSIGINFO: {
			printsiginfo_at(tcp, tcp->u_arg[3]);
			break;
		}
		case PTRACE_GETREGSET:
			tprint_iov(tcp, /*len:*/ 1, tcp->u_arg[3], /*as string:*/ 0);
			break;
		}
	}
	return 0;
}
Пример #16
0
int main(int argc, char **argv)
{
    int i, j, result = 0;

    // process flags for -v verbose, -h help
    for (i = 1; i < argc; i++) {
        if (argv[i] && argv[i][0] == '-') {
            int len = strlen(argv[i]);
            for (j = 1; j < len; j++) {
                switch (argv[i][j]) {
                    case 'h':
                        eprintf("testdatabase.c: possible arguments "
                                "-q quiet (suppress output), "
                                "-h help\n");
                        return 1;
                        break;
                    case 'q':
                        verbose = 0;
                        break;
                    default:
                        break;
                }
            }
        }
    }

    lo_message lom;
    mapper_message msg;
    uint64_t id = 1;
    mapper_network net = mapper_network_new(0, 0, 0);
    mapper_database db = &net->database;

    mapper_device dev, *pdev, *pdev2;
    mapper_signal sig, *psig, *psig2;
    mapper_map *pmap, *pmap2;

    /* Test the database functions */

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }
    lo_message_add_string(lom, "@port");
    lo_message_add_int32(lom, 1234);
    lo_message_add_string(lom, "@host");
    lo_message_add_string(lom, "localhost");
    lo_message_add_string(lom, "@num_inputs");
    lo_message_add_int32(lom, 2);
    lo_message_add_string(lom, "@num_outputs");
    lo_message_add_int32(lom, 2);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_device(db, "testdatabase.1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }
    lo_message_add_string(lom, "@port");
    lo_message_add_int32(lom, 1234);
    lo_message_add_string(lom, "@host");
    lo_message_add_string(lom, "localhost");
    lo_message_add_string(lom, "@num_inputs");
    lo_message_add_int32(lom, 2);
    lo_message_add_string(lom, "@num_outputs");
    lo_message_add_int32(lom, 1);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_device(db, "testdatabase__.2", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }
    lo_message_add_string(lom, "@port");
    lo_message_add_int32(lom, 3000);
    lo_message_add_string(lom, "@host");
    lo_message_add_string(lom, "192.168.0.100");

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_device(db, "testdatabase.3", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }
    lo_message_add_string(lom, "@port");
    lo_message_add_int32(lom, 5678);
    lo_message_add_string(lom, "@host");
    lo_message_add_string(lom, "192.168.0.100");

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_device(db, "testdatabase__.4", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }
    lo_message_add_string(lom, "@direction");
    lo_message_add_string(lom, "input");
    lo_message_add_string(lom, "@type");
    lo_message_add_char(lom, 'f');
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_signal(db, "in1", "testdatabase.1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@direction");
    lo_message_add_string(lom, "input");
    lo_message_add_string(lom, "@type");
    lo_message_add_char(lom, 'f');
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_signal(db, "in2", "testdatabase.1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@direction");
    lo_message_add_string(lom, "output");
    lo_message_add_string(lom, "@type");
    lo_message_add_char(lom, 'f');
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_signal(db, "out1", "testdatabase.1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@direction");
    lo_message_add_string(lom, "output");
    lo_message_add_string(lom, "@type");
    lo_message_add_char(lom, 'f');
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_signal(db, "out2", "testdatabase.1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@direction");
    lo_message_add_string(lom, "output");
    lo_message_add_string(lom, "@type");
    lo_message_add_char(lom, 'f');
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    mapper_database_add_or_update_signal(db, "out1", "testdatabase__.2", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@mode");
    lo_message_add_string(lom, "bypass");
    lo_message_add_string(lom, "@dst@bound_min");
    lo_message_add_string(lom, "none");
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    const char *src_sig_name = "testdatabase.1/out2";
    mapper_database_add_or_update_map(db, 1, &src_sig_name,
                                      "testdatabase__.2/in1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@mode");
    lo_message_add_string(lom, "bypass");
    lo_message_add_string(lom, "@dst@bound_min");
    lo_message_add_string(lom, "none");
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    src_sig_name = "testdatabase__.2/out1";
    mapper_database_add_or_update_map(db, 1, &src_sig_name,
                                      "testdatabase.1/in1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@mode");
    lo_message_add_string(lom, "expression");
    lo_message_add_string(lom, "@expression");
    lo_message_add_string(lom, "(x-10)*80");
    lo_message_add_string(lom, "@dst@bound_min");
    lo_message_add_string(lom, "clamp");
    lo_message_add_string(lom, "@src@min");
    lo_message_add_float(lom, 0.f);
    lo_message_add_float(lom, 1.f);
    lo_message_add_string(lom, "@src@max");
    lo_message_add_float(lom, 1.f);
    lo_message_add_float(lom, 2.f);
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    src_sig_name = "testdatabase.1/out1";
    mapper_database_add_or_update_map(db, 1, &src_sig_name,
                                      "testdatabase__.2/in2", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    lom = lo_message_new();
    if (!lom) {
        result = 1;
        goto done;
    }

    id++;
    lo_message_add_string(lom, "@mode");
    lo_message_add_string(lom, "expression");
    lo_message_add_string(lom, "@expression");
    lo_message_add_string(lom, "(x-10)*80");
    lo_message_add_string(lom, "@dst@bound_min");
    lo_message_add_string(lom, "clamp");
    lo_message_add_string(lom, "@src@min");
    lo_message_add_float(lom, 0.f);
    lo_message_add_float(lom, 1.f);
    lo_message_add_string(lom, "@src@max");
    lo_message_add_float(lom, 1.f);
    lo_message_add_float(lom, 2.f);
    lo_message_add_string(lom, "@id");
    lo_message_add_int64(lom, id);

    if (!(msg = mapper_message_parse_properties(lo_message_get_argc(lom),
                                                lo_message_get_types(lom),
                                                lo_message_get_argv(lom)))) {
        eprintf("1: Error, parsing failed.\n");
        result = 1;
        goto done;
    }

    src_sig_name = "testdatabase.1/out1";
    mapper_database_add_or_update_map(db, 1, &src_sig_name,
                                      "testdatabase__.2/in1", msg);

    mapper_message_free(msg);
    lo_message_free(lom);

    /*********/

    if (verbose) {
        eprintf("Dump:\n");
        mapper_database_print(db);
    }

    /*********/

    eprintf("\n--- Devices ---\n");

    eprintf("\nWalk the whole database:\n");
    pdev = mapper_database_devices(db);
    int count=0;
    if (!pdev) {
        eprintf("mapper_database_devices() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pdev) {
        eprintf("mapper_database_devices() returned something "
               "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pdev) {
        count ++;
        printdevice(*pdev);
        pdev = mapper_device_query_next(pdev);
    }

    if (count != 4) {
        eprintf("Expected 4 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind device named 'testdatabase.3':\n");

    dev = mapper_database_device_by_name(db, "testdatabase.3");
    if (!dev) {
        eprintf("Not found.\n");
        result = 1;
        goto done;
    }

    printdevice(dev);

    /*********/

    eprintf("\nFind device named 'dummy':\n");

    dev = mapper_database_device_by_name(db, "dummy");
    if (dev) {
        eprintf("unexpected found 'dummy': %p\n", dev);
        result = 1;
        goto done;
    }
    eprintf("  not found, good.\n");

    /*********/

    eprintf("\nFind devices matching '__':\n");

    pdev = mapper_database_devices_by_name(db, "*__*");

    count=0;
    if (!pdev) {
        eprintf("mapper_database_devices_by_name() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pdev) {
        eprintf("mapper_database_devices_by_name() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pdev) {
        count ++;
        printdevice(*pdev);
        pdev = mapper_device_query_next(pdev);
    }

    if (count != 2) {
        eprintf("Expected 2 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind devices with property 'host'=='192.168.0.100':\n");

    pdev = mapper_database_devices_by_property(db, "host", 1, 's',
                                               "192.168.0.100", MAPPER_OP_EQUAL);

    count=0;
    if (!pdev) {
        eprintf("mapper_database_devices_by_property() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pdev) {
        eprintf("mapper_database_devices_by_property() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pdev) {
        count ++;
        printdevice(*pdev);
        pdev = mapper_device_query_next(pdev);
    }

    if (count != 2) {
        eprintf("Expected 2 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind devices with property 'port'<5678:\n");

    int port = 5678;
    pdev = mapper_database_devices_by_property(db, "port", 1, 'i', &port,
                                               MAPPER_OP_LESS_THAN);

    count=0;
    if (!pdev) {
        eprintf("mapper_database_devices_by_property() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pdev) {
        eprintf("mapper_database_devices_by_property() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pdev) {
        count ++;
        printdevice(*pdev);
        pdev = mapper_device_query_next(pdev);
    }

    if (count != 3) {
        eprintf("Expected 3 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind devices with property 'num_outputs'==2:\n");
    int temp = 2;
    pdev = mapper_database_devices_by_property(db, "num_outputs", 1, 'i', &temp,
                                               MAPPER_OP_EQUAL);

    count=0;
    if (!pdev) {
        eprintf("mapper_database_devices_by_property() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pdev) {
        eprintf("mapper_database_devices_by_property() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pdev) {
        count ++;
        printdevice(*pdev);
        pdev = mapper_device_query_next(pdev);
    }

    if (count != 1) {
        eprintf("Expected 1 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind devices with properties 'host'!='localhost' AND 'port'>=4000:\n");

    pdev = mapper_database_devices_by_property(db, "host", 1, 's', "localhost",
                                               MAPPER_OP_NOT_EQUAL);
    pdev2 = mapper_database_devices_by_property(db, "port", 1, 'i', &port,
                                                MAPPER_OP_GREATER_THAN_OR_EQUAL);
    pdev = mapper_device_query_intersection(pdev, pdev2);

    count=0;
    if (!pdev) {
        eprintf("mapper_database_devices_by_property() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pdev) {
        eprintf("mapper_database_devices_by_property() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pdev) {
        count ++;
        printdevice(*pdev);
        pdev = mapper_device_query_next(pdev);
    }

    if (count != 1) {
        eprintf("Expected 1 record, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\n--- Signals ---\n");

    eprintf("\nFind all signals for device 'testdatabase.1':\n");

    dev = mapper_database_device_by_name(db, "testdatabase.1");
    psig = mapper_device_signals(dev, MAPPER_DIR_ANY);

    count=0;
    if (!psig) {
        eprintf("mapper_device_signals() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*psig) {
        eprintf("mapper_device_signals() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_signal_query_next(psig);
    }

    if (count != 4) {
        eprintf("Expected 4 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind all signals for device 'testdatabase__xx.2':\n");

    dev = mapper_database_device_by_name(db, "testdatabase__xx.2");
    psig = mapper_device_signals(dev, MAPPER_DIR_ANY);

    count=0;
    if (psig) {
        eprintf("mapper_device_signals() incorrectly found something.\n");
        printsignal(*psig);
        mapper_signal_query_done(psig);
        result = 1;
        goto done;
    }
    else
        eprintf("  correctly returned 0.\n");

    /*********/

    eprintf("\nFind all outputs for device 'testdatabase__.2':\n");

    dev = mapper_database_device_by_name(db, "testdatabase__.2");
    psig = mapper_device_signals(dev, MAPPER_DIR_ANY);

    count=0;
    if (!psig) {
        eprintf("mapper_device_signals() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*psig) {
        eprintf("mapper_device_signals() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_signal_query_next(psig);
    }

    if (count != 3) {
        eprintf("Expected 3 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind signal matching 'in' for device 'testdatabase.1':\n");

    dev = mapper_database_device_by_name(db, "testdatabase.1");
    psig = mapper_device_signals(dev, MAPPER_DIR_ANY);
    psig2 = mapper_database_signals_by_name(db, "*in*");
    psig = mapper_signal_query_intersection(psig, psig2);

    count=0;
    if (!psig) {
        eprintf("intersection of mapper_device_signals() and "
                "mapper_database_signals_by_name() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*psig) {
        eprintf("intersection of mapper_device_signals() and "
                "mapper_database_signals_by_name() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_signal_query_next(psig);
    }

    if (count != 2) {
        eprintf("Expected 2 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind signal matching 'out' for device 'testdatabase.1':\n");

    dev = mapper_database_device_by_name(db, "testdatabase.1");
    psig = mapper_device_signals(dev, MAPPER_DIR_ANY);
    psig2 = mapper_database_signals_by_name(db, "*out*");
    psig = mapper_signal_query_intersection(psig, psig2);

    count=0;
    if (!psig) {
        eprintf("intersection of mapper_device_signals() and "
                "mapper_database_signals_by_name() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*psig) {
        eprintf("intersection of mapper_device_signals() and "
                "mapper_database_signals_by_name() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_signal_query_next(psig);
    }

    if (count != 2) {
        eprintf("Expected 2 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind signal matching 'out' for device 'testdatabase__.2':\n");

    dev = mapper_database_device_by_name(db, "testdatabase__.2");
    psig = mapper_device_signals(dev, MAPPER_DIR_ANY);
    psig2 = mapper_database_signals_by_name(db, "*out*");
    psig = mapper_signal_query_intersection(psig, psig2);

    count=0;
    if (!psig) {
        eprintf("intersection of mapper_device_signals() and "
                "mapper_database_signals_by_name() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*psig) {
        eprintf("intersection of mapper_device_signals() and "
                "mapper_database_signals_by_name() returned something "
                "which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (psig) {
        count ++;
        printsignal(*psig);
        psig = mapper_signal_query_next(psig);
    }

    if (count != 1) {
        eprintf("Expected 1 record, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\n--- maps ---\n");

    eprintf("\nFind maps with source 'out1':\n");

    psig = mapper_database_signals_by_name(db, "out1");
    pmap = 0;
    while (psig) {
        pmap2 = mapper_signal_maps(*psig, MAPPER_DIR_OUTGOING);
        pmap = mapper_map_query_union(pmap, pmap2);
        psig = mapper_signal_query_next(psig);
    }

    count=0;
    if (!pmap) {
        eprintf("combined query returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pmap) {
        eprintf("combined query returned something which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pmap) {
        count ++;
        printmap(*pmap);
        pmap = mapper_map_query_next(pmap);
    }

    if (count != 3) {
        eprintf("Expected 3 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind maps for device 'testdatabase.1', source 'out1':\n");

    dev = mapper_database_device_by_name(db, "testdatabase.1");
    sig = mapper_device_signal_by_name(dev, "out1");
    pmap = mapper_signal_maps(sig, 0);

    count=0;
    if (!pmap) {
        eprintf("mapper_signal_maps() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pmap) {
        eprintf("mapper_signal_maps() returned something which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pmap) {
        count ++;
        printmap(*pmap);
        pmap = mapper_map_query_next(pmap);
    }

    if (count != 2) {
        eprintf("Expected 2 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind maps with destination signal named 'in2':\n");

    psig = mapper_database_signals_by_name(db, "in2");
    pmap = 0;
    while (psig) {
        pmap2 = mapper_signal_maps(*psig, MAPPER_DIR_INCOMING);
        pmap = mapper_map_query_union(pmap, pmap2);
        psig = mapper_signal_query_next(psig);
    }

    count=0;
    if (!pmap) {
        eprintf("combined query returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pmap) {
        eprintf("combined query returned something which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pmap) {
        count ++;
        printmap(*pmap);
        pmap = mapper_map_query_next(pmap);
    }

    if (count != 1) {
        eprintf("Expected 1 record, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind maps for device 'testdatabase__.2', destination 'in1':\n");

    dev = mapper_database_device_by_name(db, "testdatabase__.2");
    sig = mapper_device_signal_by_name(dev, "in1");
    pmap = mapper_signal_maps(sig, MAPPER_DIR_INCOMING);

    count=0;
    if (!pmap) {
        eprintf("mapper_signal_maps() returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pmap) {
        eprintf("mapper_signal_maps() returned something which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pmap) {
        count ++;
        printmap(*pmap);
        pmap = mapper_map_query_next(pmap);
    }

    if (count != 2) {
        eprintf("Expected 2 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind maps for source device 'testdatabase__.2', signal 'out1'"
            "\n          AND dest device 'testdatabase.1', signal 'in1':\n");

    // get maps with source signal
    dev = mapper_database_device_by_name(db, "testdatabase__.2");
    sig = mapper_device_signal_by_name(dev, "out1");
    pmap = mapper_signal_maps(sig, MAPPER_DIR_OUTGOING);

    // get maps with destination signal
    dev = mapper_database_device_by_name(db, "testdatabase.1");
    sig = mapper_device_signal_by_name(dev, "in1");
    pmap2 = mapper_signal_maps(sig, MAPPER_DIR_INCOMING);

    // intersect map queries
    pmap = mapper_map_query_intersection(pmap, pmap2);

    count=0;
    if (!pmap) {
        eprintf("combined query returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pmap) {
        eprintf("combined query returned something which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pmap) {
        count ++;
        printmap(*pmap);
        pmap = mapper_map_query_next(pmap);
    }

    if (count != 1) {
        eprintf("Expected 1 records, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/

    eprintf("\nFind maps for source device 'testdatabase__.2', signals matching 'out',"
            "\n          AND dest device 'testdatabase.1', all signals:\n");

    // build source query
    dev = mapper_database_device_by_name(db, "testdatabase__.2");
    psig = mapper_device_signals(dev, MAPPER_DIR_ANY);
    psig2 = mapper_database_signals_by_name(db, "*out*");
    psig = mapper_signal_query_intersection(psig, psig2);

    pmap = 0;
    while (psig) {
        pmap2 = mapper_signal_maps(*psig, MAPPER_DIR_OUTGOING);
        pmap = mapper_map_query_union(pmap, pmap2);
        psig = mapper_signal_query_next(psig);
    }

    // build destination query
    dev = mapper_database_device_by_name(db, "testdatabase.1");
    pmap2 = mapper_device_maps(dev, MAPPER_DIR_ANY);

    // intersect queries
    pmap = mapper_map_query_intersection(pmap, pmap2);

    count=0;
    if (!pmap) {
        eprintf("combined query returned 0.\n");
        result = 1;
        goto done;
    }
    if (!*pmap) {
        eprintf("combined query returned something which pointed to 0.\n");
        result = 1;
        goto done;
    }

    while (pmap) {
        count ++;
        printmap(*pmap);
        pmap = mapper_map_query_next(pmap);
    }

    if (count != 1) {
        eprintf("Expected 1 record, but counted %d.\n", count);
        result = 1;
        goto done;
    }

    /*********/
done:
    mapper_network_free(net);
    if (!verbose)
        printf("..................................................");
    printf("Test %s.\n", result ? "FAILED" : "PASSED");
    return result;
}