2 ** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 ** Distributed under the terms of the Haiku License.
10 #include <util/AutoLock.h>
14 #include "tty_private.h"
19 # define TRACE(x) dprintf x
25 struct slave_cookie
: tty_cookie
{
29 struct tty gSlaveTTYs
[kNumTTYs
];
33 slave_open(const char *name
, uint32 flags
, void **_cookie
)
35 // Get the tty index: Opening "/dev/tty" means opening the process'
37 int32 index
= get_tty_index(name
);
38 if (strcmp(name
, "tty") == 0) {
39 index
= team_get_controlling_tty();
43 index
= get_tty_index(name
);
44 if (index
>= (int32
)kNumTTYs
)
48 TRACE(("slave_open: TTY index = %ld (name = %s)\n", index
, name
));
50 MutexLocker
globalLocker(gGlobalTTYLock
);
52 // we may only be used if our master has already been opened
53 if (gMasterTTYs
[index
].open_count
== 0)
56 bool makeControllingTTY
= (flags
& O_NOCTTY
) == 0;
57 pid_t processID
= getpid();
58 pid_t sessionID
= getsid(processID
);
60 if (gSlaveTTYs
[index
].open_count
== 0) {
61 // We only allow session leaders to open the tty initially.
62 if (makeControllingTTY
&& processID
!= sessionID
)
65 status_t status
= tty_open(&gSlaveTTYs
[index
], NULL
);
67 // initializing TTY failed
70 } else if (makeControllingTTY
) {
71 // If already open, we allow only processes from the same session
72 // to open the tty again.
73 pid_t ttySession
= gSlaveTTYs
[index
].settings
->session_id
;
74 if (ttySession
>= 0) {
75 if (ttySession
!= sessionID
)
77 makeControllingTTY
= false;
79 // The tty is not associated with a session yet. The process needs
80 // to be a session leader.
81 if (makeControllingTTY
&& processID
!= sessionID
)
86 slave_cookie
*cookie
= (slave_cookie
*)malloc(sizeof(struct slave_cookie
));
88 if (gSlaveTTYs
[index
].open_count
== 0)
89 tty_close(&gSlaveTTYs
[index
]);
94 status_t status
= init_tty_cookie(cookie
, &gSlaveTTYs
[index
],
95 &gMasterTTYs
[index
], flags
);
99 if (gSlaveTTYs
[index
].open_count
== 0)
100 tty_close(&gSlaveTTYs
[index
]);
105 if (gSlaveTTYs
[index
].open_count
== 0) {
106 gSlaveTTYs
[index
].lock
= gMasterTTYs
[index
].lock
;
107 gSlaveTTYs
[index
].settings
->session_id
= -1;
108 gSlaveTTYs
[index
].settings
->pgrp_id
= -1;
111 if (makeControllingTTY
) {
112 gSlaveTTYs
[index
].settings
->session_id
= sessionID
;
113 gSlaveTTYs
[index
].settings
->pgrp_id
= sessionID
;
114 team_set_controlling_tty(gSlaveTTYs
[index
].index
);
117 add_tty_cookie(cookie
);
126 slave_close(void *_cookie
)
128 slave_cookie
*cookie
= (slave_cookie
*)_cookie
;
130 TRACE(("slave_close: cookie %p\n", _cookie
));
132 MutexLocker
globalLocker(gGlobalTTYLock
);
134 // unblock and wait for all blocking operations
135 tty_close_cookie(cookie
);
142 slave_free_cookie(void *_cookie
)
144 // The TTY is already closed. We only have to free the cookie.
145 slave_cookie
*cookie
= (slave_cookie
*)_cookie
;
147 TRACE(("slave_free_cookie: cookie %p\n", _cookie
));
149 MutexLocker
globalLocker(gGlobalTTYLock
);
150 uninit_tty_cookie(cookie
);
151 globalLocker
.Unlock();
160 slave_ioctl(void *_cookie
, uint32 op
, void *buffer
, size_t length
)
162 slave_cookie
*cookie
= (slave_cookie
*)_cookie
;
164 TRACE(("slave_ioctl: cookie %p, op %lu, buffer %p, length %lu\n", _cookie
, op
, buffer
, length
));
166 return tty_ioctl(cookie
, op
, buffer
, length
);
171 slave_read(void *_cookie
, off_t offset
, void *buffer
, size_t *_length
)
173 slave_cookie
*cookie
= (slave_cookie
*)_cookie
;
175 TRACE(("slave_read: cookie %p, offset %Ld, buffer %p, length %lu\n",
176 _cookie
, offset
, buffer
, *_length
));
178 status_t result
= tty_input_read(cookie
, buffer
, _length
);
180 TRACE(("slave_read done: cookie %p, result %lx, length %lu\n",
181 _cookie
, result
, *_length
));
188 slave_write(void *_cookie
, off_t offset
, const void *buffer
, size_t *_length
)
190 slave_cookie
*cookie
= (slave_cookie
*)_cookie
;
192 TRACE(("slave_write: cookie %p, offset %Ld, buffer %p, length %lu\n",
193 _cookie
, offset
, buffer
, *_length
));
195 status_t result
= tty_write_to_tty_slave(cookie
, buffer
, _length
);
197 TRACE(("slave_write done: cookie %p, result %lx, length %lu\n",
198 _cookie
, result
, *_length
));
205 slave_select(void *_cookie
, uint8 event
, uint32 ref
, selectsync
*sync
)
207 slave_cookie
*cookie
= (slave_cookie
*)_cookie
;
209 return tty_select(cookie
, event
, ref
, sync
);
214 slave_deselect(void *_cookie
, uint8 event
, selectsync
*sync
)
216 slave_cookie
*cookie
= (slave_cookie
*)_cookie
;
218 return tty_deselect(cookie
, event
, sync
);
222 device_hooks gSlaveTTYHooks
= {
231 NULL
, // read_pages()
232 NULL
// write_pages()