aboutsummaryrefslogtreecommitdiff
path: root/src/monkey/get_free_pty.c
blob: 8c145d0dbfd3a92a344d64a483c61d1c10635603 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/**[txh]********************************************************************

  Copyright (c) 2004 by Salvador E. Tropea.
  Covered by the GPL license.

  Module: pseudo terminal
  Comments:
  Helper to find a free pseudo terminal. Use this if you need to manage
  input *and* output to the target process. If you just need output then
  define a handler for target output stream records (assuming that this
  is working for your particular version of gdb).
  Usage:

        mi_pty *pty = gmi_look_for_free_pty();
        if (pty) gmi_target_terminal(mih, pty->slave);
        ...
        * reading from pty->master will get stdout from target *
        * writing to pty->master will send to target stdin *
        
  Note: Contributed by Greg Watson (gwatson lanl gov)

***************************************************************************/

#define _GNU_SOURCE
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>

#include "mi_gdb.h"

/**[txh]********************************************************************

  Description:
  Look for a free and usable pseudo terminal. Low level, use
@x{gmi_look_for_free_pty}.
  
  Return: A file descriptor connected to the master pty and the name of the slave device, or <0 on error.
  
***************************************************************************/

#ifdef __APPLE__

#include <util.h>

int mi_look_for_free_pty(int *master, char **slave)
{
 int fdmaster;
 int fdslave;
 static char name[BUFSIZ];

 if (openpty(&fdmaster,&fdslave,name,NULL,NULL)<0)
    return -1;

 (void)close(fdslave); /* this will be reopened by gdb */
 *master=fdmaster;
 *slave =name;

 return 0;
}

#elif defined(__linux__)

int mi_look_for_free_pty(int *master, char **slave)
{
 if ((*master=open("/dev/ptmx",O_RDWR))<0)
    return -1;
 if (grantpt(*master)<0 || unlockpt(*master)<0)
    return -1;
 *slave = ptsname(*master);

 return 0;
}

#else /* undefined o/s */

int mi_look_for_free_pty(int *master, char **slave)
{
 return -1;
}
#endif

/**[txh]********************************************************************

  Description:
  Look for a free and usable pseudo terminal to be used by the child.
  
  Return: A new mi_pty structure, you can use @x{gmi_end_pty} to
release it.
  
***************************************************************************/

mi_pty *gmi_look_for_free_pty()
{
 int master;
 char *slave;
 int pty=mi_look_for_free_pty(&master,&slave);
 mi_pty *res;

 if (pty<0)
    return NULL;
 res=(mi_pty *)malloc(sizeof(mi_pty));
 if (!res)
    return NULL;
 res->slave=strdup(slave);
 res->master=master;
 return res;
}

void mi_free_pty(mi_pty *p)
{
 if (!p)
    return;
 free(p->slave);
 free(p);
}

/**[txh]********************************************************************

  Description:
  Closes the pseudo termial master and releases the allocated memory.
  
***************************************************************************/

void gmi_end_pty(mi_pty *p)
{
 if (!p)
    return;
 close(p->master);
 mi_free_pty(p);
}