kernel, libc: tty names

This commit is contained in:
K. Lange 2018-10-09 19:56:45 +09:00
parent b2771a3dde
commit 11772506bb
4 changed files with 153 additions and 8 deletions

18
apps/tty.c Normal file
View File

@ -0,0 +1,18 @@
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* This file is part of ToaruOS and is released under the terms
* of the NCSA / University of Illinois License - see LICENSE.md
* Copyright (C) 2018 K. Lange
*
* tty - print terminal name
*/
#include <stdio.h>
#include <unistd.h>
int main(int argc, char * argv[]) {
if (!isatty(STDIN_FILENO)) {
fprintf(stdout, "not a tty\n");
return 1;
}
fprintf(stdout,"%s\n",ttyname(STDIN_FILENO));
return 0;
}

View File

@ -8,5 +8,7 @@
#define IOCTL_DTYPE_FILE 1
#define IOCTL_DTYPE_TTY 2
#define IOCTLTTYNAME 0x4F01
#define IOCTL_PACKETFS_QUEUED 0x5050

View File

@ -9,6 +9,7 @@
#include <kernel/logging.h>
#include <kernel/printf.h>
#include <kernel/ringbuffer.h>
#include <toaru/hashmap.h>
#include <sys/ioctl.h>
#include <sys/termios.h>
@ -43,7 +44,9 @@ typedef struct pty {
} pty_t;
list_t * pty_list = NULL;
static int _pty_counter = 0;
static hashmap_t * _pty_index = NULL;
static fs_node_t * _pty_dir = NULL;
#define IN(character) ring_buffer_write(pty->in, 1, (uint8_t *)&(character))
#define OUT(character) ring_buffer_write(pty->out, 1, (uint8_t *)&(character))
@ -209,6 +212,12 @@ int pty_ioctl(pty_t * pty, int request, void * argp) {
* but for here we just need to say we're a TTY.
*/
return IOCTL_DTYPE_TTY;
case IOCTLTTYNAME:
if (!argp) return -1;
validate(argp);
((char*)argp)[0] = '\0';
sprintf((char*)argp, "/dev/pts/%d", pty->name);
return 0;
case TIOCSWINSZ:
if (!argp) return -1;
validate(argp);
@ -303,6 +312,10 @@ void open_pty_slave(fs_node_t * node, unsigned int flags) {
return;
}
void close_pty_slave(fs_node_t * node) {
pty_t * pty = (pty_t *)node->device;
hashmap_remove(_pty_index, (void*)pty->name);
return;
}
@ -364,7 +377,7 @@ fs_node_t * pty_master_create(pty_t * pty) {
fnode->name[0] = '\0';
sprintf(fnode->name, "pty master");
fnode->uid = 0;
fnode->uid = current_process->user;
fnode->gid = 0;
fnode->mask = 0666;
fnode->flags = FS_PIPE;
@ -378,6 +391,9 @@ fs_node_t * pty_master_create(pty_t * pty) {
fnode->finddir = NULL;
fnode->ioctl = ioctl_pty_master;
fnode->get_size = pty_available_output;
fnode->ctime = now();
fnode->mtime = now();
fnode->atime = now();
fnode->device = pty;
@ -390,7 +406,7 @@ fs_node_t * pty_slave_create(pty_t * pty) {
fnode->name[0] = '\0';
sprintf(fnode->name, "pty slave");
fnode->uid = 0;
fnode->uid = current_process->user;
fnode->gid = 0;
fnode->mask = 0666;
fnode->flags = FS_PIPE;
@ -404,17 +420,114 @@ fs_node_t * pty_slave_create(pty_t * pty) {
fnode->finddir = NULL;
fnode->ioctl = ioctl_pty_slave;
fnode->get_size = pty_available_input;
fnode->ctime = now();
fnode->mtime = now();
fnode->atime = now();
fnode->device = pty;
return fnode;
}
static struct dirent * readdir_pty(fs_node_t *node, uint32_t index) {
if (index == 0) {
struct dirent * out = malloc(sizeof(struct dirent));
memset(out, 0x00, sizeof(struct dirent));
out->ino = 0;
strcpy(out->name, ".");
return out;
}
if (index == 1) {
struct dirent * out = malloc(sizeof(struct dirent));
memset(out, 0x00, sizeof(struct dirent));
out->ino = 0;
strcpy(out->name, "..");
return out;
}
index -= 2;
pty_t * out_pty = NULL;
list_t * values = hashmap_values(_pty_index);
foreach(node, values) {
if (index == 0) {
out_pty = node->value;
break;
}
index--;
}
list_free(values);
if (out_pty) {
struct dirent * out = malloc(sizeof(struct dirent));
memset(out, 0x00, sizeof(struct dirent));
out->ino = out_pty->name;
out->name[0] = '\0';
sprintf(out->name, "%d", out_pty->name);
return out;
} else {
return NULL;
}
}
static fs_node_t * finddir_pty(fs_node_t * node, char * name) {
if (!name) return NULL;
if (strlen(name) < 1) return NULL;
int c = 0;
for (int i = 0; name[i]; ++i) {
if (name[i] < '0' || name[i] > '9') {
return NULL;
}
c = c * 10 + name[i] - '0';
}
pty_t * _pty = hashmap_get(_pty_index, (void*)c);
if (!_pty) {
debug_print(ERROR, "Invalid PTY number: %d\n", c);
return NULL;
}
return _pty->slave;
}
static fs_node_t * create_pty_dir(void) {
fs_node_t * fnode = malloc(sizeof(fs_node_t));
memset(fnode, 0x00, sizeof(fs_node_t));
fnode->inode = 0;
strcpy(fnode->name, "pty");
fnode->mask = 0555;
fnode->uid = 0;
fnode->gid = 0;
fnode->flags = FS_DIRECTORY;
fnode->read = NULL;
fnode->write = NULL;
fnode->open = NULL;
fnode->close = NULL;
fnode->readdir = readdir_pty;
fnode->finddir = finddir_pty;
fnode->nlink = 1;
fnode->ctime = now();
fnode->mtime = now();
fnode->atime = now();
return fnode;
}
void pty_install(void) {
pty_list = list_create();
_pty_index = hashmap_create_int(10);
_pty_dir = create_pty_dir();
vfs_mount("/dev/pts", _pty_dir);
}
pty_t * pty_new(struct winsize * size) {
if (!_pty_index) {
pty_install();
}
pty_t * pty = malloc(sizeof(pty_t));
/* stdin linkage; characters from terminal → PTY slave */
@ -429,8 +542,10 @@ pty_t * pty_new(struct winsize * size) {
/* Slave endpoint, reads come from stdin, writes go to stdout */
pty->slave = pty_slave_create(pty);
/* TODO PTY name */
pty->name = 0;
/* tty name */
pty->name = _pty_counter++;
hashmap_set(_pty_index, (void*)pty->name, pty);
if (size) {
memcpy(&pty->size, size, sizeof(struct winsize));

View File

@ -1,7 +1,17 @@
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
static char _tty_name[30]; /* only needs to hold /dev/pty/ttyXXXXXXX */
char * ttyname(int fd) {
errno = ENOTSUP;
if (!isatty(fd)) {
errno = ENOTTY;
return NULL;
}
ioctl(fd, IOCTLTTYNAME, _tty_name);
return _tty_name;
}