* Sanitization fixes to retain new files.
[binutils-gdb.git] / gdb / serial.c
blob89a116e565c8223006e986f264488601206bcbb0
1 /* Generic serial interface routines
2 Copyright 1992, 1993, 1996, 1997 Free Software Foundation, Inc.
4 This file is part of GDB.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
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.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 #include "defs.h"
21 #include <ctype.h>
22 #include "serial.h"
23 #include "gdb_string.h"
24 #include "gdbcmd.h"
26 /* Linked list of serial I/O handlers */
28 static struct serial_ops *serial_ops_list = NULL;
30 /* This is the last serial stream opened. Used by connect command. */
32 static serial_t last_serial_opened = NULL;
34 /* Pointer to list of scb's. */
36 static serial_t scb_base;
38 /* Non-NULL gives filename which contains a recording of the remote session,
39 suitable for playback by gdbserver. */
41 static char *serial_logfile = NULL;
42 static FILE *serial_logfp = NULL;
44 static struct serial_ops *serial_interface_lookup PARAMS ((char *));
45 static void serial_logchar PARAMS ((int chtype, int ch, int timeout));
46 static char logbase_hex[] = "hex";
47 static char logbase_octal[] = "octal";
48 static char logbase_ascii[] = "ascii";
49 static char *logbase_enums[] = {logbase_hex, logbase_octal, logbase_ascii, NULL};
50 static char *serial_logbase = logbase_ascii;
53 static int serial_current_type = 0;
55 /* Log char CH of type CHTYPE, with TIMEOUT */
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
61 static void
62 serial_logchar (chtype, ch, timeout)
63 int chtype;
64 int ch;
65 int timeout;
67 if (chtype != serial_current_type)
69 fprintf_unfiltered (serial_logfp, "\n%c ", chtype);
70 serial_current_type = chtype;
73 if (serial_logbase != logbase_ascii)
74 fputc_unfiltered (' ', serial_logfp);
76 switch (ch)
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)
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;
110 void
111 serial_log_command (cmd)
112 const char *cmd;
114 if (!serial_logfp)
115 return;
117 serial_current_type = 'c';
119 fputs_unfiltered ("\nc ", serial_logfp);
120 fputs_unfiltered (cmd, serial_logfp);
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);
128 serial_write (scb, str, len)
129 serial_t scb;
130 const char *str;
131 int len;
133 if (serial_logfp != NULL)
135 int count;
137 for (count = 0; count < len; count++)
138 serial_logchar ('w', str[count] & 0xff, 0);
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. */
142 gdb_flush (serial_logfp);
145 return (scb -> ops -> write (scb, str, len));
149 serial_readchar (scb, timeout)
150 serial_t scb;
151 int timeout;
153 int ch;
155 ch = scb -> ops -> readchar (scb, timeout);
156 if (serial_logfp != NULL)
158 serial_logchar ('r', ch, timeout);
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. */
162 gdb_flush (serial_logfp);
165 return (ch);
169 serial_send_break (scb)
170 serial_t scb;
172 if (serial_logfp != NULL)
173 serial_logchar ('w', SERIAL_BREAK, 0);
175 return (scb -> ops -> send_break (scb));
178 static struct serial_ops *
179 serial_interface_lookup (name)
180 char *name;
182 struct serial_ops *ops;
184 for (ops = serial_ops_list; ops; ops = ops->next)
185 if (strcmp (name, ops->name) == 0)
186 return ops;
188 return NULL;
191 void
192 serial_add_interface(optable)
193 struct serial_ops *optable;
195 optable->next = serial_ops_list;
196 serial_ops_list = optable;
199 /* Open up a device or a network socket, depending upon the syntax of NAME. */
201 serial_t
202 serial_open (name)
203 const char *name;
205 serial_t scb;
206 struct serial_ops *ops;
208 for (scb = scb_base; scb; scb = scb->next)
209 if (scb->name && strcmp (scb->name, name) == 0)
211 scb->refcnt++;
212 return scb;
215 if (strcmp (name, "ocd") == 0)
216 ops = serial_interface_lookup ("ocd");
217 else if (strcmp (name, "pc") == 0)
218 ops = serial_interface_lookup ("pc");
219 else if (strchr (name, ':'))
220 ops = serial_interface_lookup ("tcp");
221 else if (strncmp (name, "lpt", 3) == 0)
222 ops = serial_interface_lookup ("parallel");
223 else
224 ops = serial_interface_lookup ("hardwire");
226 if (!ops)
227 return NULL;
229 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
231 scb->ops = ops;
233 scb->bufcnt = 0;
234 scb->bufp = scb->buf;
236 if (scb->ops->open(scb, name))
238 free (scb);
239 return NULL;
242 scb->name = strsave (name);
243 scb->next = scb_base;
244 scb->refcnt = 1;
245 scb_base = scb;
247 last_serial_opened = scb;
249 if (serial_logfile != NULL)
251 serial_logfp = gdb_fopen (serial_logfile, "w");
252 if (serial_logfp == NULL)
253 perror_with_name (serial_logfile);
256 return scb;
259 serial_t
260 serial_fdopen (fd)
261 const int fd;
263 serial_t scb;
264 struct serial_ops *ops;
266 for (scb = scb_base; scb; scb = scb->next)
267 if (scb->fd == fd)
269 scb->refcnt++;
270 return scb;
273 ops = serial_interface_lookup ("hardwire");
275 if (!ops)
276 return NULL;
278 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
280 scb->ops = ops;
282 scb->bufcnt = 0;
283 scb->bufp = scb->buf;
285 scb->fd = fd;
287 scb->name = NULL;
288 scb->next = scb_base;
289 scb->refcnt = 1;
290 scb_base = scb;
292 last_serial_opened = scb;
294 return scb;
297 void
298 serial_close (scb, really_close)
299 serial_t scb;
300 int really_close;
302 serial_t tmp_scb;
304 last_serial_opened = NULL;
306 if (serial_logfp)
308 fputs_unfiltered ("\nEnd of log\n", serial_logfp);
309 serial_current_type = 0;
311 fclose (serial_logfp); /* XXX - What if serial_logfp == stdout or stderr? */
312 serial_logfp = NULL;
315 /* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you
316 should fix your code instead. */
318 if (!scb)
319 return;
321 scb->refcnt--;
322 if (scb->refcnt > 0)
323 return;
325 if (really_close)
326 scb->ops->close (scb);
328 if (scb->name)
329 free (scb->name);
331 if (scb_base == scb)
332 scb_base = scb_base->next;
333 else
334 for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next)
336 if (tmp_scb->next != scb)
337 continue;
339 tmp_scb->next = tmp_scb->next->next;
340 break;
343 free(scb);
346 #if 0
348 The connect command is #if 0 because I hadn't thought of an elegant
349 way to wait for I/O on two serial_t's simultaneously. Two solutions
350 came to mind:
352 1) Fork, and have have one fork handle the to user direction,
353 and have the other hand the to target direction. This
354 obviously won't cut it for MSDOS.
356 2) Use something like select. This assumes that stdin and
357 the target side can both be waited on via the same
358 mechanism. This may not be true for DOS, if GDB is
359 talking to the target via a TCP socket.
360 -grossman, 8 Jun 93
363 /* Connect the user directly to the remote system. This command acts just like
364 the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
366 static serial_t tty_desc; /* Controlling terminal */
368 static void
369 cleanup_tty(ttystate)
370 serial_ttystate ttystate;
372 printf_unfiltered ("\r\n[Exiting connect mode]\r\n");
373 SERIAL_SET_TTY_STATE (tty_desc, ttystate);
374 free (ttystate);
375 SERIAL_CLOSE (tty_desc);
378 static void
379 connect_command (args, fromtty)
380 char *args;
381 int fromtty;
383 int c;
384 char cur_esc = 0;
385 serial_ttystate ttystate;
386 serial_t port_desc; /* TTY port */
388 dont_repeat();
390 if (args)
391 fprintf_unfiltered(gdb_stderr, "This command takes no args. They have been ignored.\n");
393 printf_unfiltered("[Entering connect mode. Use ~. or ~^D to escape]\n");
395 tty_desc = SERIAL_FDOPEN (0);
396 port_desc = last_serial_opened;
398 ttystate = SERIAL_GET_TTY_STATE (tty_desc);
400 SERIAL_RAW (tty_desc);
401 SERIAL_RAW (port_desc);
403 make_cleanup (cleanup_tty, ttystate);
405 while (1)
407 int mask;
409 mask = SERIAL_WAIT_2 (tty_desc, port_desc, -1);
411 if (mask & 2)
412 { /* tty input */
413 char cx;
415 while (1)
417 c = SERIAL_READCHAR(tty_desc, 0);
419 if (c == SERIAL_TIMEOUT)
420 break;
422 if (c < 0)
423 perror_with_name("connect");
425 cx = c;
426 SERIAL_WRITE(port_desc, &cx, 1);
428 switch (cur_esc)
430 case 0:
431 if (c == '\r')
432 cur_esc = c;
433 break;
434 case '\r':
435 if (c == '~')
436 cur_esc = c;
437 else
438 cur_esc = 0;
439 break;
440 case '~':
441 if (c == '.' || c == '\004')
442 return;
443 else
444 cur_esc = 0;
449 if (mask & 1)
450 { /* Port input */
451 char cx;
453 while (1)
455 c = SERIAL_READCHAR(port_desc, 0);
457 if (c == SERIAL_TIMEOUT)
458 break;
460 if (c < 0)
461 perror_with_name("connect");
463 cx = c;
465 SERIAL_WRITE(tty_desc, &cx, 1);
470 #endif /* 0 */
472 /* VARARGS */
473 void
474 #ifdef ANSI_PROTOTYPES
475 serial_printf (serial_t desc, const char *format, ...)
476 #else
477 serial_printf (va_alist)
478 va_dcl
479 #endif
481 va_list args;
482 char *buf;
483 #ifdef ANSI_PROTOTYPES
484 va_start (args, format);
485 #else
486 serial_t desc;
487 char *format;
489 va_start (args);
490 desc = va_arg (args, serial_t);
491 format = va_arg (args, char *);
492 #endif
494 vasprintf (&buf, format, args);
495 SERIAL_WRITE (desc, buf, strlen (buf));
497 free (buf);
498 va_end (args);
501 void
502 _initialize_serial ()
504 #if 0
505 add_com ("connect", class_obscure, connect_command,
506 "Connect the terminal directly up to the command monitor.\n\
507 Use <CR>~. or <CR>~^D to break out.");
508 #endif /* 0 */
510 add_show_from_set (add_set_cmd ("remotelogfile", no_class,
511 var_filename, (char *)&serial_logfile,
512 "Set filename for remote session recording.\n\
513 This file is used to record the remote session for future playback\n\
514 by gdbserver.", &setlist),
515 &showlist);
517 add_show_from_set (add_set_enum_cmd ("remotelogbase", no_class,
518 logbase_enums,
519 (char *)&serial_logbase,
520 "Set numerical base for remote session logging",
521 &setlist),
522 &showlist);