8c145d0dbfd3a92a344d64a483c61d1c10635603
[gdbmicli.git] / src / get_free_pty.c
1 /**[txh]********************************************************************
2
3   Copyright (c) 2004 by Salvador E. Tropea.
4   Covered by the GPL license.
5
6   Module: pseudo terminal
7   Comments:
8   Helper to find a free pseudo terminal. Use this if you need to manage
9   input *and* output to the target process. If you just need output then
10   define a handler for target output stream records (assuming that this
11   is working for your particular version of gdb).
12   Usage:
13
14         mi_pty *pty = gmi_look_for_free_pty();
15         if (pty) gmi_target_terminal(mih, pty->slave);
16         ...
17         * reading from pty->master will get stdout from target *
18         * writing to pty->master will send to target stdin *
19         
20   Note: Contributed by Greg Watson (gwatson lanl gov)
21
22 ***************************************************************************/
23
24 #define _GNU_SOURCE
25 #include <string.h>
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <sys/ioctl.h>
30
31 #include "mi_gdb.h"
32
33 /**[txh]********************************************************************
34
35   Description:
36   Look for a free and usable pseudo terminal. Low level, use
37 @x{gmi_look_for_free_pty}.
38   
39   Return: A file descriptor connected to the master pty and the name of the slave device, or <0 on error.
40   
41 ***************************************************************************/
42
43 #ifdef __APPLE__
44
45 #include <util.h>
46
47 int mi_look_for_free_pty(int *master, char **slave)
48 {
49  int fdmaster;
50  int fdslave;
51  static char name[BUFSIZ];
52
53  if (openpty(&fdmaster,&fdslave,name,NULL,NULL)<0)
54     return -1;
55
56  (void)close(fdslave); /* this will be reopened by gdb */
57  *master=fdmaster;
58  *slave =name;
59
60  return 0;
61 }
62
63 #elif defined(__linux__)
64
65 int mi_look_for_free_pty(int *master, char **slave)
66 {
67  if ((*master=open("/dev/ptmx",O_RDWR))<0)
68     return -1;
69  if (grantpt(*master)<0 || unlockpt(*master)<0)
70     return -1;
71  *slave = ptsname(*master);
72
73  return 0;
74 }
75
76 #else /* undefined o/s */
77
78 int mi_look_for_free_pty(int *master, char **slave)
79 {
80  return -1;
81 }
82 #endif
83
84 /**[txh]********************************************************************
85
86   Description:
87   Look for a free and usable pseudo terminal to be used by the child.
88   
89   Return: A new mi_pty structure, you can use @x{gmi_end_pty} to
90 release it.
91   
92 ***************************************************************************/
93
94 mi_pty *gmi_look_for_free_pty()
95 {
96  int master;
97  char *slave;
98  int pty=mi_look_for_free_pty(&master,&slave);
99  mi_pty *res;
100
101  if (pty<0)
102     return NULL;
103  res=(mi_pty *)malloc(sizeof(mi_pty));
104  if (!res)
105     return NULL;
106  res->slave=strdup(slave);
107  res->master=master;
108  return res;
109 }
110
111 void mi_free_pty(mi_pty *p)
112 {
113  if (!p)
114     return;
115  free(p->slave);
116  free(p);
117 }
118
119 /**[txh]********************************************************************
120
121   Description:
122   Closes the pseudo termial master and releases the allocated memory.
123   
124 ***************************************************************************/
125
126 void gmi_end_pty(mi_pty *p)
127 {
128  if (!p)
129     return;
130  close(p->master);
131  mi_free_pty(p);
132 }