1 /***************************************************************************
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
24 #include "tcl_server.h"
27 #define TCL_SERVER_VERSION "TCL Server 0.1"
28 #define TCL_MAX_LINE (4096)
30 typedef struct tcl_connection_s
{
33 char tc_line
[TCL_MAX_LINE
];
34 int tc_outerror
; /* flag an output error */
37 static unsigned short tcl_port
= 6666;
40 static int handle_tcl_port_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
43 static int tcl_new_connection(connection_t
*connection
);
44 static int tcl_input(connection_t
*connection
);
45 static int tcl_output(connection_t
*connection
, const void *buf
, ssize_t len
);
46 static int tcl_closed(connection_t
*connection
);
48 /* write data out to a socket.
50 * this is a blocking write, so the return value must equal the length, if
51 * that is not the case then flag the connection with an output error.
53 int tcl_output(connection_t
*connection
, const void *data
, ssize_t len
)
56 tcl_connection_t
*tclc
;
58 tclc
= connection
->priv
;
59 if (tclc
->tc_outerror
)
60 return ERROR_SERVER_REMOTE_CLOSED
;
62 wlen
= write_socket(connection
->fd
, data
, len
);
66 LOG_ERROR("error during write: %d != %d", (int)wlen
, (int)len
);
67 tclc
->tc_outerror
= 1;
68 return ERROR_SERVER_REMOTE_CLOSED
;
72 static int tcl_new_connection(connection_t
*connection
)
74 tcl_connection_t
*tclc
;
76 tclc
= malloc(sizeof(tcl_connection_t
));
78 return ERROR_CONNECTION_REJECTED
;
80 memset(tclc
, 0, sizeof(tcl_connection_t
));
81 connection
->priv
= tclc
;
85 static int tcl_input(connection_t
*connection
)
92 tcl_connection_t
*tclc
;
95 rlen
= read_socket(connection
->fd
, &in
, sizeof(in
));
98 LOG_ERROR("error during read: %s", strerror(errno
));
99 return ERROR_SERVER_REMOTE_CLOSED
;
102 tclc
= connection
->priv
;
104 return ERROR_CONNECTION_REJECTED
;
106 /* push as much data into the line as possible */
107 for (i
= 0; i
< rlen
; i
++)
109 if (!isprint(in
[i
]) && !isspace(in
[i
]))
112 tclc
->tc_linedrop
= 1;
116 /* buffer the data */
117 tclc
->tc_line
[tclc
->tc_lineoffset
] = in
[i
];
118 if (tclc
->tc_lineoffset
< TCL_MAX_LINE
)
119 tclc
->tc_lineoffset
++;
121 tclc
->tc_linedrop
= 1;
126 /* process the line */
127 if (tclc
->tc_linedrop
) {
128 #define ESTR "line too long\n"
129 retval
= tcl_output(connection
, ESTR
, sizeof(ESTR
));
130 if (retval
!= ERROR_OK
)
135 tclc
->tc_line
[tclc
->tc_lineoffset
-1] = '\0';
136 retval
= Jim_Eval_Named(interp
, tclc
->tc_line
, "remote:connection",1);
137 result
= Jim_GetString(Jim_GetResult(interp
), &reslen
);
138 retval
= tcl_output(connection
, result
, reslen
);
139 if (retval
!= ERROR_OK
)
141 if (memchr(result
, '\n', reslen
) == NULL
)
142 tcl_output(connection
, "\n", 1);
145 tclc
->tc_lineoffset
= 0;
146 tclc
->tc_linedrop
= 0;
152 static int tcl_closed(connection_t
*connection
)
154 /* cleanup connection context */
155 if (connection
->priv
) {
156 free(connection
->priv
);
157 connection
->priv
= NULL
;
168 LOG_INFO("tcl port disabled");
172 retval
= add_service("tcl", CONNECTION_TCP
, tcl_port
, 1, tcl_new_connection
, tcl_input
, tcl_closed
, NULL
);
176 int tcl_register_commands(command_context_t
*cmd_ctx
)
178 register_command(cmd_ctx
, NULL
, "tcl_port", handle_tcl_port_command
, COMMAND_CONFIG
, "port on which to listen for incoming TCL syntax");
182 static int handle_tcl_port_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
185 tcl_port
= strtoul(args
[0], NULL
, 0);