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