Imported from conserver-8.1.14.tar.gz

This commit is contained in:
Bryan Stansell 2006-04-09 19:07:58 -07:00
parent c418af32c7
commit ed79341c2c
35 changed files with 1327 additions and 588 deletions

32
CHANGES
View File

@ -1,6 +1,36 @@
CHANGES
=======
version 8.1.14 (Apr 9, 2006):
- fixed rpm conserver.spec file - based on patch by Martin Evans
<m.d.t.evans@qmul.ac.uk>
- added 'uds' console type for unix domain socket connections -
based on patch by DJ Gregor <dj@gregor.com>
- probing of interfaces under cygwin (and possibly others?) now
skips unconfigured interfaces (even if flagged as up!) -
reported by Chris Riddoch <chrisr@digeo.com>
- added the '!login' console option to prevent clients from
connecting to a console - suggested by Greg Tillman
<gregtillman@comcast.net>
- added a 'noop' console type for consoles you'd like to name,
but have no connection to - suggested by Greg Tillman
<gregtillman@comcast.net>
- deprecated escape commands removed from the code
- added '^EcP' and '^EcR' sequences to set the playback and
replay line lengths
- new console config options 'playback' and 'replay' to let the
client set prefered output lengths (with a special feature for
a size of zero)
- prefer strlcpy() over strcpy() - based on patch by Peter
Valchev <pvalchev@openbsd.org>
- fixed bug where '^Eco' by user on an 'exec' console with an
'initcmd' causes input by user to be ignored (could be other
console types as well) - reported by Mark Wedel
<Mark.Wedel@sun.com>
- made POSIX termios code in autologin a requirement (since
conserver requires it) and cleaned up a few other issues -
based on reports by Arthur Clune <ajc22@york.ac.uk>
version 8.1.13 (Jan 15, 2006):
- use SIOCGIFNUM for interface count (if available) and catch
EINVAL on Solaris - patch by Peter Jeremy
@ -823,5 +853,5 @@ before version 6.05:
and enhancements of various types were applied.
#
# $Id: CHANGES,v 1.212 2006/01/15 17:11:42 bryan Exp $
# $Id: CHANGES,v 1.215 2006/04/10 02:07:13 bryan Exp $
#

8
README
View File

@ -21,6 +21,8 @@ Downloading
Mirrors of the site are at:
Australia http://planetmirror.com/pub/conserver/
Ireland http://conserver.oss-mirror.org/
Germany http://conserver.linux-mirror.org/
Russia http://conserver.rinet.ru/
@ -35,7 +37,9 @@ Systems Tested
Cygwin (w2k),gcc 2.95.3
DEC Tru64 4.0, gcc
DEC Tru64 4.0/5.1, native cc
FreeBSD 4.2/4.8/5.1 (x86), gcc
FreeBSD 4.x (i386) gcc
FreeBSD 5.x (i386/amd64/sparc64) gcc
FreeBSD 6.x/7.x (i386/amd64/sparc64/ia64) gcc
HP-UX 10.20, gcc
HP-UX 11.10 parisc and ia64, native cc
Irix 6.15, native cc
@ -61,5 +65,5 @@ Contributions
http://www.columbia.edu/acis/sy/unixdev/zinc
#
# $Id: README,v 1.24 2005/09/05 21:46:43 bryan Exp $
# $Id: README,v 1.25 2006/03/20 16:48:37 bryan Exp $
#

10
TODO
View File

@ -54,8 +54,6 @@ Bryan Stansell
- cyclades ts1000/2000 port : "Moses, Joel" <jmoses@deloitte.com>
- config file for client (list of masters, for example)
- strftime() idea for logfile names : Lars Kellogg-Stedman <lars@larsshack.org>
- 9600baud log replay?
@ -86,9 +84,6 @@ Bryan Stansell
- not even sure if this is possible w/o confusing the client,
but maybe with the new 8.1.0 client-server protocol, we can!
- allow for very long replays (hundres of lines) : John Stoffel
<stoffel@lucent.com>
- log rotation by date : Tom Pachla <tom.pachla@nlc-bnc.ca>
- strict file permission checks on conserver.passwd/conserver.cf : Erik
@ -109,6 +104,9 @@ Bryan Stansell
- reintroduce console grouping : Martin Turba
<martin.turba@igd.fraunhofer.de>
- quick-recheck of down consoles (for uds) and possibly only log state
changes (instead of each try) : DJ Gregor <dj@gregor.com>
#
# $Id: TODO,v 1.55 2005/06/06 23:02:36 bryan Exp $
# $Id: TODO,v 1.56 2006/04/03 22:20:34 bryan Exp $
#

View File

@ -69,7 +69,7 @@
*/
#ifndef lint
char *rcsid = "$Id: autologin.c,v 1.24 2004/12/12 07:36:07 bryan Exp $";
char *rcsid = "$Id: autologin.c,v 1.25 2006/04/10 01:50:16 bryan Exp $";
#endif /* not lint */
extern char *progname;
gid_t awGrps[NGROUPS_MAX];
@ -88,37 +88,18 @@ void usage();
int
Process()
{
register int c;
int iErrs = 0;
int i, iNewGrp;
gid_t wGid;
uid_t wUid;
char *pcCmd = (char *)0,
*pcDevTty = (char *)0;
char *pcTmp;
#ifdef HAVE_GETUSERATTR
char *pcGrps;
#endif
struct passwd *pwd;
struct stat st;
#ifdef HAVE_TERMIOS_H
struct termios n_tio;
#else
# ifdef TIOCNOTTY
# ifdef O_CBREAK
auto struct tc n_tchars;
# else
auto struct tchars n_tchars;
# endif
# ifdef TIOCGLTC
auto struct ltchars n_ltchars;
# endif
# else
# ifdef TIOCGETP
auto struct sgttyb n_sty;
# endif
# endif
#endif
#if defined(HAVE_BSM_AUDIT_H) && defined(HAVE_LIBBSM)
char my_hostname[MAXHOSTNAMELEN];
#endif
@ -320,7 +301,7 @@ Process()
# endif
(void)au_write(iAuditFile, ptAuditToken);
if(0 > au_close(iAuditFile, AU_TO_WRITE, AUE_autologin)) {
fprintf(stderr, "%s: audit write failed",
fprintf(stderr, "%s: audit write failed: %s",
progname,
strerror(errno));
}
@ -372,54 +353,6 @@ Process()
/* put the tty in the correct mode
*/
#ifndef HAVE_TERMIOS_H
if (0 != ioctl(0, TIOCGETP, (char *)&n_sty)) {
fprintf(stderr, "%s: iotcl: getp: %s\n", progname, strerror(errno));
exit(10);
}
#ifdef O_CBREAK
n_sty.sg_flags &= ~(O_CBREAK);
n_sty.sg_flags |= (O_CRMOD|O_ECHO);
#else
n_sty.sg_flags &= ~(CBREAK);
n_sty.sg_flags |= (CRMOD|ECHO);
#endif
n_sty.sg_kill = '\025'; /* ^U */
n_sty.sg_erase = '\010'; /* ^H */
if (0 != ioctl(0, TIOCSETP, (char *)&n_sty)) {
fprintf(stderr, "%s: iotcl: setp: %s\n", progname, strerror(errno));
exit(10);
}
/* stty undef all tty chars
*/
#if 0
if (-1 == ioctl(0, TIOCGETC, (char *)&n_tchars)) {
fprintf(stderr, "%s: ioctl: getc: %s\n", progname, strerror(errno));
return;
}
n_tchars.t_intrc = -1;
n_tchars.t_quitc = -1;
if (-1 == ioctl(0, TIOCSETC, (char *)&n_tchars)) {
fprintf(stderr, "%s: ioctl: setc: %s\n", progname, strerror(errno));
return;
}
#endif
#ifdef TIOCGLTC
if (-1 == ioctl(0, TIOCGLTC, (char *)&n_ltchars)) {
fprintf(stderr, "%s: ioctl: gltc: %s\n", progname, strerror(errno));
return;
}
n_ltchars.t_suspc = -1;
n_ltchars.t_dsuspc = -1;
n_ltchars.t_flushc = -1;
n_ltchars.t_lnextc = -1;
if (-1 == ioctl(0, TIOCSLTC, (char *)&n_ltchars)) {
fprintf(stderr, "%s: ioctl: sltc: %s\n", progname, strerror(errno));
return;
}
#endif
#else /* not using ioctl, using POSIX or sun stuff */
#ifdef HAVE_TCGETATTR
if (0 != tcgetattr(0, &n_tio)) {
(void) fprintf(stderr, "%s: tcgetattr: %s\n", progname, strerror(errno));
@ -455,16 +388,7 @@ Process()
exit(1);
/* NOTREACHED */
}
#else
#ifndef HAVE_TERMIOS_H
if (0 != ioctl(0, TCSETS, &n_tio)) {
(void) fprintf(stderr, "%s: ioctl: TCSETS: %s\n", progname, strerror(errno));
exit(1);
/* NOTREACHED */
}
#endif
#endif
#endif /* setup tty */
if (fMakeUtmp) {
extern char *ttyname();
@ -532,7 +456,7 @@ char *pctty;
register int fdUtmp;
register char *pcDev;
register struct utmp *up;
auto struct utmp outmp, utmp;
auto struct utmp utmp;
if ((char *)0 == pctty) {

View File

@ -8,9 +8,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#if USE_UNIX_DOMAIN_SOCKETS
#include <sys/un.h>
#endif
#include <arpa/inet.h>
#include <netdb.h>
#include <ctype.h>
@ -37,6 +35,17 @@
# define DEFESC 'c'
#endif
/* set the default length of the replay functions
* DEFREPLAY for 'r'
* DEFPLAYBACK for 'p'
*/
#if !defined(DEFREPLAY)
# define DEFREPLAY 20
#endif
#if !defined(PLAYBACK)
# define DEFPLAYBACK 60
#endif
/* For legacy compile-time setting of the port...
*/
#if ! defined(DEFPORT)
@ -94,6 +103,18 @@ typedef long fd_set;
#include <termios.h>
#ifndef TAB3
# ifdef OXTABS
# define TAB3 OXTABS
# else
# ifdef XTABS
# define TAB3 XTABS
# else
# define TAB3 0
# endif
# endif
#endif
#ifdef HAVE_STROPTS_H
# include <stropts.h>
#endif

32
config.guess vendored
View File

@ -1,9 +1,10 @@
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
# Inc.
timestamp='2006-01-02'
timestamp='2006-03-13'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@ -106,7 +107,7 @@ set_cc_for_build='
trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
: ${TMPDIR=/tmp} ;
{ tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
{ tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
@ -788,7 +789,10 @@ EOF
echo ${UNAME_MACHINE}-pc-pw32
exit ;;
x86:Interix*:[345]*)
echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
EM64T:Interix*:[345]*)
echo x86_64-unknown-interix${UNAME_RELEASE}
exit ;;
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
echo i${UNAME_MACHINE}-pc-mks
@ -859,7 +863,11 @@ EOF
#endif
#endif
EOF
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '/^CPU/{s: ::g;p;}'`"
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
/^CPU/{
s: ::g
p
}'`"
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
;;
mips64:Linux:*:*)
@ -878,7 +886,11 @@ EOF
#endif
#endif
EOF
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '/^CPU/{s: ::g;p;}'`"
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
/^CPU/{
s: ::g
p
}'`"
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
;;
or32:Linux:*:*)
@ -975,7 +987,7 @@ EOF
LIBC=gnulibc1
# endif
#else
#if defined(__INTEL_COMPILER) || defined(__PGI)
#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__sun)
LIBC=gnu
#else
LIBC=gnuaout
@ -985,7 +997,11 @@ EOF
LIBC=dietlibc
#endif
EOF
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '/^LIBC/{s: ::g;p;}'`"
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
/^LIBC/{
s: ::g
p
}'`"
test x"${LIBC}" != x && {
echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
exit

View File

@ -195,6 +195,9 @@
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strlcpy' function. */
#undef HAVE_STRLCPY
/* Define to 1 if you have the <stropts.h> header file. */
#undef HAVE_STROPTS_H
@ -243,6 +246,9 @@
/* Define to 1 if you have the <sys/uio.h> header file. */
#undef HAVE_SYS_UIO_H
/* Define to 1 if you have the <sys/un.h> header file. */
#undef HAVE_SYS_UN_H
/* Define to 1 if you have the <sys/vlimit.h> header file. */
#undef HAVE_SYS_VLIMIT_H

21
config.sub vendored
View File

@ -1,9 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
# Inc.
timestamp='2006-01-02'
timestamp='2006-03-07'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@ -268,15 +269,16 @@ case $basic_machine in
| mn10200 | mn10300 \
| mt \
| msp430 \
| nios | nios2 \
| ns16k | ns32k \
| or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| pyramid \
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
| strongarm \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
@ -350,17 +352,18 @@ case $basic_machine in
| mmix-* \
| mt-* \
| msp430-* \
| nios-* | nios2-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| pyramid-* \
| romp-* | rs6000-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tron-* \
@ -1126,7 +1129,7 @@ case $basic_machine in
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b)
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
basic_machine=sparc-sun
;;
cydra)

6
configure vendored
View File

@ -3770,7 +3770,8 @@ fi
for ac_header in unistd.h getopt.h sys/vlimit.h sys/resource.h ttyent.h sys/ttold.h sys/uio.h sys/ioctl_compat.h usersec.h sys/select.h stropts.h sys/audit.h shadow.h sys/time.h crypt.h sysexits.h types.h sys/sockio.h sys/param.h
for ac_header in unistd.h getopt.h sys/vlimit.h sys/resource.h ttyent.h sys/ttold.h sys/uio.h sys/ioctl_compat.h usersec.h sys/select.h stropts.h sys/audit.h shadow.h sys/time.h crypt.h sysexits.h types.h sys/sockio.h sys/param.h sys/un.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@ -6955,7 +6956,8 @@ done
for ac_func in getopt strerror getrlimit getsid setsid getuserattr setgroups tcgetpgrp tcsetpgrp tcgetattr tcsetattr tcsendbreak setpgrp getutent setttyent getspnam setlinebuf setvbuf ptsname grantpt unlockpt sigaction setsockopt getdtablesize putenv memset memcpy memcmp memmove sysconf getlogin inet_aton setproctitle gettimeofday
for ac_func in getopt strerror getrlimit getsid setsid getuserattr setgroups tcgetpgrp tcsetpgrp tcgetattr tcsetattr tcsendbreak setpgrp getutent setttyent getspnam setlinebuf setvbuf ptsname grantpt unlockpt sigaction setsockopt getdtablesize putenv memset memcpy memcmp memmove sysconf getlogin inet_aton setproctitle gettimeofday strlcpy
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_func" >&5

View File

@ -326,7 +326,7 @@ if test "$ac_cv_sys_posix_termios" != "yes"; then
AC_MSG_ERROR([POSIX termios interface required])
fi
AC_CHECK_HEADERS(unistd.h getopt.h sys/vlimit.h sys/resource.h ttyent.h sys/ttold.h sys/uio.h sys/ioctl_compat.h usersec.h sys/select.h stropts.h sys/audit.h shadow.h sys/time.h crypt.h sysexits.h types.h sys/sockio.h sys/param.h)
AC_CHECK_HEADERS(unistd.h getopt.h sys/vlimit.h sys/resource.h ttyent.h sys/ttold.h sys/uio.h sys/ioctl_compat.h usersec.h sys/select.h stropts.h sys/audit.h shadow.h sys/time.h crypt.h sysexits.h types.h sys/sockio.h sys/param.h sys/un.h)
dnl sys/proc.h needs sys/param.h on openbsd, apparently
AC_CHECK_HEADERS(sys/proc.h, [], [],
[#if HAVE_SYS_PARAM_H
@ -610,7 +610,7 @@ AC_CHECK_HEADERS(pty.h libutil.h util.h)
AC_CHECK_LIB(util, openpty)
AC_CHECK_FUNCS(openpty)
AC_CHECK_FUNCS(getopt strerror getrlimit getsid setsid getuserattr setgroups tcgetpgrp tcsetpgrp tcgetattr tcsetattr tcsendbreak setpgrp getutent setttyent getspnam setlinebuf setvbuf ptsname grantpt unlockpt sigaction setsockopt getdtablesize putenv memset memcpy memcmp memmove sysconf getlogin inet_aton setproctitle gettimeofday)
AC_CHECK_FUNCS(getopt strerror getrlimit getsid setsid getuserattr setgroups tcgetpgrp tcsetpgrp tcgetattr tcsetattr tcsendbreak setpgrp getutent setttyent getspnam setlinebuf setvbuf ptsname grantpt unlockpt sigaction setsockopt getdtablesize putenv memset memcpy memcmp memmove sysconf getlogin inet_aton setproctitle gettimeofday strlcpy)
AC_FUNC_SETPGRP
AC_CHECK_FUNC(strcasecmp,
[AC_DEFINE(HAVE_STRCASECMP, 1, [Define if strcasecmp is available])],

View File

@ -1,5 +1,5 @@
.\" $Id: conserver.cf.man,v 1.73 2005/06/09 07:09:31 bryan Exp $
.TH CONSERVER.CF 5 "2005/06/09" "conserver-8.1.13" "conserver"
.\" $Id: conserver.cf.man,v 1.76 2006/03/20 16:47:03 bryan Exp $
.TH CONSERVER.CF 5 "2006/03/20" "conserver-8.1.14" "conserver"
.SH NAME
conserver.cf \- console configuration file for
.BR conserver (8)
@ -465,7 +465,7 @@ the ``^Ecl0'' client escape sequence.
.br
Assign the serial device
.I filename
as the access to the console.
as the path to the console.
Only consoles of type ``device'' will use this value.
.TP
\f3devicesubst\fP \f2c\fP\f3=\fP\f2t\fP[\f2n\fP]\f2f\fP[\f3,\fP...]|\f3""\fP
@ -885,6 +885,16 @@ The conserver option
will set this flag for all consoles.
Default is
.BR !unloved .
.TP
.B login
Allow users to log into this console.
If logins are not allowed, conserver will send a generic message to the
client saying so and terminate the connection.
You can override the generic message by setting the
.B motd
message.
Default is
.BR login .
.PD
.RE
.TP
@ -1046,25 +1056,58 @@ A
.RB ` b '
can be specified to add logging of break sequences sent to the console.
.TP
\f3type\fP \f3device\fP|\f3exec\fP|\f3host\fP
\f3type\fP \f3device\fP|\f3exec\fP|\f3host\fP|\f3noop\fP|\f3uds\fP
.br
Set the type of console.
The type
A type of
.RB `` device ''
should be used for local serial ports (also set the
.B device
option), the type
value).
A type of
.RB `` exec ''
should be used for command invocations (perhaps also set the
.B exec
option), and the type
value).
A type of
.RB `` host ''
should be used for terminal servers and other socket-based
should be used for terminal servers and other TCP socket-based
interaction (also set the
.B host
and
.B port
options).
values).
A type of
.RB `` noop ''
should be used as a placeholder - it does nothing, ignores any
.B logfile
value and forces the
.B !nologin
option (so you might want to set the
.B motd
value).
A type of
.RB `` uds ''
should be used for Unix domain sockets (also set the
.B uds
option).
.TP
\f3uds\fP \f2filename\fP
.br
Assign the Unix domain socket
.I filename
as the path to the console.
Only consoles of type ``uds'' will use this value.
.TP
\f3udssubst\fP \f2c\fP\f3=\fP\f2t\fP[\f2n\fP]\f2f\fP[\f3,\fP...]|\f3""\fP
.br
Perform character substitutions on the
.B uds
value.
See the
.B devicesubst
option for an explanation of the format string.
If the null string (``\f3""\fP'') is used, no replacements will be done.
.RE
.TP
\f3group\fP \f2name\fP

View File

@ -1,5 +1,5 @@
.\" $Id: conserver.passwd.man,v 1.10 2004/01/08 16:12:33 bryan Exp $
.TH CONSERVER.PASSWD 5 "2004/01/08" "conserver-8.1.13" "conserver"
.TH CONSERVER.PASSWD 5 "2004/01/08" "conserver-8.1.14" "conserver"
.SH NAME
conserver.passwd \- user access information for
.BR conserver (8)

View File

@ -36,6 +36,10 @@
<TD colspan="2" align="center">Please pick your closest
mirror: &nbsp;&nbsp;<A href=
"http://planetmirror.com/pub/conserver/">Australia</A>
&nbsp;&nbsp;<A href=
"http://conserver.linux-mirror.org/">Germany</A>
&nbsp;&nbsp;<A href=
"http://conserver.oss-mirror.org/">Ireland</A>
&nbsp;&nbsp;<A href="http://conserver.rinet.ru/">Russia</A>
&nbsp;&nbsp;<A href="http://www.conserver.com/">US-West
(Primary)</A><BR>
@ -182,11 +186,11 @@
<H3>Downloading</H3>
<P>The current version, released on Jan 15, 2006, is <A
href="8.1.13.tar.gz">8.1.13.tar.gz</A>. You can get it
<P>The current version, released on Apr 9, 2006, is <A
href="8.1.14.tar.gz">8.1.14.tar.gz</A>. You can get it
via <A href=
"ftp://ftp.conserver.com/conserver/8.1.13.tar.gz">FTP</A>
or <A href="8.1.13.tar.gz">HTTP</A>. See the <A href=
"ftp://ftp.conserver.com/conserver/8.1.14.tar.gz">FTP</A>
or <A href="8.1.14.tar.gz">HTTP</A>. See the <A href=
"CHANGES">CHANGES</A> file for information on the latest
updates.</P>
@ -230,7 +234,11 @@
<LI>DEC Tru64 4.0/5.1, native cc</LI>
<LI>FreeBSD 4.2/4.8/5.1 (x86), gcc</LI>
<LI>FreeBSD 4.x (i386) gcc</LI>
<LI>FreeBSD 5.x (i386/amd64/sparc64) gcc</LI>
<LI>FreeBSD 6.x/7.x (i386/amd64/sparc64/ia64) gcc</LI>
<LI>HP-UX 10.20, gcc</LI>

View File

@ -1,5 +1,5 @@
/*
* $Id: client.c,v 5.89 2005/09/04 00:28:58 bryan Exp $
* $Id: client.c,v 5.90 2006/04/03 13:32:08 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -107,174 +107,134 @@ BumpClient(pCE, message)
pCE->pCLwr = (CONSCLIENT *)0;
}
/* replay last iBack lines of the log file upon connect to console (ksb)
/* replay last 'back' lines of the log file upon connect to console (ksb)
*
* NB: we know the console might be spewing when the replay happens,
* we want to just output what is in the log file and get out,
* so we don't drop chars...
*/
#define REPLAYBUFFER 4096
void
#if PROTOTYPES
Replay(CONSENT *pCE, CONSFILE *fdOut, int iBack)
Replay(CONSENT *pCE, CONSFILE *fdOut, unsigned short back)
#else
Replay(pCE, fdOut, iBack)
Replay(pCE, fdOut, back)
CONSENT *pCE;
CONSFILE *fdOut;
int iBack;
unsigned short back;
#endif
{
CONSFILE *fdLog = (CONSFILE *)0;
STRING *line = (STRING *)0;
off_t file_pos;
off_t buf_pos;
char *buf;
char *bp = (char *)0;
char *s;
int r;
int ch;
struct stat stLog;
struct lines {
int is_mark;
STRING *line;
STRING *mark_end;
} *lines;
int n_lines;
int ln;
int i;
int j;
int u;
int is_mark;
char dummy[4];
int was_mark = 0;
#if HAVE_DMALLOC && DMALLOC_MARK_REPLAY
unsigned long dmallocMarkReplay = 0;
#endif
if (pCE != (CONSENT *)0) {
fdLog = pCE->fdlog;
/* no logfile and down and logfile defined? try and open it */
if (fdLog == (CONSFILE *)0 && !pCE->fup &&
pCE->logfile != (char *)0)
if (pCE != (CONSENT *)0 && pCE->logfile != (char *)0)
fdLog = FileOpen(pCE->logfile, O_RDONLY, 0644);
}
if (fdLog == (CONSFILE *)0) {
FileWrite(fdOut, FLAGFALSE, "[no log file on this console]\r\n",
-1);
return;
}
/* find the size of the file
*/
if (0 != FileStat(fdLog, &stLog)) {
return;
}
#if HAVE_DMALLOC && DMALLOC_MARK_REPLAY
dmallocMarkReplay = dmalloc_mark();
#endif
file_pos = stLog.st_size - 1;
/* find the size of the file
*/
if (0 != FileStat(fdLog, &stLog))
goto common_exit;
file_pos = stLog.st_size - 1; /* point at last byte */
buf_pos = file_pos + 1;
/* get space for the line information and initialize it
*
* we allocate room for one more line than requested to be able to
* do the mark ranges
*/
if ((char *)0 == (buf = malloc(BUFSIZ))) {
if ((char *)0 == (buf = malloc(REPLAYBUFFER)))
OutOfMem();
}
n_lines = iBack + 1;
lines = (struct lines *)calloc(n_lines, sizeof(*lines));
if ((struct lines *)0 == lines) {
OutOfMem();
}
for (i = 0; i < n_lines; i++) {
lines[i].mark_end = AllocString();
lines[i].line = AllocString();
}
ln = -1;
bp = buf + 1; /* just give it something - it resets below */
line = AllocString();
/* loop as long as there is data in the file or we have not found
* the requested number of lines
*/
while (file_pos >= 0) {
ln = -1;
for (; file_pos >= 0; file_pos--, bp--) {
if (file_pos < buf_pos) {
int r;
/* read one buffer worth of data a buffer boundary
*
* the first read will probably not get a full buffer but
* the rest (as we work our way back in the file) should be
*/
buf_pos = (file_pos / BUFSIZ) * BUFSIZ;
buf_pos = (file_pos / REPLAYBUFFER) * REPLAYBUFFER;
if (FileSeek(fdLog, buf_pos, SEEK_SET) < 0) {
goto common_exit;
}
if ((r = FileRead(fdLog, buf, BUFSIZ)) < 0) {
if ((r = FileRead(fdLog, buf, REPLAYBUFFER)) < 0) {
goto common_exit;
}
bp = buf + r;
bp = buf + r - 1;
}
/* process the next character
*/
--file_pos;
if ((ch = *--bp) == '\n') {
if ((ch = *bp) == '\n') {
if (ln >= 0) {
int i;
int u;
int is_mark = 0;
/* reverse the text to put it in forward order
*/
u = lines[ln].line->used - 1;
u = line->used - 1;
for (i = 0; i < u / 2; i++) {
int temp;
temp = lines[ln].line->string[i];
lines[ln].line->string[i]
= lines[ln].line->string[u - i - 1];
lines[ln].line->string[u - i - 1] = temp;
temp = line->string[i];
line->string[i] = line->string[u - i - 1];
line->string[u - i - 1] = temp;
}
/* see if this line is a MARK
*/
if (lines[ln].line->used > 0 &&
lines[ln].line->string[0] == '[') {
i = sscanf(lines[ln].line->string + 1,
if (line->used > 0 && line->string[0] == '[') {
char dummy[4];
int j;
i = sscanf(line->string + 1,
"-- MARK -- %3c %3c %d %d:%d:%d %d]\r\n",
dummy, dummy, &j, &j, &j, &j, &j);
is_mark = (i == 7);
} else {
is_mark = 0;
}
/* process this line
*/
if (is_mark && ln > 0 && lines[ln - 1].is_mark) {
if (is_mark && was_mark) {
/* this is a mark and the previous line is also
* a mark, so make (or continue) that range
* a mark, so reduce the line count 'cause it'll
* go up by one and we're joining them on output.
*/
if (0 == lines[ln - 1].mark_end->used) {
/* this is a new range - shuffle pointers
*
* remember that we are moving backward
*/
BuildStringN(lines[ln - 1].line->string,
lines[ln - 1].line->used - 1,
lines[ln - 1].mark_end);
BuildString((char *)0, lines[ln - 1].line);
}
BuildString((char *)0, lines[ln - 1].line);
BuildStringN(lines[ln].line->string,
lines[ln].line->used - 1,
lines[ln - 1].line);
BuildString((char *)0, lines[ln].line);
ln--;
}
lines[ln].is_mark = is_mark;
was_mark = is_mark;
}
/* advance to the next line and break if we have enough
*/
ln++;
if (ln >= n_lines - 1) {
BuildString((char *)0, line);
if (ln >= back) {
break;
}
}
@ -285,90 +245,122 @@ Replay(pCE, fdOut, iBack)
if (ln < 0) {
ln = 0;
}
BuildStringChar(ch, lines[ln].line);
BuildStringChar(ch, line);
/* if we've processed "a lot" of data for a line, then bail
* why? there must be some very long non-newline terminated
* strings and if we just keep going back, we could spew lots
* of data and chew up lots of memory
*/
if (lines[ln].line->used > MAXREPLAYLINELEN) {
if (line->used > MAXREPLAYLINELEN) {
break;
}
}
free(buf);
buf = (char *)0;
/* if we got back to beginning of file but saw some data, include it
/* move forward. either we hit the beginning of the file and we
* move to the first byte, or we hit a \n and we move past it
*/
if (ln >= 0 && lines[ln].line->used > 0) {
file_pos++;
/* reverse the text to put it in forward order
*/
u = lines[ln].line->used - 1;
for (i = 0; i < u / 2; i++) {
int temp;
/* Now output the lines, starting from where we stopped */
if (FileSeek(fdLog, file_pos, SEEK_SET) >= 0) {
int eof = 0;
int i = 0;
int r = 0;
STRING *mark_beg = (STRING *)0;
STRING *mark_end = (STRING *)0;
temp = lines[ln].line->string[i];
lines[ln].line->string[i]
= lines[ln].line->string[u - i - 1];
lines[ln].line->string[u - i - 1] = temp;
}
ln++;
mark_beg = AllocString();
mark_end = AllocString();
ln = 0; /* number of lines output */
BuildString((char *)0, line);
while (ln < back && !eof) {
if (r <= 0) {
if ((r = FileRead(fdLog, buf, REPLAYBUFFER)) < 0)
eof = 1;
i = 0;
}
/* copy the lines into the buffer and put them in order
*/
for (i = ln - 1; i >= 0; i--) {
if (lines[i].is_mark && 0 != lines[i].mark_end->used) {
int mark_len;
if (!eof)
BuildStringChar(buf[i], line);
/* output the start of the range, stopping at the ']'
*/
s = strrchr(lines[i].line->string, ']');
if ((char *)0 != s) {
if (buf[i] == '\n' || eof) {
int is_mark = 0;
if (line->used > 0 && line->string[0] == '[') {
char dummy[4];
int j;
int i;
i = sscanf(line->string + 1,
"-- MARK -- %3c %3c %d %d:%d:%d %d]\r\n",
dummy, dummy, &j, &j, &j, &j, &j);
is_mark = (i == 7);
}
if (is_mark) {
if (mark_beg->used > 1) {
BuildString((char *)0, mark_end);
BuildString(line->string, mark_end);
} else
BuildString(line->string, mark_beg);
} else {
if (mark_beg->used > 1) {
if (mark_end->used > 1) {
char *s;
/* output the start of the range, stopping at the ']' */
s = strrchr(mark_beg->string, ']');
if ((char *)0 != s)
*s = '\000';
}
FileWrite(fdOut, FLAGTRUE, lines[i].line->string, -1);
FileWrite(fdOut, FLAGTRUE, mark_beg->string,
-1);
FileWrite(fdOut, FLAGTRUE, " .. ", 4);
/* build the end string by removing the leading "[-- MARK -- "
* and replacing "]\r\n" on the end with " -- MARK --]\r\n"
*/
mark_len = sizeof("[-- MARK -- ") - 1;
s = strrchr(lines[i].mark_end->string + mark_len, ']');
if ((char *)0 != s) {
s = strrchr(mark_end->string, ']');
if ((char *)0 != s)
*s = '\000';
}
FileWrite(fdOut, FLAGTRUE,
lines[i].mark_end->string + mark_len, -1);
FileWrite(fdOut, FLAGFALSE, " -- MARK --]\r\n", -1);
u = lines[i].mark_end->used;
s = lines[i].mark_end->string;
} else
FileWrite(fdOut, FLAGFALSE, lines[i].line->string,
lines[i].line->used - 1);
mark_end->string +
sizeof("[-- MARK -- ") - 1, -1);
FileWrite(fdOut, FLAGFALSE, " -- MARK --]\r\n",
-1);
} else {
FileWrite(fdOut, FLAGFALSE, mark_beg->string,
mark_beg->used - 1);
}
BuildString((char *)0, mark_beg);
BuildString((char *)0, mark_end);
ln++;
if (ln >= back)
break;
}
FileWrite(fdOut, FLAGFALSE, line->string,
line->used - 1);
ln++;
}
BuildString((char *)0, line);
}
/* move the counters */
i++;
r--;
}
DestroyString(mark_end);
DestroyString(mark_beg);
}
common_exit:
/* if we opened the logfile, close it */
if (fdLog != pCE->fdlog)
if (line != (STRING *)0)
DestroyString(line);
if (buf != (char *)0)
free(buf);
if (fdLog != (CONSFILE *)0)
FileClose(&fdLog);
if ((struct lines *)0 != lines) {
for (i = 0; i < n_lines; i++) {
DestroyString(lines[i].mark_end);
DestroyString(lines[i].line);
}
free(lines);
lines = (struct lines *)0;
}
if ((char *)0 != buf) {
free(buf);
buf = (char *)0;
}
#if HAVE_DMALLOC && DMALLOC_MARK_REPLAY
CONDDEBUG((1, "Replay(): dmalloc / MarkReplay"));
dmalloc_log_changed(dmallocMarkReplay, 1, 0, 1);
@ -408,9 +400,11 @@ static HELP aHLTable[] = {
{WHEN_ATTACH, "l1-9 send specific break sequence"},
{WHEN_ALWAYS, "m display the message of the day"},
{WHEN_ALWAYS, "o (re)open the tty and log file"},
{WHEN_ALWAYS, "p replay the last 60 lines"},
{WHEN_ALWAYS, "r replay the last 20 lines"},
{WHEN_ATTACH, "s spy read only"},
{WHEN_ALWAYS, "p playback the last %hu lines"},
{WHEN_ALWAYS, "P set number of playback lines"},
{WHEN_ALWAYS, "r replay the last %hu lines"},
{WHEN_ALWAYS, "R set number of replay lines"},
{WHEN_ATTACH, "s spy mode (read only)"},
{WHEN_ALWAYS, "u show host status"},
{WHEN_ALWAYS, "v show version info"},
{WHEN_ALWAYS, "w who is on this console"},
@ -454,6 +448,8 @@ HelpUser(pCL, pCE)
BuildString((char *)0, acLine);
for (i = 0; i < sizeof(aHLTable) / sizeof(HELP); ++i) {
char *text;
if (aHLTable[i].iwhen & IS_LIMITED &&
ConsentUserOk(pLUList, pCL->username->string) == 1)
continue;
@ -461,12 +457,21 @@ HelpUser(pCL, pCE)
if (0 == (aHLTable[i].iwhen & iCmp))
continue;
text = aHLTable[i].actext;
if (text[0] == 'p') {
BuildTmpString((char *)0);
text = BuildTmpStringPrint(text, pCL->playback);
} else if (text[0] == 'r') {
BuildTmpString((char *)0);
text = BuildTmpStringPrint(text, pCL->replay);
}
if (acLine->used != 0) { /* second part of line */
if (strlen(aHLTable[i].actext) < HALFLINE) {
if (strlen(text) < HALFLINE) {
for (j = acLine->used; j <= HALFLINE; ++j) {
BuildStringChar(' ', acLine);
}
BuildString(aHLTable[i].actext, acLine);
BuildString(text, acLine);
BuildString(acEoln, acLine);
FileWrite(pCL->fd, FLAGTRUE, acLine->string,
acLine->used - 1);
@ -481,7 +486,7 @@ HelpUser(pCL, pCE)
}
if (acLine->used == 0) { /* at new line */
BuildStringChar(' ', acLine);
BuildString(aHLTable[i].actext, acLine);
BuildString(text, acLine);
if (acLine->used > HALFLINE) {
BuildString(acEoln, acLine);
FileWrite(pCL->fd, FLAGTRUE, acLine->string,

View File

@ -1,5 +1,5 @@
/*
* $Id: client.h,v 5.40 2005/06/07 19:55:51 bryan Exp $
* $Id: client.h,v 5.41 2006/04/03 13:32:08 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -48,7 +48,9 @@ typedef enum clientState {
S_QUOTE, /* send any character we can spell */
S_BCAST, /* send a broadcast message to all clients */
S_CWAIT, /* wait for client */
S_CEXEC /* client execing a program */
S_CEXEC, /* client execing a program */
S_REPLAY, /* set replay length for 'r' */
S_PLAYBACK /* set replay length for 'p' */
} CLIENTSTATE;
typedef struct client { /* Connection Information: */
@ -75,17 +77,18 @@ typedef struct client { /* Connection Information: */
*pCLnext; /* next person on this list */
/* next lists link clients on a console */
char ic[2]; /* two character escape sequence */
unsigned short replay; /* lines to replay for 'r' */
unsigned short playback; /* lines to replay for 'p' */
CLIENTSTATE iState; /* state for fsm in server */
char caccess; /* did we trust the remote machine */
IOSTATE ioState; /* state of the socket */
time_t stateTimer; /* timer for various ioState states */
STRING *accmd; /* the command the user issued */
STRING *msg; /* the broadcast message */
struct sockaddr_in
cnct_port; /* where from */
} CONSCLIENT;
extern void Replay PARAMS((CONSENT *, CONSFILE *, int));
extern void Replay PARAMS((CONSENT *, CONSFILE *, unsigned short));
extern void HelpUser PARAMS((CONSCLIENT *));
extern void FindWrite PARAMS((CONSENT *));
extern int ClientAccessOk PARAMS((CONSCLIENT *));

View File

@ -1,5 +1,5 @@
/*
* $Id: consent.c,v 5.145 2005/06/08 18:09:40 bryan Exp $
* $Id: consent.c,v 5.149 2006/04/07 15:47:20 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -276,6 +276,12 @@ StopInit(pCE)
if (pCE->initcmd == (char *)0)
return;
if (pCE->initpid != 0 || pCE->initfile != (CONSFILE *)0)
SendIWaitClientsMsg(pCE,
(pCE->fup &&
pCE->ioState ==
ISNORMAL) ? "up]\r\n" : "down]\r\n");
if (pCE->initpid != 0) {
kill(pCE->initpid, SIGHUP);
CONDDEBUG((1, "StopInit(): sending initcmd pid %lu signal %d",
@ -779,6 +785,10 @@ ConsInit(pCE)
switch (pCE->type) {
case UNKNOWNTYPE: /* shut up gcc */
break;
case NOOP:
pCE->fup = 1;
pCE->ioState = ISNORMAL;
break;
case EXEC:
if ((cofile =
FallBack(&pCE->execSlave, &pCE->execSlaveFD)) == -1) {
@ -887,6 +897,74 @@ ConsInit(pCE)
}
pCE->fup = 1;
break;
case UDS:
{
struct sockaddr_un port;
#if HAVE_MEMSET
memset((void *)&port, 0, sizeof(port));
#else
bzero((char *)&port, sizeof(port));
#endif
/* we ensure that pCE->uds exists and fits inside port.sun_path
* in readcfg.c, so we can just defend ourselves here (which
* should never trigger).
*/
if (strlen(pCE->uds) >= sizeof(port.sun_path)) {
Error
("[%s] strlen(uds path) > sizeof(port.sun_path): forcing down",
pCE->server);
ConsDown(pCE, FLAGTRUE, FLAGTRUE);
return;
}
StrCpy(port.sun_path, pCE->uds, sizeof(port.sun_path));
port.sun_family = AF_UNIX;
if ((cofile = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
Error
("[%s] socket(AF_UNIX,SOCK_STREAM): %s: forcing down",
pCE->server, strerror(errno));
ConsDown(pCE, FLAGTRUE, FLAGTRUE);
return;
}
if (!SetFlags(cofile, O_NONBLOCK, 0)) {
ConsDown(pCE, FLAGTRUE, FLAGTRUE);
return;
}
if ((ret =
connect(cofile, (struct sockaddr *)&port,
sizeof(port))) < 0) {
if (errno != EINPROGRESS) {
Error("[%s] connect(%u): %s: forcing down",
pCE->server, cofile, strerror(errno));
ConsDown(pCE, FLAGTRUE, FLAGTRUE);
return;
}
}
}
if ((pCE->cofile =
FileOpenFD(cofile, simpleSocket)) == (CONSFILE *)0) {
Error
("[%s] FileOpenFD(%d,simpleSocket) failed: forcing down",
pCE->server, cofile);
ConsDown(pCE, FLAGTRUE, FLAGTRUE);
return;
}
if (ret == 0) {
pCE->ioState = ISNORMAL;
pCE->stateTimer = 0;
} else {
pCE->ioState = INCONNECT;
pCE->stateTimer = time((time_t *)0) + CONNECTTIMEOUT;
if (timers[T_STATE] == (time_t)0 ||
timers[T_STATE] > pCE->stateTimer)
timers[T_STATE] = pCE->stateTimer;
}
pCE->fup = 1;
break;
case DEVICE:
if (-1 ==
(cofile = open(pCE->device, O_RDWR | O_NONBLOCK, 0600))) {
@ -925,12 +1003,19 @@ ConsInit(pCE)
Verbose("[%s] port %hu on %s", pCE->server, pCE->netport,
pCE->host);
break;
case NOOP:
Verbose("[%s] noop", pCE->server);
break;
case UDS:
Verbose("[%s] uds %s", pCE->server, pCE->uds);
break;
case DEVICE:
Verbose("[%s] at %s%c on %s", pCE->server, pCE->baud->acrate,
pCE->parity->key[0], pCE->device);
break;
}
if (cofile != -1) {
/* if we're waiting for connect() to finish, watch the
* write bit, otherwise watch for the read bit
*/
@ -940,6 +1025,7 @@ ConsInit(pCE)
FD_SET(cofile, &rinit);
if (maxfd < cofile + 1)
maxfd = cofile + 1;
}
tyme = time((time_t *)0);

View File

@ -1,5 +1,5 @@
/*
* $Id: consent.h,v 5.63 2005/06/08 18:09:40 bryan Exp $
* $Id: consent.h,v 5.66 2006/03/20 16:47:03 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -55,7 +55,9 @@ typedef enum consType {
UNKNOWNTYPE = 0,
DEVICE,
EXEC,
HOST
HOST,
NOOP,
UDS
} CONSTYPE;
typedef struct names {
@ -102,6 +104,9 @@ typedef struct consent { /* console information */
char *execsubst; /* exec substitution pattern */
uid_t execuid; /* user to run exec as */
gid_t execgid; /* group to run exec as */
/* type == UDS */
char *uds; /* socket file */
char *udssubst; /* socket file substitution pattern */
/* global stuff */
char *master; /* master hostname */
unsigned short breakNum; /* break type [1-9] */
@ -127,6 +132,7 @@ typedef struct consent { /* console information */
FLAG striphigh; /* strip high-bit of console data */
FLAG autoreinit; /* auto-reinitialize if failed */
FLAG unloved; /* copy "unloved" data to stdout */
FLAG login; /* allow logins to the console */
/*** runtime settings ***/
CONSFILE *fdlog; /* the local log file */

View File

@ -1,6 +1,6 @@
.\" @(#)conserver.8 01/06/91 OSU CIS; Thomas A. Fine
.\" $Id: conserver.man,v 1.51 2005/04/02 09:59:48 bryan Exp $
.TH CONSERVER 8 "2005/04/02" "conserver-8.1.13" "conserver"
.\" $Id: conserver.man,v 1.53 2006/03/20 16:47:03 bryan Exp $
.TH CONSERVER 8 "2006/03/20" "conserver-8.1.14" "conserver"
.SH NAME
conserver \- console server daemon
.SH SYNOPSIS
@ -380,13 +380,16 @@ The console aliases in a comma-separated list.
.I type
The type of console.
Values will be a `/' for a local device, `|' for
a command, or `!' for a remote port.
a command, `!' for a remote port, `%' for a Unix domain socket,
and `#' for a noop console.
.TP
.I details
Multiple values are comma-separated and depend on the type of the console.
Local devices will have the values of the device file and baud rate/parity.
Commands will have string to invoke.
Remote ports will have the values of the remote hostname and port number.
Unix domain sockets will have the path to the socket.
Noop consoles will have nothing.
.RE
.TP
.B \-u

View File

@ -1,5 +1,5 @@
/*
* $Id: convert.c,v 1.10 2004/05/28 01:08:28 bryan Exp $
* $Id: convert.c,v 1.12 2006/04/07 15:47:20 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -86,7 +86,7 @@ ReadLine2(fp, save, iLine)
|| peek) {
/* If we have a previously saved line, use it instead */
if (save->used) {
strcpy(buf, save->string);
StrCpy(buf, save->string, sizeof(buf));
BuildString((char *)0, save);
}

View File

@ -1,5 +1,5 @@
/*
* $Id: cutil.c,v 1.125 2006/01/15 17:10:14 bryan Exp $
* $Id: cutil.c,v 1.130 2006/04/07 15:47:20 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -9,6 +9,7 @@
#include <compat.h>
#include <cutil.h>
#include <version.h>
#include <net/if.h>
#if HAVE_SYS_SOCKIO_H
@ -84,7 +85,7 @@ StrTime(ltime)
time_t tyme;
tyme = time((time_t *)0);
strcpy(curtime, ctime(&tyme));
StrCpy(curtime, ctime(&tyme), sizeof(curtime));
curtime[24] = '\000'; /* might need to adjust this at some point */
if (ltime != NULL)
*ltime = tyme;
@ -424,7 +425,7 @@ ReadLine(fp, save, iLine)
|| peek) {
/* If we have a previously saved line, use it instead */
if (save->used) {
strcpy(buf, save->string);
StrCpy(buf, save->string, sizeof(buf));
BuildString((char *)0, save);
}
@ -2290,6 +2291,21 @@ ProbeInterfaces(bindAddr)
if (sa->sa_family == AF_INET) {
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
/* make sure the address isn't 0.0.0.0, which is how we
* signal the end of our list
*/
if (
#if HAVE_MEMCMP
memcmp(&(myAddrs[m]), &(sin->sin_addr),
sizeof(struct in_addr))
#else
bcmp(&(myAddrs[m]), &(sin->sin_addr),
sizeof(struct in_addr))
#endif
== 0)
continue;
#ifdef SIOCGIFFLAGS
/* make sure the interface is up */
ifrcopy = *ifr;
@ -2297,13 +2313,16 @@ ProbeInterfaces(bindAddr)
((ifrcopy.ifr_flags & IFF_UP) == 0))
continue;
#endif
CONDDEBUG((1, "ProbeInterfaces(): name=%s addr=%s",
ifr->ifr_name, inet_ntoa(sin->sin_addr)));
#if HAVE_MEMCPY
memcpy(&myAddrs[m], &(sin->sin_addr), sizeof(struct in_addr));
#else
bcopy(&(sin->sin_addr), &myAddrs[m], sizeof(struct in_addr));
#endif
Verbose("interface address %s (%s)", inet_ntoa(myAddrs[m]),
ifr->ifr_name);
m++;
@ -2508,10 +2527,10 @@ SetFlags(fd, s, c)
char *
#if PROTOTYPES
StrDup(char *msg)
StrDup(const char *msg)
#else
StrDup(msg)
char *msg;
const char *msg;
#endif
{
int len;
@ -3163,6 +3182,11 @@ ProcessSubst(s, repl, str, name, id)
REP_END
} state;
if (s == (SUBST *)0) {
Error("ProcessSubst(): WTF? No substitute support structure?!?!");
Bye(EX_SOFTWARE);
}
if (str != (char **)0) {
if (*str != (char *)0) {
free(*str);
@ -3204,7 +3228,7 @@ ProcessSubst(s, repl, str, name, id)
break;
case REP_EQ:
repfmt[repnum] = p;
if (s->tokens[(unsigned)(*(repfmt[repnum]))] != ISNOTHING)
if (s->token(*(repfmt[repnum])) != ISNOTHING)
state = REP_INT;
else
goto subst_err;
@ -3212,13 +3236,11 @@ ProcessSubst(s, repl, str, name, id)
case REP_INT:
if (*p == 'd' || *p == 'x' || *p == 'X' || *p == 'a' ||
*p == 'A') {
if (s->tokens[(unsigned)(*(repfmt[repnum]))] !=
ISNUMBER)
if (s->token(*(repfmt[repnum])) != ISNUMBER)
goto subst_err;
state = REP_END;
} else if (*p == 's') {
if (s->tokens[(unsigned)(*(repfmt[repnum]))] !=
ISSTRING)
if (s->token(*(repfmt[repnum])) != ISSTRING)
goto subst_err;
state = REP_END;
} else if (!isdigit((int)(*p)))
@ -3246,7 +3268,7 @@ ProcessSubst(s, repl, str, name, id)
OutOfMem();
}
if (s != (SUBST *)0 && repl != (char **)0) {
if (s != (SUBST *)0 && repl != (char **)0 && *repl != (char *)0) {
static STRING *result = (STRING *)0;
if (result == (STRING *)0)
@ -3260,13 +3282,13 @@ ProcessSubst(s, repl, str, name, id)
char *c = (char *)0;
int o = 0;
if (s->tokens[(unsigned)(*r)] == ISSTRING) {
if (s->token(*r) == ISSTRING) {
/* check the pattern for a length */
if (isdigit((int)(*(r + 1))))
plen = atoi(r + 1);
/* this should never return zero, but just in case */
if ((*s->callback) (*r, &c, (int *)0) == 0)
if ((*s->value) (*r, &c, (int *)0) == 0)
c = "";
plen -= strlen(c);
@ -3288,7 +3310,7 @@ ProcessSubst(s, repl, str, name, id)
BuildString((char *)0, num);
/* this should never return zero, but just in case */
if ((*s->callback) (*r, (char **)0, &i) == 0)
if ((*s->value) (*r, (char **)0, &i) == 0)
port = 0;
else
port = (unsigned short)i;
@ -3365,3 +3387,54 @@ ProcessSubst(s, repl, str, name, id)
return;
}
char *
#if PROTOTYPES
MyVersion(void)
#else
MyVersion()
#endif
{
static STRING *version = (STRING *)0;
if (version != (STRING *)0)
return version->string;
version = AllocString();
BuildStringPrint(version, "%s %d.%d.%d", VERSION_TEXT, VERSION_MAJOR,
VERSION_MINOR, VERSION_REV);
return version->string;
}
unsigned int
#if PROTOTYPES
AtoU(char *str)
#else
AtoU(c)
char *str;
#endif
{
unsigned int v;
int i;
v = 0;
for (i = 0; isdigit((int)str[i]); i++) {
v *= 10;
v += str[i] - '0';
}
return v;
}
void
#if PROTOTYPES
StrCpy(char *dst, const char *src, unsigned int size)
#else
StrCpy(dst, src, size)
char *dst;
const char *src;
unsigned int size;
#endif
{
#ifdef HAVE_STRLCPY
strlcpy(dst, src, size);
#else
strcpy(dst, src);
#endif
}

View File

@ -1,5 +1,5 @@
/*
* $Id: cutil.h,v 1.64 2006/01/15 17:10:14 bryan Exp $
* $Id: cutil.h,v 1.68 2006/04/07 15:47:20 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -111,14 +111,16 @@ typedef enum substToken {
} SUBSTTOKEN;
typedef struct subst {
SUBSTTOKEN tokens[255];
/* function to retrieve a token type based on a character
*/
SUBSTTOKEN (*token) PARAMS((char));
/* data for callback function
*/
void *data;
/* function to retrieve a value (as a char* or int or both) for
* a substitution
*/
int (*callback) PARAMS((char, char **, int *));
int (*value) PARAMS((char, char **, int *));
} SUBST;
extern int isMultiProc, fDebug, fVerbose, fErrorPrinted;
@ -189,7 +191,7 @@ extern int FileCanRead PARAMS((CONSFILE *, fd_set *, fd_set *));
extern int FileCanWrite PARAMS((CONSFILE *, fd_set *, fd_set *));
extern int FileBufEmpty PARAMS((CONSFILE *));
extern int SetFlags PARAMS((int, int, int));
extern char *StrDup PARAMS((char *));
extern char *StrDup PARAMS((const char *));
extern int ParseIACBuf PARAMS((CONSFILE *, void *, int *));
extern void *MemMove PARAMS((void *, void *, size_t));
extern char *StringChar PARAMS((STRING *, int, char));
@ -197,6 +199,9 @@ extern void ParseFile PARAMS((char *, FILE *, int));
extern void ProbeInterfaces PARAMS((in_addr_t));
extern void ProcessSubst
PARAMS((SUBST *, char **, char **, char *, char *));
extern char *MyVersion PARAMS((void));
extern unsigned int AtoU PARAMS((char *));
extern void StrCpy PARAMS((char *, const char *, unsigned int));
#if HAVE_OPENSSL
extern SSL *FileGetSSL PARAMS((CONSFILE *));
extern void FileSetSSL PARAMS((CONSFILE *, SSL *));

View File

@ -1,5 +1,5 @@
/*
* $Id: group.c,v 5.319 2005/11/28 20:46:08 bryan Exp $
* $Id: group.c,v 5.325 2006/04/07 15:47:20 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -68,10 +68,10 @@
#include <client.h>
#include <access.h>
#include <group.h>
#include <version.h>
#include <readcfg.h>
#include <master.h>
#include <main.h>
#include <version.h>
#if HAVE_PAM
#include <security/pam_appl.h>
@ -419,8 +419,6 @@ DestroyClient(pCL)
DestroyString(pCL->peername);
if (pCL->accmd != (STRING *)0)
DestroyString(pCL->accmd);
if (pCL->msg != (STRING *)0)
DestroyString(pCL->msg);
if (pCL->username != (STRING *)0)
DestroyString(pCL->username);
FileClose(&pCL->fd);
@ -2085,6 +2083,16 @@ CommandExamine(pGE, pCLServing, pCEServing, tyme, args)
b = "Netwk";
p = ' ';
break;
case NOOP:
d = "NOOP";
b = "NOOP";
p = ' ';
break;
case UDS:
d = pCE->uds;
b = "UDS";
p = ' ';
break;
case UNKNOWNTYPE: /* shut up gcc */
break;
}
@ -2259,26 +2267,34 @@ CommandInfo(pGE, pCLServing, pCEServing, tyme, args)
myHostname, (unsigned long)thepid, pGE->port);
switch (pCE->type) {
case EXEC:
FilePrint(pCLServing->fd, FLAGTRUE, "|:%s,%lu,%s",
FilePrint(pCLServing->fd, FLAGTRUE, "|:%s,%lu,%s,%d:",
(pCE->exec != (char *)0 ? pCE->exec : "/bin/sh"),
(unsigned long)pCE->ipid, pCE->execSlave);
(unsigned long)pCE->ipid, pCE->execSlave,
FileFDNum(pCE->cofile));
break;
case HOST:
FilePrint(pCLServing->fd, FLAGTRUE, "!:%s,%hu,%s",
FilePrint(pCLServing->fd, FLAGTRUE, "!:%s,%hu,%s,%d:",
pCE->host, pCE->netport,
(pCE->raw == FLAGTRUE ? "raw" : "telnet"));
(pCE->raw == FLAGTRUE ? "raw" : "telnet"),
FileFDNum(pCE->cofile));
break;
case NOOP:
FileWrite(pCLServing->fd, FLAGTRUE, "#::", 3);
break;
case UDS:
FilePrint(pCLServing->fd, FLAGTRUE, "%%:%s,%d:", pCE->uds,
FileFDNum(pCE->cofile));
break;
case DEVICE:
FilePrint(pCLServing->fd, FLAGTRUE, "/:%s,%s%c",
FilePrint(pCLServing->fd, FLAGTRUE, "/:%s,%s%c,%d:",
pCE->device,
(pCE->baud ? pCE->baud->acrate : ""),
(pCE->parity ? pCE->parity->key[0] : ' '));
(pCE->parity ? pCE->parity->key[0] : ' '),
FileFDNum(pCE->cofile));
break;
case UNKNOWNTYPE: /* shut up gcc */
break;
}
FilePrint(pCLServing->fd, FLAGTRUE, ",%d:",
FileFDNum(pCE->cofile));
if (pCE->pCLwr) {
FilePrint(pCLServing->fd, FLAGTRUE, "w@%s@%ld",
pCE->pCLwr->acid->string,
@ -2351,6 +2367,8 @@ CommandInfo(pGE, pCLServing, pCEServing, tyme, args)
s = BuildTmpString(",autoreinit");
if (pCE->unloved == FLAGTRUE)
s = BuildTmpString(",unloved");
if (pCE->login == FLAGTRUE)
s = BuildTmpString(",login");
FilePrint(pCLServing->fd, FLAGFALSE, ":%s:%s:%d:%s\r\n",
(s == (char *)0 ? "" : s + 1),
(pCE->initcmd == (char *)0 ? "" : pCE->initcmd),
@ -2797,6 +2815,52 @@ Challenge()
return n[cnt];
}
/* This routine is used to gather input from the
* client and save it in the accmd string.
* GatherLine returns 0 until the user signals
* they're "done" (a \r), then it returns 1.
*/
typedef enum gatherType {
G_INT,
G_TEXT
} GATHERTYPE;
int
#if PROTOTYPES
GatherLine(char c, int limit, GATHERTYPE g, CONSCLIENT *pCL)
#else
GatherLine(c, pCL)
char c;
GATHERTYPE g;
CONSCLIENT *pCL;
#endif
{
if (c == '\r')
return 1;
if ((limit <= 0 || pCL->accmd->used - 1 < limit) &&
((g == G_TEXT && (c == '\a' || (c >= ' ' && c <= '~'))) ||
(g == G_INT && isdigit((int)c)))) {
BuildStringChar(c, pCL->accmd);
FileWrite(pCL->fd, FLAGFALSE, (char *)&c, 1);
} else if ((c == '\b' || c == 0x7f)
&& pCL->accmd->used > 1) {
if (pCL->accmd->string[pCL->accmd->used - 2] != '\a')
FileWrite(pCL->fd, FLAGFALSE, "\b \b", 3);
pCL->accmd->string[pCL->accmd->used - 2] = '\000';
pCL->accmd->used--;
} else if ((c == 0x15) && pCL->accmd->used > 1) {
while (pCL->accmd->used > 1) {
if (pCL->accmd->string[pCL->accmd->used - 2] != '\a')
FileWrite(pCL->fd, FLAGFALSE, "\b \b", 3);
pCL->accmd->string[pCL->accmd->used - 2] = '\000';
pCL->accmd->used--;
}
}
return 0;
}
void
#if PROTOTYPES
DoClientRead(GRPENT *pGE, CONSCLIENT *pCLServing)
@ -3027,6 +3091,21 @@ DoClientRead(pGE, pCLServing)
return;
}
if (pCEwant->login != FLAGTRUE) {
if (pCEwant->motd == (char *)0) {
FilePrint(pCLServing->fd, FLAGFALSE,
"%s: no logins allowed at this time\r\n",
pcArgs);
} else {
FilePrint(pCLServing->fd, FLAGFALSE,
"%s: %s\r\n", pcArgs,
pCEwant->motd);
}
DisconnectClient(pGE, pCLServing, (char *)0,
FLAGFALSE);
return;
}
/* remove from current host */
if ((CONSCLIENT *)0 != pCLServing->pCLnext) {
pCLServing->pCLnext->ppCLbnext =
@ -3188,55 +3267,67 @@ DoClientRead(pGE, pCLServing)
case S_PASSWD:
/* these are not used in this mode */
break;
case S_BCAST:
/* gather message */
if ('\r' != acIn[i]) {
if (acIn[i] == '\a' ||
(acIn[i] >= ' ' && acIn[i] <= '~')) {
BuildStringChar(acIn[i], pCLServing->msg);
if (pGE->pCEctl != pCEServing)
FileWrite(pCLServing->fd, FLAGFALSE,
(char *)&acIn[i], 1);
} else if ((acIn[i] == '\b' || acIn[i] == 0x7f)
&& pCLServing->msg->used > 1) {
if (pCLServing->msg->
string[pCLServing->msg->used - 2] !=
'\a' && pGE->pCEctl != pCEServing) {
FileWrite(pCLServing->fd, FLAGFALSE,
"\b \b", 3);
}
pCLServing->msg->string[pCLServing->msg->
used - 2] = '\000';
pCLServing->msg->used--;
} else if ((acIn[i] == 0x15) &&
pCLServing->msg->used > 1) {
while (pCLServing->msg->used > 1) {
if (pCLServing->msg->
string[pCLServing->msg->used -
2] != '\a' &&
pGE->pCEctl != pCEServing) {
FileWrite(pCLServing->fd,
FLAGFALSE, "\b \b", 3);
}
pCLServing->msg->string[pCLServing->
msg->used -
2] = '\000';
pCLServing->msg->used--;
}
}
continue;
}
FileWrite(pCLServing->fd, FLAGFALSE, "]\r\n", 3);
if (GatherLine(acIn[i], 0, G_TEXT, pCLServing)) {
FileWrite(pCLServing->fd, FLAGFALSE, "]\r\n",
3);
BuildString((char *)0, bcast);
BuildStringChar('[', bcast);
BuildString(pCLServing->acid->string, bcast);
BuildString(": ", bcast);
BuildString(pCLServing->msg->string, bcast);
BuildString(pCLServing->accmd->string, bcast);
BuildString("]\r\n", bcast);
SendClientsMsg(pCEServing, bcast->string);
BuildString((char *)0, pCLServing->msg);
BuildString((char *)0, pCLServing->accmd);
pCLServing->iState = S_NORMAL;
}
continue;
case S_REPLAY:
case S_PLAYBACK:
if (GatherLine(acIn[i], 4, G_INT, pCLServing)) {
unsigned short *s;
if (pCLServing->iState == S_REPLAY)
s = &(pCLServing->replay);
else
s = &(pCLServing->playback);
if (pCLServing->accmd->used > 1) {
unsigned short u;
u = (unsigned short)atoi(pCLServing->
accmd->string);
/* i'm limiting the value here to 10000 for a couple
* of reasons:
*
* 1. this process could be busy parsing a file for
* a long time if the logfile and replay are big.
* 2. who needs more than 10000 lines of replay? if
* you need that much, go find the raw logfile.
* and if you don't have access, find someone who
* does.
*
* change this to something bigger if you want, but
* it would scare me...even 10000 seems a bit large,
* but no one *has* to set the value so large.
* and watch out...it's an unsigned short, so you
* can't go really huge.
*/
if (u > 10000)
FileWrite(pCLServing->fd, FLAGFALSE,
" <value too large>", 18);
else
*s = u;
} else
FilePrint(pCLServing->fd, FLAGFALSE, "%u",
*s);
FileWrite(pCLServing->fd, FLAGFALSE, "]\r\n",
3);
pCLServing->iState = S_NORMAL;
}
continue;
case S_QUOTE: /* send octal code */
@ -3486,53 +3577,39 @@ DoClientRead(pGE, pCLServing)
"no drop line]\r\n", -1);
break;
#define DEPRECATED FileWrite(pCLServing->fd, FLAGFALSE, "<use of DEPRECATED (and undocumented) key> ", -1)
case 'B':
DEPRECATED;
case 'b': /* broadcast message */
FileWrite(pCLServing->fd, FLAGFALSE,
"Enter message: ", -1);
pCLServing->iState = S_BCAST;
break;
case 'A':
DEPRECATED;
case 'a': /* attach */
CommandAttach(pGE, pCLServing, pCEServing,
tyme);
break;
case 'C':
DEPRECATED;
case 'b': /* broadcast message */
FileWrite(pCLServing->fd, FLAGFALSE,
"Enter message: ", -1);
BuildString((char *)0, pCLServing->accmd);
pCLServing->iState = S_BCAST;
break;
case 'c':
CommandChangeFlow(pGE, pCLServing,
pCEServing, tyme);
break;
case 'D':
DEPRECATED;
case 'd': /* down a console */
CommandDown(pGE, pCLServing, pCEServing,
tyme);
break;
case 'E':
DEPRECATED;
case 'e': /* redefine escape keys */
pCLServing->iState = S_CATTN;
FileWrite(pCLServing->fd, FLAGFALSE,
"redef: ", -1);
break;
case 'F':
DEPRECATED;
case 'f': /* force attach */
CommandForce(pGE, pCLServing, pCEServing,
tyme);
break;
case 'G':
DEPRECATED;
case 'g': /* group info */
FilePrint(pCLServing->fd, FLAGFALSE,
"group %s]\r\n",
@ -3541,16 +3618,11 @@ DoClientRead(pGE, pCLServing)
tyme, (char *)0);
break;
case 'H':
case 'P': /* DEC vt100 pf1 */
DEPRECATED;
case 'h': /* help */
case '?':
HelpUser(pCLServing);
break;
case 'I':
DEPRECATED;
case 'i':
FileWrite(pCLServing->fd, FLAGFALSE,
"info]\r\n", -1);
@ -3585,35 +3657,47 @@ DoClientRead(pGE, pCLServing)
pCEServing->motd);
break;
case 'O':
DEPRECATED;
case 'o': /* close and re-open line */
CommandOpen(pGE, pCLServing, pCEServing,
tyme);
break;
case 'P': /* broadcast message */
FilePrint(pCLServing->fd, FLAGFALSE,
"set playback (%d): ",
pCLServing->playback);
BuildString((char *)0, pCLServing->accmd);
pCLServing->iState = S_PLAYBACK;
break;
case 'p': /* replay lines (longer, in theory) */
FileWrite(pCLServing->fd, FLAGFALSE,
"playback]\r\n", -1);
Replay(pCEServing, pCLServing->fd,
pCLServing->playback);
break;
case '\022': /* ^R */
FileWrite(pCLServing->fd, FLAGFALSE,
"^R]\r\n", -1);
Replay(pCEServing, pCLServing->fd, 1);
break;
case 'R': /* DEC vt100 pf3 */
DEPRECATED;
case 'r': /* replay 20 lines */
case 'R': /* broadcast message */
FilePrint(pCLServing->fd, FLAGFALSE,
"set replay (%d): ",
pCLServing->replay);
BuildString((char *)0, pCLServing->accmd);
pCLServing->iState = S_REPLAY;
break;
case 'r': /* replay lines */
FileWrite(pCLServing->fd, FLAGFALSE,
"replay]\r\n", -1);
Replay(pCEServing, pCLServing->fd, 20);
Replay(pCEServing, pCLServing->fd,
pCLServing->replay);
break;
case 'p': /* replay 60 lines */
FileWrite(pCLServing->fd, FLAGFALSE,
"long replay]\r\n", -1);
Replay(pCEServing, pCLServing->fd, 60);
break;
case 'S': /* DEC vt100 pf4 */
DEPRECATED;
case 's': /* spy mode */
pCLServing->fwantwr = 0;
if (!pCLServing->fwr) {
@ -3629,8 +3713,6 @@ DoClientRead(pGE, pCLServing)
"spying]\r\n", -1);
break;
case 'U':
DEPRECATED;
case 'u': /* hosts on server this */
FileWrite(pCLServing->fd, FLAGFALSE,
"hosts]\r\n", -1);
@ -3638,16 +3720,12 @@ DoClientRead(pGE, pCLServing)
tyme, (char *)0);
break;
case 'V':
DEPRECATED;
case 'v': /* version */
FilePrint(pCLServing->fd, FLAGFALSE,
"version `%s']\r\n",
THIS_VERSION);
MyVersion());
break;
case 'W':
DEPRECATED;
case 'w': /* who */
FilePrint(pCLServing->fd, FLAGFALSE,
"who %s]\r\n",
@ -3656,8 +3734,6 @@ DoClientRead(pGE, pCLServing)
tyme);
break;
case 'X':
DEPRECATED;
case 'x':
FileWrite(pCLServing->fd, FLAGFALSE,
"examine]\r\n", -1);
@ -3665,27 +3741,6 @@ DoClientRead(pGE, pCLServing)
tyme, (char *)0);
break;
case '|': /* wait for client */
if (ConsentUserOk
(pLUList,
pCLServing->username->string) == 1)
goto unknownchar;
if (!pCLServing->fwr) {
FileWrite(pCLServing->fd, FLAGFALSE,
"attach to run local command]\r\n",
-1);
continue;
}
FileSetQuoteIAC(pCLServing->fd, FLAGFALSE);
FilePrint(pCLServing->fd, FLAGFALSE,
"%c%c", OB_IAC, OB_EXEC);
FileSetQuoteIAC(pCLServing->fd, FLAGTRUE);
pCLServing->fcon = 0;
pCLServing->iState = S_CWAIT;
break;
case 'Z':
DEPRECATED;
case 'z': /* suspend the client */
case '\032':
if (ConsentUserOk
@ -3709,6 +3764,25 @@ DoClientRead(pGE, pCLServing)
}
break;
case '|': /* wait for client */
if (ConsentUserOk
(pLUList,
pCLServing->username->string) == 1)
goto unknownchar;
if (!pCLServing->fwr) {
FileWrite(pCLServing->fd, FLAGFALSE,
"attach to run local command]\r\n",
-1);
continue;
}
FileSetQuoteIAC(pCLServing->fd, FLAGFALSE);
FilePrint(pCLServing->fd, FLAGFALSE,
"%c%c", OB_IAC, OB_EXEC);
FileSetQuoteIAC(pCLServing->fd, FLAGTRUE);
pCLServing->fcon = 0;
pCLServing->iState = S_CWAIT;
break;
case '\t': /* toggle tab expand */
if (!pCLServing->fwr) {
FileWrite(pCLServing->fd, FLAGFALSE,
@ -3730,15 +3804,12 @@ DoClientRead(pGE, pCLServing)
"failed]\r\n", -1);
continue;
}
# if !defined(XTABS) /* XXX hack */
# define XTABS TAB3
# endif
if (XTABS == (TABDLY & sbuf.c_oflag)) {
if (TAB3 == (TABDLY & sbuf.c_oflag)) {
sbuf.c_oflag &= ~TABDLY;
sbuf.c_oflag |= TAB0;
} else {
sbuf.c_oflag &= ~TABDLY;
sbuf.c_oflag |= XTABS;
sbuf.c_oflag |= TAB3;
}
if (-1 ==
tcsetattr(FileFDNum
@ -3748,7 +3819,7 @@ DoClientRead(pGE, pCLServing)
"failed]\r\n", -1);
continue;
}
if (XTABS == (TABDLY & sbuf.c_oflag))
if (TAB3 == (TABDLY & sbuf.c_oflag))
FileWrite(pCLServing->fd, FLAGFALSE,
"tabs OFF]\r\n", -1);
else
@ -3756,8 +3827,6 @@ DoClientRead(pGE, pCLServing)
"tabs ON]\r\n", -1);
break;
case 'Q': /* DEC vt100 PF2 */
DEPRECATED;
case '.': /* disconnect */
case '\004':
case '\003':
@ -3793,6 +3862,17 @@ DoClientRead(pGE, pCLServing)
"quote \\", -1);
break;
case 0xD6: /* 'v' with high bit set */
/* this is really just used "behind the scenes",
* but of someone wants to type it, fine...we
* just need a way to query the server for what
* version it is so the client can determine
* functionality
*/
FilePrint(pCLServing->fd, FLAGFALSE,
"%u]\r\n", VERSION_UINT);
break;
default: /* unknown sequence */
unknownchar:
#if USE_EXTENDED_MESSAGES
@ -4190,7 +4270,6 @@ Kiddie(pGE, sfd)
pGE->pCLfree->username = AllocString();
pGE->pCLfree->peername = AllocString();
pGE->pCLfree->accmd = AllocString();
pGE->pCLfree->msg = AllocString();
/* on a SIGHUP we should close and reopen our log files and
* reread the config file
@ -4385,7 +4464,7 @@ Kiddie(pGE, sfd)
/* anything on a console? */
for (pCEServing = pGE->pCElist; pCEServing != (CONSENT *)0;
pCEServing = pCEServing->pCEnext) {
if (!pCEServing->fup)
if (!pCEServing->fup || pCEServing->type == NOOP)
continue;
switch (pCEServing->ioState) {
case INCONNECT:
@ -4630,7 +4709,7 @@ Kiddie(pGE, sfd)
BuildString("<unknown>@", pCL->acid);
BuildString((char *)0, pCL->username);
BuildString("<unknown>", pCL->username);
strcpy(pCL->actym, StrTime(&(pCL->tym)));
StrCpy(pCL->actym, StrTime(&(pCL->tym)), sizeof(pCL->actym));
pCL->typetym = pCL->tym;
/* link into the control list for the dummy console
@ -4662,6 +4741,8 @@ Kiddie(pGE, sfd)
pCL->iState = S_IDENT;
pCL->ic[0] = DEFATTN;
pCL->ic[1] = DEFESC;
pCL->replay = DEFREPLAY;
pCL->playback = DEFPLAYBACK;
BuildString((char *)0, pCL->accmd);
/* mark as stopped (no output from console)
@ -4683,7 +4764,6 @@ Kiddie(pGE, sfd)
pGE->pCLfree->username = AllocString();
pGE->pCLfree->peername = AllocString();
pGE->pCLfree->accmd = AllocString();
pGE->pCLfree->msg = AllocString();
}
if (ClientAccessOk(pCL)) {
@ -4741,7 +4821,8 @@ Spawn(pGE, msfd)
Error("Spawn(): path to socket too long: %s", portPath->string);
Bye(EX_OSERR);
}
strcpy(lstn_port.sun_path, portPath->string);
StrCpy(lstn_port.sun_path, portPath->string,
sizeof(lstn_port.sun_path));
/* create a socket to listen on
* (prepared by master so he can see the port number of the kid)

View File

@ -1,5 +1,5 @@
/*
* $Id: group.h,v 5.48 2005/05/21 17:56:14 bryan Exp $
* $Id: group.h,v 5.49 2006/04/07 15:36:09 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -82,6 +82,7 @@ extern void DestroyClient PARAMS((CONSCLIENT *));
extern int CheckPasswd PARAMS((CONSCLIENT *, char *));
extern void DeUtmp PARAMS((GRPENT *, int));
extern void ClientWantsWrite PARAMS((CONSCLIENT *));
extern void SendIWaitClientsMsg PARAMS((CONSENT *, char *));
#if HAVE_OPENSSL
extern int AttemptSSL PARAMS((CONSCLIENT *));
#endif

View File

@ -1,5 +1,5 @@
/*
* $Id: main.c,v 5.196 2005/06/11 02:31:05 bryan Exp $
* $Id: main.c,v 5.200 2006/04/03 13:32:08 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -418,8 +418,8 @@ ReopenLogfile()
close(2);
dup(1);
if (isMaster && tag) {
Msg("%s", THIS_VERSION);
Msg("%s", startedMsg->string);
Msg(MyVersion());
Msg(startedMsg->string);
}
tag = 0;
}
@ -619,7 +619,7 @@ Version()
isMultiProc = 0;
Msg("%s", THIS_VERSION);
Msg(MyVersion());
Msg("default access type `%c'", defConfig.defaultaccess);
Msg("default escape sequence `%s%s'", FmtCtl(DEFATTN, acA1),
FmtCtl(DEFESC, acA2));
@ -913,6 +913,18 @@ DumpDataStructures()
EMPTYSTR(pCE->host), FLAGSTR(pCE->raw),
pCE->netport, pCE->port, pCE->telnetState));
break;
case NOOP:
CONDDEBUG((1,
"DumpDataStructures(): server=%s, type=NOOP",
EMPTYSTR(pCE->server)));
break;
case UDS:
CONDDEBUG((1,
"DumpDataStructures(): server=%s, type=UDS",
EMPTYSTR(pCE->server)));
CONDDEBUG((1, "DumpDataStructures(): uds=%s",
EMPTYSTR(pCE->uds)));
break;
case UNKNOWNTYPE:
CONDDEBUG((1,
"DumpDataStructures(): server=%s, type=UNKNOWNTYPE",
@ -953,8 +965,8 @@ DumpDataStructures()
CONDDEBUG((1,
"DumpDataStructures(): reinitoncc=%s, striphigh=%s",
FLAGSTR(pCE->reinitoncc), FLAGSTR(pCE->striphigh)));
CONDDEBUG((1, "DumpDataStructures(): unloved=%s",
FLAGSTR(pCE->unloved)));
CONDDEBUG((1, "DumpDataStructures(): unloved=%s, login=%s",
FLAGSTR(pCE->unloved), FLAGSTR(pCE->login)));
CONDDEBUG((1,
"DumpDataStructures(): initpid=%lu, initcmd=%s, initfile=%d",
(unsigned long)pCE->initpid, EMPTYSTR(pCE->initcmd),
@ -1272,7 +1284,7 @@ main(argc, argv)
Bye(EX_OK);
}
Msg("%s", THIS_VERSION);
Msg(MyVersion());
#if HAVE_GETLOGIN
origuser = getlogin();

View File

@ -1,5 +1,5 @@
/*
* $Id: master.c,v 5.132 2005/09/05 22:22:53 bryan Exp $
* $Id: master.c,v 5.135 2006/04/07 15:47:20 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -36,7 +36,6 @@
#include <access.h>
#include <master.h>
#include <readcfg.h>
#include <version.h>
#include <main.h>
@ -615,7 +614,7 @@ DoNormalRead(pCLServing)
} else if (pCLServing->iState == S_NORMAL &&
strcmp(pcCmd, "version") == 0) {
FilePrint(pCLServing->fd, FLAGFALSE, "version `%s'\r\n",
THIS_VERSION);
MyVersion());
} else if (pCLServing->iState == S_NORMAL &&
strcmp(pcCmd, "quit") == 0) {
if (ConsentUserOk(pADList, pCLServing->username->string) ==
@ -784,7 +783,8 @@ Master()
Error("Master(): path to socket too long: %s", portPath->string);
return;
}
strcpy(master_port.sun_path, portPath->string);
StrCpy(master_port.sun_path, portPath->string,
sizeof(master_port.sun_path));
if ((msfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
Error("Master(): socket(AF_UNIX,SOCK_STREAM): %s",

View File

@ -1,5 +1,5 @@
/*
* $Id: readcfg.c,v 5.189 2005/09/05 21:55:49 bryan Exp $
* $Id: readcfg.c,v 5.192 2006/03/20 16:47:03 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -567,6 +567,10 @@ DestroyParserDefaultOrConsole(c, ph, pt)
free(c->server);
if (c->host != (char *)0)
free(c->host);
if (c->uds != (char *)0)
free(c->uds);
if (c->udssubst != (char *)0)
free(c->udssubst);
if (c->master != (char *)0)
free(c->master);
if (c->exec != (char *)0)
@ -693,12 +697,26 @@ ApplyDefault(d, c)
c->autoreinit = d->autoreinit;
if (d->unloved != FLAGUNKNOWN)
c->unloved = d->unloved;
if (d->login != FLAGUNKNOWN)
c->login = d->login;
if (d->host != (char *)0) {
if (c->host != (char *)0)
free(c->host);
if ((c->host = StrDup(d->host)) == (char *)0)
OutOfMem();
}
if (d->uds != (char *)0) {
if (c->uds != (char *)0)
free(c->uds);
if ((c->uds = StrDup(d->uds)) == (char *)0)
OutOfMem();
}
if (d->udssubst != (char *)0) {
if (c->udssubst != (char *)0)
free(c->udssubst);
if ((c->udssubst = StrDup(d->udssubst)) == (char *)0)
OutOfMem();
}
if (d->master != (char *)0) {
if (c->master != (char *)0)
free(c->master);
@ -953,9 +971,9 @@ SUBST *substData = (SUBST *)0;
int
#if PROTOTYPES
SubstCallback(char c, char **s, int *i)
SubstValue(char c, char **s, int *i)
#else
SubstCallback(c, s, i)
SubstValue(c, s, i)
char c;
char **s;
int *i;
@ -963,16 +981,6 @@ SubstCallback(c, s, i)
{
int retval = 0;
if (substData == (SUBST *)0) {
if ((substData = (SUBST *)calloc(1, sizeof(SUBST))) == (SUBST *)0)
OutOfMem();
substData->callback = &SubstCallback;
substData->tokens['p'] = ISNUMBER;
substData->tokens['P'] = ISNUMBER;
substData->tokens['h'] = ISSTRING;
substData->tokens['c'] = ISSTRING;
}
if (s != (char **)0) {
CONSENT *pCE;
if (substData->data == (void *)0)
@ -1005,6 +1013,71 @@ SubstCallback(c, s, i)
return retval;
}
int substTokenCount[255];
int
#if PROTOTYPES
SubstTokenCount(char c)
#else
SubstTokenCount(c)
char c;
#endif
{
return substTokenCount[(unsigned)c];
}
void
#if PROTOTYPES
ZeroSubstTokenCount(void)
#else
ZeroSubstTokenCount()
#endif
{
#if HAVE_MEMSET
memset((void *)&substTokenCount, 0, sizeof(substTokenCount));
#else
bzero((char *)&substTokenCount, sizeof(substTokenCount));
#endif
}
SUBSTTOKEN
#if PROTOTYPES
SubstToken(char c)
#else
SubstToken(c)
char c;
#endif
{
switch (c) {
case 'p':
case 'P':
substTokenCount[(unsigned)c]++;
return ISNUMBER;
case 'h':
case 'c':
substTokenCount[(unsigned)c]++;
return ISSTRING;
default:
return ISNOTHING;
}
}
void
#if PROTOTYPES
InitSubstCallback(void)
#else
InitSubstCallback()
#endif
{
if (substData == (SUBST *)0) {
if ((substData = (SUBST *)calloc(1, sizeof(SUBST))) == (SUBST *)0)
OutOfMem();
substData->value = &SubstValue;
substData->token = &SubstToken;
ZeroSubstTokenCount();
}
}
void
#if PROTOTYPES
DefaultItemDevicesubst(char *id)
@ -1031,6 +1104,19 @@ DefaultItemExecsubst(id)
"execsubst", id);
}
void
#if PROTOTYPES
DefaultItemUdssubst(char *id)
#else
DefaultItemUdssubst(id)
char *id;
#endif
{
CONDDEBUG((1, "DefaultItemUdssubst(%s) [%s:%d]", id, file, line));
ProcessSubst(substData, (char **)0, &(parserDefaultTemp->udssubst),
"udssubst", id);
}
void
#if PROTOTYPES
DefaultItemInitsubst(char *id)
@ -1255,6 +1341,38 @@ DefaultItemHost(id)
ProcessHost(parserDefaultTemp, id);
}
void
#if PROTOTYPES
ProcessUds(CONSENT *c, char *id)
#else
ProcessUds(c, id)
CONSENT *c;
char *id;
#endif
{
if (c->uds != (char *)0) {
free(c->uds);
c->uds = (char *)0;
}
if ((id == (char *)0) || (*id == '\000'))
return;
if ((c->uds = StrDup(id))
== (char *)0)
OutOfMem();
}
void
#if PROTOTYPES
DefaultItemUds(char *id)
#else
DefaultItemUds(id)
char *id;
#endif
{
CONDDEBUG((1, "DefaultItemUds(%s) [%s:%d]", id, file, line));
ProcessUds(parserDefaultTemp, id);
}
void
#if PROTOTYPES
ProcessInclude(CONSENT *c, char *id)
@ -1537,6 +1655,7 @@ ProcessOptions(c, id)
c->reinitoncc = FLAGUNKNOWN;
c->autoreinit = FLAGUNKNOWN;
c->unloved = FLAGUNKNOWN;
c->login = FLAGUNKNOWN;
return;
}
@ -1572,6 +1691,8 @@ ProcessOptions(c, id)
c->autoreinit = negative ? FLAGFALSE : FLAGTRUE;
else if (strcasecmp("unloved", token) == 0)
c->unloved = negative ? FLAGFALSE : FLAGTRUE;
else if (strcasecmp("login", token) == 0)
c->login = negative ? FLAGFALSE : FLAGTRUE;
else if (isMaster)
Error("invalid option `%s' [%s:%d]", token, file, line);
}
@ -2164,6 +2285,10 @@ ProcessType(c, id)
t = EXEC;
else if (strcasecmp("host", id) == 0)
t = HOST;
else if (strcasecmp("noop", id) == 0)
t = NOOP;
else if (strcasecmp("uds", id) == 0)
t = UDS;
if (t == UNKNOWNTYPE) {
if (isMaster)
Error("invalid console type `%s' [%s:%d]", id, file, line);
@ -2222,6 +2347,40 @@ ConsoleBegin(id)
OutOfMem();
}
/* returns 1 if there's an error, otherwise 0 */
int
#if PROTOTYPES
CheckSubst(char *label, char *subst)
#else
CheckSubst(label, subst)
char *label;
char *subst;
#endif
{
int invalid = 0;
ZeroSubstTokenCount();
ProcessSubst(substData, (char **)0, (char **)0, label, subst);
if (SubstTokenCount('p') && parserConsoleTemp->port == 0) {
if (isMaster)
Error
("[%s] console references 'port' in '%s' without defining 'port' attribute (ignoring %s) [%s:%d]",
parserConsoleTemp->server, label, label, file, line);
invalid = 1;
}
if (SubstTokenCount('h') && parserConsoleTemp->host == (char *)0) {
if (isMaster)
Error
("[%s] console references 'host' in '%s' without defining 'host' attribute (ignoring %s) [%s:%d]",
parserConsoleTemp->server, label, label, file, line);
invalid = 1;
}
return invalid;
}
void
#if PROTOTYPES
ConsoleEnd(void)
@ -2245,20 +2404,7 @@ ConsoleEnd()
switch (parserConsoleTemp->type) {
case EXEC:
if (parserConsoleTemp->execsubst != (char *)0) {
if (parserConsoleTemp->port == 0 ||
parserConsoleTemp->host == (char *)0) {
if (parserConsoleTemp->port == 0) {
if (isMaster)
Error
("[%s] console has 'execsubst' attribute without 'port' attribute (ignoring) [%s:%d]",
parserConsoleTemp->server, file, line);
}
if (parserConsoleTemp->host == (char *)0) {
if (isMaster)
Error
("[%s] console has 'execsubst' attribute without 'host' attribute (ignoring) [%s:%d]",
parserConsoleTemp->server, file, line);
}
if (CheckSubst("execsubst", parserConsoleTemp->execsubst)) {
free(parserConsoleTemp->execsubst);
parserConsoleTemp->execsubst = (char *)0;
}
@ -2272,25 +2418,6 @@ ConsoleEnd()
parserConsoleTemp->server, file, line);
invalid = 1;
}
if (parserConsoleTemp->devicesubst != (char *)0) {
if (parserConsoleTemp->port == 0 ||
parserConsoleTemp->host == (char *)0) {
if (parserConsoleTemp->port == 0) {
if (isMaster)
Error
("[%s] console has 'devicesubst' attribute without 'port' attribute (ignoring) [%s:%d]",
parserConsoleTemp->server, file, line);
}
if (parserConsoleTemp->host == (char *)0) {
if (isMaster)
Error
("[%s] console has 'devicesubst' attribute without 'host' attribute (ignoring) [%s:%d]",
parserConsoleTemp->server, file, line);
}
free(parserConsoleTemp->devicesubst);
parserConsoleTemp->devicesubst = (char *)0;
}
}
if (parserConsoleTemp->baud == (BAUD *)0) {
if (isMaster)
Error("[%s] console missing 'baud' attribute [%s:%d]",
@ -2304,6 +2431,13 @@ ConsoleEnd()
parserConsoleTemp->server, file, line);
invalid = 1;
}
if (parserConsoleTemp->devicesubst != (char *)0) {
if (CheckSubst
("devicesubst", parserConsoleTemp->devicesubst)) {
free(parserConsoleTemp->devicesubst);
parserConsoleTemp->devicesubst = (char *)0;
}
}
break;
case HOST:
if (parserConsoleTemp->host == (char *)0) {
@ -2319,6 +2453,22 @@ ConsoleEnd()
invalid = 1;
}
break;
case NOOP:
break;
case UDS:
if (parserConsoleTemp->uds == (char *)0) {
if (isMaster)
Error("[%s] console missing 'uds' attribute [%s:%d]",
parserConsoleTemp->server, file, line);
invalid = 1;
}
if (parserConsoleTemp->udssubst != (char *)0) {
if (CheckSubst("udssubst", parserConsoleTemp->udssubst)) {
free(parserConsoleTemp->udssubst);
parserConsoleTemp->udssubst = (char *)0;
}
}
break;
case UNKNOWNTYPE:
if (isMaster)
Error("[%s] console type unknown [%s:%d]",
@ -2328,20 +2478,7 @@ ConsoleEnd()
}
if (parserConsoleTemp->initsubst != (char *)0 &&
parserConsoleTemp->initcmd != (char *)0) {
if (parserConsoleTemp->port == 0 ||
parserConsoleTemp->host == (char *)0) {
if (parserConsoleTemp->port == 0) {
if (isMaster)
Error
("[%s] console has 'initsubst' attribute without 'port' attribute (ignoring) [%s:%d]",
parserConsoleTemp->server, file, line);
}
if (parserConsoleTemp->host == (char *)0) {
if (isMaster)
Error
("[%s] console has 'initsubst' attribute without 'host' attribute (ignoring) [%s:%d]",
parserConsoleTemp->server, file, line);
}
if (CheckSubst("initsubst", parserConsoleTemp->initsubst)) {
free(parserConsoleTemp->initsubst);
parserConsoleTemp->initsubst = (char *)0;
}
@ -2821,6 +2958,20 @@ ConsoleAdd(c)
closeMatch = 0;
}
break;
case NOOP:
break;
case UDS:
if (pCEmatch->uds != (char *)0 && c->uds != (char *)0) {
if (strcasecmp(pCEmatch->uds, c->uds) != 0) {
SwapStr(&pCEmatch->uds, &c->uds);
closeMatch = 0;
}
} else if (pCEmatch->uds != (char *)0 ||
c->uds != (char *)0) {
SwapStr(&pCEmatch->uds, &c->uds);
closeMatch = 0;
}
break;
case UNKNOWNTYPE:
break;
}
@ -2855,6 +3006,7 @@ ConsoleAdd(c)
pCEmatch->reinitoncc = c->reinitoncc;
pCEmatch->autoreinit = c->autoreinit;
pCEmatch->unloved = c->unloved;
pCEmatch->login = c->login;
pCEmatch->inituid = c->inituid;
pCEmatch->initgid = c->initgid;
while (pCEmatch->aliases != (NAMES *)0) {
@ -2969,7 +3121,9 @@ ConsoleDestroy()
*/
c->netport = c->portbase + c->portinc * c->port;
/* prepare for substitutions */
substData->data = (void *)c;
/* check for substitutions */
if (c->type == DEVICE && c->devicesubst != (char *)0)
ProcessSubst(substData, &(c->device), (char **)0, (char *)0,
@ -2979,6 +3133,10 @@ ConsoleDestroy()
ProcessSubst(substData, &(c->exec), (char **)0, (char *)0,
c->execsubst);
if (c->type == UDS && c->udssubst != (char *)0)
ProcessSubst(substData, &(c->uds), (char **)0, (char *)0,
c->udssubst);
if (c->initcmd != (char *)0 && c->initsubst != (char *)0)
ProcessSubst(substData, &(c->initcmd), (char **)0, (char *)0,
c->initsubst);
@ -3033,6 +3191,14 @@ ConsoleDestroy()
c->striphigh = FLAGFALSE;
if (c->unloved == FLAGUNKNOWN)
c->unloved = FLAGFALSE;
if (c->login == FLAGUNKNOWN)
c->login = FLAGTRUE;
/* set some forced options, based on situations */
if (c->type == NOOP) {
c->login = FLAGFALSE;
ProcessLogfile(c, (char *)0);
}
/* now let command-line args override things */
if (fNoautoreup)
@ -3048,6 +3214,23 @@ ConsoleDestroy()
/* now remember where we're headed and do the dirty work */
cNext = c->pCEnext;
/* perform all post-processing checks */
if (c->type == UDS) {
struct sockaddr_un port;
int limit, len;
limit = sizeof(port.sun_path);
len = strlen(c->uds);
if (len >= limit) {
if (isMaster)
Error("[%s] 'uds' path too large (%d >= %d) [%s:%d]",
c->server, len, limit, file, line);
continue;
}
}
if (fSyntaxOnly > 1) {
static STRING *s = (STRING *)0;
@ -3077,6 +3260,12 @@ ConsoleDestroy()
BuildString(BuildTmpStringPrint
("!:%s,%hu", c->host, c->netport), s);
break;
case NOOP:
BuildString("#:", s);
break;
case UDS:
BuildString(BuildTmpStringPrint("%%:%s", c->uds), s);
break;
case DEVICE:
BuildString(BuildTmpStringPrint
("/:%s,%s%c", c->device,
@ -3299,6 +3488,19 @@ ConsoleItemExecsubst(id)
"execsubst", id);
}
void
#if PROTOTYPES
ConsoleItemUdssubst(char *id)
#else
ConsoleItemUdssubst(id)
char *id;
#endif
{
CONDDEBUG((1, "ConsoleItemUdssubst(%s) [%s:%d]", id, file, line));
ProcessSubst(substData, (char **)0, &(parserConsoleTemp->udssubst),
"udssubst", id);
}
void
#if PROTOTYPES
ConsoleItemInitsubst(char *id)
@ -3372,6 +3574,18 @@ ConsoleItemHost(id)
ProcessHost(parserConsoleTemp, id);
}
void
#if PROTOTYPES
ConsoleItemUds(char *id)
#else
ConsoleItemUds(id)
char *id;
#endif
{
CONDDEBUG((1, "ConsoleItemUds(%s) [%s:%d]", id, file, line));
ProcessUds(parserConsoleTemp, id);
}
void
#if PROTOTYPES
ConsoleItemInclude(char *id)
@ -4621,6 +4835,8 @@ ITEM keyDefault[] = {
{"rw", DefaultItemRw},
{"timestamp", DefaultItemTimestamp},
{"type", DefaultItemType},
{"uds", DefaultItemUds},
{"udssubst", DefaultItemUdssubst},
{(char *)0, (void *)0}
};
@ -4657,6 +4873,8 @@ ITEM keyConsole[] = {
{"rw", ConsoleItemRw},
{"timestamp", ConsoleItemTimestamp},
{"type", ConsoleItemType},
{"uds", ConsoleItemUds},
{"udssubst", ConsoleItemUdssubst},
{(char *)0, (void *)0}
};
@ -4749,7 +4967,7 @@ ReadCfg(filename, fp)
OutOfMem();
/* initialize the substition bits */
SubstCallback('\000', (char **)0, (int *)0);
InitSubstCallback();
/* ready to read in the data */
ParseFile(filename, fp, 0);

View File

@ -1,5 +1,5 @@
/*
* $Id: version.h,v 1.72 2006/01/15 17:10:44 bryan Exp $
* $Id: version.h,v 1.73 2006/04/03 13:32:08 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -14,4 +14,8 @@
@(#) Copyright 2000 conserver.com.\n\
All rights reserved.\n"
#define THIS_VERSION "conserver.com version 8.1.13"
#define VERSION_MAJOR 8
#define VERSION_MINOR 1
#define VERSION_REV 14
#define VERSION_TEXT "conserver.com version"
#define VERSION_UINT (VERSION_MAJOR * 1000000 + VERSION_MINOR * 1000 + VERSION_REV)

View File

@ -1,5 +1,5 @@
/*
* $Id: console.c,v 5.176 2005/09/05 22:34:39 bryan Exp $
* $Id: console.c,v 5.179 2006/04/07 15:47:20 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -33,8 +33,8 @@
#include <getpassword.h>
#include <cutil.h>
#include <version.h>
#include <readconf.h>
#include <version.h>
#if HAVE_OPENSSL
#include <openssl/ssl.h>
#include <openssl/err.h>
@ -58,6 +58,10 @@ char *prevName = (char *)0;
CONFIG *optConf = (CONFIG *)0;
CONFIG *config = (CONFIG *)0;
FLAG interact = FLAGFALSE;
unsigned int sversion = 0;
#if defined(TIOCGWINSZ)
struct winsize ws;
#endif
#if HAVE_OPENSSL
SSL_CTX *ctx = (SSL_CTX *)0;
@ -281,7 +285,7 @@ Version()
if (acA2 == (STRING *)0)
acA2 = AllocString();
Msg("%s", THIS_VERSION);
Msg(MyVersion());
#if USE_UNIX_DOMAIN_SOCKETS
Msg("default socket directory `%s\'", UDSDIR);
#else
@ -473,7 +477,7 @@ GetPort(pcToHost, sPort)
Error("GetPort: path to socket too long: %s", portPath->string);
return (CONSFILE *)0;
}
strcpy(port.sun_path, portPath->string);
StrCpy(port.sun_path, portPath->string, sizeof(port.sun_path));
CONDDEBUG((1, "GetPort: socket=%s", port.sun_path));
@ -624,11 +628,11 @@ DestroyDataStructures()
char *
#if PROTOTYPES
ReadReply(CONSFILE *fd, int toEOF)
ReadReply(CONSFILE *fd, FLAG toEOF)
#else
ReadReply(fd)
ReadReply(fd, toEOF)
CONSFILE *fd;
int toEOF;
FLAG toEOF;
#endif
{
int nr;
@ -646,7 +650,7 @@ ReadReply(fd)
case 0:
/* fall through */
case -1:
if (result->used > 1 || toEOF)
if (result->used > 1 || toEOF == FLAGTRUE)
break;
C2Cooked();
Error("lost connection");
@ -660,7 +664,7 @@ ReadReply(fd)
MemMove(buf, buf + l, nr);
}
BuildStringN(buf, nr, result);
if (toEOF) /* if toEOF, read until EOF */
if (toEOF == FLAGTRUE) /* if toEOF, read until EOF */
continue;
if ((result->used > 1) &&
strchr(result->string, '\n') != (char *)0)
@ -931,7 +935,7 @@ DoExec(pcf)
FileSetQuoteIAC(pcf, FLAGFALSE);
FilePrint(pcf, FLAGFALSE, "%c%c", OB_IAC, OB_EXEC);
FileSetQuoteIAC(pcf, FLAGTRUE);
r = ReadReply(pcf, 0);
r = ReadReply(pcf, FLAGFALSE);
/* now back to non-blocking, now that we've got reply */
SetFlags(FileFDNum(pcf), O_NONBLOCK, 0);
/* if we aren't still r/w, abort */
@ -1390,7 +1394,7 @@ CallUp(pcf, pcMaster, pcMach, pcHow, result)
*/
FilePrint(pcf, FLAGFALSE, "%c%ce%c%c", DEFATTN, DEFESC, chAttn,
chEsc);
r = ReadReply(pcf, 0);
r = ReadReply(pcf, FLAGFALSE);
if (strncmp(r, "[redef:", 7) != 0) {
Error("protocol botch on redef of escape sequence");
Bye(EX_UNAVAILABLE);
@ -1399,10 +1403,16 @@ CallUp(pcf, pcMaster, pcMach, pcHow, result)
/* try to grok the state of the console */
FilePrint(pcf, FLAGFALSE, "%c%c=", chAttn, chEsc);
r = ReadReply(pcf, 0);
r = ReadReply(pcf, FLAGFALSE);
if (strncmp(r, "[unknown", 8) != 0 && strncmp(r, "[up]", 4) != 0)
FileWrite(cfstdout, FLAGFALSE, r, -1);
/* try to grok the version of the server */
FilePrint(pcf, FLAGFALSE, "%c%c%c", chAttn, chEsc, 0xD6);
r = ReadReply(pcf, FLAGFALSE);
if (strncmp(r, "[unknown", 8) != 0)
sversion = AtoU(r + 1);
printf("[Enter `");
PutCtlc(chAttn, stdout);
PutCtlc(chEsc, stdout);
@ -1410,13 +1420,33 @@ CallUp(pcf, pcMaster, pcMach, pcHow, result)
/* try and display the MOTD */
FilePrint(pcf, FLAGFALSE, "%c%cm", chAttn, chEsc);
r = ReadReply(pcf, 0);
r = ReadReply(pcf, FLAGFALSE);
if (strncmp(r, "[unknown", 8) != 0 &&
strncmp(r, "[-- MOTD --]", 12) != 0)
FileWrite(cfstdout, FLAGFALSE, r, -1);
if (sversion >= 8001014) {
if (config->playback) {
FilePrint(pcf, FLAGFALSE, "%c%cP%hu\r", chAttn, chEsc,
#if defined(TIOCGWINSZ)
config->playback == 1 ? ws.ws_row :
#endif
config->playback - 1);
r = ReadReply(pcf, FLAGFALSE);
}
if (config->replay) {
FilePrint(pcf, FLAGFALSE, "%c%cR%hu\r", chAttn, chEsc,
#if defined(TIOCGWINSZ)
config->replay == 1 ? ws.ws_row :
#endif
config->replay - 1);
r = ReadReply(pcf, FLAGFALSE);
}
}
FilePrint(pcf, FLAGFALSE, "%c%c;", chAttn, chEsc);
r = ReadReply(pcf, 0);
r = ReadReply(pcf, FLAGFALSE);
if (strncmp(r, "[unknown", 8) != 0 &&
strncmp(r, "[connected]", 11) != 0)
FileWrite(cfstdout, FLAGFALSE, r, -1);
@ -1528,7 +1558,7 @@ DoCmds(master, pports, cmdi)
FileSetQuoteIAC(pcf, FLAGTRUE);
t = ReadReply(pcf, 0);
t = ReadReply(pcf, FLAGFALSE);
if (strcmp(t, "ok\r\n") != 0) {
FileClose(&pcf);
FilePrint(cfstdout, FLAGFALSE, "%s: %s", serverName, t);
@ -1537,7 +1567,7 @@ DoCmds(master, pports, cmdi)
#if HAVE_OPENSSL
if (config->sslenabled == FLAGTRUE) {
FileWrite(pcf, FLAGFALSE, "ssl\r\n", 5);
t = ReadReply(pcf, 0);
t = ReadReply(pcf, FLAGFALSE);
if (strcmp(t, "ok\r\n") == 0) {
AttemptSSL(pcf);
if (FileGetType(pcf) != SSLSocket) {
@ -1557,7 +1587,7 @@ DoCmds(master, pports, cmdi)
FilePrint(pcf, FLAGFALSE, "login %s\r\n", config->username);
t = ReadReply(pcf, 0);
t = ReadReply(pcf, FLAGFALSE);
if (strncmp(t, "passwd?", 7) == 0) {
static int count = 0;
static STRING *tmpString = (STRING *)0;
@ -1588,7 +1618,7 @@ DoCmds(master, pports, cmdi)
}
FileWrite(pcf, FLAGFALSE, tmpString->string,
tmpString->used - 1);
t = ReadReply(pcf, 0);
t = ReadReply(pcf, FLAGFALSE);
if (strcmp(t, "ok\r\n") != 0) {
FilePrint(cfstdout, FLAGFALSE, "%s: %s", serverName, t);
if (++count < 3) {
@ -1621,7 +1651,7 @@ DoCmds(master, pports, cmdi)
* that the ReadReply can stop once the socket closes.
*/
if (cmdi != 0) {
t = ReadReply(pcf, 0);
t = ReadReply(pcf, FLAGFALSE);
/* save the result */
if (result != (char *)0)
free(result);
@ -1639,7 +1669,7 @@ DoCmds(master, pports, cmdi)
Bye(EX_SOFTWARE);
}
FileWrite(pcf, FLAGFALSE, "exit\r\n", 6);
t = ReadReply(pcf, 1);
t = ReadReply(pcf, FLAGTRUE);
} else {
/* if we're not trying to connect to a console */
if (interact == FLAGFALSE) {
@ -1664,7 +1694,7 @@ DoCmds(master, pports, cmdi)
}
} else if (cmds[cmdi][0] == 'q') {
if (cmdi == 0) {
t = ReadReply(pcf, 0);
t = ReadReply(pcf, FLAGFALSE);
FilePrint(cfstdout, FLAGFALSE, "%s: %s", serverName, t);
} else {
FilePrint(cfstdout, FLAGFALSE, "%s: %s", serverName,
@ -1673,7 +1703,7 @@ DoCmds(master, pports, cmdi)
/* only say 'exit' if 'quit' failed...since it's dying anyway */
if (t[0] != 'o' || t[1] != 'k') {
FileWrite(pcf, FLAGFALSE, "exit\r\n", 6);
t = ReadReply(pcf, 1);
t = ReadReply(pcf, FLAGTRUE);
}
} else {
/* all done */
@ -1685,7 +1715,7 @@ DoCmds(master, pports, cmdi)
* like i said. wacky.
*/
FileWrite(pcf, FLAGFALSE, "exit\r\n", 6);
t = ReadReply(pcf, cmdi == 0 ? 1 : 0);
t = ReadReply(pcf, cmdi == 0 ? FLAGTRUE : FLAGFALSE);
if (cmdi == 0) {
int len;
@ -2132,6 +2162,20 @@ main(argc, argv)
if (config->port == (char *)0)
OutOfMem();
if (optConf->replay != 0)
config->replay = optConf->replay;
else if (pConfig->replay != 0)
config->replay = pConfig->replay;
else
config->replay = 0;
if (optConf->playback != 0)
config->playback = optConf->playback;
else if (pConfig->playback != 0)
config->playback = pConfig->playback;
else
config->playback = 0;
#if HAVE_OPENSSL
if (optConf->sslcredentials != (char *)0 &&
optConf->sslcredentials[0] != '\000')
@ -2214,7 +2258,7 @@ main(argc, argv)
Error("getservbyname(%s) failed", config->port);
Bye(EX_UNAVAILABLE);
} else {
bindPort = ntohs((u_short) pSE->s_port);
bindPort = ntohs((unsigned short)pSE->s_port);
}
}
#endif
@ -2280,6 +2324,21 @@ main(argc, argv)
cmds[++cmdi] = "master";
}
#if defined(TIOCGWINSZ)
if (interact == FLAGTRUE) {
int fd;
#if HAVE_MEMSET
memset((void *)(&ws), '\000', sizeof(ws));
#else
bzero((char *)(&ws), sizeof(ws));
#endif
if ((fd = open("/dev/tty", O_RDONLY)) != -1) {
ioctl(fd, TIOCGWINSZ, &ws);
}
close(fd);
}
#endif
for (;;) {
if (gotoConsole == (CONSFILE *)0)
DoCmds(config->master, acPorts->string, cmdi);

View File

@ -1,5 +1,5 @@
.\" $Id: console.man,v 1.58 2005/09/05 22:17:33 bryan Exp $
.TH CONSOLE 1 "2005/09/05" "conserver-8.1.13" "conserver"
.\" $Id: console.man,v 1.61 2006/04/03 13:32:12 bryan Exp $
.TH CONSOLE 1 "2006/04/03" "conserver-8.1.14" "conserver"
.SH NAME
console \- console server client program
.SH SYNOPSIS
@ -426,7 +426,8 @@ the console.
.I type
The type of console.
Values will be a `/' for a local device, `|' for
a command, or `!' for a remote port.
a command, `!' for a remote port, `%' for a Unix domain socket,
and `#' for a noop console.
.TP
.I console-details
The details regarding the console.
@ -437,6 +438,9 @@ Commands will have values of the command, the command's pid, the
pseudo-tty, and file descriptor for the pseudo-tty.
Remote ports will have values of the remote hostname, remote port number,
``raw'' or ``telnet'' protocol, and file descriptor for the socket connection.
Unix domain sockets will have the path to the socket and the file
descriptor for the socket connection.
Noop consoles will have nothing.
.TP
.I users-list
The details of each user connected to the console.
@ -530,6 +534,17 @@ Set the default master to
.B \-M
command-line flag).
.TP
\f3playback\fP \f2num\fP|\f3""\fP
.br
Override the playback length for the
.B p
escape command to
.I num
lines (if the server supports it).
Using the special value of ``0'' will cause the client to use the number
of lines of the current terminal (if that can be determined).
If the null string (``""'') is used, the playback length will not be overridden.
.TP
\f3port\fP \f2port\fP
.br
Set the default port to
@ -538,6 +553,17 @@ Set the default port to
.B \-p
command-line flag).
.TP
\f3replay\fP \f2num\fP|\f3""\fP
.br
Override the replay length for the
.B r
escape command to
.I num
lines (if the server supports it).
Using the special value of ``0'' will cause the client to use the number
of lines of the current terminal (if that can be determined).
If the null string (``""'') is used, the replay length will not be overridden.
.TP
\f3sslcredentials\fP \f2filename\fP
.br
Set the
@ -830,11 +856,17 @@ close (if open) and reopen the line (to clear errors (silo overflows))
and the log file
.TP
.B p
replay the last 60 lines of output
playback the last 60 lines of output
.TP
.B P
set number of playback lines
.TP
.B r
replay the last 20 lines of output
.TP
.B R
set number of replay lines
.TP
.B s
switch to spy mode (read-only)
.TP

View File

@ -1,5 +1,5 @@
/*
* $Id: readconf.c,v 5.3 2005/06/11 02:32:21 bryan Exp $
* $Id: readconf.c,v 5.5 2006/04/03 13:32:12 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -81,6 +81,10 @@ ApplyConfigDefault(c)
}
if (parserConfigDefault->striphigh != FLAGUNKNOWN)
c->striphigh = parserConfigDefault->striphigh;
if (parserConfigDefault->replay != FLAGUNKNOWN)
c->replay = parserConfigDefault->replay;
if (parserConfigDefault->playback != FLAGUNKNOWN)
c->playback = parserConfigDefault->playback;
#if HAVE_OPENSSL
if (parserConfigDefault->sslcredentials != (char *)0) {
if (c->sslcredentials != (char *)0)
@ -395,6 +399,35 @@ ConfigItemMaster(id)
OutOfMem();
}
void
#if PROTOTYPES
ConfigItemPlayback(char *id)
#else
ConfigItemPlayback(id)
char *id;
#endif
{
int i;
CONDDEBUG((1, "ConfigItemPlayback(%s) [%s:%d]", id, file, line));
if ((id == (char *)0) || (*id == '\000')) {
parserConfigTemp->playback = 0;
return;
}
for (i = 0; id[i] != '\000'; i++) {
if (!isdigit((int)id[i])) {
Error("invalid playback value [%s:%d]", file, line);
return;
}
}
if (i > 4) {
Error("playback value too large [%s:%d]", file, line);
return;
}
parserConfigTemp->playback = (unsigned short)atoi(id) + 1;
}
void
#if PROTOTYPES
ConfigItemPort(char *id)
@ -416,6 +449,35 @@ ConfigItemPort(id)
OutOfMem();
}
void
#if PROTOTYPES
ConfigItemReplay(char *id)
#else
ConfigItemReplay(id)
char *id;
#endif
{
int i;
CONDDEBUG((1, "ConfigItemReplay(%s) [%s:%d]", id, file, line));
if ((id == (char *)0) || (*id == '\000')) {
parserConfigTemp->replay = 0;
return;
}
for (i = 0; id[i] != '\000'; i++) {
if (!isdigit((int)id[i])) {
Error("invalid replay value [%s:%d]", file, line);
return;
}
}
if (i > 4) {
Error("replay value too large [%s:%d]", file, line);
return;
}
parserConfigTemp->replay = (unsigned short)atoi(id) + 1;
}
void
#if PROTOTYPES
ConfigItemSslcredentials(char *id)
@ -512,11 +574,28 @@ ConfigItemUsername(id)
SUBST *substData = (SUBST *)0;
SUBSTTOKEN
#if PROTOTYPES
SubstToken(char c)
#else
SubstToken(c)
char c;
#endif
{
switch (c) {
case 'u':
case 'c':
return ISSTRING;
default:
return ISNOTHING;
}
}
int
#if PROTOTYPES
SubstCallback(char c, char **s, int *i)
SubstValue(char c, char **s, int *i)
#else
SubstCallback(c, s, i)
SubstValue(c, s, i)
char c;
char **s;
int *i;
@ -524,14 +603,6 @@ SubstCallback(c, s, i)
{
int retval = 0;
if (substData == (SUBST *)0) {
if ((substData = (SUBST *)calloc(1, sizeof(SUBST))) == (SUBST *)0)
OutOfMem();
substData->callback = &SubstCallback;
substData->tokens['u'] = ISSTRING;
substData->tokens['c'] = ISSTRING;
}
if (s != (char **)0) {
CONFIG *pc;
if (substData->data == (void *)0)
@ -550,6 +621,22 @@ SubstCallback(c, s, i)
return retval;
}
void
#if PROTOTYPES
InitSubstCallback(void)
#else
InitSubstCallback()
#endif
{
if (substData == (SUBST *)0) {
if ((substData = (SUBST *)calloc(1, sizeof(SUBST))) == (SUBST *)0)
OutOfMem();
substData->value = &SubstValue;
substData->token = &SubstToken;
}
}
void
#if PROTOTYPES
TerminalItemAttach(char *id)
@ -621,7 +708,9 @@ TerminalItemDetachsubst(id)
ITEM keyConfig[] = {
{"escape", ConfigItemEscape},
{"master", ConfigItemMaster},
{"playback", ConfigItemPlayback},
{"port", ConfigItemPort},
{"replay", ConfigItemReplay},
{"sslcredentials", ConfigItemSslcredentials},
{"sslrequired", ConfigItemSslrequired},
{"sslenabled", ConfigItemSslenabled},
@ -664,7 +753,7 @@ ReadConf(filename, verbose)
}
/* initialize the substition bits */
SubstCallback('\000', (char **)0, (int *)0);
InitSubstCallback();
parserConfigDefault = pConfig;
pConfig = (CONFIG *)0;
@ -699,6 +788,8 @@ ReadConf(filename, verbose)
CONDDEBUG((1, "pConfig->escape = %s", EMPTYSTR(pConfig->escape)));
CONDDEBUG((1, "pConfig->striphigh = %s",
FLAGSTR(pConfig->striphigh)));
CONDDEBUG((1, "pConfig->replay = %hu", pConfig->replay));
CONDDEBUG((1, "pConfig->playback = %hu", pConfig->playback));
#if HAVE_OPENSSL
CONDDEBUG((1, "pConfig->sslcredentials = %s",
EMPTYSTR(pConfig->sslcredentials)));

View File

@ -1,5 +1,5 @@
/*
* $Id: readconf.h,v 5.3 2004/05/25 23:03:25 bryan Exp $
* $Id: readconf.h,v 5.4 2006/04/03 13:32:12 bryan Exp $
*
* Copyright conserver.com, 2000
*
@ -14,6 +14,8 @@ typedef struct config {
char *port;
char *escape;
FLAG striphigh;
unsigned short replay;
unsigned short playback;
#if HAVE_OPENSSL
char *sslcredentials;
FLAG sslrequired;

View File

@ -4,7 +4,7 @@
#
%define pkg conserver
%define ver 8.1.13
%define ver 8.1.14
# define the name of the machine on which the main conserver
# daemon will be running if you don't want to use the default
@ -12,13 +12,13 @@
%define master console
# what red hat (or other distibution) version are you running?
%define distver 6
%define distver 1
Summary: Serial console server daemon/client
Name: %{pkg}
Version: %{ver}
Release: 1.%{distver}
Copyright: distributable
Release: %{distver}
License: BSD
Group: System Environment/Daemons
URL: http://www.conserver.com/
Source: http://www.conserver.com/%{pkg}-%{ver}.tar.gz
@ -96,6 +96,7 @@ fi
%config(noreplace) %{_sysconfdir}/conserver.passwd
%attr(555,root,root) %{_initrddir}/conserver
%{prefix}/bin/console
%{prefix}/lib/conserver/convert
%{prefix}/share/man/man1/console.1.gz
%{prefix}/share/man/man8/conserver.8.gz
%{prefix}/share/man/man5/conserver.cf.5.gz

View File

@ -1,7 +1,7 @@
PKG="conserver"
NAME="Console server and client"
CATEGORY="system"
VERSION="8.1.13"
VERSION="8.1.14"
DESC="Console server and client"
CLASSES=none
ARCH=sparc

View File

@ -8,8 +8,9 @@
L toggle logging on/off l? break sequence list
l0 send break per config file l1-9 send specific break sequence
m display the message of the day o (re)open the tty and log file
p replay the last 60 lines r replay the last 20 lines
s spy read only u show host status
p playback the last 60 lines P set number of playback lines
r replay the last 20 lines R set number of replay lines
s spy mode (read only) u show host status
v show version info w who is on this console
x show console baud info z suspend the connection
| attach local command ? print this message

View File

@ -8,8 +8,9 @@
L toggle logging on/off l? break sequence list
l0 send break per config file l1-9 send specific break sequence
m display the message of the day o (re)open the tty and log file
p replay the last 60 lines r replay the last 20 lines
s spy read only u show host status
p playback the last 60 lines P set number of playback lines
r replay the last 20 lines R set number of replay lines
s spy mode (read only) u show host status
v show version info w who is on this console
x show console baud info z suspend the connection
| attach local command ? print this message