2 * Simulator of microcontrollers (cmd.src/newcmdposix.cc)
\r
4 * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
\r
5 * Copyright (C) 2006, Borut Razem - borut.razem@siol.net
\r
7 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
\r
11 /* This file is part of microcontroller simulator: ucsim.
\r
13 UCSIM is free software; you can redistribute it and/or modify
\r
14 it under the terms of the GNU General Public License as published by
\r
15 the Free Software Foundation; either version 2 of the License, or
\r
16 (at your option) any later version.
\r
18 UCSIM is distributed in the hope that it will be useful,
\r
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
21 GNU General Public License for more details.
\r
23 You should have received a copy of the GNU General Public License
\r
24 along with UCSIM; see the file COPYING. If not, write to the Free
\r
25 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
\r
29 #include "ddconfig.h"
\r
35 #include <sys/types.h>
\r
36 #include <sys/time.h>
\r
38 # include HEADER_SOCKET
\r
39 # if defined HAVE_SYS_SOCKET_H
\r
40 # include <netinet/in.h>
\r
41 # include <arpa/inet.h>
\r
48 #ifdef HAVE_UNISTD_H
\r
49 # include <unistd.h>
\r
51 #include "i_string.h"
\r
53 #include "cmdlexcl.h"
\r
54 #include "cmdpars.h"
\r
57 #include "globals.h"
\r
66 #include "newcmdposixcl.h"
\r
71 *____________________________________________________________________________
\r
74 cl_console::cl_console(char *fin, char *fout, class cl_app *the_app)
\r
81 if (f= fopen(fin, "r"), in= f, !f)
\r
82 fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
\r
85 if (f= fopen(fout, "w"), out= f, !f)
\r
86 fprintf(stderr, "Can't open `%s': %s\n", fout, strerror(errno));
\r
90 flags|= CONS_INTERACTIVE;
\r
92 ;//fprintf(stderr, "Warning: non-interactive console\n");
\r
95 lines_printed= new cl_ustrings(100, 100, "console_cache");
\r
98 cl_console::cl_console(FILE *fin, FILE *fout, class cl_app *the_app)
\r
106 flags|= CONS_INTERACTIVE;
\r
108 ;//fprintf(stderr, "Warning: non-interactive console\n");
\r
111 lines_printed= new cl_ustrings(100, 100, "console_cache");
\r
115 cl_console::clone_for_exec(char *fin)
\r
117 FILE *fi= 0, *fo= 0;
\r
121 if (fi= fopen(fin, "r"), !fi)
\r
123 fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
\r
126 if ((fo= fdopen(dup(fileno(out)), "a")) == 0)
\r
129 fprintf(stderr, "Can't re-open output file: %s\n", strerror(errno));
\r
132 class cl_console *con= new cl_sub_console(this, fi, fo, app);
\r
136 cl_console::~cl_console(void)
\r
143 if (flags & CONS_PROMPT)
\r
144 fprintf(out, "\n");
\r
148 delete prompt_option;
\r
149 delete null_prompt_option;
\r
150 delete debug_option;
\r
151 #ifdef SOCKET_AVAIL
\r
166 cl_console::redirect(char *fname, char *mode)
\r
168 if ((rout= fopen(fname, mode)) == NULL)
\r
169 dd_printf("Unable to open file '%s' for %s: %s\n",
\r
170 fname, (mode[0]=='w')?"write":"append", strerror(errno));
\r
174 cl_console::un_redirect(void)
\r
183 cl_console::cmd_do_print(char *format, va_list ap)
\r
186 FILE *f = get_out();
\r
190 ret= vfprintf(f, format, ap);
\r
204 cl_console::read_line(void)
\r
208 #ifdef HAVE_GETLINE
\r
209 if (getline(&s, 0, in) < 0)
\r
211 #elif defined HAVE_GETDELIM
\r
213 s= (char *)malloc(n);
\r
214 if (getdelim(&s, &n, '\n', in) < 0)
\r
219 #elif defined HAVE_FGETS
\r
220 s= (char *)malloc(300);
\r
221 if (fgets(s, 300, in) == NULL)
\r
227 s[strlen(s)-1]= '\0';
\r
228 if (s[strlen(s)-1] == '\r')
\r
229 s[strlen(s)-1]= '\0';
\r
230 flags&= ~CONS_PROMPT;
\r
236 * This console listen on a socket and can accept connection requests
\r
238 #ifdef SOCKET_AVAIL
\r
240 cl_listen_console::cl_listen_console(int serverport, class cl_app *the_app)
\r
243 if ((sock= make_server_socket(serverport)) >= 0)
\r
245 if (listen(sock, 10) < 0)
\r
246 fprintf(stderr, "Listen on port %d: %s\n",
\r
247 serverport, strerror(errno));
\r
253 cl_listen_console::proc_input(class cl_cmdset *cmdset)
\r
256 ACCEPT_SOCKLEN_T size;
\r
257 struct sockaddr_in sock_addr;
\r
258 class cl_commander_base *cmd;
\r
261 cmd= app->get_commander();
\r
262 size= sizeof(struct sockaddr);
\r
263 newsock= accept(sock, (struct sockaddr*)&sock_addr, &size);
\r
269 if (!(in= fdopen(newsock, "r")))
\r
270 fprintf(stderr, "cannot open port for input\n");
\r
271 if (!(out= fdopen(newsock, "w")))
\r
272 fprintf(stderr, "cannot open port for output\n");
\r
273 class cl_console_base *c= new cl_console(in, out, app);
\r
274 c->flags|= CONS_INTERACTIVE;
\r
275 cmd->add_console(c);
\r
279 #endif /* SOCKET_AVAIL */
\r
286 cl_sub_console::cl_sub_console(class cl_console_base *the_parent,
\r
287 FILE *fin, FILE *fout, class cl_app *the_app):
\r
288 cl_console(fin, fout, the_app)
\r
290 parent= the_parent;
\r
293 cl_sub_console::~cl_sub_console(void)
\r
295 class cl_commander_base *c= app->get_commander();
\r
299 c->activate_console(parent);
\r
304 cl_sub_console::init(void)
\r
306 class cl_commander_base *c= app->get_commander();
\r
310 c->deactivate_console(parent);
\r
312 cl_console::init();
\r
319 * Command interpreter
\r
320 *____________________________________________________________________________
\r
324 cl_commander::init(void)
\r
326 class cl_optref console_on_option(this);
\r
327 class cl_optref config_file_option(this);
\r
328 class cl_optref port_number_option(this);
\r
329 class cl_console_base *con;
\r
331 console_on_option.init();
\r
332 console_on_option.use("console_on");
\r
333 config_file_option.init();
\r
334 config_file_option.use("config_file");
\r
335 port_number_option.init();
\r
338 set_name("Commander");
\r
340 bool need_config= DD_TRUE;
\r
342 #ifdef SOCKET_AVAIL
\r
343 if (port_number_option.use("port_number"))
\r
344 add_console(new cl_listen_console(port_number_option.get_value((long)0), app));
\r
347 /* The following code is commented out because it produces gcc warnings
\r
348 * newcmd.cc: In member function `virtual int cl_commander::init()':
\r
349 * newcmd.cc:785: warning: 'Config' might be used uninitialized in this function
\r
350 * newcmd.cc:786: warning: 'cn' might be used uninitialized in this function
\r
353 char *Config= config_file_option.get_value(Config);
\r
354 char *cn= console_on_option.get_value(cn);
\r
356 /* Here shoud probably be something else, but is still better then the former code... */
\r
357 char *Config= config_file_option.get_value("");
\r
358 char *cn= console_on_option.get_value("");
\r
362 add_console(con= new cl_console(cn, cn, app));
\r
363 exec_on(con, Config);
\r
364 need_config= DD_FALSE;
\r
366 if (cons->get_count() == 0)
\r
368 add_console(con= new cl_console(stdin, stdout, app));
\r
369 exec_on(con, Config);
\r
370 need_config= DD_FALSE;
\r
376 FILE *fc= fopen(Config, "r");
\r
378 fprintf(stderr, "Can't open `%s': %s\n", Config, strerror(errno));
\r
381 con= new cl_console(fc, stderr, app);
\r
382 con->flags|= CONS_NOWELCOME|CONS_ECHO;
\r
390 cl_commander::set_fd_set(void)
\r
394 FD_ZERO(&read_set);
\r
396 for (i = 0; i < cons->count; i++)
\r
398 class cl_console *c= dynamic_cast<class cl_console*>((class cl_console_base*)(cons->at(i)));
\r
400 if (c->input_active())
\r
402 UCSOCKET_T fd = c->get_in_fd();
\r
405 FD_SET(fd, &read_set);
\r
414 cl_commander::input_avail(void)
\r
416 struct timeval tv = {0, 0};
\r
417 active_set = read_set;
\r
419 int i = select(fd_num, &active_set, NULL, NULL, &tv);
\r
427 cl_commander::wait_input(void)
\r
430 active_set = read_set;
\r
431 int i = select(fd_num, &active_set, NULL, NULL, NULL);
\r
436 cl_commander::proc_input(void)
\r
438 for (int j = 0; j < cons->count; j++)
\r
440 class cl_console *c = dynamic_cast<class cl_console*>((class cl_console_base*)(cons->at(j)));
\r
442 if (c->input_active())
\r
444 UCSOCKET_T fd = c->get_in_fd();
\r
447 if (FD_ISSET(fd, &active_set))
\r
449 actual_console = c;
\r
450 int retval = c->proc_input(cmdset);
\r
456 actual_console = 0;
\r
457 return(0 == cons->count);
\r
465 /* End of cmd.src/newcmdposix.cc */
\r