* configure.in (host_makefile_frag): Don't set. Substitute for
[deliverable/binutils-gdb.git] / gdb / serial.c
1 /* Generic serial interface routines
2 Copyright 1992, 1993 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
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.
10
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.
15
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. */
19
20 #include "defs.h"
21 #include "serial.h"
22
23 /* Linked list of serial I/O handlers */
24
25 static struct serial_ops *serial_ops_list = NULL;
26
27 /* This is the last serial stream opened. Used by connect command. */
28
29 static serial_t last_serial_opened = NULL;
30
31 /* Pointer to list of scb's. */
32
33 static serial_t scb_base;
34
35 static struct serial_ops *
36 serial_interface_lookup (name)
37 char *name;
38 {
39 struct serial_ops *ops;
40
41 for (ops = serial_ops_list; ops; ops = ops->next)
42 if (strcmp (name, ops->name) == 0)
43 return ops;
44
45 return NULL;
46 }
47
48 void
49 serial_add_interface(optable)
50 struct serial_ops *optable;
51 {
52 optable->next = serial_ops_list;
53 serial_ops_list = optable;
54 }
55
56 /* Open up a device or a network socket, depending upon the syntax of NAME. */
57
58 serial_t
59 serial_open (name)
60 const char *name;
61 {
62 serial_t scb;
63 struct serial_ops *ops;
64
65 for (scb = scb_base; scb; scb = scb->next)
66 if (scb->name && strcmp (scb->name, name) == 0)
67 {
68 scb->refcnt++;
69 return scb;
70 }
71
72 if (strcmp (name, "pc") == 0)
73 ops = serial_interface_lookup ("pc");
74 else if (strchr (name, ':'))
75 ops = serial_interface_lookup ("tcp");
76 else
77 ops = serial_interface_lookup ("hardwire");
78
79 if (!ops)
80 return NULL;
81
82 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
83
84 scb->ops = ops;
85
86 scb->bufcnt = 0;
87 scb->bufp = scb->buf;
88
89 if (scb->ops->open(scb, name))
90 {
91 free (scb);
92 return NULL;
93 }
94
95 scb->name = strsave (name);
96 scb->next = scb_base;
97 scb->refcnt = 1;
98 scb_base = scb;
99
100 last_serial_opened = scb;
101
102 return scb;
103 }
104
105 serial_t
106 serial_fdopen (fd)
107 const int fd;
108 {
109 serial_t scb;
110 struct serial_ops *ops;
111
112 for (scb = scb_base; scb; scb = scb->next)
113 if (scb->fd == fd)
114 {
115 scb->refcnt++;
116 return scb;
117 }
118
119 ops = serial_interface_lookup ("hardwire");
120
121 if (!ops)
122 return NULL;
123
124 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
125
126 scb->ops = ops;
127
128 scb->bufcnt = 0;
129 scb->bufp = scb->buf;
130
131 scb->fd = fd;
132
133 scb->name = NULL;
134 scb->next = scb_base;
135 scb->refcnt = 1;
136 scb_base = scb;
137
138 last_serial_opened = scb;
139
140 return scb;
141 }
142
143 void
144 serial_close(scb, really_close)
145 serial_t scb;
146 int really_close;
147 {
148 serial_t tmp_scb;
149
150 last_serial_opened = NULL;
151
152 /* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you
153 should fix your code instead. */
154
155 if (!scb)
156 return;
157
158 scb->refcnt--;
159 if (scb->refcnt > 0)
160 return;
161
162 if (really_close)
163 scb->ops->close (scb);
164
165 if (scb->name)
166 free (scb->name);
167
168 if (scb_base == scb)
169 scb_base = scb_base->next;
170 else
171 for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next)
172 {
173 if (tmp_scb->next != scb)
174 continue;
175
176 tmp_scb->next = tmp_scb->next->next;
177 break;
178 }
179
180 free(scb);
181 }
182
183 #if 0
184 /*
185 The connect command is #if 0 because I hadn't thought of an elegant
186 way to wait for I/O on two serial_t's simultaneously. Two solutions
187 came to mind:
188
189 1) Fork, and have have one fork handle the to user direction,
190 and have the other hand the to target direction. This
191 obviously won't cut it for MSDOS.
192
193 2) Use something like select. This assumes that stdin and
194 the target side can both be waited on via the same
195 mechanism. This may not be true for DOS, if GDB is
196 talking to the target via a TCP socket.
197 -grossman, 8 Jun 93
198 */
199
200 /* Connect the user directly to the remote system. This command acts just like
201 the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
202
203 static serial_t tty_desc; /* Controlling terminal */
204
205 static void
206 cleanup_tty(ttystate)
207 serial_ttystate ttystate;
208 {
209 printf_unfiltered ("\r\n[Exiting connect mode]\r\n");
210 SERIAL_SET_TTY_STATE (tty_desc, ttystate);
211 free (ttystate);
212 SERIAL_CLOSE (tty_desc);
213 }
214
215 static void
216 connect_command (args, fromtty)
217 char *args;
218 int fromtty;
219 {
220 int c;
221 char cur_esc = 0;
222 serial_ttystate ttystate;
223 serial_t port_desc; /* TTY port */
224
225 dont_repeat();
226
227 if (args)
228 fprintf_unfiltered(gdb_stderr, "This command takes no args. They have been ignored.\n");
229
230 printf_unfiltered("[Entering connect mode. Use ~. or ~^D to escape]\n");
231
232 tty_desc = SERIAL_FDOPEN (0);
233 port_desc = last_serial_opened;
234
235 ttystate = SERIAL_GET_TTY_STATE (tty_desc);
236
237 SERIAL_RAW (tty_desc);
238 SERIAL_RAW (port_desc);
239
240 make_cleanup (cleanup_tty, ttystate);
241
242 while (1)
243 {
244 int mask;
245
246 mask = SERIAL_WAIT_2 (tty_desc, port_desc, -1);
247
248 if (mask & 2)
249 { /* tty input */
250 char cx;
251
252 while (1)
253 {
254 c = SERIAL_READCHAR(tty_desc, 0);
255
256 if (c == SERIAL_TIMEOUT)
257 break;
258
259 if (c < 0)
260 perror_with_name("connect");
261
262 cx = c;
263 SERIAL_WRITE(port_desc, &cx, 1);
264
265 switch (cur_esc)
266 {
267 case 0:
268 if (c == '\r')
269 cur_esc = c;
270 break;
271 case '\r':
272 if (c == '~')
273 cur_esc = c;
274 else
275 cur_esc = 0;
276 break;
277 case '~':
278 if (c == '.' || c == '\004')
279 return;
280 else
281 cur_esc = 0;
282 }
283 }
284 }
285
286 if (mask & 1)
287 { /* Port input */
288 char cx;
289
290 while (1)
291 {
292 c = SERIAL_READCHAR(port_desc, 0);
293
294 if (c == SERIAL_TIMEOUT)
295 break;
296
297 if (c < 0)
298 perror_with_name("connect");
299
300 cx = c;
301
302 SERIAL_WRITE(tty_desc, &cx, 1);
303 }
304 }
305 }
306 }
307 #endif /* 0 */
308
309 void
310 _initialize_serial ()
311 {
312 #if 0
313 add_com ("connect", class_obscure, connect_command,
314 "Connect the terminal directly up to the command monitor.\n\
315 Use <CR>~. or <CR>~^D to break out.");
316 #endif /* 0 */
317 }
This page took 0.035804 seconds and 4 git commands to generate.