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 struct tcl_connection
{
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 tcl_new_connection(struct connection
*connection
);
41 static int tcl_input(struct connection
*connection
);
42 static int tcl_output(struct connection
*connection
, const void *buf
, ssize_t len
);
43 static int tcl_closed(struct connection
*connection
);
45 /* write data out to a socket.
47 * this is a blocking write, so the return value must equal the length, if
48 * that is not the case then flag the connection with an output error.
50 int tcl_output(struct connection
*connection
, const void *data
, ssize_t len
)
53 struct tcl_connection
*tclc
;
55 tclc
= connection
->priv
;
56 if (tclc
->tc_outerror
)
57 return ERROR_SERVER_REMOTE_CLOSED
;
59 wlen
= write_socket(connection
->fd
, data
, len
);
63 LOG_ERROR("error during write: %d != %d", (int)wlen
, (int)len
);
64 tclc
->tc_outerror
= 1;
65 return ERROR_SERVER_REMOTE_CLOSED
;
69 static int tcl_new_connection(struct connection
*connection
)
71 struct tcl_connection
*tclc
;
73 tclc
= malloc(sizeof(struct tcl_connection
));
75 return ERROR_CONNECTION_REJECTED
;
77 memset(tclc
, 0, sizeof(struct tcl_connection
));
78 connection
->priv
= tclc
;
82 static int tcl_input(struct connection
*connection
)
84 Jim_Interp
*interp
= (Jim_Interp
*)connection
->priv
;
90 struct tcl_connection
*tclc
;
91 unsigned char in
[256];
93 rlen
= read_socket(connection
->fd
, &in
, sizeof(in
));
96 LOG_ERROR("error during read: %s", strerror(errno
));
97 return ERROR_SERVER_REMOTE_CLOSED
;
100 tclc
= connection
->priv
;
102 return ERROR_CONNECTION_REJECTED
;
104 /* push as much data into the line as possible */
105 for (i
= 0; i
< rlen
; i
++)
107 if (!isprint(in
[i
]) && !isspace(in
[i
]))
110 tclc
->tc_linedrop
= 1;
114 /* buffer the data */
115 tclc
->tc_line
[tclc
->tc_lineoffset
] = in
[i
];
116 if (tclc
->tc_lineoffset
< TCL_MAX_LINE
)
117 tclc
->tc_lineoffset
++;
119 tclc
->tc_linedrop
= 1;
124 /* process the line */
125 if (tclc
->tc_linedrop
) {
126 #define ESTR "line too long\n"
127 retval
= tcl_output(connection
, ESTR
, sizeof(ESTR
));
128 if (retval
!= ERROR_OK
)
133 tclc
->tc_line
[tclc
->tc_lineoffset
-1] = '\0';
134 retval
= Jim_Eval_Named(interp
, tclc
->tc_line
, "remote:connection",1);
135 result
= Jim_GetString(Jim_GetResult(interp
), &reslen
);
136 retval
= tcl_output(connection
, result
, reslen
);
137 if (retval
!= ERROR_OK
)
139 if (memchr(result
, '\n', reslen
) == NULL
)
140 tcl_output(connection
, "\n", 1);
143 tclc
->tc_lineoffset
= 0;
144 tclc
->tc_linedrop
= 0;
150 static int tcl_closed(struct connection
*connection
)
152 /* cleanup connection context */
153 if (connection
->priv
) {
154 free(connection
->priv
);
155 connection
->priv
= NULL
;
160 int tcl_init(struct command_context
*cmd_ctx
)
166 LOG_INFO("tcl port disabled");
170 retval
= add_service("tcl", CONNECTION_TCP
, tcl_port
, 1,
171 &tcl_new_connection
, &tcl_input
,
172 &tcl_closed
, cmd_ctx
->interp
);
176 COMMAND_HANDLER(handle_tcl_port_command
)
178 return CALL_COMMAND_HANDLER(server_port_command
, &tcl_port
);
181 static const struct command_registration tcl_command_handlers
[] = {
184 .handler
= &handle_tcl_port_command
,
185 .mode
= COMMAND_CONFIG
,
186 .help
= "port on which to listen "
187 "for incoming TCL syntax",
190 COMMAND_REGISTRATION_DONE
193 int tcl_register_commands(struct command_context
*cmd_ctx
)
195 return register_commands(cmd_ctx
, NULL
, tcl_command_handlers
);