示例#1
0
文件: swap.c 项目: xcw0579/mudOS
/*
 * Actually swap something out.
 *   block   - the memory to swap out
 *   size    - how big it is
 *   locp    - the swap location is written to the int this points to
 */
static int
swap_out(char *  block, int  size, int *  locp)
{
    if (!block || time_to_swap == 0)
	return 0;
    if (!assert_swap_file())
	return 0;

    if (*locp == -1) {		/* needs data written out */
	*locp = alloc_swap(size + sizeof size);
	swap_seek(*locp, 0);
#ifdef SWAP_USE_FD
        if ((write(swap_file, &size, sizeof size) != sizeof size) ||
	    write(swap_file, block, size) != size) {
	    debug_perror("swap_out", swap_file);
	    *locp = -1;
	    return 0;
	}
#else
	if (fwrite((char *) &size, sizeof size, 1, swap_file) != 1 ||
	    fwrite(block, size, 1, swap_file) != 1) {
	    debug_perror("swap_out:swap file", 0);
	    *locp = -1;
	    return 0;
	}
#endif
	if (*locp >= last_data)
	    last_data = *locp + sizeof size + size;
    }
    total_bytes_swapped += size;/* also count sizeof int?? */
    return 1;
}
示例#2
0
文件: state.c 项目: kfish/libuiomux
static struct uiomux_state *
create_shared_state (void)
{
  struct uiomux_state * state;
  int shm_descr;
  size_t size;

  size = sizeof(struct uiomux_state) + init_owners_table(NULL);

  shm_descr = shm_open (UIOMUX_SHM_NAME, O_CREAT | O_EXCL | O_RDWR, S_IRWXU);
  if (shm_descr == -1) {
    debug_perror ("create_shared_state: shm_open");
    return NULL;
  }

  if (ftruncate (shm_descr, size) < 0 ) {
    debug_perror ("create_shared_state: ftruncate");
  }

  state = (struct uiomux_state *) mmap(0, size, PROT_READ | PROT_WRITE,
                                       MAP_SHARED, shm_descr, (long)0);
  if (state == MAP_FAILED) {
    debug_perror ("create_shared_state: mmap");
    return NULL;
  }

  close (shm_descr);

  state->proper_address = (void *)state;
  state->version = UIOMUX_STATE_VERSION;
  state->size = size;
  
  return state;
}
示例#3
0
文件: state.c 项目: kfish/libuiomux
static struct uiomux_state *
map_shared_state (void)
{
  struct uiomux_state * state;
  int shm_descr;
  void * exact_address;
  size_t size;

  debug_info ("map_shared_state: IN");

  size = sizeof(struct uiomux_state) + init_owners_table(NULL);

  shm_descr = shm_open (UIOMUX_SHM_NAME, O_RDWR, S_IRWXU);
  if (shm_descr == -1) {
    debug_perror ("map_shared_state: shm_open");
    return NULL;
  }

  debug_info ("map_shared_state: mmap ...");
  state = (struct uiomux_state *) mmap(0, size, PROT_READ | PROT_WRITE,
                                       MAP_SHARED, shm_descr, (long)0);
  if (state == MAP_FAILED) {
    debug_perror ("map_shared_state: mmap");
    close (shm_descr);
    return NULL;
  }

  if (state->proper_address != (void *)state) {
    debug_info ("map_shared_state: Not mapped at proper address, trying with MAP_FIXED ...");
    exact_address = state->proper_address;
#ifdef DEBUG
    fprintf (stderr, "%s: exact_address %p\n", __func__, exact_address);
#endif
    munmap ((void *)state, size);
    state = (struct uiomux_state *) mmap(exact_address, size, PROT_READ | PROT_WRITE,
                                         MAP_SHARED | MAP_FIXED, shm_descr, (long)0);
    if (state == MAP_FAILED) {
      debug_perror ("map_shared_state: mmap (MAP_FIXED)");
      close (shm_descr);
      return NULL;
    }
  }

  if (state->version != UIOMUX_STATE_VERSION || state->num_blocks < UIOMUX_BLOCK_MAX) {
    debug_info ("map_shared_state: Incorrect version or num_blocks, unmapping and closing ...");
    munmap ((void *)state, size);
    close (shm_descr);
    /* XXX: Set error code for incorrect UIOMux version */
    return NULL;
  }

  close (shm_descr);

  return state;
}
示例#4
0
文件: state.c 项目: kfish/libuiomux
int
destroy_shared_state (struct uiomux_state * state)
{
  pthread_mutex_t * mutex;
  int i, ret;
  size_t size;

  if (state == NULL) return -1;
  if (state->proper_address != state) return -1;

  for (i = 0; i < UIOMUX_BLOCK_MAX; i++) {
    /* Destroy mutex */
    mutex = &state->mutex[i].mutex;
    ret = pthread_mutex_destroy (mutex);
    if (ret == EBUSY) {
#ifdef DEBUG
      perror ("pthread_mutex_destroy");
#endif
    }
  }

  if (state->version == 1) {
    size = sizeof (struct uiomux_state);
  } else {
    size = state->size;
  }
  munmap ((void *)state, size);

  if (shm_unlink (UIOMUX_SHM_NAME) < 0) {
    debug_perror ("shm_unlink");
  }

  return 0;
}
示例#5
0
/* transmit and free message */
void cann_transmit(cann_conn_t *conn, rs232can_msg *msg)
{
        // sanity
        if (conn->error) {
                debug(5,
                      "cann_transmit: not transmiting on errorous connection fd=%d",
                      conn->fd);
                return;
        }

        debug(9, "Transmitting message fd=%d", conn->fd);

        /* copy this into another buffer, convert to cantcp and send it with a single write to avoid multiple tcp packets */
        unsigned char txbuf[sizeof(rs232can_msg)], swap;
        memcpy((void *) txbuf, (void *) msg, sizeof(rs232can_msg));
        swap = txbuf[0];
        txbuf[0] = txbuf[1];
        txbuf[1] = swap;
        if (send(conn->fd, txbuf, 2 + msg->len, MSG_NOSIGNAL) != msg->len + 2)
                goto error;

        return;
error:
        conn->error = 1;
        debug_perror(5, "Error sending fd %d", conn->fd);
        return;

}
示例#6
0
/*
 * I/O handler.
 */
INLINE void aserv_process_io (int nb)
{
    int i;

    switch (nb) {
    case -1:
	debug_perror("sigio_handler: select", 0);
	break;
    case 0:
	break;
    default:
	/*
	 * check for new connection.
	 */
	if (FD_ISSET(conn_fd, &readmask)) {
	    DBG(("sigio_handler: NEW_CONN"));
	    enqueue_datapending(conn_fd, NEW_CONN);
	}
	/*
	 * check for data pending on established connections.
	 */
	for (i = 0; i < MAX_CONNS; i++) {
	    if (FD_ISSET(all_conns[i].fd, &readmask)) {
		DBG(("sigio_handler: CONN"));
		enqueue_datapending(all_conns[i].fd, CONN);
	    }
	}
	break;
    }
}
示例#7
0
void cache_add_hosts_entries(FILE *cache_file)
{
  FILE *hosts_fp;
  char line[BUF_SIZE];
  char *ip, *name;

  debug("cache_add_hosts_entreies()\n");

  hosts_fp = fopen( config.hosts_file , "r");
  if( !hosts_fp ) {
	debug_perror("can not open 'hosts'-file ");
	return;
  }

  while( fgets(line, BUF_SIZE, hosts_fp) ){
	 line[strlen(line) - 1] = 0; /* get rid of '\n' */
	 ip = strtok( line, " \t");
	 if( ip == NULL ) continue;  /* ignore blank lines */
	 if( ip[0] == '#' )continue; /* ignore comments */
	 while( (name = strtok( NULL, " \t" )) ){
	   if(name[0] == '#')break;

#if 0//defined(AEI_VDSL_CUSTOMER_NCS)
           if(strstr(name,config.domain_name)==NULL)
                fprintf( cache_file, "%s.%s %s %ld\n", name,config.domain_name, ip, 0L );
           else
#endif
		fprintf( cache_file, "%s %s %ld\n", name, ip, 0L );
	 }
	 
  }
  fclose(hosts_fp);
  debug("cache_add_hosts_entreies(): done\n");
}
示例#8
0
int dns_read_packet(int sock, dns_request_t *m)
{
  struct sockaddr_in sa;
  int salen;
  
  /* Read in the actual packet */
  salen = sizeof(sa);
  
  m->numread = recvfrom(sock, m->original_buf, sizeof(m->original_buf), 0,
		     (struct sockaddr *)&sa, &salen);
  
  if ( m->numread < 0) {
    debug_perror("dns_read_packet: recvfrom\n");
    return -1;
  }
  
  /* TODO: check source addr against list of allowed hosts */

  /* record where it came from */
  memcpy( (void *)&m->src_addr, (void *)&sa.sin_addr, sizeof(struct in_addr));
  m->src_port = ntohs( sa.sin_port );

  /* check that the message is long enough */
  if( m->numread < sizeof (m->message.header) ){
    debug("dns_read_packet: packet from '%s' to short to be dns packet", 
	  inet_ntoa (sa.sin_addr) );
    return -1;
  }

  /* pass on for full decode */
  dns_decode_request( m );

  return 0;
}
示例#9
0
int main(int argc, char **argv)
{

  /* get commandline options, load config if needed. */
  if(get_options( argc, argv ) < 0 ) {
	  exit(1);
  }

  signal(SIGHUP, sig_hup);

  dns_init();

  if (config.daemon_mode) {
    /* Standard fork and background code */
    switch (fork()) {
	 case -1:	/* Oh shit, something went wrong */
		debug_perror("fork");
		exit(-1);
	 case 0:	/* Child: close off stdout, stdin and stderr */
		close(0);
		close(1);
		close(2);
		break;
	 default:	/* Parent: Just exit */
		exit(0);
    }
  }

  dns_main_loop();

  return 0;
}
示例#10
0
int dns_init()
{
  struct sockaddr_in sa;
  struct in_addr ip;

  /* Clear it out */
  memset((void *)&sa, 0, sizeof(sa));

  dns_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

  /* Error */
  if( dns_sock < 0 ){
	 debug_perror("Could not create socket");
	 exit(1);
  }

  ip.s_addr = INADDR_ANY;
  sa.sin_family = AF_INET;
  memcpy((void *)&sa.sin_addr, (void *)&ip, sizeof(struct in_addr));
  sa.sin_port = htons(PORT);

  /* bind() the socket to the interface */
  if (bind(dns_sock, (struct sockaddr *)&sa, sizeof(struct sockaddr)) < 0){
	 debug_perror("dns_init: bind: Could not bind to port");
	 exit(1);
  }

  dns_main_quit = 0;

  FD_ZERO( &rfds );
  FD_SET( dns_sock, &rfds );

  dns_request_list = NULL;

  cache_purge( config.purge_time );

  return 1;
}
示例#11
0
INLINE int set_socket_nonblocking P2(int, fd, int, which)
{
#if !defined(OLD_ULTRIX) && !defined(_SEQUENT_)
    int result;
#endif

#ifdef OLD_ULTRIX
    if (which)
	return fcntl(fd, F_SETFL, FNDELAY);
    else
	return fcntl(fd, F_SETFL, FNBLOCK);
#else

#ifdef _SEQUENT_
    int flags = fcntl(fd, F_GETFL, 0);

    if (flags == -1)
	return (-1);
    if (which)
	flags |= O_NONBLOCK;
    else
	flags &= ~O_NONBLOCK;
    return fcntl(fd, F_SETFL, flags);
#else
    result = OS_socket_ioctl(fd, FIONBIO, &which);
    if (result == -1)
	debug_perror("set_socket_nonblocking: ioctl", 0);
#if 0
    /* boggle ... someone track down an errno for this */
    if (result == -1) {
	XXX("Try using cc instead of gcc to correct this error.\n");
    }
#endif
    return result;
#endif

#endif
}
示例#12
0
int dns_write_packet(int sock, struct in_addr in, int port, dns_request_t *m)
{
  struct sockaddr_in sa;
  int retval;

  /* Zero it out */
  memset((void *)&sa, 0, sizeof(sa));

  /* Fill in the information */
  //inet_aton( "203.12.160.35", &in );
  memcpy( &sa.sin_addr.s_addr, &in, sizeof(in) );
  sa.sin_port = htons(port);
  sa.sin_family = AF_INET;

  retval = sendto(sock, m->original_buf, m->numread, 0, 
		(struct sockaddr *)&sa, sizeof(sa));
  
  if( retval < 0 ){
    debug_perror("dns_write_packet: sendto");
  }

  return retval;
}
示例#13
0
文件: file.c 项目: Elohim/FGmud
int copy_file (const char * from, const char * to)
{
    char buf[128];
    int from_fd, to_fd;
    int num_read, num_written;
    char *write_ptr;
    extern svalue_t apply_ret_value;

    from = check_valid_path(from, current_object, "move_file", 0);
    assign_svalue(&from_sv, &apply_ret_value);

    to = check_valid_path(to, current_object, "move_file", 1);
    assign_svalue(&to_sv, &apply_ret_value);

    if (from == 0)
        return -1;
    if (to == 0)
        return -2;

    if (lstat(from, &from_stats) != 0) {
        error("/%s: lstat failed\n", from);
        return 1;
    }
    if (lstat(to, &to_stats) == 0) {
#ifdef WIN32
        if (!strcmp(from, to))
#else
        if (from_stats.st_dev == to_stats.st_dev
            && from_stats.st_ino == to_stats.st_ino)
#endif
        {
            error("`/%s' and `/%s' are the same file", from, to);
            return 1;
        }
    } else if (errno != ENOENT) {
        error("/%s: unknown error\n", to);
        return 1;
    }
    
    from_fd = open(from, OPEN_READ);
    if (from_fd < 0)
        return -1;

    if (file_size(to) == -2) {
        /* Target is a directory; build full target filename. */
        const char *cp;
        char newto[MAX_FNAME_SIZE + MAX_PATH_LEN + 2];

        cp = strrchr(from, '/');
        if (cp)
            cp++;
        else
            cp = from;

        sprintf(newto, "%s/%s", to, cp);
        close(from_fd);
        return copy_file(from, newto);
    }
    to_fd = open(to, OPEN_WRITE | O_CREAT | O_TRUNC, 0666);
    if (to_fd < 0) {
        close(from_fd);
        return -2;
    }
    while ((num_read = read(from_fd, buf, 128)) != 0) {
        if (num_read < 0) {
            debug_perror("copy_file: read", from);
            close(from_fd);
            close(to_fd);
            return -3;
        }
        write_ptr = buf;
        while (write_ptr != (buf + num_read)) {
            num_written = write(to_fd, write_ptr, num_read);
            if (num_written < 0) {
                debug_perror("copy_file: write", to);
                close(from_fd);
                close(to_fd);
                return -3;
            }
            write_ptr += num_written;
        }
    }
    close(from_fd);
    close(to_fd);
    return 1;
}
示例#14
0
void cache_purge(int older_than)
{
  FILE /**in_fp, */*out_fp;
//  char line[BUF_SIZE];
//  char old_cache[1024];
//  char *name, *ip, *time_made;

  debug("enter cache_purge()\n");

#if 0 //BRCM
  in_fp = fopen( config.cache_file , "r");
  if(!in_fp){
	 debug_perror("Could not open old cache file");
	 /*return;*/
  }

  if( in_fp ) {
    sprintf( old_cache, "%s.old", config.cache_file );
    if( rename( config.cache_file, old_cache ) < 0 ){
	 debug_perror("Could not move cache file");
	 fclose(in_fp);
	 return;
    }
  }
#endif

  out_fp = fopen( config.cache_file , "w");
  if(!out_fp){
#if 0 //BRCM
	 if( in_fp ) {
	 	fclose(in_fp);
	 }
#endif
	 debug_perror("Could not open new cache file");
	 return;
  }

  cache_add_hosts_entries(out_fp);

  /* No need to add dhcp entries any more, It seems that all dhcp
   * entries now will be added to the host entries */
#if !defined(AEI_VDSL_DNS_CACHE)
  cache_add_dhcp_entries(out_fp);
#endif

#if 0 //BRCM
  if( in_fp ) {
    while( fgets(line, BUF_SIZE, in_fp) ){
	 name = strtok( line, " ");
	 ip = strtok( NULL, " ");
	 time_made = strtok( NULL, " ");
	 if(!time_made)continue;
	 if( time(NULL) - atoi( time_made ) < older_than )
		fprintf( out_fp, "%s %s %s", name, ip, time_made );
    }

    fclose(in_fp);
    unlink(old_cache);
  }
#endif

  fclose(out_fp);
}
示例#15
0
/* open connection to cand */
cann_conn_t *cann_connect(char *server, char *port)
{
        struct addrinfo hints;
        struct addrinfo *result, *rp;
        int s;
        cann_conn_t *client;
        char buf[INET6_ADDRSTRLEN];

        // initialize client struct
        client = malloc(sizeof(cann_conn_t));
        if (client == NULL) {
                debug(0, "Could not allocate client buffer!\n");
                free(client);
                exit(EXIT_FAILURE);
        }
        client->state = CANN_LEN;
        client->missing_bytes = 0;
        client->error = 0;

#ifdef USE_WINSOCK
        WSADATA wsaData;
        int err;

        err = WSAStartup(0x0202, &wsaData);
        if (err != 0) {
                /* Tell the user that we could not find a usable */
                /* Winsock DLL.                                  */
                printf("WSAStartup failed with error: %d\n", err);
                exit(EXIT_FAILURE);
        }
#endif
        /* Obtain address(es) matching host/port */

        memset(&hints, 0, sizeof(struct addrinfo));
        hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
        hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
        hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; //
        hints.ai_protocol = 0;          /* Any protocol */

        s = getaddrinfo(server, port, &hints, &result);
        if (s != 0) {
                debug_perror(0, "getaddrinfo: %s\n", gai_strerror(s));
                free(client);
                exit(EXIT_FAILURE);
        }

        /* getaddrinfo() returns a list of address structures.
        Try each address until we successfully connect(2).
        If socket(2) (or connect(2)) fails, we (close the socket
        and) try the next address. */

        for (rp = result; rp != NULL; rp = rp->ai_next) {
                client->fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
                if (client->fd == -1)
                        continue;

                if (connect(client->fd, rp->ai_addr, rp->ai_addrlen) != -1)
                        break;                  /* Success */

                close(client->fd);
        }
        if (rp == NULL) {               /* No address succeeded */
                debug_perror(0, "Could not connect\n");
                free(client);
                exit(EXIT_FAILURE);
        }
        debug(4, "Connected to %s.", get_ip_str((struct sockaddr *)rp->ai_addr,
                                                buf,
                                                sizeof(buf)));


        freeaddrinfo(result);           /* No longer needed */
        listen_socket = client->fd;
#ifdef USE_WINSOCK
        u_long option = 1;
        ioctlsocket(client->fd, FIONBIO, &option);
#else
        // set some options on socket
        fcntl(client->fd, F_SETFL, O_NONBLOCK);
#endif

        int flag = 1;
        setsockopt(client->fd,
                   IPPROTO_TCP,     /* set option at TCP level */
                   TCP_NODELAY,     /* name of option */
                   (char *) &flag,  /* the cast is historical cruft */
                   sizeof(int));    /* length of option value */

        debug(9, "connected to server, fd=%d\r\n", client->fd);

        return client;
}
示例#16
0
/* open listening socket and initialize */
void cann_listen(char *port)
{
        struct addrinfo hints;
        struct addrinfo *result, *rp;
        int sfd, s;
        char buf[200];
        int ret, one = 1;

        signal(SIGPIPE, SIG_IGN);

        memset(&hints, 0, sizeof(struct addrinfo));
        hints.ai_family = AF_UNSPEC;  // Allow IPv4 or IPv6 - ipv4 is mapped into an v6 addr -> ai_v4mapped
        hints.ai_socktype = SOCK_STREAM;                // Datagram socket
        hints.ai_flags = AI_PASSIVE | AI_V4MAPPED | AI_NUMERICSERV | AI_ALL;     // For wildcard IP address

        s = getaddrinfo(NULL, port, &hints, &result);
        if (s != 0) {
                fprintf(stderr,
                        "No listening addresses available(getaddrinfo: %s)\n",
                        gai_strerror(s));
                exit(EXIT_FAILURE);
        }

        //dump address info
        for (rp = result; rp != NULL; rp = rp->ai_next)
                debug(5, "Found Address %s\t\t(family: %s, socktype %i: protocol %i)",
                      get_ip_str((struct sockaddr *)rp->ai_addr,
                                 buf, sizeof(buf)),
                      (rp->ai_family == AF_INET) ? "IPv4" :
                      ((rp->ai_family == AF_INET6) ? "IPv6" :
                       ((snprintf(buf, sizeof(buf), "%i", rp->ai_family) != 0)
                        ? buf : "")),
                      rp->ai_socktype,
                      rp->ai_protocol);

        /* getaddrinfo() returns a list of address structures.
           Try each address until we successfully bind(2).
           If socket(2) (or bind(2)) fails, we (close the socket
           and) try the next address. */

        for (rp = result; rp != NULL; rp = rp->ai_next) {
                sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
                if (sfd == -1)
                        continue;

                debug(5, "Trying to bind to %s (%s)",
                      get_ip_str((struct sockaddr *)rp->ai_addr,
                                 buf, sizeof(buf)),
                      (rp->ai_family == AF_INET) ? "IPv4" :
                      ((rp->ai_family == AF_INET6) ? "IPv6" :
                       ((snprintf(buf, sizeof(buf), "%i", rp->ai_family) != 0)
                        ? buf : "")),
                      rp->ai_socktype,
                      rp->ai_protocol);

                //set reuseaddr to avoid address in use (b/c if close_wait) when restarting
                ret = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));

                if (ret != 0) debug_perror(0, "Could not set socket options: ");

                if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
                        break;                  /* Success */

                debug_perror(0, "Could not bind to %s.",
                             get_ip_str((struct sockaddr *)rp->ai_addr,
                                        buf,
                                        sizeof(buf)));
                close(sfd);
        }

        if (rp == NULL) {               /* No address succeeded */
                debug_perror(0, "All addresses in use");
                exit(EXIT_FAILURE);
        } else debug(5, "Bind succeeded!");

        freeaddrinfo(result);           /* No longer needed */
        listen_socket = sfd;

        int flags = 0;
        flags = fcntl(listen_socket, F_GETFL, 0);
        fcntl(listen_socket, F_SETFL, flags | O_NDELAY);

        /* specify queue */
        ret = listen(listen_socket, SOMAXCONN);
        debug_assert(ret >= 0, "Could listen() listening socket");
}
示例#17
0
/* nonblocking read on netwok -- returns msg if complete msg arrived */
rs232can_msg *cann_get_nb(cann_conn_t *client)
{
        int ret;
        unsigned char val;

        // sanity
        if (client->error) {
                debug( 0,
                       "cann_get_nb() with error %d on %d",
                       client->error,
                       client->fd);
                return NULL;
        }

        // XXX das alles geht auch einfacher XXX
        if (client->state == CANN_LEN) {
                ret = read(client->fd, &val, 1);

                if (ret == 0) goto eof;
                if (ret < 0) goto error;

                // check msg length
                if (val > sizeof(client->msg.data)) {
                        debug( 2, "Protocol error on fd %d: message too big (size=%d)",
                               client->fd, val );
                        client->error = 1;
                        return NULL;
                }

                debug(10, "Next packet on %d: length=%d", client->fd, val);
                client->msg.len        = val;
                client->missing_bytes  = val;
                client->rcv_ptr        = client->msg.data;
                client->state          = CANN_CMD;
        }

        if (client->state == CANN_CMD) {
                ret = read(client->fd, &(client->msg.cmd), 1);

                if (ret == 0) goto eof;
                if (ret < 0) goto error;

                debug(10, "Next packet on %d: cmd=%d", client->fd, client->msg.cmd);
                client->state = CANN_PAYLOAD;
        }

        if (client->missing_bytes > 0) {
                // read data
                ret = read(client->fd, client->rcv_ptr, client->missing_bytes);

                if (ret == 0) goto eof;
                if (ret < 0) goto error;

                client->missing_bytes -= ret;
                client->rcv_ptr       += ret;

                debug(10, "fd %d: recived %d bytes, %d missing",
                      client->fd, ret, client->missing_bytes);
        }

        // message complete?
        if (client->missing_bytes == 0) {
                rs232can_msg *rmsg = malloc(sizeof(rs232can_msg));

                if (rmsg == NULL) {
                        debug(0, "Could not allocate rmsg buffer, exiting!\n");
                        exit(EXIT_FAILURE);
                }

                memcpy(rmsg, &(client->msg), sizeof(rs232can_msg));
                client->state = CANN_LEN;
                return rmsg;
        }

        return NULL;

error:
        if ((errno == EAGAIN) || (errno == 0))
                return NULL;

eof:
        debug_perror(5, "Error readig fd %d (ret==%d)", client->fd, ret);
        client->error = 1;
        return NULL;
}