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,860 @@ +/******************************************************************************* + * 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 + * Intel - implemented terminals service + *******************************************************************************/ + +/* + * Sample TCF service implementation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef TIOCGWINSZ +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TERMINALS_DEBUG 1 + +#define TERMINALS_NO_LOGIN 0 + +static const char * TERMINALS = "Terminals"; + +#if defined(WIN32) +# include +# ifdef _MSC_VER +# pragma warning(disable:4201) /* nonstandard extension used : nameless struct/union (in winternl.h) */ +# include +# else +# include +# 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 +# include +# include +# include +# include +# error("unsupported WRS!") +#else +# include +# include +# include +# 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; + char env_term[TERM_PROP_DEF_SIZE]; + + if (*pty_type) { + 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; + } + } + + if (!err && *encoding) { + envp = newenvp; + envp_len += 1; + snprintf(env_term, sizeof(env_term), "LANG=%s", encoding); + 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,26 @@ +/******************************************************************************* + * 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 + * Intel - implemented terminals service + *******************************************************************************/ + +/* + * 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,28 @@ +/******************************************************************************* + * 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 + * Intel - implemented terminals service + *******************************************************************************/ + +/* + * TCF terminals service header file. + */ + +#ifndef TERMINALS_H_ +#define TERMINALS_H_ + +#include +#include + +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,64 @@ +/******************************************************************************* + * 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 + * Intel - implemented terminals service + *******************************************************************************/ + +/* + * 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 + +#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 +# 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) +