aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/tcf-agent
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/tcf-agent')
-rw-r--r--meta/recipes-devtools/tcf-agent/tcf-agent/fix_tcf-agent.init.patch92
-rw-r--r--meta/recipes-devtools/tcf-agent/tcf-agent/terminals_agent.patch1025
-rw-r--r--meta/recipes-devtools/tcf-agent/tcf-agent_svn.bb36
3 files changed, 1153 insertions, 0 deletions
diff --git a/meta/recipes-devtools/tcf-agent/tcf-agent/fix_tcf-agent.init.patch b/meta/recipes-devtools/tcf-agent/tcf-agent/fix_tcf-agent.init.patch
new file mode 100644
index 0000000000..fa9e458714
--- /dev/null
+++ b/meta/recipes-devtools/tcf-agent/tcf-agent/fix_tcf-agent.init.patch
@@ -0,0 +1,92 @@
+--- a/Makefile
++++ b/Makefile
+@@ -32,7 +32,7 @@
+ install -d -m 755 $(INSTALLROOT)$(SBIN)
+ install -d -m 755 $(INSTALLROOT)$(INIT)
+ install -c $(BINDIR)/agent -m 755 $(INSTALLROOT)$(SBIN)/tcf-agent
+- install -c $(TCF_AGENT_DIR)/main/tcf-agent.init -m 755 $(INSTALLROOT)$(INIT)/tcf-agent
++ install -c tcf-agent.init -m 755 $(INSTALLROOT)$(INIT)/tcf-agent
+
+ clean:
+ rm -rf $(BINDIR)
+--- /dev/null
++++ b/tcf-agent.init
+@@ -0,0 +1,78 @@
++#!/bin/sh
++### BEGIN INIT INFO
++# Provides: tcf-agent
++# Default-Start: 3 5
++# Default-Stop: 0 1 2 6
++# Short-Description: Target Communication Framework agent
++### END INIT INFO
++
++DAEMON_PATH=/usr/sbin/tcf-agent
++DAEMON_NAME=`basename $DAEMON_PATH`
++
++. /etc/init.d/functions
++
++test -x $DAEMON_PATH || exit 0
++
++PATH=/sbin:/usr/sbin:/bin:/usr/bin
++export PATH
++
++RETVAL=0
++
++case "$1" in
++ start)
++ echo -n "Starting $DAEMON_NAME: "
++ $DAEMON_PATH -d -L- -l0
++ RETVAL=$?
++ if [ $RETVAL -eq 0 ] ; then
++ echo "OK"
++ touch /var/lock/subsys/$DAEMON_NAME
++ else
++ echo "FAIL"
++ fi
++ ;;
++
++ stop)
++ echo -n "Stopping $DAEMON_NAME: "
++ count=0
++ while [ -n "`/bin/pidof $DAEMON_PATH`" -a $count -lt 10 ] ; do
++ killproc $DAEMON_PATH >& /dev/null
++ sleep 1
++ RETVAL=$?
++ if [ $RETVAL != 0 -o -n "`/bin/pidof $DAEMON_PATH`" ] ; then
++ sleep 3
++ fi
++ count=`expr $count + 1`
++ done
++ rm -f /var/lock/subsys/$DAEMON_NAME
++ if [ -n "`/bin/pidof $DAEMON_PATH`" ] ; then
++ echo "FAIL"
++ else
++ echo "OK"
++ fi
++ ;;
++
++ restart)
++ $0 stop
++ sleep 1
++ $0 start
++ ;;
++
++ status)
++ if [ -n "`/bin/pidof $DAEMON_PATH`" ] ; then
++ echo "$DAEMON_NAME is running"
++ else
++ echo "$DAEMON_NAME is not running"
++ fi
++ ;;
++
++ condrestart)
++ [ -f /var/lock/subsys/$DAEMON_NAME ] && $0 restart
++ ;;
++
++ *)
++ echo "usage: $0 { start | stop | restart | condrestart | status }"
++ ;;
++esac
++
++exit $RETVAL
++
diff --git a/meta/recipes-devtools/tcf-agent/tcf-agent/terminals_agent.patch b/meta/recipes-devtools/tcf-agent/tcf-agent/terminals_agent.patch
new file mode 100644
index 0000000000..b88b5e70cd
--- /dev/null
+++ b/meta/recipes-devtools/tcf-agent/tcf-agent/terminals_agent.patch
@@ -0,0 +1,1025 @@
+Index: org.eclipse.tm.tcf.terminals.agent/terminals.c
+===================================================================
+--- org.eclipse.tm.tcf.terminals.agent/terminals.c (revision 0)
++++ org.eclipse.tm.tcf.terminals.agent/terminals.c (revision 0)
+@@ -0,0 +1,846 @@
++/*******************************************************************************
++ * Copyright (c) 2008 Wind River Systems, Inc. and others.
++ * All rights reserved. This program and the accompanying materials
++ * are made available under the terms of the Eclipse Public License v1.0
++ * and Eclipse Distribution License v1.0 which accompany this distribution.
++ * The Eclipse Public License is available at
++ * http://www.eclipse.org/legal/epl-v10.html
++ * and the Eclipse Distribution License is available at
++ * http://www.eclipse.org/org/documents/edl-v10.php.
++ *
++ * Contributors:
++ * Wind River Systems - initial API and implementation
++ *******************************************************************************/
++
++/*
++ * Sample TCF service implementation.
++ */
++
++#include <config.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <signal.h>
++#include <assert.h>
++#include <termios.h>
++#ifndef TIOCGWINSZ
++#include <sys/ioctl.h>
++#endif
++#include <framework/myalloc.h>
++#include <framework/protocol.h>
++#include <framework/trace.h>
++#include <framework/context.h>
++#include <framework/json.h>
++#include <framework/asyncreq.h>
++#include <framework/exceptions.h>
++#include <framework/waitpid.h>
++#include <framework/signames.h>
++#include <services/streamsservice.h>
++#include <terminals.h>
++
++#define TERMINALS_DEBUG 1
++
++#define TERMINALS_NO_LOGIN 0
++
++static const char * TERMINALS = "Terminals";
++
++#if defined(WIN32)
++# include <tlhelp32.h>
++# ifdef _MSC_VER
++# pragma warning(disable:4201) /* nonstandard extension used : nameless struct/union (in winternl.h) */
++# include <winternl.h>
++# else
++# include <ntdef.h>
++# endif
++# ifndef STATUS_INFO_LENGTH_MISMATCH
++# define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
++# endif
++# ifndef SystemHandleInformation
++# define SystemHandleInformation 16
++# endif
++# error("unsupported WIN32!")
++#elif defined(_WRS_KERNEL)
++# include <symLib.h>
++# include <sysSymTbl.h>
++# include <ioLib.h>
++# include <ptyDrv.h>
++# include <taskHookLib.h>
++# error("unsupported WRS!")
++#else
++# include <sys/stat.h>
++# include <unistd.h>
++# include <dirent.h>
++# if TERMINALS_NO_LOGIN
++# define TERM_LAUNCH_EXEC "/bin/bash"
++# define TERM_LAUNCH_ARGS {TERM_LAUNCH_EXEC, NULL}
++# else
++# define TERM_LAUNCH_EXEC "/bin/login"
++# define TERM_LAUNCH_ARGS {TERM_LAUNCH_EXEC, "-p", NULL}
++# endif
++#endif
++
++#define PIPE_SIZE 0x1000
++#define TERM_PROP_DEF_SIZE 256
++
++typedef struct Terminal
++{
++ LINK link;
++ int pid; /*pid of the login process of the terminal*/
++ TCFBroadcastGroup * bcg;
++ int inp;
++ int out;
++ int err;
++ struct TerminalInput * inp_struct;
++ struct TerminalOutput * out_struct;
++ struct TerminalOutput * err_struct;
++ char inp_id[256];
++ char out_id[256];
++ char err_id[256];
++
++ char pty_type[TERM_PROP_DEF_SIZE];
++ char encoding[TERM_PROP_DEF_SIZE];
++ unsigned long width;
++ unsigned long height;
++ long exit_code;
++
++ Channel *channel;
++} Terminal;
++
++typedef struct TerminalOutput
++{
++ Terminal * prs;
++ AsyncReqInfo req;
++ int req_posted;
++ char buf[PIPE_SIZE];
++ size_t buf_pos;
++ int eos;
++ VirtualStream * vstream;
++} TerminalOutput;
++
++typedef struct TerminalInput
++{
++ Terminal * prs;
++ AsyncReqInfo req;
++ int req_posted;
++ char buf[PIPE_SIZE];
++ size_t buf_pos;
++ size_t buf_len;
++ int eos;
++ VirtualStream * vstream;
++} TerminalInput;
++
++#define link2term(A) ((Terminal *)((char *)(A) - offsetof(Terminal, link)))
++
++static LINK terms_list;
++#if defined(_WRS_KERNEL)
++static SEM_ID prs_list_lock = NULL;
++#endif
++
++static Terminal * find_terminal(int pid)
++{
++ LINK * qhp = &terms_list;
++ LINK * qp = qhp->next;
++
++ while (qp != qhp) {
++ Terminal * prs = link2term(qp);
++ if (prs->pid == pid)
++ return prs;
++ qp = qp->next;
++ }
++ return NULL;
++}
++
++static char * tid2id(int tid)
++{
++ static char s[64];
++ char * p = s + sizeof(s);
++ unsigned long n = (long) tid;
++ *(--p) = 0;
++ do {
++ *(--p) = (char) (n % 10 + '0');
++ n = n / 10;
++ } while (n != 0);
++
++ *(--p) = 'T';
++ return p;
++}
++
++static int id2tid(const char * id)
++{
++ int tid = 0;
++ if (id == NULL)
++ return 0;
++ if (id[0] != 'T')
++ return 0;
++ if (id[1] == 0)
++ return 0;
++ tid = (unsigned) strtol(id + 1, (char **) &id, 10);
++ if (id[0] != 0)
++ return 0;
++ return tid;
++}
++
++static void write_context(OutputStream * out, int tid)
++{
++ Terminal * prs = find_terminal(tid);
++
++ write_stream(out, '{');
++
++ if (prs != NULL) {
++ if (*prs->pty_type) {
++ json_write_string(out, "PtyType");
++ write_stream(out, ':');
++ json_write_string(out, prs->pty_type);
++ write_stream(out, ',');
++ }
++
++ if (*prs->encoding) {
++ json_write_string(out, "Encoding");
++ write_stream(out, ':');
++ json_write_string(out, prs->encoding);
++ write_stream(out, ',');
++ }
++
++ json_write_string(out, "Width");
++ write_stream(out, ':');
++ json_write_ulong(out, prs->width);
++ write_stream(out, ',');
++
++ json_write_string(out, "Height");
++ write_stream(out, ':');
++ json_write_ulong(out, prs->height);
++ write_stream(out, ',');
++
++ if (*prs->inp_id) {
++ json_write_string(out, "StdInID");
++ write_stream(out, ':');
++ json_write_string(out, prs->inp_id);
++ write_stream(out, ',');
++ }
++ if (*prs->out_id) {
++ json_write_string(out, "StdOutID");
++ write_stream(out, ':');
++ json_write_string(out, prs->out_id);
++ write_stream(out, ',');
++ }
++ if (*prs->err_id) {
++ json_write_string(out, "StdErrID");
++ write_stream(out, ':');
++ json_write_string(out, prs->err_id);
++ write_stream(out, ',');
++ }
++ }
++
++ json_write_string(out, "ID");
++ write_stream(out, ':');
++ json_write_string(out, tid2id(tid));
++
++ write_stream(out, '}');
++}
++
++static void send_event_terminal_exited(OutputStream * out, Terminal * prs)
++{
++ write_stringz(out, "E");
++ write_stringz(out, TERMINALS);
++ write_stringz(out, "exited");
++
++ json_write_string(out, tid2id(prs->pid));
++ write_stream(out, 0);
++
++ json_write_ulong(out, prs->exit_code);
++ write_stream(out, 0);
++
++ write_stream(out, MARKER_EOM);
++}
++
++static void send_event_terminal_win_size_changed(OutputStream * out,
++ Terminal * prs)
++{
++ write_stringz(out, "E");
++ write_stringz(out, TERMINALS);
++ write_stringz(out, "winSizeChanged");
++
++ json_write_string(out, tid2id(prs->pid));
++ write_stream(out, 0);
++
++ json_write_long(out, prs->width);
++ write_stream(out, 0);
++
++ json_write_long(out, prs->height);
++ write_stream(out, 0);
++
++ write_stream(out, MARKER_EOM);
++}
++
++static int kill_term(Terminal *term)
++{
++ int err = 0;
++
++#if defined(WIN32)
++ HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, term->pid);
++ if (h == NULL)
++ {
++ err = set_win32_errno(GetLastError());
++ }
++ else
++ {
++ if (!TerminateProcess(h, 1)) err = set_win32_errno(GetLastError());
++ if (!CloseHandle(h) && !err) err = set_win32_errno(GetLastError());
++ }
++#else
++ if (kill(term->pid, SIGTERM) < 0)
++ err = errno;
++#endif
++ return err;
++}
++
++static void command_exit(char * token, Channel * c)
++{
++ int err = 0;
++ char id[256];
++ unsigned tid;
++ Terminal *term = NULL;
++
++ json_read_string(&c->inp, id, sizeof(id));
++ if (read_stream(&c->inp) != 0)
++ exception(ERR_JSON_SYNTAX);
++ if (read_stream(&c->inp) != MARKER_EOM)
++ exception(ERR_JSON_SYNTAX);
++
++ tid = id2tid(id);
++ write_stringz(&c->out, "R");
++ write_stringz(&c->out, token);
++
++ if (tid == 0) {
++ err = ERR_INV_CONTEXT;
++ } else {
++ term = find_terminal(tid);
++ if (term == NULL) {
++ err = ERR_INV_CONTEXT;
++ } else {
++ err = kill_term(term);
++ }
++ }
++
++ write_errno(&c->out, err);
++ write_stream(&c->out, MARKER_EOM);
++}
++
++static void terminal_exited(Terminal * prs)
++{
++ Trap trap;
++
++ if (set_trap(&trap)) {
++ send_event_terminal_exited(&prs->bcg->out, prs);
++ clear_trap(&trap);
++ } else {
++ trace(LOG_ALWAYS, "Exception sending terminal exited event: %d %s",
++ trap.error, errno_to_str(trap.error));
++ }
++
++#if defined(_WRS_KERNEL)
++ semTake(prs_list_lock, WAIT_FOREVER);
++#endif
++ list_remove(&prs->link);
++ close(prs->inp);
++ close(prs->out);
++ if (prs->out != prs->err)
++ close(prs->err);
++ if (prs->inp_struct) {
++ TerminalInput * inp = prs->inp_struct;
++ if (!inp->req_posted) {
++ virtual_stream_delete(inp->vstream);
++ loc_free(inp);
++ } else {
++ inp->prs = NULL;
++ }
++ }
++ if (prs->out_struct)
++ prs->out_struct->prs = NULL;
++ if (prs->err_struct)
++ prs->err_struct->prs = NULL;
++ loc_free(prs);
++#if defined(_WRS_KERNEL)
++ semGive(prs_list_lock);
++#endif
++}
++
++static void terminal_input_streams_callback(VirtualStream * stream,
++ int event_code, void * args)
++{
++ TerminalInput * inp = (TerminalInput *) args;
++
++ assert(inp->vstream == stream);
++ if (!inp->req_posted) {
++ if (inp->buf_pos >= inp->buf_len && !inp->eos) {
++ inp->buf_pos = inp->buf_len = 0;
++ virtual_stream_get_data(stream, inp->buf, sizeof(inp->buf),
++ &inp->buf_len, &inp->eos);
++ }
++ if (inp->buf_pos < inp->buf_len) {
++ inp->req.u.fio.bufp = inp->buf + inp->buf_pos;
++ inp->req.u.fio.bufsz = inp->buf_len - inp->buf_pos;
++ inp->req_posted = 1;
++ async_req_post(&inp->req);
++ }
++ }
++}
++
++static void write_terminal_input_done(void * x)
++{
++ AsyncReqInfo * req = (AsyncReqInfo *) x;
++ TerminalInput * inp = (TerminalInput *) req->client_data;
++
++ inp->req_posted = 0;
++ if (inp->prs == NULL) {
++ /* Process has exited */
++ virtual_stream_delete(inp->vstream);
++ loc_free(inp);
++ } else {
++ int wr = inp->req.u.fio.rval;
++
++ if (wr < 0) {
++ int err = inp->req.error;
++ trace(LOG_ALWAYS, "Can't write terminal input stream: %d %s", err,
++ errno_to_str(err));
++ inp->buf_pos = inp->buf_len = 0;
++ } else {
++ inp->buf_pos += wr;
++ }
++
++ terminal_input_streams_callback(inp->vstream, 0, inp);
++ }
++}
++
++static void write_terminal_input(Terminal * prs)
++{
++ TerminalInput * inp = prs->inp_struct = (TerminalInput *) loc_alloc_zero(
++ sizeof(TerminalInput));
++ inp->prs = prs;
++ inp->req.client_data = inp;
++ inp->req.done = write_terminal_input_done;
++ inp->req.type = AsyncReqWrite;
++ inp->req.u.fio.fd = prs->inp;
++ virtual_stream_create(TERMINALS, tid2id(prs->pid), PIPE_SIZE,
++ VS_ENABLE_REMOTE_WRITE, terminal_input_streams_callback, inp,
++ &inp->vstream);
++ virtual_stream_get_id(inp->vstream, prs->inp_id, sizeof(prs->inp_id));
++}
++
++static void terminal_output_streams_callback(VirtualStream * stream,
++ int event_code, void * args)
++{
++ TerminalOutput * out = (TerminalOutput *) args;
++
++ assert(out->vstream == stream);
++ if (!out->req_posted) {
++ int buf_len = out->req.u.fio.rval;
++ int err = 0;
++ int eos = 0;
++
++ if (buf_len < 0) {
++ buf_len = 0;
++ err = out->req.error;
++ }
++ if (buf_len == 0)
++ eos = 1;
++ if (out->prs == NULL) {
++ eos = 1;
++ err = 0;
++ }
++
++ assert(buf_len <= (int)sizeof(out->buf));
++ assert(out->buf_pos <= (size_t)buf_len);
++ assert(out->req.u.fio.bufp == out->buf);
++#ifdef __linux__
++ if (err == EIO)
++ err = 0;
++#endif
++ if (err)
++ trace(LOG_ALWAYS, "Can't read terminal output stream: %d %s", err,
++ errno_to_str(err));
++
++ if (out->buf_pos < (size_t) buf_len || out->eos != eos) {
++ size_t done = 0;
++ virtual_stream_add_data(stream, out->buf + out->buf_pos, buf_len
++ - out->buf_pos, &done, eos);
++ out->buf_pos += done;
++ if (eos)
++ out->eos = 1;
++ }
++
++ if (out->buf_pos >= (size_t) buf_len) {
++ if (!eos) {
++ out->req_posted = 1;
++ async_req_post(&out->req);
++ } else if (virtual_stream_is_empty(stream)) {
++ if (out->prs != NULL) {
++ if (out == out->prs->out_struct)
++ out->prs->out_struct = NULL;
++ if (out == out->prs->err_struct)
++ out->prs->err_struct = NULL;
++ }
++ virtual_stream_delete(stream);
++ loc_free(out);
++ }
++ }
++ } // end if(!out->req_posted)
++}
++
++static void read_terminal_output_done(void * x)
++{
++ AsyncReqInfo * req = (AsyncReqInfo *) x;
++ TerminalOutput * out = (TerminalOutput *) req->client_data;
++
++ out->buf_pos = 0;
++ out->req_posted = 0;
++ terminal_output_streams_callback(out->vstream, 0, out);
++}
++
++static TerminalOutput * read_terminal_output(Terminal * prs, int fd, char * id,
++ size_t id_size)
++{
++ TerminalOutput * out = (TerminalOutput *) loc_alloc_zero(
++ sizeof(TerminalOutput));
++ out->prs = prs;
++ out->req.client_data = out;
++ out->req.done = read_terminal_output_done;
++ out->req.type = AsyncReqRead;
++ out->req.u.fio.bufp = out->buf;
++ out->req.u.fio.bufsz = sizeof(out->buf);
++ out->req.u.fio.fd = fd;
++ virtual_stream_create(TERMINALS, tid2id(prs->pid), PIPE_SIZE,
++ VS_ENABLE_REMOTE_READ, terminal_output_streams_callback, out,
++ &out->vstream);
++ virtual_stream_get_id(out->vstream, id, id_size);
++ out->req_posted = 1;
++ async_req_post(&out->req);
++ return out;
++}
++
++static char **envp_add(char **old_envp, int old_envp_len, char *env)
++{
++ char **new_envp = NULL;
++ int i;
++ int env_size;
++ int old_envp_size;
++
++ assert(old_envp || (old_envp==NULL && old_envp_len==0));
++ assert(env);
++ assert(*env);
++
++ for (i = 0, old_envp_size = 0; i < old_envp_len; i++) {
++ old_envp_size += sizeof(char *); //size of env pointer
++ old_envp_size += strlen(old_envp[i]) + 1; //size of env string, including trailing '\0'
++ }
++ assert((old_envp && old_envp[i]==NULL) || (old_envp==NULL));
++ old_envp_size += sizeof(char *);//last null pointer
++
++ env_size = strlen(env); //new env string size
++
++ new_envp = loc_alloc(old_envp_size + sizeof(char *) + env_size + 1);
++ if (new_envp != NULL) {
++ new_envp[0] = (char *) new_envp + old_envp_size + sizeof(char *); //setting new env ptr
++ strcpy(new_envp[0], env); //copy new env string
++ if (old_envp) {
++ memcpy(&new_envp[1], old_envp, old_envp_size); //copy old envp
++ } else {
++ new_envp[1] = NULL;
++ }
++ }
++ return new_envp;
++}
++
++static int start_terminal(Channel * c, char *pty_type, char *encoding,
++ char ** envp, int envp_len, char * exe, char ** args, int *pid,
++ Terminal ** prs)
++{
++ int err = 0;
++ int fd_tty_master = -1;
++ char * tty_slave_name = NULL;
++ struct winsize size;
++ char **newenvp = envp;
++
++ memset(&size, 0, sizeof(struct winsize));
++ fd_tty_master = posix_openpt(O_RDWR | O_NOCTTY);
++ if (fd_tty_master < 0 || grantpt(fd_tty_master) < 0 || unlockpt(
++ fd_tty_master) < 0)
++ err = errno;
++ if (!err) {
++ tty_slave_name = ptsname(fd_tty_master);
++ if (tty_slave_name == NULL)
++ err = EINVAL;
++ }
++
++ if (ioctl(fd_tty_master, TIOCGWINSZ, (char *) &size) < 0)
++ err = errno;
++
++ if (!err && fd_tty_master < 3) {
++ int fd0 = fd_tty_master;
++ if ((fd_tty_master = dup(fd_tty_master)) < 0 || close(fd0))
++ err = errno;
++ }
++
++ if (!err) {
++ *pid = fork();
++ if (*pid < 0)
++ err = errno;
++ if (*pid == 0) {
++ int fd = -1;
++ int fd_tty_slave = -1;
++
++ if (*pty_type) {
++ char env_term[TERM_PROP_DEF_SIZE];
++ snprintf(env_term, sizeof(env_term), "TERM=%s", pty_type);
++ newenvp = envp_add(envp, envp_len, env_term);
++ if (newenvp == NULL) {
++ err = ENOMEM;
++ } else if (envp) {
++ loc_free(envp);
++ envp = NULL;
++ }
++ }
++
++ setsid();
++
++ if (!err && (fd = sysconf(_SC_OPEN_MAX)) < 0)
++ err = errno;
++ if (!err && (fd_tty_slave = open(tty_slave_name, O_RDWR)) < 0)
++ err = errno;
++#if defined(TIOCSCTTY)
++ if (!err && (ioctl(fd_tty_slave, TIOCSCTTY, (char *) 0)) < 0)
++ err = errno;
++#endif
++ if (!err && dup2(fd_tty_slave, 0) < 0)
++ err = errno;
++ if (!err && dup2(fd_tty_slave, 1) < 0)
++ err = errno;
++ if (!err && dup2(fd_tty_slave, 2) < 0)
++ err = errno;
++ while (!err && fd > 3)
++ close(--fd);
++ if (!err) {
++ execve(exe, args, newenvp);
++ err = errno;
++ }
++ if (newenvp)
++ loc_free(newenvp);
++ err = 1;
++ if (err < 1)
++ err = EINVAL;
++ else if (err > 0xff)
++ err = EINVAL;
++ exit(err);
++ }
++ }
++
++ if (!err) {
++ *prs = (Terminal *) loc_alloc_zero(sizeof(Terminal));
++ (*prs)->inp = fd_tty_master;
++ (*prs)->out = fd_tty_master;
++ (*prs)->err = fd_tty_master;
++ (*prs)->pid = *pid;
++ (*prs)->bcg = c->bcg;
++ (*prs)->channel = c;
++ if (*pty_type)
++ snprintf((*prs)->pty_type, sizeof((*prs)->pty_type), "%s", pty_type);
++ if (*encoding)
++ snprintf((*prs)->encoding, sizeof((*prs)->encoding), "%s", encoding);
++ (*prs)->width = size.ws_row;
++ (*prs)->height = size.ws_col;
++ list_add_first(&(*prs)->link, &terms_list);
++ }
++
++ if (!err)
++ return 0;
++ errno = err;
++ return -1;
++}
++
++static void command_get_context(char * token, Channel * c)
++{
++ int err = 0;
++ char id[256];
++ int tid;
++ Terminal *term;
++
++ json_read_string(&c->inp, id, sizeof(id));
++ if (read_stream(&c->inp) != 0)
++ exception(ERR_JSON_SYNTAX);
++ if (read_stream(&c->inp) != MARKER_EOM)
++ exception(ERR_JSON_SYNTAX);
++
++ tid = id2tid(id);
++ write_stringz(&c->out, "R");
++ write_stringz(&c->out, token);
++
++ if (tid == 0) {
++ err = ERR_INV_CONTEXT;
++ } else {
++ term = find_terminal(tid);
++ if (term == NULL) {
++ err = ERR_INV_CONTEXT;
++ } else {
++ write_context(&c->out, tid);
++ write_stream(&c->out, 0);
++ }
++ }
++
++ write_errno(&c->out, err);
++ write_stream(&c->out, MARKER_EOM);
++}
++
++static void command_launch(char * token, Channel * c)
++{
++ int pid = 0;
++ int err = 0;
++ char encoding[TERM_PROP_DEF_SIZE];
++ char pty_type[TERM_PROP_DEF_SIZE];
++ char *args[] = TERM_LAUNCH_ARGS;
++
++ char ** envp = NULL;
++ int envp_len = 0;
++
++ Terminal * prs = NULL;
++ Trap trap;
++
++ if (set_trap(&trap)) {
++ json_read_string(&c->inp, pty_type, sizeof(pty_type));
++ if (read_stream(&c->inp) != 0)
++ exception(ERR_JSON_SYNTAX);
++ json_read_string(&c->inp, encoding, sizeof(encoding));
++ if (read_stream(&c->inp) != 0)
++ exception(ERR_JSON_SYNTAX);
++ envp = json_read_alloc_string_array(&c->inp, &envp_len);
++ if (read_stream(&c->inp) != 0)
++ exception(ERR_JSON_SYNTAX);
++ if (read_stream(&c->inp) != MARKER_EOM)
++ exception(ERR_JSON_SYNTAX);
++
++ if (err == 0 && start_terminal(c, pty_type, encoding, envp, envp_len,
++ TERM_LAUNCH_EXEC, args, &pid, &prs) < 0)
++ err = errno;
++ if (prs != NULL) {
++ write_terminal_input(prs);
++ prs->out_struct = read_terminal_output(prs, prs->out, prs->out_id,
++ sizeof(prs->out_id));
++ if (prs->out != prs->err)
++ prs->err_struct = read_terminal_output(prs, prs->err,
++ prs->err_id, sizeof(prs->err_id));
++ }
++ if (!err) {
++ add_waitpid_process(pid);
++ }
++ //write result back
++ {
++ write_stringz(&c->out, "R");
++ write_stringz(&c->out, token);
++ write_errno(&c->out, err);
++ if (err || pid == 0) {
++ write_stringz(&c->out, "null");
++ } else {
++ write_context(&c->out, pid);
++ write_stream(&c->out, 0);
++ }
++ write_stream(&c->out, MARKER_EOM);
++ }
++ clear_trap(&trap);
++ }
++
++ loc_free(envp);
++
++ if (trap.error)
++ exception(trap.error);
++}
++
++static void command_set_win_size(char * token, Channel * c)
++{
++ int err = 0;
++ struct winsize size;
++ char id[256];
++ unsigned tid;
++ Terminal *term = NULL;
++
++ json_read_string(&c->inp, id, sizeof(id));
++ if (read_stream(&c->inp) != 0)
++ exception(ERR_JSON_SYNTAX);
++ size.ws_col=json_read_ulong(&c->inp);
++ if (read_stream(&c->inp) != 0)
++ exception(ERR_JSON_SYNTAX);
++ size.ws_row=json_read_ulong(&c->inp);
++ if (read_stream(&c->inp) != 0)
++ exception(ERR_JSON_SYNTAX);
++ if (read_stream(&c->inp) != MARKER_EOM)
++ exception(ERR_JSON_SYNTAX);
++
++ tid = id2tid(id);
++
++ if(tid==0 || (term=find_terminal(tid))==NULL) {
++ err=ERR_INV_CONTEXT;
++ }else if (term->width != size.ws_col || term->height != size.ws_row) {
++ if(ioctl(term->inp,TIOCSWINSZ,&size)<0) {
++ err=errno;
++ }
++ if(!err) {
++ term->width=size.ws_col;
++ term->height=size.ws_row;
++ send_event_terminal_win_size_changed(&term->channel->out,term);
++ }
++ }
++
++ write_stringz(&c->out, "R");
++ write_stringz(&c->out, token);
++ write_errno(&c->out, err);
++ write_stream(&c->out, MARKER_EOM);
++
++}
++
++static void waitpid_listener(int pid, int exited, int exit_code, int signal,
++ int event_code, int syscall, void * args)
++{
++ if (exited) {
++ Terminal * prs = find_terminal(pid);
++ if (prs) {
++ if (signal != 0)
++ prs->exit_code = -signal;
++ else
++ prs->exit_code = exit_code;
++ terminal_exited(prs);
++ }
++ }
++}
++
++static void channel_close_listener(Channel * c)
++{
++ LINK * l = NULL;
++
++ for (l = terms_list.next; l != &terms_list;) {
++ Terminal * term = link2term(l);
++ l = l->next;
++ if (term->channel == c) {
++ trace(LOG_ALWAYS, "Terminal is left launched: T%d", term->pid);
++ kill_term(term);
++ }
++ }
++}
++
++void ini_terminals_service(Protocol * proto)
++{
++#if defined(_WRS_KERNEL)
++ prs_list_lock = semMCreate(SEM_Q_PRIORITY);
++ if (prs_list_lock == NULL) check_error(errno);
++ if (taskCreateHookAdd((FUNCPTR)task_create_hook) != OK) check_error(errno);
++ if (taskDeleteHookAdd((FUNCPTR)task_delete_hook) != OK) check_error(errno);
++#endif
++ list_init(&terms_list);
++
++ add_waitpid_listener(waitpid_listener, NULL);
++ add_channel_close_listener(channel_close_listener);
++
++ add_command_handler(proto, TERMINALS, "getContext", command_get_context);
++ add_command_handler(proto, TERMINALS, "launch", command_launch);
++ add_command_handler(proto, TERMINALS, "exit", command_exit);
++ add_command_handler(proto, TERMINALS, "setWinSize", command_set_win_size);
++}
+Index: org.eclipse.tm.tcf.terminals.agent/main/services-ext.h
+===================================================================
+--- org.eclipse.tm.tcf.terminals.agent/main/services-ext.h (revision 0)
++++ org.eclipse.tm.tcf.terminals.agent/main/services-ext.h (revision 0)
+@@ -0,0 +1,25 @@
++/*******************************************************************************
++ * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
++ * All rights reserved. This program and the accompanying materials
++ * are made available under the terms of the Eclipse Public License v1.0
++ * and Eclipse Distribution License v1.0 which accompany this distribution.
++ * The Eclipse Public License is available at
++ * http://www.eclipse.org/legal/epl-v10.html
++ * and the Eclipse Distribution License is available at
++ * http://www.eclipse.org/org/documents/edl-v10.php.
++ *
++ * Contributors:
++ * Wind River Systems - initial API and implementation
++ *******************************************************************************/
++
++/*
++ * Services initialization code extension point.
++ * If the agent is built with additional user-defined services,
++ * a customized version of services-ext.h file can be added to compiler headers search paths.
++ */
++
++#include "terminals.h"
++
++static void ini_ext_services(Protocol * proto, TCFBroadcastGroup * bcg) {
++ ini_terminals_service(proto);
++}
+Index: org.eclipse.tm.tcf.terminals.agent/terminals.h
+===================================================================
+--- org.eclipse.tm.tcf.terminals.agent/terminals.h (revision 0)
++++ org.eclipse.tm.tcf.terminals.agent/terminals.h (revision 0)
+@@ -0,0 +1,27 @@
++/*******************************************************************************
++ * Copyright (c) 2008 Wind River Systems, Inc. and others.
++ * All rights reserved. This program and the accompanying materials
++ * are made available under the terms of the Eclipse Public License v1.0
++ * and Eclipse Distribution License v1.0 which accompany this distribution.
++ * The Eclipse Public License is available at
++ * http://www.eclipse.org/legal/epl-v10.html
++ * and the Eclipse Distribution License is available at
++ * http://www.eclipse.org/org/documents/edl-v10.php.
++ *
++ * Contributors:
++ * Wind River Systems - initial API and implementation
++ *******************************************************************************/
++
++/*
++ * Sample TCF service header file.
++ */
++
++#ifndef TERMINALS_H_
++#define TERMINALS_H_
++
++#include <config.h>
++#include <framework/protocol.h>
++
++extern void ini_terminals_service(Protocol * proto);
++
++#endif /*TERMINALS_H_*/
+Index: org.eclipse.tm.tcf.terminals.agent/config.h
+===================================================================
+--- org.eclipse.tm.tcf.terminals.agent/config.h (revision 0)
++++ org.eclipse.tm.tcf.terminals.agent/config.h (revision 0)
+@@ -0,0 +1,63 @@
++/*******************************************************************************
++ * Copyright (c) 2008 Wind River Systems, Inc. and others.
++ * All rights reserved. This program and the accompanying materials
++ * are made available under the terms of the Eclipse Public License v1.0
++ * and Eclipse Distribution License v1.0 which accompany this distribution.
++ * The Eclipse Public License is available at
++ * http://www.eclipse.org/legal/epl-v10.html
++ * and the Eclipse Distribution License is available at
++ * http://www.eclipse.org/org/documents/edl-v10.php.
++ *
++ * Contributors:
++ * Wind River Systems - initial API and implementation
++ *******************************************************************************/
++
++/*
++ * This file contains "define" statements that control agent configuration.
++ * SERVICE_* definitions control which service implementations are included into the agent.
++ *
++ * This is example agent configuration. It includes only few standard services,
++ * and one example service: Day Time.
++ */
++
++#ifndef D_config
++#define D_config
++
++#include <framework/mdep.h>
++
++#if defined(WIN32) || defined(__CYGWIN__)
++# define TARGET_UNIX 0
++#elif defined(_WRS_KERNEL)
++# define TARGET_UNIX 0
++#else
++# define TARGET_UNIX 1
++#endif
++
++#define SERVICE_Locator 1
++#define SERVICE_Processes 1
++#define SERVICE_Streams 1
++#define SERVICE_FileSystem 1
++#define SERVICE_SysMonitor TARGET_UNIX
++
++#define ENABLE_ZeroCopy 1
++
++#if !defined(ENABLE_Splice)
++# if ENABLE_ZeroCopy
++# include <fcntl.h>
++# if defined(SPLICE_F_MOVE)
++# define ENABLE_Splice 1
++# else
++# define ENABLE_Splice 0
++# endif
++# else
++# define ENABLE_Splice 0
++# endif
++#endif
++
++#define ENABLE_SSL 0
++
++#define ENABLE_Trace 1
++#define ENABLE_Discovery 1
++
++
++#endif /* D_config */
+Index: org.eclipse.tm.tcf.terminals.agent/Makefile
+===================================================================
+--- org.eclipse.tm.tcf.terminals.agent/Makefile (revision 0)
++++ org.eclipse.tm.tcf.terminals.agent/Makefile (revision 0)
+@@ -0,0 +1,39 @@
++TCF_AGENT_DIR=../agent
++
++include $(TCF_AGENT_DIR)/Makefile.inc
++
++override CFLAGS += $(foreach dir,$(INCDIRS),-I$(dir)) $(OPTS)
++
++HFILES := $(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.h)) $(HFILES)
++CFILES := $(sort $(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.c)) $(CFILES))
++
++#no using SSL
++LIBS = -lpthread -lrt
++
++EXECS = $(BINDIR)/agent$(EXTEXE)
++
++all: $(EXECS)
++
++$(BINDIR)/libtcf$(EXTLIB) : $(OFILES)
++ $(AR) rcs $@ $^
++
++$(BINDIR)/agent$(EXTEXE): $(BINDIR)/main/main$(EXTOBJ) $(BINDIR)/libtcf$(EXTLIB)
++ $(CC) $(CFLAGS) -o $@ $(BINDIR)/main/main$(EXTOBJ) $(BINDIR)/libtcf$(EXTLIB) $(LIBS)
++
++$(BINDIR)/%$(EXTOBJ): %.c $(HFILES) Makefile
++ @mkdir -p $(dir $@)
++ $(CC) $(CFLAGS) -c -o $@ $<
++
++$(BINDIR)/%$(EXTOBJ): $(TCF_AGENT_DIR)/%.c $(HFILES) Makefile
++ @mkdir -p $(dir $@)
++ $(CC) $(CFLAGS) -c -o $@ $<
++
++install: all
++ install -d -m 755 $(INSTALLROOT)$(SBIN)
++ install -d -m 755 $(INSTALLROOT)$(INIT)
++ install -c $(BINDIR)/agent -m 755 $(INSTALLROOT)$(SBIN)/tcf-agent
++ install -c $(TCF_AGENT_DIR)/main/tcf-agent.init -m 755 $(INSTALLROOT)$(INIT)/tcf-agent
++
++clean:
++ rm -rf $(BINDIR)
++
diff --git a/meta/recipes-devtools/tcf-agent/tcf-agent_svn.bb b/meta/recipes-devtools/tcf-agent/tcf-agent_svn.bb
new file mode 100644
index 0000000000..b4c70ec8b8
--- /dev/null
+++ b/meta/recipes-devtools/tcf-agent/tcf-agent_svn.bb
@@ -0,0 +1,36 @@
+DESCRIPTION = "Target Communication Framework"
+HOMEPAGE = "http://dsdp.eclipse.org/dsdp/tm/"
+BUGTRACKER = "https://bugs.eclipse.org/bugs/"
+
+LICENSE = "EPLv1.0 | EDLv1.0"
+LIC_FILES_CHKSUM = "file://../epl-v10.html;md5=7aa4215a330a0a4f6a1cbf8da1a0879f \
+ file://../agent/edl-v10.html;md5=522a390a83dc186513f0500543ad3679"
+
+PV = "0.3.0+svnr${SRCREV}"
+PR = "r0"
+
+SRC_URI = "svn://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/;module=tags/0.3.0/;proto=http \
+ file://terminals_agent.patch \
+ file://fix_tcf-agent.init.patch"
+
+S = "${WORKDIR}/tags/0.3.0/tcf-agent"
+
+inherit update-rc.d
+
+INITSCRIPT_NAME = "tcf-agent"
+INITSCRIPT_PARAMS = "start 999 3 5 . stop 20 0 1 2 6 ."
+
+# mangling needed for make
+MAKE_ARCH = `echo ${TARGET_ARCH} | sed s,i.86,i686,`
+MAKE_OS = `echo ${TARGET_OS} | sed s,linux,GNU/Linux,`
+
+EXTRA_OEMAKE = "MACHINE=${MAKE_ARCH} OPSYS=${MAKE_OS} 'CC=${CC}' 'AR=${AR}'"
+
+do_compile() {
+ oe_runmake
+}
+
+do_install() {
+ oe_runmake install INSTALLROOT=${D}
+}
+