* config/monitor.exp: Detect the "Couldn't establish connection"
[deliverable/binutils-gdb.git] / gdb / serial.c
CommitLineData
4e772f44 1/* Generic serial interface routines
c84e5000 2 Copyright 1992, 1993, 1996 Free Software Foundation, Inc.
4e772f44
SG
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
6c9638b4 18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
4e772f44
SG
19
20#include "defs.h"
72ae15f6 21#include <ctype.h>
4e772f44 22#include "serial.h"
0694bce6 23#include "gdb_string.h"
e8f1ad9a 24#include "gdbcmd.h"
4e772f44 25
e36491f4 26/*#define DEBUGIFY*/
16a43bf4
DP
27#include "debugify.h"
28
29
38dc5e12 30/* Linked list of serial I/O handlers */
4e772f44
SG
31
32static struct serial_ops *serial_ops_list = NULL;
33
38dc5e12
SG
34/* This is the last serial stream opened. Used by connect command. */
35
36static serial_t last_serial_opened = NULL;
37
bbcc95bd
PS
38/* Pointer to list of scb's. */
39
40static serial_t scb_base;
41
e8f1ad9a
FF
42/* Non-NULL gives filename which contains a recording of the remote session,
43 suitable for playback by gdbserver. */
44
d9951af4
SG
45static char *serial_logfile = NULL;
46static FILE *serial_logfp = NULL;
e8f1ad9a 47
b607efe7 48static struct serial_ops *serial_interface_lookup PARAMS ((char *));
d9951af4
SG
49static void serial_logchar PARAMS ((int ch, int timeout));
50static char logbase_hex[] = "hex";
51static char logbase_octal[] = "octal";
52static char logbase_ascii[] = "ascii";
53static char *logbase_enums[] = {logbase_hex, logbase_octal, logbase_ascii, NULL};
54static char *serial_logbase = logbase_ascii;
b607efe7 55
e8f1ad9a
FF
56\f
57static int serial_reading = 0;
58static int serial_writing = 0;
59
60void
61serial_log_command (cmd)
62 const char *cmd;
63{
d9951af4
SG
64 if (!serial_logfp)
65 return;
66
e8f1ad9a
FF
67 if (serial_reading || serial_writing)
68 {
0db5a6fe 69 fputc_unfiltered ('\n', serial_logfp);
e8f1ad9a
FF
70 serial_reading = 0;
71 serial_writing = 0;
72 }
0db5a6fe 73 fprintf_unfiltered (serial_logfp, "c %s\n", cmd);
e8f1ad9a
FF
74 /* Make sure that the log file is as up-to-date as possible,
75 in case we are getting ready to dump core or something. */
76 fflush (serial_logfp);
77}
78
d9951af4
SG
79/* Define bogus char to represent a BREAK. Should be careful to choose a value
80 that can't be confused with a normal char, or an error code. */
81#define SERIAL_BREAK 1235
82
e8f1ad9a 83static void
d9951af4 84serial_logchar (ch, timeout)
e8f1ad9a 85 int ch;
d9951af4 86 int timeout;
e8f1ad9a 87{
d9951af4
SG
88 if (serial_logbase != logbase_ascii)
89 fputc_unfiltered (' ', serial_logfp);
90
e8f1ad9a
FF
91 switch (ch)
92 {
d9951af4
SG
93 case SERIAL_TIMEOUT:
94 fprintf_unfiltered (serial_logfp, "<Timeout: %d seconds>", timeout);
95 return;
96 case SERIAL_ERROR:
97 fprintf_unfiltered (serial_logfp, "<Error: %s>", safe_strerror (errno));
98 return;
99 case SERIAL_EOF:
100 fputs_unfiltered ("<Eof>", serial_logfp);
101 return;
102 case SERIAL_BREAK:
103 fputs_unfiltered ("<Break>", serial_logfp);
104 return;
105 default:
106 if (serial_logbase == logbase_hex)
107 fprintf_unfiltered (serial_logfp, "%02x", ch & 0xff);
108 else if (serial_logbase == logbase_octal)
109 fprintf_unfiltered (serial_logfp, "%03o", ch & 0xff);
110 else
111 switch (ch)
112 {
113 case '\\': fputs_unfiltered ("\\\\", serial_logfp); break;
114 case '\b': fputs_unfiltered ("\\b", serial_logfp); break;
115 case '\f': fputs_unfiltered ("\\f", serial_logfp); break;
116 case '\n': fputs_unfiltered ("\\n", serial_logfp); break;
117 case '\r': fputs_unfiltered ("\\r", serial_logfp); break;
118 case '\t': fputs_unfiltered ("\\t", serial_logfp); break;
119 case '\v': fputs_unfiltered ("\\v", serial_logfp); break;
120 default: fprintf_unfiltered (serial_logfp, isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF); break;
121 }
122 }
e8f1ad9a
FF
123}
124
125int
126serial_write (scb, str, len)
127 serial_t scb;
128 const char *str;
129 int len;
130{
131 int count;
132
133 if (serial_logfp != NULL)
134 {
135 if (serial_reading)
136 {
0db5a6fe 137 fputc_unfiltered ('\n', serial_logfp);
e8f1ad9a
FF
138 serial_reading = 0;
139 }
140 if (!serial_writing)
141 {
d9951af4 142 fputs_unfiltered ("w ", serial_logfp);
e8f1ad9a
FF
143 serial_writing = 1;
144 }
145 for (count = 0; count < len; count++)
146 {
d9951af4 147 serial_logchar (str[count] & 0xff, 0);
e8f1ad9a
FF
148 }
149 /* Make sure that the log file is as up-to-date as possible,
150 in case we are getting ready to dump core or something. */
151 fflush (serial_logfp);
152 }
153 return (scb -> ops -> write (scb, str, len));
154}
155
156int
157serial_readchar (scb, timeout)
158 serial_t scb;
159 int timeout;
160{
161 int ch;
162
163 ch = scb -> ops -> readchar (scb, timeout);
164 if (serial_logfp != NULL)
165 {
166 if (serial_writing)
167 {
0db5a6fe 168 fputc_unfiltered ('\n', serial_logfp);
e8f1ad9a
FF
169 serial_writing = 0;
170 }
171 if (!serial_reading)
172 {
d9951af4 173 fputs_unfiltered ("r ", serial_logfp);
e8f1ad9a
FF
174 serial_reading = 1;
175 }
d9951af4 176 serial_logchar (ch, timeout);
e8f1ad9a
FF
177 /* Make sure that the log file is as up-to-date as possible,
178 in case we are getting ready to dump core or something. */
179 fflush (serial_logfp);
180 }
181 return (ch);
182}
183
d9951af4
SG
184int
185serial_send_break (scb)
186 serial_t scb;
187{
188 if (serial_logfp != NULL)
189 {
190 if (serial_reading)
191 {
192 fputc_unfiltered ('\n', serial_logfp);
193 serial_reading = 0;
194 }
195 if (!serial_writing)
196 {
197 fputs_unfiltered ("w ", serial_logfp);
198 serial_writing = 1;
199 }
200 serial_logchar (SERIAL_BREAK, 0);
201 /* Make sure that the log file is as up-to-date as possible,
202 in case we are getting ready to dump core or something. */
203 fflush (serial_logfp);
204 }
205 return (scb -> ops -> send_break (scb));
206}
207
4e772f44
SG
208static struct serial_ops *
209serial_interface_lookup (name)
210 char *name;
211{
212 struct serial_ops *ops;
16a43bf4 213 DBG(("serial_interface_lookup(%s)\n",name));
4e772f44
SG
214
215 for (ops = serial_ops_list; ops; ops = ops->next)
216 if (strcmp (name, ops->name) == 0)
217 return ops;
218
16a43bf4 219 DBG(("serial_interface_lookup: %s not found!\n",name));
4e772f44
SG
220 return NULL;
221}
222
223void
224serial_add_interface(optable)
225 struct serial_ops *optable;
226{
227 optable->next = serial_ops_list;
228 serial_ops_list = optable;
229}
230
38dc5e12
SG
231/* Open up a device or a network socket, depending upon the syntax of NAME. */
232
4e772f44 233serial_t
55679787 234serial_open (name)
4e772f44
SG
235 const char *name;
236{
237 serial_t scb;
238 struct serial_ops *ops;
239
16a43bf4 240 DBG(("serial_open\n"));
4887063b
SG
241 for (scb = scb_base; scb; scb = scb->next)
242 if (scb->name && strcmp (scb->name, name) == 0)
243 {
244 scb->refcnt++;
16a43bf4 245 DBG(("serial_open: scb %s found\n", name));
4887063b
SG
246 return scb;
247 }
248
55679787
SC
249 if (strcmp (name, "pc") == 0)
250 ops = serial_interface_lookup ("pc");
251 else if (strchr (name, ':'))
38dc5e12 252 ops = serial_interface_lookup ("tcp");
c84e5000
SC
253 else if (strncmp (name, "lpt", 3) == 0)
254 ops = serial_interface_lookup ("parallel");
38dc5e12
SG
255 else
256 ops = serial_interface_lookup ("hardwire");
4e772f44
SG
257
258 if (!ops)
16a43bf4
DP
259 {
260 DBG(("serial_open: !ops; returning NULL\n"));
4e772f44 261 return NULL;
16a43bf4 262 }
4e772f44
SG
263
264 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
265
266 scb->ops = ops;
267
268 scb->bufcnt = 0;
269 scb->bufp = scb->buf;
270
4febd102 271 if (scb->ops->open(scb, name))
4e772f44
SG
272 {
273 free (scb);
16a43bf4 274 DBG(("serial_open: scb->ops->open failed!\n"));
4e772f44
SG
275 return NULL;
276 }
277
4887063b
SG
278 scb->name = strsave (name);
279 scb->next = scb_base;
280 scb->refcnt = 1;
281 scb_base = scb;
282
38dc5e12
SG
283 last_serial_opened = scb;
284
e8f1ad9a
FF
285 if (serial_logfile != NULL)
286 {
287 serial_logfp = fopen (serial_logfile, "w");
288 if (serial_logfp == NULL)
289 {
16a43bf4 290 DBG(("serial_open: unable to open serial logfile %s!\n",serial_logfile));
e8f1ad9a
FF
291 perror_with_name (serial_logfile);
292 }
293 }
294
16a43bf4 295 DBG(("serial_open: Done! :-)\n"));
38dc5e12
SG
296 return scb;
297}
298
299serial_t
4887063b 300serial_fdopen (fd)
38dc5e12
SG
301 const int fd;
302{
303 serial_t scb;
304 struct serial_ops *ops;
16a43bf4 305 DBG(("serial_fdopen\n"));
38dc5e12 306
4887063b
SG
307 for (scb = scb_base; scb; scb = scb->next)
308 if (scb->fd == fd)
309 {
310 scb->refcnt++;
311 return scb;
312 }
313
38dc5e12
SG
314 ops = serial_interface_lookup ("hardwire");
315
316 if (!ops)
317 return NULL;
318
319 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
320
321 scb->ops = ops;
322
323 scb->bufcnt = 0;
324 scb->bufp = scb->buf;
325
326 scb->fd = fd;
327
4887063b
SG
328 scb->name = NULL;
329 scb->next = scb_base;
330 scb->refcnt = 1;
331 scb_base = scb;
332
38dc5e12
SG
333 last_serial_opened = scb;
334
4e772f44
SG
335 return scb;
336}
337
4febd102 338void
bbcc95bd 339serial_close(scb, really_close)
4febd102 340 serial_t scb;
bbcc95bd 341 int really_close;
4febd102 342{
4887063b
SG
343 serial_t tmp_scb;
344
38dc5e12
SG
345 last_serial_opened = NULL;
346
e8f1ad9a
FF
347 if (serial_logfp)
348 {
349 if (serial_reading || serial_writing)
350 {
0db5a6fe 351 fputc_unfiltered ('\n', serial_logfp);
e8f1ad9a
FF
352 serial_reading = 0;
353 serial_writing = 0;
354 }
355 fclose (serial_logfp);
356 serial_logfp = NULL;
357 }
358
a037b21e
SG
359/* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you
360 should fix your code instead. */
361
362 if (!scb)
363 return;
364
4887063b
SG
365 scb->refcnt--;
366 if (scb->refcnt > 0)
367 return;
368
bbcc95bd
PS
369 if (really_close)
370 scb->ops->close (scb);
4887063b
SG
371
372 if (scb->name)
373 free (scb->name);
374
375 if (scb_base == scb)
376 scb_base = scb_base->next;
377 else
378 for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next)
379 {
380 if (tmp_scb->next != scb)
381 continue;
382
383 tmp_scb->next = tmp_scb->next->next;
384 break;
385 }
386
a037b21e 387 free(scb);
4febd102
SG
388}
389
4e772f44 390#if 0
bf3b8abd
JK
391/*
392The connect command is #if 0 because I hadn't thought of an elegant
393way to wait for I/O on two serial_t's simultaneously. Two solutions
394came to mind:
395
396 1) Fork, and have have one fork handle the to user direction,
397 and have the other hand the to target direction. This
398 obviously won't cut it for MSDOS.
399
400 2) Use something like select. This assumes that stdin and
401 the target side can both be waited on via the same
402 mechanism. This may not be true for DOS, if GDB is
403 talking to the target via a TCP socket.
404-grossman, 8 Jun 93
405*/
38dc5e12 406
4e772f44
SG
407/* Connect the user directly to the remote system. This command acts just like
408 the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
409
38dc5e12
SG
410static serial_t tty_desc; /* Controlling terminal */
411
4e772f44
SG
412static void
413cleanup_tty(ttystate)
38dc5e12 414 serial_ttystate ttystate;
4e772f44 415{
199b2450 416 printf_unfiltered ("\r\n[Exiting connect mode]\r\n");
38dc5e12
SG
417 SERIAL_SET_TTY_STATE (tty_desc, ttystate);
418 free (ttystate);
419 SERIAL_CLOSE (tty_desc);
4e772f44
SG
420}
421
422static void
423connect_command (args, fromtty)
424 char *args;
425 int fromtty;
426{
4e772f44
SG
427 int c;
428 char cur_esc = 0;
38dc5e12
SG
429 serial_ttystate ttystate;
430 serial_t port_desc; /* TTY port */
16a43bf4 431 DBG(("connect_command\n"));
4e772f44
SG
432
433 dont_repeat();
434
4e772f44 435 if (args)
199b2450 436 fprintf_unfiltered(gdb_stderr, "This command takes no args. They have been ignored.\n");
4e772f44 437
199b2450 438 printf_unfiltered("[Entering connect mode. Use ~. or ~^D to escape]\n");
4e772f44 439
38dc5e12
SG
440 tty_desc = SERIAL_FDOPEN (0);
441 port_desc = last_serial_opened;
4e772f44 442
38dc5e12 443 ttystate = SERIAL_GET_TTY_STATE (tty_desc);
4e772f44 444
38dc5e12
SG
445 SERIAL_RAW (tty_desc);
446 SERIAL_RAW (port_desc);
447
448 make_cleanup (cleanup_tty, ttystate);
4e772f44
SG
449
450 while (1)
451 {
38dc5e12 452 int mask;
4e772f44 453
38dc5e12 454 mask = SERIAL_WAIT_2 (tty_desc, port_desc, -1);
4e772f44 455
38dc5e12
SG
456 if (mask & 2)
457 { /* tty input */
4e772f44
SG
458 char cx;
459
38dc5e12 460 while (1)
4e772f44 461 {
38dc5e12
SG
462 c = SERIAL_READCHAR(tty_desc, 0);
463
464 if (c == SERIAL_TIMEOUT)
465 break;
466
467 if (c < 0)
468 perror_with_name("connect");
469
470 cx = c;
471 SERIAL_WRITE(port_desc, &cx, 1);
472
473 switch (cur_esc)
474 {
475 case 0:
476 if (c == '\r')
477 cur_esc = c;
478 break;
479 case '\r':
480 if (c == '~')
481 cur_esc = c;
482 else
483 cur_esc = 0;
484 break;
485 case '~':
486 if (c == '.' || c == '\004')
487 return;
488 else
489 cur_esc = 0;
490 }
4e772f44
SG
491 }
492 }
493
38dc5e12
SG
494 if (mask & 1)
495 { /* Port input */
496 char cx;
497
4e772f44
SG
498 while (1)
499 {
38dc5e12
SG
500 c = SERIAL_READCHAR(port_desc, 0);
501
502 if (c == SERIAL_TIMEOUT)
503 break;
504
4e772f44 505 if (c < 0)
38dc5e12
SG
506 perror_with_name("connect");
507
508 cx = c;
509
510 SERIAL_WRITE(tty_desc, &cx, 1);
4e772f44 511 }
4e772f44
SG
512 }
513 }
514}
976bb0be 515#endif /* 0 */
4e772f44 516
5c8ba017
SG
517/* VARARGS */
518void
519#ifdef ANSI_PROTOTYPES
520serial_printf (serial_t desc, const char *format, ...)
521#else
522serial_printf (va_alist)
523 va_dcl
524#endif
525{
526 va_list args;
527 char *buf;
528#ifdef ANSI_PROTOTYPES
529 va_start (args, format);
530#else
531 serial_t desc;
532 char *format;
533
534 va_start (args);
535 desc = va_arg (args, serial_t);
536 format = va_arg (args, char *);
537#endif
538
539 vasprintf (&buf, format, args);
540 SERIAL_WRITE (desc, buf, strlen (buf));
541
542 free (buf);
543 va_end (args);
544}
545
4e772f44
SG
546void
547_initialize_serial ()
548{
d9951af4
SG
549 struct cmd_list_element *cmd;
550
976bb0be 551#if 0
4e772f44
SG
552 add_com ("connect", class_obscure, connect_command,
553 "Connect the terminal directly up to the command monitor.\n\
554Use <CR>~. or <CR>~^D to break out.");
38dc5e12 555#endif /* 0 */
e8f1ad9a
FF
556
557 add_show_from_set (add_set_cmd ("remotelogfile", no_class,
558 var_filename, (char *)&serial_logfile,
559 "Set filename for remote session recording.\n\
560This file is used to record the remote session for future playback\n\
561by gdbserver.", &setlist),
562 &showlist);
563
d9951af4
SG
564 add_show_from_set (add_set_enum_cmd ("remotelogbase", no_class,
565 logbase_enums,
566 (char *)&serial_logbase,
567 "Set ...",
568 &setlist),
569 &showlist);
976bb0be 570}
This page took 0.244355 seconds and 4 git commands to generate.