Commit | Line | Data |
---|---|---|
bd5635a1 | 1 | /* Low level interface to ptrace, for GDB when running under Unix. |
ee0613d1 | 2 | Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc. |
bd5635a1 RP |
3 | |
4 | This file is part of GDB. | |
5 | ||
715d2e06 | 6 | This program is free software; you can redistribute it and/or modify |
bd5635a1 | 7 | it under the terms of the GNU General Public License as published by |
715d2e06 JG |
8 | the Free Software Foundation; either version 2 of the License, or |
9 | (at your option) any later version. | |
bd5635a1 | 10 | |
715d2e06 | 11 | This program is distributed in the hope that it will be useful, |
bd5635a1 RP |
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 | |
715d2e06 JG |
17 | along with this program; if not, write to the Free Software |
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
bd5635a1 RP |
19 | |
20 | #include <stdio.h> | |
21 | #include "defs.h" | |
bd5635a1 RP |
22 | #include "frame.h" |
23 | #include "inferior.h" | |
24 | #include "command.h" | |
25 | #include "signals.h" | |
26 | #include "terminal.h" | |
27 | #include "target.h" | |
28 | ||
29 | #ifdef USG | |
30 | #include <sys/types.h> | |
31 | #endif | |
32 | ||
33 | /* Some USG-esque systems (some of which are BSD-esque enough so that USG | |
34 | is not defined) want this header, and it won't do any harm. */ | |
35 | #include <fcntl.h> | |
36 | ||
37 | #include <sys/param.h> | |
bd5635a1 RP |
38 | #include <signal.h> |
39 | ||
2a5ec41d JG |
40 | extern char *strerror(); /* strings corresponding to errno */ |
41 | ||
bd5635a1 RP |
42 | extern struct target_ops child_ops; |
43 | ||
44 | /* Nonzero if we are debugging an attached outside process | |
45 | rather than an inferior. */ | |
46 | ||
47 | int attach_flag; | |
48 | ||
49 | \f | |
50 | /* Record terminal status separately for debugger and inferior. */ | |
51 | ||
2a5ec41d JG |
52 | /* Does GDB have a terminal (on stdin)? */ |
53 | int gdb_has_a_terminal; | |
54 | ||
bd5635a1 RP |
55 | static TERMINAL sg_inferior; |
56 | static TERMINAL sg_ours; | |
57 | ||
58 | static int tflags_inferior; | |
59 | static int tflags_ours; | |
60 | ||
61 | #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) | |
62 | static struct tchars tc_inferior; | |
63 | static struct tchars tc_ours; | |
64 | #endif | |
65 | ||
7d9884b9 | 66 | #if defined(TIOCGLTC) && !defined(TIOCGLTC_BROKEN) |
bd5635a1 RP |
67 | static struct ltchars ltc_inferior; |
68 | static struct ltchars ltc_ours; | |
69 | #endif | |
70 | ||
71 | #ifdef TIOCLGET | |
72 | static int lmode_inferior; | |
73 | static int lmode_ours; | |
74 | #endif | |
75 | ||
76 | #ifdef TIOCGPGRP | |
7d9884b9 JG |
77 | # ifdef SHORT_PGRP |
78 | static short pgrp_inferior; | |
79 | static short pgrp_ours; | |
7e97eb28 | 80 | # else /* not def SHORT_PGRP */ |
bd5635a1 RP |
81 | static int pgrp_inferior; |
82 | static int pgrp_ours; | |
7e97eb28 SG |
83 | # endif /* not def SHORT_PGRP */ |
84 | #else /* not def TIOCGPGRP */ | |
bd5635a1 RP |
85 | static void (*sigint_ours) (); |
86 | static void (*sigquit_ours) (); | |
87 | #endif /* TIOCGPGRP */ | |
88 | ||
2a5ec41d JG |
89 | /* The name of the tty (from the `tty' command) that we gave to the inferior |
90 | when it was last started. */ | |
bd5635a1 | 91 | |
2a5ec41d | 92 | static char *inferior_thisrun_terminal; |
bd5635a1 RP |
93 | |
94 | /* Nonzero if our terminal settings are in effect. | |
95 | Zero if the inferior's settings are in effect. */ | |
2a5ec41d | 96 | |
bd5635a1 RP |
97 | static int terminal_is_ours; |
98 | ||
2a5ec41d JG |
99 | /* Macro for printing errors from ioctl operations */ |
100 | ||
101 | #define OOPSY(what) \ | |
102 | if (result == -1) \ | |
103 | fprintf(stderr, "[%s failed in terminal_inferior: %s]\n", \ | |
104 | what, strerror (errno)) | |
105 | ||
106 | static void terminal_ours_1 (); | |
107 | ||
bd5635a1 RP |
108 | /* Initialize the terminal settings we record for the inferior, |
109 | before we actually run the inferior. */ | |
110 | ||
111 | void | |
112 | terminal_init_inferior () | |
113 | { | |
114 | sg_inferior = sg_ours; | |
115 | tflags_inferior = tflags_ours; | |
116 | ||
117 | #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) | |
118 | tc_inferior = tc_ours; | |
119 | #endif | |
120 | ||
7d9884b9 | 121 | #if defined(TIOCGLTC) && !defined(TIOCGLTC_BROKEN) |
bd5635a1 RP |
122 | ltc_inferior = ltc_ours; |
123 | #endif | |
124 | ||
125 | #ifdef TIOCLGET | |
126 | lmode_inferior = lmode_ours; | |
127 | #endif | |
128 | ||
129 | #ifdef TIOCGPGRP | |
130 | pgrp_inferior = inferior_pid; | |
131 | #endif /* TIOCGPGRP */ | |
132 | ||
133 | terminal_is_ours = 1; | |
134 | } | |
135 | ||
136 | /* Put the inferior's terminal settings into effect. | |
137 | This is preparation for starting or resuming the inferior. */ | |
138 | ||
139 | void | |
140 | terminal_inferior () | |
141 | { | |
2a5ec41d JG |
142 | int result; |
143 | ||
144 | if (gdb_has_a_terminal && terminal_is_ours && inferior_thisrun_terminal == 0) | |
bd5635a1 | 145 | { |
2a5ec41d JG |
146 | result = fcntl (0, F_SETFL, tflags_inferior); |
147 | result = fcntl (0, F_SETFL, tflags_inferior); | |
148 | OOPSY ("fcntl F_SETFL"); | |
149 | result = ioctl (0, TIOCSETN, &sg_inferior); | |
150 | OOPSY ("ioctl TIOCSETN"); | |
bd5635a1 RP |
151 | |
152 | #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) | |
2a5ec41d JG |
153 | result = ioctl (0, TIOCSETC, &tc_inferior); |
154 | OOPSY ("ioctl TIOCSETC"); | |
bd5635a1 | 155 | #endif |
7d9884b9 | 156 | #if defined(TIOCGLTC) && !defined(TIOCGLTC_BROKEN) |
2a5ec41d JG |
157 | result = ioctl (0, TIOCSLTC, <c_inferior); |
158 | OOPSY ("ioctl TIOCSLTC"); | |
bd5635a1 RP |
159 | #endif |
160 | #ifdef TIOCLGET | |
2a5ec41d JG |
161 | result = ioctl (0, TIOCLSET, &lmode_inferior); |
162 | OOPSY ("ioctl TIOCLSET"); | |
bd5635a1 RP |
163 | #endif |
164 | ||
165 | #ifdef TIOCGPGRP | |
2a5ec41d | 166 | result = ioctl (0, TIOCSPGRP, &pgrp_inferior); |
7e97eb28 SG |
167 | /* If we attached to the process, we might or might not be sharing |
168 | a terminal. Avoid printing error msg if we are unable to set our | |
169 | terminal's process group to his process group ID. */ | |
170 | if (!attach_flag) { | |
171 | OOPSY ("ioctl TIOCSPGRP"); | |
172 | } | |
bd5635a1 RP |
173 | #else |
174 | sigint_ours = (void (*) ()) signal (SIGINT, SIG_IGN); | |
175 | sigquit_ours = (void (*) ()) signal (SIGQUIT, SIG_IGN); | |
176 | #endif /* TIOCGPGRP */ | |
177 | } | |
178 | terminal_is_ours = 0; | |
179 | } | |
180 | ||
181 | /* Put some of our terminal settings into effect, | |
182 | enough to get proper results from our output, | |
183 | but do not change into or out of RAW mode | |
184 | so that no input is discarded. | |
185 | ||
186 | After doing this, either terminal_ours or terminal_inferior | |
187 | should be called to get back to a normal state of affairs. */ | |
188 | ||
189 | void | |
190 | terminal_ours_for_output () | |
191 | { | |
192 | terminal_ours_1 (1); | |
193 | } | |
194 | ||
195 | /* Put our terminal settings into effect. | |
196 | First record the inferior's terminal settings | |
197 | so they can be restored properly later. */ | |
198 | ||
199 | void | |
200 | terminal_ours () | |
201 | { | |
202 | terminal_ours_1 (0); | |
203 | } | |
204 | ||
205 | static void | |
206 | terminal_ours_1 (output_only) | |
207 | int output_only; | |
208 | { | |
2a5ec41d | 209 | int result; |
bd5635a1 RP |
210 | #ifdef TIOCGPGRP |
211 | /* Ignore this signal since it will happen when we try to set the pgrp. */ | |
212 | void (*osigttou) (); | |
213 | #endif /* TIOCGPGRP */ | |
214 | ||
2a5ec41d | 215 | /* Checking inferior_thisrun_terminal is necessary so that |
bd5635a1 | 216 | if GDB is running in the background, it won't block trying |
2a5ec41d JG |
217 | to do the ioctl()'s below. Checking gdb_has_a_terminal |
218 | avoids attempting all the ioctl's when running in batch. */ | |
219 | if (inferior_thisrun_terminal != 0 || gdb_has_a_terminal == 0) | |
bd5635a1 RP |
220 | return; |
221 | ||
222 | if (!terminal_is_ours) | |
223 | { | |
224 | terminal_is_ours = 1; | |
225 | ||
226 | #ifdef TIOCGPGRP | |
227 | osigttou = (void (*) ()) signal (SIGTTOU, SIG_IGN); | |
228 | ||
2a5ec41d JG |
229 | result = ioctl (0, TIOCGPGRP, &pgrp_inferior); |
230 | result = ioctl (0, TIOCSPGRP, &pgrp_ours); | |
bd5635a1 RP |
231 | |
232 | signal (SIGTTOU, osigttou); | |
233 | #else | |
234 | signal (SIGINT, sigint_ours); | |
235 | signal (SIGQUIT, sigquit_ours); | |
236 | #endif /* TIOCGPGRP */ | |
237 | ||
238 | tflags_inferior = fcntl (0, F_GETFL, 0); | |
2a5ec41d | 239 | result = ioctl (0, TIOCGETP, &sg_inferior); |
bd5635a1 RP |
240 | |
241 | #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) | |
2a5ec41d | 242 | result = ioctl (0, TIOCGETC, &tc_inferior); |
bd5635a1 | 243 | #endif |
7d9884b9 | 244 | #if defined(TIOCGLTC) && !defined(TIOCGLTC_BROKEN) |
2a5ec41d | 245 | result = ioctl (0, TIOCGLTC, <c_inferior); |
bd5635a1 RP |
246 | #endif |
247 | #ifdef TIOCLGET | |
2a5ec41d | 248 | result = ioctl (0, TIOCLGET, &lmode_inferior); |
bd5635a1 RP |
249 | #endif |
250 | } | |
251 | ||
252 | #ifdef HAVE_TERMIO | |
253 | sg_ours.c_lflag |= ICANON; | |
254 | if (output_only && !(sg_inferior.c_lflag & ICANON)) | |
255 | sg_ours.c_lflag &= ~ICANON; | |
256 | #else /* not HAVE_TERMIO */ | |
257 | sg_ours.sg_flags &= ~RAW & ~CBREAK; | |
258 | if (output_only) | |
259 | sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags; | |
260 | #endif /* not HAVE_TERMIO */ | |
261 | ||
2a5ec41d JG |
262 | result = fcntl (0, F_SETFL, tflags_ours); |
263 | result = fcntl (0, F_SETFL, tflags_ours); | |
264 | result = ioctl (0, TIOCSETN, &sg_ours); | |
bd5635a1 RP |
265 | |
266 | #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) | |
2a5ec41d | 267 | result = ioctl (0, TIOCSETC, &tc_ours); |
bd5635a1 | 268 | #endif |
7d9884b9 | 269 | #if defined(TIOCGLTC) && !defined(TIOCGLTC_BROKEN) |
2a5ec41d | 270 | result = ioctl (0, TIOCSLTC, <c_ours); |
bd5635a1 RP |
271 | #endif |
272 | #ifdef TIOCLGET | |
2a5ec41d | 273 | result = ioctl (0, TIOCLSET, &lmode_ours); |
bd5635a1 RP |
274 | #endif |
275 | ||
276 | #ifdef HAVE_TERMIO | |
277 | sg_ours.c_lflag |= ICANON; | |
278 | #else /* not HAVE_TERMIO */ | |
279 | sg_ours.sg_flags &= ~RAW & ~CBREAK; | |
280 | #endif /* not HAVE_TERMIO */ | |
281 | } | |
282 | ||
283 | /* ARGSUSED */ | |
284 | void | |
285 | term_info (arg, from_tty) | |
286 | char *arg; | |
287 | int from_tty; | |
288 | { | |
289 | target_terminal_info (arg, from_tty); | |
290 | } | |
291 | ||
715d2e06 | 292 | /* ARGSUSED */ |
bd5635a1 RP |
293 | void |
294 | child_terminal_info (args, from_tty) | |
295 | char *args; | |
296 | int from_tty; | |
297 | { | |
298 | register int i; | |
299 | ||
2a5ec41d JG |
300 | if (!gdb_has_a_terminal) { |
301 | printf_filtered ("This GDB does not control a terminal.\n"); | |
302 | return; | |
303 | } | |
304 | ||
7e97eb28 | 305 | #ifdef TIOCGPGRP |
bd5635a1 RP |
306 | printf_filtered ("Inferior's terminal status (currently saved by GDB):\n"); |
307 | ||
2a5ec41d JG |
308 | printf_filtered ("owner pgrp = %d, fcntl flags = 0x%x.\n", |
309 | pgrp_inferior, tflags_inferior); | |
7e97eb28 | 310 | #endif /* TIOCGPGRP */ |
2a5ec41d | 311 | |
bd5635a1 RP |
312 | #ifdef HAVE_TERMIO |
313 | ||
817b8c46 | 314 | printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n", |
2a5ec41d | 315 | sg_inferior.c_iflag, sg_inferior.c_oflag); |
bd5635a1 RP |
316 | printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n", |
317 | sg_inferior.c_cflag, sg_inferior.c_lflag, sg_inferior.c_line); | |
318 | printf_filtered ("c_cc: "); | |
319 | for (i = 0; (i < NCC); i += 1) | |
320 | printf_filtered ("0x%x ", sg_inferior.c_cc[i]); | |
321 | printf_filtered ("\n"); | |
322 | ||
323 | #else /* not HAVE_TERMIO */ | |
324 | ||
2a5ec41d | 325 | printf_filtered ("sgttyb.sg_flags = 0x%x.\n", sg_inferior.sg_flags); |
bd5635a1 RP |
326 | |
327 | #endif /* not HAVE_TERMIO */ | |
328 | ||
329 | #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) | |
330 | printf_filtered ("tchars: "); | |
331 | for (i = 0; i < (int)sizeof (struct tchars); i++) | |
2a5ec41d | 332 | printf_filtered ("0x%x ", ((unsigned char *)&tc_inferior)[i]); |
bd5635a1 RP |
333 | printf_filtered ("\n"); |
334 | #endif | |
335 | ||
7d9884b9 | 336 | #if defined(TIOCGLTC) && !defined(TIOCGLTC_BROKEN) |
bd5635a1 RP |
337 | printf_filtered ("ltchars: "); |
338 | for (i = 0; i < (int)sizeof (struct ltchars); i++) | |
2a5ec41d | 339 | printf_filtered ("0x%x ", ((unsigned char *)<c_inferior)[i]); |
bd5635a1 RP |
340 | printf_filtered ("\n"); |
341 | #endif | |
342 | ||
343 | #ifdef TIOCLGET | |
344 | printf_filtered ("lmode: 0x%x\n", lmode_inferior); | |
345 | #endif | |
346 | } | |
347 | \f | |
715d2e06 JG |
348 | /* NEW_TTY_PREFORK is called before forking a new child process, |
349 | so we can record the state of ttys in the child to be formed. | |
350 | TTYNAME is null if we are to share the terminal with gdb; | |
351 | or points to a string containing the name of the desired tty. | |
bd5635a1 | 352 | |
715d2e06 JG |
353 | NEW_TTY is called in new child processes under Unix, which will |
354 | become debugger target processes. This actually switches to | |
355 | the terminal specified in the NEW_TTY_PREFORK call. */ | |
356 | ||
7d9884b9 | 357 | void |
715d2e06 | 358 | new_tty_prefork (ttyname) |
bd5635a1 RP |
359 | char *ttyname; |
360 | { | |
bd5635a1 RP |
361 | /* Save the name for later, for determining whether we and the child |
362 | are sharing a tty. */ | |
363 | inferior_thisrun_terminal = ttyname; | |
715d2e06 JG |
364 | } |
365 | ||
366 | void | |
367 | new_tty () | |
368 | { | |
369 | register int tty; | |
370 | ||
371 | if (inferior_thisrun_terminal == 0) | |
bd5635a1 RP |
372 | return; |
373 | ||
374 | #ifdef TIOCNOTTY | |
375 | /* Disconnect the child process from our controlling terminal. */ | |
376 | tty = open("/dev/tty", O_RDWR); | |
377 | if (tty > 0) | |
378 | { | |
379 | ioctl(tty, TIOCNOTTY, 0); | |
380 | close(tty); | |
381 | } | |
382 | #endif | |
383 | ||
384 | /* Now open the specified new terminal. */ | |
385 | ||
7d9884b9 JG |
386 | #ifdef USE_O_NOCTTY |
387 | tty = open(inferior_thisrun_terminal, O_RDWR | O_NOCTTY); | |
388 | #else | |
715d2e06 | 389 | tty = open(inferior_thisrun_terminal, O_RDWR); |
7d9884b9 | 390 | #endif |
bd5635a1 RP |
391 | if (tty == -1) |
392 | { | |
715d2e06 | 393 | print_sys_errmsg (inferior_thisrun_terminal, errno); |
bd5635a1 RP |
394 | _exit(1); |
395 | } | |
396 | ||
397 | /* Avoid use of dup2; doesn't exist on all systems. */ | |
398 | if (tty != 0) | |
399 | { close (0); dup (tty); } | |
400 | if (tty != 1) | |
401 | { close (1); dup (tty); } | |
402 | if (tty != 2) | |
403 | { close (2); dup (tty); } | |
404 | if (tty > 2) | |
405 | close(tty); | |
406 | } | |
407 | \f | |
408 | /* Kill the inferior process. Make us have no inferior. */ | |
409 | ||
410 | /* ARGSUSED */ | |
411 | static void | |
412 | kill_command (arg, from_tty) | |
413 | char *arg; | |
414 | int from_tty; | |
415 | { | |
416 | if (inferior_pid == 0) | |
417 | error ("The program is not being run."); | |
418 | if (!query ("Kill the inferior process? ")) | |
419 | error ("Not confirmed."); | |
ee0613d1 | 420 | target_kill (); |
777bef06 JK |
421 | |
422 | /* Killing off the inferior can leave us with a core file. If so, | |
423 | print the state we are left in. */ | |
424 | if (target_has_stack) { | |
425 | printf_filtered ("In %s,\n", current_target->to_longname); | |
426 | if (selected_frame == NULL) | |
427 | fputs_filtered ("No selected stack frame.\n", stdout); | |
428 | else | |
cadbb07a | 429 | print_stack_frame (selected_frame, selected_frame_level, 1); |
777bef06 | 430 | } |
bd5635a1 RP |
431 | } |
432 | ||
433 | /* The inferior process has died. Long live the inferior! */ | |
434 | ||
435 | void | |
436 | generic_mourn_inferior () | |
437 | { | |
438 | inferior_pid = 0; | |
439 | attach_flag = 0; | |
440 | mark_breakpoints_out (); | |
441 | registers_changed (); | |
442 | ||
443 | #ifdef CLEAR_DEFERRED_STORES | |
444 | /* Delete any pending stores to the inferior... */ | |
445 | CLEAR_DEFERRED_STORES; | |
446 | #endif | |
447 | ||
bd5635a1 | 448 | reopen_exec_file (); |
777bef06 | 449 | if (target_has_stack) { |
bd5635a1 RP |
450 | set_current_frame ( create_new_frame (read_register (FP_REGNUM), |
451 | read_pc ())); | |
777bef06 JK |
452 | select_frame (get_current_frame (), 0); |
453 | } else { | |
bd5635a1 | 454 | set_current_frame (0); |
777bef06 JK |
455 | select_frame ((FRAME) 0, -1); |
456 | } | |
bd5635a1 RP |
457 | /* It is confusing to the user for ignore counts to stick around |
458 | from previous runs of the inferior. So clear them. */ | |
459 | breakpoint_clear_ignore_counts (); | |
460 | } | |
461 | ||
462 | void | |
463 | child_mourn_inferior () | |
464 | { | |
465 | unpush_target (&child_ops); | |
466 | generic_mourn_inferior (); | |
467 | } | |
468 | \f | |
469 | #if 0 | |
470 | /* This function is just for testing, and on some systems (Sony NewsOS | |
471 | 3.2) <sys/user.h> also includes <sys/time.h> which leads to errors | |
472 | (since on this system at least sys/time.h is not protected against | |
473 | multiple inclusion). */ | |
474 | /* ARGSUSED */ | |
475 | static void | |
476 | try_writing_regs_command (arg, from_tty) | |
477 | char *arg; | |
478 | int from_tty; | |
479 | { | |
480 | register int i; | |
481 | register int value; | |
482 | ||
483 | if (inferior_pid == 0) | |
484 | error ("There is no inferior process now."); | |
485 | ||
486 | /* A Sun 3/50 or 3/60 (at least) running SunOS 4.0.3 will have a | |
487 | kernel panic if we try to write past the end of the user area. | |
488 | Presumably Sun will fix this bug (it has been reported), but it | |
489 | is tacky to crash the system, so at least on SunOS4 we need to | |
490 | stop writing when we hit the end of the user area. */ | |
491 | for (i = 0; i < sizeof (struct user); i += 2) | |
492 | { | |
493 | QUIT; | |
494 | errno = 0; | |
495 | value = call_ptrace (3, inferior_pid, i, 0); | |
496 | call_ptrace (6, inferior_pid, i, value); | |
497 | if (errno == 0) | |
498 | { | |
499 | printf (" Succeeded with address 0x%x; value 0x%x (%d).\n", | |
500 | i, value, value); | |
501 | } | |
502 | else if ((i & 0377) == 0) | |
503 | printf (" Failed at 0x%x.\n", i); | |
504 | } | |
505 | } | |
506 | #endif | |
507 | \f | |
508 | void | |
509 | _initialize_inflow () | |
510 | { | |
2a5ec41d JG |
511 | int result; |
512 | ||
bd5635a1 RP |
513 | add_info ("terminal", term_info, |
514 | "Print inferior's saved terminal status."); | |
515 | ||
516 | #if 0 | |
517 | add_com ("try-writing-regs", class_obscure, try_writing_regs_command, | |
518 | "Try writing all locations in inferior's system block.\n\ | |
519 | Report which ones can be written."); | |
520 | #endif | |
521 | ||
522 | add_com ("kill", class_run, kill_command, | |
523 | "Kill execution of program being debugged."); | |
524 | ||
525 | inferior_pid = 0; | |
526 | ||
2a5ec41d JG |
527 | /* Get all the current tty settings (including whether we have a tty at |
528 | all!). */ | |
529 | ||
cadbb07a | 530 | tflags_ours = fcntl (0, F_GETFL, 0); |
2a5ec41d | 531 | OOPSY ("fcntl F_GETFL"); /* Should always work */ |
bd5635a1 | 532 | |
2a5ec41d JG |
533 | result = ioctl (0, TIOCGETP, &sg_ours); |
534 | if (result == 0) { | |
535 | gdb_has_a_terminal = 1; | |
536 | /* Get the rest of the tty settings, then... */ | |
bd5635a1 | 537 | #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN) |
2a5ec41d | 538 | ioctl (0, TIOCGETC, &tc_ours); |
bd5635a1 | 539 | #endif |
7d9884b9 | 540 | #if defined(TIOCGLTC) && !defined(TIOCGLTC_BROKEN) |
2a5ec41d | 541 | ioctl (0, TIOCGLTC, <c_ours); |
bd5635a1 RP |
542 | #endif |
543 | #ifdef TIOCLGET | |
2a5ec41d | 544 | ioctl (0, TIOCLGET, &lmode_ours); |
bd5635a1 | 545 | #endif |
bd5635a1 | 546 | #ifdef TIOCGPGRP |
2a5ec41d | 547 | ioctl (0, TIOCGPGRP, &pgrp_ours); |
bd5635a1 | 548 | #endif /* TIOCGPGRP */ |
2a5ec41d JG |
549 | } else { |
550 | gdb_has_a_terminal = 0; | |
551 | } | |
bd5635a1 RP |
552 | |
553 | terminal_is_ours = 1; | |
554 | } |