Beispiel #1
0
BOOL	exec_pipes(t_pipes *p, t_info *info, FLAG son, FD pi[3])
{
  STATUS	status_quo;
  pid_t		pid;
  FD		w[2];

  if (!(pid = -(!((unsigned long)(p->next != NULL)))))
    {
      if (pipe(w) == -1)
	return (FALSE);
      if ((pid = xfork()) < 0)
	return (FALSE);
    }
  if (!pid)
    {
      init_pipe(w, pi, W_IN);
      exec_pipes(p->next, info, SON, pi);
      return (FALSE);
    }
  if (p->next)
    init_pipe(w, pi, W_OUT);
  if (exec_cmd(p->cmd, info, info->son = (son | (2 * (pid > 0))), pi) == FALSE)
    return (FALSE);
  my_wait(pid, &status_quo);
  if (pid < 0)
    return (TRUE);
  return (get_status(info, status_quo));
}
Beispiel #2
0
// Initialize resources for both the node and the clients
// First initialization function called
void IPC_initialize(int _nb_nodes)
{
  int i;

  nb_nodes = _nb_nodes;

  node0_to_all = (int **) malloc(sizeof(*node0_to_all) * nb_nodes);
  if (!node0_to_all)
  {
    printf("node0_to_all allocation error\n");
    perror("");
  }

  nodei_to_0 = (int **) malloc(sizeof(*nodei_to_0) * nb_nodes);
  if (!nodei_to_0)
  {
    printf("nodei_to_0 allocation error\n");
    perror("");
  }

  for (i = 0; i < nb_nodes; i++)
  {
    init_pipe(&node0_to_all[i]);
    init_pipe(&nodei_to_0[i]);
  }
}
Beispiel #3
0
int init(int argc, char *argv[])
{
  mtn = mtn_init(MODULE_NAME);
  ctx = calloc(1,sizeof(CTX));
  if(!mtn){
    return(-1);
  }
  if(!ctx){
    mtnlogger(NULL, 0, "[error] %s: %s\n", __func__, strerror(errno));
    return(-1);
  }
  mtn->mps_max = 512;
  mtn->logtype = 0;
  mtn->logmode = MTNLOG_STDERR;
  ctx->afd     = -1;
  ctx->nobuf   = 1;
  ctx->text    = 1;
  ctx->delim   = newstr(" ");
  ctx->targets = newarg(0);
  ctx->arg_max = sysconf(_SC_ARG_MAX);
  ctx->cpu_num = sysconf(_SC_NPROCESSORS_ONLN);
  ctx->job_max = sysconf(_SC_NPROCESSORS_ONLN);
  ctx->cmdargs = parse(argc, argv);
  gettimeofday(&(ctx->polltv), NULL);
  if(init_pipe() == -1){
    return(-1);
  }
  if(init_poll() == -1){
    return(-1);
  }
  ctx->job = calloc(ctx->job_max, sizeof(MTNJOB));
  set_signal_handler();
  mtnlogger(mtn, 1, "LogLevel: %d\n", mtn->loglevel);
  return(0);
}
Beispiel #4
0
USERS *adduser(ape_socket *client, const char *host, const char *ip, USERS *allocated, acetables *g_ape)
{
	USERS *nuser = NULL;

	/* Calling module */
	if (allocated == NULL) {
		FIRE_EVENT(allocateuser, nuser, client, host, ip, g_ape);
		
		nuser = init_user(g_ape);
		strncpy(nuser->ip, ip, 16);
		
		nuser->pipe = init_pipe(nuser, USER_PIPE, g_ape);
		nuser->type = (client != NULL ? HUMAN : BOT);
		
		nuser->istmp = 1;
		
		hashtbl_append(g_ape->hSessid, nuser->sessid, (void *)nuser);

		addsubuser(client, host, nuser, g_ape);
	} else {
		FIRE_EVENT(adduser, nuser, allocated, g_ape);
		
		nuser = allocated;
		nuser->istmp = 0;
		
		g_ape->nConnected++;
		
		//ape_log(APE_INFO, __FILE__, __LINE__, g_ape, 
		//	"New user - (ip : %s)", nuser->ip);
	}

	return nuser;
	
}
Beispiel #5
0
int	do_shell_bin(t_command *t, t_env *env)
{
  char	buffer[4096];
  int	i[2];
  int	pipefd[2][2];

  init_pipe(pipefd, i);
  while (i[0] < t->command_count)
    if (create_path(t->commands[i[0]][0], env, buffer) == 1)
    {
      if (CMD_C > 1 && i[0] != CMD_C - 1 && pipe(pipefd[i[1]]) == -1)
          return (my_printf("Error: fail to create pipe...\n"));
      safe_close(pipefd[!i[1]][1]);
      if (fork() == 0)
      {
        create_pipe_redirect(pipefd, t, i[0], i[1]);
        execve(buffer, t->commands[i[0]], env->environ);
        exit(1);
      }
      else
        wait(NULL);
      i[1] = !i[1];
      ++i[0];
    }
    else
      return (1);
  return (close_pipefd(pipefd));
}
Beispiel #6
0
CHANNEL *mkchan(char *chan, acetables *g_ape)
{
	CHANNEL *new_chan = NULL;


	FIRE_EVENT(mkchan, new_chan, chan, g_ape);

	
	if (!isvalidchan(chan)) {
		return NULL;
	}
	
	new_chan = (CHANNEL *) xmalloc(sizeof(*new_chan));
		
	memcpy(new_chan->name, chan, strlen(chan)+1);
	
	new_chan->head = NULL;
	new_chan->banned = NULL;
	new_chan->properties = NULL;
	
	new_chan->interactive = (*new_chan->name == '*' ? 0 : 1);

	//memcpy(new_chan->topic, topic, strlen(topic)+1);

	new_chan->pipe = init_pipe(new_chan, CHANNEL_PIPE, g_ape);
	
	hashtbl_append(g_ape->hLusers, chan, (void *)new_chan);
	
	/* just to test */
	//proxy_attach(proxy_init("olol", "localhost", 1337, g_ape), new_chan->pipe->pubid, 0, g_ape);
	
	return new_chan;
	
}
Beispiel #7
0
int
run_client_thread(in_port_t distant_por, struct in_addr *distant_addr, uint8_t proposed_page_page_count,
        handler_run handler_fct,  struct xen_shm_handler_data* hdlr_data, pthread_t* thread_info)
{

    int ret;

    hdlr_data->stop = 0;

    ret = init_pipe(distant_por, distant_addr, &hdlr_data->receive_fd, &hdlr_data->send_fd, proposed_page_page_count);
    if(ret!=0) {
        perror("init pipe");
        return ret;
    }

    ret = pthread_create(thread_info, /* Default attr */ NULL, (void * (*)(void *))handler_fct, hdlr_data);
    if (ret != 0) {
        perror("pthread create");
        xen_shm_pipe_free(hdlr_data->receive_fd);
        xen_shm_pipe_free(hdlr_data->send_fd);
        return ret;
    }

    return 0;
}
Beispiel #8
0
static inline bool init_hook(HANDLE thread_handle)
{
	wait_for_dll_main_finish(thread_handle);

	sprintf(keepalive_name, "%s%d", EVENT_HOOK_KEEPALIVE,
			GetCurrentProcessId());

	if (!init_pipe()) {
		return false;
	}
	if (!init_signals()) {
		return false;
	}
	if (!init_mutexes()) {
		return false;
	}
	if (!init_system_path()) {
		return false;
	}
	if (!init_hook_info()) {
		return false;
	}

	log_current_process();

	SetEvent(signal_restart);
	return true;
}
Beispiel #9
0
USERS *adduser(unsigned int fdclient, char *host, acetables *g_ape)
{
	USERS *nuser = NULL;

	/* Calling module */
	FIRE_EVENT(adduser, nuser, fdclient, host, g_ape);
	

	nuser = init_user(g_ape);
	
	nuser->type = (fdclient ? HUMAN : BOT);
		
	g_ape->uHead = nuser;
	
	nuser->pipe = init_pipe(nuser, USER_PIPE, g_ape);

	hashtbl_append(g_ape->hSessid, nuser->sessid, (void *)nuser);
	
	g_ape->nConnected++;
	
	addsubuser(fdclient, host, nuser, g_ape);

	return nuser;
	
}
Beispiel #10
0
inline bool capture_should_init(void)
{
	if (!capture_active() && capture_restarted()) {
		if (capture_alive()) {
			if (!ipc_pipe_client_valid(&pipe)) {
				init_pipe();
			}
			return true;
		}
	}

	return false;
}
Beispiel #11
0
/// <summary>Our raspicomm daemon specific work gets done.</summary>
void do_work(void)
{
  /* setup the syslog for logging */
  init_syslog();

  /* read the settings from the settings file */
  Settings settings; int ret;
  if ((ret = load_settings(&settings)) < 0)
  {
    //syslog(LOG_ERR, "loading settings failed (%i)", ret); 
    exit(EXIT_FAILURE);
  }
    
  if (settings.log)
  {
    syslog(LOG_INFO, "starting...");

    syslog(LOG_INFO, "using %s: port '%i' and pidfile '%s' and log=%i", 
      ret == 0 ? "default configuration" : "configurationfile",
      settings.port, 
      settings.pidfile,
      settings.log);
  }  

  /* write the pidfile */
  if ( write_pidfile(settings.pidfile) != 0)
    if (settings.log)
      syslog(LOG_ERR, "writing PIDFILE '%s' failed", settings.pidfile);

  /* use the settings to initialize the raspicomm */
  if (daemon_init_raspicomm(&settings) != SUCCESS)
    exit(EXIT_FAILURE);

  /* init the pipe */
  if (init_pipe() != 0)
    if (settings.log)
      syslog(LOG_ERR, "init_pipe failed");

  /* block and work */
  enter_main_loop(&settings);
  
  /* tear down raspicomm */
  daemon_shutdown();

}
Beispiel #12
0
int
run_client(in_port_t distant_por, struct in_addr *distant_addr, uint8_t proposed_page_page_count,
        handler_run handler_fct,  struct xen_shm_handler_data* hdlr_data, void** returned_value)
{
    int ret;

    hdlr_data->stop = 0;

    ret = init_pipe(distant_por, distant_addr, &hdlr_data->receive_fd, &hdlr_data->send_fd, proposed_page_page_count);
    if(ret!=0) {
        perror("init pipe");
        return ret;
    }

    *returned_value = handler_fct(hdlr_data);

    return 0;
}
Beispiel #13
0
ape_proxy *proxy_init(char *ident, char *host, int port, acetables *g_ape)
{
	ape_proxy *proxy;

	ape_proxy_cache *host_cache;

	
	if (strlen(ident) > 32 || ((host_cache = proxy_cache_gethostbyname(host, g_ape)) == NULL)) {
		return NULL;
	}
	
	proxy = xmalloc(sizeof(*proxy));
	
	memcpy(proxy->identifier, ident, strlen(ident)+1);
	
	proxy->sock.host = host_cache;
	proxy->sock.port = port;
	proxy->sock.fd = -1;
	proxy->eol = 0;
	
	proxy->state = PROXY_NOT_CONNECTED;
	proxy->nlink = 0;
	
	proxy->to = NULL;
	proxy->next = NULL;
	proxy->properties = NULL;
	
	proxy->pipe = init_pipe(proxy, PROXY_PIPE, g_ape);
	
	
	proxy->prev = NULL;
	
	proxy->next = g_ape->proxy.list;
	if (proxy->next != NULL) {
		proxy->next->prev = proxy;
	}
	
	g_ape->proxy.list = proxy;
	
	return proxy;
}
Beispiel #14
0
//-----------------------------------------------------------------------------
bool init_predcontroller_to_coordinator_pipe( void ) {
  return init_pipe( FD_PREDCONTROLLER_TO_COORDINATOR_READ_CHANNEL, FD_PREDCONTROLLER_TO_COORDINATOR_WRITE_CHANNEL, true );
}
Beispiel #15
0
//-----------------------------------------------------------------------------
bool init_predplanner_to_coordinator_pipe( void ) {
  return init_pipe( FD_PREDPLANNER_TO_COORDINATOR_READ_CHANNEL, FD_PREDPLANNER_TO_COORDINATOR_WRITE_CHANNEL, true );
}
Beispiel #16
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool init_wakeup_pipe( void ) {
  return init_pipe( FD_WAKEUP_TO_COORDINATOR_READ_CHANNEL, FD_WAKEUP_TO_COORDINATOR_WRITE_CHANNEL, true );
}
Beispiel #17
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool init_timer_pipe( void ) {
  return init_pipe( FD_TIMER_TO_COORDINATOR_READ_CHANNEL, FD_TIMER_TO_COORDINATOR_WRITE_CHANNEL, true );
}
Beispiel #18
0
int main(int argc, char* argv[])
{
	struct pipe p;
	void* h;
	void* h0, *h1, *h2;
	void* b;
	const void* b0, *b1, *b2;
	int s0, s1, s2;

	// init
	printf("%d\n", init_pipe(&p, 3, 2, 0x1));

#if 0
	//get and push
	h0 = get_buf(&p, &b);
	printf("%p %p\n", h0, b);
	printf("%d\n", push_buf(&p, h0, 1));

	print_pipe(&p);

	h0 = pull_buf(&p, 0, &b0, &s0);
	h1 = pull_buf(&p, 1, &b1, &s1);
	h2 = pull_buf(&p, 2, &b2, &s2);
	put_buf(&p, h0);
	put_buf(&p, h1);
	put_buf(&p, h2);

	print_pipe(&p);

	h0 = get_buf(&p, &b);
	printf("%p %p\n", h0, b);
	printf("%d\n", push_buf(&p, h0, 1));
#endif

	// src push 0 1 2
	h = get_buf(&p, &b); push_buf(&p, h, 1);
	// src push 0 1 2
	h = get_buf(&p, &b); push_buf(&p, h, 2);

	// dst pull 1 2
	h2 = pull_buf(&p, 2, &b2, &s2); put_buf(&p, h2);
	h1 = pull_buf(&p, 1, &b1, &s1); put_buf(&p, h1);
	//print_pipe(&p); exit(0);

	// src push 1 2 (0 is full)
	h = get_buf(&p, &b); push_buf(&p, h, 3);
	//print_pipe(&p); exit(0);

	// dst pull 1 2
	h2 = pull_buf(&p, 2, &b2, &s2); put_buf(&p, h2);
	h1 = pull_buf(&p, 1, &b1, &s1); put_buf(&p, h1);
	//print_pipe(&p); exit(0);

	// dst pull 1 2
	h2 = pull_buf(&p, 2, &b2, &s2); put_buf(&p, h2);
	h1 = pull_buf(&p, 1, &b1, &s1); put_buf(&p, h1);
	//print_pipe(&p); exit(0);

	// dst pull 0
	h0 = pull_buf(&p, 0, &b0, &s0); put_buf(&p, h0);

	// dst pull 0
	h0 = pull_buf(&p, 0, &b0, &s0); put_buf(&p, h0);
	//print_pipe(&p); exit(0);

	// src push 0 1 2
	h = get_buf(&p, &b); push_buf(&p, h, 4);
	// src push 0 1 2
	h = get_buf(&p, &b); push_buf(&p, h, 5);
	// src push 0 1 2
	h = get_buf(&p, &b); push_buf(&p, h, 6);
	// src push 0 1 2
	h = get_buf(&p, &b); push_buf(&p, h, 7);
	//print_pipe(&p); exit(0);

	// dst pull 0
	h0 = pull_buf(&p, 0, &b0, &s0); put_buf(&p, h0);
	// dst pull 0
	h0 = pull_buf(&p, 0, &b0, &s0); put_buf(&p, h0);
	h0 = pull_buf(&p, 0, &b0, &s0); 
	printf("%p\n", h0);

	print_pipe(&p); exit(0);
		//should be src(0), dst0(0), dst1(2), dst2(2)

#if 0
	struct queue q;
	void* p;
	init_queue(&q, 5);
	printf("%d\n", enqueue(&q, (void*)1));
	printf("%d\n", enqueue(&q, (void*)2));
	printf("%d\n", enqueue(&q, (void*)3));
	printf("%d\n", enqueue(&q, (void*)4));
	printf("%d\n", enqueue(&q, (void*)5));
	printf("%d\n", enqueue(&q, (void*)6));
	printf("\n");
	printf("%d ", dequeue(&q, &p)); printf("%p\n", p);
	printf("%d ", dequeue(&q, &p)); printf("%p\n", p);
	printf("%d ", dequeue(&q, &p)); printf("%p\n", p);
	printf("%d ", dequeue(&q, &p)); printf("%p\n", p);
	printf("%d ", dequeue(&q, &p)); printf("%p\n", p);
	printf("%d ", dequeue(&q, &p)); printf("%p\n", p);

	printf("\n\n");
	init_queue(&q, 7);
	printf("%d\n", enqueue(&q, (void*)1));
	printf("%d\n", enqueue(&q, (void*)2));
	printf("%d\n", enqueue(&q, (void*)3));
	printf("%d\n", enqueue(&q, (void*)4));
	printf("%d\n", enqueue(&q, (void*)5));
	printf("%d\n", enqueue(&q, (void*)6));
	printf("%d\n", enqueue(&q, (void*)7));
	printf("%d\n", enqueue(&q, (void*)8));
	printf("\n");
	printf("%d ", dequeue(&q, &p)); printf("%p\n", p);
	printf("%d ", dequeue(&q, &p)); printf("%p\n", p);
	printf("%d ", dequeue(&q, &p)); printf("%p\n", p);
	printf("%d ", dequeue(&q, &p)); printf("%p\n", p);
	printf("%d ", dequeue(&q, &p)); printf("%p\n", p);
	printf("%d ", dequeue(&q, &p)); printf("%p\n", p);
	printf("%d ", dequeue(&q, &p)); printf("%p\n", p);
	printf("%d ", dequeue(&q, &p)); printf("%p\n", p);
#endif

	return 0;
}
Beispiel #19
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool init_wakeup_pipe( void ) {
  // should be write blocking or not?
  return init_pipe( FD_WAKEUP_TO_COORDINATOR_READ_CHANNEL, FD_WAKEUP_TO_COORDINATOR_WRITE_CHANNEL, true );
}
Beispiel #20
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool init_coordinator_to_preycontroller_pipe( void ) {
  return init_pipe( FD_COORDINATOR_TO_PREYCONTROLLER_READ_CHANNEL, FD_COORDINATOR_TO_PREYCONTROLLER_WRITE_CHANNEL );
}
Beispiel #21
0
static int test_update(void)
{
   logbuffer_t logbuf = logbuffer_FREE;
   thread_t *  thread = 0;
   pipe_t      pipe   = pipe_FREE;
   uint8_t     buffer[1024];
   uint8_t     readbuffer[1024+1];

   // prepare
   TEST(0 == init_pipe(&pipe));
   logbuf = (logbuffer_t) logbuffer_INIT(sizeof(buffer), buffer, pipe.write);

   // TEST truncate_logbuffer
   for (unsigned i = 0; i < 32; ++i) {
      logbuf.logsize = 32;
      logbuf.addr[i] = 'a';
      truncate_logbuffer(&logbuf, i);
      TEST(logbuf.addr == buffer);
      TEST(logbuf.size == sizeof(buffer));
      TEST(logbuf.io   == pipe.write);
      TEST(logbuf.addr[i] == 0);
      TEST(logbuf.logsize == i);
   }

   // TEST truncate_logbuffer: parameter with bigger or equal size are ignored
   for (unsigned i = 0; i < 32; ++i) {
      logbuf.logsize = i;
      logbuf.addr[i]   = 'a';
      logbuf.addr[i+1] = 'a';
      truncate_logbuffer(&logbuf, i+1);
      truncate_logbuffer(&logbuf, i);
      TEST(logbuf.addr == buffer);
      TEST(logbuf.size == sizeof(buffer));
      TEST(logbuf.io   == pipe.write);
      TEST(logbuf.addr[i]   == 'a');
      TEST(logbuf.addr[i+1] == 'a');
      TEST(logbuf.logsize   == i);
   }

   // TEST write_logbuffer
   memset(readbuffer, 0, sizeof(readbuffer));
   for (unsigned i = 0; i < sizeof(buffer); ++i) {
      buffer[i] = (uint8_t)i;
   }
   logbuf.logsize = logbuf.size;
   // test
   TEST( 0 == write_logbuffer(&logbuf));
   // check logbuf
   TEST( logbuf.addr == buffer);
   TEST( logbuf.size == sizeof(buffer));
   TEST( logbuf.logsize == sizeof(buffer));
   TEST( logbuf.io   == pipe.write);
   // check content of pipe
   static_assert(sizeof(readbuffer) > sizeof(buffer), "check that only sizeof(buffer) are written");
   TEST(sizeof(buffer) == read(pipe.read, readbuffer, sizeof(readbuffer)));
   for (unsigned i = 0; i < sizeof(buffer); ++i) {
      TEST(buffer[i] == readbuffer[i]);
   }

   // TEST printheader_logbuffer
   logbuf.logsize = 0;
   log_header_t header = log_header_INIT("test_update", "file", 123456);
   printheader_logbuffer(&logbuf, &header);
   TEST(0 == compare_header(logbuf.logsize, logbuf.addr, "test_update", "file", 123456));
   for (size_t len = logbuf.logsize, i = 1; i < 10; ++i) {
      printheader_logbuffer(&logbuf, &header);
      TEST((i+1)*len == logbuf.logsize);
      TEST(0 == compare_header(len, logbuf.addr + i*len, "test_update", "file", 123456));
   }

   // TEST printheader_logbuffer: other thread
   TEST(0 == newgeneric_thread(&thread, &thread_printheader, &logbuf));
   TEST(0 == join_thread(thread));
   TEST(0 == returncode_thread(thread));
   TEST(0 == delete_thread(&thread));

   // TEST printheader_logbuffer: adds " ..." at end in case of truncated message
   logbuf.logsize = logbuf.size - 10;
   logbuf.addr[logbuf.logsize] = 0;
   printheader_logbuffer(&logbuf, &header);
   TEST(logbuf.logsize == logbuf.size - 1)
   TEST(0 == memcmp(logbuf.addr + logbuf.size - 10, "[", 1));
   TEST(0 == memcmp(logbuf.addr + logbuf.size - 5, " ...", 5));

   // TEST vprintf_logbuffer: append on already stored content
   for (unsigned i = 0; i < sizeof(buffer)-100; ++i) {
      memset(buffer, 0, sizeof(buffer));
      memset(readbuffer, 0, sizeof(readbuffer));
      logbuf.logsize = i;
      printf_logbuffer(&logbuf, "%d : %s : %c;;", i, "OK!", '0');
      snprintf((char*)readbuffer + i, 100, "%d : %s : %c;;", i, "OK!", '0');
      TEST(0 == memcmp(buffer, readbuffer, sizeof(buffer)));
   }

   // TEST vprintf_logbuffer: different formats
   logbuf.logsize = 0;
   printf_logbuffer(&logbuf, "%%%s%%", "str" );
   printf_logbuffer(&logbuf, "%"PRIi8";", (int8_t)-1);
   printf_logbuffer(&logbuf, "%"PRIu8";", (uint8_t)1);
   printf_logbuffer(&logbuf, "%"PRIi16";", (int16_t)-256);
   printf_logbuffer(&logbuf, "%"PRIu16";", (uint16_t)256);
   printf_logbuffer(&logbuf, "%"PRIi32";", (int32_t)-65536);
   printf_logbuffer(&logbuf, "%"PRIu32";", (uint32_t)65536);
   printf_logbuffer(&logbuf, "%zd;", (ssize_t)-65536);
   printf_logbuffer(&logbuf, "%zu;", (size_t)65536);
   printf_logbuffer(&logbuf, "%g;", 2e100);
   printf_logbuffer(&logbuf, "%.0f;", (double)1234567);
   const char * result = "%str%-1;1;-256;256;-65536;65536;-65536;65536;2e+100;1234567;";
   TEST(strlen(result) == logbuf.logsize);
   TEST(0 == memcmp(logbuf.addr, result, logbuf.logsize));

   // TEST vprintf_logwriter: adds " ..." at end in case of truncated message
   char strtoobig[100];
   memset(strtoobig, '1', sizeof(strtoobig));
   logbuf.logsize = logbuf.size - sizeof(strtoobig);
   logbuf.addr[logbuf.logsize] = 0;
   printf_logbuffer(&logbuf, "%.100s", strtoobig);
   TEST(logbuf.logsize == logbuf.size - 1)
   TEST(0 == memcmp(logbuf.addr + logbuf.size - sizeof(strtoobig), strtoobig, sizeof(strtoobig)-5));
   TEST(0 == memcmp(logbuf.addr + logbuf.size - 5, " ...", 5));

   // TEST vprintf_logbuffer: format == 0
   logbuf.logsize = 0;
   printf_logbuffer(&logbuf, 0);
   // nothing printed
   TEST(0 == logbuf.logsize);

   // TEST vprintf_logbuffer: sizefree_logbuffer() == 0
   logbuf.logsize = logbuf.size;
   memset(logbuf.addr, 255, logbuf.size);
   printf_logbuffer(&logbuf, "%d", 12345);
   // check logbuf not changed
   TEST(buffer == logbuf.addr);
   TEST(sizeof(buffer) == logbuf.size);
   TEST(sizeof(buffer) == logbuf.logsize);
   TEST(pipe.write     == logbuf.io);
   // check content of logbuf not changed except for " ..."
   for (size_t i = 0; i < logbuf.logsize - 5; ++i) {
      TEST(255 == logbuf.addr[i]);
   }
   TEST(0 == memcmp(logbuf.addr + logbuf.logsize - 5, " ...", 4));
   TEST(255 == logbuf.addr[logbuf.logsize-1]);

   // TEST vprintf_logbuffer: logbuffer_t.size <= 5
   for (size_t s = 5; s <= 5; --s) {
      TEST(sizeof(buffer) == logbuf.size);
      logbuf.size = s;
      logbuf.logsize = 0;
      memset(logbuf.addr, 255, s);
      printf_logbuffer(&logbuf, "%d", 12345);
      // check logbuf
      TEST(buffer == logbuf.addr);
      TEST(s      == logbuf.size);
      TEST((s?s-1:0)  == logbuf.logsize);
      TEST(pipe.write == logbuf.io);
      // check content of logbuf
      if (s == 5) {
         // " ..."
         TEST(0 == memcmp(logbuf.addr, " ...", 5));
      } else {
         // truncated 12345
         for (size_t i = 0; i < logbuf.logsize; ++i) {
            TEST(i+'1' == logbuf.addr[i]);
         }
         TEST(0 == (logbuf.size ? logbuf.addr[logbuf.size-1] : 0));
      }
      // reset
      logbuf.size = sizeof(buffer);
   }

   // unprepare
   TEST(-1 == read(pipe.read, readbuffer, sizeof(readbuffer)));
   TEST(0 == free_pipe(&pipe));

   return 0;
ONERR:
   delete_thread(&thread);
   free_pipe(&pipe);
   return EINVAL;
}