summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/tcf-agent/tcf-agent/terminals_agent.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/tcf-agent/tcf-agent/terminals_agent.patch')
-rw-r--r--meta/recipes-devtools/tcf-agent/tcf-agent/terminals_agent.patch1025
1 files changed, 1025 insertions, 0 deletions
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 @@
1Index: org.eclipse.tm.tcf.terminals.agent/terminals.c
2===================================================================
3--- org.eclipse.tm.tcf.terminals.agent/terminals.c (revision 0)
4+++ org.eclipse.tm.tcf.terminals.agent/terminals.c (revision 0)
5@@ -0,0 +1,846 @@
6+/*******************************************************************************
7+ * Copyright (c) 2008 Wind River Systems, Inc. and others.
8+ * All rights reserved. This program and the accompanying materials
9+ * are made available under the terms of the Eclipse Public License v1.0
10+ * and Eclipse Distribution License v1.0 which accompany this distribution.
11+ * The Eclipse Public License is available at
12+ * http://www.eclipse.org/legal/epl-v10.html
13+ * and the Eclipse Distribution License is available at
14+ * http://www.eclipse.org/org/documents/edl-v10.php.
15+ *
16+ * Contributors:
17+ * Wind River Systems - initial API and implementation
18+ *******************************************************************************/
19+
20+/*
21+ * Sample TCF service implementation.
22+ */
23+
24+#include <config.h>
25+#include <stdlib.h>
26+#include <stdio.h>
27+#include <string.h>
28+#include <errno.h>
29+#include <fcntl.h>
30+#include <signal.h>
31+#include <assert.h>
32+#include <termios.h>
33+#ifndef TIOCGWINSZ
34+#include <sys/ioctl.h>
35+#endif
36+#include <framework/myalloc.h>
37+#include <framework/protocol.h>
38+#include <framework/trace.h>
39+#include <framework/context.h>
40+#include <framework/json.h>
41+#include <framework/asyncreq.h>
42+#include <framework/exceptions.h>
43+#include <framework/waitpid.h>
44+#include <framework/signames.h>
45+#include <services/streamsservice.h>
46+#include <terminals.h>
47+
48+#define TERMINALS_DEBUG 1
49+
50+#define TERMINALS_NO_LOGIN 0
51+
52+static const char * TERMINALS = "Terminals";
53+
54+#if defined(WIN32)
55+# include <tlhelp32.h>
56+# ifdef _MSC_VER
57+# pragma warning(disable:4201) /* nonstandard extension used : nameless struct/union (in winternl.h) */
58+# include <winternl.h>
59+# else
60+# include <ntdef.h>
61+# endif
62+# ifndef STATUS_INFO_LENGTH_MISMATCH
63+# define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
64+# endif
65+# ifndef SystemHandleInformation
66+# define SystemHandleInformation 16
67+# endif
68+# error("unsupported WIN32!")
69+#elif defined(_WRS_KERNEL)
70+# include <symLib.h>
71+# include <sysSymTbl.h>
72+# include <ioLib.h>
73+# include <ptyDrv.h>
74+# include <taskHookLib.h>
75+# error("unsupported WRS!")
76+#else
77+# include <sys/stat.h>
78+# include <unistd.h>
79+# include <dirent.h>
80+# if TERMINALS_NO_LOGIN
81+# define TERM_LAUNCH_EXEC "/bin/bash"
82+# define TERM_LAUNCH_ARGS {TERM_LAUNCH_EXEC, NULL}
83+# else
84+# define TERM_LAUNCH_EXEC "/bin/login"
85+# define TERM_LAUNCH_ARGS {TERM_LAUNCH_EXEC, "-p", NULL}
86+# endif
87+#endif
88+
89+#define PIPE_SIZE 0x1000
90+#define TERM_PROP_DEF_SIZE 256
91+
92+typedef struct Terminal
93+{
94+ LINK link;
95+ int pid; /*pid of the login process of the terminal*/
96+ TCFBroadcastGroup * bcg;
97+ int inp;
98+ int out;
99+ int err;
100+ struct TerminalInput * inp_struct;
101+ struct TerminalOutput * out_struct;
102+ struct TerminalOutput * err_struct;
103+ char inp_id[256];
104+ char out_id[256];
105+ char err_id[256];
106+
107+ char pty_type[TERM_PROP_DEF_SIZE];
108+ char encoding[TERM_PROP_DEF_SIZE];
109+ unsigned long width;
110+ unsigned long height;
111+ long exit_code;
112+
113+ Channel *channel;
114+} Terminal;
115+
116+typedef struct TerminalOutput
117+{
118+ Terminal * prs;
119+ AsyncReqInfo req;
120+ int req_posted;
121+ char buf[PIPE_SIZE];
122+ size_t buf_pos;
123+ int eos;
124+ VirtualStream * vstream;
125+} TerminalOutput;
126+
127+typedef struct TerminalInput
128+{
129+ Terminal * prs;
130+ AsyncReqInfo req;
131+ int req_posted;
132+ char buf[PIPE_SIZE];
133+ size_t buf_pos;
134+ size_t buf_len;
135+ int eos;
136+ VirtualStream * vstream;
137+} TerminalInput;
138+
139+#define link2term(A) ((Terminal *)((char *)(A) - offsetof(Terminal, link)))
140+
141+static LINK terms_list;
142+#if defined(_WRS_KERNEL)
143+static SEM_ID prs_list_lock = NULL;
144+#endif
145+
146+static Terminal * find_terminal(int pid)
147+{
148+ LINK * qhp = &terms_list;
149+ LINK * qp = qhp->next;
150+
151+ while (qp != qhp) {
152+ Terminal * prs = link2term(qp);
153+ if (prs->pid == pid)
154+ return prs;
155+ qp = qp->next;
156+ }
157+ return NULL;
158+}
159+
160+static char * tid2id(int tid)
161+{
162+ static char s[64];
163+ char * p = s + sizeof(s);
164+ unsigned long n = (long) tid;
165+ *(--p) = 0;
166+ do {
167+ *(--p) = (char) (n % 10 + '0');
168+ n = n / 10;
169+ } while (n != 0);
170+
171+ *(--p) = 'T';
172+ return p;
173+}
174+
175+static int id2tid(const char * id)
176+{
177+ int tid = 0;
178+ if (id == NULL)
179+ return 0;
180+ if (id[0] != 'T')
181+ return 0;
182+ if (id[1] == 0)
183+ return 0;
184+ tid = (unsigned) strtol(id + 1, (char **) &id, 10);
185+ if (id[0] != 0)
186+ return 0;
187+ return tid;
188+}
189+
190+static void write_context(OutputStream * out, int tid)
191+{
192+ Terminal * prs = find_terminal(tid);
193+
194+ write_stream(out, '{');
195+
196+ if (prs != NULL) {
197+ if (*prs->pty_type) {
198+ json_write_string(out, "PtyType");
199+ write_stream(out, ':');
200+ json_write_string(out, prs->pty_type);
201+ write_stream(out, ',');
202+ }
203+
204+ if (*prs->encoding) {
205+ json_write_string(out, "Encoding");
206+ write_stream(out, ':');
207+ json_write_string(out, prs->encoding);
208+ write_stream(out, ',');
209+ }
210+
211+ json_write_string(out, "Width");
212+ write_stream(out, ':');
213+ json_write_ulong(out, prs->width);
214+ write_stream(out, ',');
215+
216+ json_write_string(out, "Height");
217+ write_stream(out, ':');
218+ json_write_ulong(out, prs->height);
219+ write_stream(out, ',');
220+
221+ if (*prs->inp_id) {
222+ json_write_string(out, "StdInID");
223+ write_stream(out, ':');
224+ json_write_string(out, prs->inp_id);
225+ write_stream(out, ',');
226+ }
227+ if (*prs->out_id) {
228+ json_write_string(out, "StdOutID");
229+ write_stream(out, ':');
230+ json_write_string(out, prs->out_id);
231+ write_stream(out, ',');
232+ }
233+ if (*prs->err_id) {
234+ json_write_string(out, "StdErrID");
235+ write_stream(out, ':');
236+ json_write_string(out, prs->err_id);
237+ write_stream(out, ',');
238+ }
239+ }
240+
241+ json_write_string(out, "ID");
242+ write_stream(out, ':');
243+ json_write_string(out, tid2id(tid));
244+
245+ write_stream(out, '}');
246+}
247+
248+static void send_event_terminal_exited(OutputStream * out, Terminal * prs)
249+{
250+ write_stringz(out, "E");
251+ write_stringz(out, TERMINALS);
252+ write_stringz(out, "exited");
253+
254+ json_write_string(out, tid2id(prs->pid));
255+ write_stream(out, 0);
256+
257+ json_write_ulong(out, prs->exit_code);
258+ write_stream(out, 0);
259+
260+ write_stream(out, MARKER_EOM);
261+}
262+
263+static void send_event_terminal_win_size_changed(OutputStream * out,
264+ Terminal * prs)
265+{
266+ write_stringz(out, "E");
267+ write_stringz(out, TERMINALS);
268+ write_stringz(out, "winSizeChanged");
269+
270+ json_write_string(out, tid2id(prs->pid));
271+ write_stream(out, 0);
272+
273+ json_write_long(out, prs->width);
274+ write_stream(out, 0);
275+
276+ json_write_long(out, prs->height);
277+ write_stream(out, 0);
278+
279+ write_stream(out, MARKER_EOM);
280+}
281+
282+static int kill_term(Terminal *term)
283+{
284+ int err = 0;
285+
286+#if defined(WIN32)
287+ HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, term->pid);
288+ if (h == NULL)
289+ {
290+ err = set_win32_errno(GetLastError());
291+ }
292+ else
293+ {
294+ if (!TerminateProcess(h, 1)) err = set_win32_errno(GetLastError());
295+ if (!CloseHandle(h) && !err) err = set_win32_errno(GetLastError());
296+ }
297+#else
298+ if (kill(term->pid, SIGTERM) < 0)
299+ err = errno;
300+#endif
301+ return err;
302+}
303+
304+static void command_exit(char * token, Channel * c)
305+{
306+ int err = 0;
307+ char id[256];
308+ unsigned tid;
309+ Terminal *term = NULL;
310+
311+ json_read_string(&c->inp, id, sizeof(id));
312+ if (read_stream(&c->inp) != 0)
313+ exception(ERR_JSON_SYNTAX);
314+ if (read_stream(&c->inp) != MARKER_EOM)
315+ exception(ERR_JSON_SYNTAX);
316+
317+ tid = id2tid(id);
318+ write_stringz(&c->out, "R");
319+ write_stringz(&c->out, token);
320+
321+ if (tid == 0) {
322+ err = ERR_INV_CONTEXT;
323+ } else {
324+ term = find_terminal(tid);
325+ if (term == NULL) {
326+ err = ERR_INV_CONTEXT;
327+ } else {
328+ err = kill_term(term);
329+ }
330+ }
331+
332+ write_errno(&c->out, err);
333+ write_stream(&c->out, MARKER_EOM);
334+}
335+
336+static void terminal_exited(Terminal * prs)
337+{
338+ Trap trap;
339+
340+ if (set_trap(&trap)) {
341+ send_event_terminal_exited(&prs->bcg->out, prs);
342+ clear_trap(&trap);
343+ } else {
344+ trace(LOG_ALWAYS, "Exception sending terminal exited event: %d %s",
345+ trap.error, errno_to_str(trap.error));
346+ }
347+
348+#if defined(_WRS_KERNEL)
349+ semTake(prs_list_lock, WAIT_FOREVER);
350+#endif
351+ list_remove(&prs->link);
352+ close(prs->inp);
353+ close(prs->out);
354+ if (prs->out != prs->err)
355+ close(prs->err);
356+ if (prs->inp_struct) {
357+ TerminalInput * inp = prs->inp_struct;
358+ if (!inp->req_posted) {
359+ virtual_stream_delete(inp->vstream);
360+ loc_free(inp);
361+ } else {
362+ inp->prs = NULL;
363+ }
364+ }
365+ if (prs->out_struct)
366+ prs->out_struct->prs = NULL;
367+ if (prs->err_struct)
368+ prs->err_struct->prs = NULL;
369+ loc_free(prs);
370+#if defined(_WRS_KERNEL)
371+ semGive(prs_list_lock);
372+#endif
373+}
374+
375+static void terminal_input_streams_callback(VirtualStream * stream,
376+ int event_code, void * args)
377+{
378+ TerminalInput * inp = (TerminalInput *) args;
379+
380+ assert(inp->vstream == stream);
381+ if (!inp->req_posted) {
382+ if (inp->buf_pos >= inp->buf_len && !inp->eos) {
383+ inp->buf_pos = inp->buf_len = 0;
384+ virtual_stream_get_data(stream, inp->buf, sizeof(inp->buf),
385+ &inp->buf_len, &inp->eos);
386+ }
387+ if (inp->buf_pos < inp->buf_len) {
388+ inp->req.u.fio.bufp = inp->buf + inp->buf_pos;
389+ inp->req.u.fio.bufsz = inp->buf_len - inp->buf_pos;
390+ inp->req_posted = 1;
391+ async_req_post(&inp->req);
392+ }
393+ }
394+}
395+
396+static void write_terminal_input_done(void * x)
397+{
398+ AsyncReqInfo * req = (AsyncReqInfo *) x;
399+ TerminalInput * inp = (TerminalInput *) req->client_data;
400+
401+ inp->req_posted = 0;
402+ if (inp->prs == NULL) {
403+ /* Process has exited */
404+ virtual_stream_delete(inp->vstream);
405+ loc_free(inp);
406+ } else {
407+ int wr = inp->req.u.fio.rval;
408+
409+ if (wr < 0) {
410+ int err = inp->req.error;
411+ trace(LOG_ALWAYS, "Can't write terminal input stream: %d %s", err,
412+ errno_to_str(err));
413+ inp->buf_pos = inp->buf_len = 0;
414+ } else {
415+ inp->buf_pos += wr;
416+ }
417+
418+ terminal_input_streams_callback(inp->vstream, 0, inp);
419+ }
420+}
421+
422+static void write_terminal_input(Terminal * prs)
423+{
424+ TerminalInput * inp = prs->inp_struct = (TerminalInput *) loc_alloc_zero(
425+ sizeof(TerminalInput));
426+ inp->prs = prs;
427+ inp->req.client_data = inp;
428+ inp->req.done = write_terminal_input_done;
429+ inp->req.type = AsyncReqWrite;
430+ inp->req.u.fio.fd = prs->inp;
431+ virtual_stream_create(TERMINALS, tid2id(prs->pid), PIPE_SIZE,
432+ VS_ENABLE_REMOTE_WRITE, terminal_input_streams_callback, inp,
433+ &inp->vstream);
434+ virtual_stream_get_id(inp->vstream, prs->inp_id, sizeof(prs->inp_id));
435+}
436+
437+static void terminal_output_streams_callback(VirtualStream * stream,
438+ int event_code, void * args)
439+{
440+ TerminalOutput * out = (TerminalOutput *) args;
441+
442+ assert(out->vstream == stream);
443+ if (!out->req_posted) {
444+ int buf_len = out->req.u.fio.rval;
445+ int err = 0;
446+ int eos = 0;
447+
448+ if (buf_len < 0) {
449+ buf_len = 0;
450+ err = out->req.error;
451+ }
452+ if (buf_len == 0)
453+ eos = 1;
454+ if (out->prs == NULL) {
455+ eos = 1;
456+ err = 0;
457+ }
458+
459+ assert(buf_len <= (int)sizeof(out->buf));
460+ assert(out->buf_pos <= (size_t)buf_len);
461+ assert(out->req.u.fio.bufp == out->buf);
462+#ifdef __linux__
463+ if (err == EIO)
464+ err = 0;
465+#endif
466+ if (err)
467+ trace(LOG_ALWAYS, "Can't read terminal output stream: %d %s", err,
468+ errno_to_str(err));
469+
470+ if (out->buf_pos < (size_t) buf_len || out->eos != eos) {
471+ size_t done = 0;
472+ virtual_stream_add_data(stream, out->buf + out->buf_pos, buf_len
473+ - out->buf_pos, &done, eos);
474+ out->buf_pos += done;
475+ if (eos)
476+ out->eos = 1;
477+ }
478+
479+ if (out->buf_pos >= (size_t) buf_len) {
480+ if (!eos) {
481+ out->req_posted = 1;
482+ async_req_post(&out->req);
483+ } else if (virtual_stream_is_empty(stream)) {
484+ if (out->prs != NULL) {
485+ if (out == out->prs->out_struct)
486+ out->prs->out_struct = NULL;
487+ if (out == out->prs->err_struct)
488+ out->prs->err_struct = NULL;
489+ }
490+ virtual_stream_delete(stream);
491+ loc_free(out);
492+ }
493+ }
494+ } // end if(!out->req_posted)
495+}
496+
497+static void read_terminal_output_done(void * x)
498+{
499+ AsyncReqInfo * req = (AsyncReqInfo *) x;
500+ TerminalOutput * out = (TerminalOutput *) req->client_data;
501+
502+ out->buf_pos = 0;
503+ out->req_posted = 0;
504+ terminal_output_streams_callback(out->vstream, 0, out);
505+}
506+
507+static TerminalOutput * read_terminal_output(Terminal * prs, int fd, char * id,
508+ size_t id_size)
509+{
510+ TerminalOutput * out = (TerminalOutput *) loc_alloc_zero(
511+ sizeof(TerminalOutput));
512+ out->prs = prs;
513+ out->req.client_data = out;
514+ out->req.done = read_terminal_output_done;
515+ out->req.type = AsyncReqRead;
516+ out->req.u.fio.bufp = out->buf;
517+ out->req.u.fio.bufsz = sizeof(out->buf);
518+ out->req.u.fio.fd = fd;
519+ virtual_stream_create(TERMINALS, tid2id(prs->pid), PIPE_SIZE,
520+ VS_ENABLE_REMOTE_READ, terminal_output_streams_callback, out,
521+ &out->vstream);
522+ virtual_stream_get_id(out->vstream, id, id_size);
523+ out->req_posted = 1;
524+ async_req_post(&out->req);
525+ return out;
526+}
527+
528+static char **envp_add(char **old_envp, int old_envp_len, char *env)
529+{
530+ char **new_envp = NULL;
531+ int i;
532+ int env_size;
533+ int old_envp_size;
534+
535+ assert(old_envp || (old_envp==NULL && old_envp_len==0));
536+ assert(env);
537+ assert(*env);
538+
539+ for (i = 0, old_envp_size = 0; i < old_envp_len; i++) {
540+ old_envp_size += sizeof(char *); //size of env pointer
541+ old_envp_size += strlen(old_envp[i]) + 1; //size of env string, including trailing '\0'
542+ }
543+ assert((old_envp && old_envp[i]==NULL) || (old_envp==NULL));
544+ old_envp_size += sizeof(char *);//last null pointer
545+
546+ env_size = strlen(env); //new env string size
547+
548+ new_envp = loc_alloc(old_envp_size + sizeof(char *) + env_size + 1);
549+ if (new_envp != NULL) {
550+ new_envp[0] = (char *) new_envp + old_envp_size + sizeof(char *); //setting new env ptr
551+ strcpy(new_envp[0], env); //copy new env string
552+ if (old_envp) {
553+ memcpy(&new_envp[1], old_envp, old_envp_size); //copy old envp
554+ } else {
555+ new_envp[1] = NULL;
556+ }
557+ }
558+ return new_envp;
559+}
560+
561+static int start_terminal(Channel * c, char *pty_type, char *encoding,
562+ char ** envp, int envp_len, char * exe, char ** args, int *pid,
563+ Terminal ** prs)
564+{
565+ int err = 0;
566+ int fd_tty_master = -1;
567+ char * tty_slave_name = NULL;
568+ struct winsize size;
569+ char **newenvp = envp;
570+
571+ memset(&size, 0, sizeof(struct winsize));
572+ fd_tty_master = posix_openpt(O_RDWR | O_NOCTTY);
573+ if (fd_tty_master < 0 || grantpt(fd_tty_master) < 0 || unlockpt(
574+ fd_tty_master) < 0)
575+ err = errno;
576+ if (!err) {
577+ tty_slave_name = ptsname(fd_tty_master);
578+ if (tty_slave_name == NULL)
579+ err = EINVAL;
580+ }
581+
582+ if (ioctl(fd_tty_master, TIOCGWINSZ, (char *) &size) < 0)
583+ err = errno;
584+
585+ if (!err && fd_tty_master < 3) {
586+ int fd0 = fd_tty_master;
587+ if ((fd_tty_master = dup(fd_tty_master)) < 0 || close(fd0))
588+ err = errno;
589+ }
590+
591+ if (!err) {
592+ *pid = fork();
593+ if (*pid < 0)
594+ err = errno;
595+ if (*pid == 0) {
596+ int fd = -1;
597+ int fd_tty_slave = -1;
598+
599+ if (*pty_type) {
600+ char env_term[TERM_PROP_DEF_SIZE];
601+ snprintf(env_term, sizeof(env_term), "TERM=%s", pty_type);
602+ newenvp = envp_add(envp, envp_len, env_term);
603+ if (newenvp == NULL) {
604+ err = ENOMEM;
605+ } else if (envp) {
606+ loc_free(envp);
607+ envp = NULL;
608+ }
609+ }
610+
611+ setsid();
612+
613+ if (!err && (fd = sysconf(_SC_OPEN_MAX)) < 0)
614+ err = errno;
615+ if (!err && (fd_tty_slave = open(tty_slave_name, O_RDWR)) < 0)
616+ err = errno;
617+#if defined(TIOCSCTTY)
618+ if (!err && (ioctl(fd_tty_slave, TIOCSCTTY, (char *) 0)) < 0)
619+ err = errno;
620+#endif
621+ if (!err && dup2(fd_tty_slave, 0) < 0)
622+ err = errno;
623+ if (!err && dup2(fd_tty_slave, 1) < 0)
624+ err = errno;
625+ if (!err && dup2(fd_tty_slave, 2) < 0)
626+ err = errno;
627+ while (!err && fd > 3)
628+ close(--fd);
629+ if (!err) {
630+ execve(exe, args, newenvp);
631+ err = errno;
632+ }
633+ if (newenvp)
634+ loc_free(newenvp);
635+ err = 1;
636+ if (err < 1)
637+ err = EINVAL;
638+ else if (err > 0xff)
639+ err = EINVAL;
640+ exit(err);
641+ }
642+ }
643+
644+ if (!err) {
645+ *prs = (Terminal *) loc_alloc_zero(sizeof(Terminal));
646+ (*prs)->inp = fd_tty_master;
647+ (*prs)->out = fd_tty_master;
648+ (*prs)->err = fd_tty_master;
649+ (*prs)->pid = *pid;
650+ (*prs)->bcg = c->bcg;
651+ (*prs)->channel = c;
652+ if (*pty_type)
653+ snprintf((*prs)->pty_type, sizeof((*prs)->pty_type), "%s", pty_type);
654+ if (*encoding)
655+ snprintf((*prs)->encoding, sizeof((*prs)->encoding), "%s", encoding);
656+ (*prs)->width = size.ws_row;
657+ (*prs)->height = size.ws_col;
658+ list_add_first(&(*prs)->link, &terms_list);
659+ }
660+
661+ if (!err)
662+ return 0;
663+ errno = err;
664+ return -1;
665+}
666+
667+static void command_get_context(char * token, Channel * c)
668+{
669+ int err = 0;
670+ char id[256];
671+ int tid;
672+ Terminal *term;
673+
674+ json_read_string(&c->inp, id, sizeof(id));
675+ if (read_stream(&c->inp) != 0)
676+ exception(ERR_JSON_SYNTAX);
677+ if (read_stream(&c->inp) != MARKER_EOM)
678+ exception(ERR_JSON_SYNTAX);
679+
680+ tid = id2tid(id);
681+ write_stringz(&c->out, "R");
682+ write_stringz(&c->out, token);
683+
684+ if (tid == 0) {
685+ err = ERR_INV_CONTEXT;
686+ } else {
687+ term = find_terminal(tid);
688+ if (term == NULL) {
689+ err = ERR_INV_CONTEXT;
690+ } else {
691+ write_context(&c->out, tid);
692+ write_stream(&c->out, 0);
693+ }
694+ }
695+
696+ write_errno(&c->out, err);
697+ write_stream(&c->out, MARKER_EOM);
698+}
699+
700+static void command_launch(char * token, Channel * c)
701+{
702+ int pid = 0;
703+ int err = 0;
704+ char encoding[TERM_PROP_DEF_SIZE];
705+ char pty_type[TERM_PROP_DEF_SIZE];
706+ char *args[] = TERM_LAUNCH_ARGS;
707+
708+ char ** envp = NULL;
709+ int envp_len = 0;
710+
711+ Terminal * prs = NULL;
712+ Trap trap;
713+
714+ if (set_trap(&trap)) {
715+ json_read_string(&c->inp, pty_type, sizeof(pty_type));
716+ if (read_stream(&c->inp) != 0)
717+ exception(ERR_JSON_SYNTAX);
718+ json_read_string(&c->inp, encoding, sizeof(encoding));
719+ if (read_stream(&c->inp) != 0)
720+ exception(ERR_JSON_SYNTAX);
721+ envp = json_read_alloc_string_array(&c->inp, &envp_len);
722+ if (read_stream(&c->inp) != 0)
723+ exception(ERR_JSON_SYNTAX);
724+ if (read_stream(&c->inp) != MARKER_EOM)
725+ exception(ERR_JSON_SYNTAX);
726+
727+ if (err == 0 && start_terminal(c, pty_type, encoding, envp, envp_len,
728+ TERM_LAUNCH_EXEC, args, &pid, &prs) < 0)
729+ err = errno;
730+ if (prs != NULL) {
731+ write_terminal_input(prs);
732+ prs->out_struct = read_terminal_output(prs, prs->out, prs->out_id,
733+ sizeof(prs->out_id));
734+ if (prs->out != prs->err)
735+ prs->err_struct = read_terminal_output(prs, prs->err,
736+ prs->err_id, sizeof(prs->err_id));
737+ }
738+ if (!err) {
739+ add_waitpid_process(pid);
740+ }
741+ //write result back
742+ {
743+ write_stringz(&c->out, "R");
744+ write_stringz(&c->out, token);
745+ write_errno(&c->out, err);
746+ if (err || pid == 0) {
747+ write_stringz(&c->out, "null");
748+ } else {
749+ write_context(&c->out, pid);
750+ write_stream(&c->out, 0);
751+ }
752+ write_stream(&c->out, MARKER_EOM);
753+ }
754+ clear_trap(&trap);
755+ }
756+
757+ loc_free(envp);
758+
759+ if (trap.error)
760+ exception(trap.error);
761+}
762+
763+static void command_set_win_size(char * token, Channel * c)
764+{
765+ int err = 0;
766+ struct winsize size;
767+ char id[256];
768+ unsigned tid;
769+ Terminal *term = NULL;
770+
771+ json_read_string(&c->inp, id, sizeof(id));
772+ if (read_stream(&c->inp) != 0)
773+ exception(ERR_JSON_SYNTAX);
774+ size.ws_col=json_read_ulong(&c->inp);
775+ if (read_stream(&c->inp) != 0)
776+ exception(ERR_JSON_SYNTAX);
777+ size.ws_row=json_read_ulong(&c->inp);
778+ if (read_stream(&c->inp) != 0)
779+ exception(ERR_JSON_SYNTAX);
780+ if (read_stream(&c->inp) != MARKER_EOM)
781+ exception(ERR_JSON_SYNTAX);
782+
783+ tid = id2tid(id);
784+
785+ if(tid==0 || (term=find_terminal(tid))==NULL) {
786+ err=ERR_INV_CONTEXT;
787+ }else if (term->width != size.ws_col || term->height != size.ws_row) {
788+ if(ioctl(term->inp,TIOCSWINSZ,&size)<0) {
789+ err=errno;
790+ }
791+ if(!err) {
792+ term->width=size.ws_col;
793+ term->height=size.ws_row;
794+ send_event_terminal_win_size_changed(&term->channel->out,term);
795+ }
796+ }
797+
798+ write_stringz(&c->out, "R");
799+ write_stringz(&c->out, token);
800+ write_errno(&c->out, err);
801+ write_stream(&c->out, MARKER_EOM);
802+
803+}
804+
805+static void waitpid_listener(int pid, int exited, int exit_code, int signal,
806+ int event_code, int syscall, void * args)
807+{
808+ if (exited) {
809+ Terminal * prs = find_terminal(pid);
810+ if (prs) {
811+ if (signal != 0)
812+ prs->exit_code = -signal;
813+ else
814+ prs->exit_code = exit_code;
815+ terminal_exited(prs);
816+ }
817+ }
818+}
819+
820+static void channel_close_listener(Channel * c)
821+{
822+ LINK * l = NULL;
823+
824+ for (l = terms_list.next; l != &terms_list;) {
825+ Terminal * term = link2term(l);
826+ l = l->next;
827+ if (term->channel == c) {
828+ trace(LOG_ALWAYS, "Terminal is left launched: T%d", term->pid);
829+ kill_term(term);
830+ }
831+ }
832+}
833+
834+void ini_terminals_service(Protocol * proto)
835+{
836+#if defined(_WRS_KERNEL)
837+ prs_list_lock = semMCreate(SEM_Q_PRIORITY);
838+ if (prs_list_lock == NULL) check_error(errno);
839+ if (taskCreateHookAdd((FUNCPTR)task_create_hook) != OK) check_error(errno);
840+ if (taskDeleteHookAdd((FUNCPTR)task_delete_hook) != OK) check_error(errno);
841+#endif
842+ list_init(&terms_list);
843+
844+ add_waitpid_listener(waitpid_listener, NULL);
845+ add_channel_close_listener(channel_close_listener);
846+
847+ add_command_handler(proto, TERMINALS, "getContext", command_get_context);
848+ add_command_handler(proto, TERMINALS, "launch", command_launch);
849+ add_command_handler(proto, TERMINALS, "exit", command_exit);
850+ add_command_handler(proto, TERMINALS, "setWinSize", command_set_win_size);
851+}
852Index: org.eclipse.tm.tcf.terminals.agent/main/services-ext.h
853===================================================================
854--- org.eclipse.tm.tcf.terminals.agent/main/services-ext.h (revision 0)
855+++ org.eclipse.tm.tcf.terminals.agent/main/services-ext.h (revision 0)
856@@ -0,0 +1,25 @@
857+/*******************************************************************************
858+ * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
859+ * All rights reserved. This program and the accompanying materials
860+ * are made available under the terms of the Eclipse Public License v1.0
861+ * and Eclipse Distribution License v1.0 which accompany this distribution.
862+ * The Eclipse Public License is available at
863+ * http://www.eclipse.org/legal/epl-v10.html
864+ * and the Eclipse Distribution License is available at
865+ * http://www.eclipse.org/org/documents/edl-v10.php.
866+ *
867+ * Contributors:
868+ * Wind River Systems - initial API and implementation
869+ *******************************************************************************/
870+
871+/*
872+ * Services initialization code extension point.
873+ * If the agent is built with additional user-defined services,
874+ * a customized version of services-ext.h file can be added to compiler headers search paths.
875+ */
876+
877+#include "terminals.h"
878+
879+static void ini_ext_services(Protocol * proto, TCFBroadcastGroup * bcg) {
880+ ini_terminals_service(proto);
881+}
882Index: org.eclipse.tm.tcf.terminals.agent/terminals.h
883===================================================================
884--- org.eclipse.tm.tcf.terminals.agent/terminals.h (revision 0)
885+++ org.eclipse.tm.tcf.terminals.agent/terminals.h (revision 0)
886@@ -0,0 +1,27 @@
887+/*******************************************************************************
888+ * Copyright (c) 2008 Wind River Systems, Inc. and others.
889+ * All rights reserved. This program and the accompanying materials
890+ * are made available under the terms of the Eclipse Public License v1.0
891+ * and Eclipse Distribution License v1.0 which accompany this distribution.
892+ * The Eclipse Public License is available at
893+ * http://www.eclipse.org/legal/epl-v10.html
894+ * and the Eclipse Distribution License is available at
895+ * http://www.eclipse.org/org/documents/edl-v10.php.
896+ *
897+ * Contributors:
898+ * Wind River Systems - initial API and implementation
899+ *******************************************************************************/
900+
901+/*
902+ * Sample TCF service header file.
903+ */
904+
905+#ifndef TERMINALS_H_
906+#define TERMINALS_H_
907+
908+#include <config.h>
909+#include <framework/protocol.h>
910+
911+extern void ini_terminals_service(Protocol * proto);
912+
913+#endif /*TERMINALS_H_*/
914Index: org.eclipse.tm.tcf.terminals.agent/config.h
915===================================================================
916--- org.eclipse.tm.tcf.terminals.agent/config.h (revision 0)
917+++ org.eclipse.tm.tcf.terminals.agent/config.h (revision 0)
918@@ -0,0 +1,63 @@
919+/*******************************************************************************
920+ * Copyright (c) 2008 Wind River Systems, Inc. and others.
921+ * All rights reserved. This program and the accompanying materials
922+ * are made available under the terms of the Eclipse Public License v1.0
923+ * and Eclipse Distribution License v1.0 which accompany this distribution.
924+ * The Eclipse Public License is available at
925+ * http://www.eclipse.org/legal/epl-v10.html
926+ * and the Eclipse Distribution License is available at
927+ * http://www.eclipse.org/org/documents/edl-v10.php.
928+ *
929+ * Contributors:
930+ * Wind River Systems - initial API and implementation
931+ *******************************************************************************/
932+
933+/*
934+ * This file contains "define" statements that control agent configuration.
935+ * SERVICE_* definitions control which service implementations are included into the agent.
936+ *
937+ * This is example agent configuration. It includes only few standard services,
938+ * and one example service: Day Time.
939+ */
940+
941+#ifndef D_config
942+#define D_config
943+
944+#include <framework/mdep.h>
945+
946+#if defined(WIN32) || defined(__CYGWIN__)
947+# define TARGET_UNIX 0
948+#elif defined(_WRS_KERNEL)
949+# define TARGET_UNIX 0
950+#else
951+# define TARGET_UNIX 1
952+#endif
953+
954+#define SERVICE_Locator 1
955+#define SERVICE_Processes 1
956+#define SERVICE_Streams 1
957+#define SERVICE_FileSystem 1
958+#define SERVICE_SysMonitor TARGET_UNIX
959+
960+#define ENABLE_ZeroCopy 1
961+
962+#if !defined(ENABLE_Splice)
963+# if ENABLE_ZeroCopy
964+# include <fcntl.h>
965+# if defined(SPLICE_F_MOVE)
966+# define ENABLE_Splice 1
967+# else
968+# define ENABLE_Splice 0
969+# endif
970+# else
971+# define ENABLE_Splice 0
972+# endif
973+#endif
974+
975+#define ENABLE_SSL 0
976+
977+#define ENABLE_Trace 1
978+#define ENABLE_Discovery 1
979+
980+
981+#endif /* D_config */
982Index: org.eclipse.tm.tcf.terminals.agent/Makefile
983===================================================================
984--- org.eclipse.tm.tcf.terminals.agent/Makefile (revision 0)
985+++ org.eclipse.tm.tcf.terminals.agent/Makefile (revision 0)
986@@ -0,0 +1,39 @@
987+TCF_AGENT_DIR=../agent
988+
989+include $(TCF_AGENT_DIR)/Makefile.inc
990+
991+override CFLAGS += $(foreach dir,$(INCDIRS),-I$(dir)) $(OPTS)
992+
993+HFILES := $(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.h)) $(HFILES)
994+CFILES := $(sort $(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.c)) $(CFILES))
995+
996+#no using SSL
997+LIBS = -lpthread -lrt
998+
999+EXECS = $(BINDIR)/agent$(EXTEXE)
1000+
1001+all: $(EXECS)
1002+
1003+$(BINDIR)/libtcf$(EXTLIB) : $(OFILES)
1004+ $(AR) rcs $@ $^
1005+
1006+$(BINDIR)/agent$(EXTEXE): $(BINDIR)/main/main$(EXTOBJ) $(BINDIR)/libtcf$(EXTLIB)
1007+ $(CC) $(CFLAGS) -o $@ $(BINDIR)/main/main$(EXTOBJ) $(BINDIR)/libtcf$(EXTLIB) $(LIBS)
1008+
1009+$(BINDIR)/%$(EXTOBJ): %.c $(HFILES) Makefile
1010+ @mkdir -p $(dir $@)
1011+ $(CC) $(CFLAGS) -c -o $@ $<
1012+
1013+$(BINDIR)/%$(EXTOBJ): $(TCF_AGENT_DIR)/%.c $(HFILES) Makefile
1014+ @mkdir -p $(dir $@)
1015+ $(CC) $(CFLAGS) -c -o $@ $<
1016+
1017+install: all
1018+ install -d -m 755 $(INSTALLROOT)$(SBIN)
1019+ install -d -m 755 $(INSTALLROOT)$(INIT)
1020+ install -c $(BINDIR)/agent -m 755 $(INSTALLROOT)$(SBIN)/tcf-agent
1021+ install -c $(TCF_AGENT_DIR)/main/tcf-agent.init -m 755 $(INSTALLROOT)$(INIT)/tcf-agent
1022+
1023+clean:
1024+ rm -rf $(BINDIR)
1025+