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