]> Git Repo - binutils.git/blob - gdb/energize.c
* w89k-rom.c op50-rom.c monitor.c config/pa/hppapro.mt: New files
[binutils.git] / gdb / energize.c
1 /* Energize (formerly known as Cadillac) interface routines.
2    Copyright 1991, 1992 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include "defs.h"
21 #include "symtab.h"
22 #include "inferior.h"
23 #include "command.h"
24 #include "bfd.h"
25 #include "symfile.h"
26 #include "objfiles.h"
27 #include "target.h"
28 #include <sys/types.h>
29 #include <sys/time.h>
30 #include <sys/param.h>
31 #include "energize/connection.h"
32 #include "energize/genericreq.h"
33 #include "energize/debuggerreq.h"
34 #include "energize/debuggerconn.h"
35 #include "energize/ttyconn.h"
36 #include <varargs.h>
37 #include <sys/stat.h>
38 #ifdef USG
39 #include <sys/file.h>
40 #endif
41 #include <fcntl.h>
42 #include <sys/filio.h>
43 #include <setjmp.h>
44 #include <signal.h>
45 #include <sys/errno.h>
46 #include <termios.h>
47 #include <string.h>
48 #ifdef NCR486
49 #include <sys/stropts.h>
50 #endif
51
52 /* Non-zero means that we're doing the energize interface. */
53 int energize = 0;
54
55 /* Non-zero means we are reloading breakpoints, etc from the
56    Energize kernel, and we should suppress various messages */
57 static int energize_reloading = 0;
58
59 /* Connection block for debugger<=>kernel communications. */
60 static Connection *conn = 0;
61
62 /* fd for our socket to the kernel. */
63 static int kerfd;
64
65 /* The kernel's ID for this instance of the program. */
66 static int program_id;
67
68 static int instance_id;
69
70 /* The fd for the pty associated with the inferior. */
71 static int inferior_pty = -1;
72 static int inferior_tty = -1;
73
74 static int has_run = 0;
75
76 extern int pgrp_inferior;
77
78 extern char *source_path;
79
80 /* The name of the executable file */
81 static char *exec_file;
82
83 /* Tell energize_command_line_input() where to get its text from */
84 static int doing_breakcommands_message = 0;
85
86 /* Stash command text here */
87 static char *command_line_text = 0;
88 static int command_line_length = 0;
89
90 /* Flags returned by wait_for_events() */
91 #define KERNEL_EVENT 1
92 #define PTY_EVENT 2
93
94 static void execute_command_1();
95
96 \f
97 /* This routine redirects the output of fputs_filtered to the kernel so that
98    the user can see what's going on in his debugger window. */
99
100 void
101 energize_fputs(ptr)
102      const char *ptr;
103 {
104   if (conn)
105     CVWriteTranscriptInfo (conn, instance_id, (char *)ptr);
106   else
107     fputs (ptr, stdout);
108 }
109
110 void
111 energize_query(query, args)
112      char *query;
113      va_list args;
114 {
115   char buf[100];
116
117   if (!energize)
118     return;
119
120   vsprintf(buf, query, args);
121
122   CVWriteQueryInfo(conn,
123                    instance_id,
124                    CQueryConfirm,
125                    qno_unknown,
126                    buf,
127                    "");         /* transcript */
128 }
129
130 void
131 energize_acknowledge_query(ack)
132      char *ack;
133 {
134   CVWriteQueryInfo(conn,
135                    instance_id,
136                    CQueryAcknowleged,
137                    0,
138                    ack,
139                    "");         /* transcript */
140 }
141
142 /* Copy all data from the pty to the kernel. */
143
144 static void
145 pty_to_kernel()
146 {
147   CTtyRequest *req;
148   char buf[1024];
149   int cc;
150
151   while (1)
152     {
153       cc = read(inferior_pty, buf, sizeof(buf));
154
155       if (cc == 0
156           || (cc < 0
157               && (errno == EWOULDBLOCK
158                   || errno == EAGAIN)))
159         break;
160
161       if (cc < 0)
162         {
163           close(inferior_pty);
164           inferior_pty = -1;
165           perror("pty_to_kernel: pty read error");
166           break;
167         }
168
169       req = CWriteTtyRequest(conn, TextIORType);
170       CWriteVstringLen(conn, buf, cc);
171       CWriteLength(conn);
172     }
173   CWriteRequestBuffer(conn);
174 }
175
176 /* Copy data from the kernel to the pty. */
177
178 static void
179 kernel_to_pty(data, len)
180      char *data;
181      int len;
182 {
183   int cc;
184
185   cc = write(inferior_pty, data, len);
186
187   if (cc != len)
188     {
189       if (cc < 0)
190         {
191           close(inferior_pty);
192           inferior_pty = -1;
193           perror("kernel_to_pty: pty write error");
194           return;
195         }
196       printf("Couldn't write all the data to the pty, wanted %d, got %d\n",
197              len, cc);
198     }
199 }
200 \f
201 static char *
202 full_filename(symtab)
203      struct symtab *symtab;
204 {
205   int pathlen;
206   char *filename;
207
208   if (!symtab)
209     return NULL;
210
211   if (symtab->fullname)
212     return savestring(symtab->fullname, strlen(symtab->fullname));
213
214   if (symtab->filename[0] == '/')
215     return savestring(symtab->filename, strlen(symtab->filename));
216
217   if (symtab->dirname)
218     pathlen = strlen(symtab->dirname);
219   else
220     pathlen = 0;
221   if (symtab->filename)
222     pathlen += strlen(symtab->filename);
223
224   filename = xmalloc(pathlen+1);
225
226   if (symtab->dirname)
227     strcpy(filename, symtab->dirname);
228   else
229     *filename = '\000';
230   if (symtab->filename)
231     strcat(filename, symtab->filename);
232
233   return filename;
234 }
235
236 /* Tell the energize kernel how high the stack is so that frame numbers (which
237    are relative to the current stack height make sense.
238
239    Calculate the number of frames on the stack, and the number of subroutine
240    invocations that haven't changed since the last call to this routine.  The
241    second number is calculated by comparing the PCs of the current stack frames
242    to the PCs of the previous set of stack frames.  The screw here is that a
243    subroutine may call several different procedures, which means that the PC
244    in its frame changes, even though you are still in the same subroutine.  We
245    resolve this by converting the frames PC into the PC at the start of the
246    function (for efficiency, this is done only if the simple comparison test
247    fails). */
248
249 struct pclist
250 {
251   CORE_ADDR pc;
252   struct pclist *next;
253 };
254
255 /* Non-zero means that Energize kernel already knows how high the stack is. */
256 static int stack_info_valid = 0;
257
258 static void
259 send_stack_info()
260 {
261   struct pclist *pclist = 0, *pli, *opli;
262   static struct pclist *old_pclist;
263   FRAME frame;
264   int height, similar;
265
266   if (stack_info_valid)
267     return;
268
269   height = 0;
270   similar = 0;
271
272 /* First, calculate the stack height, and build the new pclist */
273
274   for (frame = get_current_frame();
275        frame != 0;
276        frame = get_prev_frame(frame))
277     {
278       (height)++;
279       pli = (struct pclist *)xmalloc(sizeof(struct pclist));
280
281       pli->pc = frame->pc;
282       pli->next = pclist;
283       pclist = pli;
284     }
285
286 /* Now, figure out how much of the stack hasn't changed */
287
288   for (pli = pclist, opli = old_pclist;
289        pli != 0 && opli != 0;
290        pli = pli->next, opli = opli->next, (similar)++)
291     {
292       if ((pli->pc != opli->pc)
293           && (get_pc_function_start(pli->pc)
294               != get_pc_function_start(opli->pc)))
295         break;
296     }
297
298 /* Free up all elements of the old pclist */
299
300   opli = old_pclist;
301
302   while (opli)
303     {
304       pli = opli->next;
305       free (opli);
306       opli = pli;
307     }
308
309   old_pclist = pclist;          /* Install the new pclist */
310
311   CVWriteStackSizeInfo(conn,
312                        instance_id,
313                        height,  /* Frame depth */
314                        CInnerFrameIs0,
315                        similar, /* Frame diff */
316                        ""       /* Transcript */
317                        );
318
319   stack_info_valid = 1;
320 }
321
322 /* Tell the Energize server about the file and line # that corresponds to pc,
323    and which stack frame level that pc corresponds to. */
324
325 static void
326 send_location(pc, frame_level)
327      CORE_ADDR pc;
328      int frame_level;
329 {
330   char *funcname, *filename;
331   struct symtab_and_line sal;
332   struct symbol *symbol;
333
334   sal = find_pc_line(pc, 0);
335   symbol = find_pc_function(pc);
336
337   funcname = symbol ? symbol->name : "";
338   filename = full_filename(sal.symtab);
339
340   send_stack_info();
341
342   CVWriteStackFrameInfo(conn,
343                         instance_id,
344                         sal.line,
345                         CFileLinePos,
346                         frame_level,
347                         funcname,
348                         filename,
349                         ""      /* XXX ? transcript */
350                         );
351   if (filename)
352     free(filename);
353 }
354
355 /* Tell the kernel where we are in the program, and what the stack looks like.
356    */
357
358 static void
359 send_status()
360
361   char *funcname;
362   struct symbol *symbol;
363   static int sent_prog_inst = 0;
364
365   symbol = find_pc_function(stop_pc);
366   funcname = symbol ? symbol->name : "";
367
368   if (!has_run)
369     return;
370
371   if (inferior_pid == 0)        /* target has died */
372     {
373       CVWriteProgramTerminatedInfo(conn,
374                                    instance_id,
375                                    ""
376                                    );
377       return;
378     }
379
380   if (!sent_prog_inst)
381     {
382       sent_prog_inst = 1;
383       CVWriteProgramInstanceInfo(conn,
384                                  program_id,
385                                  instance_id,
386                                  "", /* hostname */
387                                  "", /* arglist */
388                                  ""
389                                  );
390     }
391
392   send_location(stop_pc,
393                 selected_frame_level); /* Had better be 0! */
394
395   CVWriteProgramStoppedInfo(conn,
396                             instance_id,
397                             0,  /* XXX - breakpoint # or signal # */
398                             CDebuggerCommand,
399                             funcname,
400                             ""  /* XXX ? transcript */
401                             );
402
403 }
404
405 /* Call this to output annotated function names.  Names will be demangled if
406    necessary.  arg_mode contains flags that are passed on to cplus_demangle. */
407
408 void
409 energize_annotate_function(funcname, arg_mode, level)
410      char *funcname;
411      int arg_mode;
412      int level;
413 {
414   char *demangled_name = NULL;
415
416   if (funcname == NULL)
417     return;
418
419   if (demangle)
420     {
421       demangled_name = cplus_demangle(funcname, arg_mode);
422
423       if (demangled_name)
424         {
425           funcname = demangled_name;
426           printf_filtered("'");
427         }
428     }
429
430   send_stack_info();
431
432   if (level < 0) level = 0;
433
434   CVWriteBackTraceEntryInfo(conn,
435                             instance_id,
436                             level, /* frameNo */
437                             funcname);
438
439   if (demangled_name)
440     {
441       free(demangled_name);
442       printf_filtered("'");
443     }
444 }
445
446 /* Call this just prior to printing out the name & value of a variable.  This
447    tells the kernel where to annotate the output. */
448
449 /* The args are:
450    expression - A text handle on what GDB can use to reference this value.
451                 This can be a symbol name, or a convenience var, etc...
452    symbol - Used to determine the scope of the data.  May be NULL.
453    type - Determines if we have a pointer ref, and the print name of the type.
454           Used in ShowValue message.
455    valaddr - The address in target memory of the data.
456    field - The field name of the struct or union element being referenced.
457 */
458
459 static char cum_expr[200];      /* Cumulative expression */
460 static char *expr_stack[100] = {cum_expr}; /* Pointers to end of expressions */
461 static char **last_expr = expr_stack;   /* Current expr stack pointer */
462
463 void
464 energize_start_variable_annotation(expression, symbol, type, valaddr, field)
465      char *expression;
466      struct symbol *symbol;
467      struct type *type;
468      CORE_ADDR valaddr;
469      char *field;
470 {
471   int ref_type;
472   int stor_cl;
473   enum type_code type_code;
474   enum address_class sym_class;
475   char *type_cast;
476
477   if (!energize)
478     return;
479
480   send_stack_info();
481
482   strcpy(*last_expr++, expression);
483   *last_expr = *(last_expr-1) + strlen(expression);
484
485   switch (TYPE_CODE(type))
486     {
487     case TYPE_CODE_ARRAY:
488     case TYPE_CODE_STRUCT:
489     case TYPE_CODE_UNION:
490     case TYPE_CODE_ENUM:
491     case TYPE_CODE_INT:
492     case TYPE_CODE_FLT:
493       ref_type = CValueValueRef;
494       break;
495     case TYPE_CODE_PTR:
496       ref_type = CValuePointerRef;
497       break;
498     default:
499       ref_type = CValueUndefRef;
500       break;
501     }
502
503 /* Make sure that pointer points at something we understand */
504
505   if (ref_type == CValuePointerRef)
506     switch (TYPE_CODE(TYPE_TARGET_TYPE(type)))
507       {
508       case TYPE_CODE_PTR:
509       case TYPE_CODE_ARRAY:
510       case TYPE_CODE_STRUCT:
511       case TYPE_CODE_UNION:
512       case TYPE_CODE_ENUM:
513       case TYPE_CODE_INT:
514       case TYPE_CODE_FLT:
515         break;
516       default:
517         ref_type = CValueUndefRef;
518         break;
519       }
520
521   if (symbol)
522     {
523       sym_class = SYMBOL_CLASS(symbol);
524
525       switch (sym_class)
526         {
527         case LOC_CONST:
528         case LOC_CONST_BYTES:
529           stor_cl = CValueStorStaticConst;
530           break;
531         case LOC_STATIC:
532           stor_cl = CValueStorStaticVar;
533           break;
534         case LOC_REGISTER:
535         case LOC_REGPARM:
536           stor_cl = CValueStorRegister;
537           break;
538         case LOC_ARG:
539         case LOC_REF_ARG:
540         case LOC_LOCAL:
541         case LOC_LOCAL_ARG:
542           stor_cl = CValueStorLocalVar;
543           break;
544         default:
545           stor_cl = CValueStorUndef;
546           break;
547         }
548     }
549   else
550     stor_cl = CValueStorUndef;
551
552   type_cast = TYPE_NAME(type);
553
554   CVWriteValueBeginInfo(conn,
555                         instance_id,
556                         valaddr,
557                         ref_type,
558                         stor_cl,
559                         0,      /* XXX - frameno */
560                         cum_expr,
561                         field,
562                         type_cast,
563                         "");    /* transcript */
564 }
565
566 void
567 energize_end_variable_annotation()
568 {
569   if (!energize)
570     return;
571
572   last_expr--;                  /* Pop the expr stack */
573   **last_expr = '\000';         /* Cut off the last part of the expr */
574
575   CVWriteValueEndInfo(conn,
576                       instance_id,
577                       "");      /* transcript */
578 }
579 \f
580 /* Tell the kernel that the target is now running. */
581
582 static void
583 go_busy()
584 {
585   CVWriteProgramBusyInfo(conn,
586                          instance_id,
587                          "");   /* XXX ? transcript */
588   CWriteRequestBuffer(conn);    /* Must take place synchronusly! */
589   stack_info_valid = 0;
590 }
591
592 \f
593 void
594 energize_symbol_file(objfile)
595      struct objfile *objfile;
596 {
597   if (!energize)
598     return;
599
600   CVWriteSymbolTableInfo(conn,
601                          objfile->name,
602                          "");   /* Transcript */
603 }
604
605 /* execute_command_1(echo, queue, cmd, args) - echo - non-zero means echo the
606    command.  queue - non-zero means don't execute it now, just save it away for
607    later.  cmd - string containing printf control sequences.  args - list of
608    arguments needed by those control sequences.
609  */
610
611 /* Linked list of queued up commands */
612 static struct command_line *queued_commands = 0;
613 static struct command_line *last_queued_command = 0;
614
615 /* Call this routine to save a command for later.  The command string is
616    copied into freshly malloc'ed memory. */
617
618 static void
619 queue_command(cmd)
620      char *cmd;
621 {
622   char *buf;
623   struct command_line *cl;
624   unsigned long s;
625
626   s = (strlen(cmd) + 1) + 7 & ~(unsigned long)7;
627
628   buf = (char *)xmalloc(s + sizeof(struct command_line));
629   cl = (struct command_line *)(buf + s);
630   cl->next = 0;
631   cl->line = buf;
632
633   strncpy(cl->line, cmd, s);
634
635   if (queued_commands)
636     last_queued_command->next = cl;
637   else
638     queued_commands = cl;
639
640   last_queued_command = cl;
641 }
642
643 /* Call this procedure to take a command off of the command queue.  It returns
644    a pointer to a buf which the caller is responsible for freeing.  NULL is
645    returned if there are no commands queued. */
646
647 static char *
648 dequeue_command()
649 {
650   struct command_line *cl;
651   char *cmd;
652
653   cl = queued_commands;
654
655   if (!cl)
656     return NULL;
657
658   queued_commands = cl->next;
659
660   return cl->line;
661 }
662
663 static void
664 execute_command_1(va_alist)
665      va_dcl
666 {
667   char buf[100];                /* XXX - make buf dynamic! */
668   
669   int echo;
670   int queue;
671   char *cmd;
672   va_list args;
673
674   va_start(args);
675   echo = va_arg(args, int);
676
677   queue = va_arg(args, int);
678   cmd = va_arg(args, char *);
679
680   vsprintf(buf, cmd, args);
681
682   if (queue)
683     queue_command(buf);
684   else
685     {
686       if (echo)
687         printf_filtered("%s\n", buf);
688       execute_command(buf, 1);
689     }
690
691   va_end(args);
692 }
693
694 #ifdef KERNEL_RECORD
695 GDB_FILE *kerout;
696
697 static int
698 kernel_record(fd, ptr, num)
699      int fd, num;
700      char *ptr;
701
702 {
703   fwrite(ptr, num, 1, kerout);
704   fflush(kerout);
705   return write(fd, ptr, num);
706 }
707 #endif
708
709 void
710 energize_condition_breakpoint(b)
711      struct breakpoint *b;
712 {
713   if (energize)
714     CVWriteBreakConditionInfo(conn,
715                               instance_id,
716                               b->number,
717                               b->cond_string ? b->cond_string : "",
718                               "" /* transcript */
719                               );
720 }
721
722 void
723 energize_commands_breakpoint(b)
724      struct breakpoint *b;
725 {
726   struct command_line *l;
727
728   if (!energize)
729     return;
730
731   CVWriteBreakCommandBegInfo(conn,
732                              instance_id,
733                              b->number,
734                              ""); /* transcript */
735
736   for (l = b->commands; l; l = l->next)
737     CVWriteBreakCommandEntryInfo(conn,
738                                  instance_id,
739                                  l->line,
740                                  ""); /* transcript */
741
742   CVWriteBreakCommandEndInfo(conn,
743                              instance_id,
744                              ""); /* transcript */
745 }
746
747 static void
748 breakpoint_notify(b, action)
749      struct breakpoint *b;
750      int action;
751 {
752   struct symbol *sym;
753   char *funcname = "";
754   char *filename;
755   char *included_in_filename = "";
756
757   if (!energize
758       || energize_reloading)    /* Don't notify energize about breakpoint changes, as it's about to send us
759                                    a new bunch.  */
760     return;
761
762   if (b->type != bp_breakpoint)
763     return;
764
765   filename = full_filename(b->symtab);
766
767   sym = find_pc_function(b->address);
768   if (sym)
769     funcname = SYMBOL_NAME(sym);
770
771   CVWriteBreakpointInfo (conn,
772                          instance_id,
773                          b->number,
774                          b->line_number,
775                          CFileLinePos,
776                          CBreakOnInstrAccess,
777                          action,
778                          b->ignore_count,
779                          funcname,
780                          filename ? filename : "",
781                          "",    /* included_in_filename */
782                          ""     /* transcript */
783                          );
784
785   if (b->commands)
786     energize_commands_breakpoint(b);
787
788   energize_condition_breakpoint(b);
789
790   if (filename)
791     free(filename);
792 }
793
794 void
795 energize_create_breakpoint(b)
796      struct breakpoint *b;
797 {
798   breakpoint_notify(b, CEnableBreakpoint);
799 }
800
801 void
802 energize_delete_breakpoint(b)
803      struct breakpoint *b;
804 {
805   breakpoint_notify(b, CDeleteBreakpoint);
806 }
807
808 void
809 energize_enable_breakpoint(b)
810      struct breakpoint *b;
811 {
812   breakpoint_notify(b, CEnableBreakpoint);
813 }
814
815 void
816 energize_disable_breakpoint(b)
817      struct breakpoint *b;
818 {
819   breakpoint_notify(b, CDisableBreakpoint);
820 }
821
822 void
823 energize_ignore_breakpoint(b)
824      struct breakpoint *b;
825 {
826   breakpoint_notify(b, CBreakAttrUnchanged);
827 }
828 \f
829 /* Open up a pty and its associated tty.  Return the fd of the tty. */
830
831 #ifndef NCR486
832 static void
833 getpty()
834 {
835   int n, ptyfd, ttyfd;
836   static char dev[30];
837   struct stat statbuf;
838   struct termios termios;
839
840 #define HIGHPTY (('z' - 'p') * 16 - 1)
841
842   for (n = 0; n <= HIGHPTY; n++)
843     {
844       sprintf(dev, "/dev/pty%c%x", n/16 + 'p', n%16);
845       if (stat(dev, &statbuf))
846         break;
847       ptyfd = open(dev, O_RDWR);
848       if (ptyfd < 0)
849         continue;
850       sprintf(dev, "/dev/tty%c%x", n/16 + 'p', n%16);
851       ttyfd = open(dev, O_RDWR);
852       if (ttyfd < 0)
853         {
854           close(ptyfd);
855           continue;
856         }
857
858       /* Setup pty for non-blocking I/O.  Also make it give us a SIGIO when
859          there's data available.  */
860
861       n = fcntl(ptyfd, F_GETFL, 0);
862       fcntl(ptyfd, F_SETFL, n|FNDELAY|FASYNC);
863       fcntl(ptyfd, F_SETOWN, getpid());
864
865       tcgetattr(ttyfd, &termios);
866       termios.c_oflag &= ~OPOST; /* No post-processing */
867       tcsetattr(ttyfd, TCSANOW, &termios);
868
869       inferior_pty = ptyfd;
870       inferior_tty = ttyfd;
871       return;
872     }
873
874   error ("getpty: can't get a pty\n");
875 }
876 #endif
877 /* Alternate getpty for NCRs */
878
879 #ifdef NCR486 /* LTL */
880 #define MAX_PTM_TRY 16
881 #define MAX_GRANTPT_TRY 4
882 static void
883 getpty()
884 {
885   char *slavename;
886   extern char *ptsname();
887   int j, i;
888   int n, mfd, sfd;
889   struct stat statbuf; 
890   struct termios termios;
891
892   mfd = open("/dev/ptmx", O_RDWR); /* get the master */
893   if (mfd < 0)
894     error ("getpty: can't locate master\n");
895
896   if (grantpt(mfd) < 0) /* get a slave */
897     error ("getpty: can't acquire slave");
898
899   unlockpt(mfd);
900
901   slavename = ptsname(mfd); /* get the slave device name */
902   if (!slavename)
903     error ("getpty: can't get a pts\n");
904
905   /* Drop controlling tty, become pgrp master */
906
907   if (setpgid(0, getppid()) == -1)
908     perror("setpgid() failed: ");
909
910   if (setsid() == -1)
911     perror("setsid() failed: ");
912
913   sfd = open(slavename, O_RDWR);
914   if (sfd < 0)
915     {
916       close(mfd);
917       error ("getpty: can't open slave\n");
918     }
919
920
921   if (ioctl(sfd, I_PUSH, "ptem")) perror ("getpty: ioctl I_PUSH fails");
922   if (ioctl(sfd, I_PUSH, "ldterm")) perror ("getpty: ioctl I_PUSH fails");
923
924   /* setup mty for non-blocking I/O. */
925
926   n = fcntl(mfd, F_GETFL);
927   if (n < 0)
928     perror ("getpty: fcntl F_GETFL failed");
929
930   if (fcntl(mfd, F_SETFL, n|O_NDELAY) <0)
931     perror("getpty: fcntl F_SETFL failed");
932
933   /* set up for async i/o - V.4 will send SIGPOLL when data available */
934
935   if (ioctl (mfd,  I_SETSIG, S_INPUT|S_RDNORM) < 0)
936     perror ("getpty: ioctl I_SETSIG failed");
937
938   if (tcgetattr(sfd, &termios))
939     perror("getpty: tcgetattr fails");
940   termios.c_oflag &= ~OPOST;    /* no post-processing */
941   if (tcsetattr(sfd, TCSANOW, &termios))
942     perror("getpty: tcsetattr fails");
943
944   inferior_pty=mfd;
945   inferior_tty=sfd;
946
947   return;
948
949
950 #endif /* NCR486 */
951 \f
952 /* Examine a protocol packet from the driver. */
953
954 static void
955 kernel_dispatch(queue)
956      int queue;                 /* Non-zero means we should just queue up
957                                    commands. */
958 {
959   register CHeader *head;
960
961   head = (CHeader *)CPeekNextRequest (conn);
962   if (head == NULL)
963     {
964       fprintf (stderr, "EOF on kernel read!\n");
965       exit (1);
966     }
967
968   if (head->reqType < LastTtyRequestRType)
969     {
970       CTtyRequest* req = CReadTtyRequest (conn);
971       switch (req->head.reqType)
972         {
973         case AcceptConnectionRType:
974           /* Tell the rest of the world that energize is now set up */
975           CSkipRequest (conn);
976           break;
977
978         case RefuseConnectionRType:
979           fprintf (stderr, "Debugger connection refused\n");
980           exit (1);
981
982         case KillProgramRType:
983           exit (0);
984
985         case TextIORType:
986           {
987             char *p;
988             ReqLen len;
989
990             p = CGetVstring(conn, &len);
991             kernel_to_pty(p, len);
992           }
993           break;
994         default:
995           fprintf(stderr, "Unknown Tty request type = %d\n",
996                   req->head.reqType);
997           break;
998         }
999     }
1000   else
1001     {
1002       CVDebuggerRequest *req = CVReadDebuggerRequest (conn);
1003       if (!req)
1004         {
1005           fprintf (stderr, "CVReadDebuggerRequest returned NULL, type = %d\n",
1006                    head->reqType);
1007           exit(1);
1008         }
1009
1010       switch (req->head.request->reqType)
1011         {
1012         case OpenProgramInstanceRType:
1013           {
1014             char *arglist, buf[100]; /* XXX - Make buf dynamic! */
1015             int arglen;
1016             /* XXX - should notice when program_id changes */
1017             arglist = req->openProgramInstance.progArglist.text;
1018             arglen = req->openProgramInstance.progArglist.byteLen;
1019
1020             execute_command_1(1, queue, "break main");
1021             execute_command_1(1, queue, "enable delete $bpnum");
1022             if (arglist)
1023               {
1024                 execute_command_1(1, queue, "set args %.*s", arglen, arglist);
1025               }
1026             execute_command_1(1, queue, "run");
1027           }
1028           break;
1029         case SearchPathRType:
1030           directory_command(req->searchPath.searchPath.text, 0);
1031           break;
1032         case QuitDebuggerRType:
1033           execute_command_1(1, queue, "quit");
1034           break;
1035         case RunRType:
1036           if (req->run.request->useArglist == CNewArglist)
1037             {
1038               execute_command_1(1, queue, "set args %.*s",
1039                                 req->run.progArglist.byteLen,
1040                                 req->run.progArglist.text);
1041             }
1042           execute_command_1(1, queue, "run");
1043           break;
1044         case ContinueRType:
1045           execute_command_1(1, queue, "continue");
1046           break;
1047         case StepRType:
1048           execute_command_1(1, queue, "step %d", req->step.request->stepCount);
1049           break;
1050         case NextRType:
1051           execute_command_1(1, queue, "next %d", req->next.request->nextCount);
1052           break;
1053         case ChangeStackFrameRType:
1054           switch (req->changeStackFrame.request->frameMovement)
1055             {
1056             case CToCurrentStackFrame:
1057               execute_command_1(1, queue, "frame %d",
1058                                 req->changeStackFrame.request->frameNo);
1059               break;
1060             case CToInnerStackFrame:
1061               execute_command_1(1, queue, "down %d",
1062                                 req->changeStackFrame.request->frameNo);
1063               break;
1064             case CToOuterStackFrame:
1065               execute_command_1(1, queue, "up %d",
1066                                 req->changeStackFrame.request->frameNo);
1067               break;
1068             case CToAbsoluteStackFrame:
1069               execute_command_1(1, queue, "frame %d",
1070                                 req->changeStackFrame.request->frameNo);
1071               break;
1072             }
1073           break;
1074         case BackTraceRType:
1075           /* XXX - deal with limit??? */
1076           execute_command_1(1, queue, "backtrace");
1077           break;
1078         case FinishRType:
1079           execute_command_1(1, queue, "finish");
1080           break;
1081         case TerminateProgramRType:
1082           execute_command_1(1, queue, "kill");
1083           break;
1084         case NewBreakpointRType:
1085           {
1086             char *tail;
1087             int skipped;
1088
1089             tail = strrchr(req->newBreakpoint.fileName.text, '/');
1090             if (!tail)
1091               tail = req->newBreakpoint.fileName.text;
1092             else
1093               tail++;
1094             skipped = tail - req->newBreakpoint.fileName.text;
1095             execute_command_1(1, queue, "break %.*s:%d",
1096                               req->newBreakpoint.fileName.byteLen - skipped,
1097                               tail,
1098                               req->newBreakpoint.request->fileLinePos);
1099           }
1100           break;
1101         case StopRType:
1102           kill(-pgrp_inferior, SIGINT);
1103           break;
1104         case UserInputRType:
1105           {
1106             char *text;
1107             long len;
1108
1109             /* XXX - should really break command up into seperate lines
1110                and spoon-feed it to execute_command */
1111
1112             text = req->userInput.userInput.text;
1113             len = req->userInput.userInput.byteLen;
1114
1115             if (text[len-1] == '\n') text[len-1] = '\000';
1116
1117             while (*text == ' ' || *text == '\t') text++;
1118
1119             if (STREQ(text, "]*[")) /* XXX - What does this mean??? */
1120               break;
1121
1122             if (*text != '\000')
1123               execute_command_1(0, queue, "%s", text);
1124             else
1125               print_prompt();   /* User just typed a blank line */
1126           }
1127           break;
1128         case QueryResponseRType:
1129           {
1130             char *resp;
1131
1132             if (req->queryResponse.request->response)
1133               resp = "y";
1134             else
1135               resp = "n";
1136             execute_command_1(1, 1, resp);
1137             printf_filtered("%s\n", resp);
1138           }
1139           break;
1140         case ChangeBreakpointRType:
1141           switch (req->changeBreakpoint.request->breakpointAttr)
1142             {
1143             case CBreakAttrUnchanged:
1144               execute_command_1(1, queue, "ignore %d %d",
1145                                 req->changeBreakpoint.request->breakpointId,
1146                                 req->changeBreakpoint.request->ignoreCount);
1147               break;
1148             case CEnableBreakpoint:
1149               execute_command_1(1, queue, "enable %d",
1150                                 req->changeBreakpoint.request->breakpointId);
1151               break;
1152             case CDisableBreakpoint:
1153               execute_command_1(1, queue, "disable %d",
1154                                 req->changeBreakpoint.request->breakpointId);
1155               break;
1156             case CDeleteBreakpoint:
1157               execute_command_1(1, queue, "delete %d",
1158                                 req->changeBreakpoint.request->breakpointId);
1159               break;
1160             case CEnableDisableBreakpoint:
1161               execute_command_1(1, queue, "enable once %d",
1162                                 req->changeBreakpoint.request->breakpointId);
1163               break;
1164             case CEnableDeleteBreakpoint:
1165               execute_command_1(1, queue, "enable delete %d",
1166                                 req->changeBreakpoint.request->breakpointId);
1167               break;
1168             default:
1169               printf_filtered("ChangeBreakpointRType: unknown breakpointAttr\n");
1170               printf_filtered("  breakpointAttr = %d\n",
1171                               req->changeBreakpoint.request->breakpointAttr);
1172               printf_filtered("  breakpointId = %d\n",
1173                               req->changeBreakpoint.request->breakpointId);
1174               printf_filtered("  breakpointType = %d\n",
1175                               req->changeBreakpoint.request->breakpointType);
1176               printf_filtered("  ignoreCount = %d\n",
1177                               req->changeBreakpoint.request->ignoreCount);
1178               break;
1179             }
1180           break;
1181         case BreakConditionRType:
1182           execute_command_1(1, queue, "condition %d %.*s",
1183                           req->breakCondition.request->breakpointId,
1184                           req->breakCondition.condition.byteLen,
1185                           req->breakCondition.condition.text);
1186           break;
1187         case BreakCommandsRType:
1188           /* Put pointers to where energize_command_line_input() can find
1189              them. */
1190           doing_breakcommands_message = 1;
1191           command_line_length = req->breakCommands.commands.byteLen;
1192           command_line_text = req->breakCommands.commands.text;
1193           execute_command_1(1, queue, "commands %d",
1194                             req->breakCommands.request->breakpointId);
1195           command_line_text = (char *)NULL;
1196           command_line_length = 0;
1197           doing_breakcommands_message = 0;
1198           break;
1199         case ShowValueRType:
1200           {
1201             char expr[100], *p = expr;
1202
1203             expr[0] = 0;
1204
1205             if (req->showValue.request->ref_type == CValuePointerRef)
1206               strcat(expr, "* ");
1207
1208             if (req->showValue.type_cast.byteLen)
1209               {
1210                 strcat(expr, "(");
1211                 strncat(expr, req->showValue.type_cast.text,
1212                         req->showValue.type_cast.byteLen);
1213                 strcat(expr, ") ");
1214               }
1215
1216             if (req->showValue.field.byteLen)
1217               strcat(expr, "(");
1218
1219             strncat(expr, req->showValue.expression.text,
1220                     req->showValue.expression.byteLen);
1221
1222             if (req->showValue.field.byteLen)
1223               {
1224                 strcat(expr, ")");
1225
1226                 strncat(expr, req->showValue.field.text,
1227                         req->showValue.field.byteLen);
1228               }
1229
1230             execute_command_1(1, queue, "print %s", expr);
1231           }
1232           break;
1233         case SetValueRType:
1234           {
1235             char expr[100], *p = expr;
1236
1237             expr[0] = 0;
1238
1239             if (req->setValue.request->ref_type == CValuePointerRef)
1240               strcat(expr, "* ");
1241
1242 #if 0
1243             if (req->setValue.type_cast.byteLen)
1244               {
1245                 strcat(expr, "(");
1246                 strncat(expr, req->setValue.type_cast.text,
1247                         req->setValue.type_cast.byteLen);
1248                 strcat(expr, ") ");
1249               }
1250 #endif
1251             if (req->setValue.field.byteLen)
1252               strcat(expr, "(");
1253
1254             strncat(expr, req->setValue.expression.text,
1255                     req->setValue.expression.byteLen);
1256
1257             if (req->setValue.field.byteLen)
1258               {
1259                 strcat(expr, ")");
1260
1261                 strncat(expr, req->setValue.field.text,
1262                         req->setValue.field.byteLen);
1263               }
1264
1265             execute_command_1(1, queue, "print %s = (%s) %s", expr,
1266                               req->setValue.type_cast.text,
1267                               req->setValue.value.text);
1268           }
1269           break;
1270         case DynamicLoadRType:
1271           {
1272             char *filename;
1273
1274             filename = req->dynamicLoad.filenames.byteLen ?
1275               req->dynamicLoad.filenames.text : exec_file;
1276
1277             switch (req->dynamicLoad.request->action)
1278               {
1279               case CDynamicLoadUpdateSymtab:
1280                 energize_reloading = 1;
1281                 execute_command_1(1, queue, "set confirm no");
1282                 execute_command_1(1, queue, "delete");
1283 /*              execute_command_1(1, queue, "set $bpnum=1");*/ /* Use this to reset breakpoint #s */
1284                 execute_command_1(1, queue, "exec-file %s", filename);
1285                 execute_command_1(1, queue, "symbol-file %s", filename);
1286                 execute_command_1(1, queue, "set confirm yes");
1287                 energize_reloading = 0;
1288                 break;
1289               case CDynamicLoadRestoreStart:
1290                 break;
1291               case CDynamicLoadRestoreEnd: /* Not used anymore??? */
1292                 printf_filtered("\n[Target has changed, automatic restoration of state has been done.]\n");
1293                 print_prompt();
1294                 break;
1295               default:
1296                 printf_filtered("DynamicLoadRType: unknown action=%d, filename=%s\n",
1297                                 req->dynamicLoad.request->action,
1298                                 req->dynamicLoad.filenames.text);
1299                 break;
1300               }
1301           }
1302           break;
1303         default:
1304           fprintf(stderr, "Unknown Debugger request type = %d\n",
1305                   req->head.request->reqType);
1306           break;
1307         }
1308       free (req); /* Should probably call CVFreeDebuggerRequest() here, but
1309                      can't do so if interrupt level has mucked with req->
1310                      request.  CVFreeDebuggerRequest() only ends up calling
1311                      free() anyway! */
1312     }
1313 }
1314 \f
1315 /* Return a bitmask indicating if the kernel or the pty did something
1316    interesting.  Set poll to non-zero if you don't want to wait.  */
1317
1318 static int
1319 wait_for_events(poll)
1320      int poll;
1321 {
1322   fd_set readfds;
1323   int numfds;
1324   int eventmask = 0;
1325   static struct timeval tv = {0};
1326
1327   /* Output all pending requests. */
1328   CWriteRequestBuffer(conn);
1329
1330   FD_ZERO(&readfds);
1331
1332   /* Wait till there's some activity from the kernel or the pty. */
1333   do
1334     {
1335       FD_SET(kerfd, &readfds);
1336
1337       FD_SET(inferior_pty, &readfds);
1338
1339       if (poll)
1340         numfds = select(sizeof(readfds)*8, &readfds, 0, 0, &tv);
1341       else
1342         numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0);
1343     }
1344   while (numfds <= 0 && !poll);
1345
1346   if (numfds == 0)
1347     return 0;
1348
1349   if (FD_ISSET(inferior_pty, &readfds))
1350     eventmask |= PTY_EVENT;
1351
1352   if (FD_ISSET(kerfd, &readfds))
1353     eventmask |= KERNEL_EVENT;
1354
1355   return eventmask;
1356 }
1357 \f
1358 /* This is called from read_command_lines() to provide the text for breakpoint
1359    commands, which is supplied in a BreakCommands message.  Each call to this
1360    routine supplies a single line of text, with the newline removed. */
1361
1362 /* This routine may be invoked in two different contexts.  In the first, it
1363    is being called as a result of the BreakCommands message.  In this case,
1364    all of the command text is immediately available.  In the second case, it is
1365    called as a result of the user typing the 'command' command.  The command
1366    text then needs to be glommed out of UserInput messages (and possibly other
1367    messages as well).  The most 'straighforward' way of doing this is to
1368    basically simulate the main loop, but just accumulate the command text
1369    instead of sending it to execute_command().  */
1370
1371 char *
1372 energize_command_line_input(prompt, repeat)
1373      char *prompt;
1374      int repeat;
1375 {
1376   char *p;
1377
1378   if (!energize)
1379     return command_line_input(prompt, repeat);
1380
1381   if (doing_breakcommands_message)
1382     {
1383       if (command_line_length <= 0)
1384         return (char *)NULL;
1385
1386       p = command_line_text;
1387
1388       while (command_line_length-- > 0)
1389         {
1390           if (*command_line_text == '\n')
1391             {
1392               *command_line_text = '\000';
1393               command_line_text++;
1394               break;
1395             }
1396           command_line_text++;
1397         }
1398
1399       printf_filtered("%s\n", p);
1400       return p;
1401     }
1402   else
1403     {
1404       /* We come here when the user has typed the 'command' or 'define' command
1405          to the GDB window.  We are basically deep inside of the 'command'
1406          command processing routine right now, and will be called to get a new
1407          line of input.  We expect that kernel_dispatch will queue up only one
1408          command at a time. */
1409
1410       int eventmask;
1411       static char buf[100];
1412       
1413       eventmask = wait_for_events(0);
1414
1415       if (eventmask & PTY_EVENT)
1416         pty_to_kernel();
1417
1418       if (eventmask & KERNEL_EVENT)
1419         kernel_dispatch(1);     /* Queue up commands */
1420
1421 /* Note that command has been echoed by the time we get here */
1422
1423       p = dequeue_command();
1424
1425       if (p)
1426         {
1427           strncpy(buf, p, sizeof(buf));
1428           free(p);
1429           return buf;
1430         }
1431       else
1432         return NULL;
1433     }
1434 }
1435 \f
1436 /* Establish contact with the kernel. */
1437
1438 void
1439 energize_initialize(energize_id, execarg)
1440      char *energize_id;
1441      char *execarg;
1442 {
1443   CTtyRequest *req;
1444   char *ctmp;
1445   extern long strtol(char *str, char **ptr, int base);
1446   char pathname[MAXPATHLEN];
1447   int n;
1448
1449   if (!energize_id)
1450     return;
1451
1452   if (!execarg) execarg = "";
1453
1454   exec_file = strdup(execarg);  /* Save for later */
1455
1456   printf("\ngdb-debugger pid=%d\n", getpid()); /* XXX - debugging only */
1457   
1458   /* First establish the connection with the kernel. */
1459
1460   kerfd = COpenClientSocket(NULL);
1461   if (kerfd < 0) {
1462     printf("COpenClientSocket() failed\n");
1463     exit(1);
1464   }
1465
1466   /* Setup for I/O interrupts when appropriate. */
1467
1468   signal(SIGIO, SIG_IGN);
1469
1470 #ifdef NCR486
1471   if (ioctl (kerfd,  I_SETSIG, S_INPUT|S_RDNORM) < 0)
1472     perror ("getpty: ioctl I_SETSIG failed");
1473 #else
1474   n = fcntl(kerfd, F_GETFL, 0);
1475   fcntl(kerfd, F_SETFL, n|FASYNC);
1476   fcntl(kerfd, F_SETOWN, getpid()); 
1477 #endif
1478
1479   /* Setup connection buffering. */
1480
1481   CSetSocketBufferSize (kerfd, 12000);
1482
1483   /* Generate a new connection control block. */
1484
1485   conn = NewConnection (0, kerfd, kerfd);
1486   if (!conn) {
1487     printf("NewConnection() failed\n");
1488     exit(1);
1489   }
1490
1491 #ifdef KERNEL_RECORD
1492   kerout = fopen("kernel.output", "+w");
1493
1494   CReadWriteHooks(conn, conn->previewMethod, conn->readMethod, kernel_record);
1495 #endif
1496
1497   /* Tell the kernel that we are the "debugger". */
1498
1499   req = CWriteTtyRequest (conn, QueryConnectionRType);
1500   req->generic.queryconnection.major = 0;
1501   req->generic.queryconnection.minor = 0;
1502   req->generic.queryconnection.cadillacId1=strtol(energize_id, &ctmp, 16);
1503   req->generic.queryconnection.cadillacId2 = strtol(++ctmp, NULL, 16);
1504   req->generic.queryconnection.nProtocols = 1;
1505   CWriteProtocol (conn, 0, 0, "debugger");
1506   CWriteLength (conn);
1507
1508   /* Tell the kernel that we are actually running. */
1509
1510   /* KROCK ALERT!!!  The kernel doesn't really care about the arguments to
1511      the program at all!  It only cares that argument 7 be the name of the
1512      target program.  So, we just fill in the rest of the slots with
1513      padding.  I hope the kernel never cares about this! */
1514
1515   req = CWriteTtyRequest (conn, RunningProgramRType);
1516   req->runningprogram.argc = 8;
1517   getcwd (pathname, MAXPATHLEN);
1518   CWriteVstring0 (conn, pathname);
1519
1520   CWriteVstring0 (conn, "0");
1521   CWriteVstring0 (conn, "1");
1522   CWriteVstring0 (conn, "2");
1523   CWriteVstring0 (conn, "3");
1524   CWriteVstring0 (conn, "4");
1525   CWriteVstring0 (conn, "5");
1526   CWriteVstring0 (conn, "6");
1527   CWriteVstring0 (conn, execarg);
1528   CWriteLength (conn);
1529
1530   /* Tell the kernel our PID and all that */
1531
1532   program_id = 1;
1533   CVWriteDebugProgramInfo(conn,
1534                           getpid(),
1535                           program_id,
1536                           execarg,
1537                           "");
1538
1539   /* Tell the rest of the world that Energize is now set up. */
1540   energize = 1;
1541
1542   getpty();                     /* Setup the pty */
1543
1544   /* Attach all GDB I/O to the pty */
1545
1546   dup2(inferior_tty, 0);
1547   dup2(inferior_tty, 1);
1548   dup2(inferior_tty, 2);
1549 }
1550
1551 /* This is called from execute_command, and provides a wrapper around
1552    various command routines in a place where both protocol messages and
1553    user input both flow through.
1554 */
1555
1556 void
1557 energize_call_command(cmdblk, arg, from_tty)
1558      struct cmd_list_element *cmdblk;
1559      char *arg;
1560      int from_tty;
1561 {
1562   if (!energize)
1563     {
1564       (*cmdblk->function.cfunc) (arg, from_tty);
1565       return;
1566     }
1567
1568   if (cmdblk->class == class_run)
1569     {
1570       go_busy();
1571       has_run = 1;
1572       (*cmdblk->function.cfunc)(arg, from_tty);
1573       send_status();
1574     }
1575   else
1576     (*cmdblk->function.cfunc)(arg, from_tty);
1577
1578   if (STREQ(cmdblk->name, "up")
1579       || STREQ(cmdblk->name, "down")
1580       || STREQ(cmdblk->name, "frame"))
1581     send_location(get_frame_info(selected_frame)->pc,
1582                   selected_frame_level);
1583   print_prompt();
1584 }
1585
1586 void
1587 energize_new_process()
1588 {
1589   instance_id = inferior_pid;
1590 }
1591
1592 static void
1593 iosig(signo)
1594      int signo;
1595 {
1596   while (1)
1597     {
1598       int eventmask;
1599
1600       eventmask = wait_for_events(1);
1601
1602       if (eventmask == 0)
1603         return;
1604
1605       if (eventmask & PTY_EVENT)
1606         pty_to_kernel();
1607
1608       if (eventmask & KERNEL_EVENT)
1609         kernel_dispatch(1);
1610     }
1611 }
1612
1613 int
1614 energize_wait(status)
1615      int *status;
1616 {
1617   int pid;
1618   struct sigaction action;
1619   static sigset_t nullsigmask = {0};
1620
1621   if (!energize)
1622     return target_wait(status);
1623
1624 #ifdef NCR486
1625   action.sa_handler = iosig;
1626   action.sa_mask = nullsigmask;
1627   action.sa_flags = SA_RESTART;
1628   sigaction(SIGIO, &action, NULL);
1629 #else
1630   signal(SIGIO, iosig);
1631 #endif
1632
1633   pid = target_wait(status);
1634
1635   signal(SIGIO, SIG_IGN);
1636   return pid;
1637 }
1638
1639 int
1640 energize_shell_wait(status)
1641      int *status;
1642 {
1643   int pid;
1644   struct sigaction action;
1645   static sigset_t nullsigmask = {0};
1646
1647   if (!energize)
1648     return wait(status);
1649
1650 #ifdef NCR486
1651   action.sa_handler = iosig;
1652   action.sa_mask = nullsigmask;
1653   action.sa_flags = SA_RESTART;
1654   sigaction(SIGIO, &action, NULL);
1655 #else
1656   signal(SIGIO, iosig);
1657 #endif
1658
1659   pid = wait(status);
1660
1661   signal(SIGIO, SIG_IGN);
1662   return pid;
1663 }
1664
1665 static void
1666 null_routine(arg)
1667      int arg;
1668 {
1669 }
1670
1671 /* All requests from the Energize kernel eventually end up here. */
1672
1673 void
1674 energize_main_loop()
1675 {
1676   CTtyRequest *req;
1677   struct cleanup *old_chain;
1678
1679   doing_breakcommands_message = 0;
1680
1681 /* We will come thru here any time there is an error, so send status if
1682    necessary. */
1683
1684   send_status();
1685
1686   print_prompt();
1687
1688   /* The actual event loop! */
1689
1690   while (1)
1691     {
1692       int eventmask;
1693       char *cmd;
1694
1695       old_chain = make_cleanup(null_routine, 0);
1696
1697 /* First, empty out the command queue, then check for new requests. */
1698
1699       while (cmd = dequeue_command())
1700         {
1701           execute_command_1(1, 0, cmd);
1702           free(cmd);
1703         }
1704
1705       eventmask = wait_for_events(0);
1706
1707       if (eventmask & PTY_EVENT)
1708         pty_to_kernel();
1709
1710       if (eventmask & KERNEL_EVENT)
1711         kernel_dispatch(0);
1712
1713       bpstat_do_actions(&stop_bpstat);
1714       do_cleanups(old_chain);
1715     }
1716 }
This page took 0.125236 seconds and 4 git commands to generate.