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