gcc lint
[external/binutils.git] / gdb / ser-unix.c
1 /* Serial interface for local (hardwired) serial ports on Un*x like systems
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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include "defs.h"
21 #include "serial.h"
22 #include <fcntl.h>
23 #include <sys/types.h>
24
25 #if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY)
26 #define HAVE_SGTTY
27 #endif
28
29 #ifdef HAVE_TERMIOS
30 #include <termios.h>
31 #include <unistd.h>
32
33 struct hardwire_ttystate
34 {
35   struct termios termios;
36   pid_t process_group;
37 };
38 #endif /* termios */
39
40 #ifdef HAVE_TERMIO
41 #include <termio.h>
42
43 /* It is believed that all systems which have added job control to SVR3
44    (e.g. sco) have also added termios.  Even if not, trying to figure out
45    all the variations (TIOCGPGRP vs. TCGETPGRP, etc.) would be pretty
46    bewildering.  So we don't attempt it.  */
47
48 struct hardwire_ttystate
49 {
50   struct termio termio;
51 };
52 #endif /* termio */
53
54 #ifdef HAVE_SGTTY
55 /* Needed for the code which uses select().  We would include <sys/select.h>
56    too if it existed on all systems.  */
57 #include <sys/time.h>
58
59 #include <sgtty.h>
60
61 struct hardwire_ttystate
62 {
63   struct sgttyb sgttyb;
64   struct tchars tc;
65   struct ltchars ltc;
66   /* Line discipline flags.  */
67   int lmode;
68
69 #ifdef SHORT_PGRP
70   /* This is only used for the ultra.  Does it have pid_t?  */
71   short process_group;
72 #else
73   int process_group;
74 #endif
75 };
76 #endif /* sgtty */
77
78 static int hardwire_open PARAMS ((serial_t scb, const char *name));
79 static void hardwire_raw PARAMS ((serial_t scb));
80 static int wait_for PARAMS ((serial_t scb, int timeout));
81 static int hardwire_readchar PARAMS ((serial_t scb, int timeout));
82 static int rate_to_code PARAMS ((int rate));
83 static int hardwire_setbaudrate PARAMS ((serial_t scb, int rate));
84 static int hardwire_write PARAMS ((serial_t scb, const char *str, int len));
85 /* FIXME: static void hardwire_restore PARAMS ((serial_t scb)); */
86 static void hardwire_close PARAMS ((serial_t scb));
87 static int get_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate *state));
88 static int set_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate *state));
89 static serial_ttystate hardwire_get_tty_state PARAMS ((serial_t scb));
90 static int hardwire_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
91
92 /* Open up a real live device for serial I/O */
93
94 static int
95 hardwire_open(scb, name)
96      serial_t scb;
97      const char *name;
98 {
99   scb->fd = open (name, O_RDWR);
100   if (scb->fd < 0)
101     return -1;
102
103   return 0;
104 }
105
106 static int
107 get_tty_state(scb, state)
108      serial_t scb;
109      struct hardwire_ttystate *state;
110 {
111 #ifdef HAVE_TERMIOS
112   extern int errno;
113   pid_t new_process_group;
114
115   if (tcgetattr(scb->fd, &state->termios) < 0)
116     return -1;
117
118   if (!job_control)
119     return 0;
120
121   /* Apparently, if a tty has no process group, then tcgetpgrp returns -1 with
122      errno == 0.   In this case, set the process group to -1 so that we know to
123      omit resetting it later.  */
124   new_process_group = tcgetpgrp (scb->fd);
125   if ((new_process_group == (pid_t)-1)
126       && (errno != ENOTTY))
127     return -1;
128   errno = 0;
129   state->process_group = new_process_group;
130   return 0;
131 #endif
132
133 #ifdef HAVE_TERMIO
134   if (ioctl (scb->fd, TCGETA, &state->termio) < 0)
135     return -1;
136   return 0;
137 #endif
138
139 #ifdef HAVE_SGTTY
140   if (ioctl (scb->fd, TIOCGETP, &state->sgttyb) < 0)
141     return -1;
142   if (ioctl (scb->fd, TIOCGETC, &state->tc) < 0)
143     return -1;
144   if (ioctl (scb->fd, TIOCGLTC, &state->ltc) < 0)
145     return -1;
146   if (ioctl (scb->fd, TIOCLGET, &state->lmode) < 0)
147     return -1;
148
149   if (!job_control)
150     return 0;
151
152   return ioctl (scb->fd, TIOCGPGRP, &state->process_group);
153 #endif
154 }
155
156 static int
157 set_tty_state(scb, state)
158      serial_t scb;
159      struct hardwire_ttystate *state;
160 {
161 #ifdef HAVE_TERMIOS
162   if (tcsetattr(scb->fd, TCSANOW, &state->termios) < 0)
163     return -1;
164
165   if (!job_control)
166     return 0;
167
168   /* If the tty had no process group before, then do not reset it. */
169   if (state->process_group == -1)
170     return 0;
171   else
172     return tcsetpgrp (scb->fd, state->process_group);
173 #endif
174
175 #ifdef HAVE_TERMIO
176   if (ioctl (scb->fd, TCSETA, &state->termio) < 0)
177     return -1;
178   return 0;
179 #endif
180
181 #ifdef HAVE_SGTTY
182   if (ioctl (scb->fd, TIOCSETN, &state->sgttyb) < 0)
183     return -1;
184
185   if (!job_control)
186     return 0;
187
188   return ioctl (scb->fd, TIOCSPGRP, &state->process_group);
189 #endif
190 }
191
192 static serial_ttystate
193 hardwire_get_tty_state(scb)
194      serial_t scb;
195 {
196   struct hardwire_ttystate *state;
197
198   state = (struct hardwire_ttystate *)xmalloc(sizeof *state);
199
200   if (get_tty_state(scb, state))
201     return NULL;
202
203   return (serial_ttystate)state;
204 }
205
206 static int
207 hardwire_set_tty_state(scb, ttystate)
208      serial_t scb;
209      serial_ttystate ttystate;
210 {
211   struct hardwire_ttystate *state;
212
213   state = (struct hardwire_ttystate *)ttystate;
214
215   return set_tty_state(scb, state);
216 }
217
218 static int
219 hardwire_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
220      serial_t scb;
221      serial_ttystate new_ttystate;
222      serial_ttystate old_ttystate;
223 {
224   struct hardwire_ttystate new_state;
225   struct hardwire_ttystate *state = (struct hardwire_ttystate *) old_ttystate;
226
227   new_state = *(struct hardwire_ttystate *)new_ttystate;
228
229 #ifdef HAVE_TERMIOS
230   /* I'm not sure whether this is necessary; the manpage makes no mention
231      of discarding input when switching to/from ICANON.  */
232   if (state->termios.c_lflag & ICANON)
233     new_state.termios.c_lflag |= ICANON;
234   else
235     new_state.termios.c_lflag &= ~ICANON;
236 #endif
237
238 #ifdef HAVE_TERMIO
239   /* I'm not sure whether this is necessary; the manpage makes no mention
240      of discarding input when switching to/from ICANON.  */
241   if (state->termio.c_lflag & ICANON)
242     new_state.termio.c_lflag |= ICANON;
243   else
244     new_state.termio.c_lflag &= ~ICANON;
245 #endif
246
247 #ifdef HAVE_SGTTY
248   if (state->sgttyb.sg_flags & RAW)
249     new_state.sgttyb.sg_flags |= RAW;
250   else
251     new_state.sgttyb.sg_flags &= ~RAW;
252
253   /* I'm not sure whether this is necessary; the manpage just mentions
254      RAW not CBREAK.  */
255   if (state->sgttyb.sg_flags & CBREAK)
256     new_state.sgttyb.sg_flags |= CBREAK;
257   else
258     new_state.sgttyb.sg_flags &= ~CBREAK;
259 #endif
260
261   return set_tty_state (scb, &new_state);
262 }
263
264 static void
265 hardwire_print_tty_state (scb, ttystate)
266      serial_t scb;
267      serial_ttystate ttystate;
268 {
269   struct hardwire_ttystate *state = (struct hardwire_ttystate *) ttystate;
270   int i;
271
272 #ifdef HAVE_TERMIOS
273   printf_filtered ("Process group = %d\n", state->process_group);
274
275   printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n",
276                    state->termios.c_iflag, state->termios.c_oflag);
277   printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x\n",
278                    state->termios.c_cflag, state->termios.c_lflag);
279 #if 0
280   /* This not in POSIX, and is not really documented by those systems
281      which have it (at least not Sun).  */
282   printf_filtered ("c_line = 0x%x.\n", state->termios.c_line);
283 #endif
284   printf_filtered ("c_cc: ");
285   for (i = 0; i < NCCS; i += 1)
286     printf_filtered ("0x%x ", state->termios.c_cc[i]);
287   printf_filtered ("\n");
288 #endif
289
290 #ifdef HAVE_TERMIO
291   printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n",
292                    state->termio.c_iflag, state->termio.c_oflag);
293   printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n",
294                    state->termio.c_cflag, state->termio.c_lflag,
295                    state->termio.c_line);
296   printf_filtered ("c_cc: ");
297   for (i = 0; i < NCC; i += 1)
298     printf_filtered ("0x%x ", state->termio.c_cc[i]);
299   printf_filtered ("\n");
300 #endif
301
302 #ifdef HAVE_SGTTY
303   printf_filtered ("Process group = %d\n", state->process_group);
304
305   printf_filtered ("sgttyb.sg_flags = 0x%x.\n", state->sgttyb.sg_flags);
306
307   printf_filtered ("tchars: ");
308   for (i = 0; i < (int)sizeof (struct tchars); i++)
309     printf_filtered ("0x%x ", ((unsigned char *)&state->tc)[i]);
310   printf_filtered ("\n");
311
312   printf_filtered ("ltchars: ");
313   for (i = 0; i < (int)sizeof (struct ltchars); i++)
314     printf_filtered ("0x%x ", ((unsigned char *)&state->ltc)[i]);
315   printf_filtered ("\n");
316
317   printf_filtered ("lmode:  0x%x\n", state->lmode);
318 #endif
319 }
320
321 static int
322 hardwire_flush_output (scb)
323      serial_t scb;
324 {
325 #ifdef HAVE_TERMIOS
326   return tcflush (scb->fd, TCOFLUSH);
327 #endif
328
329 #ifdef HAVE_TERMIO
330   return ioctl (scb->fd, TCFLSH, 1);
331 #endif
332
333 #ifdef HAVE_SGTTY
334   /* This flushes both input and output, but we can't do better.  */
335   return ioctl (scb->fd, TIOCFLUSH, 0);
336 #endif  
337 }
338
339 static int
340 hardwire_flush_input (scb)
341      serial_t scb;
342 {
343 #ifdef HAVE_TERMIOS
344   return tcflush (scb->fd, TCIFLUSH);
345 #endif
346
347 #ifdef HAVE_TERMIO
348   return ioctl (scb->fd, TCFLSH, 0);
349 #endif
350
351 #ifdef HAVE_SGTTY
352   /* This flushes both input and output, but we can't do better.  */
353   return ioctl (scb->fd, TIOCFLUSH, 0);
354 #endif  
355 }
356
357 static int
358 hardwire_send_break (scb)
359      serial_t scb;
360 {
361 #ifdef HAVE_TERMIOS
362   return tcsendbreak (scb->fd, 0);
363 #endif
364
365 #ifdef HAVE_TERMIO
366   return ioctl (scb->fd, TCSBRK, 0);
367 #endif
368
369 #ifdef HAVE_SGTTY
370   {
371     int status;
372     struct timeval timeout;
373
374     status = ioctl (scb->fd, TIOCSBRK, 0);
375
376     /* Can't use usleep; it doesn't exist in BSD 4.2.  */
377     /* Note that if this select() is interrupted by a signal it will not wait
378        the full length of time.  I think that is OK.  */
379     timeout.tv_sec = 0;
380     timeout.tv_usec = 250000;
381     select (0, 0, 0, 0, &timeout);
382     status = ioctl (scb->fd, TIOCCBRK, 0);
383     return status;
384   }
385 #endif  
386 }
387
388 static void
389 hardwire_raw(scb)
390      serial_t scb;
391 {
392   struct hardwire_ttystate state;
393
394   if (get_tty_state(scb, &state))
395     fprintf(stderr, "get_tty_state failed: %s\n", safe_strerror(errno));
396
397 #ifdef HAVE_TERMIOS
398   state.termios.c_iflag = 0;
399   state.termios.c_oflag = 0;
400   state.termios.c_lflag = 0;
401   state.termios.c_cflag &= ~(CSIZE|PARENB);
402   state.termios.c_cflag |= CS8;
403   state.termios.c_cc[VMIN] = 0;
404   state.termios.c_cc[VTIME] = 0;
405 #endif
406
407 #ifdef HAVE_TERMIO
408   state.termio.c_iflag = 0;
409   state.termio.c_oflag = 0;
410   state.termio.c_lflag = 0;
411   state.termio.c_cflag &= ~(CSIZE|PARENB);
412   state.termio.c_cflag |= CS8;
413   state.termio.c_cc[VMIN] = 0;
414   state.termio.c_cc[VTIME] = 0;
415 #endif
416
417 #ifdef HAVE_SGTTY
418   state.sgttyb.sg_flags |= RAW | ANYP;
419   state.sgttyb.sg_flags &= ~(CBREAK | ECHO);
420 #endif
421
422   scb->current_timeout = 0;
423
424   if (set_tty_state (scb, &state))
425     fprintf(stderr, "set_tty_state failed: %s\n", safe_strerror(errno));
426 }
427
428 /* Wait for input on scb, with timeout seconds.  Returns 0 on success,
429    otherwise SERIAL_TIMEOUT or SERIAL_ERROR.
430
431    For termio{s}, we actually just setup VTIME if necessary, and let the
432    timeout occur in the read() in hardwire_read().
433  */
434
435 static int
436 wait_for(scb, timeout)
437      serial_t scb;
438      int timeout;
439 {
440 #ifdef HAVE_SGTTY
441   struct timeval tv;
442   fd_set readfds;
443
444   FD_ZERO (&readfds);
445
446   tv.tv_sec = timeout;
447   tv.tv_usec = 0;
448
449   FD_SET(scb->fd, &readfds);
450
451   while (1)
452     {
453       int numfds;
454
455       if (timeout >= 0)
456         numfds = select(scb->fd+1, &readfds, 0, 0, &tv);
457       else
458         numfds = select(scb->fd+1, &readfds, 0, 0, 0);
459
460       if (numfds <= 0)
461         if (numfds == 0)
462           return SERIAL_TIMEOUT;
463         else if (errno == EINTR)
464           continue;
465         else
466           return SERIAL_ERROR;  /* Got an error from select or poll */
467
468       return 0;
469     }
470
471 #endif  /* HAVE_SGTTY */
472
473 #if defined HAVE_TERMIO || defined HAVE_TERMIOS
474   if (timeout == scb->current_timeout)
475     return 0;
476
477   {
478     struct hardwire_ttystate state;
479
480     if (get_tty_state(scb, &state))
481       fprintf(stderr, "get_tty_state failed: %s\n", safe_strerror(errno));
482
483 #ifdef HAVE_TERMIOS
484     state.termios.c_cc[VTIME] = timeout * 10;
485 #endif
486
487 #ifdef HAVE_TERMIO
488     state.termio.c_cc[VTIME] = timeout * 10;
489 #endif
490
491     scb->current_timeout = timeout;
492
493     if (set_tty_state (scb, &state))
494       fprintf(stderr, "set_tty_state failed: %s\n", safe_strerror(errno));
495
496     return 0;
497   }
498 #endif  /* HAVE_TERMIO || HAVE_TERMIOS */
499 }
500
501 /* Read a character with user-specified timeout.  TIMEOUT is number of seconds
502    to wait, or -1 to wait forever.  Use timeout of 0 to effect a poll.  Returns
503    char if successful.  Returns SERIAL_TIMEOUT if timeout expired, EOF if line
504    dropped dead, or SERIAL_ERROR for any other error (see errno in that case).  */
505
506 static int
507 hardwire_readchar(scb, timeout)
508      serial_t scb;
509      int timeout;
510 {
511   int status;
512
513   if (scb->bufcnt-- > 0)
514     return *scb->bufp++;
515
516   status = wait_for(scb, timeout);
517
518   if (status < 0)
519     return status;
520
521   scb->bufcnt = read(scb->fd, scb->buf, BUFSIZ);
522
523   if (scb->bufcnt <= 0)
524     if (scb->bufcnt == 0)
525       return SERIAL_TIMEOUT;    /* 0 chars means timeout [may need to
526                                    distinguish between EOF & timeouts
527                                    someday] */
528     else
529       return SERIAL_ERROR;      /* Got an error from read */
530
531   scb->bufcnt--;
532   scb->bufp = scb->buf;
533   return *scb->bufp++;
534 }
535
536 #ifndef B19200
537 #define B19200 EXTA
538 #endif
539
540 #ifndef B38400
541 #define B38400 EXTB
542 #endif
543
544 /* Translate baud rates from integers to damn B_codes.  Unix should
545    have outgrown this crap years ago, but even POSIX wouldn't buck it.  */
546
547 static struct
548 {
549   int rate;
550   int code;
551 }
552 baudtab[] =
553 {
554   {50, B50},
555   {75, B75},
556   {110, B110},
557   {134, B134},
558   {150, B150},
559   {200, B200},
560   {300, B300},
561   {600, B600},
562   {1200, B1200},
563   {1800, B1800},
564   {2400, B2400},
565   {4800, B4800},
566   {9600, B9600},
567   {19200, B19200},
568   {38400, B38400},
569   {-1, -1},
570 };
571
572 static int 
573 rate_to_code(rate)
574      int rate;
575 {
576   int i;
577
578   for (i = 0; baudtab[i].rate != -1; i++)
579     if (rate == baudtab[i].rate)  
580       return baudtab[i].code;
581
582   return -1;
583 }
584
585 static int
586 hardwire_setbaudrate(scb, rate)
587      serial_t scb;
588      int rate;
589 {
590   struct hardwire_ttystate state;
591
592   if (get_tty_state(scb, &state))
593     return -1;
594
595 #ifdef HAVE_TERMIOS
596   cfsetospeed (&state.termios, rate_to_code (rate));
597   cfsetispeed (&state.termios, rate_to_code (rate));
598 #endif
599
600 #ifdef HAVE_TERMIO
601 #ifndef CIBAUD
602 #define CIBAUD CBAUD
603 #endif
604
605   state.termio.c_cflag &= ~(CBAUD | CIBAUD);
606   state.termio.c_cflag |= rate_to_code (rate);
607 #endif
608
609 #ifdef HAVE_SGTTY
610   state.sgttyb.sg_ispeed = rate_to_code (rate);
611   state.sgttyb.sg_ospeed = rate_to_code (rate);
612 #endif
613
614   return set_tty_state (scb, &state);
615 }
616
617 static int
618 hardwire_set_process_group (scb, ttystate, group)
619      serial_t scb;
620      serial_ttystate ttystate;
621      int group;
622 {
623 #if defined (HAVE_SGTTY) || defined (HAVE_TERMIOS)
624   ((struct hardwire_ttystate *)ttystate)->process_group = group;
625 #endif
626   return 0;
627 }
628
629 static int
630 hardwire_write(scb, str, len)
631      serial_t scb;
632      const char *str;
633      int len;
634 {
635   int cc;
636
637   while (len > 0)
638     {
639       cc = write(scb->fd, str, len);
640
641       if (cc < 0)
642         return 1;
643       len -= cc;
644       str += cc;
645     }
646   return 0;
647 }
648
649 static void
650 hardwire_close(scb)
651      serial_t scb;
652 {
653   if (scb->fd < 0)
654     return;
655
656   close(scb->fd);
657   scb->fd = -1;
658 }
659
660 static struct serial_ops hardwire_ops =
661 {
662   "hardwire",
663   0,
664   hardwire_open,
665   hardwire_close,
666   hardwire_readchar,
667   hardwire_write,
668   hardwire_flush_output,
669   hardwire_flush_input,
670   hardwire_send_break,
671   hardwire_raw,
672   hardwire_get_tty_state,
673   hardwire_set_tty_state,
674   hardwire_print_tty_state,
675   hardwire_noflush_set_tty_state,
676   hardwire_setbaudrate,
677   hardwire_set_process_group
678 };
679
680 int job_control;
681 #if defined (HAVE_TERMIOS)
682 #include <unistd.h>
683 #endif
684
685 /* This is here because this is where we figure out whether we (probably)
686    have job control.  Just using job_control only does part of it because
687    setpgid or setpgrp might not exist on a system without job control.
688    It might be considered misplaced (on the other hand, process groups and
689    job control are closely related to ttys).
690
691    For a more clean implementation, in libiberty, put a setpgid which merely
692    calls setpgrp and a setpgrp which does nothing (any system with job control
693    will have one or the other).  */
694 int
695 gdb_setpgid ()
696 {
697   int retval = 0;
698   if (job_control)
699     {
700 #if defined (NEED_POSIX_SETPGID) || defined (HAVE_TERMIOS)
701       /* Do all systems with termios have setpgid?  I hope so.  */
702       /* setpgid (0, 0) is supposed to work and mean the same thing as
703          this, but on Ultrix 4.2A it fails with EPERM (and
704          setpgid (getpid (), getpid ()) succeeds).  */
705       retval = setpgid (getpid (), getpid ());
706 #else
707 #if defined (TIOCGPGRP)
708 #if defined(USG) && !defined(SETPGRP_ARGS)
709       retval = setpgrp ();
710 #else
711       retval = setpgrp (getpid (), getpid ());
712 #endif /* USG */
713 #endif /* TIOCGPGRP.  */
714 #endif /* NEED_POSIX_SETPGID */
715     }
716   return retval;
717 }
718
719 void
720 _initialize_ser_hardwire ()
721 {
722   serial_add_interface (&hardwire_ops);
723
724   /* OK, figure out whether we have job control.  */
725
726 #if defined (HAVE_TERMIOS)
727   /* Do all systems with termios have the POSIX way of identifying job
728      control?  I hope so.  */
729 #ifdef _POSIX_JOB_CONTROL
730   job_control = 1;
731 #else
732   job_control = sysconf (_SC_JOB_CONTROL);
733 #endif
734 #endif /* termios */
735
736 #ifdef HAVE_TERMIO
737   /* See comment at top of file about trying to support process groups
738      with termio.  */
739   job_control = 0;
740 #endif /* termio */
741
742 #ifdef HAVE_SGTTY
743 #ifdef TIOCGPGRP
744   job_control = 1;
745 #else
746   job_control = 0;
747 #endif /* TIOCGPGRP */
748 #endif /* sgtty */
749
750 }