diff --git a/apps/login.c b/apps/login.c index 77502754..0c40c785 100644 --- a/apps/login.c +++ b/apps/login.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -142,6 +143,7 @@ do_fork: pid = getpid(); f = fork(); if (getpid() != pid) { + ioctl(STDIN_FILENO, IOCTLTTYLOGIN, &uid); setuid(uid); toaru_auth_set_vars(); char * args[] = { diff --git a/apps/logname.c b/apps/logname.c new file mode 100644 index 00000000..a99bdfc4 --- /dev/null +++ b/apps/logname.c @@ -0,0 +1,22 @@ +/* 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 + * + * logname - Effectively the same as whoami, but for compliance + * with POSIX, this uses getlogin(). + */ +#include +#include + +int main(int argc, char ** argv) { + char * name = getlogin(); + if (!name) { + fprintf(stderr, "%s: failed to determine login name\n", argv[0]); + return 1; + } + + fprintf(stdout, "%s\n", name); + return 0; +} + diff --git a/base/usr/include/pwd.h b/base/usr/include/pwd.h index 7f534ec5..c3c8de7b 100644 --- a/base/usr/include/pwd.h +++ b/base/usr/include/pwd.h @@ -1,5 +1,6 @@ #pragma once +#include #include struct passwd { diff --git a/base/usr/include/sys/ioctl.h b/base/usr/include/sys/ioctl.h index 8d5accf7..e2fa149e 100644 --- a/base/usr/include/sys/ioctl.h +++ b/base/usr/include/sys/ioctl.h @@ -8,7 +8,8 @@ #define IOCTL_DTYPE_FILE 1 #define IOCTL_DTYPE_TTY 2 -#define IOCTLTTYNAME 0x4F01 +#define IOCTLTTYNAME 0x4F01 +#define IOCTLTTYLOGIN 0x4F02 #define IOCTL_PACKETFS_QUEUED 0x5050 diff --git a/base/usr/include/unistd.h b/base/usr/include/unistd.h index c842a5f7..1a016c7b 100644 --- a/base/usr/include/unistd.h +++ b/base/usr/include/unistd.h @@ -67,6 +67,7 @@ extern char * ttyname(int fd); extern int utime(const char *filename, const struct utimbuf *times); extern int rmdir(const char *pathname); /* TODO rm probably just works */ extern int chown(const char * pathname, uid_t owner, gid_t group); +extern char * getlogin(void); #define STDIN_FILENO 0 #define STDOUT_FILENO 1 diff --git a/kernel/fs/tty.c b/kernel/fs/tty.c index a6110a93..9ed5c45b 100644 --- a/kernel/fs/tty.c +++ b/kernel/fs/tty.c @@ -198,42 +198,50 @@ int pty_ioctl(pty_t * pty, int request, void * argp) { */ return IOCTL_DTYPE_TTY; case IOCTLTTYNAME: - if (!argp) return -1; + if (!argp) return -EINVAL; validate(argp); ((char*)argp)[0] = '\0'; sprintf((char*)argp, "/dev/pts/%d", pty->name); return 0; + case IOCTLTTYLOGIN: + /* Set the user id of the login user */ + if (current_process->user != 0) return -EPERM; + if (!argp) return -EINVAL; + validate(argp); + pty->slave->uid = *(int*)argp; + pty->master->uid = *(int*)argp; + return 0; case TIOCSWINSZ: - if (!argp) return -1; + if (!argp) return -EINVAL; validate(argp); memcpy(&pty->size, argp, sizeof(struct winsize)); /* TODO send sigwinch to fg_prog */ return 0; case TIOCGWINSZ: - if (!argp) return -1; + if (!argp) return -EINVAL; validate(argp); memcpy(argp, &pty->size, sizeof(struct winsize)); return 0; case TCGETS: - if (!argp) return -1; + if (!argp) return -EINVAL; validate(argp); memcpy(argp, &pty->tios, sizeof(struct termios)); return 0; case TIOCSPGRP: - if (!argp) return -1; + if (!argp) return -EINVAL; validate(argp); pty->fg_proc = *(pid_t *)argp; debug_print(NOTICE, "Setting PTY group to %d", pty->fg_proc); return 0; case TIOCGPGRP: - if (!argp) return -1; + if (!argp) return -EINVAL; validate(argp); *(pid_t *)argp = pty->fg_proc; return 0; case TCSETS: case TCSETSW: case TCSETSF: - if (!argp) return -1; + if (!argp) return -EINVAL; validate(argp); if (!(((struct termios *)argp)->c_lflag & ICANON) && (pty->tios.c_lflag & ICANON)) { /* Switch out of canonical mode, the dump the input buffer */ diff --git a/libc/unistd/getlogin.c b/libc/unistd/getlogin.c new file mode 100644 index 00000000..98cf37bf --- /dev/null +++ b/libc/unistd/getlogin.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include + +static char _name[64]; /* NAME_MAX ? */ + +char * getlogin(void) { + + int tty = STDIN_FILENO; + if (!isatty(tty)) { + tty = STDOUT_FILENO; + if (!isatty(tty)) { + tty = STDERR_FILENO; + if (!isatty(tty)) { + errno = ENOTTY; + return NULL; + } + } + } + + /* Get the owner */ + struct stat statbuf; + fstat(tty, &statbuf); + + struct passwd * passwd = getpwuid(statbuf.st_uid); + + if (!passwd) return NULL; + if (!passwd->pw_name) return NULL; + + memcpy(_name, passwd->pw_name, strlen(passwd->pw_name)); + return _name; +}