diff --git a/headers/private/drivers/tty.h b/headers/private/drivers/tty.h new file mode 100644 index 0000000000..ae54e06214 --- /dev/null +++ b/headers/private/drivers/tty.h @@ -0,0 +1,14 @@ +/* + * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _DRIVERS_TTY_H +#define _DRIVERS_TTY_H + +#include + +#define B_IOCTL_GET_TTY_INDEX (TCGETA + 32) /* param is int32* */ +#define B_IOCTL_GRANT_TTY (TCGETA + 33) /* no param (cf. grantpt()) */ + + +#endif // _DRIVERS_TTY_H diff --git a/src/add-ons/kernel/drivers/tty/Jamfile b/src/add-ons/kernel/drivers/tty/Jamfile index 1d025216e8..487793908c 100644 --- a/src/add-ons/kernel/drivers/tty/Jamfile +++ b/src/add-ons/kernel/drivers/tty/Jamfile @@ -1,6 +1,7 @@ SubDir HAIKU_TOP src add-ons kernel drivers tty ; UsePrivateKernelHeaders ; +UsePrivateHeaders drivers ; KernelAddon tty : driver.cpp diff --git a/src/add-ons/kernel/drivers/tty/driver.cpp b/src/add-ons/kernel/drivers/tty/driver.cpp index 9fb643b679..bf25eff7df 100644 --- a/src/add-ons/kernel/drivers/tty/driver.cpp +++ b/src/add-ons/kernel/drivers/tty/driver.cpp @@ -1,7 +1,7 @@ /* -** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. -** Distributed under the terms of the Haiku License. -*/ + * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the Haiku License. + */ #include @@ -27,9 +27,9 @@ static const int kMaxCachedSemaphores = 8; int32 api_version = B_CUR_DRIVER_API_VERSION; -static char *sDeviceNames[kNumTTYs * 2 + 2]; - // reserve space for "pt/" and "tt/" entries, "tty", and the terminating - // NULL +char *gDeviceNames[kNumTTYs * 2 + 3]; + // reserve space for "pt/" and "tt/" entries, "ptmx", "tty", and the + // terminating NULL struct mutex gGlobalTTYLock; struct mutex gTTYCookieLock; @@ -49,7 +49,7 @@ init_driver(void) { TRACE((DRIVER_NAME ": init_driver()\n")); - memset(sDeviceNames, 0, sizeof(sDeviceNames)); + memset(gDeviceNames, 0, sizeof(gDeviceNames)); // create the global mutex status_t error = mutex_init(&gGlobalTTYLock, "tty global"); @@ -77,16 +77,20 @@ init_driver(void) int8 digit = 0; for (uint32 i = 0; i < kNumTTYs; i++) { - // For compatibility, we have to create the same mess in /dev/pt and /dev/tt - // as BeOS does: we publish devices p0, p1, ..., pf, r1, ..., sf. - // It would be nice if we could drop compatibility and create something better. + // For compatibility, we have to create the same mess in /dev/pt and + // /dev/tt as BeOS does: we publish devices p0, p1, ..., pf, r1, ..., + // sf. It would be nice if we could drop compatibility and create + // something better. In fact we already don't need the master devices + // anymore, since "/dev/ptmx" does the job. The slaves entries could + // be published on the fly when a master is opened (e.g via + // vfs_create_special_node()). char buffer[64]; snprintf(buffer, sizeof(buffer), "pt/%c%x", letter, digit); - sDeviceNames[i] = strdup(buffer); + gDeviceNames[i] = strdup(buffer); snprintf(buffer, sizeof(buffer), "tt/%c%x", letter, digit); - sDeviceNames[i + kNumTTYs] = strdup(buffer); + gDeviceNames[i + kNumTTYs] = strdup(buffer); if (++digit > 15) digit = 0, letter++; @@ -95,13 +99,14 @@ init_driver(void) reset_tty(&gSlaveTTYs[i], i, false); reset_tty_settings(&gTTYSettings[i], i); - if (!sDeviceNames[i] || !sDeviceNames[i + kNumTTYs]) { + if (!gDeviceNames[i] || !gDeviceNames[i + kNumTTYs]) { uninit_driver(); return B_NO_MEMORY; } } - sDeviceNames[2 * kNumTTYs] = "tty"; + gDeviceNames[2 * kNumTTYs] = "ptmx"; + gDeviceNames[2 * kNumTTYs + 1] = "tty"; tty_add_debugger_commands(); @@ -117,7 +122,7 @@ uninit_driver(void) tty_remove_debugger_commands(); for (int32 i = 0; i < (int32)kNumTTYs * 2; i++) - free(sDeviceNames[i]); + free(gDeviceNames[i]); recursive_lock_destroy(&gTTYRequestLock); mutex_destroy(&gTTYCookieLock); @@ -129,7 +134,7 @@ const char ** publish_devices(void) { TRACE((DRIVER_NAME ": publish_devices()\n")); - return const_cast(sDeviceNames); + return const_cast(gDeviceNames); } @@ -138,9 +143,11 @@ find_device(const char *name) { TRACE((DRIVER_NAME ": find_device(\"%s\")\n", name)); - for (uint32 i = 0; sDeviceNames[i] != NULL; i++) - if (!strcmp(name, sDeviceNames[i])) - return i < kNumTTYs ? &gMasterTTYHooks : &gSlaveTTYHooks; + for (uint32 i = 0; gDeviceNames[i] != NULL; i++) + if (!strcmp(name, gDeviceNames[i])) { + return i < kNumTTYs || i == (2 * kNumTTYs) + ? &gMasterTTYHooks : &gSlaveTTYHooks; + } return NULL; } diff --git a/src/add-ons/kernel/drivers/tty/master.cpp b/src/add-ons/kernel/drivers/tty/master.cpp index 62acbecf25..d7b262a4e4 100644 --- a/src/add-ons/kernel/drivers/tty/master.cpp +++ b/src/add-ons/kernel/drivers/tty/master.cpp @@ -65,15 +65,27 @@ create_master_cookie(master_cookie *&cookie, struct tty *master, static status_t master_open(const char *name, uint32 flags, void **_cookie) { - int32 index = get_tty_index(name); - if (index >= (int32)kNumTTYs) - return B_ERROR; + bool findUnusedTTY = strcmp(name, "ptmx") == 0; + + int32 index = -1; + if (!findUnusedTTY) { + index = get_tty_index(name); + if (index >= (int32)kNumTTYs) + return B_ERROR; + } TRACE(("master_open: TTY index = %ld (name = %s)\n", index, name)); MutexLocker globalLocker(gGlobalTTYLock); - if (gMasterTTYs[index].open_count > 0) { + if (findUnusedTTY) { + for (index = 0; index < (int32)kNumTTYs; index++) { + if (gMasterTTYs[index].open_count == 0) + break; + } + if (index >= (int32)kNumTTYs) + return ENOENT; + } else if (gMasterTTYs[index].open_count > 0) { // we're already open! return B_BUSY; } diff --git a/src/add-ons/kernel/drivers/tty/tty.cpp b/src/add-ons/kernel/drivers/tty/tty.cpp index 9eb2a022f8..2b20ee045f 100644 --- a/src/add-ons/kernel/drivers/tty/tty.cpp +++ b/src/add-ons/kernel/drivers/tty/tty.cpp @@ -10,8 +10,11 @@ #include +#include #include +#include #include +#include #include #include @@ -19,6 +22,8 @@ #include +#include + #include "tty_private.h" @@ -765,11 +770,11 @@ reset_termios(struct termios &termios) { memset(&termios, 0, sizeof(struct termios)); - termios.c_iflag = 0; - termios.c_oflag = 0; + termios.c_iflag = ICRNL; + termios.c_oflag = OPOST | ONLCR; termios.c_cflag = B19200 | CS8 | CREAD | HUPCL; // enable receiver, hang up on last close - termios.c_lflag = 0; + termios.c_lflag = ECHO | ISIG | ICANON; // control characters termios.c_cc[VINTR] = CTRL('C'); @@ -1390,6 +1395,31 @@ tty_ioctl(tty_cookie *cookie, uint32 op, void *buffer, size_t length) return B_OK; } + + case B_IOCTL_GET_TTY_INDEX: + if (user_memcpy(buffer, &tty->index, sizeof(int32)) < B_OK) + return B_BAD_ADDRESS; + + return B_OK; + + case B_IOCTL_GRANT_TTY: + { + if (!tty->is_master) + return B_BAD_VALUE; + + // get slave path + char path[64]; + snprintf(path, sizeof(path), "/dev/%s", + gDeviceNames[kNumTTYs + tty->index]); + + // set owner and permissions respectively + if (chown(path, getuid(), getgid()) != 0 + || chmod(path, S_IRUSR | S_IWUSR | S_IWGRP) != 0) { + return errno; + } + + return B_OK; + } } TRACE(("tty: unsupported opcode %lu\n", op)); diff --git a/src/add-ons/kernel/drivers/tty/tty_private.h b/src/add-ons/kernel/drivers/tty/tty_private.h index b9d8399a5f..bfeef05883 100644 --- a/src/add-ons/kernel/drivers/tty/tty_private.h +++ b/src/add-ons/kernel/drivers/tty/tty_private.h @@ -145,6 +145,8 @@ struct tty { static const uint32 kNumTTYs = 64; +extern char *gDeviceNames[kNumTTYs * 2 + 3]; + extern tty gMasterTTYs[kNumTTYs]; extern tty gSlaveTTYs[kNumTTYs]; extern tty_settings gTTYSettings[kNumTTYs];