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