]> Git Repo - binutils.git/blob - gdb/energize.c
* c-exp.y (parse_number): Change high_bit to unsigned.
[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   extern int demangle;
415   char *demangled_name = NULL;
416
417   if (funcname == NULL)
418     return;
419
420   if (demangle)
421     {
422       demangled_name = cplus_demangle(funcname, arg_mode);
423
424       if (demangled_name)
425         {
426           funcname = demangled_name;
427           printf_filtered("'");
428         }
429     }
430
431   send_stack_info();
432
433   if (level < 0) level = 0;
434
435   CVWriteBackTraceEntryInfo(conn,
436                             instance_id,
437                             level, /* frameNo */
438                             funcname);
439
440   if (demangled_name)
441     {
442       free(demangled_name);
443       printf_filtered("'");
444     }
445 }
446
447 /* Call this just prior to printing out the name & value of a variable.  This
448    tells the kernel where to annotate the output. */
449
450 /* The args are:
451    expression - A text handle on what GDB can use to reference this value.
452                 This can be a symbol name, or a convenience var, etc...
453    symbol - Used to determine the scope of the data.  May be NULL.
454    type - Determines if we have a pointer ref, and the print name of the type.
455           Used in ShowValue message.
456    valaddr - The address in target memory of the data.
457    field - The field name of the struct or union element being referenced.
458 */
459
460 static char cum_expr[200];      /* Cumulative expression */
461 static char *expr_stack[100] = {cum_expr}; /* Pointers to end of expressions */
462 static char **last_expr = expr_stack;   /* Current expr stack pointer */
463
464 void
465 energize_start_variable_annotation(expression, symbol, type, valaddr, field)
466      char *expression;
467      struct symbol *symbol;
468      struct type *type;
469      CORE_ADDR valaddr;
470      char *field;
471 {
472   int ref_type;
473   int stor_cl;
474   enum type_code type_code;
475   enum address_class sym_class;
476   char *type_cast;
477
478   if (!energize)
479     return;
480
481   send_stack_info();
482
483   strcpy(*last_expr++, expression);
484   *last_expr = *(last_expr-1) + strlen(expression);
485
486   switch (TYPE_CODE(type))
487     {
488     case TYPE_CODE_ARRAY:
489     case TYPE_CODE_STRUCT:
490     case TYPE_CODE_UNION:
491     case TYPE_CODE_ENUM:
492     case TYPE_CODE_INT:
493     case TYPE_CODE_FLT:
494       ref_type = CValueValueRef;
495       break;
496     case TYPE_CODE_PTR:
497       ref_type = CValuePointerRef;
498       break;
499     default:
500       ref_type = CValueUndefRef;
501       break;
502     }
503
504 /* Make sure that pointer points at something we understand */
505
506   if (ref_type == CValuePointerRef)
507     switch (TYPE_CODE(TYPE_TARGET_TYPE(type)))
508       {
509       case TYPE_CODE_PTR:
510       case TYPE_CODE_ARRAY:
511       case TYPE_CODE_STRUCT:
512       case TYPE_CODE_UNION:
513       case TYPE_CODE_ENUM:
514       case TYPE_CODE_INT:
515       case TYPE_CODE_FLT:
516         break;
517       default:
518         ref_type = CValueUndefRef;
519         break;
520       }
521
522   if (symbol)
523     {
524       sym_class = SYMBOL_CLASS(symbol);
525
526       switch (sym_class)
527         {
528         case LOC_CONST:
529         case LOC_CONST_BYTES:
530           stor_cl = CValueStorStaticConst;
531           break;
532         case LOC_STATIC:
533           stor_cl = CValueStorStaticVar;
534           break;
535         case LOC_REGISTER:
536         case LOC_REGPARM:
537           stor_cl = CValueStorRegister;
538           break;
539         case LOC_ARG:
540         case LOC_REF_ARG:
541         case LOC_LOCAL:
542         case LOC_LOCAL_ARG:
543           stor_cl = CValueStorLocalVar;
544           break;
545         default:
546           stor_cl = CValueStorUndef;
547           break;
548         }
549     }
550   else
551     stor_cl = CValueStorUndef;
552
553   type_cast = TYPE_NAME(type);
554
555   CVWriteValueBeginInfo(conn,
556                         instance_id,
557                         valaddr,
558                         ref_type,
559                         stor_cl,
560                         0,      /* XXX - frameno */
561                         cum_expr,
562                         field,
563                         type_cast,
564                         "");    /* transcript */
565 }
566
567 void
568 energize_end_variable_annotation()
569 {
570   if (!energize)
571     return;
572
573   last_expr--;                  /* Pop the expr stack */
574   **last_expr = '\000';         /* Cut off the last part of the expr */
575
576   CVWriteValueEndInfo(conn,
577                       instance_id,
578                       "");      /* transcript */
579 }
580 \f
581 /* Tell the kernel that the target is now running. */
582
583 static void
584 go_busy()
585 {
586   CVWriteProgramBusyInfo(conn,
587                          instance_id,
588                          "");   /* XXX ? transcript */
589   CWriteRequestBuffer(conn);    /* Must take place synchronusly! */
590   stack_info_valid = 0;
591 }
592
593 \f
594 void
595 energize_symbol_file(objfile)
596      struct objfile *objfile;
597 {
598   if (!energize)
599     return;
600
601   CVWriteSymbolTableInfo(conn,
602                          objfile->name,
603                          "");   /* Transcript */
604 }
605
606 /* execute_command_1(echo, queue, cmd, args) - echo - non-zero means echo the
607    command.  queue - non-zero means don't execute it now, just save it away for
608    later.  cmd - string containing printf control sequences.  args - list of
609    arguments needed by those control sequences.
610  */
611
612 /* Linked list of queued up commands */
613 static struct command_line *queued_commands = 0;
614 static struct command_line *last_queued_command = 0;
615
616 /* Call this routine to save a command for later.  The command string is
617    copied into freshly malloc'ed memory. */
618
619 static void
620 queue_command(cmd)
621      char *cmd;
622 {
623   char *buf;
624   struct command_line *cl;
625   unsigned long s;
626
627   s = (strlen(cmd) + 1) + 7 & ~(unsigned long)7;
628
629   buf = (char *)xmalloc(s + sizeof(struct command_line));
630   cl = (struct command_line *)(buf + s);
631   cl->next = 0;
632   cl->line = buf;
633
634   strncpy(cl->line, cmd, s);
635
636   if (queued_commands)
637     last_queued_command->next = cl;
638   else
639     queued_commands = cl;
640
641   last_queued_command = cl;
642 }
643
644 /* Call this procedure to take a command off of the command queue.  It returns
645    a pointer to a buf which the caller is responsible for freeing.  NULL is
646    returned if there are no commands queued. */
647
648 static char *
649 dequeue_command()
650 {
651   struct command_line *cl;
652   char *cmd;
653
654   cl = queued_commands;
655
656   if (!cl)
657     return NULL;
658
659   queued_commands = cl->next;
660
661   return cl->line;
662 }
663
664 static void
665 execute_command_1(va_alist)
666      va_dcl
667 {
668   char buf[100];                /* XXX - make buf dynamic! */
669   
670   int echo;
671   int queue;
672   char *cmd;
673   va_list args;
674
675   va_start(args);
676   echo = va_arg(args, int);
677
678   queue = va_arg(args, int);
679   cmd = va_arg(args, char *);
680
681   vsprintf(buf, cmd, args);
682
683   if (queue)
684     queue_command(buf);
685   else
686     {
687       if (echo)
688         printf_filtered("%s\n", buf);
689       execute_command(buf, 1);
690     }
691
692   va_end(args);
693 }
694
695 #ifdef KERNEL_RECORD
696 FILE *kerout;
697
698 static int
699 kernel_record(fd, ptr, num)
700      int fd, num;
701      char *ptr;
702
703 {
704   fwrite(ptr, num, 1, kerout);
705   fflush(kerout);
706   return write(fd, ptr, num);
707 }
708 #endif
709
710 void
711 energize_condition_breakpoint(b)
712      struct breakpoint *b;
713 {
714   if (energize)
715     CVWriteBreakConditionInfo(conn,
716                               instance_id,
717                               b->number,
718                               b->cond_string ? b->cond_string : "",
719                               "" /* transcript */
720                               );
721 }
722
723 void
724 energize_commands_breakpoint(b)
725      struct breakpoint *b;
726 {
727   struct command_line *l;
728
729   if (!energize)
730     return;
731
732   CVWriteBreakCommandBegInfo(conn,
733                              instance_id,
734                              b->number,
735                              ""); /* transcript */
736
737   for (l = b->commands; l; l = l->next)
738     CVWriteBreakCommandEntryInfo(conn,
739                                  instance_id,
740                                  l->line,
741                                  ""); /* transcript */
742
743   CVWriteBreakCommandEndInfo(conn,
744                              instance_id,
745                              ""); /* transcript */
746 }
747
748 static void
749 breakpoint_notify(b, action)
750      struct breakpoint *b;
751      int action;
752 {
753   struct symbol *sym;
754   char *funcname = "";
755   char *filename;
756   char *included_in_filename = "";
757
758   if (!energize
759       || energize_reloading)    /* Don't notify energize about breakpoint changes, as it's about to send us
760                                    a new bunch.  */
761     return;
762
763   if (b->type != bp_breakpoint)
764     return;
765
766   filename = full_filename(b->symtab);
767
768   sym = find_pc_function(b->address);
769   if (sym)
770     funcname = SYMBOL_NAME(sym);
771
772   CVWriteBreakpointInfo (conn,
773                          instance_id,
774                          b->number,
775                          b->line_number,
776                          CFileLinePos,
777                          CBreakOnInstrAccess,
778                          action,
779                          b->ignore_count,
780                          funcname,
781                          filename ? filename : "",
782                          "",    /* included_in_filename */
783                          ""     /* transcript */
784                          );
785
786   if (b->commands)
787     energize_commands_breakpoint(b);
788
789   energize_condition_breakpoint(b);
790
791   if (filename)
792     free(filename);
793 }
794
795 void
796 energize_create_breakpoint(b)
797      struct breakpoint *b;
798 {
799   breakpoint_notify(b, CEnableBreakpoint);
800 }
801
802 void
803 energize_delete_breakpoint(b)
804      struct breakpoint *b;
805 {
806   breakpoint_notify(b, CDeleteBreakpoint);
807 }
808
809 void
810 energize_enable_breakpoint(b)
811      struct breakpoint *b;
812 {
813   breakpoint_notify(b, CEnableBreakpoint);
814 }
815
816 void
817 energize_disable_breakpoint(b)
818      struct breakpoint *b;
819 {
820   breakpoint_notify(b, CDisableBreakpoint);
821 }
822
823 void
824 energize_ignore_breakpoint(b)
825      struct breakpoint *b;
826 {
827   breakpoint_notify(b, CBreakAttrUnchanged);
828 }
829 \f
830 /* Open up a pty and its associated tty.  Return the fd of the tty. */
831
832 #ifndef NCR486
833 static void
834 getpty()
835 {
836   int n, ptyfd, ttyfd;
837   static char dev[30];
838   struct stat statbuf;
839   struct termios termios;
840
841 #define HIGHPTY (('z' - 'p') * 16 - 1)
842
843   for (n = 0; n <= HIGHPTY; n++)
844     {
845       sprintf(dev, "/dev/pty%c%x", n/16 + 'p', n%16);
846       if (stat(dev, &statbuf))
847         break;
848       ptyfd = open(dev, O_RDWR);
849       if (ptyfd < 0)
850         continue;
851       sprintf(dev, "/dev/tty%c%x", n/16 + 'p', n%16);
852       ttyfd = open(dev, O_RDWR);
853       if (ttyfd < 0)
854         {
855           close(ptyfd);
856           continue;
857         }
858
859       /* Setup pty for non-blocking I/O.  Also make it give us a SIGIO when
860          there's data available.  */
861
862       n = fcntl(ptyfd, F_GETFL, 0);
863       fcntl(ptyfd, F_SETFL, n|FNDELAY|FASYNC);
864       fcntl(ptyfd, F_SETOWN, getpid());
865
866       tcgetattr(ttyfd, &termios);
867       termios.c_oflag &= ~OPOST; /* No post-processing */
868       tcsetattr(ttyfd, TCSANOW, &termios);
869
870       inferior_pty = ptyfd;
871       inferior_tty = ttyfd;
872       return;
873     }
874
875   error ("getpty: can't get a pty\n");
876 }
877 #endif
878 /* Alternate getpty for NCRs */
879
880 #ifdef NCR486 /* LTL */
881 #define MAX_PTM_TRY 16
882 #define MAX_GRANTPT_TRY 4
883 static void
884 getpty()
885 {
886   char *slavename;
887   extern char *ptsname();
888   int j, i;
889   int n, mfd, sfd;
890   struct stat statbuf; 
891   struct termios termios;
892
893   mfd = open("/dev/ptmx", O_RDWR); /* get the master */
894   if (mfd < 0)
895     error ("getpty: can't locate master\n");
896
897   if (grantpt(mfd) < 0) /* get a slave */
898     error ("getpty: can't acquire slave");
899
900   unlockpt(mfd);
901
902   slavename = ptsname(mfd); /* get the slave device name */
903   if (!slavename)
904     error ("getpty: can't get a pts\n");
905
906   /* Drop controlling tty, become pgrp master */
907
908   if (setpgid(0, getppid()) == -1)
909     perror("setpgid() failed: ");
910
911   if (setsid() == -1)
912     perror("setsid() failed: ");
913
914   sfd = open(slavename, O_RDWR);
915   if (sfd < 0)
916     {
917       close(mfd);
918       error ("getpty: can't open slave\n");
919     }
920
921
922   if (ioctl(sfd, I_PUSH, "ptem")) perror ("getpty: ioctl I_PUSH fails");
923   if (ioctl(sfd, I_PUSH, "ldterm")) perror ("getpty: ioctl I_PUSH fails");
924
925   /* setup mty for non-blocking I/O. */
926
927   n = fcntl(mfd, F_GETFL);
928   if (n < 0)
929     perror ("getpty: fcntl F_GETFL failed");
930
931   if (fcntl(mfd, F_SETFL, n|O_NDELAY) <0)
932     perror("getpty: fcntl F_SETFL failed");
933
934   /* set up for async i/o - V.4 will send SIGPOLL when data available */
935
936   if (ioctl (mfd,  I_SETSIG, S_INPUT|S_RDNORM) < 0)
937     perror ("getpty: ioctl I_SETSIG failed");
938
939   if (tcgetattr(sfd, &termios))
940     perror("getpty: tcgetattr fails");
941   termios.c_oflag &= ~OPOST;    /* no post-processing */
942   if (tcsetattr(sfd, TCSANOW, &termios))
943     perror("getpty: tcsetattr fails");
944
945   inferior_pty=mfd;
946   inferior_tty=sfd;
947
948   return;
949
950
951 #endif /* NCR486 */
952 \f
953 /* Examine a protocol packet from the driver. */
954
955 static void
956 kernel_dispatch(queue)
957      int queue;                 /* Non-zero means we should just queue up
958                                    commands. */
959 {
960   register CHeader *head;
961
962   head = (CHeader *)CPeekNextRequest (conn);
963   if (head == NULL)
964     {
965       fprintf (stderr, "EOF on kernel read!\n");
966       exit (1);
967     }
968
969   if (head->reqType < LastTtyRequestRType)
970     {
971       CTtyRequest* req = CReadTtyRequest (conn);
972       switch (req->head.reqType)
973         {
974         case AcceptConnectionRType:
975           /* Tell the rest of the world that energize is now set up */
976           CSkipRequest (conn);
977           break;
978
979         case RefuseConnectionRType:
980           fprintf (stderr, "Debugger connection refused\n");
981           exit (1);
982
983         case KillProgramRType:
984           exit (0);
985
986         case TextIORType:
987           {
988             char *p;
989             ReqLen len;
990
991             p = CGetVstring(conn, &len);
992             kernel_to_pty(p, len);
993           }
994           break;
995         default:
996           fprintf(stderr, "Unknown Tty request type = %d\n",
997                   req->head.reqType);
998           break;
999         }
1000     }
1001   else
1002     {
1003       CVDebuggerRequest *req = CVReadDebuggerRequest (conn);
1004       if (!req)
1005         {
1006           fprintf (stderr, "CVReadDebuggerRequest returned NULL, type = %d\n",
1007                    head->reqType);
1008           exit(1);
1009         }
1010
1011       switch (req->head.request->reqType)
1012         {
1013         case OpenProgramInstanceRType:
1014           {
1015             char *arglist, buf[100]; /* XXX - Make buf dynamic! */
1016             int arglen;
1017             /* XXX - should notice when program_id changes */
1018             arglist = req->openProgramInstance.progArglist.text;
1019             arglen = req->openProgramInstance.progArglist.byteLen;
1020
1021             execute_command_1(1, queue, "break main");
1022             execute_command_1(1, queue, "enable delete $bpnum");
1023             if (arglist)
1024               {
1025                 execute_command_1(1, queue, "set args %.*s", arglen, arglist);
1026               }
1027             execute_command_1(1, queue, "run");
1028           }
1029           break;
1030         case SearchPathRType:
1031           directory_command(req->searchPath.searchPath.text, 0);
1032           break;
1033         case QuitDebuggerRType:
1034           execute_command_1(1, queue, "quit");
1035           break;
1036         case RunRType:
1037           if (req->run.request->useArglist == CNewArglist)
1038             {
1039               execute_command_1(1, queue, "set args %.*s",
1040                                 req->run.progArglist.byteLen,
1041                                 req->run.progArglist.text);
1042             }
1043           execute_command_1(1, queue, "run");
1044           break;
1045         case ContinueRType:
1046           execute_command_1(1, queue, "continue");
1047           break;
1048         case StepRType:
1049           execute_command_1(1, queue, "step %d", req->step.request->stepCount);
1050           break;
1051         case NextRType:
1052           execute_command_1(1, queue, "next %d", req->next.request->nextCount);
1053           break;
1054         case ChangeStackFrameRType:
1055           switch (req->changeStackFrame.request->frameMovement)
1056             {
1057             case CToCurrentStackFrame:
1058               execute_command_1(1, queue, "frame %d",
1059                                 req->changeStackFrame.request->frameNo);
1060               break;
1061             case CToInnerStackFrame:
1062               execute_command_1(1, queue, "down %d",
1063                                 req->changeStackFrame.request->frameNo);
1064               break;
1065             case CToOuterStackFrame:
1066               execute_command_1(1, queue, "up %d",
1067                                 req->changeStackFrame.request->frameNo);
1068               break;
1069             case CToAbsoluteStackFrame:
1070               execute_command_1(1, queue, "frame %d",
1071                                 req->changeStackFrame.request->frameNo);
1072               break;
1073             }
1074           break;
1075         case BackTraceRType:
1076           /* XXX - deal with limit??? */
1077           execute_command_1(1, queue, "backtrace");
1078           break;
1079         case FinishRType:
1080           execute_command_1(1, queue, "finish");
1081           break;
1082         case TerminateProgramRType:
1083           execute_command_1(1, queue, "kill");
1084           break;
1085         case NewBreakpointRType:
1086           {
1087             char *tail;
1088             int skipped;
1089
1090             tail = strrchr(req->newBreakpoint.fileName.text, '/');
1091             if (!tail)
1092               tail = req->newBreakpoint.fileName.text;
1093             else
1094               tail++;
1095             skipped = tail - req->newBreakpoint.fileName.text;
1096             execute_command_1(1, queue, "break %.*s:%d",
1097                               req->newBreakpoint.fileName.byteLen - skipped,
1098                               tail,
1099                               req->newBreakpoint.request->fileLinePos);
1100           }
1101           break;
1102         case StopRType:
1103           kill(-pgrp_inferior, SIGINT);
1104           break;
1105         case UserInputRType:
1106           {
1107             char *text;
1108             long len;
1109
1110             /* XXX - should really break command up into seperate lines
1111                and spoon-feed it to execute_command */
1112
1113             text = req->userInput.userInput.text;
1114             len = req->userInput.userInput.byteLen;
1115
1116             if (text[len-1] == '\n') text[len-1] = '\000';
1117
1118             while (*text == ' ' || *text == '\t') text++;
1119
1120             if (STREQ(text, "]*[")) /* XXX - What does this mean??? */
1121               break;
1122
1123             if (*text != '\000')
1124               execute_command_1(0, queue, "%s", text);
1125             else
1126               print_prompt();   /* User just typed a blank line */
1127           }
1128           break;
1129         case QueryResponseRType:
1130           {
1131             char *resp;
1132
1133             if (req->queryResponse.request->response)
1134               resp = "y";
1135             else
1136               resp = "n";
1137             execute_command_1(1, 1, resp);
1138             printf_filtered("%s\n", resp);
1139           }
1140           break;
1141         case ChangeBreakpointRType:
1142           switch (req->changeBreakpoint.request->breakpointAttr)
1143             {
1144             case CBreakAttrUnchanged:
1145               execute_command_1(1, queue, "ignore %d %d",
1146                                 req->changeBreakpoint.request->breakpointId,
1147                                 req->changeBreakpoint.request->ignoreCount);
1148               break;
1149             case CEnableBreakpoint:
1150               execute_command_1(1, queue, "enable %d",
1151                                 req->changeBreakpoint.request->breakpointId);
1152               break;
1153             case CDisableBreakpoint:
1154               execute_command_1(1, queue, "disable %d",
1155                                 req->changeBreakpoint.request->breakpointId);
1156               break;
1157             case CDeleteBreakpoint:
1158               execute_command_1(1, queue, "delete %d",
1159                                 req->changeBreakpoint.request->breakpointId);
1160               break;
1161             case CEnableDisableBreakpoint:
1162               execute_command_1(1, queue, "enable once %d",
1163                                 req->changeBreakpoint.request->breakpointId);
1164               break;
1165             case CEnableDeleteBreakpoint:
1166               execute_command_1(1, queue, "enable delete %d",
1167                                 req->changeBreakpoint.request->breakpointId);
1168               break;
1169             default:
1170               printf_filtered("ChangeBreakpointRType: unknown breakpointAttr\n");
1171               printf_filtered("  breakpointAttr = %d\n",
1172                               req->changeBreakpoint.request->breakpointAttr);
1173               printf_filtered("  breakpointId = %d\n",
1174                               req->changeBreakpoint.request->breakpointId);
1175               printf_filtered("  breakpointType = %d\n",
1176                               req->changeBreakpoint.request->breakpointType);
1177               printf_filtered("  ignoreCount = %d\n",
1178                               req->changeBreakpoint.request->ignoreCount);
1179               break;
1180             }
1181           break;
1182         case BreakConditionRType:
1183           execute_command_1(1, queue, "condition %d %.*s",
1184                           req->breakCondition.request->breakpointId,
1185                           req->breakCondition.condition.byteLen,
1186                           req->breakCondition.condition.text);
1187           break;
1188         case BreakCommandsRType:
1189           /* Put pointers to where energize_command_line_input() can find
1190              them. */
1191           doing_breakcommands_message = 1;
1192           command_line_length = req->breakCommands.commands.byteLen;
1193           command_line_text = req->breakCommands.commands.text;
1194           execute_command_1(1, queue, "commands %d",
1195                             req->breakCommands.request->breakpointId);
1196           command_line_text = (char *)NULL;
1197           command_line_length = 0;
1198           doing_breakcommands_message = 0;
1199           break;
1200         case ShowValueRType:
1201           {
1202             char expr[100], *p = expr;
1203
1204             expr[0] = 0;
1205
1206             if (req->showValue.request->ref_type == CValuePointerRef)
1207               strcat(expr, "* ");
1208
1209             if (req->showValue.type_cast.byteLen)
1210               {
1211                 strcat(expr, "(");
1212                 strncat(expr, req->showValue.type_cast.text,
1213                         req->showValue.type_cast.byteLen);
1214                 strcat(expr, ") ");
1215               }
1216
1217             if (req->showValue.field.byteLen)
1218               strcat(expr, "(");
1219
1220             strncat(expr, req->showValue.expression.text,
1221                     req->showValue.expression.byteLen);
1222
1223             if (req->showValue.field.byteLen)
1224               {
1225                 strcat(expr, ")");
1226
1227                 strncat(expr, req->showValue.field.text,
1228                         req->showValue.field.byteLen);
1229               }
1230
1231             execute_command_1(1, queue, "print %s", expr);
1232           }
1233           break;
1234         case SetValueRType:
1235           {
1236             char expr[100], *p = expr;
1237
1238             expr[0] = 0;
1239
1240             if (req->setValue.request->ref_type == CValuePointerRef)
1241               strcat(expr, "* ");
1242
1243 #if 0
1244             if (req->setValue.type_cast.byteLen)
1245               {
1246                 strcat(expr, "(");
1247                 strncat(expr, req->setValue.type_cast.text,
1248                         req->setValue.type_cast.byteLen);
1249                 strcat(expr, ") ");
1250               }
1251 #endif
1252             if (req->setValue.field.byteLen)
1253               strcat(expr, "(");
1254
1255             strncat(expr, req->setValue.expression.text,
1256                     req->setValue.expression.byteLen);
1257
1258             if (req->setValue.field.byteLen)
1259               {
1260                 strcat(expr, ")");
1261
1262                 strncat(expr, req->setValue.field.text,
1263                         req->setValue.field.byteLen);
1264               }
1265
1266             execute_command_1(1, queue, "print %s = (%s) %s", expr,
1267                               req->setValue.type_cast.text,
1268                               req->setValue.value.text);
1269           }
1270           break;
1271         case DynamicLoadRType:
1272           {
1273             char *filename;
1274
1275             filename = req->dynamicLoad.filenames.byteLen ?
1276               req->dynamicLoad.filenames.text : exec_file;
1277
1278             switch (req->dynamicLoad.request->action)
1279               {
1280               case CDynamicLoadUpdateSymtab:
1281                 energize_reloading = 1;
1282                 execute_command_1(1, queue, "set confirm no");
1283                 execute_command_1(1, queue, "delete");
1284 /*              execute_command_1(1, queue, "set $bpnum=1");*/ /* Use this to reset breakpoint #s */
1285                 execute_command_1(1, queue, "exec-file %s", filename);
1286                 execute_command_1(1, queue, "symbol-file %s", filename);
1287                 execute_command_1(1, queue, "set confirm yes");
1288                 energize_reloading = 0;
1289                 break;
1290               case CDynamicLoadRestoreStart:
1291                 break;
1292               case CDynamicLoadRestoreEnd: /* Not used anymore??? */
1293                 printf_filtered("\n[Target has changed, automatic restoration of state has been done.]\n");
1294                 print_prompt();
1295                 break;
1296               default:
1297                 printf_filtered("DynamicLoadRType: unknown action=%d, filename=%s\n",
1298                                 req->dynamicLoad.request->action,
1299                                 req->dynamicLoad.filenames.text);
1300                 break;
1301               }
1302           }
1303           break;
1304         default:
1305           fprintf(stderr, "Unknown Debugger request type = %d\n",
1306                   req->head.request->reqType);
1307           break;
1308         }
1309       free (req); /* Should probably call CVFreeDebuggerRequest() here, but
1310                      can't do so if interrupt level has mucked with req->
1311                      request.  CVFreeDebuggerRequest() only ends up calling
1312                      free() anyway! */
1313     }
1314 }
1315 \f
1316 /* Return a bitmask indicating if the kernel or the pty did something
1317    interesting.  Set poll to non-zero if you don't want to wait.  */
1318
1319 static int
1320 wait_for_events(poll)
1321      int poll;
1322 {
1323   fd_set readfds;
1324   int numfds;
1325   int eventmask = 0;
1326   static struct timeval tv = {0};
1327
1328   /* Output all pending requests. */
1329   CWriteRequestBuffer(conn);
1330
1331   FD_ZERO(&readfds);
1332
1333   /* Wait till there's some activity from the kernel or the pty. */
1334   do
1335     {
1336       FD_SET(kerfd, &readfds);
1337
1338       FD_SET(inferior_pty, &readfds);
1339
1340       if (poll)
1341         numfds = select(sizeof(readfds)*8, &readfds, 0, 0, &tv);
1342       else
1343         numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0);
1344     }
1345   while (numfds <= 0 && !poll);
1346
1347   if (numfds == 0)
1348     return 0;
1349
1350   if (FD_ISSET(inferior_pty, &readfds))
1351     eventmask |= PTY_EVENT;
1352
1353   if (FD_ISSET(kerfd, &readfds))
1354     eventmask |= KERNEL_EVENT;
1355
1356   return eventmask;
1357 }
1358 \f
1359 /* This is called from read_command_lines() to provide the text for breakpoint
1360    commands, which is supplied in a BreakCommands message.  Each call to this
1361    routine supplies a single line of text, with the newline removed. */
1362
1363 /* This routine may be invoked in two different contexts.  In the first, it
1364    is being called as a result of the BreakCommands message.  In this case,
1365    all of the command text is immediately available.  In the second case, it is
1366    called as a result of the user typing the 'command' command.  The command
1367    text then needs to be glommed out of UserInput messages (and possibly other
1368    messages as well).  The most 'straighforward' way of doing this is to
1369    basically simulate the main loop, but just accumulate the command text
1370    instead of sending it to execute_command().  */
1371
1372 char *
1373 energize_command_line_input(prompt, repeat)
1374      char *prompt;
1375      int repeat;
1376 {
1377   char *p;
1378
1379   if (!energize)
1380     return command_line_input(prompt, repeat);
1381
1382   if (doing_breakcommands_message)
1383     {
1384       if (command_line_length <= 0)
1385         return (char *)NULL;
1386
1387       p = command_line_text;
1388
1389       while (command_line_length-- > 0)
1390         {
1391           if (*command_line_text == '\n')
1392             {
1393               *command_line_text = '\000';
1394               command_line_text++;
1395               break;
1396             }
1397           command_line_text++;
1398         }
1399
1400       printf_filtered("%s\n", p);
1401       return p;
1402     }
1403   else
1404     {
1405       /* We come here when the user has typed the 'command' or 'define' command
1406          to the GDB window.  We are basically deep inside of the 'command'
1407          command processing routine right now, and will be called to get a new
1408          line of input.  We expect that kernel_dispatch will queue up only one
1409          command at a time. */
1410
1411       int eventmask;
1412       static char buf[100];
1413       
1414       eventmask = wait_for_events(0);
1415
1416       if (eventmask & PTY_EVENT)
1417         pty_to_kernel();
1418
1419       if (eventmask & KERNEL_EVENT)
1420         kernel_dispatch(1);     /* Queue up commands */
1421
1422 /* Note that command has been echoed by the time we get here */
1423
1424       p = dequeue_command();
1425
1426       if (p)
1427         {
1428           strncpy(buf, p, sizeof(buf));
1429           free(p);
1430           return buf;
1431         }
1432       else
1433         return NULL;
1434     }
1435 }
1436 \f
1437 /* Establish contact with the kernel. */
1438
1439 void
1440 energize_initialize(energize_id, execarg)
1441      char *energize_id;
1442      char *execarg;
1443 {
1444   CTtyRequest *req;
1445   char *ctmp;
1446   extern long strtol(char *str, char **ptr, int base);
1447   char pathname[MAXPATHLEN];
1448   int n;
1449
1450   if (!energize_id)
1451     return;
1452
1453   if (!execarg) execarg = "";
1454
1455   exec_file = strdup(execarg);  /* Save for later */
1456
1457   printf("\ngdb-debugger pid=%d\n", getpid()); /* XXX - debugging only */
1458   
1459   /* First establish the connection with the kernel. */
1460
1461   kerfd = COpenClientSocket(NULL);
1462   if (kerfd < 0) {
1463     printf("COpenClientSocket() failed\n");
1464     exit(1);
1465   }
1466
1467   /* Setup for I/O interrupts when appropriate. */
1468
1469   signal(SIGIO, SIG_IGN);
1470
1471 #ifdef NCR486
1472   if (ioctl (kerfd,  I_SETSIG, S_INPUT|S_RDNORM) < 0)
1473     perror ("getpty: ioctl I_SETSIG failed");
1474 #else
1475   n = fcntl(kerfd, F_GETFL, 0);
1476   fcntl(kerfd, F_SETFL, n|FASYNC);
1477   fcntl(kerfd, F_SETOWN, getpid()); 
1478 #endif
1479
1480   /* Setup connection buffering. */
1481
1482   CSetSocketBufferSize (kerfd, 12000);
1483
1484   /* Generate a new connection control block. */
1485
1486   conn = NewConnection (0, kerfd, kerfd);
1487   if (!conn) {
1488     printf("NewConnection() failed\n");
1489     exit(1);
1490   }
1491
1492 #ifdef KERNEL_RECORD
1493   kerout = fopen("kernel.output", "+w");
1494
1495   CReadWriteHooks(conn, conn->previewMethod, conn->readMethod, kernel_record);
1496 #endif
1497
1498   /* Tell the kernel that we are the "debugger". */
1499
1500   req = CWriteTtyRequest (conn, QueryConnectionRType);
1501   req->generic.queryconnection.major = 0;
1502   req->generic.queryconnection.minor = 0;
1503   req->generic.queryconnection.cadillacId1=strtol(energize_id, &ctmp, 16);
1504   req->generic.queryconnection.cadillacId2 = strtol(++ctmp, NULL, 16);
1505   req->generic.queryconnection.nProtocols = 1;
1506   CWriteProtocol (conn, 0, 0, "debugger");
1507   CWriteLength (conn);
1508
1509   /* Tell the kernel that we are actually running. */
1510
1511   /* KROCK ALERT!!!  The kernel doesn't really care about the arguments to
1512      the program at all!  It only cares that argument 7 be the name of the
1513      target program.  So, we just fill in the rest of the slots with
1514      padding.  I hope the kernel never cares about this! */
1515
1516   req = CWriteTtyRequest (conn, RunningProgramRType);
1517   req->runningprogram.argc = 8;
1518   getcwd (pathname, MAXPATHLEN);
1519   CWriteVstring0 (conn, pathname);
1520
1521   CWriteVstring0 (conn, "0");
1522   CWriteVstring0 (conn, "1");
1523   CWriteVstring0 (conn, "2");
1524   CWriteVstring0 (conn, "3");
1525   CWriteVstring0 (conn, "4");
1526   CWriteVstring0 (conn, "5");
1527   CWriteVstring0 (conn, "6");
1528   CWriteVstring0 (conn, execarg);
1529   CWriteLength (conn);
1530
1531   /* Tell the kernel our PID and all that */
1532
1533   program_id = 1;
1534   CVWriteDebugProgramInfo(conn,
1535                           getpid(),
1536                           program_id,
1537                           execarg,
1538                           "");
1539
1540   /* Tell the rest of the world that Energize is now set up. */
1541   energize = 1;
1542
1543   getpty();                     /* Setup the pty */
1544
1545   /* Attach all GDB I/O to the pty */
1546
1547   dup2(inferior_tty, 0);
1548   dup2(inferior_tty, 1);
1549   dup2(inferior_tty, 2);
1550 }
1551
1552 /* This is called from execute_command, and provides a wrapper around
1553    various command routines in a place where both protocol messages and
1554    user input both flow through.
1555 */
1556
1557 void
1558 energize_call_command(cmdblk, arg, from_tty)
1559      struct cmd_list_element *cmdblk;
1560      char *arg;
1561      int from_tty;
1562 {
1563   if (!energize)
1564     {
1565       (*cmdblk->function.cfunc) (arg, from_tty);
1566       return;
1567     }
1568
1569   if (cmdblk->class == class_run)
1570     {
1571       go_busy();
1572       has_run = 1;
1573       (*cmdblk->function.cfunc)(arg, from_tty);
1574       send_status();
1575     }
1576   else
1577     (*cmdblk->function.cfunc)(arg, from_tty);
1578
1579   if (STREQ(cmdblk->name, "up")
1580       || STREQ(cmdblk->name, "down")
1581       || STREQ(cmdblk->name, "frame"))
1582     send_location(get_frame_info(selected_frame)->pc,
1583                   selected_frame_level);
1584   print_prompt();
1585 }
1586
1587 void
1588 energize_new_process()
1589 {
1590   instance_id = inferior_pid;
1591 }
1592
1593 static void
1594 iosig(signo)
1595      int signo;
1596 {
1597   while (1)
1598     {
1599       int eventmask;
1600
1601       eventmask = wait_for_events(1);
1602
1603       if (eventmask == 0)
1604         return;
1605
1606       if (eventmask & PTY_EVENT)
1607         pty_to_kernel();
1608
1609       if (eventmask & KERNEL_EVENT)
1610         kernel_dispatch(1);
1611     }
1612 }
1613
1614 int
1615 energize_wait(status)
1616      int *status;
1617 {
1618   int pid;
1619   struct sigaction action;
1620   static sigset_t nullsigmask = {0};
1621
1622   if (!energize)
1623     return target_wait(status);
1624
1625 #ifdef NCR486
1626   action.sa_handler = iosig;
1627   action.sa_mask = nullsigmask;
1628   action.sa_flags = SA_RESTART;
1629   sigaction(SIGIO, &action, NULL);
1630 #else
1631   signal(SIGIO, iosig);
1632 #endif
1633
1634   pid = target_wait(status);
1635
1636   signal(SIGIO, SIG_IGN);
1637   return pid;
1638 }
1639
1640 int
1641 energize_shell_wait(status)
1642      int *status;
1643 {
1644   int pid;
1645   struct sigaction action;
1646   static sigset_t nullsigmask = {0};
1647
1648   if (!energize)
1649     return wait(status);
1650
1651 #ifdef NCR486
1652   action.sa_handler = iosig;
1653   action.sa_mask = nullsigmask;
1654   action.sa_flags = SA_RESTART;
1655   sigaction(SIGIO, &action, NULL);
1656 #else
1657   signal(SIGIO, iosig);
1658 #endif
1659
1660   pid = wait(status);
1661
1662   signal(SIGIO, SIG_IGN);
1663   return pid;
1664 }
1665
1666 static void
1667 null_routine(arg)
1668      int arg;
1669 {
1670 }
1671
1672 /* All requests from the Energize kernel eventually end up here. */
1673
1674 void
1675 energize_main_loop()
1676 {
1677   CTtyRequest *req;
1678   struct cleanup *old_chain;
1679
1680   doing_breakcommands_message = 0;
1681
1682 /* We will come thru here any time there is an error, so send status if
1683    necessary. */
1684
1685   send_status();
1686
1687   print_prompt();
1688
1689   /* The actual event loop! */
1690
1691   while (1)
1692     {
1693       int eventmask;
1694       char *cmd;
1695
1696       old_chain = make_cleanup(null_routine, 0);
1697
1698 /* First, empty out the command queue, then check for new requests. */
1699
1700       while (cmd = dequeue_command())
1701         {
1702           execute_command_1(1, 0, cmd);
1703           free(cmd);
1704         }
1705
1706       eventmask = wait_for_events(0);
1707
1708       if (eventmask & PTY_EVENT)
1709         pty_to_kernel();
1710
1711       if (eventmask & KERNEL_EVENT)
1712         kernel_dispatch(0);
1713
1714       bpstat_do_actions(&stop_bpstat);
1715       do_cleanups(old_chain);
1716     }
1717 }
This page took 0.114081 seconds and 4 git commands to generate.