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