all remaining *.c *.h files from hp merge.
[deliverable/binutils-gdb.git] / gdb / serial.c
CommitLineData
4e772f44 1/* Generic serial interface routines
64e6335a 2 Copyright 1992, 1993, 1996, 1997 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 41static char *serial_logfile = NULL;
65b07ddc 42static GDB_FILE *serial_logfp = NULL;
e8f1ad9a 43
b607efe7 44static struct serial_ops *serial_interface_lookup PARAMS ((char *));
65b07ddc 45static void serial_logchar PARAMS ((int, int, int));
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
65b07ddc
DT
62serial_logchar (ch_type, ch, timeout)
63 int ch_type;
e8f1ad9a 64 int ch;
d9951af4 65 int timeout;
e8f1ad9a 66{
65b07ddc 67 if (ch_type != serial_current_type)
4ce7ba51 68 {
65b07ddc
DT
69 fprintf_unfiltered (serial_logfp, "\n%c ", ch_type);
70 serial_current_type = ch_type;
4ce7ba51
SG
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
64e6335a
PS
119 fputs_unfiltered ("\nc ", serial_logfp);
120 fputs_unfiltered (cmd, serial_logfp);
4ce7ba51
SG
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
9cf7f520
GN
215 if (strcmp (name, "ocd") == 0)
216 ops = serial_interface_lookup ("ocd");
217 else if (strcmp (name, "pc") == 0)
55679787
SC
218 ops = serial_interface_lookup ("pc");
219 else if (strchr (name, ':'))
38dc5e12 220 ops = serial_interface_lookup ("tcp");
c84e5000
SC
221 else if (strncmp (name, "lpt", 3) == 0)
222 ops = serial_interface_lookup ("parallel");
38dc5e12
SG
223 else
224 ops = serial_interface_lookup ("hardwire");
4e772f44
SG
225
226 if (!ops)
227 return NULL;
228
229 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
230
231 scb->ops = ops;
232
233 scb->bufcnt = 0;
234 scb->bufp = scb->buf;
235
4febd102 236 if (scb->ops->open(scb, name))
4e772f44
SG
237 {
238 free (scb);
239 return NULL;
240 }
241
4887063b
SG
242 scb->name = strsave (name);
243 scb->next = scb_base;
244 scb->refcnt = 1;
245 scb_base = scb;
246
38dc5e12
SG
247 last_serial_opened = scb;
248
e8f1ad9a
FF
249 if (serial_logfile != NULL)
250 {
4ce7ba51 251 serial_logfp = gdb_fopen (serial_logfile, "w");
e8f1ad9a 252 if (serial_logfp == NULL)
4ce7ba51 253 perror_with_name (serial_logfile);
e8f1ad9a
FF
254 }
255
38dc5e12
SG
256 return scb;
257}
258
259serial_t
4887063b 260serial_fdopen (fd)
38dc5e12
SG
261 const int fd;
262{
263 serial_t scb;
264 struct serial_ops *ops;
265
4887063b
SG
266 for (scb = scb_base; scb; scb = scb->next)
267 if (scb->fd == fd)
268 {
269 scb->refcnt++;
270 return scb;
271 }
272
38dc5e12
SG
273 ops = serial_interface_lookup ("hardwire");
274
275 if (!ops)
276 return NULL;
277
278 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
279
280 scb->ops = ops;
281
282 scb->bufcnt = 0;
283 scb->bufp = scb->buf;
284
285 scb->fd = fd;
286
4887063b
SG
287 scb->name = NULL;
288 scb->next = scb_base;
289 scb->refcnt = 1;
290 scb_base = scb;
291
38dc5e12
SG
292 last_serial_opened = scb;
293
4e772f44
SG
294 return scb;
295}
296
4febd102 297void
4ce7ba51 298serial_close (scb, really_close)
4febd102 299 serial_t scb;
bbcc95bd 300 int really_close;
4febd102 301{
4887063b
SG
302 serial_t tmp_scb;
303
38dc5e12
SG
304 last_serial_opened = NULL;
305
e8f1ad9a
FF
306 if (serial_logfp)
307 {
4ce7ba51
SG
308 fputs_unfiltered ("\nEnd of log\n", serial_logfp);
309 serial_current_type = 0;
310
65b07ddc
DT
311 /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr? */
312 gdb_fclose (serial_logfp);
e8f1ad9a
FF
313 serial_logfp = NULL;
314 }
315
a037b21e
SG
316/* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you
317 should fix your code instead. */
318
319 if (!scb)
320 return;
321
4887063b
SG
322 scb->refcnt--;
323 if (scb->refcnt > 0)
324 return;
325
bbcc95bd
PS
326 if (really_close)
327 scb->ops->close (scb);
4887063b
SG
328
329 if (scb->name)
330 free (scb->name);
331
332 if (scb_base == scb)
333 scb_base = scb_base->next;
334 else
335 for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next)
336 {
337 if (tmp_scb->next != scb)
338 continue;
339
340 tmp_scb->next = tmp_scb->next->next;
341 break;
342 }
343
a037b21e 344 free(scb);
4febd102
SG
345}
346
4e772f44 347#if 0
bf3b8abd
JK
348/*
349The connect command is #if 0 because I hadn't thought of an elegant
350way to wait for I/O on two serial_t's simultaneously. Two solutions
351came to mind:
352
353 1) Fork, and have have one fork handle the to user direction,
354 and have the other hand the to target direction. This
355 obviously won't cut it for MSDOS.
356
357 2) Use something like select. This assumes that stdin and
358 the target side can both be waited on via the same
359 mechanism. This may not be true for DOS, if GDB is
360 talking to the target via a TCP socket.
361-grossman, 8 Jun 93
362*/
38dc5e12 363
4e772f44
SG
364/* Connect the user directly to the remote system. This command acts just like
365 the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
366
38dc5e12
SG
367static serial_t tty_desc; /* Controlling terminal */
368
4e772f44
SG
369static void
370cleanup_tty(ttystate)
38dc5e12 371 serial_ttystate ttystate;
4e772f44 372{
199b2450 373 printf_unfiltered ("\r\n[Exiting connect mode]\r\n");
38dc5e12
SG
374 SERIAL_SET_TTY_STATE (tty_desc, ttystate);
375 free (ttystate);
376 SERIAL_CLOSE (tty_desc);
4e772f44
SG
377}
378
379static void
380connect_command (args, fromtty)
381 char *args;
382 int fromtty;
383{
4e772f44
SG
384 int c;
385 char cur_esc = 0;
38dc5e12
SG
386 serial_ttystate ttystate;
387 serial_t port_desc; /* TTY port */
4e772f44
SG
388
389 dont_repeat();
390
4e772f44 391 if (args)
199b2450 392 fprintf_unfiltered(gdb_stderr, "This command takes no args. They have been ignored.\n");
4e772f44 393
199b2450 394 printf_unfiltered("[Entering connect mode. Use ~. or ~^D to escape]\n");
4e772f44 395
38dc5e12
SG
396 tty_desc = SERIAL_FDOPEN (0);
397 port_desc = last_serial_opened;
4e772f44 398
38dc5e12 399 ttystate = SERIAL_GET_TTY_STATE (tty_desc);
4e772f44 400
38dc5e12
SG
401 SERIAL_RAW (tty_desc);
402 SERIAL_RAW (port_desc);
403
404 make_cleanup (cleanup_tty, ttystate);
4e772f44
SG
405
406 while (1)
407 {
38dc5e12 408 int mask;
4e772f44 409
38dc5e12 410 mask = SERIAL_WAIT_2 (tty_desc, port_desc, -1);
4e772f44 411
38dc5e12
SG
412 if (mask & 2)
413 { /* tty input */
4e772f44
SG
414 char cx;
415
38dc5e12 416 while (1)
4e772f44 417 {
38dc5e12
SG
418 c = SERIAL_READCHAR(tty_desc, 0);
419
420 if (c == SERIAL_TIMEOUT)
421 break;
422
423 if (c < 0)
424 perror_with_name("connect");
425
426 cx = c;
427 SERIAL_WRITE(port_desc, &cx, 1);
428
429 switch (cur_esc)
430 {
431 case 0:
432 if (c == '\r')
433 cur_esc = c;
434 break;
435 case '\r':
436 if (c == '~')
437 cur_esc = c;
438 else
439 cur_esc = 0;
440 break;
441 case '~':
442 if (c == '.' || c == '\004')
443 return;
444 else
445 cur_esc = 0;
446 }
4e772f44
SG
447 }
448 }
449
38dc5e12
SG
450 if (mask & 1)
451 { /* Port input */
452 char cx;
453
4e772f44
SG
454 while (1)
455 {
38dc5e12
SG
456 c = SERIAL_READCHAR(port_desc, 0);
457
458 if (c == SERIAL_TIMEOUT)
459 break;
460
4e772f44 461 if (c < 0)
38dc5e12
SG
462 perror_with_name("connect");
463
464 cx = c;
465
466 SERIAL_WRITE(tty_desc, &cx, 1);
4e772f44 467 }
4e772f44
SG
468 }
469 }
470}
976bb0be 471#endif /* 0 */
4e772f44 472
5c8ba017
SG
473/* VARARGS */
474void
475#ifdef ANSI_PROTOTYPES
476serial_printf (serial_t desc, const char *format, ...)
477#else
478serial_printf (va_alist)
479 va_dcl
480#endif
481{
482 va_list args;
483 char *buf;
484#ifdef ANSI_PROTOTYPES
485 va_start (args, format);
486#else
487 serial_t desc;
488 char *format;
489
490 va_start (args);
491 desc = va_arg (args, serial_t);
492 format = va_arg (args, char *);
493#endif
494
495 vasprintf (&buf, format, args);
496 SERIAL_WRITE (desc, buf, strlen (buf));
497
498 free (buf);
499 va_end (args);
500}
501
4e772f44
SG
502void
503_initialize_serial ()
504{
976bb0be 505#if 0
4e772f44
SG
506 add_com ("connect", class_obscure, connect_command,
507 "Connect the terminal directly up to the command monitor.\n\
508Use <CR>~. or <CR>~^D to break out.");
38dc5e12 509#endif /* 0 */
e8f1ad9a
FF
510
511 add_show_from_set (add_set_cmd ("remotelogfile", no_class,
512 var_filename, (char *)&serial_logfile,
513 "Set filename for remote session recording.\n\
514This file is used to record the remote session for future playback\n\
515by gdbserver.", &setlist),
516 &showlist);
517
d9951af4
SG
518 add_show_from_set (add_set_enum_cmd ("remotelogbase", no_class,
519 logbase_enums,
520 (char *)&serial_logbase,
1d7a3fd7 521 "Set numerical base for remote session logging",
d9951af4
SG
522 &setlist),
523 &showlist);
976bb0be 524}
This page took 0.387761 seconds and 4 git commands to generate.