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