|  | 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 */
 |