diff --git a/CHANGES b/CHANGES index 861d9d5..239f6a2 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,36 @@ CHANGES ======= +version 8.1.14 (Apr 9, 2006): + - fixed rpm conserver.spec file - based on patch by Martin Evans + + - added 'uds' console type for unix domain socket connections - + based on patch by DJ Gregor + - probing of interfaces under cygwin (and possibly others?) now + skips unconfigured interfaces (even if flagged as up!) - + reported by Chris Riddoch + - added the '!login' console option to prevent clients from + connecting to a console - suggested by Greg Tillman + + - added a 'noop' console type for consoles you'd like to name, + but have no connection to - suggested by Greg Tillman + + - 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 + - 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 + + - 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 + 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 $ # diff --git a/README b/README index beeed60..4e573f8 100644 --- a/README +++ b/README @@ -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 $ # diff --git a/TODO b/TODO index b6d0eab..2c5d494 100644 --- a/TODO +++ b/TODO @@ -54,8 +54,6 @@ Bryan Stansell - cyclades ts1000/2000 port : "Moses, Joel" -- config file for client (list of masters, for example) - - strftime() idea for logfile names : Lars Kellogg-Stedman - 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 - - - log rotation by date : Tom Pachla - strict file permission checks on conserver.passwd/conserver.cf : Erik @@ -109,6 +104,9 @@ Bryan Stansell - reintroduce console grouping : Martin Turba +- quick-recheck of down consoles (for uds) and possibly only log state + changes (instead of each try) : DJ Gregor + # -# $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 $ # diff --git a/autologin/autologin.c b/autologin/autologin.c index 12a179f..da48ba4 100644 --- a/autologin/autologin.c +++ b/autologin/autologin.c @@ -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) { diff --git a/compat.h b/compat.h index 385dbc6..fe49bf0 100644 --- a/compat.h +++ b/compat.h @@ -8,9 +8,7 @@ #include #include #include -#if USE_UNIX_DOMAIN_SOCKETS #include -#endif #include #include #include @@ -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 +#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 #endif diff --git a/config.guess b/config.guess index 17690ae..22906b3 100755 --- a/config.guess +++ b/config.guess @@ -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 diff --git a/config.h.in b/config.h.in index 4f9dea1..4393688 100644 --- a/config.h.in +++ b/config.h.in @@ -195,6 +195,9 @@ /* Define to 1 if you have the 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 header file. */ #undef HAVE_STROPTS_H @@ -243,6 +246,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UIO_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UN_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_VLIMIT_H diff --git a/config.sub b/config.sub index a4e8a94..5705e54 100755 --- a/config.sub +++ b/config.sub @@ -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) diff --git a/configure b/configure index 28a1eb1..84e53b0 100755 --- a/configure +++ b/configure @@ -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 diff --git a/configure.in b/configure.in index db123c8..adced32 100644 --- a/configure.in +++ b/configure.in @@ -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])], diff --git a/conserver.cf/conserver.cf.man b/conserver.cf/conserver.cf.man index 795aa5c..550b095 100644 --- a/conserver.cf/conserver.cf.man +++ b/conserver.cf/conserver.cf.man @@ -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 diff --git a/conserver.cf/conserver.passwd.man b/conserver.cf/conserver.passwd.man index 51e301e..37dfa8b 100644 --- a/conserver.cf/conserver.passwd.man +++ b/conserver.cf/conserver.passwd.man @@ -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) diff --git a/conserver.html b/conserver.html index b4c3cf2..0b536c9 100644 --- a/conserver.html +++ b/conserver.html @@ -36,6 +36,10 @@ Please pick your closest mirror:   Australia +   Germany +   Ireland   Russia   US-West (Primary)
@@ -182,11 +186,11 @@

Downloading

-

The current version, released on Jan 15, 2006, is 8.1.13.tar.gz. You can get it +

The current version, released on Apr 9, 2006, is 8.1.14.tar.gz. You can get it via FTP - or HTTP. See the FTP + or HTTP. See the CHANGES file for information on the latest updates.

@@ -230,7 +234,11 @@
  • 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
  • diff --git a/conserver/client.c b/conserver/client.c index 093d454..fc025c9 100644 --- a/conserver/client.c +++ b/conserver/client.c @@ -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) - fdLog = FileOpen(pCE->logfile, O_RDONLY, 0644); - } + 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; + 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; + } + + if (!eof) + BuildStringChar(buf[i], line); + + 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, 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" + */ + s = strrchr(mark_end->string, ']'); + if ((char *)0 != s) + *s = '\000'; + FileWrite(fdOut, FLAGTRUE, + 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--; } - ln++; - } - - /* 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; - - /* output the start of the range, stopping at the ']' - */ - s = strrchr(lines[i].line->string, ']'); - if ((char *)0 != s) { - *s = '\000'; - } - FileWrite(fdOut, FLAGTRUE, lines[i].line->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 = '\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); + 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, diff --git a/conserver/client.h b/conserver/client.h index f8ae783..257be9e 100644 --- a/conserver/client.h +++ b/conserver/client.h @@ -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 *)); diff --git a/conserver/consent.c b/conserver/consent.c index 77d0e75..a8d7ff1 100644 --- a/conserver/consent.c +++ b/conserver/consent.c @@ -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,21 +1003,29 @@ 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 we're waiting for connect() to finish, watch the - * write bit, otherwise watch for the read bit - */ - if (pCE->ioState == INCONNECT) - FD_SET(cofile, &winit); - else - FD_SET(cofile, &rinit); - if (maxfd < cofile + 1) - maxfd = cofile + 1; + if (cofile != -1) { + /* if we're waiting for connect() to finish, watch the + * write bit, otherwise watch for the read bit + */ + if (pCE->ioState == INCONNECT) + FD_SET(cofile, &winit); + else + FD_SET(cofile, &rinit); + if (maxfd < cofile + 1) + maxfd = cofile + 1; + } tyme = time((time_t *)0); diff --git a/conserver/consent.h b/conserver/consent.h index faa25bf..175dba0 100644 --- a/conserver/consent.h +++ b/conserver/consent.h @@ -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 */ diff --git a/conserver/conserver.man b/conserver/conserver.man index cd69f59..aaabc16 100644 --- a/conserver/conserver.man +++ b/conserver/conserver.man @@ -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 diff --git a/conserver/convert.c b/conserver/convert.c index 6befa53..7cf3c4c 100644 --- a/conserver/convert.c +++ b/conserver/convert.c @@ -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); } diff --git a/conserver/cutil.c b/conserver/cutil.c index 05a2d49..f2a6f4a 100644 --- a/conserver/cutil.c +++ b/conserver/cutil.c @@ -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 #include +#include #include #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 +} diff --git a/conserver/cutil.h b/conserver/cutil.h index ccd1fb2..a9b579a 100644 --- a/conserver/cutil.h +++ b/conserver/cutil.h @@ -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 *)); diff --git a/conserver/group.c b/conserver/group.c index 3772ba6..a50128c 100644 --- a/conserver/group.c +++ b/conserver/group.c @@ -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 #include #include -#include #include #include #include +#include #if HAVE_PAM #include @@ -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); - BuildString((char *)0, bcast); - BuildStringChar('[', bcast); - BuildString(pCLServing->acid->string, bcast); - BuildString(": ", bcast); - BuildString(pCLServing->msg->string, bcast); - BuildString("]\r\n", bcast); - SendClientsMsg(pCEServing, bcast->string); - BuildString((char *)0, pCLServing->msg); - pCLServing->iState = S_NORMAL; + case S_BCAST: + 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->accmd->string, bcast); + BuildString("]\r\n", bcast); + SendClientsMsg(pCEServing, bcast->string); + + 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, + " ", 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, " ", -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("@", pCL->acid); BuildString((char *)0, pCL->username); BuildString("", 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) diff --git a/conserver/group.h b/conserver/group.h index 6e43244..3bda519 100644 --- a/conserver/group.h +++ b/conserver/group.h @@ -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 diff --git a/conserver/main.c b/conserver/main.c index e8a30eb..b37e824 100644 --- a/conserver/main.c +++ b/conserver/main.c @@ -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(); diff --git a/conserver/master.c b/conserver/master.c index 2fc5090..36622cc 100644 --- a/conserver/master.c +++ b/conserver/master.c @@ -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 #include #include -#include #include @@ -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", diff --git a/conserver/readcfg.c b/conserver/readcfg.c index 58d3a89..f739857 100644 --- a/conserver/readcfg.c +++ b/conserver/readcfg.c @@ -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); diff --git a/conserver/version.h b/conserver/version.h index b76af29..c5133ec 100644 --- a/conserver/version.h +++ b/conserver/version.h @@ -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) diff --git a/console/console.c b/console/console.c index f05e7d1..e24d8d8 100644 --- a/console/console.c +++ b/console/console.c @@ -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 #include -#include #include +#include #if HAVE_OPENSSL #include #include @@ -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); diff --git a/console/console.man b/console/console.man index 1b0d783..18b159c 100644 --- a/console/console.man +++ b/console/console.man @@ -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 diff --git a/console/readconf.c b/console/readconf.c index a934022..0cd6a58 100644 --- a/console/readconf.c +++ b/console/readconf.c @@ -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))); diff --git a/console/readconf.h b/console/readconf.h index b3e60dd..7a7ed5b 100644 --- a/console/readconf.h +++ b/console/readconf.h @@ -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; diff --git a/contrib/redhat-rpm/conserver.spec b/contrib/redhat-rpm/conserver.spec index 87a5a7e..8463b32 100644 --- a/contrib/redhat-rpm/conserver.spec +++ b/contrib/redhat-rpm/conserver.spec @@ -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 diff --git a/contrib/solaris-package/pkginfo b/contrib/solaris-package/pkginfo index 54f1628..be3a203 100644 --- a/contrib/solaris-package/pkginfo +++ b/contrib/solaris-package/pkginfo @@ -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 diff --git a/test/results/test2 b/test/results/test2 index f128892..031479a 100644 --- a/test/results/test2 +++ b/test/results/test2 @@ -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 diff --git a/test/results/test7 b/test/results/test7 index f128892..031479a 100644 --- a/test/results/test7 +++ b/test/results/test7 @@ -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