* sim/ucsim/configure, sim/ucsim/cmd.src/newcmdcl.h,
[fw/sdcc] / sim / ucsim / cmd.src / newcmd.cc
1 /*
2  * Simulator of microcontrollers (cmd.src/newcmd.cc)
3  *
4  * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
5  * 
6  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
7  *
8  */
9
10 /* This file is part of microcontroller simulator: ucsim.
11
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING.  If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26 /*@1@*/
27
28 #include "ddconfig.h"
29
30 #include <stdio.h>
31 #include <errno.h>
32 #include <stdarg.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #include <sys/time.h>
36 #ifdef SOCKET_AVAIL
37 # include HEADER_SOCKET
38 # if defined HAVE_SYS_SOCKET_H
39 #  include <netinet/in.h>
40 #  include <arpa/inet.h>
41 #  include <netdb.h>
42 # endif
43 #endif
44 #if FD_HEADER_OK
45 # include HEADER_FD
46 #endif
47 #ifdef HAVE_UNISTD_H
48 # include <unistd.h>
49 #endif
50 #include "i_string.h"
51
52 #include "cmdlexcl.h"
53 #include "cmdpars.h"
54
55 // prj
56 #include "globals.h"
57 #include "utils.h"
58
59 // sim
60 #include "simcl.h"
61 #include "argcl.h"
62 #include "appcl.h"
63
64 // local
65 #include "newcmdcl.h"
66 #include "cmdutil.h"
67
68
69 extern "C" int vasprintf(char **strp, const  char *format, va_list ap);
70 extern "C" int vsnprintf(char *str, size_t size,const char *format,va_list ap);
71
72
73 /*
74  * Options of console
75  */
76
77 cl_prompt_option::cl_prompt_option(class cl_console *console):
78   cl_optref(console)
79 {
80   con= console;
81 }
82
83 int
84 cl_prompt_option::init(void)
85 {
86   char *help;
87   help= format_string("Prompt string of console%d", con->get_id());
88   create(con, string_opt, "prompt", help);
89   //fprintf(stderr," **new prompt option %p\"%s\", value=%p str=%p\n",option,object_name(option),option->get_value(),option->get_value()->sval);
90   free(help);
91   default_option("prompt");
92   //fprintf(stderr,"opt=%p\"%s\" value after default set=%p str=%p\n",option,object_name(option),option->get_value(),option->get_value()->sval);
93   return(0);
94 }
95
96 void
97 cl_prompt_option::option_changed(void)
98 {
99   if (!con)
100     return;
101   char *s;
102   option->get_value(&s);
103   con->set_prompt(s);
104 }
105
106
107 cl_debug_option::cl_debug_option(class cl_console *console):
108   cl_prompt_option(console)
109 {}
110
111 int
112 cl_debug_option::init(void)
113 {
114   char *help;
115   help= format_string("Debug messages to console%d", con->get_id());
116   create(con, bool_opt, "debug", help);
117   free(help);
118   default_option("debug");
119   return(0);
120 }
121
122 void
123 cl_debug_option::option_changed(void)
124 {
125   if (!con)
126     return;
127   bool b;
128   option->get_value(&b);
129   if (b)
130     con->flags|= CONS_DEBUG;
131   else
132     con->flags&= ~CONS_DEBUG;
133 }
134
135
136 /*
137  * Command console
138  *____________________________________________________________________________
139  */
140
141 cl_console::cl_console(char *fin, char *fout, class cl_app *the_app):
142   cl_base()
143 {
144   FILE *f;
145
146   app= the_app;
147   in= 0;
148   if (fin)
149     if (f= fopen(fin, "r"), in= f, !f)
150       fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
151   out= 0;
152   if (fout)
153     if (f= fopen(fout, "w"), out= f, !f)
154       fprintf(stderr, "Can't open `%s': %s\n", fout, strerror(errno));
155   prompt= 0;
156   flags= CONS_NONE;
157   if (in &&
158       isatty(fileno(in)))
159     flags|= CONS_INTERACTIVE;
160   else
161     ;//fprintf(stderr, "Warning: non-interactive console\n");
162   rout= 0;
163   id= 0;
164   lines_printed= new cl_ustrings(100, 100, "console_cache");
165 }
166
167 cl_console::cl_console(FILE *fin, FILE *fout, class cl_app *the_app):
168   cl_base()
169 {
170   app= the_app;
171   in = fin;
172   out= fout;
173   prompt= 0;
174   flags= CONS_NONE;
175   if (in &&
176       isatty(fileno(in)))
177     flags|= CONS_INTERACTIVE;
178   else
179     ;//fprintf(stderr, "Warning: non-interactive console\n");
180   rout= 0;
181   id= 0;
182   lines_printed= new cl_ustrings(100, 100, "console_cache");
183 }
184
185 /*
186  * use the port number supplied to connect to localhost for 
187  * (by Sandeep)
188  */
189
190 #ifdef SOCKET_AVAIL
191 static int
192 connect_to_port(int portnum)
193 {
194   int sock= socket(AF_INET,SOCK_STREAM,0);
195   struct sockaddr_in sin;
196
197   sin.sin_family = AF_INET;
198   sin.sin_port = htons(portnum);
199   sin.sin_addr.s_addr = inet_addr("127.0.0.1");
200
201   if (connect(sock, (struct sockaddr *)&sin, sizeof(sin))) {
202     fprintf(stderr, "Connect to port %d: %s\n", portnum, strerror(errno));
203     return -1;
204   }
205   return sock;
206 }
207
208 cl_console::cl_console(int portnumber, class cl_app *the_app)
209 {
210   int sock= connect_to_port(portnumber);
211
212   app= the_app;
213   if (!(in= fdopen(sock, "r")))
214     fprintf(stderr, "cannot open port for input\n");
215   if (!(out= fdopen(sock, "w")))
216     fprintf(stderr, "cannot open port for output\n");
217   //fprintf(stderr, "init socket done\n");
218   id= 0;
219   lines_printed= new cl_ustrings(1, 1, "console_cache");
220 }
221 #endif
222
223 class cl_console *
224 cl_console::clone_for_exec(char *fin)
225 {
226   FILE *fi= 0, *fo= 0;
227
228   if (!fin)
229     return(0);
230   if (fi= fopen(fin, "r"), !fi)
231     {
232       fprintf(stderr, "Can't open `%s': %s\n", fin, strerror(errno));
233       return(0);
234     }
235   if ((fo= fdopen(dup(fileno(out)), "a")) == 0)
236     {
237       fclose(fi);
238       fprintf(stderr, "Can't re-open output file: %s\n", strerror(errno));
239       return(0);
240     }
241   class cl_console *con= new cl_sub_console(this, fi, fo, app);
242   return(con);
243 }
244
245 int
246 cl_console::init(void)
247 {
248   cl_base::init();
249   prompt_option= new cl_prompt_option(this);
250   prompt_option->init();
251   null_prompt_option= new cl_optref(this);
252   null_prompt_option->init();
253   null_prompt_option->use("null_prompt");
254   debug_option= new cl_debug_option(this);
255   debug_option->init();
256   welcome();
257   flags&= ~CONS_PROMPT;
258   //print_prompt();
259   last_command= 0;
260   last_cmdline= 0;
261   return(0);
262 }
263
264 cl_console::~cl_console(void)
265 {
266   if (in)
267     fclose(in);
268   un_redirect();
269   if (out)
270     {
271       if (flags & CONS_PROMPT)
272         fprintf(out, "\n");
273       fflush(out);
274       fclose(out);
275     }
276   delete prompt_option;
277   delete null_prompt_option;
278   delete debug_option;
279 #ifdef SOCKET_AVAIL
280   /*  if (sock)
281     {
282       shutdown(sock, 2);
283       close(sock);
284       }*/
285 #endif
286 }
287
288
289 bool
290 cl_console::accept_last(void)
291 {
292   if (!in)
293     return(DD_FALSE);
294   if (isatty(fileno(in)))
295     return(DD_TRUE);
296   return(DD_FALSE);
297 }
298
299
300 /*
301  * Output functions
302  */
303
304 void
305 cl_console::welcome(void)
306 {
307   FILE *Out= rout?rout:out;
308
309   if (!Out ||
310       (flags & CONS_NOWELCOME))
311     return;
312   fprintf(Out, "uCsim %s, Copyright (C) 1997 Daniel Drotos, Talker Bt.\n"
313           "uCsim comes with ABSOLUTELY NO WARRANTY; for details type "
314           "`show w'.\n"
315           "This is free software, and you are welcome to redistribute it\n"
316           "under certain conditions; type `show c' for details.\n",
317           VERSIONSTR);
318   fflush(Out);
319 }
320
321 void
322 cl_console::redirect(char *fname, char *mode)
323 {
324   if ((rout= fopen(fname, mode)) == NULL)
325     dd_printf("Unable to open file '%s' for %s: %s\n",
326               fname, (mode[0]=='w')?"write":"append", strerror(errno));
327 }
328
329 void
330 cl_console::un_redirect(void)
331 {
332   if (!rout)
333     return;
334   fclose(rout);
335   rout= NULL;
336 }
337
338
339 int
340 cl_console::cmd_do_print(FILE *f, char *format, va_list ap)
341 {
342   int ret;
343 #ifdef HAVE_VASPRINTF
344   char *msg= NULL;
345   vasprintf(&msg, format, ap);
346   ret= fprintf(f, "%s", msg);
347   free(msg);
348 #else
349 #  ifdef HAVE_VSNPRINTF
350   char msg[80*25];
351   vsnprintf(msg, 80*25, format, ap);
352   ret= fprintf(f, "%s", msg);
353 #  else
354 #    ifdef HAVE_VPRINTF
355   char msg[80*25];
356   vsprintf(msg, format, ap); /* Dangerous */
357   ret= fprintf(f, "%s", msg);
358 #    else
359 #      ifdef HAVE_DOPRNT
360   /* ??? */
361   /*strcpy(msg, "Unimplemented printf has called.\n");*/
362 #      else
363   /*strcpy(msg, "printf can not be implemented, upgrade your libc.\n");*/
364 #      endif
365 #    endif
366 #  endif
367 #endif
368   fflush(f);
369   return(ret);
370 }
371
372 void
373 cl_console::print_prompt(void)
374 {
375   //char *p;
376   FILE *Out= rout?rout:out;
377
378   if (flags & (CONS_PROMPT|CONS_FROZEN|CONS_INACTIVE))
379     return;
380   flags|= CONS_PROMPT;
381   if (!Out)
382     return;
383   if (/*app->args->arg_avail('P')*/null_prompt_option->get_value(bool(0)))
384     putc('\0', Out);
385   else
386     {
387       fprintf(Out, "%d", id);
388       fprintf(Out, "%s", (prompt && prompt[0])?prompt:"> ");
389       //              ((p= app->args->get_sarg(0, "prompt"))?p:"> "));
390     }
391   fflush(Out);
392 }
393
394 int
395 cl_console::dd_printf(char *format, ...)
396 {
397   va_list ap;
398   int ret= 0;
399   FILE *Out= rout?rout:out;
400
401   if (Out)
402     {
403       va_start(ap, format);
404       ret= cmd_do_print(Out, format, ap);
405       va_end(ap);
406     }
407   return(ret);
408 }
409
410 int
411 cl_console::debug(char *format, ...)
412 {
413   if ((flags & CONS_DEBUG) == 0)
414     return(0);
415
416   va_list ap;
417   int ret= 0;
418   FILE *Out= rout?rout:out;
419
420   if (Out)
421     {
422       va_start(ap, format);
423       ret= cmd_do_print(Out, format, ap);
424       va_end(ap);
425     }
426   return(ret);
427 }
428
429 void
430 cl_console::print_bin(long data, int bits)
431 {
432   long mask= 1;
433   FILE *Out= rout?rout:out;
434
435   if (!Out)
436     return;
437   mask= mask << ((bits >= 1)?(bits-1):0);
438   while (bits--)
439     {
440       fprintf(Out, "%c", (data&mask)?'1':'0');
441       mask>>= 1;
442     }
443 }
444
445 void
446 cl_console::print_char_octal(char c)
447 {
448   FILE *Out= rout?rout:out;
449
450   if (Out)
451     ::print_char_octal(c, Out);
452 }
453
454
455 /*
456  * Input functions
457  */
458
459 int
460 cl_console::match(int fdnum)
461 {
462   if (in &&
463       fileno(in) == fdnum)
464     return(1);
465   return(0);
466 }
467
468 int
469 cl_console::get_in_fd(void)
470 {
471   if (flags & CONS_INACTIVE)
472     return(-2);
473   return(in?fileno(in):-1);
474 }
475
476 int
477 cl_console::input_avail(void)
478 {
479   struct timeval tv;
480   UCSOCKET_T i;
481   
482   if ((i= get_in_fd()) < 0)
483     return(0);
484   fd_set s;
485   FD_ZERO(&s);
486   FD_SET(i, &s);
487   tv.tv_sec= tv.tv_usec= 0;
488   i= select(i+1, &s, NULL, NULL, &tv);
489   return(i);
490 }
491
492 char *
493 cl_console::read_line(void)
494 {
495   char *s= NULL;
496
497 #ifdef HAVE_GETLINE
498   if (getline(&s, 0, in) < 0)
499     return(0);
500 #else
501
502 # ifdef HAVE_GETDELIM
503   size_t n= 30;
504   s= (char *)malloc(n);
505   if (getdelim(&s, &n, '\n', in) < 0)
506     {
507       free(s);
508       return(0);
509     }
510 # else
511
512 #  ifdef HAVE_FGETS
513   s= (char *)malloc(300);
514   if (fgets(s, 300, in) == NULL)
515     {
516       free(s);
517       return(0);
518     }
519 #  endif
520 # endif
521 #endif
522   s[strlen(s)-1]= '\0';
523   if (s[strlen(s)-1] == '\r')
524     s[strlen(s)-1]= '\0';
525   flags&= ~CONS_PROMPT;
526   return(s);
527 }
528
529 int
530 cl_console::proc_input(class cl_cmdset *cmdset)
531 {
532   int retval= 0;
533
534   un_redirect();
535   if (feof(in))
536     {
537       fprintf(out, "End\n");
538       return(1);
539     }
540   char *cmdstr= read_line();
541   if (!cmdstr)
542     return(1);
543   if (flags & CONS_FROZEN)
544     {
545       app->get_sim()->stop(resUSER);
546       flags&= ~CONS_FROZEN;
547       retval= 0;
548     }
549   else
550     {
551       if (cmdstr &&
552           *cmdstr == '\004')
553         retval= 1;
554       else
555         {
556           class cl_cmdline *cmdline= 0;
557           class cl_cmd *cm= 0;
558           if (flags & CONS_ECHO)
559             dd_printf("%s\n", cmdstr);
560           cmdline= new cl_cmdline(app, cmdstr, this);
561           cmdline->init();
562           if (cmdline->repeat() &&
563               accept_last() &&
564               last_command)
565             {
566               cm= last_command;
567               delete cmdline;
568               cmdline= last_cmdline;
569             }
570           else
571             {
572               cm= cmdset->get_cmd(cmdline, accept_last());
573               if (last_cmdline)
574                 {
575                   delete last_cmdline;
576                   last_cmdline= 0;
577                 }
578               last_command= 0;
579             }
580           if (cm)
581             {
582               retval= cm->work(app, cmdline, this);
583               if (cm->can_repeat)
584                 {
585                   last_command= cm;
586                   last_cmdline= cmdline;
587                 }
588               else
589                 delete cmdline;
590             }
591           else
592             {
593               class YY_cl_ucsim_parser_CLASS *pars;
594               class cl_ucsim_lexer *lexer;
595               lexer= new cl_ucsim_lexer(cmdstr);
596               pars= new YY_cl_ucsim_parser_CLASS(lexer);
597               pars->yyparse();
598               delete cmdline;
599               delete pars;
600             }
601           /*if (!cm)
602             retval= interpret(cmdstr);*/
603         }
604     }
605   //retval= sim->do_cmd(cmd, this);
606   un_redirect();
607   /*if (!retval)
608     print_prompt();*/
609   free(cmdstr);
610   return(retval);
611 }
612
613 /*
614  * Old version, sim->do_cmd() falls into this if it doesn't find a new
615  * command object which can handle entered command
616  */
617
618 int
619 cl_console::interpret(char *cmd)
620 {
621   FILE *Out= rout?rout:out;
622
623   fprintf(Out, "Unknown command\n");
624   return(0);
625 }
626
627 void
628 cl_console::set_id(int new_id)
629 {
630   char *s;
631
632   id= new_id;
633   set_name(s= format_string("console%d", id));
634   free(s);
635 }
636
637 void
638 cl_console::set_prompt(char *p)
639 {
640   if (prompt)
641     free(prompt);
642   if (p &&
643       *p)
644     prompt= strdup(p);
645   else
646     prompt= 0;
647 }
648
649
650 /*
651  * This console listen on a socket and can accept connection requests
652  */
653 #ifdef SOCKET_AVAIL
654
655 cl_listen_console::cl_listen_console(int serverport, class cl_app *the_app)
656 {
657   app= the_app;
658   if ((sock= make_server_socket(serverport)) >= 0)
659     {
660       if (listen(sock, 10) < 0)
661         fprintf(stderr, "Listen on port %d: %s\n",
662                 serverport, strerror(errno));
663     }
664   in= out= 0;
665 }
666
667 int
668 cl_listen_console::match(int fdnum)
669 {
670   return(sock == fdnum);
671 }
672
673 int
674 cl_listen_console::get_in_fd(void)
675 {
676   return(sock);
677 }
678
679 int
680 cl_listen_console::proc_input(class cl_cmdset *cmdset)
681 {
682   int newsock;
683   ACCEPT_SOCKLEN_T size;
684   struct sockaddr_in sock_addr;
685   class cl_commander *cmd;
686
687   cmd= app->get_commander();
688   size= sizeof(struct sockaddr); 
689   newsock= accept(sock, (struct sockaddr*)&sock_addr, &size);
690   if (newsock < 0)
691     {
692       perror("accept");
693       return(0);
694     }
695   if (!(in= fdopen(newsock, "r+")))
696     fprintf(stderr, "cannot open port for input\n");
697   if (!(out= fdopen(newsock, "w+")))
698     fprintf(stderr, "cannot open port for output\n");
699   class cl_console *c= cmd->mk_console(in, out);
700   c->flags|= CONS_INTERACTIVE;
701   cmd->add_console(c);
702   in= out= 0;
703   return(0);
704 }
705
706 #endif /* SOCKET_AVAIL */
707
708
709 /*
710  * Sub-console
711  */
712
713 cl_sub_console::cl_sub_console(class cl_console *the_parent,
714                                FILE *fin, FILE *fout, class cl_app *the_app):
715   cl_console(fin, fout, the_app)
716 {
717   parent= the_parent;
718 }
719
720 cl_sub_console::~cl_sub_console(void)
721 {
722   class cl_commander *c= app->get_commander();
723
724   if (parent && c)
725     {
726       c->activate_console(parent);
727     }
728 }
729
730 int
731 cl_sub_console::init(void)
732 {
733   class cl_commander *c= app->get_commander();
734
735   if (parent && c)
736     {
737       c->deactivate_console(parent);
738     }
739   cl_console::init();
740   flags|= CONS_ECHO;
741   return(0);
742 }
743
744
745 /*
746  * Command interpreter
747  *____________________________________________________________________________
748  */
749
750 cl_commander::cl_commander(class cl_app *the_app, class cl_cmdset *acmdset
751                            /*, class cl_sim *asim*/):
752   cl_base()
753 {
754   app= the_app;
755   cons= new cl_list(1, 1, "consoles"); 
756   actual_console= frozen_console= 0;
757   cmdset= acmdset;
758 }
759
760 int
761 cl_commander::init(void)
762 {
763   class cl_optref console_on_option(this);
764   class cl_optref config_file_option(this);
765   class cl_optref port_number_option(this);
766   class cl_console *con;
767
768   console_on_option.init();
769   console_on_option.use("console_on");
770   config_file_option.init();
771   config_file_option.use("config_file");
772   port_number_option.init();
773
774   cl_base::init();
775   set_name("Commander");
776   
777   bool need_config= DD_TRUE;
778
779 #ifdef SOCKET_AVAIL
780   if (port_number_option.use("port_number"))
781     add_console(mk_console(port_number_option.get_value((long)0)));
782 #endif
783
784   /* The following code is commented out because it produces gcc warnings
785    * newcmd.cc: In member function `virtual int cl_commander::init()':
786    * newcmd.cc:785: warning: 'Config' might be used uninitialized in this function
787    * newcmd.cc:786: warning: 'cn' might be used uninitialized in this function
788    */
789   /*
790   char *Config= config_file_option.get_value(Config);
791   char *cn= console_on_option.get_value(cn);
792    */
793   /* Here shoud probably be something else, but is still better then the former code... */
794   char *Config= config_file_option.get_value("");
795   char *cn= console_on_option.get_value("");
796
797   if (cn)
798     {
799       add_console(con= mk_console(cn, cn));
800       exec_on(con, Config);
801       need_config= DD_FALSE;
802     }
803   if (cons->get_count() == 0)
804     {
805       add_console(con= mk_console(stdin, stdout));
806       exec_on(con, Config);
807       need_config= DD_FALSE;
808     }
809   if (need_config &&
810       Config &&
811       *Config)
812     {
813       FILE *fc= fopen(Config, "r");
814       if (!fc)
815         fprintf(stderr, "Can't open `%s': %s\n", Config, strerror(errno));
816       else
817         {
818           con= mk_console(fc, stderr);
819           con->flags|= CONS_NOWELCOME|CONS_ECHO;
820           add_console(con);
821         }
822     }
823   return(0);
824 }
825
826 cl_commander::~cl_commander(void)
827 {
828   delete cons;
829   delete cmdset;
830 }
831
832 class cl_console *
833 cl_commander::mk_console(char *fin, char *fout)
834 {
835   return(new cl_console(fin, fout, app));
836 }
837
838 class cl_console *
839 cl_commander::mk_console(FILE *fin, FILE *fout)
840 {
841   return(new cl_console(fin, fout, app));
842 }
843
844 #ifdef SOCKET_AVAIL
845 class cl_console *
846 cl_commander::mk_console(int portnumber)
847 {
848   return(new cl_listen_console(portnumber, app));
849 }
850 #endif
851
852 void
853 cl_commander::add_console(class cl_console *console)
854 {
855   if (!console)
856     return;
857   int i=cons->add(console);
858   console->set_id(i);
859   console->init();
860   set_fd_set();
861 }
862
863 void
864 cl_commander::del_console(class cl_console *console)
865 {
866   cons->disconn(console);
867   set_fd_set();
868 }
869
870 void
871 cl_commander::activate_console(class cl_console *console)
872 {
873   console->flags&= ~CONS_INACTIVE;
874   //console->print_prompt();
875   set_fd_set();
876 }
877
878 void
879 cl_commander::deactivate_console(class cl_console *console)
880 {
881   console->flags|= CONS_INACTIVE;
882   set_fd_set();
883 }
884
885 void
886 cl_commander::set_fd_set(void)
887 {
888   int i;
889
890   //fprintf(stderr, "** Setting fd set\n");  
891   FD_ZERO(&read_set);
892   fd_num= 0;
893   for (i= 0; i < cons->count; i++)
894     {
895       UCSOCKET_T fd;
896       class cl_console *c= (class cl_console*)(cons->at(i));
897       if ((fd= c->get_in_fd()) >= 0)
898         {
899           if ((c->flags & CONS_FROZEN) == 0 ||
900               (c->flags & CONS_INTERACTIVE) != 0)
901             {
902               FD_SET(fd, &read_set);
903               if (fd > fd_num)
904                 fd_num= fd;
905             }
906         }
907       else
908         ;//fprintf(stderr, "** Skipping console %p\n",c);
909     }
910   fd_num++;
911 }
912
913
914 /*
915  * Printing to all consoles
916  */
917
918 int
919 cl_commander::all_printf(char *format, ...)
920 {
921   va_list ap;
922   int i, ret= 0;
923   
924   for (i= 0; i < cons->count; i++)
925     {
926       class cl_console *c= (class cl_console*)(cons->at(i));
927       FILE *Out= c->get_out();
928       if (Out)
929         {
930           va_start(ap, format);
931           ret= c->cmd_do_print(Out, format, ap);
932           va_end(ap);
933         }
934     }
935   return(ret);
936 }
937
938 void
939 cl_commander::prompt(void)
940 {
941   int i;
942   
943   for (i= 0; i < cons->count; i++)
944     {
945       class cl_console *c= (class cl_console*)(cons->at(i));
946       c->print_prompt();
947     }
948 }
949
950 int
951 cl_commander::all_print(char *string, int length)
952 {
953   int i;
954   
955   for (i= 0; i < cons->count; i++)
956     {
957       class cl_console *c= (class cl_console*)(cons->at(i));
958       FILE *Out= c->get_out();
959       if (Out)
960         {
961           for (int j= 0; j < length; j++)
962             putc(string[j], Out);
963         }
964     }
965   return(0);
966 }
967
968 /*
969  * Printing to actual_console
970  */
971
972 FILE *
973 cl_commander::get_out(void)
974 {
975   if (actual_console)
976     return(actual_console->get_out());
977   else if (frozen_console)
978     return(frozen_console->get_out());
979   return(0);
980 }
981
982 int
983 cl_commander::dd_printf(char *format, ...)
984 {
985   va_list ap;
986   int ret= 0;
987   FILE *f;
988   class cl_console *con;
989
990   if (actual_console)
991     {
992       f= actual_console->get_out();
993       con= actual_console;
994     }
995   else if (frozen_console)
996     {
997       f= frozen_console->get_out();
998       con= frozen_console;
999     }
1000   else
1001     {
1002       f= 0;
1003       con= 0;
1004     }
1005   if (/*actual_console &&
1006         actual_console->out*/f &&
1007                              con)
1008     {
1009       va_start(ap, format);
1010       ret= con->cmd_do_print(f/*actual_console->out*/, format, ap);
1011       va_end(ap);
1012     }
1013   return(ret);
1014 }
1015
1016 int
1017 cl_commander::dd_printf(char *format, va_list ap)
1018 {
1019   int ret= 0;
1020   FILE *f;
1021   class cl_console *con;
1022
1023   if (actual_console)
1024     {
1025       f= actual_console->get_out();
1026       con= actual_console;
1027     }
1028   else if (frozen_console)
1029     {
1030       f= frozen_console->get_out();
1031       con= frozen_console;
1032     }
1033   else
1034     {
1035       f= 0;
1036       con= 0;
1037     }
1038   if (/*actual_console &&
1039         actual_console->out*/f &&
1040                              con)
1041     {
1042       ret= con->cmd_do_print(f/*actual_console->out*/, format, ap);
1043     }
1044   return(ret);
1045 }
1046
1047 /*
1048  * Printing to consoles which have CONS_DEBUG flag set
1049  */
1050
1051 int
1052 cl_commander::debug(char *format, ...)
1053 {
1054   va_list ap;
1055   int i, ret= 0;
1056
1057   for (i= 0; i < cons->count; i++)
1058     {
1059       class cl_console *c= (class cl_console*)(cons->at(i));
1060       FILE *Out= c->get_out();
1061       if (Out &&
1062           c->flags & CONS_DEBUG)
1063         {
1064           va_start(ap, format);
1065           ret= c->cmd_do_print(Out, format, ap);
1066           va_end(ap);
1067         }
1068     }
1069   return(ret);
1070 }
1071
1072 int
1073 cl_commander::debug(char *format, va_list ap)
1074 {
1075   int i, ret= 0;
1076
1077   for (i= 0; i < cons->count; i++)
1078     {
1079       class cl_console *c= (class cl_console*)(cons->at(i));
1080       FILE *Out= c->get_out();
1081       if (Out &&
1082           c->flags & CONS_DEBUG)
1083         {
1084           ret= c->cmd_do_print(Out, format, ap);
1085         }
1086     }
1087   return(ret);
1088 }
1089
1090 int
1091 cl_commander::flag_printf(int iflags, char *format, ...)
1092 {
1093   va_list ap;
1094   int i, ret= 0;
1095
1096   for (i= 0; i < cons->count; i++)
1097     {
1098       class cl_console *c= (class cl_console*)(cons->at(i));
1099       FILE *Out= c->get_out();
1100       if (Out &&
1101           (c->flags & iflags) == iflags)
1102         {
1103           va_start(ap, format);
1104           ret= c->cmd_do_print(Out, format, ap);
1105           va_end(ap);
1106         }
1107     }
1108   return(ret);
1109 }
1110
1111 int
1112 cl_commander::input_avail(void)
1113 {
1114   struct timeval tv;
1115   int i;
1116
1117   tv.tv_sec= tv.tv_usec= 0;
1118   active_set= read_set;
1119   i= select(fd_num, &active_set, NULL, NULL, &tv);
1120   return(i);
1121 }
1122
1123 int
1124 cl_commander::input_avail_on_frozen(void)
1125 {
1126   int fd;
1127
1128   if (!frozen_console)
1129     return(0);
1130   if ((fd= frozen_console->get_in_fd()) >= 0 &&
1131       !isatty(fd))
1132     return(0);
1133   return(frozen_console->input_avail());
1134 }
1135
1136 int
1137 cl_commander::wait_input(void)
1138 {
1139   int i;
1140
1141   active_set= read_set;
1142   prompt();
1143   i= select(fd_num, &active_set, NULL, NULL, NULL);
1144   return(i);
1145 }
1146
1147 int
1148 cl_commander::proc_input(void)
1149 {
1150   UCSOCKET_T i;
1151
1152   for (i= 0; i < fd_num; i++)
1153     if (FD_ISSET(i, &active_set))
1154       {
1155         class cl_console *c;
1156         int j;
1157         for (j= 0; j < cons->count; j++)
1158           {
1159             c= (class cl_console*)(cons->at(j));
1160             if (c->match(i))
1161               {
1162                 actual_console= c;
1163                 int retval= c->proc_input(cmdset);
1164                 if (retval)
1165                   {
1166                     del_console(c);
1167                     delete c;
1168                   }
1169                 actual_console= 0;
1170                 return(cons->count == 0);
1171               }
1172           }
1173       }
1174   return(0);
1175 }
1176
1177 void
1178 cl_commander::exec_on(class cl_console *cons, char *file_name)
1179 {
1180   FILE *fi= fopen(file_name, "r");
1181
1182   if (!cons ||
1183       !fi)
1184     return;
1185   class cl_console *subcon= cons->clone_for_exec(file_name);
1186   subcon->flags|= CONS_NOWELCOME;
1187   add_console(subcon);
1188 }
1189
1190
1191 /* End of cmd.src/newcmd.cc */