| Hi,
I have the same problem and it can be partially solved by using
a small program modified from xconsole. I named it vtcons which
is essentially an xconsole but output is directed to stdout.
Attached is the source. Simply compiled it by
# cc -O -o vtcons vtcons.c
The vtcons need to be owned by root with setuid, i.e. you need to
change mode to 4755.
But it raise another problem for me because I am using a DEC7000 and
once I use vtcons to trap all the console message, I cannot login from
the console (or strictly speaking, I can login from the console but
output will be redirected to the vtcons's stdout). This is exactly
the same behaviour as using dxconsole or xconsole for the DEC7000.
May be I need to make the stdin for vtcons as the stdin for the
console? Any other good idea to solve it?
Regards,
Joseph
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#ifndef _POSIX_SOURCE
#define _POSIX_SOURCE
#include <stdio.h>
#undef _POSIX_SOURCE
#else
#include <stdio.h>
#endif
#include <ctype.h>
/* Fix ISC brain damage. When using gcc fdopen isn't declared in <stdio.h>. */
#if defined(SYSV) && defined(SYSV386) && defined(__STDC__) && defined(ISC)
extern FILE *fdopen(int, char const *);
#endif
static FILE *input;
static int prcharonly = 0;
#ifdef ultrix
#define USE_FILE
#define FILE_NAME "/dev/xcons"
#endif
#ifndef USE_FILE
#include <sys/ioctl.h>
#ifdef hpux
#include <termios.h>
#endif
#ifdef SVR4
#include <termios.h>
#include <sys/stropts.h> /* for I_PUSH */
#ifdef sun
#include <sys/strredir.h>
#endif
#endif
#if defined(TIOCCONS) || defined(SRIOCSREDIR)
#define USE_PTY
static int tty_fd, pty_fd;
static char ttydev[64], ptydev[64];
#endif
#endif
#if defined(SVR4) || (defined(SYSV) && defined(SYSV386))
#define USE_OSM
#include <signal.h>
FILE *osm_pipe();
static int child_pid;
#endif
static void inputReady ();
static
OpenConsole ()
{
struct stat sbuf;
input = 0;
/* must be owner and have read/write permission */
if (!stat("/dev/console", &sbuf) &&
(sbuf.st_uid == getuid()) &&
!access("/dev/console", R_OK|W_OK))
{
#ifdef USE_FILE
input = fopen (FILE_NAME, "r");
#endif
#ifdef USE_PTY
if (get_pty (&pty_fd, &tty_fd, ttydev, ptydev) == 0)
{
#ifdef TIOCCONS
int on = 1;
if (ioctl (tty_fd, TIOCCONS, (char *) &on) != -1)
input = fdopen (pty_fd, "r");
#else
int consfd = open("/dev/console", O_RDONLY);
if (consfd >= 0)
{
if (ioctl(consfd, SRIOCSREDIR, tty_fd) != -1)
input = fdopen (pty_fd, "r");
close(consfd);
}
#endif
}
#endif
}
#ifdef USE_OSM
/* Don't have to be owner of /dev/console when using /dev/osm. */
if (!input)
input = osm_pipe();
#endif
}
static
CloseConsole ()
{
if (input) {
fclose (input);
}
#ifdef USE_PTY
close (tty_fd);
#endif
}
#ifdef USE_OSM
static void
KillChild(sig)
int sig;
{
if (child_pid > 0)
kill(child_pid, SIGTERM);
exit(0);
}
#endif
/*ARGSUSED*/
static void
Quit ()
{
#ifdef USE_OSM
if (child_pid > 0)
kill(child_pid, SIGTERM);
#endif
exit (0);
}
static void
stripNonprint (b)
char *b;
{
char *c;
c = b;
while (*b)
{
if (isprint (*b) || isspace (*b) && *b != '\r')
{
if (c != b)
*c = *b;
++c;
}
++b;
}
*c = '\0';
}
static void
inputReady ()
{
char buffer[1025];
int n;
n = read (fileno(input), buffer, sizeof (buffer) - 1);
if (n <= 0)
{
CloseConsole();
Quit();
}
buffer[n] = '\0';
if (prcharonly)
{
stripNonprint (buffer);
n = strlen (buffer);
}
printf("%s", buffer);
}
main ()
{
OpenConsole ();
if (input)
do {
inputReady ();
} while (1);
}
#ifdef USE_PTY
/* This function opens up a pty master and stuffs it's value into pty.
* If it finds one, it returns a value of 0. If it does not find one,
* it returns a value of !0. This routine is designed to be re-entrant,
* so that if a pty master is found and later, we find that the slave
* has problems, we can re-enter this function and get another one.
*/
/*
** allow for mobility of the pty master/slave directories
*/
#ifndef PTYDEV
#ifdef hpux
#define PTYDEV "/dev/ptym/ptyxx"
#else /* !hpux */
#define PTYDEV "/dev/ptyxx"
#endif /* !hpux */
#endif /* !PTYDEV */
#ifndef TTYDEV
#ifdef hpux
#define TTYDEV "/dev/pty/ttyxx"
#else /* !hpux */
#define TTYDEV "/dev/ttyxx"
#endif /* !hpux */
#endif /* !TTYDEV */
#ifndef PTYCHAR1
#ifdef hpux
#define PTYCHAR1 "zyxwvutsrqp"
#else /* !hpux */
#define PTYCHAR1 "pqrstuvwxyzPQRSTUVWXYZ"
#endif /* !hpux */
#endif /* !PTYCHAR1 */
#ifndef PTYCHAR2
#ifdef hpux
#define PTYCHAR2 "fedcba9876543210"
#else /* !hpux */
#define PTYCHAR2 "0123456789abcdef"
#endif /* !hpux */
#endif /* !PTYCHAR2 */
get_pty (pty, tty, ttydev, ptydev)
int *pty, *tty;
char *ttydev, *ptydev;
{
#ifdef SVR4
if ((*pty = open ("/dev/ptmx", O_RDWR)) < 0) {
return 1;
}
grantpt(*pty);
unlockpt(*pty);
strcpy(ttydev, (char *)ptsname(*pty));
if ((*tty = open(ttydev, O_RDWR)) >= 0) {
(void)ioctl(*tty, I_PUSH, "ttcompat");
return 0;
}
if (*pty >= 0)
close (*pty);
#else /* !SVR4, need lots of code */
#ifdef USE_GET_PSEUDOTTY
if ((*pty = getpseudotty (&ttydev, &ptydev)) >= 0 &&
(*tty = open (ttydev, O_RDWR)) >= 0)
return 0;
if (*pty >= 0)
close (*pty);
#else
static int devindex, letter = 0;
#if defined(umips) && defined (SYSTYPE_SYSV)
struct stat fstat_buf;
*pty = open ("/dev/ptc", O_RDWR);
if (*pty < 0 || (fstat (*pty, &fstat_buf)) < 0) {
return(1);
}
sprintf (ttydev, "/dev/ttyq%d", minor(fstat_buf.st_rdev));
sprintf (ptydev, "/dev/ptyq%d", minor(fstat_buf.st_rdev));
if ((*tty = open (ttydev, O_RDWR)) >= 0) {
/* got one! */
return(0);
}
close (*pty);
#else /* not (umips && SYSTYPE_SYSV) */
#ifdef CRAY
for (; devindex < 256; devindex++) {
sprintf (ttydev, "/dev/ttyp%03d", devindex);
sprintf (ptydev, "/dev/pty/%03d", devindex);
if ((*pty = open (ptydev, O_RDWR)) >= 0 &&
(*tty = open (ttydev, O_RDWR)) >= 0)
{
/* We need to set things up for our next entry
* into this function!
*/
(void) devindex++;
return(0);
}
if (*pty >= 0)
close (*pty);
}
#else /* !CRAY */
#ifdef sgi
{
char *slave;
slave = _getpty (pty, O_RDWR, 0622, 0);
if ((*tty = open (slave, O_RDWR)) != -1)
return 0;
}
#else
strcpy (ttydev, "/dev/ttyxx");
strcpy (ptydev, "/dev/ptyxx");
while (PTYCHAR1[letter]) {
ttydev [strlen(ttydev) - 2] = ptydev [strlen(ptydev) - 2] =
PTYCHAR1 [letter];
while (PTYCHAR2[devindex]) {
ttydev [strlen(ttydev) - 1] = ptydev [strlen(ptydev) - 1] =
PTYCHAR2 [devindex];
if ((*pty = open (ptydev, O_RDWR)) >= 0 &&
(*tty = open (ttydev, O_RDWR)) >= 0)
{
/* We need to set things up for our next entry
* into this function!
*/
(void) devindex++;
return(0);
}
if (*pty >= 0)
close (*pty);
devindex++;
}
devindex = 0;
(void) letter++;
}
#endif /* sgi else not sgi */
#endif /* CRAY else not CRAY */
#endif /* umips && SYSTYPE_SYSV */
#endif /* USE_GET_PSEUDOTTY */
#endif /* SVR4 */
/* We were unable to allocate a pty master! Return an error
* condition and let our caller terminate cleanly.
*/
return(1);
}
#endif
#ifdef USE_OSM
/*
* On SYSV386 there is a special device, /dev/osm, where system messages
* are sent. Problem is that we can't perform a select(2) on this device.
* So this routine creates a streams-pty where one end reads the device and
* sends the output to xconsole.
*/
FILE *
osm_pipe()
{
int tty;
char ttydev[64];
if (access("/dev/osm", R_OK) < 0) return NULL;
if ((tty = open("/dev/ptmx", O_RDWR)) < 0) return NULL;
grantpt(tty);
unlockpt(tty);
strcpy(ttydev, (char *)ptsname(tty));
if ((child_pid = fork()) == 0) {
int pty, osm, nbytes, skip;
char cbuf[128];
skip = 0;
osm = open("/dev/osm1", O_RDONLY);
if (osm >= 0) {
while ((nbytes = read(osm, cbuf, sizeof(cbuf))) > 0)
skip += nbytes;
close(osm);
}
pty = open(ttydev, O_RDWR);
if (pty < 0) exit(1);
osm = open("/dev/osm", O_RDONLY);
if (osm < 0) exit(1);
for (nbytes = 0; skip > 0 && nbytes >= 0; skip -= nbytes) {
nbytes = skip;
if (nbytes > sizeof(cbuf))
nbytes = sizeof(cbuf);
nbytes = read(osm, cbuf, nbytes);
}
while ((nbytes = read(osm, cbuf, sizeof(cbuf))) >= 0)
write(pty, cbuf, nbytes);
exit(0);
}
signal(SIGHUP, KillChild);
signal(SIGINT, KillChild);
signal(SIGTERM, KillChild);
return fdopen(tty, "r");
}
#endif /* USE_OSM */
|
|
Didn't get vtcons to print on stdout when used together with rsh .
Added fflush(stdout) which seems to do the trick. And some other
things
-------------------cut here--------------------------------------
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#ifndef _POSIX_SOURCE
#define _POSIX_SOURCE
#include <stdio.h>
#undef _POSIX_SOURCE
#else
#include <stdio.h>
#endif
#include <ctype.h>
/* Fix ISC brain damage. When using gcc fdopen isn't declared in <stdio.h>. */
#if defined(SYSV) && defined(SYSV386) && defined(__STDC__) && defined(ISC)
extern FILE *fdopen(int, char const *);
#endif
static FILE *input;
static int prcharonly = 0;
#ifdef ultrix
#define USE_FILE
#define FILE_NAME "/dev/xcons"
#endif
#ifndef USE_FILE
#include <sys/ioctl.h>
#ifdef hpux
#include <termios.h>
#endif
#ifdef SVR4
#include <termios.h>
#include <sys/stropts.h> /* for I_PUSH */
#ifdef sun
#include <sys/strredir.h>
#endif
#endif
#if defined(TIOCCONS) || defined(SRIOCSREDIR)
#define USE_PTY
static int tty_fd, pty_fd;
static char ttydev[64], ptydev[64];
#endif
#endif
#if defined(SVR4) || (defined(SYSV) && defined(SYSV386))
#define USE_OSM
#include <signal.h>
FILE *osm_pipe();
static int child_pid;
#endif
static void inputReady ();
static void quit_signalled ( int );
static
OpenConsole ()
{
struct stat sbuf;
input = 0;
/* must be owner and have read/write permission */
if (!stat("/dev/console", &sbuf) &&
(sbuf.st_uid == getuid()) &&
!access("/dev/console", R_OK|W_OK))
{
#ifdef USE_FILE
input = fopen (FILE_NAME, "r");
#endif
#ifdef USE_PTY
if (get_pty (&pty_fd, &tty_fd, ttydev, ptydev) == 0)
{
#ifdef TIOCCONS
int on = 1;
if (ioctl (tty_fd, TIOCCONS, &on) != -1)
input = fdopen (pty_fd, "r");
else
perror("ioctl error: ");
#else
int consfd = open("/dev/console", O_RDONLY);
if (consfd >= 0)
{
if (ioctl(consfd, SRIOCSREDIR, tty_fd) != -1)
input = fdopen (pty_fd, "r");
else
perror("ioctl error: ");
close(consfd);
}
#endif
}
#endif
}
#ifdef USE_OSM
/* Don't have to be owner of /dev/console when using /dev/osm. */
if (!input)
input = osm_pipe();
#endif
}
static
CloseConsole ()
{
if (input) {
fclose (input);
}
#ifdef USE_PTY
close (tty_fd);
#endif
}
#ifdef USE_OSM
static void
KillChild(sig)
int sig;
{
if (child_pid > 0)
kill(child_pid, SIGTERM);
exit(0);
}
#endif
/*ARGSUSED*/
static void
Quit ()
{
#ifdef USE_OSM
if (child_pid > 0)
kill(child_pid, SIGTERM);
#endif
exit (0);
}
static void
stripNonprint (b)
char *b;
{
char *c;
c = b;
while (*b)
{
if (isprint (*b) || isspace (*b) && *b != '\r')
{
if (c != b)
*c = *b;
++c;
}
++b;
}
*c = '\0';
}
static void
inputReady ()
{
char buffer[1025];
int n;
n = read (fileno(input), buffer, sizeof (buffer) - 1);
if (n <= 0)
{
CloseConsole();
Quit();
}
buffer[n] = '\0';
if (prcharonly)
{
stripNonprint (buffer);
n = strlen (buffer);
}
printf("%s", buffer);
fflush(stdout);
}
main ()
{
/*
* catch interrupt, hangup, and quit so we can unlock the front panel
*/
(void) signal(SIGINT, quit_signalled);
(void) signal(SIGHUP, quit_signalled);
(void) signal(SIGQUIT, quit_signalled);
(void) signal(SIGABRT, quit_signalled);
(void) signal(SIGKILL, quit_signalled);
(void) signal(SIGTERM, quit_signalled);
OpenConsole ();
if (input)
do {
inputReady ();
} while (1);
}
/************************************************************************
*
* quit_signalled()... bye!
*
************************************************************************/
static void quit_signalled(int sig)
{
int on=0;
ioctl (0, TIOCCONS, &on);
printf("Exiting....\n");
exit(0);
}
#ifdef USE_PTY
/* This function opens up a pty master and stuffs it's value into pty.
* If it finds one, it returns a value of 0. If it does not find one,
* it returns a value of !0. This routine is designed to be re-entrant,
* so that if a pty master is found and later, we find that the slave
* has problems, we can re-enter this function and get another one.
*/
/*
** allow for mobility of the pty master/slave directories
*/
#ifndef PTYDEV
#ifdef hpux
#define PTYDEV "/dev/ptym/ptyxx"
#else /* !hpux */
#define PTYDEV "/dev/ptyxx"
#endif /* !hpux */
#endif /* !PTYDEV */
#ifndef TTYDEV
#ifdef hpux
#define TTYDEV "/dev/pty/ttyxx"
#else /* !hpux */
#define TTYDEV "/dev/ttyxx"
#endif /* !hpux */
#endif /* !TTYDEV */
#ifndef PTYCHAR1
#ifdef hpux
#define PTYCHAR1 "zyxwvutsrqp"
#else /* !hpux */
#define PTYCHAR1 "pqrstuvwxyzPQRSTUVWXYZ"
#endif /* !hpux */
#endif /* !PTYCHAR1 */
#ifndef PTYCHAR2
#ifdef hpux
#define PTYCHAR2 "fedcba9876543210"
#else /* !hpux */
#define PTYCHAR2 "0123456789abcdef"
#endif /* !hpux */
#endif /* !PTYCHAR2 */
get_pty (pty, tty, ttydev, ptydev)
int *pty, *tty;
char *ttydev, *ptydev;
{
#ifdef SVR4
if ((*pty = open ("/dev/ptmx", O_RDWR)) < 0) {
return 1;
}
grantpt(*pty);
unlockpt(*pty);
strcpy(ttydev, (char *)ptsname(*pty));
if ((*tty = open(ttydev, O_RDWR)) >= 0) {
(void)ioctl(*tty, I_PUSH, "ttcompat");
return 0;
}
if (*pty >= 0)
close (*pty);
#else /* !SVR4, need lots of code */
#ifdef USE_GET_PSEUDOTTY
if ((*pty = getpseudotty (&ttydev, &ptydev)) >= 0 &&
(*tty = open (ttydev, O_RDWR)) >= 0)
return 0;
if (*pty >= 0)
close (*pty);
#else
static int devindex, letter = 0;
#if defined(umips) && defined (SYSTYPE_SYSV)
struct stat fstat_buf;
*pty = open ("/dev/ptc", O_RDWR);
if (*pty < 0 || (fstat (*pty, &fstat_buf)) < 0) {
return(1);
}
sprintf (ttydev, "/dev/ttyq%d", minor(fstat_buf.st_rdev));
sprintf (ptydev, "/dev/ptyq%d", minor(fstat_buf.st_rdev));
if ((*tty = open (ttydev, O_RDWR)) >= 0) {
/* got one! */
return(0);
}
close (*pty);
#else /* not (umips && SYSTYPE_SYSV) */
#ifdef CRAY
for (; devindex < 256; devindex++) {
sprintf (ttydev, "/dev/ttyp%03d", devindex);
sprintf (ptydev, "/dev/pty/%03d", devindex);
if ((*pty = open (ptydev, O_RDWR)) >= 0 &&
(*tty = open (ttydev, O_RDWR)) >= 0)
{
/* We need to set things up for our next entry
* into this function!
*/
(void) devindex++;
return(0);
}
if (*pty >= 0)
close (*pty);
}
#else /* !CRAY */
#ifdef sgi
{
char *slave;
slave = _getpty (pty, O_RDWR, 0622, 0);
if ((*tty = open (slave, O_RDWR)) != -1)
return 0;
}
#else
strcpy (ttydev, "/dev/ttyxx");
strcpy (ptydev, "/dev/ptyxx");
while (PTYCHAR1[letter]) {
ttydev [strlen(ttydev) - 2] = ptydev [strlen(ptydev) - 2] =
PTYCHAR1 [letter];
while (PTYCHAR2[devindex]) {
ttydev [strlen(ttydev) - 1] = ptydev [strlen(ptydev) - 1] =
PTYCHAR2 [devindex];
if ((*pty = open (ptydev, O_RDWR)) >= 0 &&
(*tty = open (ttydev, O_RDWR)) >= 0)
{
/* We need to set things up for our next entry
* into this function!
*/
(void) devindex++;
return(0);
}
if (*pty >= 0)
close (*pty);
devindex++;
}
devindex = 0;
(void) letter++;
}
#endif /* sgi else not sgi */
#endif /* CRAY else not CRAY */
#endif /* umips && SYSTYPE_SYSV */
#endif /* USE_GET_PSEUDOTTY */
#endif /* SVR4 */
/* We were unable to allocate a pty master! Return an error
* condition and let our caller terminate cleanly.
*/
return(1);
}
#endif
#ifdef USE_OSM
/*
* On SYSV386 there is a special device, /dev/osm, where system messages
* are sent. Problem is that we can't perform a select(2) on this device.
* So this routine creates a streams-pty where one end reads the device and
* sends the output to xconsole.
*/
FILE *
osm_pipe()
{
int tty;
char ttydev[64];
if (access("/dev/osm", R_OK) < 0) return NULL;
if ((tty = open("/dev/ptmx", O_RDWR)) < 0) return NULL;
grantpt(tty);
unlockpt(tty);
strcpy(ttydev, (char *)ptsname(tty));
if ((child_pid = fork()) == 0) {
int pty, osm, nbytes, skip;
char cbuf[128];
skip = 0;
osm = open("/dev/osm1", O_RDONLY);
if (osm >= 0) {
while ((nbytes = read(osm, cbuf, sizeof(cbuf))) > 0)
skip += nbytes;
close(osm);
}
pty = open(ttydev, O_RDWR);
if (pty < 0) exit(1);
osm = open("/dev/osm", O_RDONLY);
if (osm < 0) exit(1);
for (nbytes = 0; skip > 0 && nbytes >= 0; skip -= nbytes) {
nbytes = skip;
if (nbytes > sizeof(cbuf))
nbytes = sizeof(cbuf);
nbytes = read(osm, cbuf, nbytes);
}
while ((nbytes = read(osm, cbuf, sizeof(cbuf))) >= 0)
write(pty, cbuf, nbytes);
exit(0);
}
signal(SIGHUP, KillChild);
signal(SIGINT, KillChild);
signal(SIGTERM, KillChild);
return fdopen(tty, "r");
}
#endif /* USE_OSM */
|