|
Packit Service |
50ad14 |
#include "config.h"
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
#include <fcntl.h>
|
|
Packit Service |
50ad14 |
#include <limits.h>
|
|
Packit Service |
50ad14 |
#include <stdio.h>
|
|
Packit Service |
50ad14 |
#include <stdarg.h>
|
|
Packit Service |
50ad14 |
#include <unistd.h>
|
|
Packit Service |
50ad14 |
#include <getopt.h>
|
|
Packit Service |
50ad14 |
#include <dirent.h>
|
|
Packit Service |
50ad14 |
#include <pwd.h>
|
|
Packit Service |
50ad14 |
#include <errno.h>
|
|
Packit Service |
50ad14 |
#include <sys/ioctl.h>
|
|
Packit Service |
50ad14 |
#include <sys/stat.h>
|
|
Packit Service |
50ad14 |
#include <sys/vt.h>
|
|
Packit Service |
50ad14 |
#include <sys/wait.h>
|
|
Packit Service |
50ad14 |
#include <sys/file.h>
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
#include "version.h"
|
|
Packit Service |
50ad14 |
#include "kbd_error.h"
|
|
Packit Service |
50ad14 |
#include "xmalloc.h"
|
|
Packit Service |
50ad14 |
#include "getfd.h"
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
#ifdef COMPAT_HEADERS
|
|
Packit Service |
50ad14 |
#include "compat/linux-limits.h"
|
|
Packit Service |
50ad14 |
#endif
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
// There must be a universal way to find these!
|
|
Packit Service |
50ad14 |
#define TRUE (1)
|
|
Packit Service |
50ad14 |
#define FALSE (0)
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
#ifdef ESIX_5_3_2_D
|
|
Packit Service |
50ad14 |
#define VTBASE "/dev/vt%02d"
|
|
Packit Service |
50ad14 |
#endif
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
// Where your VTs are hidden
|
|
Packit Service |
50ad14 |
#ifdef __linux__
|
|
Packit Service |
50ad14 |
#define VTNAME "/dev/tty%d"
|
|
Packit Service |
50ad14 |
#define VTNAME2 "/dev/vc/%d"
|
|
Packit Service |
50ad14 |
#endif
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
#ifndef VTNAME
|
|
Packit Service |
50ad14 |
#error vt device name must be defined
|
|
Packit Service |
50ad14 |
#endif
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
static void
|
|
Packit Service |
50ad14 |
__attribute__((noreturn))
|
|
Packit Service |
50ad14 |
print_help(int ret)
|
|
Packit Service |
50ad14 |
{
|
|
Packit Service |
50ad14 |
printf(_("Usage: %s [OPTIONS] -- command\n"
|
|
Packit Service |
50ad14 |
"\n"
|
|
Packit Service |
50ad14 |
"This utility help you to start a program on a new virtual terminal (VT).\n"
|
|
Packit Service |
50ad14 |
"\n"
|
|
Packit Service |
50ad14 |
"Options:\n"
|
|
Packit Service |
50ad14 |
" -c, --console=NUM use the given VT number;\n"
|
|
Packit Service |
50ad14 |
" -e, --exec execute the command, without forking;\n"
|
|
Packit Service |
50ad14 |
" -f, --force force opening a VT without checking;\n"
|
|
Packit Service |
50ad14 |
" -l, --login make the command a login shell;\n"
|
|
Packit Service |
50ad14 |
" -u, --user figure out the owner of the current VT;\n"
|
|
Packit Service |
50ad14 |
" -s, --switch switch to the new VT;\n"
|
|
Packit Service |
50ad14 |
" -w, --wait wait for command to complete;\n"
|
|
Packit Service |
50ad14 |
" -v, --verbose print a message for each action;\n"
|
|
Packit Service |
50ad14 |
" -V, --version print program version and exit;\n"
|
|
Packit Service |
50ad14 |
" -h, --help output a brief help message.\n"
|
|
Packit Service |
50ad14 |
"\n"),
|
|
Packit Service |
50ad14 |
progname);
|
|
Packit Service |
50ad14 |
exit(ret);
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/*
|
|
Packit Service |
50ad14 |
* Support for Spawn_Console: openvt running from init
|
|
Packit Service |
50ad14 |
* added by Joshua Spoerri, Thu Jul 18 21:13:16 EDT 1996
|
|
Packit Service |
50ad14 |
*
|
|
Packit Service |
50ad14 |
* -u Figure out the owner of the current VT, and run
|
|
Packit Service |
50ad14 |
* login as that user. Suitable to be called by init.
|
|
Packit Service |
50ad14 |
* Shouldn't be used with -c or -l.
|
|
Packit Service |
50ad14 |
* Sample inittab line:
|
|
Packit Service |
50ad14 |
* kb::kbrequest:/usr/bin/openvt -us
|
|
Packit Service |
50ad14 |
*
|
|
Packit Service |
50ad14 |
* It is the job of authenticate_user() to find out who
|
|
Packit Service |
50ad14 |
* produced this keyboard signal. It is called only as root.
|
|
Packit Service |
50ad14 |
*
|
|
Packit Service |
50ad14 |
* Note that there is a race condition: curvt may not be the vt
|
|
Packit Service |
50ad14 |
* from which the keyboard signal was produced.
|
|
Packit Service |
50ad14 |
* (Possibly the signal was not produced at the keyboard at all,
|
|
Packit Service |
50ad14 |
* but by a "kill -SIG 1". However, only root can do this.)
|
|
Packit Service |
50ad14 |
*
|
|
Packit Service |
50ad14 |
* Conclusion: do not use this in high security environments.
|
|
Packit Service |
50ad14 |
* Or fix the code below to be more suspicious.
|
|
Packit Service |
50ad14 |
*
|
|
Packit Service |
50ad14 |
* Maybe it is better to just start a login at the new vt,
|
|
Packit Service |
50ad14 |
* instead of pre-authenticating the user with "login -f".
|
|
Packit Service |
50ad14 |
*/
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
static char *
|
|
Packit Service |
50ad14 |
authenticate_user(int curvt)
|
|
Packit Service |
50ad14 |
{
|
|
Packit Service |
50ad14 |
DIR *dp;
|
|
Packit Service |
50ad14 |
struct dirent *dentp;
|
|
Packit Service |
50ad14 |
struct stat buf;
|
|
Packit Service |
50ad14 |
dev_t console_dev;
|
|
Packit Service |
50ad14 |
ino_t console_ino;
|
|
Packit Service |
50ad14 |
uid_t console_uid;
|
|
Packit Service |
50ad14 |
char filename[NAME_MAX + 12];
|
|
Packit Service |
50ad14 |
struct passwd *pwnam;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (!(dp = opendir("/proc")))
|
|
Packit Service |
50ad14 |
kbd_error(EXIT_FAILURE, errno, "opendir(/proc)");
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* get the current tty */
|
|
Packit Service |
50ad14 |
/* try /dev/ttyN, then /dev/vc/N */
|
|
Packit Service |
50ad14 |
sprintf(filename, VTNAME, curvt);
|
|
Packit Service |
50ad14 |
if (stat(filename, &buf)) {
|
|
Packit Service |
50ad14 |
int errsv = errno;
|
|
Packit Service |
50ad14 |
sprintf(filename, VTNAME2, curvt);
|
|
Packit Service |
50ad14 |
if (stat(filename, &buf)) {
|
|
Packit Service |
50ad14 |
/* give error message for first attempt */
|
|
Packit Service |
50ad14 |
sprintf(filename, VTNAME, curvt);
|
|
Packit Service |
50ad14 |
kbd_error(EXIT_FAILURE, errsv, "%s", filename);
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
console_dev = buf.st_dev;
|
|
Packit Service |
50ad14 |
console_ino = buf.st_ino;
|
|
Packit Service |
50ad14 |
console_uid = buf.st_uid;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* get the owner of current tty */
|
|
Packit Service |
50ad14 |
if (!(pwnam = getpwuid(console_uid)))
|
|
Packit Service |
50ad14 |
kbd_error(EXIT_FAILURE, errno, "getpwuid");
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* check to make sure that user has a process on that tty */
|
|
Packit Service |
50ad14 |
/* this will fail for example when X is running on the tty */
|
|
Packit Service |
50ad14 |
while ((dentp = readdir(dp))) {
|
|
Packit Service |
50ad14 |
sprintf(filename, "/proc/%s/fd/0", dentp->d_name);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (stat(filename, &buf))
|
|
Packit Service |
50ad14 |
continue;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (buf.st_dev == console_dev && buf.st_ino == console_ino && buf.st_uid == console_uid)
|
|
Packit Service |
50ad14 |
goto got_a_process;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
kbd_error(EXIT_FAILURE, 0, _("Couldn't find owner of current tty!"));
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
got_a_process:
|
|
Packit Service |
50ad14 |
closedir(dp);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
return pwnam->pw_name;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
static int
|
|
Packit Service |
50ad14 |
open_vt(char *vtname, int force)
|
|
Packit Service |
50ad14 |
{
|
|
Packit Service |
50ad14 |
int fd;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if ((fd = open(vtname, O_RDWR)) == -1)
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (ioctl(fd, TIOCSCTTY, force) == -1) {
|
|
Packit Service |
50ad14 |
close(fd);
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
return fd;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
int main(int argc, char *argv[])
|
|
Packit Service |
50ad14 |
{
|
|
Packit Service |
50ad14 |
int opt, pid, i;
|
|
Packit Service |
50ad14 |
struct vt_stat vtstat;
|
|
Packit Service |
50ad14 |
int vtno = -1;
|
|
Packit Service |
50ad14 |
int fd = -1;
|
|
Packit Service |
50ad14 |
int consfd = -1;
|
|
Packit Service |
50ad14 |
int force = 0;
|
|
Packit Service |
50ad14 |
char optc = FALSE;
|
|
Packit Service |
50ad14 |
char show = FALSE;
|
|
Packit Service |
50ad14 |
char login = FALSE;
|
|
Packit Service |
50ad14 |
char verbose = FALSE;
|
|
Packit Service |
50ad14 |
char direct_exec = FALSE;
|
|
Packit Service |
50ad14 |
char do_wait = FALSE;
|
|
Packit Service |
50ad14 |
char as_user = FALSE;
|
|
Packit Service |
50ad14 |
char vtname[sizeof(VTNAME) + 2]; /* allow 999 possible VTs */
|
|
Packit Service |
50ad14 |
char *cmd = NULL, *def_cmd = NULL, *username = NULL;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
struct option long_options[] = {
|
|
Packit Service |
50ad14 |
{ "help", no_argument, 0, 'h' },
|
|
Packit Service |
50ad14 |
{ "version", no_argument, 0, 'V' },
|
|
Packit Service |
50ad14 |
{ "verbose", no_argument, 0, 'v' },
|
|
Packit Service |
50ad14 |
{ "exec", no_argument, 0, 'e' },
|
|
Packit Service |
50ad14 |
{ "force", no_argument, 0, 'f' },
|
|
Packit Service |
50ad14 |
{ "login", no_argument, 0, 'l' },
|
|
Packit Service |
50ad14 |
{ "user", no_argument, 0, 'u' },
|
|
Packit Service |
50ad14 |
{ "switch", no_argument, 0, 's' },
|
|
Packit Service |
50ad14 |
{ "wait", no_argument, 0, 'w' },
|
|
Packit Service |
50ad14 |
{ "console", required_argument, 0, 'c' },
|
|
Packit Service |
50ad14 |
{ 0, 0, 0, 0 }
|
|
Packit Service |
50ad14 |
};
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
set_progname(argv[0]);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
setlocale(LC_ALL, "");
|
|
Packit Service |
50ad14 |
bindtextdomain(PACKAGE_NAME, LOCALEDIR);
|
|
Packit Service |
50ad14 |
textdomain(PACKAGE_NAME);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
while ((opt = getopt_long(argc, argv, "c:lsfuewhvV", long_options, NULL)) != -1) {
|
|
Packit Service |
50ad14 |
switch (opt) {
|
|
Packit Service |
50ad14 |
case 'c':
|
|
Packit Service |
50ad14 |
optc = 1; /* vtno was specified by the user */
|
|
Packit Service |
50ad14 |
vtno = (int)atol(optarg);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (vtno <= 0 || vtno > 63)
|
|
Packit Service |
50ad14 |
kbd_error(5, 0, _("%s: Illegal vt number"), optarg);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* close security holes - until we can do this safely */
|
|
Packit Service |
50ad14 |
(void)setuid(getuid());
|
|
Packit Service |
50ad14 |
break;
|
|
Packit Service |
50ad14 |
case 'l':
|
|
Packit Service |
50ad14 |
login = TRUE;
|
|
Packit Service |
50ad14 |
break;
|
|
Packit Service |
50ad14 |
case 's':
|
|
Packit Service |
50ad14 |
show = TRUE;
|
|
Packit Service |
50ad14 |
break;
|
|
Packit Service |
50ad14 |
case 'v':
|
|
Packit Service |
50ad14 |
verbose = TRUE;
|
|
Packit Service |
50ad14 |
break;
|
|
Packit Service |
50ad14 |
case 'f':
|
|
Packit Service |
50ad14 |
force = 1;
|
|
Packit Service |
50ad14 |
break;
|
|
Packit Service |
50ad14 |
case 'e':
|
|
Packit Service |
50ad14 |
direct_exec = TRUE;
|
|
Packit Service |
50ad14 |
break;
|
|
Packit Service |
50ad14 |
case 'w':
|
|
Packit Service |
50ad14 |
do_wait = TRUE;
|
|
Packit Service |
50ad14 |
break;
|
|
Packit Service |
50ad14 |
case 'u':
|
|
Packit Service |
50ad14 |
/* we'll let 'em get away with the meaningless -ul combo */
|
|
Packit Service |
50ad14 |
if (getuid())
|
|
Packit Service |
50ad14 |
kbd_error(EXIT_FAILURE, 0, _("Only root can use the -u flag."));
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
as_user = TRUE;
|
|
Packit Service |
50ad14 |
break;
|
|
Packit Service |
50ad14 |
case 'V':
|
|
Packit Service |
50ad14 |
print_version_and_exit();
|
|
Packit Service |
50ad14 |
break;
|
|
Packit Service |
50ad14 |
default:
|
|
Packit Service |
50ad14 |
case 'h':
|
|
Packit Service |
50ad14 |
print_help(EXIT_SUCCESS);
|
|
Packit Service |
50ad14 |
break;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
for (i = 0; i < 3; i++) {
|
|
Packit Service |
50ad14 |
struct stat st;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (fstat(i, &st) == -1 && open("/dev/null", O_RDWR) == -1)
|
|
Packit Service |
50ad14 |
kbd_error(EXIT_FAILURE, errno, "open(/dev/null)");
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if ((consfd = getfd(NULL)) < 0)
|
|
Packit Service |
50ad14 |
kbd_error(2, 0, _("Couldn't get a file descriptor referring to the console"));
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (ioctl(consfd, VT_GETSTATE, &vtstat) < 0)
|
|
Packit Service |
50ad14 |
kbd_error(4, errno, "ioctl(VT_GETSTATE)");
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (vtno == -1) {
|
|
Packit Service |
50ad14 |
if (ioctl(consfd, VT_OPENQRY, &vtno) < 0 || vtno == -1)
|
|
Packit Service |
50ad14 |
kbd_error(3, errno, _("Cannot find a free vt"));
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
} else if (!force) {
|
|
Packit Service |
50ad14 |
if (vtno >= 16)
|
|
Packit Service |
50ad14 |
kbd_error(7, 0, _("Cannot check whether vt %d is free; use `%s -f' to force."),
|
|
Packit Service |
50ad14 |
vtno, progname);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (vtstat.v_state & (1 << vtno))
|
|
Packit Service |
50ad14 |
kbd_error(7, 0, _("vt %d is in use; command aborted; use `%s -f' to force."),
|
|
Packit Service |
50ad14 |
vtno, progname);
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (as_user)
|
|
Packit Service |
50ad14 |
username = authenticate_user(vtstat.v_active);
|
|
Packit Service |
50ad14 |
else {
|
|
Packit Service |
50ad14 |
if (!(argc > optind)) {
|
|
Packit Service |
50ad14 |
def_cmd = getenv("SHELL");
|
|
Packit Service |
50ad14 |
if (def_cmd == NULL)
|
|
Packit Service |
50ad14 |
kbd_error(7, 0, _("Unable to find command."));
|
|
Packit Service |
50ad14 |
cmd = xmalloc(strlen(def_cmd) + 2);
|
|
Packit Service |
50ad14 |
} else {
|
|
Packit Service |
50ad14 |
cmd = xmalloc(strlen(argv[optind]) + 2);
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (login)
|
|
Packit Service |
50ad14 |
strcpy(cmd, "-");
|
|
Packit Service |
50ad14 |
else
|
|
Packit Service |
50ad14 |
cmd[0] = '\0';
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (def_cmd)
|
|
Packit Service |
50ad14 |
strcat(cmd, def_cmd);
|
|
Packit Service |
50ad14 |
else
|
|
Packit Service |
50ad14 |
strcat(cmd, argv[optind]);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (login)
|
|
Packit Service |
50ad14 |
argv[optind] = cmd++;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (direct_exec || ((pid = fork()) == 0)) {
|
|
Packit Service |
50ad14 |
/* leave current vt */
|
|
Packit Service |
50ad14 |
if (!direct_exec) {
|
|
Packit Service |
50ad14 |
#ifdef ESIX_5_3_2_D
|
|
Packit Service |
50ad14 |
#ifdef HAVE_SETPGRP
|
|
Packit Service |
50ad14 |
if (setpgrp() < 0)
|
|
Packit Service |
50ad14 |
#else
|
|
Packit Service |
50ad14 |
if (1)
|
|
Packit Service |
50ad14 |
#endif /* HAVE_SETPGRP */
|
|
Packit Service |
50ad14 |
#else
|
|
Packit Service |
50ad14 |
if (setsid() < 0)
|
|
Packit Service |
50ad14 |
#endif /* ESIX_5_3_2_D */
|
|
Packit Service |
50ad14 |
kbd_error(5, errno, _("Unable to set new session"));
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
sprintf(vtname, VTNAME, vtno);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* Can we open the vt we want? */
|
|
Packit Service |
50ad14 |
if ((fd = open_vt(vtname, force)) == -1) {
|
|
Packit Service |
50ad14 |
int errsv = errno;
|
|
Packit Service |
50ad14 |
if (!optc) {
|
|
Packit Service |
50ad14 |
/* We found vtno ourselves - it is free according
|
|
Packit Service |
50ad14 |
to the kernel, but we cannot open it. Maybe X
|
|
Packit Service |
50ad14 |
used it and did a chown. Try a few vt's more
|
|
Packit Service |
50ad14 |
before giving up. Note: the 16 is a kernel limitation. */
|
|
Packit Service |
50ad14 |
for (i = vtno + 1; i < 16; i++) {
|
|
Packit Service |
50ad14 |
if ((vtstat.v_state & (1 << i)) == 0) {
|
|
Packit Service |
50ad14 |
sprintf(vtname, VTNAME, i);
|
|
Packit Service |
50ad14 |
if ((fd = open_vt(vtname, force)) >= 0) {
|
|
Packit Service |
50ad14 |
vtno = i;
|
|
Packit Service |
50ad14 |
goto got_vtno;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
sprintf(vtname, VTNAME, vtno);
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
kbd_error(5, errsv, _("Unable to open %s"), vtname);
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
got_vtno:
|
|
Packit Service |
50ad14 |
if (verbose)
|
|
Packit Service |
50ad14 |
kbd_warning(0, _("Using VT %s"), vtname);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* Maybe we are suid root, and the -c option was given.
|
|
Packit Service |
50ad14 |
Check that the real user can access this VT.
|
|
Packit Service |
50ad14 |
We assume getty has made any in use VT non accessable */
|
|
Packit Service |
50ad14 |
if (access(vtname, R_OK | W_OK) < 0)
|
|
Packit Service |
50ad14 |
kbd_error(5, errno, _("Cannot open %s read/write"), vtname);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (!as_user && !geteuid()) {
|
|
Packit Service |
50ad14 |
uid_t uid = getuid();
|
|
Packit Service |
50ad14 |
if (chown(vtname, uid, getgid()) == -1)
|
|
Packit Service |
50ad14 |
kbd_error(5, errno, "chown");
|
|
Packit Service |
50ad14 |
setuid(uid);
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (show) {
|
|
Packit Service |
50ad14 |
if (ioctl(fd, VT_ACTIVATE, vtno))
|
|
Packit Service |
50ad14 |
kbd_error(1, errno, _("Couldn't activate vt %d"), vtno);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (ioctl(fd, VT_WAITACTIVE, vtno))
|
|
Packit Service |
50ad14 |
kbd_error(1, errno, _("Activation interrupted?"));
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
close(0);
|
|
Packit Service |
50ad14 |
close(1);
|
|
Packit Service |
50ad14 |
close(2);
|
|
Packit Service |
50ad14 |
close(consfd);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if ((dup2(fd, 0) == -1) || (dup2(fd, 1) == -1) || (dup2(fd, 2) == -1))
|
|
Packit Service |
50ad14 |
kbd_error(1, errno, "dup");
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* slight problem: after "openvt -su" has finished, the
|
|
Packit Service |
50ad14 |
utmp entry is not removed */
|
|
Packit Service |
50ad14 |
if (as_user)
|
|
Packit Service |
50ad14 |
execlp("login", "login", "-f", username, NULL);
|
|
Packit Service |
50ad14 |
else if (def_cmd)
|
|
Packit Service |
50ad14 |
execlp(cmd, def_cmd, NULL);
|
|
Packit Service |
50ad14 |
else
|
|
Packit Service |
50ad14 |
execvp(cmd, &argv[optind]);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
kbd_error(127, errno, "exec");
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (pid < 0)
|
|
Packit Service |
50ad14 |
kbd_error(6, errno, "fork");
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (do_wait) {
|
|
Packit Service |
50ad14 |
int retval = 0; /* actual value returned form process */
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
wait(NULL);
|
|
Packit Service |
50ad14 |
waitpid(pid, &retval, 0);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (show) { /* Switch back... */
|
|
Packit Service |
50ad14 |
if (ioctl(consfd, VT_ACTIVATE, vtstat.v_active))
|
|
Packit Service |
50ad14 |
kbd_error(8, errno, "ioctl(VT_ACTIVATE)");
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* wait to be really sure we have switched */
|
|
Packit Service |
50ad14 |
if (ioctl(consfd, VT_WAITACTIVE, vtstat.v_active))
|
|
Packit Service |
50ad14 |
kbd_error(8, errno, "ioctl(VT_WAITACTIVE)");
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (ioctl(consfd, VT_DISALLOCATE, vtno))
|
|
Packit Service |
50ad14 |
kbd_error(8, 0, _("Couldn't deallocate console %d"), vtno);
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* if all our stuff went right, we want to return the exit code of the command we ran
|
|
Packit Service |
50ad14 |
super vital for scripting loops etc */
|
|
Packit Service |
50ad14 |
return (retval);
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
return EXIT_SUCCESS;
|
|
Packit Service |
50ad14 |
}
|