Add missed log entry for som.c.
[deliverable/binutils-gdb.git] / gdb / energize.c
CommitLineData
f823634c
SG
1/* Energize (formerly known as Cadillac) interface routines.
2 Copyright 1991, 1992 Free Software Foundation, Inc.
3
4This file is part of GDB.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, 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"
f63f41df 27#include "target.h"
f823634c
SG
28#include <sys/types.h>
29#include <sys/time.h>
30#include <sys/param.h>
509c1804
SG
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"
f823634c
SG
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>
b869d3f4
SG
48#ifdef NCR486
49#include <sys/stropts.h>
50#endif
f823634c
SG
51
52/* Non-zero means that we're doing the energize interface. */
53int energize = 0;
54
00556177
SG
55/* Non-zero means we are reloading breakpoints, etc from the
56 Energize kernel, and we should suppress various messages */
57static int energize_reloading = 0;
58
f823634c
SG
59/* Connection block for debugger<=>kernel communications. */
60static Connection *conn = 0;
61
62/* fd for our socket to the kernel. */
63static int kerfd;
64
65/* The kernel's ID for this instance of the program. */
66static int program_id;
67
68static int instance_id;
69
70/* The fd for the pty associated with the inferior. */
71static int inferior_pty = -1;
72static int inferior_tty = -1;
73
74static int has_run = 0;
75
76extern int pgrp_inferior;
77
78extern char *source_path;
79
b5fee91e
SG
80/* The name of the executable file */
81static char *exec_file;
f823634c
SG
82
83/* Tell energize_command_line_input() where to get its text from */
84static int doing_breakcommands_message = 0;
85
86/* Stash command text here */
87static char *command_line_text = 0;
88static int command_line_length = 0;
89
90/* Flags returned by wait_for_events() */
91#define KERNEL_EVENT 1
92#define PTY_EVENT 2
93
b869d3f4
SG
94static void execute_command_1();
95
f823634c
SG
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
100void
101energize_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
110void
111energize_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
130void
131energize_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
144static void
145pty_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
00556177
SG
157 && (errno == EWOULDBLOCK
158 || errno == EAGAIN)))
f823634c
SG
159 break;
160
161 if (cc < 0)
162 {
163 close(inferior_pty);
164 inferior_pty = -1;
00556177 165 perror("pty_to_kernel: pty read error");
f823634c
SG
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
178static void
179kernel_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;
00556177 193 perror("kernel_to_pty: pty write error");
f823634c
SG
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
201static char *
202full_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
00556177
SG
214 if (symtab->filename[0] == '/')
215 return savestring(symtab->filename, strlen(symtab->filename));
216
f823634c
SG
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
00556177 237 are relative to the current stack height make sense.
f823634c
SG
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
249struct 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. */
256static int stack_info_valid = 0;
257
258static void
259send_stack_info()
260{
261 struct pclist *pclist = 0, *pli, *opli;
262 static struct pclist *old_pclist;
1dfc8dfb 263 struct frame_info *frame;
f823634c
SG
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
5ca812d4
SG
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
325static void
326send_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
f823634c
SG
355/* Tell the kernel where we are in the program, and what the stack looks like.
356 */
357
358static void
359send_status()
5ca812d4
SG
360{
361 char *funcname;
f823634c 362 struct symbol *symbol;
f823634c
SG
363 static int sent_prog_inst = 0;
364
5ca812d4
SG
365 symbol = find_pc_function(stop_pc);
366 funcname = symbol ? symbol->name : "";
367
f823634c
SG
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
f823634c
SG
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
5ca812d4
SG
392 send_location(stop_pc,
393 selected_frame_level); /* Had better be 0! */
f823634c
SG
394
395 CVWriteProgramStoppedInfo(conn,
396 instance_id,
397 0, /* XXX - breakpoint # or signal # */
398 CDebuggerCommand,
399 funcname,
400 "" /* XXX ? transcript */
401 );
402
f823634c
SG
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
408void
409energize_annotate_function(funcname, arg_mode, level)
410 char *funcname;
411 int arg_mode;
412 int level;
413{
f823634c
SG
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)
5ca812d4
SG
424 {
425 funcname = demangled_name;
426 printf_filtered("'");
427 }
f823634c
SG
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)
5ca812d4
SG
440 {
441 free(demangled_name);
442 printf_filtered("'");
443 }
f823634c
SG
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
459static char cum_expr[200]; /* Cumulative expression */
460static char *expr_stack[100] = {cum_expr}; /* Pointers to end of expressions */
461static char **last_expr = expr_stack; /* Current expr stack pointer */
462
463void
464energize_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
566void
567energize_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
582static void
583go_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
593void
594energize_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 */
612static struct command_line *queued_commands = 0;
613static 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
618static void
619queue_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
647static char *
648dequeue_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
663static void
664execute_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);
f823634c 675 echo = va_arg(args, int);
00556177 676
f823634c
SG
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
199b2450 695GDB_FILE *kerout;
f823634c
SG
696
697static int
698kernel_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
709void
710energize_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
722void
723energize_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
747static void
748breakpoint_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
00556177
SG
757 if (!energize
758 || energize_reloading) /* Don't notify energize about breakpoint changes, as it's about to send us
759 a new bunch. */
f823634c
SG
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
794void
795energize_create_breakpoint(b)
796 struct breakpoint *b;
797{
798 breakpoint_notify(b, CEnableBreakpoint);
799}
800
801void
802energize_delete_breakpoint(b)
803 struct breakpoint *b;
804{
805 breakpoint_notify(b, CDeleteBreakpoint);
806}
807
808void
809energize_enable_breakpoint(b)
810 struct breakpoint *b;
811{
812 breakpoint_notify(b, CEnableBreakpoint);
813}
814
815void
816energize_disable_breakpoint(b)
817 struct breakpoint *b;
818{
819 breakpoint_notify(b, CDisableBreakpoint);
820}
821
822void
823energize_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
5ca812d4 831#ifndef NCR486
f823634c
SG
832static void
833getpty()
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);
5ca812d4
SG
852 if (ttyfd < 0)
853 {
854 close(ptyfd);
855 continue;
856 }
f823634c
SG
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}
5ca812d4
SG
876#endif
877/* Alternate getpty for NCRs */
878
879#ifdef NCR486 /* LTL */
880#define MAX_PTM_TRY 16
881#define MAX_GRANTPT_TRY 4
882static void
883getpty()
884{
885 char *slavename;
886 extern char *ptsname();
887 int j, i;
888 int n, mfd, sfd;
00556177 889 struct stat statbuf;
5ca812d4
SG
890 struct termios termios;
891
b869d3f4
SG
892 mfd = open("/dev/ptmx", O_RDWR); /* get the master */
893 if (mfd < 0)
894 error ("getpty: can't locate master\n");
00556177 895
b869d3f4
SG
896 if (grantpt(mfd) < 0) /* get a slave */
897 error ("getpty: can't acquire slave");
5ca812d4 898
b869d3f4 899 unlockpt(mfd);
5ca812d4 900
b869d3f4
SG
901 slavename = ptsname(mfd); /* get the slave device name */
902 if (!slavename)
903 error ("getpty: can't get a pts\n");
5ca812d4 904
b869d3f4 905 /* Drop controlling tty, become pgrp master */
5ca812d4 906
b869d3f4
SG
907 if (setpgid(0, getppid()) == -1)
908 perror("setpgid() failed: ");
5ca812d4 909
b869d3f4
SG
910 if (setsid() == -1)
911 perror("setsid() failed: ");
5ca812d4 912
00556177 913 sfd = open(slavename, O_RDWR);
00556177
SG
914 if (sfd < 0)
915 {
916 close(mfd);
917 error ("getpty: can't open slave\n");
5ca812d4 918 }
00556177 919
b869d3f4
SG
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");
00556177
SG
923
924 /* setup mty for non-blocking I/O. */
925
b869d3f4
SG
926 n = fcntl(mfd, F_GETFL);
927 if (n < 0)
00556177 928 perror ("getpty: fcntl F_GETFL failed");
b869d3f4
SG
929
930 if (fcntl(mfd, F_SETFL, n|O_NDELAY) <0)
931 perror("getpty: fcntl F_SETFL failed");
00556177
SG
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
b869d3f4
SG
938 if (tcgetattr(sfd, &termios))
939 perror("getpty: tcgetattr fails");
00556177 940 termios.c_oflag &= ~OPOST; /* no post-processing */
b869d3f4
SG
941 if (tcsetattr(sfd, TCSANOW, &termios))
942 perror("getpty: tcsetattr fails");
00556177
SG
943
944 inferior_pty=mfd;
945 inferior_tty=sfd;
946
947 return;
5ca812d4 948}
00556177
SG
949
950#endif /* NCR486 */
f823634c
SG
951\f
952/* Examine a protocol packet from the driver. */
953
954static void
955kernel_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:
509c1804 995 fprintf(stderr, "Unknown Tty request type = %d\n",
f823634c
SG
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:
00556177 1102 kill(-pgrp_inferior, SIGINT);
f823634c
SG
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
2e4964ad 1119 if (STREQ(text, "]*[")) /* XXX - What does this mean??? */
f823634c
SG
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;
509c1804 1270 case DynamicLoadRType:
b5fee91e
SG
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:
00556177
SG
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 */
b5fee91e
SG
1284 execute_command_1(1, queue, "exec-file %s", filename);
1285 execute_command_1(1, queue, "symbol-file %s", filename);
00556177
SG
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();
b5fee91e
SG
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 }
509c1804 1302 break;
f823634c 1303 default:
509c1804 1304 fprintf(stderr, "Unknown Debugger request type = %d\n",
f823634c
SG
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
1318static int
1319wait_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);
00556177
SG
1336
1337 FD_SET(inferior_pty, &readfds);
1338
f823634c
SG
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
00556177
SG
1346 if (numfds == 0)
1347 return 0;
1348
f823634c
SG
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
1371char *
1372energize_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
1438void
1439energize_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
b5fee91e
SG
1454 exec_file = strdup(execarg); /* Save for later */
1455
f823634c
SG
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
b869d3f4
SG
1468 signal(SIGIO, SIG_IGN);
1469
00556177
SG
1470#ifdef NCR486
1471 if (ioctl (kerfd, I_SETSIG, S_INPUT|S_RDNORM) < 0)
1472 perror ("getpty: ioctl I_SETSIG failed");
1473#else
f823634c
SG
1474 n = fcntl(kerfd, F_GETFL, 0);
1475 fcntl(kerfd, F_SETFL, n|FASYNC);
00556177
SG
1476 fcntl(kerfd, F_SETOWN, getpid());
1477#endif
f823634c
SG
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;
00556177 1517 getcwd (pathname, MAXPATHLEN);
f823634c
SG
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
f823634c 1542 getpty(); /* Setup the pty */
00556177
SG
1543
1544 /* Attach all GDB I/O to the pty */
1545
1546 dup2(inferior_tty, 0);
f823634c
SG
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
1556void
1557energize_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
2e4964ad
FF
1578 if (STREQ(cmdblk->name, "up")
1579 || STREQ(cmdblk->name, "down")
1580 || STREQ(cmdblk->name, "frame"))
5ca812d4
SG
1581 send_location(get_frame_info(selected_frame)->pc,
1582 selected_frame_level);
f823634c
SG
1583 print_prompt();
1584}
1585
1586void
1587energize_new_process()
1588{
1589 instance_id = inferior_pid;
1590}
1591
1592static void
1593iosig(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
1613int
1614energize_wait(status)
1615 int *status;
1616{
1617 int pid;
b869d3f4 1618 struct sigaction action;
00556177 1619 static sigset_t nullsigmask = {0};
f823634c
SG
1620
1621 if (!energize)
f63f41df 1622 return target_wait(status);
f823634c 1623
00556177
SG
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
f823634c 1630 signal(SIGIO, iosig);
00556177 1631#endif
f823634c 1632
f63f41df 1633 pid = target_wait(status);
f823634c 1634
00556177 1635 signal(SIGIO, SIG_IGN);
f823634c
SG
1636 return pid;
1637}
1638
b869d3f4
SG
1639int
1640energize_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
f823634c
SG
1665static void
1666null_routine(arg)
1667 int arg;
1668{
1669}
1670
1671/* All requests from the Energize kernel eventually end up here. */
1672
1673void
1674energize_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.204942 seconds and 4 git commands to generate.