Example #1
0
/* return the amount of a read */
static int max_input_read(struct telnet_session_s *t)
{
	int max_in;
	int max_out;

	daemon_assert(invariant(t));

	/* figure out how much space is available in the input buffer */
	if (t->in_buflen < BUF_LEN) {
		max_in = BUF_LEN - t->in_buflen;
	} else {
		max_in = 0;
	}

	/* worry about space in the output buffer (for DONT/WONT replies) */
	if (t->out_buflen < BUF_LEN) {
		max_out = BUF_LEN - t->out_buflen;
	} else {
		max_out = 0;
	}

	daemon_assert(invariant(t));

	/* return the minimum of the two values */
	return (max_in < max_out) ? max_in : max_out;
}
Example #2
0
File: watchdog.c Project: gpg/oftpd
int watchdog_init(watchdog_t *w, int inactivity_timeout, error_t *err)
{
    pthread_t thread_id;
    int error_code;

    daemon_assert(w != NULL);
    daemon_assert(inactivity_timeout > 0);
    daemon_assert(err != NULL);

    pthread_mutex_init(&w->mutex, NULL);
    w->inactivity_timeout = inactivity_timeout;
    w->oldest = NULL;
    w->newest = NULL;

    error_code = pthread_create(&thread_id, NULL, watcher, w);
    if (error_code != 0) {
	error_init(err, error_code, "error %d from pthread_create()", 
	  error_code);
        return 0;
    }
    pthread_detach(thread_id);

    daemon_assert(invariant(w));

    return 1;
}
Example #3
0
int watchdog_init(struct watchdog_s *w, int inactivity_timeout)
{
	pthread_t thread_id;
	int error_code;

	daemon_assert(w != NULL);
	daemon_assert(inactivity_timeout > 0);

	_MUTEX_INIT(w->mutex);
	w->inactivity_timeout = inactivity_timeout;
	w->oldest = NULL;
	w->newest = NULL;

	error_code = pthread_create(&thread_id, DEFAULT_THREAD_ATTR, watcher, w);
	if (error_code != 0) {
		errno = error_code;
		ERROR_CONNECT("Watchdog thread create problem\n");
		return 0;
	}
	pthread_detach(thread_id);

	daemon_assert(invariant(w));

	return 1;
}
Example #4
0
static const char *parse_host_port(struct sockaddr_in *addr, const char *s)
{
    int i;
    int octets[6];
    char addr_str[16];
    int port;
    struct in_addr in_addr;

    daemon_assert(addr != NULL);
    daemon_assert(s != NULL);

    /* scan in 5 pairs of "#," */
    for (i=0; i<5; i++) {
        s = parse_number(&octets[i], s, 255);
	if (s == NULL) {
	    return NULL;
	}
	if (*s != ',') {
	    return NULL;
	}
	s++;
    }

    /* scan in ending "#" */
    s = parse_number(&octets[5], s, 255);
    if (s == NULL) {
        return NULL;
    }

    daemon_assert(octets[0] >= 0);
    daemon_assert(octets[0] <= 255);
    daemon_assert(octets[1] >= 0);
    daemon_assert(octets[1] <= 255);
    daemon_assert(octets[2] >= 0);
    daemon_assert(octets[2] <= 255);
    daemon_assert(octets[3] >= 0);
    daemon_assert(octets[3] <= 255);

    /* convert our number to a IP/port */
    sprintf(addr_str, "%d.%d.%d.%d", 
            octets[0], octets[1], octets[2], octets[3]);
    port = (octets[4] << 8) | octets[5];
#ifdef HAVE_INET_ATON
    if (inet_aton(addr_str, &in_addr) == 0) {
        return NULL;
    }
#else
    in_addr.s_addr = inet_addr(addr_str);
    if (in_addr.s_addr == -1) {
        return NULL;
    }
#endif
    addr->sin_family = AF_INET;
    addr->sin_addr = in_addr;
    addr->sin_port = htons(port);

    /* return success */
    return s;
}
Example #5
0
static const char *parse_offset(off_t *ofs, const char *s)
{
    off_t tmp_ofs;
    int cur_digit;
    off_t max_ofs;
#if SIZEOF_UNSIGNED_LONG >= SIZEOF_OFF_T
    unsigned long cutoff, cutlim;
#elif SIZEOF_UNSIGNED_LONG_LONG && SIZEOF_UNSIGNED_LONG_LONG >= SIZEOF_OFF_T
    unsigned long long cutoff, cutlim;
#else
# error cannot figure out a type larger or equal to off_t
#endif

    daemon_assert(ofs != NULL);
    daemon_assert(s != NULL);

    /* calculate maximum allowable offset based on size of off_t */
#if SIZEOF_OFF_T == 8
    max_ofs = (off_t)9223372036854775807LL;
#elif SIZEOF_OFF_T == 4
    max_ofs = (off_t)2147483647LL;
#elif SIZEOF_OFF_T == 2
    max_ofs = (off_t)32767LL;
#else
# error sizeof(off_t) unknown
#endif

    cutoff = max_ofs / 10;
    cutlim = max_ofs % 10;

    /* handle first character */
    if (!isdigit(*s)) {
        return NULL;
    }
    tmp_ofs = (*s - '0');
    s++;

    /* handle subsequent characters */
    while (isdigit(*s)) {
        cur_digit = (*s - '0');

        if (tmp_ofs > cutoff || (tmp_ofs == cutoff && cur_digit > cutlim))
          return NULL; /*overflow*/

        tmp_ofs *= 10;
	tmp_ofs += cur_digit;
        s++;
    }

    /* return */
    *ofs = tmp_ofs;
    return s;
}
Example #6
0
/* read a line */
int telnet_session_readln(struct telnet_session_s *t, char *buf, int buflen)
{
	int amt_read;

	daemon_assert(invariant(t));
	amt_read = 0;
	for (;;) {
		if ((t->in_errno != 0) || (t->in_eof != 0)) {
			daemon_assert(invariant(t));
			return 0;
		}
		while (t->in_buflen > 0) {
			if (amt_read == buflen - 1) {
				buf[amt_read] = '\0';
				daemon_assert(invariant(t));
				return 1;
			}
			daemon_assert(amt_read >= 0);
			daemon_assert(amt_read < buflen);
			buf[amt_read] = use_incoming_char(t);
			if (buf[amt_read] == '\012') {
				daemon_assert(amt_read + 1 >= 0);
				daemon_assert(amt_read + 1 < buflen);
				buf[amt_read + 1] = '\0';
				daemon_assert(invariant(t));
				return 1;
			}
			amt_read++;
		}
		process_data(t, 1);
	}
}
Example #7
0
/* print a line output */
int telnet_session_println(struct telnet_session_s *t, const char *s)
{
	daemon_assert(invariant(t));
	if (!telnet_session_print(t, s)) {
		daemon_assert(invariant(t));
		return 0;
	}
	if (!telnet_session_print(t, "\015\012")) {
		daemon_assert(invariant(t));
		return 0;
	}
	daemon_assert(invariant(t));
	return 1;
}
Example #8
0
void watchdog_add_watched(struct watchdog_s *w, struct watched_s *watched)
{
	daemon_assert(invariant(w));

	_MUTEX_LOCK(w->mutex);

	watched->watched_thread = pthread_self();
	watched->watchdog = w;
	insert(w, watched);

	_MUTEX_UNLOCK(w->mutex);

	daemon_assert(invariant(w));
}
Example #9
0
void watchdog_remove_watched(struct watched_s *watched)
{
	struct watchdog_s *w;

	daemon_assert(invariant(watched->watchdog));

	w = watched->watchdog;
	_MUTEX_LOCK(w->mutex);

	delete(w, watched);

	_MUTEX_UNLOCK(w->mutex);
	daemon_assert(invariant(w));
}
Example #10
0
/* copy a string terminated with a newline */
static const char *copy_string(char *dst, const char *src)
{
    int i;

    daemon_assert(dst != NULL);
    daemon_assert(src != NULL);

    for (i=0; (i<=MAX_STRING_LEN) && (src[i]!='\0') && (src[i]!='\n'); i++) {
        dst[i] = src[i];
    }
    dst[i] = '\0';

    return src+i;
}
Example #11
0
File: watchdog.c Project: gpg/oftpd
void watchdog_remove_watched(watched_t *watched)
{
    watchdog_t *w;

    daemon_assert(invariant(watched->watchdog));

    w = watched->watchdog;
    pthread_mutex_lock(&w->mutex);

    delete(w, watched);

    pthread_mutex_unlock(&w->mutex);
    daemon_assert(invariant(w));
}
Example #12
0
File: watchdog.c Project: gpg/oftpd
void watchdog_add_watched(watchdog_t *w, watched_t *watched)
{
    daemon_assert(invariant(w));

    pthread_mutex_lock(&w->mutex);

    watched->watched_thread = pthread_self();
    watched->watchdog = w;
    insert(w, watched);

    pthread_mutex_unlock(&w->mutex);

    daemon_assert(invariant(w));
}
Example #13
0
/* remove a single character */
static int use_incoming_char(struct telnet_session_s *t)
{
	int c;

	daemon_assert(t->in_take >= 0);
	daemon_assert(t->in_take < BUF_LEN);
	c = t->in_buf[t->in_take];
	t->in_take++;
	if (t->in_take == BUF_LEN) {
		t->in_take = 0;
	}
	t->in_buflen--;

	return c;
}
Example #14
0
File: error.c Project: gpg/oftpd
void error_init(error_t *err, int error_code, const char *desc_fmt, ...)
{
    va_list args;

    daemon_assert(err != NULL);
    daemon_assert(error_code >= 0);
    daemon_assert(desc_fmt != NULL);

    err->error_code = error_code;
    va_start(args, desc_fmt);
    vsnprintf(err->desc, sizeof(err->desc), desc_fmt, args);
    va_end(args);

    daemon_assert(invariant(err));
}
Example #15
0
void telnet_session_destroy(struct telnet_session_s *t)
{
	daemon_assert(invariant(t));

	Test_and_Close( & t->in_fd);
	Test_and_Close( & t->out_fd);
}
Example #16
0
static void write_outgoing_data(struct telnet_session_s *t)
{
	ssize_t write_ret;

	if (t->out_take < t->out_add) {
		/* handle a buffer that looks like this:       */
		/*     |-- empty --|-- data --|-- empty --|    */
		daemon_assert(t->out_take >= 0);
		daemon_assert(t->out_take < BUF_LEN);
		daemon_assert(t->out_buflen > 0);
		daemon_assert(t->out_buflen + t->out_take <= BUF_LEN);
		write_ret = write(t->out_fd, t->out_buf + t->out_take, t->out_buflen);
	} else {
		/* handle a buffer that looks like this:       */
		/*     |-- data --|-- empty --|-- data --|     */
		daemon_assert(t->out_take >= 0);
		daemon_assert(t->out_take < BUF_LEN);
		daemon_assert((BUF_LEN - t->out_take) > 0);
		write_ret = write(t->out_fd, t->out_buf + t->out_take, BUF_LEN - t->out_take);
	}

	/* handle three possible write results */
	if (write_ret == -1) {
		t->out_errno = errno;
	} else if (write_ret == 0) {
		t->out_eof = 1;
	} else {
		t->out_buflen -= write_ret;
		t->out_take += write_ret;
		if (t->out_take >= BUF_LEN) {
			t->out_take -= BUF_LEN;
		}
	}
}
Example #17
0
/* add a single character, hopefully will never happen :) */
static void add_outgoing_char(struct telnet_session_s *t, int c)
{
	daemon_assert(t->out_add >= 0);
	daemon_assert(t->out_add < BUF_LEN);
	t->out_buf[t->out_add] = c;
	t->out_add++;
	if (t->out_add == BUF_LEN) {
		t->out_add = 0;
	}
	if (t->out_buflen == BUF_LEN) {
		t->out_take++;
		if (t->out_take == BUF_LEN) {
			t->out_take = 0;
		}
	} else {
		t->out_buflen++;
	}
}
Example #18
0
/* returns NULL if not at least one digit */
static const char *parse_number(int *num, const char *s, int max_num)
{
    int tmp;
    int cur_digit;
    
    daemon_assert(s != NULL);
    daemon_assert(num != NULL);
    
    /* handle first character */
    if (!isdigit(*s)) {
        return NULL;
    }
    tmp = (*s - '0');
    s++;

    /* handle subsequent characters */
    while (isdigit(*s)) {
        cur_digit = (*s - '0');

        /* check for overflow */
        if ((max_num - cur_digit) < (tmp*10)) {
	    return NULL;
	}

        tmp *= 10;
	tmp += cur_digit;
        s++;
    }

    daemon_assert(tmp >= 0);
    daemon_assert(tmp <= max_num);

    /* return the result */
    *num = tmp;
    return s;
}
Example #19
0
/* initialize a telnet session */
void telnet_session_init(struct telnet_session_s *t, FILE_DESCRIPTOR_OR_ERROR in, FILE_DESCRIPTOR_OR_ERROR out)
{
	daemon_assert(t != NULL);
	daemon_assert(in >= 0);
	daemon_assert(out >= 0);

	t->in_fd = in;
	t->in_errno = 0;
	t->in_eof = 0;
	t->in_take = t->in_add = 0;
	t->in_buflen = 0;

	t->in_status = NORMAL;

	t->out_fd = out;
	t->out_errno = 0;
	t->out_eof = 0;
	t->out_take = t->out_add = 0;
	t->out_buflen = 0;

	process_data(t, 0);

	daemon_assert(invariant(t));
}
Example #20
0
int main( int argc, char **argv ) {

    cx_t cx;
    memset(&cx, 0, sizeof(cx));
/*    static cx_t cx;
    memset(&cx, 0, sizeof(cx));
    cx.d_opts.ident = "fastrakd";
    cx.d_opts.sched_rt = SOMATIC_D_SCHED_UI; // logger not realtime

    cx.opt_chan_name = "fastrak";
    cx.opt_freq = -1;
    cx.opt_peekabot = 0;
    cx.opt_peekabot_host = "localhost";
    cx.opt_device = "/dev/ttyS0";
    cx.opt_kalman = 0;
    cx.opt_diag_E = 1;
    cx.opt_diag_Q = 250;
    cx.opt_diag_R = 1;
*/

    // parse options
//    argp_parse (&argp, argc, argv, 0, NULL, &cx);
//    somatic_verbprintf_prefix="fastrak";
//    somatic_verbprintf( 1, "Frequency of %d Hz\n", cx.opt_freq );


//    init(&cx);
    daemonize("fastrakd");
    int r = fastrak_init(&(cx.fk), "/dev/ttyS0" );

    r = ach_open( &chan, "fastrak", NULL );
    daemon_assert( ACH_OK == r, __LINE__ );

    //printf("About to start\n");

    run(&cx);
//    destroy(&cx);
    daemon_close();

    return 0;
}
Example #21
0
static void read_incoming_data(struct telnet_session_s *t)
{
	ssize_t read_ret;
	char buf[BUF_LEN];
	ssize_t i;

	/* read as much data as we have buffer space for */
	daemon_assert(max_input_read(t) <= BUF_LEN);
	read_ret = read(t->in_fd, buf, max_input_read(t));

	/* handle three possible read results */
	if (read_ret == -1) {
		t->in_errno = errno;
	} else if (read_ret == 0) {
		t->in_eof = 1;
	} else {
		for (i = 0; i < read_ret; i++) {
			process_incoming_char(t, (unsigned char) buf[i]);
		}
	}
}
Example #22
0
/* print output */
int telnet_session_print(struct telnet_session_s *t, const char *s)
{
	int len;
	int amt_printed;

	daemon_assert(invariant(t));

	len = strlen(s);
	if (len == 0) {
		daemon_assert(invariant(t));
		return 1;
	}

	amt_printed = 0;
	do {
		if ((t->out_errno != 0) || (t->out_eof != 0)) {
			daemon_assert(invariant(t));
			return 0;
		}
		while ((amt_printed < len) && (t->out_buflen < BUF_LEN)) {
			daemon_assert(s[amt_printed] != '\0');
			add_outgoing_char(t, s[amt_printed]);
			amt_printed++;
		}
		process_data(t, 1);
	} while (amt_printed < len);

	while (t->out_buflen > 0) {
		if ((t->out_errno != 0) || (t->out_eof != 0)) {
			daemon_assert(invariant(t));
			return 0;
		}
		process_data(t, 1);
	}

	daemon_assert(invariant(t));
	return 1;
}
Example #23
0
File: error.c Project: gpg/oftpd
const char *error_get_desc(const error_t *err)
{
    daemon_assert(invariant(err));
    return err->desc;
}
Example #24
0
File: error.c Project: gpg/oftpd
int error_get_error_code(const error_t *err)
{
    daemon_assert(invariant(err));
    return err->error_code;
}
Example #25
0
/*       this is okay, as long as subsequent uses VERIFY THE FAMILY first */
static const char *parse_host_port_long(sockaddr_storage_t *sa, const char *s)
{   
    int i;
    int family;
    int tmp;
    int addr_len;
    unsigned char addr[255];
    int port_len;
    unsigned char port[255];

    /* we are family */
    s = parse_number(&family, s, 255);
    if (s == NULL) {
        return NULL;
    }
    if (*s != ',') {
        return NULL;
    }
    s++;

    /* parse host length */
    s = parse_number(&addr_len, s, 255);
    if (s == NULL) {
        return NULL;
    }
    if (*s != ',') {
        return NULL;
    }
    s++;

    /* parse address */
    for (i=0; i<addr_len; i++) {
	daemon_assert(i < sizeof(addr)/sizeof(addr[0]));
        s = parse_number(&tmp, s, 255);
	addr[i] = tmp;
	if (s == NULL) {
	    return NULL;
	}
	if (*s != ',') {
	    return NULL;
	}
        s++;
    }

    /* parse port length */
    s = parse_number(&port_len, s, 255);
    if (s == NULL) {
        return NULL;
    }

    /* parse port */
    for (i=0; i<port_len; i++) {
        if (*s != ',') {
	    return NULL;
	}
	s++;
	daemon_assert(i < sizeof(port)/sizeof(port[0]));
	s = parse_number(&tmp, s, 255);
        port[i] = tmp;
    }

    /* okay, everything parses, load the address if possible */
    if (family == 4) {
        SAFAM(sa) = AF_INET;
	if (addr_len != sizeof(struct in_addr)) {
	    return NULL;
	}
	if (port_len != 2) {
	    return NULL;
	}
	memcpy(&SINADDR(sa), addr, addr_len);
	SINPORT(sa) = htons((port[0] << 8) + port[1]);
    }
#ifdef INET6
    else if (family == 6) {
        SAFAM(sa) = AF_INET6;
	if (addr_len != sizeof(struct in6_addr)) {
	    return NULL;
	}
	if (port_len != 2) {
	    return NULL;
	}
	memcpy(&SIN6ADDR(sa), addr, addr_len);
	SINPORT(sa) = htons((port[0] << 8) + port[1]);
    }
#endif
    else {
        SAFAM(sa) = -1;
    }

    /* return new pointer */
    return s;
}
Example #26
0
int ftp_command_parse(const char *input, ftp_command_t *cmd)
{
    int i;
    int len;
    int match;
    ftp_command_t tmp;
    int c;
    const char *optional_number;

    daemon_assert(input != NULL);
    daemon_assert(cmd != NULL);

    /* see if our input starts with a valid command */
    match = -1;
    for (i=0; (i<NUM_COMMAND) && (match == -1); i++) {
        len = strlen(command_def[i].name);
        if (strncasecmp(input, command_def[i].name, len) == 0) {
	    match = i;
	}
    }

    /* if we didn't find a match, return error */
    if (match == -1) {
        return 0;
    }
    daemon_assert(match >= 0);
    daemon_assert(match < NUM_COMMAND);

    /* copy our command */
    strcpy(tmp.command, command_def[match].name);

    /* advance input past the command */
    input += strlen(command_def[match].name);

    /* now act based on the command */
    switch (command_def[match].arg_type) {

        case ARG_NONE:
	    tmp.num_arg = 0;
	    break;

        case ARG_STRING:
	    if (*input != ' ') {
	        return 0;
	    }
            ++input;
            input = copy_string(tmp.arg[0].string, input);
	    tmp.num_arg = 1;
	    break;

        case ARG_OPTIONAL_STRING:
	    if (*input == ' ') {
	        ++input;
	        input = copy_string(tmp.arg[0].string, input);
	        tmp.num_arg = 1;
	    } else {
	        tmp.num_arg = 0;
	    }
	    break;

        case ARG_HOST_PORT:
	    if (*input != ' ') {
	        return 0;
	    }
	    input++;

            /* parse the host & port information (if any) */
	    input = parse_host_port(&tmp.arg[0].host_port, input);
	    if (input == NULL) {
	        return 0;
	    }
	    tmp.num_arg = 1;
	    break;

       case ARG_HOST_PORT_LONG:
            if (*input != ' ') {
                return 0;
            }
            input++;
 
            /* parse the host & port information (if any) */
            input = parse_host_port_long(&tmp.arg[0].host_port, input);
            if (input == NULL) {
                return 0;
            }
            tmp.num_arg = 1;
            break;    

        case ARG_HOST_PORT_EXT:
            if (*input != ' ') {
                return 0;
            }
            input++;
 
            /* parse the host & port information (if any) */
            input = parse_host_port_ext(&tmp.arg[0].host_port, input);
            if (input == NULL) {
                return 0;
            }
            tmp.num_arg = 1;
            break;
 
        /* the optional number may also be "ALL" */
        case ARG_OPTIONAL_NUMBER:
            if (*input == ' ') {
                ++input;
                optional_number = parse_number(&tmp.arg[0].num, input, 255);
                if (optional_number != NULL) {
                    input = optional_number;
                } else {
                    if ((tolower(input[0]) == 'a') &&
                        (tolower(input[1]) == 'l') &&
                        (tolower(input[2]) == 'l')) 
                    {
			tmp.arg[0].num = EPSV_ALL;
                        input += 3;
                    } else {
                        return 0;
                    }
                }
                tmp.num_arg = 1;
            } else {
                tmp.num_arg = 0;
            }
            break;     

        case ARG_TYPE:
	    if (*input != ' ') {
	        return 0;
	    }
	    input++;

            c = toupper(*input);
            if ((c == 'A') || (c == 'E')) {
	        tmp.arg[0].string[0] = c;
		tmp.arg[0].string[1] = '\0';
		input++;

		if (*input == ' ') {
		    input++;
		    c = toupper(*input);
		    if ((c != 'N') && (c != 'T') && (c != 'C')) {
		        return 0;
		    }
		    tmp.arg[1].string[0] = c;
		    tmp.arg[1].string[1] = '\0';
		    input++;
		    tmp.num_arg = 2;
		} else {
		    tmp.num_arg = 1;
		}
	    } else if (c == 'I') {
	        tmp.arg[0].string[0] = 'I';
	        tmp.arg[0].string[1] = '\0';
		input++;
	        tmp.num_arg = 1;
	    } else if (c == 'L') {
	        tmp.arg[0].string[0] = 'L';
	        tmp.arg[0].string[1] = '\0';
		input++;
		input = parse_number(&tmp.arg[1].num, input, 255);
		if (input == NULL) {
		    return 0;
		}
	        tmp.num_arg = 2;
	    } else {
	        return 0;
	    }

	    break;

        case ARG_STRUCTURE:
	    if (*input != ' ') {
	        return 0;
	    }
	    input++;

            c = toupper(*input);
	    if ((c != 'F') && (c != 'R') && (c != 'P')) {
	        return 0;
	    }
            input++;
	    tmp.arg[0].string[0] = c;
	    tmp.arg[0].string[1] = '\0';
	    tmp.num_arg = 1;
	    break;

        case ARG_MODE:
	    if (*input != ' ') {
	        return 0;
	    }
	    input++;

            c = toupper(*input);
	    if ((c != 'S') && (c != 'B') && (c != 'C')) {
	        return 0;
	    }
            input++;
	    tmp.arg[0].string[0] = c;
	    tmp.arg[0].string[1] = '\0';
	    tmp.num_arg = 1;
	    break;

        case ARG_OFFSET:
	    if (*input != ' ') {
	        return 0;
	    }
	    input++;
	    input = parse_offset(&tmp.arg[0].offset, input);
	    if (input == NULL) {
	        return 0;
	    }
	    tmp.num_arg = 1;
	    break;

        default:
	    daemon_assert(0);
    } 

    /* check for our ending newline */
    if (*input != '\n') {
        return 0;
    }

    /* return our result */
    *cmd = tmp;
    return 1;
}
Example #27
0
void Walker::commenceWalking(balance_state_t &parent_state, nudge_state_t &state, balance_gains_t &gains)
{
    int timeIndex=0, nextTimeIndex=0, prevTimeIndex=0;
    keepWalking = true;
    size_t fs;
 
    zmp_traj_t *prevTrajectory, *currentTrajectory, *nextTrajectory;
    prevTrajectory = new zmp_traj_t;
    currentTrajectory = new zmp_traj_t;
    nextTrajectory = new zmp_traj_t;

    memset( prevTrajectory, 0, sizeof(*prevTrajectory) );
    memset( currentTrajectory, 0, sizeof(*currentTrajectory) );
    memset( nextTrajectory, 0, sizeof(*nextTrajectory) );
    
    // TODO: Consider making these values persistent
    memset( &state, 0, sizeof(state) );


    memcpy( &bal_state, &parent_state, sizeof(bal_state) );

    bal_state.m_balance_mode = BAL_ZMP_WALKING; 
    bal_state.m_walk_mode = WALK_WAITING;
    bal_state.m_walk_error = NO_WALK_ERROR;
    sendState();

    currentTrajectory->reuse = true;
    fprintf(stdout, "Waiting for first trajectory\n"); fflush(stdout);
    ach_status_t r;
    do {
        struct timespec t;
        clock_gettime( ACH_DEFAULT_CLOCK, &t );
        t.tv_sec += 1;
        r = ach_get( &zmp_chan, currentTrajectory, sizeof(*currentTrajectory), &fs,
                    &t, ACH_O_WAIT | ACH_O_LAST );

        checkCommands();
        if( cmd.cmd_request != BAL_ZMP_WALKING )
            keepWalking = false;
    } while(!daemon_sig_quit && keepWalking && (r==ACH_TIMEOUT
                || !currentTrajectory->reuse) ); // TODO: Replace this with something more intelligent

    if(!keepWalking || !currentTrajectory->reuse) // TODO: Take out the reuse condition here
    {
        bal_state.m_walk_mode = WALK_INACTIVE;
        sendState();
        return;
    }

    if(!daemon_sig_quit)
        fprintf(stdout, "First trajectory acquired\n");
    
        
    daemon_assert( !daemon_sig_quit, __LINE__ );

    bal_state.m_walk_mode = WALK_INITIALIZING;
    sendState();

    // Get the balancing gains from the ach channel
    ach_get( &param_chan, &gains, sizeof(gains), &fs, NULL, ACH_O_LAST );

    hubo.update(true);

    // Set all the joints to the initial posiiton in the trajectory
    // using the control daemon to interpolate in joint space.
    for(int i=0; i<HUBO_JOINT_COUNT; i++)
    {
        // Don't worry about where these joint are
        if( LF1!=i && LF2!=i && LF3!=i && LF4!=i && LF5!=i
         && RF1!=i && RF2!=i && RF3!=i && RF4!=i && RF5!=i
         && NK1!=i && NK2!=i && NKY!=i && LWR!=i && RWR!=i && RWY!=i && RWP!=i) //FIXME
        {
            hubo.setJointAngle( i, currentTrajectory->traj[0].angles[i] + bal_state.jointOffset[i] );
            hubo.setJointNominalSpeed( i, 0.4 );
            hubo.setJointNominalAcceleration( i, 0.4 );
        }
        //std::cout << jointNames[i] << " = " << currentTrajectory->traj[0].angles[i] + bal_state.jointOffset[i] << "\n";
    }
    
    hubo.setJointNominalSpeed( RKN, 0.8 );
    hubo.setJointNominalAcceleration( RKN, 0.8 );
    hubo.setJointNominalSpeed( LKN, 0.8 );
    hubo.setJointNominalAcceleration( LKN, 0.8 );

//    hubo.setJointAngle( RSR, currentTrajectory->traj[0].angles[RSR] + hubo.getJointAngleMax(RSR) );
//    hubo.setJointAngle( LSR, currentTrajectory->traj[0].angles[LSR] + hubo.getJointAngleMin(LSR) );

    hubo.sendControls();

    // Wait specified time for joints to get into initial configuration,
    // otherwise time out and alert user.
    double m_maxInitTime = 10;
    double biggestErr = 0;
    int worstJoint=-1;

    double dt, time, stime; stime=hubo.getTime(); time=hubo.getTime();
    double norm = m_jointSpaceTolerance+1; // make sure this fails initially
    while( !daemon_sig_quit && (norm > m_jointSpaceTolerance && time-stime < m_maxInitTime)) {
//    while(false) { // FIXME TODO: SWITCH THIS BACK!!!
        hubo.update(true);
        norm = 0;
        for(int i=0; i<HUBO_JOINT_COUNT; i++)
        {
            double err=0;
            // Don't worry about waiting for these joints to get into position.
            if( LF1!=i && LF2!=i && LF3!=i && LF4!=i && LF5!=i
             && RF1!=i && RF2!=i && RF3!=i && RF4!=i && RF5!=i
             && NK1!=i && NK2!=i && NKY!=i && LWR!=i && RWR!=i && RWY!=i && RWP!=i) //FIXME
                err = (hubo.getJointAngleState( i )-currentTrajectory->traj[0].angles[i] + bal_state.jointOffset[i]);
//            if( LSR == i )
//                err -= hubo.getJointAngleMin(i);
//            if( RSR == i )
//                err -= hubo.getJointAngleMax(i);

            norm += err*err;
            if( fabs(err) > fabs(biggestErr) )
            {
                biggestErr = err;
                worstJoint = i;
            }
        }
        time = hubo.getTime();
    }
    // Print timeout error if joints don't get to initial positions in time
    if( time-stime >= m_maxInitTime )
    {
        fprintf(stderr, "Warning: could not reach the starting Trajectory within %f seconds\n"
                        " -- Biggest error was %f radians in joint %s\n",
                        m_maxInitTime, biggestErr, jointNames[worstJoint] );

        keepWalking = false;
        
        bal_state.m_walk_error = WALK_INIT_FAILED;
    }

    timeIndex = 1;
    bool haveNewTrajectory = false;
    if( keepWalking )
        fprintf(stdout, "Beginning main walking loop\n"); fflush(stdout);
    while(keepWalking && !daemon_sig_quit)
    {
        haveNewTrajectory = checkForNewTrajectory(*nextTrajectory, haveNewTrajectory);
        ach_get( &param_chan, &gains, sizeof(gains), &fs, NULL, ACH_O_LAST );
        hubo.update(true);

        bal_state.m_walk_mode = WALK_IN_PROGRESS;

        dt = hubo.getTime() - time;
        time = hubo.getTime();
        if( dt <= 0 )
        {
            fprintf(stderr, "Something unnatural has happened... %f\n", dt);
            continue;
        }

        if( timeIndex==0 )
        {
            bal_state.m_walk_error = NO_WALK_ERROR;
            nextTimeIndex = timeIndex+1;
            executeTimeStep( hubo, prevTrajectory->traj[prevTimeIndex],
                                   currentTrajectory->traj[timeIndex],
                                   currentTrajectory->traj[nextTimeIndex],
                                   state, gains, dt );
            
        }
        else if( timeIndex == currentTrajectory->periodEndTick && haveNewTrajectory )
        {
            if( validateNextTrajectory( currentTrajectory->traj[timeIndex],
                                        nextTrajectory->traj[0], dt ) )
            {
                nextTimeIndex = 0;
                executeTimeStep( hubo, currentTrajectory->traj[prevTimeIndex],
                                       currentTrajectory->traj[timeIndex],
                                       nextTrajectory->traj[nextTimeIndex],
                                       state, gains, dt );
                
                memcpy( prevTrajectory, currentTrajectory, sizeof(*prevTrajectory) );
                memcpy( currentTrajectory, nextTrajectory, sizeof(*nextTrajectory) );
                fprintf(stderr, "Notice: Swapping in new trajectory\n");
            }
            else
            {
                fprintf(stderr, "WARNING: Discontinuous trajectory passed in. Walking to a stop.\n");
                bal_state.m_walk_error = WALK_FAILED_SWAP;

                nextTimeIndex = timeIndex+1;
                executeTimeStep( hubo, currentTrajectory->traj[prevTimeIndex],
                                       currentTrajectory->traj[timeIndex],
                                       currentTrajectory->traj[nextTimeIndex],
                                       state, gains, dt );
            }
            haveNewTrajectory = false;
        }
        else if( timeIndex == currentTrajectory->periodEndTick && currentTrajectory->reuse )
        {
            checkCommands();
            if( cmd.cmd_request != BAL_ZMP_WALKING )
                currentTrajectory->reuse = false;

            if( currentTrajectory->reuse == true )
                nextTimeIndex = currentTrajectory->periodStartTick;
            else
                nextTimeIndex = timeIndex+1;

            executeTimeStep( hubo, currentTrajectory->traj[prevTimeIndex],
                                   currentTrajectory->traj[timeIndex],
                                   currentTrajectory->traj[nextTimeIndex],
                                   state, gains, dt );
        }
        else if( timeIndex < currentTrajectory->count-1 )
        {
            nextTimeIndex = timeIndex+1;
            executeTimeStep( hubo, currentTrajectory->traj[prevTimeIndex],
                                   currentTrajectory->traj[timeIndex],
                                   currentTrajectory->traj[nextTimeIndex],
                                   state, gains, dt );
        }
        else if( timeIndex == currentTrajectory->count-1 && haveNewTrajectory )
        {
            checkCommands();
            if( cmd.cmd_request != BAL_ZMP_WALKING )
                keepWalking = false;

            if( keepWalking )
            {
                if( validateNextTrajectory( currentTrajectory->traj[timeIndex],
                                            nextTrajectory->traj[0], dt ) )
                {
                    bal_state.m_walk_error = NO_WALK_ERROR;
                    nextTimeIndex = 0;
                    executeTimeStep( hubo, currentTrajectory->traj[prevTimeIndex],
                                           currentTrajectory->traj[timeIndex],
                                           nextTrajectory->traj[nextTimeIndex],
                                           state, gains, dt );
                    
                    memcpy( prevTrajectory, currentTrajectory, sizeof(*prevTrajectory) );
                    memcpy( currentTrajectory, nextTrajectory, sizeof(*nextTrajectory) );
                }
                else
                {
                    bal_state.m_walk_mode = WALK_WAITING;
                    bal_state.m_walk_error = WALK_FAILED_SWAP;
                    fprintf(stderr, "WARNING: Discontinuous trajectory passed in. Discarding it.\n");
                }
                haveNewTrajectory = false;
            }
        }
        else
        {
            checkCommands();
            if( cmd.cmd_request != BAL_ZMP_WALKING )
                keepWalking = false;
        }

        prevTimeIndex = timeIndex;
        timeIndex = nextTimeIndex;
        sendState();
    }

    bal_state.m_walk_mode = WALK_INACTIVE;
    sendState();
}
int main( int argc, char **argv )
{
    Hubo_Control hubo("proto-manip-daemon");

    ach_channel_t chan_manip_cmd;

    int r = ach_open( &chan_manip_cmd, CHAN_HUBO_MANIP, NULL );
    daemon_assert( r==ACH_OK, __LINE__ );
    
    hubo_manip_cmd manip;
    memset( &manip, 0, sizeof(manip) );

    hubo.update();

    Eigen::Isometry3d Br, Bl;
    Vector6d right, left, zeros; zeros.setZero();
    Vector3d rtrans, ltrans, langles, rangles;
    

    hubo.getRightArmAngles(right);
    hubo.getLeftArmAngles(left);

    hubo.huboArmFK( Br, right, RIGHT );
    hubo.huboArmFK( Bl, left, LEFT );
    
    std::cout << "Performed initial FK" << std::endl;

    for(int i=0; i<3; i++)
    {
        manip.translation[RIGHT][i] = Br(i,3);
        manip.translation[LEFT][i] = Bl(i,3);
    }

    std::cout << "Putting first transformation" << std::endl;
    ach_put( &chan_manip_cmd, &manip, sizeof(manip) );

    size_t fs;

    std::cout << "About to start loop" << std::endl;

    while( !daemon_sig_quit )
    {
        hubo.update();
        ach_get( &chan_manip_cmd, &manip, sizeof(manip), &fs, NULL, ACH_O_LAST );
        
        for(int i=0; i<3; i++)
        {
            rtrans(i) = manip.translation[RIGHT][i];
            ltrans(i) = manip.translation[LEFT][i];
            rangles(i) = manip.eulerAngles[RIGHT][i];
            langles(i) = manip.eulerAngles[LEFT][i];
        }

        // Handle the right arm
        Br = Eigen::Matrix4d::Identity();
        Br.translate(rtrans);
        Br.rotate( Eigen::AngleAxisd(rangles(0), Vector3d(1,0,0)) );
        Br.rotate( Eigen::AngleAxisd(rangles(1), Vector3d(0,1,0)) );
        Br.rotate( Eigen::AngleAxisd(rangles(2), Vector3d(0,0,1)) );
        hubo.huboArmIK( right, Br, zeros, RIGHT );
        hubo.setRightArmAngles( right );

        // Handle the left arm
        Bl = Eigen::Matrix4d::Identity();
        Bl.translate(ltrans);
        Bl.rotate( Eigen::AngleAxisd(langles(0), Vector3d(1,0,0)) );
        Bl.rotate( Eigen::AngleAxisd(langles(1), Vector3d(0,1,0)) );
        Bl.rotate( Eigen::AngleAxisd(langles(2), Vector3d(0,0,1)) ); 
        hubo.huboArmIK( left, Bl, zeros, LEFT );
        hubo.setLeftArmAngles( left );

        // Send commands off to the control daemon
        hubo.sendControls();
    }
    



    ach_close( &chan_manip_cmd );




}