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