Imported from conserver-7.1.0.tar.gz

This commit is contained in:
Bryan Stansell 2001-07-26 17:05:04 -07:00
parent 6617579233
commit 4a15f7082e
44 changed files with 9924 additions and 6532 deletions

58
CHANGES
View File

@ -1,6 +1,57 @@
CHANGES CHANGES
======= =======
version 7.1.0 (Jul 26, 2001):
- Hostname in access list that began with a digit was treated as
an IP address - only strings using [0-9./] are considered CIDR
notation and they must be of the form a.b.c.d[/n]
- Fixed SIGHUP always opening logfile(-L) - shouldn't without -d
- Fixed 'make install' problem under MacOS X and cygwin
- Client -l option totally broken in 7.0.3 - patch by Daniel E.
Singer <des@cs.duke.edu>
- Client now accepts IP addresses from server and server now sends
the IP of the socket instead of its hostname to the client,
fixing part of the multi-interface problem
- Client no longer passes hostname to server along with username
- Client now turns off IEXTEN so stuff like ^V passes through
- Server now pauses one second when reopening a TCP-based console
to give the terminal server a chance to clean up
- Master server process now fork()s when accepting clients
- timestamp-spec can be numeric only ('m' default)
- Ambiguous console name error now shows ambiguous list
- Console list in conserver.passwd can now have whitespace
- Access lists in conserver.cf can now use ',' as a separator
- Added special '*any*' username in conserver.passwd
- Username match (real or '*any*') now stops conserver.passwd file
processing - allowing you to lock out users
- Added -u flag to server to enable "unloved" output - this is the
opposite of the old -n flag, which now does nothing
- Added -7 flag to client and server for stripping the high bit
of data on either side (--disable-8bit removed)
- Added -b to server to specify the base port number for the
secondary communication channel - based on code from Enrik
Berkhan <Enrik.Berkhan@planb.de>
- Changed -d and -D flags to -r and -R in client - now -D enables
debugging mode in the client (and -d is unused)
- Changed -r to -G in client so -r could be used for the above
- Client now uses getpassphrase() (if available) for > 8 char
passwords - pointed out by Gregory Bond <gnb@itga.com.au>
- Improved signal handling
- Improved process handling (POSIX waitpid() now necessary)
- Significant rework of STREAMS-based pseudo-tty code
- TCP connections ('!' config syntax) now have some Telnet protocol
knowledge, removing the "noise" seen when conneting to a terminal
server - reported by Todd Stansell <todd@stansell.org>
- Various code and message "pretty-printing" done
- Client and server both run in Windows (tested with Windows
2000) under the cygwin environment thanks to a debug-fest with
Emmett Hogan <hogan@gnac.com>
- Using autoconf version 2.50
- Man pages reworked and conserver.passwd page created by Dave
Stuit <djs@gnac.com> - the pain he suffered documenting
the program (and pointing out many of the bugs fixed above)
should help endless others
version 7.0.3 (Jul 5, 2001): version 7.0.3 (Jul 5, 2001):
- "Off by 1" bug in 7.0.2 line-oriented timestamp code fixed (extra - "Off by 1" bug in 7.0.2 line-oriented timestamp code fixed (extra
chars in logfile) reported by Matthew Cheek <cheek@mars-systems.com> chars in logfile) reported by Matthew Cheek <cheek@mars-systems.com>
@ -8,9 +59,10 @@ version 7.0.3 (Jul 5, 2001):
- 'attached', 'detached', and 'bumped' actions now written to - 'attached', 'detached', and 'bumped' actions now written to
console logs that have 'a' in timestamp-spec field console logs that have 'a' in timestamp-spec field
- Default timestamp specification with TIMESTAMP= in .cf file - Default timestamp specification with TIMESTAMP= in .cf file
- config file much more forgiving about whitespace in fields - Config file much more forgiving about whitespace in fields
- gethostbyaddr() failures are no longer fatal - gethostbyaddr() failures are no longer fatal
- Added -M for server to specify the address to listen on - Added -M to server to specify the address to listen on
based on code from Enrik Berkhan <Enrik.Berkhan@planb.de>
- Added -p option to client and server to specify the port to - Added -p option to client and server to specify the port to
connect to and listen on (--with-port still sets the default) connect to and listen on (--with-port still sets the default)
- Added logfile output when going into daemon mode - Added logfile output when going into daemon mode
@ -154,5 +206,5 @@ before version 6.05:
and enhancements of various types were applied. and enhancements of various types were applied.
# #
# $Id: CHANGES,v 1.32 2001-07-05 08:09:30-07 bryan Exp $ # $Id: CHANGES,v 1.41 2001-07-26 16:42:26-07 bryan Exp $
# #

33
INSTALL
View File

@ -1,6 +1,31 @@
INSTALL INSTALL
======= =======
Upgrading?
Whenever you upgrade I suggest you upgrade both the client and
server. Most times, however, you can get away without upgrading
the client (it's usually a fairly static piece of code). I'll
document any dependencies here, but check the CHANGES file for any
new features added to the client if you're considering *not*
upgrading.
Version 7.1.0
- The client/server protocol has changed. You *MUST* use a
7.1.0 client with a 7.1.0 and above server. A 7.1.0 client
is *not* backward compatible with a pre-7.1.0 server.
- Some of the flags in the client (-d, -D, and -r) and server
(-n) have been given new identities to make the client and
server flags more uniform.
- The conserver.passwd file now uses the first username match
to determine access rights - if you have multiple instances
of a username in an existing password file, they must be
combined into one to continue to work.
Quickie Instructions Quickie Instructions
- Download conserver (http://www.conserver.com/) and unpack - Download conserver (http://www.conserver.com/) and unpack
@ -11,6 +36,7 @@ Quickie Instructions
- Now set up config files, etc. (see below) - Now set up config files, etc. (see below)
Detailed Instructions Detailed Instructions
- First thing to do is determine if you want different defaults. A - First thing to do is determine if you want different defaults. A
@ -19,13 +45,14 @@ Detailed Instructions
unique options: unique options:
--with-port=PORT Specify port number [conserver] --with-port=PORT Specify port number [conserver]
--with-base=PORT Base port for secondary channel [0]
--with-master=MASTER Specify master server hostname [console] --with-master=MASTER Specify master server hostname [console]
--with-cffile=CFFILE Specify config filename [conserver.cf] --with-cffile=CFFILE Specify config filename [conserver.cf]
--with-pwdfile=PWDFILE Specify password filename [conserver.passwd] --with-pwdfile=PWDFILE Specify password filename [conserver.passwd]
--with-logfile=LOGFILE Specify log filename [/var/log/conserver]
--with-pidfile=PIDFILE Specify PID filepath [/var/run/conserver.pid] --with-pidfile=PIDFILE Specify PID filepath [/var/run/conserver.pid]
--with-maxmemb=MAXMEMB Specify maximum consoles per process [8] --with-maxmemb=MAXMEMB Specify maximum consoles per process [16]
--with-maxgrp=MAXGRP Specify maximum number of processes [32] --with-maxgrp=MAXGRP Specify maximum number of processes [32]
--disable-8bit Disable 8bit data path
--with-timeout=TIMEOUT Specify connect() timeout in seconds [10] --with-timeout=TIMEOUT Specify connect() timeout in seconds [10]
Not surprisingly, some match the old conserver/cons.h items...here Not surprisingly, some match the old conserver/cons.h items...here
@ -85,5 +112,5 @@ Detailed Instructions
- That's it! Just start up the console server and enjoy! - That's it! Just start up the console server and enjoy!
# #
# $Id: INSTALL,v 1.11 2001-07-05 02:46:01-07 bryan Exp $ # $Id: INSTALL,v 1.17 2001-07-25 17:33:29-07 bryan Exp $
# #

View File

@ -41,3 +41,4 @@ distclean:
done done
rm -f config.cache config.log config.status config.h Makefile rm -f config.cache config.log config.status config.h Makefile
.PHONY: autologin autologin.install clean distclean install all

24
TODO
View File

@ -9,6 +9,16 @@ Bryan Stansell
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
- conserver.passwd parsing needs improvement
- shouldn't use strtok() (bryan::any == bryan:any)
- empty passwords not allowed
- Telnet protocol should be improved
- Not even RFC 854 compliant
- Data sent to terminal server not encapsulated
- Option negotiation ignored - should we negotiate anything?
- Others?
- reread of conserver.cf - totally difficult - reread of conserver.cf - totally difficult
- non-dynamic memory allocation - non-dynamic memory allocation
- no IPC for coordinated updates - no IPC for coordinated updates
@ -49,14 +59,10 @@ Bryan Stansell
- "not" or "except" in passwd file (!console). - "not" or "except" in passwd file (!console).
- master redirect for same host - big mess
- redirect for console goes to `hostname`
- should probably go to ip of connection
- addresses not allowed - has to be hostname (resolvable by client)
- can you say: gack!
- multi-homed/multi-ip hosts not supported well - multi-homed/multi-ip hosts not supported well
- other names/ip addrs not detected as local, necessarily - other names/ip addrs not detected as local, necessarily
- acls don't look at aliases properly
- the whole thing needs some serious help
- cyclades ts1000/2000 port : "Moses, Joel" <jmoses@deloitte.com> - cyclades ts1000/2000 port : "Moses, Joel" <jmoses@deloitte.com>
@ -66,10 +72,6 @@ Bryan Stansell
- config file for client (list of masters, for example) - config file for client (list of masters, for example)
- patches from Enrik Berkhan <Enrik.Berkhan@planb.de>
- bind address
- base port for children
- strftime() idea for logfile names : Lars Kellogg-Stedman <lars@larsshack.org> - strftime() idea for logfile names : Lars Kellogg-Stedman <lars@larsshack.org>
- 9600baud log replay? - 9600baud log replay?
@ -87,5 +89,5 @@ Bryan Stansell
- bios support - bios support
# #
# $Id: TODO,v 1.7 2001-07-05 07:37:34-07 bryan Exp $ # $Id: TODO,v 1.11 2001-07-25 17:36:21-07 bryan Exp $
# #

View File

@ -3,6 +3,11 @@
*/ */
#undef DEFPORT #undef DEFPORT
/*
* Base socket used for secondary channel
*/
#undef DEFBASEPORT
/* /*
* Hostname of console server * Hostname of console server
*/ */
@ -33,11 +38,6 @@
*/ */
#undef MAXGRP #undef MAXGRP
/*
* Clear parity (high-bit) [true/false setting]
*/
#undef CPARITY
/* /*
* TCP connection timeout * TCP connection timeout
*/ */

View File

@ -31,8 +31,6 @@ ALL = autologin
all: $(ALL) all: $(ALL)
.PHONY: clean distclean install
autologin: $(AUTOLOGIN_OBJS) autologin: $(AUTOLOGIN_OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o autologin $(AUTOLOGIN_OBJS) $(LIBS) $(CC) $(CFLAGS) $(LDFLAGS) -o autologin $(AUTOLOGIN_OBJS) $(LIBS)
@ -49,3 +47,4 @@ install:
$(MKDIR) $(DESTDIR)$(bindir) $(MKDIR) $(DESTDIR)$(bindir)
$(INSTALL_PROGRAM) autologin $(DESTDIR)$(bindir) $(INSTALL_PROGRAM) autologin $(DESTDIR)$(bindir)
.PHONY: clean distclean install

View File

@ -1,27 +1,6 @@
#include <config.h> #include <config.h>
/* hpux doesn't have getdtablesize() and they don't provide a macro
* in non-KERNEL cpp mode
*/
#ifndef HAVE_GETDTABLESIZE
# ifdef HAVE_GETRLIMIT
static int
getdtablesize()
{
auto struct rlimit rl;
(void)getrlimit(RLIMIT_NOFILE, &rl);
return rl.rlim_cur;
}
# else /* ! HAVE_GETRLIMIT */
# ifndef OPEN_MAX
# define OPEN_MAX 64
# endif
# define getdtablesize() OPEN_MAX
# endif /* HAVE_GETRLIMIT */
#endif /* ! HAVE_GETDTABLESIZE */
#if STDC_HEADERS #if STDC_HEADERS
# include <string.h> # include <string.h>
# include <stdlib.h> # include <stdlib.h>
@ -84,20 +63,40 @@ typedef long fd_set;
# include <sys/ttold.h> # include <sys/ttold.h>
#endif #endif
#if HAVE_TYPES_H
/* which type does wait(2) take for status location
*/
#include <sys/types.h> #include <sys/types.h>
#if HAVE_SYS_WAIT_H
# include <sys/wait.h>
#else
# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#endif #endif
#ifdef HAVE_SIGACTION #if HAVE_SYS_WAIT_H
extern void Set_signal(int isg, RETSIGTYPE (*disp)(int)); # include <sys/wait.h>
#endif
#define LO(s) ((unsigned)((s) & 0377))
#define HI(s) ((unsigned)(((s) >> 8) & 0377))
#if !defined(WIFEXITED)
#define WIFEXITED(s) (LO(s)==0)
#endif
#if !defined(WEXITSTATUS)
#define WEXITSTATUS(s) HI(s)
#endif
#if !defined(WIFSIGNALED)
#define WIFSIGNALED(s) ((LO(s)>0)&&(HI(s)==0))
#endif
#if !defined(WTERMSIG)
#define WTERMSIG(s) (LO(s)&0177)
#endif
#if !defined(WIFSTOPPED)
#define WIFSTOPPED(s) ((LO(s)==0177)&&(HI(s)!=0))
#endif
#if !defined(WSTOPSIG)
#define WSTOPSIG(s) HI(s)
#endif
#if HAVE_SYSEXITS_H
#include <sysexits.h>
#else #else
# define Set_signal(sig, disp) (void)signal((sig), (disp)) #define EX_OK 0
#define EX_UNAVAILABLE 69
#define EX_TEMPFAIL 75
#endif #endif
#include <errno.h> #include <errno.h>

View File

@ -1,38 +1,14 @@
/* config.h.in. Generated automatically from configure.in by autoheader. */ /* config.h.in. Generated automatically from configure.in by autoheader. */
/* Define if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
#undef _ALL_SOURCE
#endif
/* Define to empty if the keyword does not work. */
#undef const
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_WAIT_H
/* Define to `int' if <sys/types.h> doesn't define. */
#undef mode_t
/* Define as the return type of signal handlers (int or void). */
#undef RETSIGTYPE
/* Define if the `setpgrp' function takes no argument. */
#undef SETPGRP_VOID
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* /*
* Socket used to communicate * Socket used to communicate
*/ */
#undef DEFPORT #undef DEFPORT
/*
* Base socket used for secondary channel
*/
#undef DEFBASEPORT
/* /*
* Hostname of console server * Hostname of console server
*/ */
@ -63,11 +39,6 @@
*/ */
#undef MAXGRP #undef MAXGRP
/*
* Clear parity (high-bit) [true/false setting]
*/
#undef CPARITY
/* /*
* TCP connection timeout * TCP connection timeout
*/ */
@ -78,117 +49,132 @@
*/ */
#undef PIDFILE #undef PIDFILE
/* Define if you have the flock function. */
#undef HAVE_FLOCK
/* Define if you have the getdtablesize function. */
#undef HAVE_GETDTABLESIZE
/* Define if you have the getopt function. */
#undef HAVE_GETOPT
/* Define if you have the getpseudo function. */
#undef HAVE_GETPSEUDO
/* Define if you have the getrlimit function. */
#undef HAVE_GETRLIMIT
/* Define if you have the getsid function. */
#undef HAVE_GETSID
/* Define if you have the getspnam function. */
#undef HAVE_GETSPNAM
/* Define if you have the getuserattr function. */
#undef HAVE_GETUSERATTR
/* Define if you have the getutent function. */
#undef HAVE_GETUTENT
/* Define if you have the memcmp function. */
#undef HAVE_MEMCMP
/* Define if you have the memcpy function. */
#undef HAVE_MEMCPY
/* Define if you have the memset function. */
#undef HAVE_MEMSET
/* Define if you have the ptsname function. */
#undef HAVE_PTSNAME
/* Define if you have the putenv function. */
#undef HAVE_PUTENV
/* Define if you have the setgroups function. */
#undef HAVE_SETGROUPS
/* Define if you have the setlinebuf function. */
#undef HAVE_SETLINEBUF
/* Define if you have the setpgrp function. */
#undef HAVE_SETPGRP
/* Define if you have the setsid function. */
#undef HAVE_SETSID
/* Define if you have the setsockopt function. */
#undef HAVE_SETSOCKOPT
/* Define if you have the setttyent function. */
#undef HAVE_SETTTYENT
/* Define if you have the setvbuf function. */
#undef HAVE_SETVBUF
/* Define if you have the sigaction function. */
#undef HAVE_SIGACTION
/* Define if you have the strerror function. */
#undef HAVE_STRERROR
/* Define if you have the tcgetattr function. */
#undef HAVE_TCGETATTR
/* Define if you have the tcgetpgrp function. */
#undef HAVE_TCGETPGRP
/* Define if you have the tcsendbreak function. */
#undef HAVE_TCSENDBREAK
/* Define if you have the tcsetattr function. */
#undef HAVE_TCSETATTR
/* Define if you have the tcsetpgrp function. */
#undef HAVE_TCSETPGRP
/* Define if you have the wait3 function. */
#undef HAVE_WAIT3
/* Define if you have the <crypt.h> header file. */ /* Define if you have the <crypt.h> header file. */
#undef HAVE_CRYPT_H #undef HAVE_CRYPT_H
/* Define if you have the `flock' function. */
#undef HAVE_FLOCK
/* Define if you have the `getdtablesize' function. */
#undef HAVE_GETDTABLESIZE
/* Define if you have the `getopt' function. */
#undef HAVE_GETOPT
/* Define if you have the <getopt.h> header file. */ /* Define if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H #undef HAVE_GETOPT_H
/* Define if you have the `getpassphrase' function. */
#undef HAVE_GETPASSPHRASE
/* Define if you have the `getrlimit' function. */
#undef HAVE_GETRLIMIT
/* Define if you have the `getsid' function. */
#undef HAVE_GETSID
/* Define if you have the `getspnam' function. */
#undef HAVE_GETSPNAM
/* Define if you have the `getuserattr' function. */
#undef HAVE_GETUSERATTR
/* Define if you have the `getutent' function. */
#undef HAVE_GETUTENT
/* Define if you have the `grantpt' function. */
#undef HAVE_GRANTPT
/* Define if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define if you have the `crypt' library (-lcrypt). */
#undef HAVE_LIBCRYPT
/* Define if you have the `nsl' library (-lnsl). */
#undef HAVE_LIBNSL
/* Define if you have the `socket' library (-lsocket). */
#undef HAVE_LIBSOCKET
/* Define if you have the `memcmp' function. */
#undef HAVE_MEMCMP
/* Define if you have the `memcpy' function. */
#undef HAVE_MEMCPY
/* Define if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define if you have the `memset' function. */
#undef HAVE_MEMSET
/* Define if you have the `ptsname' function. */
#undef HAVE_PTSNAME
/* Define if you have the `putenv' function. */
#undef HAVE_PUTENV
/* Define if you have the `setgroups' function. */
#undef HAVE_SETGROUPS
/* Define if you have the `setlinebuf' function. */
#undef HAVE_SETLINEBUF
/* Define if you have the `setpgrp' function. */
#undef HAVE_SETPGRP
/* Define if you have the `setsid' function. */
#undef HAVE_SETSID
/* Define if you have the `setsockopt' function. */
#undef HAVE_SETSOCKOPT
/* Define if you have the `setttyent' function. */
#undef HAVE_SETTTYENT
/* Define if you have the `setvbuf' function. */
#undef HAVE_SETVBUF
/* Define if you have the <sgtty.h> header file. */ /* Define if you have the <sgtty.h> header file. */
#undef HAVE_SGTTY_H #undef HAVE_SGTTY_H
/* Define if you have the <shadow.h> header file. */ /* Define if you have the <shadow.h> header file. */
#undef HAVE_SHADOW_H #undef HAVE_SHADOW_H
/* Define if you have the `sigaction' function. */
#undef HAVE_SIGACTION
/* Define if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define if you have the <stropts.h> header file. */ /* Define if you have the <stropts.h> header file. */
#undef HAVE_STROPTS_H #undef HAVE_STROPTS_H
/* Define if you have the `sysconf' function. */
#undef HAVE_SYSCONF
/* Define if you have the <sysexits.h> header file. */
#undef HAVE_SYSEXITS_H
/* Define if you have the <sys/audit.h> header file. */ /* Define if you have the <sys/audit.h> header file. */
#undef HAVE_SYS_AUDIT_H #undef HAVE_SYS_AUDIT_H
/* Define if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define if you have the <sys/ioctl_compat.h> header file. */ /* Define if you have the <sys/ioctl_compat.h> header file. */
#undef HAVE_SYS_IOCTL_COMPAT_H #undef HAVE_SYS_IOCTL_COMPAT_H
/* Define if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define if you have the <sys/proc.h> header file. */ /* Define if you have the <sys/proc.h> header file. */
#undef HAVE_SYS_PROC_H #undef HAVE_SYS_PROC_H
@ -210,33 +196,72 @@
/* Define if you have the <sys/vlimit.h> header file. */ /* Define if you have the <sys/vlimit.h> header file. */
#undef HAVE_SYS_VLIMIT_H #undef HAVE_SYS_VLIMIT_H
/* Define if you have the <termio.h> header file. */ /* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_TERMIO_H #undef HAVE_SYS_WAIT_H
/* Define if you have the `tcgetattr' function. */
#undef HAVE_TCGETATTR
/* Define if you have the `tcgetpgrp' function. */
#undef HAVE_TCGETPGRP
/* Define if you have the `tcsendbreak' function. */
#undef HAVE_TCSENDBREAK
/* Define if you have the `tcsetattr' function. */
#undef HAVE_TCSETATTR
/* Define if you have the `tcsetpgrp' function. */
#undef HAVE_TCSETPGRP
/* Define if you have the <termios.h> header file. */ /* Define if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H #undef HAVE_TERMIOS_H
/* Define if you have the <termio.h> header file. */
#undef HAVE_TERMIO_H
/* Define if you have the <ttyent.h> header file. */ /* Define if you have the <ttyent.h> header file. */
#undef HAVE_TTYENT_H #undef HAVE_TTYENT_H
/* Define if you have the <types.h> header file. */
#undef HAVE_TYPES_H
/* Define if you have the <unistd.h> header file. */ /* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H #undef HAVE_UNISTD_H
/* Define if you have the `unlockpt' function. */
#undef HAVE_UNLOCKPT
/* Define if you have the <usersec.h> header file. */ /* Define if you have the <usersec.h> header file. */
#undef HAVE_USERSEC_H #undef HAVE_USERSEC_H
/* Define if you have the crypt library (-lcrypt). */ /* Define as the return type of signal handlers (`int' or `void'). */
#undef HAVE_LIBCRYPT #undef RETSIGTYPE
/* Define if you have the nsl library (-lnsl). */ /* Define if the `setpgrp' function takes no argument. */
#undef HAVE_LIBNSL #undef SETPGRP_VOID
/* Define if you have the socket library (-lsocket). */ /* Define if you have the ANSI C header files. */
#undef HAVE_LIBSOCKET #undef STDC_HEADERS
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Define if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `int' if <sys/types.h> does not define. */
#undef mode_t
/* Define if <signal.h> does not define sig_atomic_t */ /* Define if <signal.h> does not define sig_atomic_t */
#undef sig_atomic_t #undef sig_atomic_t
/* Define if <sys/socket.h> does not define socklen_t */ /* Define if <sys/socket.h> does not define socklen_t */
#undef socklen_t #undef socklen_t

4614
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@ AC_SUBST(MKDIR)
dnl ### Custom settings. ############################################ dnl ### Custom settings. ############################################
AC_MSG_CHECKING(for port number specification) AC_MSG_CHECKING(for port number specification)
AC_ARG_WITH(port, AC_ARG_WITH(port,
[ --with-port=PORT Specify port number [conserver]], AC_HELP_STRING([--with-port=PORT],[Specify port number [[conserver]]]),
[if test "$withval" != yes -a "$withval" != no; then [if test "$withval" != yes -a "$withval" != no; then
AC_DEFINE_UNQUOTED(DEFPORT, "$withval") AC_DEFINE_UNQUOTED(DEFPORT, "$withval")
AC_MSG_RESULT(port '$withval') AC_MSG_RESULT(port '$withval')
@ -25,9 +25,22 @@ AC_ARG_WITH(port,
[AC_DEFINE_UNQUOTED(DEFPORT, "conserver") [AC_DEFINE_UNQUOTED(DEFPORT, "conserver")
AC_MSG_RESULT(port 'conserver')]) AC_MSG_RESULT(port 'conserver')])
AC_MSG_CHECKING(for secondary channel base port)
AC_ARG_WITH(base,
AC_HELP_STRING([--with-base=PORT], [Base port for secondary channel [[0]]]),
[if test "$withval" != yes -a "$withval" != no; then
AC_DEFINE_UNQUOTED(DEFBASEPORT, "$withval")
AC_MSG_RESULT(port '$withval')
else
AC_DEFINE_UNQUOTED(DEFBASEPORT, "0")
AC_MSG_RESULT(port '0')
fi],
[AC_DEFINE_UNQUOTED(DEFBASEPORT, "0")
AC_MSG_RESULT(port '0')])
AC_MSG_CHECKING(for master conserver hostname) AC_MSG_CHECKING(for master conserver hostname)
AC_ARG_WITH(master, AC_ARG_WITH(master,
[ --with-master=MASTER Specify master server hostname [console]], AC_HELP_STRING([--with-master=MASTER],[Specify master server hostname [[console]]]),
[if test "$withval" != yes; then [if test "$withval" != yes; then
AC_DEFINE_UNQUOTED(MASTERHOST, "$withval") AC_DEFINE_UNQUOTED(MASTERHOST, "$withval")
AC_MSG_RESULT('$withval') AC_MSG_RESULT('$withval')
@ -40,7 +53,7 @@ AC_ARG_WITH(master,
AC_MSG_CHECKING(for configuration filename) AC_MSG_CHECKING(for configuration filename)
AC_ARG_WITH(cffile, AC_ARG_WITH(cffile,
[ --with-cffile=CFFILE Specify config filename [conserver.cf] ], AC_HELP_STRING([--with-cffile=CFFILE],[Specify config filename [[conserver.cf]]]),
[if test "$withval" != yes; then [if test "$withval" != yes; then
AC_DEFINE_UNQUOTED(CONFIGFILE, "$withval") AC_DEFINE_UNQUOTED(CONFIGFILE, "$withval")
AC_MSG_RESULT('$withval') AC_MSG_RESULT('$withval')
@ -53,7 +66,7 @@ AC_ARG_WITH(cffile,
AC_MSG_CHECKING(for password filename) AC_MSG_CHECKING(for password filename)
AC_ARG_WITH(pwdfile, AC_ARG_WITH(pwdfile,
[ --with-pwdfile=PWDFILE Specify password filename [conserver.passwd] ], AC_HELP_STRING([--with-pwdfile=PWDFILE],[Specify password filename [[conserver.passwd]]]),
[if test "$withval" != yes; then [if test "$withval" != yes; then
AC_DEFINE_UNQUOTED(PASSWDFILE, "$withval") AC_DEFINE_UNQUOTED(PASSWDFILE, "$withval")
AC_MSG_RESULT('$withval') AC_MSG_RESULT('$withval')
@ -66,7 +79,7 @@ AC_ARG_WITH(pwdfile,
AC_MSG_CHECKING(for log filename) AC_MSG_CHECKING(for log filename)
AC_ARG_WITH(logfile, AC_ARG_WITH(logfile,
[ --with-logfile=LOGFILE Specify log filename [/var/log/conserver] ], AC_HELP_STRING([--with-logfile=LOGFILE],[Specify log filename [[/var/log/conserver]]]),
[if test "$withval" != yes; then [if test "$withval" != yes; then
AC_DEFINE_UNQUOTED(LOGFILEPATH, "$withval") AC_DEFINE_UNQUOTED(LOGFILEPATH, "$withval")
AC_MSG_RESULT('$withval') AC_MSG_RESULT('$withval')
@ -79,7 +92,7 @@ AC_ARG_WITH(logfile,
AC_MSG_CHECKING(for PID filename) AC_MSG_CHECKING(for PID filename)
AC_ARG_WITH(pidfile, AC_ARG_WITH(pidfile,
[ --with-pidfile=PIDFILE Specify PID filepath [/var/run/conserver.pid] ], AC_HELP_STRING([--with-pidfile=PIDFILE],[Specify PID filepath [[/var/run/conserver.pid]]]),
[if test "$withval" != yes; then [if test "$withval" != yes; then
AC_DEFINE_UNQUOTED(PIDFILE, "$withval") AC_DEFINE_UNQUOTED(PIDFILE, "$withval")
AC_MSG_RESULT('$withval') AC_MSG_RESULT('$withval')
@ -92,7 +105,7 @@ AC_ARG_WITH(pidfile,
AC_MSG_CHECKING(for MAXMEMB setting) AC_MSG_CHECKING(for MAXMEMB setting)
AC_ARG_WITH(maxmemb, AC_ARG_WITH(maxmemb,
[ --with-maxmemb=MAXMEMB Specify maximum consoles per process [16]], AC_HELP_STRING([--with-maxmemb=MAXMEMB],[Specify maximum consoles per process [[16]]]),
[if test "$withval" != yes; then [if test "$withval" != yes; then
AC_DEFINE_UNQUOTED(MAXMEMB, $withval) AC_DEFINE_UNQUOTED(MAXMEMB, $withval)
AC_MSG_RESULT($withval) AC_MSG_RESULT($withval)
@ -105,7 +118,7 @@ AC_ARG_WITH(maxmemb,
AC_MSG_CHECKING(for MAXGRP setting) AC_MSG_CHECKING(for MAXGRP setting)
AC_ARG_WITH(maxgrp, AC_ARG_WITH(maxgrp,
[ --with-maxgrp=MAXGRP Specify maximum number of processes [32]], AC_HELP_STRING([--with-maxgrp=MAXGRP],[Specify maximum number of processes [[32]]]),
[if test "$withval" != yes; then [if test "$withval" != yes; then
AC_DEFINE_UNQUOTED(MAXGRP, $withval) AC_DEFINE_UNQUOTED(MAXGRP, $withval)
AC_MSG_RESULT($withval) AC_MSG_RESULT($withval)
@ -116,22 +129,9 @@ AC_ARG_WITH(maxgrp,
[AC_DEFINE_UNQUOTED(MAXGRP, 32) [AC_DEFINE_UNQUOTED(MAXGRP, 32)
AC_MSG_RESULT(32)]) AC_MSG_RESULT(32)])
AC_MSG_CHECKING(for 8bit setting)
AC_ARG_ENABLE(8bit,
[ --disable-8bit Disable 8bit data path ],
[if test "$enableval" != yes; then
AC_DEFINE_UNQUOTED(CPARITY, 1)
AC_MSG_RESULT(no)
else
AC_DEFINE_UNQUOTED(CPARITY, 0)
AC_MSG_RESULT(yes)
fi],
[AC_DEFINE_UNQUOTED(CPARITY, 0)
AC_MSG_RESULT(yes)])
AC_MSG_CHECKING(for connect() timeout) AC_MSG_CHECKING(for connect() timeout)
AC_ARG_WITH(timeout, AC_ARG_WITH(timeout,
[ --with-timeout=TIMEOUT Specify connect() timeout in seconds [10]], AC_HELP_STRING([--with-timeout=TIMEOUT],[Specify connect() timeout in seconds [[10]]]),
[if test "$withval" -gt 0 -o "$withval" -lt 300; then [if test "$withval" -gt 0 -o "$withval" -lt 300; then
AC_DEFINE_UNQUOTED(CONNECTTIMEOUT, $withval) AC_DEFINE_UNQUOTED(CONNECTTIMEOUT, $withval)
AC_MSG_RESULT($withval) AC_MSG_RESULT($withval)
@ -172,7 +172,7 @@ if test "$ac_cv_header_termios_h" != "yes"; then
fi fi
fi fi
AC_CHECK_HEADERS(unistd.h getopt.h sys/vlimit.h sys/resource.h ttyent.h sys/ttold.h sys/uio.h sys/proc.h sys/ioctl_compat.h usersec.h sys/select.h stropts.h sys/audit.h shadow.h sys/time.h crypt.h) AC_CHECK_HEADERS(unistd.h getopt.h sys/vlimit.h sys/resource.h ttyent.h sys/ttold.h sys/uio.h sys/proc.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)
AC_HEADER_TIME AC_HEADER_TIME
AC_HEADER_SYS_WAIT AC_HEADER_SYS_WAIT
AC_TYPE_MODE_T AC_TYPE_MODE_T
@ -218,7 +218,7 @@ AC_CHECK_LIB(crypt,crypt)
dnl ### Check for needed functions. ################################ dnl ### Check for needed functions. ################################
AC_CHECK_FUNCS(getopt strerror getrlimit getsid setsid getuserattr setgroups tcgetpgrp tcsetpgrp tcgetattr tcsetattr tcsendbreak setpgrp getutent setttyent wait3 getspnam setlinebuf setvbuf getpseudo ptsname flock sigaction setsockopt getdtablesize putenv memset memcpy memcmp) AC_CHECK_FUNCS(getopt strerror getrlimit getsid setsid getuserattr setgroups tcgetpgrp tcsetpgrp tcgetattr tcsetattr tcsendbreak setpgrp getutent setttyent getspnam setlinebuf setvbuf ptsname grantpt unlockpt flock sigaction setsockopt getdtablesize putenv memset memcpy memcmp sysconf getpassphrase)
AC_FUNC_SETPGRP AC_FUNC_SETPGRP

View File

@ -14,8 +14,6 @@ MKDIR = @MKDIR@
all: all:
.PHONY: clean distclean install
clean: clean:
rm -f *~ *.o $(ALL) core rm -f *~ *.o $(ALL) core
@ -23,6 +21,8 @@ distclean: clean
rm -f Makefile rm -f Makefile
install: install:
$(MKDIR) $(DESTDIR)$(mandir)/man8 $(MKDIR) $(DESTDIR)$(mandir)/man5
$(INSTALL) conserver.cf.man $(DESTDIR)$(mandir)/man8/conserver.cf.8 $(INSTALL) conserver.cf.man $(DESTDIR)$(mandir)/man5/conserver.cf.5
$(INSTALL) conserver.passwd.man $(DESTDIR)$(mandir)/man5/conserver.passwd.5
.PHONY: clean distclean install

View File

@ -1,19 +1,19 @@
.\" $Id: conserver.cf.man,v 1.10 2001-07-05 01:39:00-07 bryan Exp $ .\" $Id: conserver.cf.man,v 1.15 2001-07-26 10:23:16-07 bryan Exp $
.\" @(#)constab.5 01/06/91 OSU CIS; Thomas A. Fine .\" @(#)constab.5 01/06/91 OSU CIS; Thomas A. Fine
.TH CONSERVER.CF 4 "Local" .TH CONSERVER.CF 5 "Local"
.SH NAME .SH NAME
conserver.cf \- table of server console terminals used by conserver(8) conserver.cf \- console configuration file for conserver(8)
.SH SYNOPSIS .SH SYNOPSIS
.br .br
LOGDIR=\fIlogdirectory\fP .BI \s-1LOGDIR\s0= logdirectory
.br .br
TIMESTAMP=\fItimestamp-spec\fP .BI \s-1TIMESTAMP\s0= timestamp-spec
.br .br
\fIserver\fP:\fIdevice\fP[@\fIconserver\fP]:\fIbaud\fP:\fIlogfile\fP:\fItimestamp-spec\fP \fIname\fP:\fIdevice\fP[@\fIconserver\fP]:\fIbaud\fP:\fIlogfile\fP:\fItimestamp-spec\fP
.br .br
\fIserver\fP:!\fIhost\fP[@\fIconserver\fP]:\fIport\fP:\fIlogfile\fP:\fItimestamp-spec\fP \fIname\fP:!\fItermserver\fP[@\fIconserver\fP]:\fIport\fP:\fIlogfile\fP:\fItimestamp-spec\fP
.br .br
\fIserver\fP:|\fIcommand\fP[@\fIconserver\fP]::\fIlogfile\fP:\fItimestamp-spec\fP \fIname\fP:|\fIcommand\fP[@\fIconserver\fP]::\fIlogfile\fP:\fItimestamp-spec\fP
.br .br
\fB%%\fP \fB%%\fP
.br .br
@ -21,128 +21,155 @@ TIMESTAMP=\fItimestamp-spec\fP
.SH DESCRIPTION .SH DESCRIPTION
.B Conserver.cf .B Conserver.cf
is the configuration file for is the configuration file for
.IR conserver (8). .BR conserver (8).
It is read once upon startup;
modifications to the file take effect only upon restarting \fBconserver\fP.
All lines starting with the pound sign `#' are considered comment lines. All lines starting with the pound sign `#' are considered comment lines.
Blank lines are ignored. Blank lines are ignored.
.PP .PP
The first section of the file has lines that are separated into The first section of the file has lines that are separated into
six colon-separated fields: five colon-separated fields. Leading and trailing white space in each
.PP field is ignored.
\fIserver\fP name - this doesn't have to be the name of the server; .TP
it is used to refer to the server when using the console program. .I name
.PP the unique name by which this connection is referred to
\fIdevice\fP file name - the full path name of the device for this server. when using the \fBconsole\fP program.
This is typically the name of the host whose console is being monitored.
.TP
.I device
the full path name of the device for this line.
The \fIbaud\fP rate is the speed and parity for this console. The \fIbaud\fP rate is the speed and parity for this console.
Speed may be given as an integer, Speed may be given as an integer,
parity only requires the first letter of any of: even, odd, mark, space. parity only requires the first letter of any of: even, odd, mark, space.
For no parity, use the character `p'. For no parity, use the character `p'.
.PP .TP
!\fIhost\fP - the hostname of the server to connect to. .BI ! termserver
the hostname of the terminal server to connect to.
A socket connection will be made to port \fIport\fP (an integer). A socket connection will be made to port \fIport\fP (an integer).
.TP
.BI | command
the command to invoke on the console server.
.PP .PP
|\fIcommand\fP - the command to invoke on the console server. \fIdevice\fP, !\fItermserver\fP, and |\fIcommand\fP may be followed by
.PP a remote console server name in the form ``\fB@\fP\fIconserver\fP'',
\fIdevice\fP, !\fIhost\fP, and |\fIcommand\fP may contain a remote in which case the conserver daemon will send connections for \fIname\fP
console server name (ex. \fIhost\fP@\fIconserver\fP) in which case to the conserver running on the host named \fIconserver\fP.
the conserver will send connections for this server to \fIconserver\fP. When the ``\fB@\fP\fIconserver\fP'' notation is used,
.PP \fBconserver\fP recognizes consoles it should manage locally
\fIlogfile\fP - the full path name of file where all output from by comparing the IP address of \fIconserver\fP
this server is logged. Any occurance of `&' will be replaced with against the IP address of the name returned by gethostname().
the \fIserver\fP name. Any path that doesn't begin with a `/' will Thus, it will recognize host aliases, but not names that map to
have \fIlogdirectory\fP (value of LOGDIR) prepended to it. different IP addresses that may exist on the same host,
.PP so care must be used in specifying the hostname.
\fItimestamp-spec\fP - specifies the time between Since \fBconserver\fP does recognize its own hostname,
timestamps applied to the console log file and activity logging. the same cf file may be used by all servers in a network
if every console line includes a ``\fB@\fP\fIconserver\fP'' specification.
.TP
.I logfile
the full path name of file where all output from
this host is logged. Any occurrence of `&' will be replaced with
\fIname\fP. Any path that doesn't begin with a `/' will
have \fIlogdirectory\fP (as specified in the nearest preceding
\fB\s-1LOGDIR=\s0\fP
line) prepended to it.
.TP
.I timestamp-spec
specifies the time between
timestamps applied to the console log file and
whether to log read/write connection actions.
The format of the specification is The format of the specification is
[\fImark-interval\fP(\fIm\fP|\fIh\fP|\fId\fP|\fIl\fP)][\fIa\fP]. [\fImark-interval\fP[\fBm\fP|\fBh\fP|\fBd\fP|\fBl\fP]][\fBa\fP].
The timestamps look like `[-- MARK -- Mon Jan 25 14:46:56 PST 1999]'. The `m', The timestamps look like `[-- MARK -- Mon Jan 25 14:46:56 PST 1999]'.
`h', and `d' tags specify `minutes', `hours', and `days'. The `l' tag The `\fBm\fP', `\fBh\fP', and `\fBd\fP' tags specify
`minutes' (the default), `hours', and `days'. The `\fBl\fP' tag
specifies `lines' and will cause timestamps of the form specifies `lines' and will cause timestamps of the form
`[Mon Jan 25 14:46:56 PST 1999]' to `[Mon Jan 25 14:46:56 PST 1999]' to
be placed every \fImark-interval\fP lines (a newline character signifies be placed every \fImark-interval\fP lines (a newline character signifies
a new line). So, `5h' specifies every 5 hours and `2l' specifies every a new line). So, `5h' specifies every five hours and `2l' specifies every
two lines. An `a' can be specified to add activity logs to the two lines.
logfile: `attached', `detached', and `bumped' messages. An `\fBa\fP' can be specified to add logs of
.PP `attached', `detached', and `bumped' actions,
A default \fItimestamp-spec\fP can be specified by using the TIMESTAMP= including the user's name and the host from which the
syntax. All consoles below the TIMESTAMP= line will have use that \fBconsole\fP connection was made,
\fItimestamp-spec\fP unless overridden. To turn off marks for a specific to the logfile.
.IP
A default \fItimestamp-spec\fP can be specified by using the
\fB\s-1TIMESTAMP=\s0\fP syntax.
All consoles below the \fB\s-1TIMESTAMP=\s0\fP line will use that
\fItimestamp-spec\fP unless overridden on a per-line basis,
and until superseded by another \fB\s-1TIMESTAMP=\s0\fP line.
To turn off marks for a specific
console, use a \fImark-interval\fP of zero. console, use a \fImark-interval\fP of zero.
.PP .PP
This section is terminated with a `%%' token on a line by itself. This section is terminated with a `\fB%%\fP' token on a line by itself.
.PP .PP
The next section of the file contains a list of hosts and addresses The next section of the file contains a list of hosts and addresses
which are allowed to connect to the console server. Three levels which are allowed to connect to the console server.
of access all allowed, ``trust'', ``allow'', .B Conserver
and ``refuse''. looks for the first match in the config file
The access modifier is followed by a colon and a list of addresses or for a client's IP address (or network),
host names. or hostname (or domain) if it is able to do a reverse lookup on the IP address,
Any complete suffix of a host name my be used to allow access for all hosts to determine the level of access to be granted.
Three levels of access may be specified: ``\fBtrust\fP'', ``\fBallow\fP'',
and ``\fBrefuse\fP''.
The access level is followed by a colon and a space-separated list of
addresses or host names.
Any number of any combination of these levels may be specified,
bearing in mind that conserver uses the first match for each incoming
client connection, so order is important.
.PP
Any complete suffix of a host name may be used to define access for all hosts
in that subdomain. in that subdomain.
For example `cc.purdue.edu' will allow `mentor.cc.purdue.edu' For example, `\fBcc.purdue.edu\fP' will allow `mentor.cc.purdue.edu'
and `mace.cc.purdue.edu', but not `pucc.purdue.edu' or `hack.purdue.edu'. and `mace.cc.purdue.edu', but not `pucc.purdue.edu' or `hack.purdue.edu'.
For IP addresses, optional netmasks may be specified. For example `192.168.1.0' For IP addresses, optional netmask lengths may be specified
will allow the class C space of 192.168.1.0. `192.168.1.0/25' will only allow in CIDR `/' notation.
For example, `\fB192.168.1.0\fP' will allow the class C space of 192.168.1.0,
but `\fB192.168.1.0/25\fP' will allow
only the lower half of that same address space (192.168.1.0 thru 192.168.1.127). only the lower half of that same address space (192.168.1.0 thru 192.168.1.127).
.SH EXAMPLE .SH EXAMPLE
# server:path:baud:/usr/adm/logfile:mark # name:path:baud:/usr/adm/logfile:mark
.br .nf
LOGDIR=/tmp LOGDIR=/tmp
.br
# #
.br
# This logs to /tmp/treelog... # This logs to /tmp/treelog...
.br
tree:/dev/ttyj0:9600e:&log: tree:/dev/ttyj0:9600e:&log:
.br
# #
.br
# This logs to /tmp/fishlog... # This logs to /tmp/fishlog...
.br
fish:/dev/ttyj1:4800e:fishlog: fish:/dev/ttyj1:4800e:fishlog:
.br
# #
.br
# Now we're defaulting to /var/tmp for logfiles... # Now we're defaulting to /var/tmp for logfiles...
.br
LOGDIR=/var/tmp LOGDIR=/var/tmp
.br
# #
.br
# So, this is /var/tmp/birdlog # So, this is /var/tmp/birdlog
.br
bird:/dev/ttyj2:4800m:&log: bird:/dev/ttyj2:4800m:&log:
.br
# #
.br
# And this is /var/tmp/solarlog... # And this is /var/tmp/solarlog...
.br
solar:|telnet solar::solarlog: solar:|telnet solar::solarlog:
.br
# #
.br
# Now things are all in /var/consoles/<console name> # Now things are all in /var/consoles/<console name>
.br
LOGDIR=/var/consoles LOGDIR=/var/consoles
.br
shell:|::&: shell:|::&:
.br
# #
.br # These open connections to ports 2003 and 2004 of ts1...
# This opens a connection to port 2003 of ts1...
.br
tribe:!ts1:2003:&: tribe:!ts1:2003:&:
.br
reptile:!ts1:2004:&: reptile:!ts1:2004:&:
.br #
# This opens /dev/ttyh0 if running on extra.cc.purdue.edu;
# otherwise, clients are redirected to that host.
mentor:/dev/ttyh0@extra.cc.purdue.edu:2400e:&: mentor:/dev/ttyh0@extra.cc.purdue.edu:2400e:&:
.br
%% %%
.br #
# access restrictions # access restrictions
.br # (note that the "badhost.cc.purdue.edu" entry must appear
# before the "cc.purdue.edu" entry if connections from
# "badhost" are to be rejected, since only the first match
# is used)
#
trusted: console.cc.purdue.edu 128.210.7.90 trusted: console.cc.purdue.edu 128.210.7.90
.br refuse: badhost.cc.purdue.edu
allow: cc.purdue.edu stat.cc.purdue.edu allow: cc.purdue.edu stat.cc.purdue.edu
.SH "SEE ALSO" .SH "SEE ALSO"
console(1), conserver(8) .BR console (1),
.BR conserver.passwd (5),
.BR conserver (8)

View File

@ -0,0 +1,65 @@
.\" $Id: conserver.passwd.man,v 1.2 2001-07-22 11:48:29-07 bryan Exp $
.TH CONSERVER.PASSWD 5 "Local"
.SH NAME
conserver.passwd \- user access information for conserver(8)
.SH SYNOPSIS
.br
\fIusername\fB:\fIpassword\fB:\fIconsoles\fR
.SH DESCRIPTION
The \fBconserver.passwd\fP file
is the user authentication and authorization file for
.BR conserver (8).
Upon each incoming client connection,
\fBconserver\fP opens and reads the \fBconserver.passwd\fP file,
so edits to the file take effect immediately.
It reads only until the first \fIusername\fP match.
.PP
Each line consists of three colon-separated fields,
as follows:
.TP
.I username
the login name of the authorized user,
or the string ``\fB*any*\fP'' to match any user.
This is compared against the name sent by the \fBconsole\fP client,
based either on the user's identity or on the \fB\-l\fP option.
Since \fBconserver\fP only uses the first \fIusername\fP match,
an ``\fB*any*\fP'' entry will apply to any user
without an entry earlier in the file.
.TP
.I password
the encrypted password,
or the string ``\fB*passwd*\fP''
to indicate that \fBconserver\fP should look up the user's password
in the system \fBpasswd\fP (or \fBshadow\fP) database.
If this field is empty, password checking is bypassed for this user.
.TP
.I consoles
a comma- and/or space-separated list of consoles
to which the user is permitted to connect,
or the string ``\fBany\fP'' to allow access to any console.
These names must match the console names in the \fBconserver.cf\fP file.
.SH EXAMPLE
.TP 30
\fBmary:r71mXjfALB5Ak:any\fP
Mary may connect to any console if her password matches;
it does not matter whether she has a login on the conserver host.
.TP
\fBfred:*passwd*:foo.example.com,bar.example.com\fP
Fred may connect only to the listed consoles,
and only with his regular login password on the conserver host.
.TP
\fBbozo:*:\fP
Bozo is not allowed access to any consoles.
.TP
\fB*any*:*passwd*:any\fP
Anyone not listed above may access any console
if they have a regular login and know the password.
.SH "SEE ALSO"
.BR console (1),
.BR conserver.cf (5),
.BR conserver (8)
.SH BUGS
.PP
There is currently no way provided by the conserver package
to generate the encrypted password strings
besides copying them from the system \fBpasswd\fP database.

View File

@ -128,6 +128,53 @@ being released in hopes that it will help others. There is no warranty
or support implied by the distribution of the software. or support implied by the distribution of the software.
</P> </P>
<P>
So, what the heck is up with all the different conserver versions?
Well, the original authors are continuing to distribute their own
threads of the software so you have three main threads (as far as I
know). First, there's Tom Fine's thread at <A
HREF="http://hea-www.harvard.edu/~fine/Tech/console-server.html">http://hea-www.harvard.edu/~fine/Tech/console-server.html</A>.
He isn't actively developing it, however, according to the website.
Next, there's Kevin Braunsdorf's version at <A
HREF="ftp://ftp.physics.purdue.edu/pub/pundits/">ftp://ftp.physics.purdue.edu/pub/pundits/</A>.
Kevin is semi-actively working on his thread. Doesn't look like any
new versions have been out since August 2000 (version 8.5), but maybe
this info will be out of date by the time you read this. Lastly, the
conserver.com version is based on Kevin's "5.21-Beta" distribution, but
since <B>HEAVILY</B> modified and enhanced (more details in the
"Origin" section above).
</P>
<P>
If I were looking for a conserver package I would either use Kevin's
latest distribution or the conserver.com distribution. Which one?
Well, obviously I'm biased and believe the conserver.com distribution
should be your choice, but Kevin's does have UPS (serial port line
toggling bits) that the conserver.com version doesn't have. What does
the conserver.com distribution have? Well, in reality, too many things
to list. You'll have to look at the <A
HREF="http://www.conserver.com/CHANGES">CHANGES</A> file and see the
enhancements, bug fixes, and general development since the original.
Don't let the version numbers fool you - you'll have to compare and
contrast for yourself.
</P>
<H3>Downloading</H3>
<P>
The current version, released on RELEASE_DATE, is <A
HREF="http://www.conserver.com/7.1.0.tar.gz">
7.1.0.tar.gz</A>. You can get it via <A
HREF="ftp://ftp.conserver.com/conserver/7.1.0.tar.gz">FTP</A>
or <A HREF="http://www.conserver.com/7.1.0.tar.gz">HTTP</A>.
See the <A HREF="http://www.conserver.com/CHANGES">CHANGES</A> file for
information on the latest updates.
</P>
<P> <P>
As of version 6.1.7, the packaging and numbering scheme has changed. I As of version 6.1.7, the packaging and numbering scheme has changed. I
used to package conserver as conserver-GNAC-v.vv. Since GNAC (now <A used to package conserver as conserver-GNAC-v.vv. Since GNAC (now <A
@ -139,18 +186,6 @@ original authors and I couldn't come up with a good replacement for the
GNAC name - sad, but true. GNAC name - sad, but true.
</P> </P>
<H3>Downloading</H3>
<P>
The current version is <A
HREF="http://www.conserver.com/7.0.3.tar.gz">
7.0.3.tar.gz</A>. You can get it via <A
HREF="ftp://ftp.conserver.com/conserver/7.0.3.tar.gz">FTP</A>
or <A HREF="http://www.conserver.com/7.0.3.tar.gz">HTTP</A>.
See the <A HREF="http://www.conserver.com/CHANGES">CHANGES</A> file for
information on the latest updates.
</P>
<H3>Installation</H3> <H3>Installation</H3>
<P> <P>
@ -159,6 +194,24 @@ Check the
file for instructions. file for instructions.
</P> </P>
<H3>Systems Tested</H3>
<P>
Here's a list of systems that I've been told can successfully compile conserver. If anyone has more to add to this list, please let me know.
</P>
<UL>
<LI>Solaris 2.5.1 thru 8 (sparc/x86), gcc
<LI>BSDI 3.X, gcc
<LI>MacOS X
<LI>Linux 2.2.18 (x86), gcc
<LI>Linux 2.4.2 (x86), gcc
<LI>FreeBSD 4.2 (x86), gcc
<LI>cygwin (w2k),gcc 2.95.3
<LI>DEC Tru64 4.0, gcc
<LI>DEC Tru64 4.0/5.1, DEC cc
<LI>HP-UX 10.20, gcc
</UL>
<H3>Other Good Information</H3> <H3>Other Good Information</H3>
<P> <P>

View File

@ -26,18 +26,16 @@ LIBS = @LIBS@
### Makefile rules - no user-servicable parts below ### Makefile rules - no user-servicable parts below
CONSERVER_OBJS = access.o client.o consent.o group.o main.o master.o \ CONSERVER_OBJS = access.o client.o consent.o group.o main.o master.o \
readcfg.o fallback.o output.o readcfg.o fallback.o util.o
CONSERVER_HDRS = ../config.h $(top_srcdir)/compat.h $(srcdir)/access.h \ CONSERVER_HDRS = ../config.h $(top_srcdir)/compat.h $(srcdir)/access.h \
$(srcdir)/client.h $(srcdir)/consent.h $(srcdir)/group.h \ $(srcdir)/client.h $(srcdir)/consent.h $(srcdir)/group.h \
$(srcdir)/main.h $(srcdir)/master.h $(srcdir)/readcfg.h \ $(srcdir)/main.h $(srcdir)/master.h $(srcdir)/readcfg.h \
$(srcdir)/output.h $(srcdir)/util.h
ALL = conserver ALL = conserver
all: $(ALL) all: $(ALL)
.PHONY: clean distclean install
conserver: $(CONSERVER_OBJS) conserver: $(CONSERVER_OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o conserver $(CONSERVER_OBJS) $(LIBS) $(CC) $(CFLAGS) $(LDFLAGS) -o conserver $(CONSERVER_OBJS) $(LIBS)
@ -57,3 +55,5 @@ install: conserver
$(INSTALL) conserver.man $(DESTDIR)$(mandir)/man8/conserver.8 $(INSTALL) conserver.man $(DESTDIR)$(mandir)/man8/conserver.8
$(MKDIR) $(DESTDIR)$(sysconfdir) $(MKDIR) $(DESTDIR)$(sysconfdir)
[ -f $(DESTDIR)$(sysconfdir)/conserver.rc ] || $(INSTALL) conserver.rc $(DESTDIR)$(sysconfdir) [ -f $(DESTDIR)$(sysconfdir)/conserver.rc ] || $(INSTALL) conserver.rc $(DESTDIR)$(sysconfdir)
.PHONY: clean distclean install

View File

@ -1,5 +1,5 @@
/* /*
* $Id: access.c,v 5.26 2001-07-03 02:07:34-07 bryan Exp $ * $Id: access.c,v 5.35 2001-07-23 00:45:49-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -51,30 +51,18 @@
#include <pwd.h> #include <pwd.h>
#include <compat.h> #include <compat.h>
#include <port.h> #include <port.h>
#include <util.h>
#include <access.h> #include <access.h>
#include <consent.h> #include <consent.h>
#include <client.h> #include <client.h>
#include <group.h> #include <group.h>
#include <readcfg.h> #include <readcfg.h>
#include <main.h> #include <main.h>
#include <output.h>
/* in the routines below (the init code) we can bomb if malloc fails (ksb)
*/
void
OutOfMem()
{
static char acNoMem[] = ": out of memory\n";
write(2, progname, strlen(progname));
write(2, acNoMem, sizeof(acNoMem)-1);
exit(45);
}
/* Compare an Internet address (IPv4 expected), with an address pattern /* Compare an Internet address (IPv4 expected), with an address pattern
* passed as a character string representing an address in the Internet * passed as a character string representing an address in the Internet
* standard `.' notation, optionally followed by a slash and an integer * standard `.' notation, optionally followed by a slash and an integer
@ -89,8 +77,8 @@ OutOfMem()
*/ */
int int
AddrCmp(addr, pattern) AddrCmp(addr, pattern)
struct in_addr *addr; struct in_addr *addr;
char *pattern; char *pattern;
{ {
unsigned long int hostaddr, pattern_addr, netmask; unsigned long int hostaddr, pattern_addr, netmask;
char buf[200], *p, *slash_posn; char buf[200], *p, *slash_posn;
@ -100,10 +88,9 @@ char *pattern;
if (strlen(pattern) >= sizeof(buf)) if (strlen(pattern) >= sizeof(buf))
return 1; /* too long to handle */ return 1; /* too long to handle */
strncpy(buf, pattern, sizeof(buf)); strncpy(buf, pattern, sizeof(buf));
buf[slash_posn-pattern] = '\0'; /* isolate the address */ buf[slash_posn - pattern] = '\0'; /* isolate the address */
p = buf; p = buf;
} } else
else
p = pattern; p = pattern;
pattern_addr = inet_addr(p); pattern_addr = inet_addr(p);
@ -112,7 +99,7 @@ char *pattern;
if (slash_posn) { if (slash_posn) {
/* convert explicit netmask */ /* convert explicit netmask */
int mask_bits = atoi(slash_posn+1); int mask_bits = atoi(slash_posn + 1);
for (netmask = 0; mask_bits > 0; --mask_bits) for (netmask = 0; mask_bits > 0; --mask_bits)
netmask = 0x80000000 | (netmask >> 1); netmask = 0x80000000 | (netmask >> 1);
} else { } else {
@ -130,33 +117,38 @@ char *pattern;
netmask = htonl(netmask); netmask = htonl(netmask);
if (~netmask & pattern_addr) if (~netmask & pattern_addr)
netmask = 0xffffffff; /* compare entire addresses */ netmask = 0xffffffff; /* compare entire addresses */
hostaddr = *(unsigned long int*)addr; hostaddr = *(unsigned long int *)addr;
Debug( "Access check: host=%lx(%lx/%lx)", hostaddr & netmask, hostaddr, netmask ); Debug("Access check: host=%lx(%lx/%lx)", hostaddr & netmask,
Debug( "Access check: acl=%lx(%lx/%lx)", pattern_addr & netmask, pattern_addr, netmask ); hostaddr, netmask);
Debug("Access check: acl=%lx(%lx/%lx)", pattern_addr & netmask,
pattern_addr, netmask);
return (hostaddr & netmask) != (pattern_addr & netmask); return (hostaddr & netmask) != (pattern_addr & netmask);
} }
/* return the access type for a given host entry (ksb) /* return the access type for a given host entry (ksb)
*/ */
char char
AccType(addr,hname) AccType(addr, hname)
struct in_addr *addr; struct in_addr *addr;
char *hname; char *hname;
{ {
register int i; int i;
register char *pcName; char *pcName;
register int len; int len;
if ( fDebug ) { if (fDebug) {
if (hname) if (hname)
Debug( "Access check: hostname=%s, ip=%s", hname, inet_ntoa(*addr) ); Debug("Access check: hostname=%s, ip=%s", hname,
inet_ntoa(*addr));
else else
Debug( "Access check: hostname=<unresolvable>, ip=%s", inet_ntoa(*addr) ); Debug("Access check: hostname=<unresolvable>, ip=%s",
inet_ntoa(*addr));
} }
for (i = 0; i < iAccess; ++i) { for (i = 0; i < iAccess; ++i) {
Debug( "Access check: who=%s, trust=%c", pACList[i].pcwho, pACList[i].ctrust ); Debug("Access check: who=%s, trust=%c", pACList[i].pcwho,
if (isdigit((int)(pACList[i].pcwho[0]))) { pACList[i].ctrust);
if (pACList[i].isCIDR != 0) {
if (0 == AddrCmp(addr, pACList[i].pcwho)) { if (0 == AddrCmp(addr, pACList[i].pcwho)) {
return pACList[i].ctrust; return pACList[i].ctrust;
} }
@ -166,7 +158,7 @@ char *hname;
pcName = hname; pcName = hname;
len = strlen(pcName); len = strlen(pcName);
while (len >= pACList[i].ilen) { while (len >= pACList[i].ilen) {
Debug( "Access check: name=%s", pcName ); Debug("Access check: name=%s", pcName);
if (0 == strcmp(pcName, pACList[i].pcwho)) { if (0 == strcmp(pcName, pACList[i].pcwho)) {
return pACList[i].ctrust; return pACList[i].ctrust;
} }
@ -186,20 +178,20 @@ char *hname;
*/ */
void void
SetDefAccess(hpLocal) SetDefAccess(hpLocal)
struct hostent *hpLocal; struct hostent *hpLocal;
{ {
register char *pcWho, *pcDomain; char *pcWho, *pcDomain;
register int iLen; int iLen;
char *addr; char *addr;
struct in_addr *aptr; struct in_addr *aptr;
aptr = (struct in_addr *)(hpLocal->h_addr); aptr = (struct in_addr *)(hpLocal->h_addr);
addr = inet_ntoa(*aptr); addr = inet_ntoa(*aptr);
pACList = (ACCESS *)calloc(3, sizeof(ACCESS)); pACList = (ACCESS *) calloc(3, sizeof(ACCESS));
if ((ACCESS *)0 == pACList) { if ((ACCESS *) 0 == pACList) {
OutOfMem(); OutOfMem();
} }
if ((char *)0 == (pcWho = malloc(strlen(addr)+1))) { if ((char *)0 == (pcWho = malloc(strlen(addr) + 1))) {
OutOfMem(); OutOfMem();
} }
strcpy(pcWho, addr); strcpy(pcWho, addr);
@ -207,8 +199,8 @@ struct hostent *hpLocal;
pACList[iAccess].ilen = strlen(pcWho); pACList[iAccess].ilen = strlen(pcWho);
pACList[iAccess].pcwho = pcWho; pACList[iAccess].pcwho = pcWho;
Debug( "Access list prime: trust=%c, who=%s", pACList[iAccess].ctrust, Debug("Access list prime: trust=%c, who=%s", pACList[iAccess].ctrust,
pACList[iAccess].pcwho ); pACList[iAccess].pcwho);
iAccess++; iAccess++;
@ -217,13 +209,13 @@ struct hostent *hpLocal;
} }
++pcDomain; ++pcDomain;
iLen = strlen(pcDomain); iLen = strlen(pcDomain);
pcWho = malloc(iLen+1); pcWho = malloc(iLen + 1);
pACList[iAccess].ctrust = 'a'; pACList[iAccess].ctrust = 'a';
pACList[iAccess].ilen = iLen; pACList[iAccess].ilen = iLen;
pACList[iAccess].pcwho = strcpy(pcWho, pcDomain); pACList[iAccess].pcwho = strcpy(pcWho, pcDomain);
Debug( "Access list prime: trust=%c, who=%s", pACList[iAccess].ctrust, Debug("Access list prime: trust=%c, who=%s", pACList[iAccess].ctrust,
pACList[iAccess].pcwho ); pACList[iAccess].pcwho);
iAccess++; iAccess++;
} }
@ -233,15 +225,15 @@ struct hostent *hpLocal;
*/ */
REMOTE * REMOTE *
FindUniq(pRCAll) FindUniq(pRCAll)
register REMOTE *pRCAll; REMOTE *pRCAll;
{ {
register REMOTE *pRC; REMOTE *pRC;
/* INV: tail of the list we are building always contains only /* INV: tail of the list we are building always contains only
* uniq hosts, or the empty list. * uniq hosts, or the empty list.
*/ */
if ((REMOTE *)0 == pRCAll) { if ((REMOTE *) 0 == pRCAll) {
return (REMOTE *)0; return (REMOTE *) 0;
} }
pRCAll->pRCuniq = FindUniq(pRCAll->pRCnext); pRCAll->pRCuniq = FindUniq(pRCAll->pRCnext);
@ -249,11 +241,10 @@ register REMOTE *pRCAll;
/* if it is in the returned list of uniq hosts, return that list /* if it is in the returned list of uniq hosts, return that list
* else add us by returning our node * else add us by returning our node
*/ */
for (pRC = pRCAll->pRCuniq; (REMOTE *)0 != pRC; pRC = pRC->pRCuniq) { for (pRC = pRCAll->pRCuniq; (REMOTE *) 0 != pRC; pRC = pRC->pRCuniq) {
if (0 == strcmp(pRC->rhost, pRCAll->rhost)) { if (0 == strcmp(pRC->rhost, pRCAll->rhost)) {
return pRCAll->pRCuniq; return pRCAll->pRCuniq;
} }
} }
return pRCAll; return pRCAll;
} }

View File

@ -1,5 +1,5 @@
/* /*
* $Id: access.h,v 5.10 2001-02-21 17:26:06-08 bryan Exp $ * $Id: access.h,v 5.13 2001-07-17 14:14:11-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -41,6 +41,7 @@ typedef struct access {
char ctrust; /* how much do we trust the host */ char ctrust; /* how much do we trust the host */
int ilen; /* length (strlen) of pcwho */ int ilen; /* length (strlen) of pcwho */
char *pcwho; /* what is the hosts name/ip number */ char *pcwho; /* what is the hosts name/ip number */
int isCIDR; /* is this a CIDR addr (or hostname?) */
} ACCESS; } ACCESS;
typedef struct remote { /* console at another host */ typedef struct remote { /* console at another host */
@ -50,7 +51,6 @@ typedef struct remote { /* console at another host */
char rhost[256]; /* remote host to call to get it */ char rhost[256]; /* remote host to call to get it */
} REMOTE; } REMOTE;
extern void OutOfMem();
extern REMOTE *FindUniq(); extern REMOTE *FindUniq();
extern char AccType(); extern char AccType();
extern void SetDefAccess(); extern void SetDefAccess();

View File

@ -1,5 +1,5 @@
/* /*
* $Id: client.c,v 5.28 2001-06-29 00:26:39-07 bryan Exp $ * $Id: client.c,v 5.32 2001-07-23 00:54:11-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -50,8 +50,9 @@
#include <pwd.h> #include <pwd.h>
#include <compat.h> #include <compat.h>
#include <port.h> #include <port.h>
#include <util.h>
#include <consent.h> #include <consent.h>
#include <client.h> #include <client.h>
#include <group.h> #include <group.h>
@ -61,29 +62,29 @@
*/ */
CONSCLIENT * CONSCLIENT *
FindWrite(pCL) FindWrite(pCL)
CONSCLIENT *pCL; CONSCLIENT *pCL;
{ {
/* return the first guy to have the `want write' bit set /* return the first guy to have the `want write' bit set
* (tell him of the promotion, too) we could look for the * (tell him of the promotion, too) we could look for the
* most recent or some such... I guess it doesn't matter that * most recent or some such... I guess it doesn't matter that
* much. * much.
*/ */
for (/*passed in*/; (CONSCLIENT *)0 != pCL; pCL = pCL->pCLnext) { for ( /*passed in */ ; (CONSCLIENT *) 0 != pCL; pCL = pCL->pCLnext) {
if (!pCL->fwantwr) if (!pCL->fwantwr)
continue; continue;
if (!pCL->pCEto->fup || pCL->pCEto->fronly) if (!pCL->pCEto->fup || pCL->pCEto->fronly)
break; break;
pCL->fwantwr = 0; pCL->fwantwr = 0;
pCL->fwr = 1; pCL->fwr = 1;
if ( pCL->pCEto->nolog ) { if (pCL->pCEto->nolog) {
CSTROUT(pCL->fd, "\r\n[attached (nologging)]\r\n"); fileWrite(pCL->fd, "\r\n[attached (nologging)]\r\n", -1);
} else { } else {
CSTROUT(pCL->fd, "\r\n[attached]\r\n"); fileWrite(pCL->fd, "\r\n[attached]\r\n", -1);
} }
tagLogfile(pCL->pCEto, "%s attached", pCL->acid); tagLogfile(pCL->pCEto, "%s attached", pCL->acid);
return pCL; return pCL;
} }
return (CONSCLIENT *)0; return (CONSCLIENT *) 0;
} }
/* show a character as a string so the user cannot mistake it for (ksb) /* show a character as a string so the user cannot mistake it for (ksb)
@ -93,10 +94,10 @@ CONSCLIENT *pCL;
*/ */
char * char *
FmtCtl(ci, pcIn) FmtCtl(ci, pcIn)
int ci; int ci;
char *pcIn; char *pcIn;
{ {
register char *pcOut = pcIn; char *pcOut = pcIn;
unsigned char c; unsigned char c;
c = ci & 0xff; c = ci & 0xff;
@ -131,22 +132,24 @@ char *pcIn;
*/ */
void void
Replay(fdLog, fdOut, iBack) Replay(fdLog, fdOut, iBack)
int fdLog, fdOut, iBack; CONSFILE *fdLog;
CONSFILE *fdOut;
int iBack;
{ {
register int tot, nCr; int tot, nCr;
register char *pc; char *pc;
register off_t where; off_t where;
auto char bf[MAXREPLAY+2]; char bf[MAXREPLAY + 2];
auto struct stat stLog; struct stat stLog;
if (-1 == fdLog) { if ((CONSFILE *) 0 == fdLog) {
CSTROUT(fdOut, "[no log file on this console]\r\n"); fileWrite(fdOut, "[no log file on this console]\r\n", -1);
return; return;
} }
/* find the size of the file /* find the size of the file
*/ */
if (0 != fstat(fdLog, & stLog)) { if (0 != fileStat(fdLog, &stLog)) {
return; return;
} }
@ -159,21 +162,21 @@ int fdLog, fdOut, iBack;
#if defined(SEEK_SET) #if defined(SEEK_SET)
/* PTX and maybe other Posix systems /* PTX and maybe other Posix systems
*/ */
if (lseek(fdLog, where, SEEK_SET) < 0) { if (fileSeek(fdLog, where, SEEK_SET) < 0) {
return; return;
} }
#else #else
if (lseek(fdLog, where, L_SET) < 0) { if (fileSeek(fdLog, where, L_SET) < 0) {
return; return;
} }
#endif #endif
if ((tot = read(fdLog, bf, MAXREPLAY)) <= 0) { if ((tot = fileRead(fdLog, bf, MAXREPLAY)) <= 0) {
return; return;
} }
bf[tot] = '@'; bf[tot] = '@';
pc = & bf[tot]; pc = &bf[tot];
nCr = 0; nCr = 0;
while (--pc != bf) { while (--pc != bf) {
if ('\n' == *pc && iBack == nCr++) { if ('\n' == *pc && iBack == nCr++) {
@ -182,7 +185,7 @@ int fdLog, fdOut, iBack;
} }
} }
(void)write(fdOut, pc, tot-(pc - bf)); (void)fileWrite(fdOut, pc, tot - (pc - bf));
} }
@ -201,81 +204,80 @@ typedef struct HLnode {
} HELP; } HELP;
static HELP aHLTable[] = { static HELP aHLTable[] = {
{ WHEN_ALWAYS, ". disconnect"}, {WHEN_ALWAYS, ". disconnect"},
{ WHEN_ALWAYS, "a attach read/write"}, {WHEN_ALWAYS, "a attach read/write"},
{ WHEN_ATTACH, "c toggle flow control"}, {WHEN_ATTACH, "c toggle flow control"},
{ WHEN_ATTACH, "d down a console"}, {WHEN_ATTACH, "d down a console"},
{ WHEN_ALWAYS, "e change escape sequence"}, {WHEN_ALWAYS, "e change escape sequence"},
{ WHEN_ALWAYS, "f force attach read/write"}, {WHEN_ALWAYS, "f force attach read/write"},
{ WHEN_ALWAYS, "g group info"}, {WHEN_ALWAYS, "g group info"},
{ WHEN_ATTACH, "L toggle logging on/off"}, {WHEN_ATTACH, "L toggle logging on/off"},
{ WHEN_ATTACH, "l1 send break (halt host!)"}, {WHEN_ATTACH, "l1 send break (halt host!)"},
{ WHEN_ALWAYS, "o (re)open the tty and log file"}, {WHEN_ALWAYS, "o (re)open the tty and log file"},
{ WHEN_ALWAYS, "p replay the last 60 lines"}, {WHEN_ALWAYS, "p replay the last 60 lines"},
{ WHEN_ALWAYS, "r replay the last 20 lines"}, {WHEN_ALWAYS, "r replay the last 20 lines"},
{ WHEN_ATTACH, "s spy read only"}, {WHEN_ATTACH, "s spy read only"},
{ WHEN_ALWAYS, "u show host status"}, {WHEN_ALWAYS, "u show host status"},
{ WHEN_ALWAYS, "v show version info"}, {WHEN_ALWAYS, "v show version info"},
{ WHEN_ALWAYS, "w who is on this console"}, {WHEN_ALWAYS, "w who is on this console"},
{ WHEN_ALWAYS, "x show console baud info"}, {WHEN_ALWAYS, "x show console baud info"},
{ WHEN_ALWAYS, "z suspend the connection"}, {WHEN_ALWAYS, "z suspend the connection"},
{ WHEN_ALWAYS, "<cr> ignore/abort command"}, {WHEN_ALWAYS, "<cr> ignore/abort command"},
{ WHEN_ALWAYS, "? print this message"}, {WHEN_ALWAYS, "? print this message"},
{ WHEN_ALWAYS, "^R short replay"}, {WHEN_ALWAYS, "^R short replay"},
{ WHEN_ATTACH, "\\ooo send character by octal code"}, {WHEN_ATTACH, "\\ooo send character by octal code"},
{ WHEN_EXPERT, "^I toggle tab expansion"}, {WHEN_EXPERT, "^I toggle tab expansion"},
{ WHEN_EXPERT, "; change to another console"}, {WHEN_EXPERT, "; change to another console"},
{ WHEN_EXPERT, "+(-) do (not) drop line"}, {WHEN_EXPERT, "+(-) do (not) drop line"},
{ WHEN_VT100, "PF1 print this message"}, {WHEN_VT100, "PF1 print this message"},
{ WHEN_VT100, "PF2 disconnect"}, {WHEN_VT100, "PF2 disconnect"},
{ WHEN_VT100, "PF3 replay the last 20 lines"}, {WHEN_VT100, "PF3 replay the last 20 lines"},
{ WHEN_VT100, "PF4 spy read only"} {WHEN_VT100, "PF4 spy read only"}
}; };
/* list the commands we know for the user (ksb) /* list the commands we know for the user (ksb)
*/ */
void void
HelpUser(pCL) HelpUser(pCL)
CONSCLIENT *pCL; CONSCLIENT *pCL;
{ {
register int i, j, iCmp; int i, j, iCmp;
static char static char
acH1[] = "help]\r\n", acH1[] = "help]\r\n", acH2[] = "help spy mode]\r\n", acEoln[] =
acH2[] = "help spy mode]\r\n", "\r\n";
acEoln[] = "\r\n"; char acLine[HALFLINE * 2 + 3];
auto char acLine[HALFLINE*2+3];
iCmp = WHEN_ALWAYS|WHEN_SPY; iCmp = WHEN_ALWAYS | WHEN_SPY;
if (pCL->fwr) { if (pCL->fwr) {
(void)write(pCL->fd, acH1, sizeof(acH1)-1); (void)fileWrite(pCL->fd, acH1, sizeof(acH1) - 1);
iCmp |= WHEN_ATTACH; iCmp |= WHEN_ATTACH;
} else { } else {
(void)write(pCL->fd, acH2, sizeof(acH2)-1); (void)fileWrite(pCL->fd, acH2, sizeof(acH2) - 1);
} }
if ('\033' == pCL->ic[0] && 'O' == pCL->ic[1]) { if ('\033' == pCL->ic[0] && 'O' == pCL->ic[1]) {
iCmp |= WHEN_VT100; iCmp |= WHEN_VT100;
} }
acLine[0] = '\000'; acLine[0] = '\000';
for (i = 0; i < sizeof(aHLTable)/sizeof(HELP); ++i) { for (i = 0; i < sizeof(aHLTable) / sizeof(HELP); ++i) {
if (0 == (aHLTable[i].iwhen & iCmp)) { if (0 == (aHLTable[i].iwhen & iCmp)) {
continue; continue;
} }
if ('\000' == acLine[0]) { if ('\000' == acLine[0]) {
acLine[0] = ' '; acLine[0] = ' ';
(void)strcpy(acLine+1, aHLTable[i].actext); (void)strcpy(acLine + 1, aHLTable[i].actext);
continue; continue;
} }
for (j = strlen(acLine); j < HALFLINE+1; ++j) { for (j = strlen(acLine); j < HALFLINE + 1; ++j) {
acLine[j] = ' '; acLine[j] = ' ';
} }
(void)strcpy(acLine+j, aHLTable[i].actext); (void)strcpy(acLine + j, aHLTable[i].actext);
(void)strcat(acLine+j, acEoln); (void)strcat(acLine + j, acEoln);
(void)write(pCL->fd, acLine, strlen(acLine)); (void)fileWrite(pCL->fd, acLine, -1);
acLine[0] = '\000'; acLine[0] = '\000';
} }
if ('\000' != acLine[0]) { if ('\000' != acLine[0]) {
(void)strcat(acLine, acEoln); (void)strcat(acLine, acEoln);
(void)write(pCL->fd, acLine, strlen(acLine)); (void)fileWrite(pCL->fd, acLine, -1);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* $Id: client.h,v 5.16 2001-02-21 17:26:06-08 bryan Exp $ * $Id: client.h,v 5.20 2001-07-25 15:32:28-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -49,12 +49,13 @@
#define S_BCAST 11 /* send a broadcast message to all connections */ #define S_BCAST 11 /* send a broadcast message to all connections */
typedef struct client { /* Connection Information: */ typedef struct client { /* Connection Information: */
int fd; /* file descriptor */ CONSFILE *fd; /* file descriptor */
short fcon; /* currently connect or not */ short fcon; /* currently connect or not */
short fwr; /* (client) write enable flag */ short fwr; /* (client) write enable flag */
short fwantwr; /* (client) wants to write */ short fwantwr; /* (client) wants to write */
short fecho; /* echo commands (not set by machines) */ short fecho; /* echo commands (not set by machines) */
char acid[128]; /* login and location of client */ char acid[128]; /* login and location of client */
char peername[128]; /* location of client */
time_t tym; /* time of connect */ time_t tym; /* time of connect */
time_t typetym; /* time of last keystroke */ time_t typetym; /* time of last keystroke */
char actym[32]; /* pre-formatted time */ char actym[32]; /* pre-formatted time */
@ -69,10 +70,9 @@ typedef struct client { /* Connection Information: */
char ic[2]; /* two character escape sequence */ char ic[2]; /* two character escape sequence */
char iState; /* state for fsm in server */ char iState; /* state for fsm in server */
char caccess; /* did we trust the remote machine */ char caccess; /* did we trust the remote machine */
char accmd[MAXSERVLEN+1];/* the command the user issued */ char accmd[MAXSERVLEN + 1]; /* the command the user issued */
int icursor; /* the length of the command issused */ int icursor; /* the length of the command issused */
char msg[1024]; /* the broadcast message */ char msg[1024]; /* the broadcast message */
int mcursor; /* the length of the message */
struct sockaddr_in struct sockaddr_in
cnct_port; /* where from */ cnct_port; /* where from */
} CONSCLIENT; } CONSCLIENT;

View File

@ -1,5 +1,5 @@
/* /*
* $Id: consent.c,v 5.51 2001-07-05 04:12:31-07 bryan Exp $ * $Id: consent.c,v 5.68 2001-07-26 11:48:43-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -54,33 +54,33 @@
#include <pwd.h> #include <pwd.h>
#include <compat.h> #include <compat.h>
#include <port.h> #include <port.h>
#include <util.h>
#include <consent.h> #include <consent.h>
#include <client.h> #include <client.h>
#include <main.h> #include <main.h>
#include <output.h>
struct hostcache *hostcachelist=NULL; struct hostcache *hostcachelist = NULL;
BAUD baud [] = { BAUD baud[] = {
{ "Netwk", 0 }, {"Netwk", 0},
#if defined(B38400) #if defined(B38400)
{ "38400", B38400 }, {"38400", B38400},
#endif #endif
#if defined(B19200) #if defined(B19200)
{ "19200", B19200 }, {"19200", B19200},
#endif #endif
{ "9600", B9600 }, {"9600", B9600},
{ "4800", B4800 }, {"4800", B4800},
{ "2400", B2400 }, {"2400", B2400},
#if defined(B1800) #if defined(B1800)
{ "1800", B1800 }, {"1800", B1800},
#endif #endif
{ "1200", B1200 }, {"1200", B1200},
#if defined(B600) #if defined(B600)
{ "600", B600 }, {"600", B600},
#endif #endif
}; };
@ -89,14 +89,14 @@ BAUD baud [] = {
*/ */
BAUD * BAUD *
FindBaud(pcMode) FindBaud(pcMode)
char *pcMode; char *pcMode;
{ {
register int i; int i;
for (i = 0; i < sizeof(baud)/sizeof(struct baud); ++i) { for (i = 0; i < sizeof(baud) / sizeof(struct baud); ++i) {
if (0 != strncmp(pcMode, baud[i].acrate, strlen(baud[i].acrate))) if (0 != strncmp(pcMode, baud[i].acrate, strlen(baud[i].acrate)))
continue; continue;
return baud+i; return baud + i;
} }
return baud; return baud;
} }
@ -104,23 +104,33 @@ char *pcMode;
PARITY parity[] = { PARITY parity[] = {
#if HAVE_TERMIOS_H #if HAVE_TERMIOS_H
{' ', 0, 0}, /* Blank for network */ {' ', 0, 0}
, /* Blank for network */
# if !defined(PAREXT) # if !defined(PAREXT)
# define PAREXT 0 # define PAREXT 0
# endif # endif
{'e', PARENB|CS7, 0}, /* even */ {'e', PARENB | CS7, 0}
{'m', PARENB|CS7|PARODD|PAREXT, 0}, /* mark */ , /* even */
{'o', PARENB|CS7|PARODD, 0}, /* odd */ {'m', PARENB | CS7 | PARODD | PAREXT, 0}
{'p', CS8, 0}, /* pass 8 bits, no parity */ , /* mark */
{'s', PARENB|CS7|PAREXT, 0}, /* space */ {'o', PARENB | CS7 | PARODD, 0}
, /* odd */
{'p', CS8, 0}
, /* pass 8 bits, no parity */
{'s', PARENB | CS7 | PAREXT, 0}
, /* space */
#else /* ! HAVE_TERMIOS_H */ #else /* ! HAVE_TERMIOS_H */
{'e', EVENP, ODDP}, /* even */ {'e', EVENP, ODDP}
{'m', EVENP|ODDP, 0}, /* mark */ , /* even */
{'o', ODDP, EVENP}, /* odd */ {'m', EVENP | ODDP, 0}
, /* mark */
{'o', ODDP, EVENP}
, /* odd */
# if defined(PASS8) # if defined(PASS8)
{'p', PASS8,EVENP|ODDP},/* pass 8 bits, no parity */ {'p', PASS8, EVENP | ODDP}
, /* pass 8 bits, no parity */
# endif # endif
{'s', 0, EVENP|ODDP} /* space */ {'s', 0, EVENP | ODDP} /* space */
#endif #endif
}; };
@ -128,10 +138,10 @@ PARITY parity[] = {
*/ */
PARITY * PARITY *
FindParity(pcMode) FindParity(pcMode)
char *pcMode; char *pcMode;
{ {
register int i; int i;
auto char acFirst; char acFirst;
while (isdigit((int)(*pcMode))) { while (isdigit((int)(*pcMode))) {
++pcMode; ++pcMode;
@ -139,10 +149,10 @@ char *pcMode;
acFirst = *pcMode; acFirst = *pcMode;
if (isupper((int)(acFirst))) if (isupper((int)(acFirst)))
acFirst = tolower(acFirst); acFirst = tolower(acFirst);
for (i = 0; i < sizeof(parity)/sizeof(struct parity); ++i) { for (i = 0; i < sizeof(parity) / sizeof(struct parity); ++i) {
if (acFirst != parity[i].ckey) if (acFirst != parity[i].ckey)
continue; continue;
return parity+i; return parity + i;
} }
return parity; return parity;
} }
@ -153,15 +163,15 @@ char *pcMode;
*/ */
static int static int
TtyDev(pCE) TtyDev(pCE)
CONSENT *pCE; CONSENT *pCE;
{ {
struct termios termp; struct termios termp;
auto struct stat stPerm; struct stat stPerm;
/* here we should fstat for `read-only' checks /* here we should fstat for `read-only' checks
*/ */
if (-1 == fstat(pCE->fdtty, & stPerm)) { if (-1 == fstat(pCE->fdtty, &stPerm)) {
Error( "fstat: %s: %s", pCE->dfile, strerror(errno)); Error("fstat: %s: %s", pCE->dfile, strerror(errno));
} else if (0 == (stPerm.st_mode & 0222)) { } else if (0 == (stPerm.st_mode & 0222)) {
/* any device that is read-only we won't write to /* any device that is read-only we won't write to
*/ */
@ -172,7 +182,8 @@ CONSENT *pCE;
* Get terminal attributes * Get terminal attributes
*/ */
if (-1 == tcgetattr(pCE->fdtty, &termp)) { if (-1 == tcgetattr(pCE->fdtty, &termp)) {
Error( "tcgetattr: %s(%d): %s", pCE->dfile, pCE->fdtty, strerror(errno)); Error("tcgetattr: %s(%d): %s", pCE->dfile, pCE->fdtty,
strerror(errno));
return -1; return -1;
} }
@ -184,7 +195,7 @@ CONSENT *pCE;
* isig No signal generation * isig No signal generation
* Turn on: ixoff * Turn on: ixoff
*/ */
termp.c_iflag = IXON|IXOFF|BRKINT; termp.c_iflag = IXON | IXOFF | BRKINT;
termp.c_oflag = 0; termp.c_oflag = 0;
termp.c_cflag = CREAD; termp.c_cflag = CREAD;
termp.c_cflag |= pCE->pparity->iset; termp.c_cflag |= pCE->pparity->iset;
@ -197,12 +208,14 @@ CONSENT *pCE;
termp.c_cc[VMIN] = 128; termp.c_cc[VMIN] = 128;
termp.c_cc[VTIME] = 1; termp.c_cc[VTIME] = 1;
if (-1 == cfsetospeed(&termp,pCE->pbaud->irate)) { if (-1 == cfsetospeed(&termp, pCE->pbaud->irate)) {
Error( "cfsetospeed: %s(%d): %s", pCE->dfile, pCE->fdtty, strerror(errno)); Error("cfsetospeed: %s(%d): %s", pCE->dfile, pCE->fdtty,
strerror(errno));
return -1; return -1;
} }
if (-1 == cfsetispeed(&termp,pCE->pbaud->irate)) { if (-1 == cfsetispeed(&termp, pCE->pbaud->irate)) {
Error( "cfsetispeed: %s(%d): %s", pCE->dfile, pCE->fdtty, strerror(errno)); Error("cfsetispeed: %s(%d): %s", pCE->dfile, pCE->fdtty,
strerror(errno));
return -1; return -1;
} }
@ -210,10 +223,10 @@ CONSENT *pCE;
* Set terminal attributes * Set terminal attributes
*/ */
if (-1 == tcsetattr(pCE->fdtty, TCSADRAIN, &termp)) { if (-1 == tcsetattr(pCE->fdtty, TCSADRAIN, &termp)) {
Error( "tcsetattr: %s(%d): %s", pCE->dfile, pCE->fdtty, strerror(errno)); Error("tcsetattr: %s(%d): %s", pCE->dfile, pCE->fdtty,
strerror(errno));
return -1; return -1;
} }
# if HAVE_STROPTS_H # if HAVE_STROPTS_H
/* /*
* eat all the streams modules upto and including ttcompat * eat all the streams modules upto and including ttcompat
@ -228,32 +241,31 @@ CONSENT *pCE;
#else /* ! HAVE_TERMIOS_H */ #else /* ! HAVE_TERMIOS_H */
# ifdef HAVE_SGTTY_H # if HAVE_SGTTY_H
/* setup a tty device (ksb) /* setup a tty device (ksb)
*/ */
static int static int
TtyDev(pCE) TtyDev(pCE)
CONSENT *pCE; CONSENT *pCE;
{ {
struct sgttyb sty; struct sgttyb sty;
struct tchars m_tchars; struct tchars m_tchars;
struct ltchars m_ltchars; struct ltchars m_ltchars;
auto struct stat stPerm; struct stat stPerm;
/* here we should fstat for `read-only' checks /* here we should fstat for `read-only' checks
*/ */
if (-1 == fstat(pCE->fdtty, & stPerm)) { if (-1 == fstat(pCE->fdtty, &stPerm)) {
Error( "fstat: %s: %s", pCE->dfile, strerror(errno)); Error("fstat: %s: %s", pCE->dfile, strerror(errno));
} else if (0 == (stPerm.st_mode & 0222)) { } else if (0 == (stPerm.st_mode & 0222)) {
/* any device that is read-only we won't write to /* any device that is read-only we won't write to
*/ */
pCE->fronly = 1; pCE->fronly = 1;
} }
# if defined(TIOCSSOFTCAR) # if defined(TIOCSSOFTCAR)
if (-1 == ioctl(pCE->fdtty, TIOCSSOFTCAR, &fSoftcar)) { if (-1 == ioctl(pCE->fdtty, TIOCSSOFTCAR, &fSoftcar)) {
Error( "softcar: %d: %s", pCE->fdtty, strerror(errno)); Error("softcar: %d: %s", pCE->fdtty, strerror(errno));
return -1; return -1;
} }
# endif # endif
@ -261,17 +273,18 @@ CONSENT *pCE;
/* stty 9600 raw cs7 /* stty 9600 raw cs7
*/ */
if (-1 == ioctl(pCE->fdtty, TIOCGETP, (char *)&sty)) { if (-1 == ioctl(pCE->fdtty, TIOCGETP, (char *)&sty)) {
Error( "ioctl1: %s(%d): %s", pCE->dfile, pCE->fdtty, strerror(errno)); Error("ioctl1: %s(%d): %s", pCE->dfile, pCE->fdtty,
strerror(errno));
return -1; return -1;
} }
sty.sg_flags &= ~(ECHO|CRMOD|pCE->pparity->iclr); sty.sg_flags &= ~(ECHO | CRMOD | pCE->pparity->iclr);
sty.sg_flags |= (CBREAK|TANDEM|pCE->pparity->iset); sty.sg_flags |= (CBREAK | TANDEM | pCE->pparity->iset);
sty.sg_erase = -1; sty.sg_erase = -1;
sty.sg_kill = -1; sty.sg_kill = -1;
sty.sg_ispeed = pCE->pbaud->irate; sty.sg_ispeed = pCE->pbaud->irate;
sty.sg_ospeed = pCE->pbaud->irate; sty.sg_ospeed = pCE->pbaud->irate;
if (-1 == ioctl(pCE->fdtty, TIOCSETP, (char *)&sty)) { if (-1 == ioctl(pCE->fdtty, TIOCSETP, (char *)&sty)) {
Error( "ioctl2: %d: %s", pCE->fdtty, strerror(errno)); Error("ioctl2: %d: %s", pCE->fdtty, strerror(errno));
return -1; return -1;
} }
@ -279,7 +292,7 @@ CONSENT *pCE;
* (in cbreak mode we may not need to this... but we do) * (in cbreak mode we may not need to this... but we do)
*/ */
if (-1 == ioctl(pCE->fdtty, TIOCGETC, (char *)&m_tchars)) { if (-1 == ioctl(pCE->fdtty, TIOCGETC, (char *)&m_tchars)) {
Error( "ioctl3: %d: %s", pCE->fdtty, strerror(errno)); Error("ioctl3: %d: %s", pCE->fdtty, strerror(errno));
return -1; return -1;
} }
m_tchars.t_intrc = -1; m_tchars.t_intrc = -1;
@ -289,11 +302,11 @@ CONSENT *pCE;
m_tchars.t_eofc = -1; m_tchars.t_eofc = -1;
m_tchars.t_brkc = -1; m_tchars.t_brkc = -1;
if (-1 == ioctl(pCE->fdtty, TIOCSETC, (char *)&m_tchars)) { if (-1 == ioctl(pCE->fdtty, TIOCSETC, (char *)&m_tchars)) {
Error( "ioctl4: %d: %s", pCE->fdtty, strerror(errno)); Error("ioctl4: %d: %s", pCE->fdtty, strerror(errno));
return -1; return -1;
} }
if (-1 == ioctl(pCE->fdtty, TIOCGLTC, (char *)&m_ltchars)) { if (-1 == ioctl(pCE->fdtty, TIOCGLTC, (char *)&m_ltchars)) {
Error( "ioctl5: %d: %s", pCE->fdtty, strerror(errno)); Error("ioctl5: %d: %s", pCE->fdtty, strerror(errno));
return -1; return -1;
} }
m_ltchars.t_werasc = -1; m_ltchars.t_werasc = -1;
@ -302,7 +315,7 @@ CONSENT *pCE;
m_ltchars.t_suspc = -1; m_ltchars.t_suspc = -1;
m_ltchars.t_dsuspc = -1; m_ltchars.t_dsuspc = -1;
if (-1 == ioctl(pCE->fdtty, TIOCSLTC, (char *)&m_ltchars)) { if (-1 == ioctl(pCE->fdtty, TIOCSLTC, (char *)&m_ltchars)) {
Error( "ioctl6: %d: %s", pCE->fdtty, strerror(errno)); Error("ioctl6: %d: %s", pCE->fdtty, strerror(errno));
return -1; return -1;
} }
# if HAVE_STROPTS_H # if HAVE_STROPTS_H
@ -310,7 +323,7 @@ CONSENT *pCE;
* (Idea by jrs@ecn.purdue.edu) * (Idea by jrs@ecn.purdue.edu)
*/ */
while (ioctl(pCE->fdtty, I_POP, 0) == 0) { while (ioctl(pCE->fdtty, I_POP, 0) == 0) {
/* eat all the streams modules */; /* eat all the streams modules */ ;
} }
# endif # endif
pCE->fup = 1; pCE->fup = 1;
@ -324,25 +337,23 @@ CONSENT *pCE;
*/ */
static int static int
VirtDev(pCE) VirtDev(pCE)
CONSENT *pCE; CONSENT *pCE;
{ {
# if HAVE_TERMIOS_H # if HAVE_TERMIOS_H
static struct termios n_tio; static struct termios n_tio;
# else # else
# ifdef HAVE_SGTTY_H # if HAVE_SGTTY_H
auto struct sgttyb sty; struct sgttyb sty;
auto struct tchars m_tchars; struct tchars m_tchars;
auto struct ltchars m_ltchars; struct ltchars m_ltchars;
# endif # endif
# endif # endif
# if HAVE_GETRLIMIT int i, iNewGrp;
auto struct rlimit rl;
# endif
auto int i, iNewGrp;
extern char **environ; extern char **environ;
register char *pcShell, **ppcArgv; char *pcShell, **ppcArgv;
(void)fflush(stdout); (void)fflush(stdout);
(void)fflush(stderr);
switch (pCE->ipid = fork()) { switch (pCE->ipid = fork()) {
case -1: case -1:
@ -351,45 +362,35 @@ CONSENT *pCE;
thepid = getpid(); thepid = getpid();
break; break;
default: default:
Error( "%d is the pid on %s", pCE->ipid, pCE->acslave); if (fVerbose)
Error("%s has pid %d on %s", pCE->server, pCE->ipid,
pCE->acslave);
(void)fflush(stderr); (void)fflush(stderr);
pCE->fup = 1; pCE->fup = 1;
sleep(2); /* chance to open line */
return 0; return 0;
} }
/* put the signals back that we trap /* put the signals back that we trap
*/ */
signal(SIGINT, SIG_DFL); simpleSignal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL); simpleSignal(SIGQUIT, SIG_DFL);
signal(SIGTSTP, SIG_DFL); simpleSignal(SIGTSTP, SIG_DFL);
/* setup new process with clean filew descriptors /* setup new process with clean filew descriptors
*/ */
# if HAVE_GETRLIMIT i = maxfiles();
getrlimit(RLIMIT_NOFILE, &rl); for ( /* i above */ ; i-- > 2;) {
i = rl.rlim_cur;
# else
i = getdtablesize();
# endif
for (/* i above */; i-- > 2; ) {
close(i); close(i);
} }
/* leave 2 until we *have to close it* /* leave 2 until we *have to close it*
*/ */
close(1); close(1);
close(0); close(0);
# if defined(TIOCNOTTY)
if (-1 != (i = open("/dev/tty", O_RDWR, 0))) {
ioctl(i, TIOCNOTTY, (char *)0);
close(i);
}
# endif
# if HAVE_SETSID # if HAVE_SETSID
iNewGrp = setsid(); iNewGrp = setsid();
if (-1 == iNewGrp) { if (-1 == iNewGrp) {
Error( "%s: setsid: %s", pCE->server, strerror(errno)); Error("%s: setsid: %s", pCE->server, strerror(errno));
iNewGrp = getpid(); iNewGrp = getpid();
} }
# else # else
@ -397,34 +398,36 @@ CONSENT *pCE;
# endif # endif
if (0 != open(pCE->acslave, O_RDWR, 0) || 1 != dup(0)) { if (0 != open(pCE->acslave, O_RDWR, 0) || 1 != dup(0)) {
Error( "%s: fd sync error", pCE->server); Error("%s: fd sync error", pCE->server);
exit(1); exit(EX_UNAVAILABLE);
} }
# if HAVE_PTSNAME # if HAVE_STROPTS_H
/* SYSVr4 semantics for opening stream ptys (gregf) /* SYSVr4 semantics for opening stream ptys (gregf)
* under PTX (others?) we have to push the compatibility * under PTX (others?) we have to push the compatibility
* streams modules `ptem' and `ld' * streams modules `ptem', `ld', and `ttcompat'
*/ */
(void)ioctl(0, I_PUSH, "ptem"); (void)ioctl(0, I_PUSH, "ptem");
(void)ioctl(0, I_PUSH, "ldterm"); (void)ioctl(0, I_PUSH, "ldterm");
(void)ioctl(0, I_PUSH, "ttcompat");
# endif # endif
# if HAVE_TERMIOS_H # if HAVE_TERMIOS_H
# ifdef HAVE_TCGETATTR # if HAVE_TCGETATTR
if (0 != tcgetattr(0, &n_tio)) if (0 != tcgetattr(0, &n_tio))
# else # else
if (0 != ioctl(0, TCGETS, & n_tio)) if (0 != ioctl(0, TCGETS, &n_tio))
# endif # endif
{ {
Error( "iotcl: getsw: %s", strerror(errno)); Error("ioctl: getsw: %s", strerror(errno));
exit(1); exit(EX_UNAVAILABLE);
} }
n_tio.c_iflag &= ~(IGNCR|IUCLC); n_tio.c_iflag &= ~(IGNCR | IUCLC);
n_tio.c_iflag |= ICRNL|IXON|IXANY; n_tio.c_iflag |= ICRNL | IXON | IXANY;
n_tio.c_oflag &= ~(OLCUC|ONOCR|ONLRET|OFILL|NLDLY|CRDLY|TABDLY|BSDLY); n_tio.c_oflag &=
n_tio.c_oflag |= OPOST|ONLCR; ~(OLCUC | ONOCR | ONLRET | OFILL | NLDLY | CRDLY | TABDLY | BSDLY);
n_tio.c_lflag &= ~(XCASE|NOFLSH|ECHOK|ECHONL); n_tio.c_oflag |= OPOST | ONLCR;
n_tio.c_lflag |= ISIG|ICANON|ECHO; n_tio.c_lflag &= ~(XCASE | NOFLSH | ECHOK | ECHONL);
n_tio.c_lflag |= ISIG | ICANON | ECHO;
n_tio.c_cc[VEOF] = '\004'; n_tio.c_cc[VEOF] = '\004';
n_tio.c_cc[VEOL] = '\000'; n_tio.c_cc[VEOL] = '\000';
n_tio.c_cc[VERASE] = '\010'; n_tio.c_cc[VERASE] = '\010';
@ -435,14 +438,14 @@ CONSENT *pCE;
n_tio.c_cc[VSTART] = '\021'; n_tio.c_cc[VSTART] = '\021';
n_tio.c_cc[VSTOP] = '\023'; n_tio.c_cc[VSTOP] = '\023';
n_tio.c_cc[VSUSP] = '\032'; n_tio.c_cc[VSUSP] = '\032';
# ifdef HAVE_TCSETATTR # if HAVE_TCSETATTR
if (0 != tcsetattr(0, TCSANOW, & n_tio)) if (0 != tcsetattr(0, TCSANOW, &n_tio))
# else # else
if (0 != ioctl(0, TCSETS, & n_tio)) if (0 != ioctl(0, TCSETS, &n_tio))
# endif # endif
{ {
Error( "getarrt: %s", strerror(errno)); Error("getattr: %s", strerror(errno));
exit(1); exit(EX_UNAVAILABLE);
} }
tcsetpgrp(0, iNewGrp); tcsetpgrp(0, iNewGrp);
@ -450,26 +453,26 @@ CONSENT *pCE;
/* stty 9600 raw cs7 /* stty 9600 raw cs7
*/ */
if (-1 == ioctl(0, TIOCGETP, (char *)&sty)) { if (-1 == ioctl(0, TIOCGETP, (char *)&sty)) {
Error( "ioctl1: %s: %s", pCE->fdtty, strerror(errno)); Error("ioctl1: %s: %s", pCE->fdtty, strerror(errno));
exit(1); exit(EX_UNAVAILABLE);
} }
sty.sg_flags &= ~(CBREAK|TANDEM|pCE->pparity->iclr); sty.sg_flags &= ~(CBREAK | TANDEM | pCE->pparity->iclr);
sty.sg_flags |= (ECHO|CRMOD|pCE->pparity->iset); sty.sg_flags |= (ECHO | CRMOD | pCE->pparity->iset);
sty.sg_erase = '\b'; sty.sg_erase = '\b';
sty.sg_kill = '\025'; sty.sg_kill = '\025';
sty.sg_ispeed = pCE->pbaud->irate; sty.sg_ispeed = pCE->pbaud->irate;
sty.sg_ospeed = pCE->pbaud->irate; sty.sg_ospeed = pCE->pbaud->irate;
if (-1 == ioctl(0, TIOCSETP, (char *)&sty)) { if (-1 == ioctl(0, TIOCSETP, (char *)&sty)) {
Error( "ioctl2: %s", strerror(errno)); Error("ioctl2: %s", strerror(errno));
exit(1); exit(EX_UNAVAILABLE);
} }
/* stty undef all tty chars /* stty undef all tty chars
* (in cbreak mode we may not need to this... but we do) * (in cbreak mode we may not need to this... but we do)
*/ */
if (-1 == ioctl(0, TIOCGETC, (char *)&m_tchars)) { if (-1 == ioctl(0, TIOCGETC, (char *)&m_tchars)) {
Error( "ioctl3: %s", strerror(errno)); Error("ioctl3: %s", strerror(errno));
exit(1); exit(EX_UNAVAILABLE);
} }
m_tchars.t_intrc = '\003'; m_tchars.t_intrc = '\003';
m_tchars.t_quitc = '\034'; m_tchars.t_quitc = '\034';
@ -478,12 +481,12 @@ CONSENT *pCE;
m_tchars.t_eofc = '\004'; m_tchars.t_eofc = '\004';
m_tchars.t_brkc = '\033'; m_tchars.t_brkc = '\033';
if (-1 == ioctl(0, TIOCSETC, (char *)&m_tchars)) { if (-1 == ioctl(0, TIOCSETC, (char *)&m_tchars)) {
Error( "ioctl4: %s", strerror(errno)); Error("ioctl4: %s", strerror(errno));
exit(1); exit(EX_UNAVAILABLE);
} }
if (-1 == ioctl(0, TIOCGLTC, (char *)&m_ltchars)) { if (-1 == ioctl(0, TIOCGLTC, (char *)&m_ltchars)) {
Error( "ioctl5: %s", strerror(errno)); Error("ioctl5: %s", strerror(errno));
exit(1); exit(EX_UNAVAILABLE);
} }
m_ltchars.t_werasc = '\027'; m_ltchars.t_werasc = '\027';
m_ltchars.t_flushc = '\017'; m_ltchars.t_flushc = '\017';
@ -491,8 +494,8 @@ CONSENT *pCE;
m_ltchars.t_suspc = '\032'; m_ltchars.t_suspc = '\032';
m_ltchars.t_dsuspc = '\031'; m_ltchars.t_dsuspc = '\031';
if (-1 == ioctl(0, TIOCSLTC, (char *)&m_ltchars)) { if (-1 == ioctl(0, TIOCSLTC, (char *)&m_ltchars)) {
Error( "ioctl6: %s", strerror(errno)); Error("ioctl6: %s", strerror(errno));
exit(1); exit(EX_UNAVAILABLE);
} }
/* give us a process group to work in /* give us a process group to work in
@ -518,9 +521,10 @@ CONSENT *pCE;
static char *apcArgv[] = { static char *apcArgv[] = {
"-shell", "-i", (char *)0 "-shell", "-i", (char *)0
}; };
register struct passwd *pwd; struct passwd *pwd;
if ((struct passwd *)0 != (pwd = getpwuid(0)) && '\000' != pwd->pw_shell[0]) { if ((struct passwd *)0 != (pwd = getpwuid(0)) &&
'\000' != pwd->pw_shell[0]) {
pcShell = pwd->pw_shell; pcShell = pwd->pw_shell;
} }
ppcArgv = apcArgv; ppcArgv = apcArgv;
@ -534,35 +538,33 @@ CONSENT *pCE;
} }
execve(pcShell, ppcArgv, environ); execve(pcShell, ppcArgv, environ);
Error("execve: %s", strerror(errno)); Error("execve: %s", strerror(errno));
exit(1); exit(EX_UNAVAILABLE);
/*NOTREACHED*/
} }
/* down a console, virtual or real (ksb) /* down a console, virtual or real (ksb)
*/ */
void void
ConsDown(pCE, pfdSet) ConsDown(pCE, pfdSet)
CONSENT *pCE; CONSENT *pCE;
fd_set *pfdSet; fd_set *pfdSet;
{ {
if (-1 != pCE->ipid) { if (-1 != pCE->ipid) {
if (-1 != kill(pCE->ipid, SIGHUP)) Debug("Sending pid %d signal %d", pCE->ipid, SIGHUP);
sleep(1); kill(pCE->ipid, SIGHUP);
pCE->ipid = -1; pCE->ipid = -1;
} }
if (-1 != pCE->fdtty) { if (-1 != pCE->fdtty) {
if ((fd_set *) 0 != pfdSet)
FD_CLR(pCE->fdtty, pfdSet); FD_CLR(pCE->fdtty, pfdSet);
if (0 == pCE->fvirtual) {
(void)close(pCE->fdtty); (void)close(pCE->fdtty);
pCE->fdtty = -1; pCE->fdtty = -1;
} }
} if ((CONSFILE *) 0 != pCE->fdlog) {
if (-1 != pCE->fdlog) {
if (pCE->nolog) { if (pCE->nolog) {
CSTROUT(pCE->fdlog, "[Console logging restored]\r\n"); fileWrite(pCE->fdlog, "[Console logging restored]\r\n", -1);
} }
(void)close(pCE->fdlog); (void)fileClose(pCE->fdlog);
pCE->fdlog = -1; pCE->fdlog = (CONSFILE *) 0;
} }
pCE->fup = 0; pCE->fup = 0;
pCE->nolog = 0; pCE->nolog = 0;
@ -570,12 +572,12 @@ fd_set *pfdSet;
int int
CheckHostCache(hostname) CheckHostCache(hostname)
const char *hostname; const char *hostname;
{ {
struct hostcache *p; struct hostcache *p;
p = hostcachelist; p = hostcachelist;
while (p != NULL) { while (p != NULL) {
if ( 0 == strncmp( hostname, p->hostname, MAXSERVLEN ) ) { if (0 == strncmp(hostname, p->hostname, MAXSERVLEN)) {
return 1; return 1;
} }
p = p->next; p = p->next;
@ -585,11 +587,12 @@ const char *hostname;
void void
AddHostCache(hostname) AddHostCache(hostname)
const char *hostname; const char *hostname;
{ {
struct hostcache *n; struct hostcache *n;
if ((struct hostcache *)0 == (n = (struct hostcache *)malloc(sizeof(struct hostcache)))) { if ((struct hostcache *)0 ==
Error( "malloc failure: %s", strerror(errno)); (n = (struct hostcache *)malloc(sizeof(struct hostcache)))) {
Error("malloc failure: %s", strerror(errno));
return; return;
} }
(void)strncpy(n->hostname, hostname, MAXSERVLEN); (void)strncpy(n->hostname, hostname, MAXSERVLEN);
@ -616,15 +619,25 @@ ClearHostCache()
*/ */
void void
ConsInit(pCE, pfdSet, useHostCache) ConsInit(pCE, pfdSet, useHostCache)
CONSENT *pCE; CONSENT *pCE;
fd_set *pfdSet; fd_set *pfdSet;
int useHostCache; int useHostCache;
{ {
if ( ! useHostCache ) ClearHostCache(); extern int FallBack();
if (!useHostCache)
ClearHostCache();
/* clean up old stuff /* clean up old stuff
*/ */
if (pCE->fup) {
ConsDown(pCE, pfdSet); ConsDown(pCE, pfdSet);
if (pCE->isNetworkConsole) {
sleep(1); /* Give the terminal server a chance */
} else {
usleep(USLEEP_FOR_SLOW_PORTS);
}
}
pCE->fronly = 0; pCE->fronly = 0;
pCE->nolog = 0; pCE->nolog = 0;
@ -637,20 +650,21 @@ int useHostCache;
/* try to open them again /* try to open them again
*/ */
if (-1 == if ((CONSFILE *) 0 ==
(pCE->fdlog = open(pCE->lfile, O_RDWR|O_CREAT|O_APPEND, 0644))) (pCE->fdlog =
{ fileOpen(pCE->lfile, O_RDWR | O_CREAT | O_APPEND, 0644))) {
Error( "open: %s: %s", pCE->lfile, strerror(errno)); Error("open: %s: %s", pCE->lfile, strerror(errno));
return; return;
} }
if (0 != pCE->fvirtual) if (0 != pCE->fvirtual) {
{ if (-1 == (pCE->fdtty = FallBack(pCE->acslave, pCE->dfile))) {
/* still open, never ever close it, but set the bit */ Error("Failed to allocate pseudo-tty", pCE->dfile,
FD_SET(pCE->fdtty, pfdSet); strerror(errno));
ConsDown(pCE, pfdSet);
return;
} }
else if (pCE->isNetworkConsole) } else if (pCE->isNetworkConsole) {
{
struct sockaddr_in port; struct sockaddr_in port;
struct hostent *hp; struct hostent *hp;
size_t one = 1; size_t one = 1;
@ -658,17 +672,14 @@ int useHostCache;
fd_set fds; fd_set fds;
struct timeval tv; struct timeval tv;
if ( CheckHostCache( pCE->networkConsoleHost ) ) { if (CheckHostCache(pCE->networkConsoleHost)) {
Error( "cached previous timeout: %s (%d@%s): forcing down", Error("cached previous timeout: %s (%u@%s): forcing down",
pCE->server, ntohs(port.sin_port), pCE->server, ntohs(port.sin_port),
pCE->networkConsoleHost); pCE->networkConsoleHost);
ConsDown(pCE, pfdSet); ConsDown(pCE, pfdSet);
return; return;
} }
usleep(USLEEP_FOR_SLOW_PORTS); /* Sleep for slow network ports */
# if USLEEP_FOR_SLOW_PORTS
usleep( USLEEP_FOR_SLOW_PORTS ); /* Sleep for slow network ports */
# endif
#if HAVE_MEMSET #if HAVE_MEMSET
(void)memset((void *)&port, 0, sizeof(port)); (void)memset((void *)&port, 0, sizeof(port));
@ -676,49 +687,44 @@ int useHostCache;
(void)bzero((char *)&port, sizeof(port)); (void)bzero((char *)&port, sizeof(port));
#endif #endif
if ((hp = gethostbyname(pCE->networkConsoleHost)) == NULL) if ((hp = gethostbyname(pCE->networkConsoleHost)) == NULL) {
{ Error("gethostbyname(%s): %s", pCE->networkConsoleHost,
Error( "gethostbyname(%s): %s", pCE->networkConsoleHost, hstrerror(h_errno)); hstrerror(h_errno));
exit(1); exit(EX_UNAVAILABLE);
} }
#if HAVE_MEMCPY #if HAVE_MEMCPY
(void)memcpy(&port.sin_addr, hp->h_addr, hp->h_length); (void)memcpy(&port.sin_addr.s_addr, hp->h_addr, hp->h_length);
#else #else
(void)bcopy(hp->h_addr, &port.sin_addr, hp->h_length); (void)bcopy(hp->h_addr, &port.sin_addr.s_addr, hp->h_length);
#endif #endif
port.sin_family = hp->h_addrtype; port.sin_family = hp->h_addrtype;
port.sin_port = htons(pCE->networkConsolePort); port.sin_port = htons(pCE->networkConsolePort);
if ((pCE->fdtty = socket(AF_INET, SOCK_STREAM, 0)) < 0) if ((pCE->fdtty = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
{ Error("socket: %s", strerror(errno));
Error( "socket: %s", strerror(errno)); exit(EX_UNAVAILABLE);
exit(1);
} }
if (setsockopt(pCE->fdtty, SOL_SOCKET, SO_KEEPALIVE, if (setsockopt
(char *) &one, sizeof(one)) < 0) (pCE->fdtty, SOL_SOCKET, SO_KEEPALIVE, (char *)&one,
{ sizeof(one)) < 0) {
Error( "setsockopt SO_KEEPALIVE: %s", Error("setsockopt SO_KEEPALIVE: %s", strerror(errno));
strerror(errno));
} }
if ( (flags = fcntl(pCE->fdtty, F_GETFL)) >= 0 ) if ((flags = fcntl(pCE->fdtty, F_GETFL)) >= 0) {
{
flags |= O_NONBLOCK; flags |= O_NONBLOCK;
if ( fcntl(pCE->fdtty, F_SETFL, flags) < 0 ) { if (fcntl(pCE->fdtty, F_SETFL, flags) < 0) {
Error( "fcntl O_NONBLOCK: %s", strerror(errno)); Error("fcntl O_NONBLOCK: %s", strerror(errno));
} }
} else { } else {
Error( "fcntl: %s", strerror(errno)); Error("fcntl: %s", strerror(errno));
} }
if (connect(pCE->fdtty, if (connect(pCE->fdtty, (struct sockaddr *)&port, sizeof(port)) <
(struct sockaddr *)&port, sizeof(port)) < 0) 0) {
{ if (errno != EINPROGRESS) {
if (errno != EINPROGRESS ) { Error("connect: %s (%u@%s): %s: forcing down", pCE->server,
Error( "connect: %s (%d@%s): %s: forcing down", ntohs(port.sin_port), pCE->networkConsoleHost,
pCE->server, ntohs(port.sin_port), strerror(errno));
pCE->networkConsoleHost, strerror(errno));
ConsDown(pCE, pfdSet); ConsDown(pCE, pfdSet);
return; return;
} }
@ -729,57 +735,56 @@ int useHostCache;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(pCE->fdtty, &fds); FD_SET(pCE->fdtty, &fds);
if ( (one=select( pCE->fdtty+1, NULL, &fds, NULL, &tv )) < 0 ) { if ((one = select(pCE->fdtty + 1, NULL, &fds, NULL, &tv)) < 0) {
Error( "select: %s (%d@%s): %s: forcing down", Error("select: %s (%u@%s): %s: forcing down", pCE->server,
pCE->server, ntohs(port.sin_port), ntohs(port.sin_port), pCE->networkConsoleHost,
pCE->networkConsoleHost, strerror(errno)); strerror(errno));
ConsDown(pCE, pfdSet); ConsDown(pCE, pfdSet);
return; return;
} }
if (one == 0) { /* Timeout */ if (one == 0) { /* Timeout */
AddHostCache(pCE->networkConsoleHost); AddHostCache(pCE->networkConsoleHost);
Error( "timeout: %s (%d@%s): forcing down", Error("timeout: %s (%u@%s): forcing down", pCE->server,
pCE->server, ntohs(port.sin_port), ntohs(port.sin_port), pCE->networkConsoleHost);
pCE->networkConsoleHost);
ConsDown(pCE, pfdSet); ConsDown(pCE, pfdSet);
return; return;
} else { /* Response */ } else { /* Response */
socklen_t slen;
flags = 0; flags = 0;
one = sizeof(flags); slen = sizeof(flags);
/* So, getsockopt seems to return -1 if there is something /* So, getsockopt seems to return -1 if there is something
interesting in SO_ERROR under solaris...sheesh. So, interesting in SO_ERROR under solaris...sheesh. So,
the error message has the small change it's not accurate. */ the error message has the small change it's not accurate. */
if (getsockopt(pCE->fdtty, SOL_SOCKET, SO_ERROR, if (getsockopt
(char*)&flags, &one) < 0) (pCE->fdtty, SOL_SOCKET, SO_ERROR, (char *)&flags,
{ &slen) < 0) {
Error( "getsockopt SO_ERROR: %s (%d@%s): %s: forcing down", Error("getsockopt SO_ERROR: %s (%u@%s): %s: forcing down",
pCE->server, ntohs(port.sin_port), pCE->server, ntohs(port.sin_port),
pCE->networkConsoleHost, strerror(errno)); pCE->networkConsoleHost, strerror(errno));
ConsDown(pCE, pfdSet); ConsDown(pCE, pfdSet);
return; return;
} }
if (flags != 0) if (flags != 0) {
{ Error("connect: %s (%u@%s): %s: forcing down", pCE->server,
Error( "connect: %s (%d@%s): %s: forcing down", ntohs(port.sin_port), pCE->networkConsoleHost,
pCE->server, ntohs(port.sin_port), strerror(flags));
pCE->networkConsoleHost, strerror(flags));
ConsDown(pCE, pfdSet); ConsDown(pCE, pfdSet);
return; return;
} }
} }
# if POKE_ANNEX
/* /*
* Poke the connection to get the annex to wake up and * Poke the connection to get the annex to wake up and
* register this connection. * register this connection.
*/ */
# ifdef POKE_ANNEX
write(pCE->fdtty, "\r\n", 2); write(pCE->fdtty, "\r\n", 2);
# endif # endif
} else if (-1 == (pCE->fdtty = open(pCE->dfile, O_RDWR|O_NDELAY, 0600))) { } else if (-1 ==
Error( "open: %s: %s", pCE->dfile, strerror(errno)); (pCE->fdtty = open(pCE->dfile, O_RDWR | O_NDELAY, 0600))) {
(void)close(pCE->fdlog); Error("open: %s: %s", pCE->dfile, strerror(errno));
pCE->fdlog = -1; ConsDown(pCE, pfdSet);
return; return;
} }
FD_SET(pCE->fdtty, pfdSet); FD_SET(pCE->fdtty, pfdSet);
@ -788,13 +793,9 @@ int useHostCache;
*/ */
if (pCE->fvirtual) { if (pCE->fvirtual) {
VirtDev(pCE); VirtDev(pCE);
} } else if (pCE->isNetworkConsole) {
else if (pCE->isNetworkConsole)
{
pCE->fup = 1; pCE->fup = 1;
} } else {
else
{
TtyDev(pCE); TtyDev(pCE);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* $Id: consent.h,v 5.19 2001-06-28 11:14:30-07 bryan Exp $ * $Id: consent.h,v 5.22 2001-07-23 00:28:00-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -58,7 +58,7 @@ typedef struct parity { /* a parity bits table */
#define ALARMTIME 60 /* time between chimes */ #define ALARMTIME 60 /* time between chimes */
typedef struct consent { /* console information */ typedef struct consent { /* console information */
char server[MAXSERVLEN];/* server name */ char server[MAXSERVLEN]; /* server name */
char dfile[MAXDEVLEN]; /* device file */ char dfile[MAXDEVLEN]; /* device file */
char lfile[MAXLOGLEN]; /* log file */ char lfile[MAXLOGLEN]; /* log file */
BAUD *pbaud; /* the baud on this console port */ BAUD *pbaud; /* the baud on this console port */
@ -70,16 +70,17 @@ typedef struct consent { /* console information */
int isNetworkConsole; int isNetworkConsole;
char networkConsoleHost[MAXSERVLEN]; char networkConsoleHost[MAXSERVLEN];
int networkConsolePort; int networkConsolePort;
int telnetState;
/* used if virtual console */ /* used if virtual console */
char acslave[MAXDEVLEN];/* pseudo-device slave side */ char acslave[MAXDEVLEN]; /* pseudo-device slave side */
int fvirtual; /* is a pty device we use as a console */ int fvirtual; /* is a pty device we use as a console */
char *pccmd; /* virtual console command */ char *pccmd; /* virtual console command */
int ipid; /* pid of virtual command */ int ipid; /* pid of virtual command */
/* only used in child */ /* only used in child */
int nolog; /* don't log output */ int nolog; /* don't log output */
int fdlog; /* the local log file */ CONSFILE *fdlog; /* the local log file */
int fdtty; /* the port to talk to machine on */ int fdtty; /* the port to talk to machine on */
int activitylog; /* log attach/detach/bump */ int activitylog; /* log attach/detach/bump */
short int fup; /* we setup this line? */ short int fup; /* we setup this line? */
@ -88,7 +89,7 @@ typedef struct consent { /* console information */
short int inamelen; /* strlen(server) */ short int inamelen; /* strlen(server) */
struct client *pCLon; /* clients on this console */ struct client *pCLon; /* clients on this console */
struct client *pCLwr; /* client that is writting on console */ struct client *pCLwr; /* client that is writting on console */
char acline[132*2+2]; /* max chars we will call a line */ char acline[132 * 2 + 2]; /* max chars we will call a line */
} CONSENT; } CONSENT;
extern PARITY *FindParity(); extern PARITY *FindParity();

View File

@ -1,57 +1,139 @@
.\" @(#)conserver.8 01/06/91 OSU CIS; Thomas A. Fine .\" @(#)conserver.8 01/06/91 OSU CIS; Thomas A. Fine
.\" $Id: conserver.man,v 1.11 2001-07-05 05:09:50-07 bryan Exp $ .\" $Id: conserver.man,v 1.15 2001-07-26 10:23:52-07 bryan Exp $
.TH CONSERVER 8 "Local" .TH CONSERVER 8 "Local"
.SH NAME .SH NAME
conserver \- console server daemon conserver \- console server daemon
.SH SYNOPSIS .SH SYNOPSIS
.B conserver [\-\fBdDhinsvV\fP] [\-\fBa\fP \fItype\fP] [\-\fBM\fP \fIaddr\fP] \fBconserver\fP [\fB\-7dDhinuvV\fP] [\fB\-a\fP \fItype\fP]
.B [\-\fBp\fP \fIport\fP] [\-\fBC\fP \fIconfig\fP] [\-\fBP\fP \fIpasswd\fP] [\fB\-M\fP \fIaddr\fP] [\fB\-p\fP \fIport\fP] [\fB\-b\fP \fIport\fP]
.B [\-\fBL\fP \fIlogfile\fP] [\fB\-C\fP \fIconfig\fP] [\fB\-P\fP \fIpasswd\fP]
[\fB\-L\fP \fIlogfile\fP]
.SH DESCRIPTION .SH DESCRIPTION
.B Conserver .B Conserver
is the daemon for the is the daemon that manages
.IR console (1) remote access to system consoles by multiple users via the
program. .BR console (1)
It provides remote access to the server consoles, client program
and logs all console data. and logs all console output.
Slave hosts which have no current connection might produce important It can connect to consoles via local serial ports
error messages; these unloved errors are labeled with a machine name or terminal servers that allow network access,
and output on stdout. or to any external program.
.PP .PP
When started, it forks a child for each group in /etc/conserver.cf and When started,
assigns each process a port number to listen on. The \fIconsole\fP .B conserver
client program communicates with the master console server to find reads its
the host and port the child is listening on. .BR conserver.cf (5)
file for details of each console it should manage,
including serial port or network parameters and logging options.
(Also, in environments where multiple servers share a cf file,
any server is able to refer clients to the particular server
managing a requested console,
so that the client need not have knowledge of the
distribution of consoles among servers.)
.B Conserver
forks a child for each group of consoles it must manage
and assigns each process a port number to listen on.
(The maximum number of consoles managed by each child process,
as well as the maximum number of children created, is set at compile time.)
The
.BR console (1)
client program communicates with the master console server process to find
the port (and host, in a multi-server configuration)
on which the appropriate child is listening.
The master conserver process forks a new process to handle each
incoming client connection.
.B Conserver
restricts connections from clients based on the host access section of its
.BR conserver.cf (5)
and authenticates users against its
.BR conserver.passwd (5)
file.
.PP .PP
.B Conserver .B Conserver
completely controls any connection to a controlled host. completely controls any connection to a controlled host.
All handling of escape sequenes is done by the server, All escape sequences given by the user to \fBconsole\fP
except the suspend sequence which is are passed to the server without interpretation.
sent as an out-of-band command to the client. The server recognizes and processes all escape sequences,
except the suspend sequence, which is
recognized by the server and
sent as a TCP out-of-band command from the server to the client.
.PP .PP
The \fBconserver\fP parent process will automatically respawn any child The \fBconserver\fP parent process will automatically respawn any child
process that dies. If the parent process receives a SIGTERM, it will process that dies. The following signals are propagated by the parent
propagate the signal to its children, shutting everything down. The process to its children.
parent will also propagate the SIGHUP and SIGUSR1 signals. A SIGHUP .TP
will cause all the console logfiles to be closed and SIGTERM
then reopened (no reread of the configuration file is done). A SIGUSR1 close all connections and exit.
will cause the server to try and connect to any consoles marked as .TP
SIGHUP
close and reopen all console logfiles
and, if in daemon mode (\fB\-d\fP option),
the error logfile (see the \fB\-L\fP option).
(No reread of the configuration file is done.)
.TP
SIGUSR1
try to connect to any consoles marked as
down. This can come in handy if you had a terminal server (or more) down. This can come in handy if you had a terminal server (or more)
that wasn't accepting connections at startup and you want that wasn't accepting connections at startup and you want
\fBconserver\fP to try and reconnect to all those downed ports. \fBconserver\fP to try to reconnect to all those downed ports.
.PP
Slave hosts which have no current
.BR console (1)
connection might produce important error messages.
With the \fB\-u\fP option, these unloved errors are labeled with a machine name
and output on stdout (or, in daemon mode, to the logfile).
This allows a live operator or an automated log scanner
to find otherwise unseen errors by watching in a single location.
.PP
\fBConserver\fP must be run as root if it is to bind to a port under 1024
or if it must read a shadow passwd file for authentication (see
.BR conserver.passwd (5)).
Otherwise, it may be run by any user, with \fB\-p\fP used to specify
a port above 1024.
.SH OPTIONS .SH OPTIONS
.PP
Options may be given as separate arguments (e.g., \fB\-n -d\fP)
or clustered (e.g., \fB\-nd\fP).
Options and their arguments may be separated by optional white space.
Option arguments containing spaces or other characters special to the shell
must be quoted.
.TP .TP
.B \-a .B \-7
Set the default access type. Strip the high bit off of all data received,
whether from the \fBconsole\fP client or from the console device,
before any processing occurs.
.TP
.BI \-a type
Set the default access type for incoming connections from
\fBconsole\fP clients:
.RB ` r '
for refused (the default),
.RB ` a '
for allowed, or
.RB ` t '
for trusted.
This applies to hosts for which no matching entry is found in
the access section of
.BR conserver.cf (5).
.TP
.BI \-b port
Set the base port for children to listen on.
Each child starts looking for free ports at \fIport\fP
and working upward, trying a maximum number of ports
equal to twice the maximum number of groups.
If no free ports are available in that range,
\fBconserver\fP exits.
By default, \fBconserver\fP lets the operating system choose
a free port.
.TP .TP
.BI \-C config .BI \-C config
This option points the server at a different configuration file. Read configuration information from the file \fIconfig\fP.
The default \fIconfig\fP is set at compile time using the The default \fIconfig\fP may be changed at compile time using the
--with-cffile option. \fB--with-cffile\fP option.
.TP .TP
.B \-d .B \-d
Become a daemon. Disconnects from the controlling terminal and sends Become a daemon. Disconnects from the controlling terminal and sends
all output to the logfile specified with \fB\-L\fP. all output to the logfile (see \fB\-L\fP).
.TP .TP
.B \-D .B \-D
Enable debugging output, sent to stderr. Enable debugging output, sent to stderr.
@ -60,41 +142,75 @@ Enable debugging output, sent to stderr.
Output a brief help message. Output a brief help message.
.TP .TP
.B \-i .B \-i
Initiate console connections on demand (and close them when not used) Initiate console connections on demand (and close them when not used).
.TP .TP
.BI \-L logfile .BI \-L logfile
This option points the server at a different logfile path. The default Log errors and informational messages to \fIlogfile\fP
\fIlogfile\fP is set at compile time using the --with-logfile option. after startup in daemon mode (\fB\-d\fP).
This option does not apply when not running in daemon mode.
The default \fIlogfile\fP may be changed at compile time using the
\fB--with-logfile\fP option.
.TP .TP
.BI \-M addr .BI \-M addr
Set the address to listen on. This allows conserver to bind to a Set the address to listen on. This allows conserver to bind to a
particular ip address (like `localhost') instead of all interfaces. particular IP address (like `127.0.0.1') instead of all interfaces.
The default is to bind to all addresses. The default is to bind to all addresses.
.TP .TP
.B \-n .B \-n
The \fIconserver\fP will \fBnot\fP output unloved console output to Obsolete (now a no-op); see \fB\-u\fP.
stdout.
.TP .TP
.BI \-p port .BI \-p port
Set the port to listen on. The default \fIport\fP is set at compile time Set the TCP port for the master process to listen on.
using the --with-port option. This may be either a port number or a service name.
The default \fIport\fP, ``conserver'' (typically 782),
may be changed at compile time using the \fB--with-port\fP option.
.TP .TP
.BI \-P passwd .BI \-P passwd
This option points the server at a different password file. The default Read the table of authorized user data from the file \fIpasswd\fP.
\fIpasswd\fP is set at compile time using the --with-pwdfile option. The default \fIpasswd\fP may be changed at compile time using the
\fB--with-pwdfile\fP option.
.TP
.B \-u
Send unloved console output to \fBconserver\fP's stdout
(which, in daemon mode, is redirected to the logfile).
This applies to all consoles to which no user is attached,
independent of whether logging of individual consoles is enabled
via \fBconserver.cf\fP entries.
.TP .TP
.B \-v .B \-v
Echo the configuration as it is being read (be verbose). Echo the configuration as it is being read (be verbose).
.TP .TP
.B \-V .B \-V
Output the version of the console server (only) and exit. Output the version number and settings of the \fBconserver\fP
program and then exit.
.SH FILES .SH FILES
.TS .PP
l l. The following default file locations may be overridden
/etc/conserver.cf description of console terminal lines at compile time or by the command-line options described above.
/etc/conserver.passwd users allowed to access consoles Run \fBconserver \-V\fP (with no other options) to see
\fIstdout\fP unloved console errors the defaults set at compile time.
.TE .PP
.PD 0
.TP 25
.B /etc/conserver.cf
description of console terminal lines and client host access levels;
see
.BR conserver.cf (5).
.TP
.B /etc/conserver.passwd
users allowed to access consoles; see
.BR conserver.passwd (5).
.TP
.B /var/run/conserver.pid
the master conserver process ID
.TP
.B /var/log/conserver
log of errors and informational messages
.PD
.PP
Additionally, output from individual consoles may be logged
to separate files specified in
.BR conserver.cf (5).
.SH AUTHORS .SH AUTHORS
Thomas A. Fine, Ohio State Computer Science Thomas A. Fine, Ohio State Computer Science
.br .br
@ -102,4 +218,6 @@ Kevin S Braunsdorf, Purdue University Computing Center
.br .br
Bryan Stansell, conserver.com Bryan Stansell, conserver.com
.SH "SEE ALSO" .SH "SEE ALSO"
console(1), conserver.cf(5) .BR console (1),
.BR conserver.cf (5),
.BR conserver.passwd (5)

View File

@ -7,10 +7,8 @@ PATH=/usr/bin:/usr/local/bin
case "$1" in case "$1" in
'start') 'start')
LF=/var/log/conserver.log
echo "Starting console server daemon" echo "Starting console server daemon"
[ -f $LF ] && mv $LF $LF.old conserver -d
conserver -n -d > $LF 2>&1
;; ;;
'stop') 'stop')

View File

@ -1,5 +1,5 @@
/* /*
* $Id: fallback.c,v 5.29 2001-06-29 00:34:11-07 bryan Exp $ * $Id: fallback.c,v 5.39 2001-07-26 00:58:55-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -24,7 +24,6 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/errno.h> #include <sys/errno.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/un.h>
#include <syslog.h> #include <syslog.h>
#include <signal.h> #include <signal.h>
#include <netdb.h> #include <netdb.h>
@ -32,70 +31,103 @@
#include <ctype.h> #include <ctype.h>
#include <compat.h> #include <compat.h>
#include <port.h> #include <port.h>
#include <util.h>
#if 0 /* Allocate some space for the results of getpseudotty */
static char *__pty_host; #if (defined(_AIX) || defined(PTX4))
static char *__pty_fmt; static char acMaster[] = "/dev/ptc/XXXXXXXXX";
static char acSlave[] = "/dev/pts/XXXXXXXXX";
#else
static char acMaster[] = "/dev/ptyXX";
static char acSlave[] = "/dev/ttyXX";
#endif /* _AIX */
#if defined(HAVE_PTSNAME) && defined(HAVE_GRANTPT) && defined(HAVE_UNLOCKPT)
#if defined(linux)
extern char *ptsname();
extern int grantpt();
extern int unlockpt();
#endif #endif
#if ! HAVE_PTSNAME /* get a pty for the user -- emulate the neato sequent call under (gregf)
* DYNIX/ptx v4.0
*/
static int
getpseudotty(slave, master)
char **master, **slave;
{
int fd;
char *pcName;
#if HAVE_SIGACTION
sigset_t oldmask, newmask;
#else
extern RETSIGTYPE FlagReapVirt();
#endif
if (0 > (fd = open("/dev/ptmx", O_RDWR, 0))) {
return -1;
}
#if HAVE_SIGACTION
sigemptyset(&newmask);
sigaddset(&newmask, SIGCHLD);
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
Error("sigprocmask(SIG_BLOCK): %s", strerror(errno));
#else
simpleSignal(SIGCHLD, SIG_DFL);
#endif
grantpt(fd); /* change permission of slave */
#if HAVE_SIGACTION
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
Error("sigprocmask(SIG_SETMASK): %s", strerror(errno));
#else
simpleSignal(SIGCHLD, FlagReapVirt);
#endif
unlockpt(fd); /* unlock slave */
if ((char *)0 == (pcName = ttyname(fd))) {
(void)strcpy(acMaster, "/dev/ptmx");
} else {
(void)strcpy(acMaster, pcName);
}
*master = acMaster;
if ((char *)0 == (pcName = ptsname(fd))) {
return -1;
}
(void)strcpy(acSlave, pcName);
*slave = acSlave;
return fd;
}
#else
/* /*
* Below is the string for finding /dev/ptyXX. For each architecture we * Below is the string for finding /dev/ptyXX. For each architecture we
* leave some pty's world writable because we don't have source for * leave some pty's world writable because we don't have source for
* everything that uses pty's. For the most part, we'll be trying to * everything that uses pty's. For the most part, we'll be trying to
* make /dev/ptyq* the "free" pty's. * make /dev/ptyq* the "free" pty's.
*/ */
# if defined(sun)
static char charone[] =
"prstuvwxyzPQRSTUVWq";
# else
# if defined(dynix)
static char charone[] =
"prstuvwxyzPQRSTUVWq";
# else
# if defined(ultrix)
static char charone[] =
"prstuvwxyzPQRSTUVWq";
# else
/* all the world's a vax ;-) */
static char charone[] =
"prstuvwxyzPQRSTUVWq";
# endif
# endif
# endif
/* all the world's a vax ;-) */
static char charone[] = "prstuvwxyzPQRSTUVWq";
static char chartwo[] = static char chartwo[] =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
#endif /* ! HAVE_PTSNAME */ # if defined(_AIX)
# if (defined(_AIX) || defined(PTX4))
static char acMaster[] =
"/dev/ptc/XXXXXXXXX";
static char acSlave[] =
"/dev/pts/XXXXXXXXX";
# else
static char acMaster[] =
"/dev/ptyXX";
static char acSlave[] =
"/dev/ttyXX";
# endif /* _AIX */
# if !HAVE_GETPSEUDO
# ifdef _AIX
/* /*
* get a pty for the user (emulate the neato sequent call) (mm) * get a pty for the user (emulate the neato sequent call) (mm)
*/ */
static int static int
getpseudotty(slave, master) getpseudotty(slave, master)
char **master, **slave; char **master, **slave;
{ {
int fd; int fd;
char *pcName; char *pcName;
if (0 > (fd = open("/dev/ptc", O_RDWR|O_NDELAY, 0))) { if (0 > (fd = open("/dev/ptc", O_RDWR | O_NDELAY, 0))) {
return -1; return -1;
} }
if ((char *)0 == (pcName = ttyname(fd))) { if ((char *)0 == (pcName = ttyname(fd))) {
@ -110,54 +142,18 @@ char **master, **slave;
return fd; return fd;
} }
# else
# if HAVE_PTSNAME
/* get a pty for the user -- emulate the neato sequent call under (gregf)
* DYNIX/ptx v4.0
*/
static int
getpseudotty(slave, master)
char **master, **slave;
{
int fd;
char *pcName;
if (0 > (fd = open("/dev/ptmx", O_RDWR, 0))) {
return -1;
}
grantpt(fd); /* change permission of slave */
unlockpt(fd); /* unlock slave */
if ((char *)0 == (pcName = ttyname(fd))) {
(void)strcpy(acMaster, "/dev/ptmx");
} else {
(void)strcpy(acMaster, pcName);
}
*master = acMaster;
if ((char *) 0 == (pcName = ptsname(fd))) {
return -1;
}
(void)strcpy(acSlave, pcName);
*slave = acSlave;
return fd;
}
# else # else
/* /*
* get a pty for the user (emulate the neato sequent call) (ksb) * get a pty for the user (emulate the neato sequent call) (ksb)
*/ */
static int static int
getpseudotty(slave, master) getpseudotty(slave, master)
char **master, **slave; char **master, **slave;
{ {
static char *pcOne = charone, *pcTwo = chartwo; static char *pcOne = charone, *pcTwo = chartwo;
auto int fd, iLoop, iIndex = sizeof("/dev/pty")-1; int fd, iLoop, iIndex = sizeof("/dev/pty") - 1;
auto char *pcOld1; char *pcOld1;
auto struct stat statBuf; struct stat statBuf;
iLoop = 0; iLoop = 0;
pcOld1 = pcOne; pcOld1 = pcOne;
@ -166,12 +162,12 @@ char **master, **slave;
pcTwo = chartwo; pcTwo = chartwo;
if ('\000' == *++pcOne) { if ('\000' == *++pcOne) {
pcOne = charone; pcOne = charone;
if (pcOld1 == pcOne && ++iLoop > 1 || iLoop > 32) if ((pcOld1 == pcOne && ++iLoop > 1) || (iLoop > 32))
return -1; return -1;
} }
} }
acMaster[iIndex] = *pcOne; acMaster[iIndex] = *pcOne;
acMaster[iIndex+1] = *pcTwo; acMaster[iIndex + 1] = *pcTwo;
/* /*
* Remeber we are root - stat the file * Remeber we are root - stat the file
@ -179,18 +175,19 @@ char **master, **slave;
* for read/write - if it doesn't we don't * for read/write - if it doesn't we don't
* have any pty's left in the row * have any pty's left in the row
*/ */
if (-1 == stat(acMaster, &statBuf) || S_IFCHR != (statBuf.st_mode&S_IFMT)) { if (-1 == stat(acMaster, &statBuf) ||
S_IFCHR != (statBuf.st_mode & S_IFMT)) {
pcTwo = "l"; pcTwo = "l";
continue; continue;
} }
if (0 > (fd = open(acMaster, O_RDWR|O_NDELAY, 0))) { if (0 > (fd = open(acMaster, O_RDWR | O_NDELAY, 0))) {
continue; continue;
} }
acSlave[iIndex] = *pcOne; acSlave[iIndex] = *pcOne;
acSlave[iIndex+1] = *pcTwo; acSlave[iIndex + 1] = *pcTwo;
if (-1 == access(acSlave, F_OK)) { if (-1 == access(acSlave, F_OK)) {
(void) close(fd); (void)close(fd);
continue; continue;
} }
break; break;
@ -199,24 +196,23 @@ char **master, **slave;
*slave = acSlave; *slave = acSlave;
return fd; return fd;
} }
# endif /* PTX version */
# endif /* _AIX */ # endif /* _AIX */
# endif /* !HAVE_GETPSEUDO */ #endif
/* /*
* get a Joe pty bacause the daemon is not with us, sadly. (ksb) * get a Joe pty bacause the daemon is not with us, sadly. (ksb)
*/ */
int int
FallBack(pcSlave, pcMaster) FallBack(pcSlave, pcMaster)
char *pcSlave, *pcMaster; char *pcSlave, *pcMaster;
{ {
auto int fd; int fd;
auto char *pcTSlave, *pcTMaster; char *pcTSlave, *pcTMaster;
if (-1 == (fd = getpseudotty(& pcTSlave, & pcTMaster))) { if (-1 == (fd = getpseudotty(&pcTSlave, &pcTMaster))) {
return -1; return -1;
} }
(void) strcpy(pcSlave, pcTSlave); (void)strcpy(pcSlave, pcTSlave);
(void) strcpy(pcMaster, pcTMaster); (void)strcpy(pcMaster, pcTMaster);
return fd; return fd;
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* /*
* $Id: group.h,v 5.15 2001-06-28 02:05:22-07 bryan Exp $ * $Id: group.h,v 5.17 2001-07-11 12:48:01-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -37,12 +37,12 @@
#define MAXPSWDLEN 16 /* max length of encrypted password */ #define MAXPSWDLEN 16 /* max length of encrypted password */
typedef struct grpent { /* group info */ typedef struct grpent { /* group info */
int port; /* port group listens on */ unsigned short port; /* port group listens on */
int pid; /* pid of server for group */ int pid; /* pid of server for group */
int imembers; /* number of consoles in this group */ int imembers; /* number of consoles in this group */
CONSENT *pCElist; /* list of consoles in this group */ CONSENT *pCElist; /* list of consoles in this group */
CONSCLIENT *pCLall; /* all clients to scan after select */ CONSCLIENT *pCLall; /* all clients to scan after select */
char passwd[MAXPSWDLEN];/* encrypted password for this group */ char passwd[MAXPSWDLEN]; /* encrypted password for this group */
} GRPENT; } GRPENT;

View File

@ -1,5 +1,5 @@
/* /*
* $Id: main.c,v 5.56 2001-07-05 05:48:18-07 bryan Exp $ * $Id: main.c,v 5.75 2001-07-26 11:49:41-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -44,8 +44,9 @@
#include <pwd.h> #include <pwd.h>
#include <compat.h> #include <compat.h>
#include <port.h> #include <port.h>
#include <util.h>
#include <consent.h> #include <consent.h>
#include <client.h> #include <client.h>
#include <group.h> #include <group.h>
@ -53,26 +54,28 @@
#include <access.h> #include <access.h>
#include <readcfg.h> #include <readcfg.h>
#include <version.h> #include <version.h>
#include <output.h>
int fAll = 1, fVerbose = 0, fSoftcar = 0, fNoinit = 0, fVersion = 0; int fAll = 0, fVerbose = 0, fSoftcar = 0, fNoinit = 0, fVersion =
int fDaemon = 0; 0, fStrip = 0, fDaemon = 0, fUseLogfile = 0;
char chDefAcc = 'r'; char chDefAcc = 'r';
#define FULLCFPATH SYSCONFDIR "/" CONFIGFILE; #define FULLCFPATH SYSCONFDIR "/" CONFIGFILE
#define FULLPDPATH SYSCONFDIR "/" PASSWDFILE; #define FULLPDPATH SYSCONFDIR "/" PASSWDFILE
char *pcLogfile = LOGFILEPATH; char *pcLogfile = LOGFILEPATH;
char *pcConfig = FULLCFPATH; char *pcConfig = FULLCFPATH;
char *pcPasswd = FULLPDPATH; char *pcPasswd = FULLPDPATH;
char *pcPort = DEFPORT; char *pcPort = DEFPORT;
char *pcBasePort = DEFBASEPORT;
int domainHack = 0; int domainHack = 0;
char *pcAddress = NULL; char *pcAddress = NULL;
unsigned long bindAddr; unsigned long bindAddr;
unsigned int bindPort; unsigned int bindPort;
unsigned int bindBasePort;
struct sockaddr_in in_port; struct sockaddr_in in_port;
char acMyAddr[4]; /* "\200\76\7\1" */ struct in_addr acMyAddr;
char acMyHost[256]; /* staff.cc.purdue.edu */ char acMyHost[256]; /* staff.cc.purdue.edu */
void void
@ -84,10 +87,13 @@ reopenLogfile()
* after that, all bets are off...probably not see the errors (well, * after that, all bets are off...probably not see the errors (well,
* aside from the tail of the old logfile, if it was rolled). * aside from the tail of the old logfile, if it was rolled).
*/ */
if (!fUseLogfile)
return;
close(1); close(1);
if (1 != open(pcLogfile, O_WRONLY|O_CREAT|O_APPEND, 0644)) { if (1 != open(pcLogfile, O_WRONLY | O_CREAT | O_APPEND, 0644)) {
Error( "open: %s: %s", pcLogfile, strerror(errno)); Error("open: %s: %s", pcLogfile, strerror(errno));
exit(1); exit(EX_TEMPFAIL);
} }
close(2); close(2);
dup(1); dup(1);
@ -104,13 +110,13 @@ daemonize()
int td; int td;
#endif #endif
(void) signal(SIGQUIT, SIG_IGN); simpleSignal(SIGQUIT, SIG_IGN);
(void) signal(SIGINT, SIG_IGN); simpleSignal(SIGINT, SIG_IGN);
#if defined(SIGTTOU) #if defined(SIGTTOU)
(void) signal(SIGTTOU, SIG_IGN); simpleSignal(SIGTTOU, SIG_IGN);
#endif #endif
#if defined(SIGTSTP) #if defined(SIGTSTP)
(void) signal(SIGTSTP, SIG_IGN); simpleSignal(SIGTSTP, SIG_IGN);
#endif #endif
(void)fflush(stdout); (void)fflush(stdout);
@ -118,21 +124,13 @@ daemonize()
switch (res = fork()) { switch (res = fork()) {
case -1: case -1:
Error( "fork: %s", strerror(errno)); Error("fork: %s", strerror(errno));
exit(1); exit(EX_UNAVAILABLE);
case 0: case 0:
thepid = getpid(); thepid = getpid();
break; break;
default: default:
exit(0); exit(EX_OK);
}
/* if we read from stdin (by accident) we don't wanna block
*/
close(0);
if (0 != open("/dev/null", O_RDWR, 0644)) {
Error( "open: /dev/null: %s", strerror(errno));
exit(1);
} }
reopenLogfile(); reopenLogfile();
@ -144,7 +142,7 @@ daemonize()
#if HAVE_SETSID #if HAVE_SETSID
(void)setsid(); (void)setsid();
#else #else
(void) setpgrp(0, getpid()); (void)setpgrp(0, getpid());
/* lose our controlling terminal /* lose our controlling terminal
*/ */
@ -155,8 +153,8 @@ daemonize()
#endif #endif
fp = fopen(PIDFILE, "w"); fp = fopen(PIDFILE, "w");
if ( fp ) { if (fp) {
fprintf(fp, "%d\n", (int) getpid()); fprintf(fp, "%d\n", (int)getpid());
fclose(fp); fclose(fp);
} else { } else {
Error("can't write pid to %s", PIDFILE); Error("can't write pid to %s", PIDFILE);
@ -165,19 +163,22 @@ daemonize()
static char u_terse[] = static char u_terse[] =
" [-dDhinsvV] [-a type] [-M addr] [-p port] [-C config] [-P passwd] [-L logfile]"; " [-7dDhinuvV] [-a type] [-M addr] [-p port] [-b port] [-C config] [-P passwd] [-L logfile]";
static char *apcLong[] = { static char *apcLong[] = {
"7 strip the high bit of all console data",
"a type set the default access type", "a type set the default access type",
"b port base port for secondary channel (any by default)",
"C config give a new config file to the server process", "C config give a new config file to the server process",
"d become a daemon, output to logfile (see -L)", "d become a daemon, redirecting stdout/stderr to logfile",
"D enable debug output, sent to stderr", "D enable debug output, sent to stderr",
"h output this message", "h output this message",
"i init console connections on demand", "i initialize console connections on demand",
"L logfile give a new logfile path to the server process", "L logfile give a new logfile path to the server process",
"M addr address to listen on (all addresses by default)", "M addr address to listen on (all addresses by default)",
"n do not output summary stream to stdout", "n obsolete - see -u",
"p port port to listen on", "p port port to listen on",
"P passwd give a new passwd file to the server process", "P passwd give a new passwd file to the server process",
"u copy \"unloved\" console data to stdout",
"v be verbose on startup", "v be verbose on startup",
"V output version info", "V output version info",
(char *)0 (char *)0
@ -187,9 +188,9 @@ static char *apcLong[] = {
*/ */
static void static void
Usage(ppc) Usage(ppc)
char **ppc; char **ppc;
{ {
for (/* passed */; (char *)0 != *ppc; ++ppc) for ( /* passed */ ; (char *)0 != *ppc; ++ppc)
fprintf(stderr, "\t%s\n", *ppc); fprintf(stderr, "\t%s\n", *ppc);
} }
@ -198,32 +199,30 @@ char **ppc;
static void static void
Version() Version()
{ {
auto char acA1[16], acA2[16]; char acA1[16], acA2[16];
int i; int i;
outputPid = 0; outputPid = 0;
Info("%s", THIS_VERSION); Info("%s", THIS_VERSION);
Info("default access type `%c\'", chDefAcc); Info("default access type `%c\'", chDefAcc);
Info("default escape sequence `%s%s\'", FmtCtl(DEFATTN, acA1), FmtCtl(DEFESC, acA2)); Info("default escape sequence `%s%s\'", FmtCtl(DEFATTN, acA1),
FmtCtl(DEFESC, acA2));
Info("configuration in `%s\'", pcConfig); Info("configuration in `%s\'", pcConfig);
Info("password in `%s\'", pcPasswd); Info("password in `%s\'", pcPasswd);
Info("logfile is `%s\'", pcLogfile); Info("logfile is `%s\'", pcLogfile);
Info("pidfile is `%s\'", PIDFILE); Info("pidfile is `%s\'", PIDFILE);
Info("limited to %d group%s with %d member%s", MAXGRP, MAXGRP == 1 ? "" : "s", MAXMEMB, MAXMEMB == 1 ? "" : "s"); Info("limited to %d group%s with %d member%s", MAXGRP,
#if CPARITY MAXGRP == 1 ? "" : "s", MAXMEMB, MAXMEMB == 1 ? "" : "s");
Info("high-bit of data stripped (7-bit clean)");
#else
Info("high-bit of data *not* stripped (8-bit clean)");
#endif
/* Look for non-numeric characters */ /* Look for non-numeric characters */
for (i=0;pcPort[i] != '\000';i++) for (i = 0; pcPort[i] != '\000'; i++)
if (!isdigit((int)pcPort[i])) break; if (!isdigit((int)pcPort[i]))
break;
if ( pcPort[i] == '\000' ) { if (pcPort[i] == '\000') {
/* numeric only */ /* numeric only */
bindPort = atoi( pcPort ); bindPort = atoi(pcPort);
Info("on port %u (referenced as `%s')", bindPort, pcPort); Info("on port %u (referenced as `%s')", bindPort, pcPort);
} else { } else {
/* non-numeric only */ /* non-numeric only */
@ -231,14 +230,37 @@ Version()
if ((struct servent *)0 == (pSE = getservbyname(pcPort, "tcp"))) { if ((struct servent *)0 == (pSE = getservbyname(pcPort, "tcp"))) {
Error("getservbyname: %s: %s", pcPort, strerror(errno)); Error("getservbyname: %s: %s", pcPort, strerror(errno));
} else { } else {
bindPort = ntohs((u_short)pSE->s_port); bindPort = ntohs((u_short) pSE->s_port);
Info("on port %u (referenced as `%s')", bindPort, pcPort); Info("on port %u (referenced as `%s')", bindPort, pcPort);
} }
} }
/* Look for non-numeric characters */
for (i = 0; pcBasePort[i] != '\000'; i++)
if (!isdigit((int)pcBasePort[i]))
break;
if (pcBasePort[i] == '\000') {
/* numeric only */
bindBasePort = atoi(pcBasePort);
Info("secondary channel base port %u (referenced as `%s')",
bindBasePort, pcBasePort);
} else {
/* non-numeric only */
struct servent *pSE;
if ((struct servent *)0 ==
(pSE = getservbyname(pcBasePort, "tcp"))) {
Error("getservbyname: %s: %s", pcBasePort, strerror(errno));
} else {
bindBasePort = ntohs((u_short) pSE->s_port);
Info("secondary channel base port %u (referenced as `%s')",
bindBasePort, pcBasePort);
}
}
if (fVerbose) if (fVerbose)
printf(COPYRIGHT); printf(COPYRIGHT);
exit(1); exit(EX_OK);
} }
/* find out where/who we are (ksb) /* find out where/who we are (ksb)
@ -251,17 +273,17 @@ Version()
*/ */
int int
main(argc, argv) main(argc, argv)
int argc; int argc;
char **argv; char **argv;
{ {
register int i, j; int i, j;
register FILE *fpConfig; FILE *fpConfig;
auto struct hostent *hpMe; struct hostent *hpMe;
static char acOpts[] = "a:C:dDhiM:np:P:sVv"; static char acOpts[] = "7a:b:C:dDhiL:M:np:P:suVv";
extern int optopt; extern int optopt;
extern char *optarg; extern char *optarg;
auto REMOTE REMOTE *pRCUniq; /* list of uniq console servers */
*pRCUniq; /* list of uniq console servers */ struct passwd *pwd;
outputPid = 1; /* make sure stuff has the pid */ outputPid = 1; /* make sure stuff has the pid */
@ -286,21 +308,25 @@ char **argv;
(void)gethostname(acMyHost, sizeof(acMyHost)); (void)gethostname(acMyHost, sizeof(acMyHost));
if ((struct hostent *)0 == (hpMe = gethostbyname(acMyHost))) { if ((struct hostent *)0 == (hpMe = gethostbyname(acMyHost))) {
Error( "gethostbyname(%s): %s", acMyHost, hstrerror(h_errno)); Error("gethostbyname(%s): %s", acMyHost, hstrerror(h_errno));
exit(1); exit(EX_UNAVAILABLE);
} }
if (4 != hpMe->h_length || AF_INET != hpMe->h_addrtype) { if (4 != hpMe->h_length || AF_INET != hpMe->h_addrtype) {
Error( "wrong address size (4 != %d) or adress family (%d != %d)", hpMe->h_length, AF_INET, hpMe->h_addrtype); Error("wrong address size (4 != %d) or adress family (%d != %d)",
exit(1); hpMe->h_length, AF_INET, hpMe->h_addrtype);
exit(EX_UNAVAILABLE);
} }
#if HAVE_MEMCPY #if HAVE_MEMCPY
(void)memcpy(&acMyAddr[0], hpMe->h_addr, hpMe->h_length); (void)memcpy(&acMyAddr, hpMe->h_addr, hpMe->h_length);
#else #else
(void)bcopy(hpMe->h_addr, &acMyAddr[0], hpMe->h_length); (void)bcopy(hpMe->h_addr, &acMyAddr, hpMe->h_length);
#endif #endif
while (EOF != (i = getopt(argc, argv, acOpts))) { while (EOF != (i = getopt(argc, argv, acOpts))) {
switch (i) { switch (i) {
case '7':
fStrip = 1;
break;
case 'a': case 'a':
chDefAcc = '\000' == *optarg ? 'r' : *optarg; chDefAcc = '\000' == *optarg ? 'r' : *optarg;
if (isupper((int)(chDefAcc))) { if (isupper((int)(chDefAcc))) {
@ -312,21 +338,19 @@ char **argv;
case 't': case 't':
break; break;
default: default:
Error( "unknown access type `%s\'", optarg); Error("unknown access type `%s\'", optarg);
exit(3); exit(EX_UNAVAILABLE);
} }
break; break;
case 'b':
pcBasePort = optarg;
break;
case 'C': case 'C':
pcConfig = optarg; pcConfig = optarg;
break; break;
case 'p':
pcPort = optarg;
break;
case 'P':
pcPasswd = optarg;
break;
case 'd': case 'd':
fDaemon = 1; fDaemon = 1;
fUseLogfile = 1;
break; break;
case 'D': case 'D':
fDebug = 1; fDebug = 1;
@ -334,7 +358,7 @@ char **argv;
case 'h': case 'h':
fprintf(stderr, "%s: usage%s\n", progname, u_terse); fprintf(stderr, "%s: usage%s\n", progname, u_terse);
Usage(apcLong); Usage(apcLong);
exit(0); exit(EX_OK);
case 'i': case 'i':
fNoinit = 1; fNoinit = 1;
break; break;
@ -345,11 +369,20 @@ char **argv;
pcAddress = optarg; pcAddress = optarg;
break; break;
case 'n': case 'n':
fAll = 0; /* noop now */
break;
case 'p':
pcPort = optarg;
break;
case 'P':
pcPasswd = optarg;
break; break;
case 's': case 's':
fSoftcar ^= 1; fSoftcar ^= 1;
break; break;
case 'u':
fAll = 1;
break;
case 'V': case 'V':
fVersion = 1; fVersion = 1;
break; break;
@ -358,79 +391,116 @@ char **argv;
break; break;
case '\?': case '\?':
fprintf(stderr, "%s: usage%s\n", progname, u_terse); fprintf(stderr, "%s: usage%s\n", progname, u_terse);
exit(1); exit(EX_UNAVAILABLE);
default: default:
Error( "option %c needs a parameter", optopt); Error("option %c needs a parameter", optopt);
exit(1); exit(EX_UNAVAILABLE);
} }
} }
/* if we read from stdin (by accident) we don't wanna block.
* we just don't want any more input at this point.
*/
close(0);
if (0 != open("/dev/null", O_RDWR, 0644)) {
Error("open: /dev/null: %s", strerror(errno));
exit(EX_UNAVAILABLE);
}
if (fVersion) { if (fVersion) {
Version(); Version();
exit(0); exit(EX_OK);
} }
if (fDaemon) { if (fDaemon) {
daemonize(); daemonize();
} }
Info("%s", THIS_VERSION);
if ((struct passwd *)0 == (pwd = getpwuid(getuid())))
Info("Started by uid %d at %s", getuid(), strtime(NULL));
else
Info("Started by `%s' at %s", pwd->pw_name, strtime(NULL));
#if HAVE_GETSPNAM #if HAVE_GETSPNAM
if (0 != geteuid()) { if (0 != geteuid()) {
Error( "Warning: Running as a non-root user - any shadow password usage will most likely fail!" ); Error
("Warning: Running as a non-root user - any shadow password usage will most likely fail!");
} }
#endif #endif
/* read the config file /* read the config file
*/ */
if ((FILE *)0 == (fpConfig = fopen(pcConfig, "r"))) { if ((FILE *) 0 == (fpConfig = fopen(pcConfig, "r"))) {
Error( "fopen: %s: %s", pcConfig, strerror(errno)); Error("fopen: %s: %s", pcConfig, strerror(errno));
exit(1); exit(EX_UNAVAILABLE);
} }
#if HAVE_FLOCK #if HAVE_FLOCK
/* we lock the configuration file so that two identical /* we lock the configuration file so that two identical
* conservers will not be running together (but two with * conservers will not be running together (but two with
* different configurations can run on the same host). * different configurations can run on the same host).
*/ */
if (-1 == flock(fileno(fpConfig), LOCK_NB|LOCK_EX)) { if (-1 == flock(fileno(fpConfig), LOCK_NB | LOCK_EX)) {
Error( "%s is locked, won\'t run more than one conserver?", pcConfig); Error("%s is locked, won\'t run more than one conserver?",
exit(3); pcConfig);
exit(EX_UNAVAILABLE);
} }
#endif #endif
ReadCfg(pcConfig, fpConfig); ReadCfg(pcConfig, fpConfig);
if ( pcAddress == NULL ) { if (pcAddress == NULL) {
bindAddr = (unsigned long)INADDR_ANY; bindAddr = (unsigned long)INADDR_ANY;
} else { } else {
if ((bindAddr = inet_addr(pcAddress)) == -1) { if ((bindAddr = inet_addr(pcAddress)) == -1) {
Error("inet_addr: %s: %s", pcAddress, "invalid IP address"); Error("inet_addr: %s: %s", pcAddress, "invalid IP address");
exit(1); exit(EX_UNAVAILABLE);
} }
} }
Debug( "Bind address set to `%s'", inet_ntoa(*(struct in_addr *)&bindAddr) ); Debug("Bind address set to `%s'",
inet_ntoa(*(struct in_addr *)&bindAddr));
if ( pcPort == NULL ) if (pcPort == NULL) {
{ Error("Severe error: pcPort is NULL???? How can that be?");
Error( "Severe error: pcPort is NULL???? How can that be?" ); exit(EX_UNAVAILABLE);
exit(1);
} }
/* Look for non-numeric characters */ /* Look for non-numeric characters */
for (i=0;pcPort[i] != '\000';i++) for (i = 0; pcPort[i] != '\000'; i++)
if (!isdigit((int)pcPort[i])) break; if (!isdigit((int)pcPort[i]))
break;
if ( pcPort[i] == '\000' ) { if (pcPort[i] == '\000') {
/* numeric only */ /* numeric only */
bindPort = atoi( pcPort ); bindPort = atoi(pcPort);
} else { } else {
/* non-numeric only */ /* non-numeric only */
struct servent *pSE; struct servent *pSE;
if ((struct servent *)0 == (pSE = getservbyname(pcPort, "tcp"))) { if ((struct servent *)0 == (pSE = getservbyname(pcPort, "tcp"))) {
Debug("getservbyname: %s: %s", pcPort, strerror(errno)); Error("getservbyname: %s: %s", pcPort, strerror(errno));
exit(1); exit(EX_UNAVAILABLE);
} else { } else {
bindPort = ntohs((u_short)pSE->s_port); bindPort = ntohs((u_short) pSE->s_port);
}
}
/* Look for non-numeric characters */
for (i = 0; pcBasePort[i] != '\000'; i++)
if (!isdigit((int)pcBasePort[i]))
break;
if (pcBasePort[i] == '\000') {
/* numeric only */
bindBasePort = atoi(pcBasePort);
} else {
/* non-numeric only */
struct servent *pSE;
if ((struct servent *)0 ==
(pSE = getservbyname(pcBasePort, "tcp"))) {
Error("getservbyname: %s: %s", pcBasePort, strerror(errno));
exit(EX_UNAVAILABLE);
} else {
bindBasePort = ntohs((u_short) pSE->s_port);
} }
} }
@ -446,10 +516,11 @@ char **argv;
if (0 == aGroups[i].imembers) if (0 == aGroups[i].imembers)
continue; continue;
if (aGroups[i].imembers) { if (aGroups[i].imembers) {
Spawn(& aGroups[i]); Spawn(&aGroups[i]);
} }
if (fVerbose) { if (fVerbose) {
Info("group %d on port %d", i, ntohs((u_short)aGroups[i].port)); Info("group #%d pid %d on port %u", i, aGroups[i].pid,
ntohs(aGroups[i].port));
} }
for (j = 0; j < aGroups[i].imembers; ++j) { for (j = 0; j < aGroups[i].imembers; ++j) {
if (-1 != aGroups[i].pCElist[j].fdtty) if (-1 != aGroups[i].pCElist[j].fdtty)
@ -459,7 +530,8 @@ char **argv;
if (fVerbose) { if (fVerbose) {
for (i = 0; i < iAccess; ++i) { for (i = 0; i < iAccess; ++i) {
Info("access type '%c' for \"%s\"", pACList[i].ctrust, pACList[i].pcwho); Info("access type '%c' for \"%s\"", pACList[i].ctrust,
pACList[i].pcwho);
} }
} }
@ -467,8 +539,8 @@ char **argv;
/* output unique console server peers? /* output unique console server peers?
*/ */
if (fVerbose) { if (fVerbose) {
register REMOTE *pRC; REMOTE *pRC;
for (pRC = pRCUniq; (REMOTE *)0 != pRC; pRC = pRC->pRCuniq) { for (pRC = pRCUniq; (REMOTE *) 0 != pRC; pRC = pRC->pRCuniq) {
Info("peer server on `%s'", pRC->rhost); Info("peer server on `%s'", pRC->rhost);
} }
} }
@ -479,16 +551,11 @@ char **argv;
/* stop putting kids back, and shoot them /* stop putting kids back, and shoot them
*/ */
(void)signal(SIGCHLD, SIG_DFL); simpleSignal(SIGCHLD, SIG_DFL);
for (i = 0; i < MAXGRP; ++i) { SignalKids(SIGTERM);
if (0 == aGroups[i].imembers)
continue;
if (-1 == kill(aGroups[i].pid, SIGTERM)) {
Error( "kill: %s", strerror(errno));
}
}
Info("Stopped at %s", strtime(NULL));
(void)endpwent(); (void)endpwent();
(void)fclose(fpConfig); (void)fclose(fpConfig);
exit(0); exit(EX_OK);
} }

View File

@ -1,5 +1,5 @@
/* /*
* $Id: main.h,v 5.21 2001-07-05 05:09:50-07 bryan Exp $ * $Id: main.h,v 5.27 2001-07-11 12:52:57-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -37,15 +37,16 @@
/* program options and stuff /* program options and stuff
*/ */
extern char rcsid[]; extern char rcsid[];
extern int fAll, fVerbose, fSoftcar, fNoinit, fInteractive; extern int fAll, fVerbose, fSoftcar, fNoinit, fInteractive, fStrip,
fDaemon;
extern char chDefAcc; extern char chDefAcc;
extern unsigned long bindAddr; extern unsigned long bindAddr;
extern unsigned int bindPort; extern unsigned int bindPort, bindBasePort;
extern char *pcLogfile; extern char *pcLogfile;
extern char *pcConfig; extern char *pcConfig;
extern char *pcPasswd; extern char *pcPasswd;
extern struct sockaddr_in in_port; extern struct sockaddr_in in_port;
extern char acMyHost[]; extern char acMyHost[];
extern char acMyAddr[]; extern struct in_addr acMyAddr;
extern int domainHack; extern int domainHack;
extern void reopenLogfile(); extern void reopenLogfile();

View File

@ -1,5 +1,5 @@
/* /*
* $Id: master.c,v 5.42 2001-07-05 07:36:57-07 bryan Exp $ * $Id: master.c,v 5.60 2001-07-26 00:49:48-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -35,6 +35,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
@ -42,8 +43,9 @@
#include <pwd.h> #include <pwd.h>
#include <compat.h> #include <compat.h>
#include <port.h> #include <port.h>
#include <util.h>
#include <consent.h> #include <consent.h>
#include <client.h> #include <client.h>
#include <group.h> #include <group.h>
@ -52,7 +54,6 @@
#include <readcfg.h> #include <readcfg.h>
#include <version.h> #include <version.h>
#include <main.h> #include <main.h>
#include <output.h>
@ -65,7 +66,7 @@ FlagSawCHLD(sig)
{ {
fSawCHLD = 1; fSawCHLD = 1;
#if !HAVE_SIGACTION #if !HAVE_SIGACTION
(void)signal(SIGCHLD, FlagSawCHLD); simpleSignal(SIGCHLD, FlagSawCHLD);
#endif #endif
} }
@ -75,14 +76,10 @@ FlagSawCHLD(sig)
static void static void
FixKids() FixKids()
{ {
register int i, pid; int i, pid;
auto int UWbuf; int UWbuf;
#if HAVE_WAIT3 while (-1 != (pid = waitpid(-1, &UWbuf, WNOHANG))) {
while (-1 != (pid = wait3(& UWbuf, WNOHANG, (struct rusage *)0))) {
#else
while (-1 != (pid = wait(& UWbuf))) {
#endif
if (0 == pid) { if (0 == pid) {
break; break;
} }
@ -98,10 +95,41 @@ FixKids()
if (pid != aGroups[i].pid) if (pid != aGroups[i].pid)
continue; continue;
/* A couple ways to shut down the whole system */
if (WIFEXITED(UWbuf) && (WEXITSTATUS(UWbuf) == EX_UNAVAILABLE)) {
fSawQuit = 1;
/* So we don't kill something that's dead */
aGroups[i].pid = -1;
Info("%s: exit(%d), shutdown [%s]",
aGroups[i].pCElist[0].server, WEXITSTATUS(UWbuf),
strtime(NULL));
break;
}
if (WIFSIGNALED(UWbuf) && (WTERMSIG(UWbuf) == SIGTERM)) {
fSawQuit = 1;
/* So we don't kill something that's dead */
aGroups[i].pid = -1;
Info("%s: signal(%d), shutdown [%s]",
aGroups[i].pCElist[0].server, WTERMSIG(UWbuf),
strtime(NULL));
break;
}
/* If not, then just a simple restart of the child */
if (WIFEXITED(UWbuf))
Info("%s(%d): exit(%d), restarted [%s]", progname, pid,
WEXITSTATUS(UWbuf), strtime(NULL));
if (WIFSIGNALED(UWbuf))
Info("%s(%d): signal(%d), restarted [%s]", progname, pid,
WTERMSIG(UWbuf), strtime(NULL));
/* this kid kid is dead, start another /* this kid kid is dead, start another
*/ */
Spawn(& aGroups[i]); Spawn(&aGroups[i]);
Info("%s: exit(%d), restarted %s", aGroups[i].pCElist[0].server, WEXITSTATUS(UWbuf), strtime(NULL)); if (fVerbose) {
Info("group #%d pid %d on port %u", i, aGroups[i].pid,
ntohs(aGroups[i].port));
}
} }
} }
} }
@ -110,10 +138,26 @@ FixKids()
* Called when master process receives SIGTERM * Called when master process receives SIGTERM
*/ */
static RETSIGTYPE static RETSIGTYPE
QuitIt(arg) FlagQuitIt(arg)
int arg; int arg;
{ {
fSawQuit = 1; fSawQuit = 1;
#if !HAVE_SIGACTION
simpleSignal(SIGTERM, FlagQuitIt);
#endif
}
/* yes, this is basically the same as FlagQuitIt but we *may*
* want to do something special on SIGINT at some point.
*/
static RETSIGTYPE
FlagSawINT(arg)
int arg;
{
fSawQuit = 1;
#if !HAVE_SIGACTION
simpleSignal(SIGINT, FlagSawINT);
#endif
} }
static RETSIGTYPE static RETSIGTYPE
@ -122,7 +166,7 @@ FlagSawHUP(arg)
{ {
fSawHUP = 1; fSawHUP = 1;
#if !HAVE_SIGACTION #if !HAVE_SIGACTION
(void)signal(SIGHUP, FlagSawHUP); simpleSignal(SIGHUP, FlagSawHUP);
#endif #endif
} }
@ -132,7 +176,7 @@ FlagSawUSR1(arg)
{ {
fSawUSR1 = 1; fSawUSR1 = 1;
#if !HAVE_SIGACTION #if !HAVE_SIGACTION
(void)signal(SIGUSR1, FlagSawUSR1); simpleSignal(SIGUSR1, FlagSawUSR1);
#endif #endif
} }
@ -144,8 +188,9 @@ SignalKids(arg)
{ {
int i; int i;
for (i = 0; i < MAXGRP; ++i) { for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers) if (0 == aGroups[i].imembers || -1 == aGroups[i].pid)
continue; continue;
Debug("Sending pid %d signal %d", aGroups[i].pid, arg);
if (-1 == kill(aGroups[i].pid, arg)) { if (-1 == kill(aGroups[i].pid, arg)) {
Error("kill: %s", strerror(errno)); Error("kill: %s", strerror(errno));
} }
@ -157,29 +202,34 @@ SignalKids(arg)
*/ */
void void
Master(pRCUniq) Master(pRCUniq)
REMOTE REMOTE *pRCUniq; /* list of uniq console servers */
*pRCUniq; /* list of uniq console servers */
{ {
register char *pcArgs; char *pcArgs;
register int i, j, cfd; int i, j, cfd;
register REMOTE *pRC, *pRCFound; CONSFILE *csocket;
register int nr, prnum = 0, found, msfd; REMOTE *pRC, *pRCFound;
register struct hostent *hpPeer; int nr, found, msfd;
auto char cType; unsigned short prnum = 0;
auto int so; struct hostent *hpPeer;
auto fd_set rmask, rmaster; char cType;
auto char acIn[1024], acOut[BUFSIZ]; int so;
auto struct sockaddr_in master_port, response_port; fd_set rmask, rmaster;
unsigned char acIn[1024], acOut[BUFSIZ];
struct sockaddr_in master_port, response_port;
int true = 1; int true = 1;
int pid;
char *ambiguous = (char *)0;
/* set up signal handler */ /* set up signal handler */
#if defined(SIGPOLL) #if defined(SIGPOLL)
signal(SIGPOLL, SIG_IGN); simpleSignal(SIGPOLL, SIG_IGN);
#endif #endif
Set_signal(SIGCHLD, FlagSawCHLD); simpleSignal(SIGCHLD, FlagSawCHLD);
Set_signal(SIGTERM, QuitIt); simpleSignal(SIGTERM, FlagQuitIt);
Set_signal(SIGUSR1, FlagSawUSR1); simpleSignal(SIGUSR1, FlagSawUSR1);
Set_signal(SIGHUP, FlagSawHUP); simpleSignal(SIGHUP, FlagSawHUP);
if (!fDaemon)
simpleSignal(SIGINT, FlagSawINT);
/* set up port for master to listen on /* set up port for master to listen on
*/ */
@ -189,20 +239,23 @@ REMOTE
(void)bzero((char *)&master_port, sizeof(master_port)); (void)bzero((char *)&master_port, sizeof(master_port));
#endif #endif
master_port.sin_family = AF_INET; master_port.sin_family = AF_INET;
*(u_long *)&master_port.sin_addr = bindAddr; master_port.sin_addr.s_addr = bindAddr;
master_port.sin_port = htons(bindPort); master_port.sin_port = htons(bindPort);
if ((msfd=socket(AF_INET, SOCK_STREAM, 0)) < 0) { if ((msfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
Error("socket: %s", strerror(errno)); Error("socket: %s", strerror(errno));
return; return;
} }
#if HAVE_SETSOCKOPT #if HAVE_SETSOCKOPT
if (setsockopt(msfd, SOL_SOCKET, SO_REUSEADDR, (char *)&true, sizeof(true))<0) { if (setsockopt
(msfd, SOL_SOCKET, SO_REUSEADDR, (char *)&true,
sizeof(true)) < 0) {
Error("setsockopt: %s", strerror(errno)); Error("setsockopt: %s", strerror(errno));
return; return;
} }
#endif #endif
if (bind(msfd, (struct sockaddr *)&master_port, sizeof(master_port))<0) { if (bind(msfd, (struct sockaddr *)&master_port, sizeof(master_port)) <
0) {
Error("bind: %s", strerror(errno)); Error("bind: %s", strerror(errno));
return; return;
} }
@ -212,7 +265,7 @@ REMOTE
FD_ZERO(&rmaster); FD_ZERO(&rmaster);
FD_SET(msfd, &rmaster); FD_SET(msfd, &rmaster);
for (fSawQuit = 0; !fSawQuit; /* can't close here :-( */) { for (fSawQuit = 0; !fSawQuit; /* can't close here :-( */ ) {
if (fSawCHLD) { if (fSawCHLD) {
fSawCHLD = 0; fSawCHLD = 0;
FixKids(); FixKids();
@ -226,11 +279,16 @@ REMOTE
fSawUSR1 = 0; fSawUSR1 = 0;
SignalKids(SIGUSR1); SignalKids(SIGUSR1);
} }
if (fSawQuit) { /* Something above set the quit flag */
break;
}
rmask = rmaster; rmask = rmaster;
if (-1 == select(msfd+1, &rmask, (fd_set *)0, (fd_set *)0, (struct timeval *)0)) { if (-1 ==
if ( errno != EINTR ) { select(msfd + 1, &rmask, (fd_set *) 0, (fd_set *) 0,
(struct timeval *)0)) {
if (errno != EINTR) {
Error("select: %s", strerror(errno)); Error("select: %s", strerror(errno));
} }
continue; continue;
@ -239,77 +297,97 @@ REMOTE
continue; continue;
} }
so = sizeof(response_port); so = sizeof(response_port);
cfd = accept(msfd, (struct sockaddr *)&response_port, (socklen_t *)&so); cfd =
accept(msfd, (struct sockaddr *)&response_port,
(socklen_t *) & so);
if (cfd < 0) { if (cfd < 0) {
Error("accept: %s", strerror(errno)); Error("accept: %s", strerror(errno));
continue; continue;
} }
if ((CONSFILE *) 0 == (csocket = fileOpenFD(cfd, simpleSocket))) {
Error("fileOpenFD: %s", strerror(errno));
close(cfd);
continue;
}
so = sizeof(in_port); so = sizeof(in_port);
if (-1 == getpeername(cfd, (struct sockaddr *)&in_port, (socklen_t *)&so)) { if (-1 ==
CSTROUT(cfd, "getpeername failed\r\n"); getpeername(fileFDNum(csocket), (struct sockaddr *)&in_port,
(void)close(cfd); (socklen_t *) & so)) {
fileWrite(csocket, "getpeername failed\r\n", -1);
(void)fileClose(csocket);
continue; continue;
} }
so = sizeof(in_port.sin_addr); so = sizeof(in_port.sin_addr);
if ((struct hostent *)0 == (hpPeer = gethostbyaddr((char *)&in_port.sin_addr, so, AF_INET))) { if ((struct hostent *)0 ==
(hpPeer =
gethostbyaddr((char *)&in_port.sin_addr, so, AF_INET))) {
cType = AccType(&in_port.sin_addr, NULL); cType = AccType(&in_port.sin_addr, NULL);
} else { } else {
cType = AccType(&in_port.sin_addr, hpPeer->h_name); cType = AccType(&in_port.sin_addr, hpPeer->h_name);
} }
if ('r' == cType) { if ('r' == cType) {
CSTROUT(cfd, "access from your host refused\r\n"); fileWrite(csocket, "access from your host refused\r\n", -1);
(void)close(cfd); (void)fileClose(csocket);
continue; continue;
} }
#if TEST_FORK (void)fflush(stdin);
/* we should fork here, or timeout (void)fflush(stderr);
*/ switch (pid = fork()) {
switch(fork()) {
default:
(void)close(cfd);
continue;
case -1: case -1:
CSTROUT(cfd, "fork failed, try again\r\n"); fileWrite(csocket, "fork failed, try again later\r\n", -1);
(void)close(cfd); fileClose(csocket);
Error("fork: %s", strerror(errno));
continue;
default:
#if defined(__CYGWIN__)
/* Since we've got all that "special" stuff in the fileClose
* routine for getting around a winsock bug, we have to
* shut things down differently here. Instead of calling
* fileClose (which half-closes the socket as well as just
* closing the descriptor), we "unopen" the structure (to
* free memory) and then do a regular close. The child (which
* writes to the client) will do a fileClose and all the
* flushing magic will happen. UGH! -bryan
*/
close(fileUnopen(csocket));
#else
fileClose(csocket);
#endif
continue; continue;
case 0: case 0:
thepid = getpid(); thepid = getpid();
break; break;
} }
#endif
/* handle the connection /* handle the connection
* (port lookup, who, users, or quit) * (port lookup, who, users, or quit)
*/ */
CSTROUT(cfd, "ok\r\n"); fileWrite(csocket, "ok\r\n", -1);
for (i = 0; i < sizeof(acIn); /* i+=nr */) { for (i = 0; i < sizeof(acIn); /* i+=nr */ ) {
if (0 >= (nr = read(cfd, &acIn[i], sizeof(acIn)-1-i))) { if (0 >=
(nr = fileRead(csocket, &acIn[i], sizeof(acIn) - 1 - i))) {
i = 0; i = 0;
break; break;
} }
i += nr; i += nr;
if ('\n' == acIn[i-1]) { if ('\n' == acIn[i - 1]) {
acIn[i] = '\000'; acIn[i] = '\000';
--i; --i;
break; break;
} }
} }
if (i > 0 && '\n' == acIn[i-1]) { if (i > 0 && '\n' == acIn[i - 1]) {
acIn[--i] = '\000'; acIn[--i] = '\000';
} }
if (i > 0 && '\r' == acIn[i-1]) { if (i > 0 && '\r' == acIn[i - 1]) {
acIn[--i] = '\000'; acIn[--i] = '\000';
} }
if (0 == i) { if (0 == i) {
Error("lost connection"); Error("lost connection");
(void)close(cfd); (void)fileClose(csocket);
#if TEST_FORK exit(EX_OK);
exit(1);
#else
continue;
#endif
} }
if ((char *)0 != (pcArgs = strchr(acIn, ':'))) { if ((char *)0 != (pcArgs = strchr(acIn, ':'))) {
*pcArgs++ = '\000'; *pcArgs++ = '\000';
@ -327,133 +405,103 @@ REMOTE
"version provide version info for server\r\n", "version provide version info for server\r\n",
(char *)0 (char *)0
}; };
register char **ppc; char **ppc;
for (ppc = apcHelp; (char *)0 != *ppc; ++ppc) { for (ppc = apcHelp; (char *)0 != *ppc; ++ppc) {
(void)write(cfd, *ppc, strlen(*ppc)); (void)fileWrite(csocket, *ppc, -1);
} }
(void)close(cfd); (void)fileClose(csocket);
#if TEST_FORK exit(EX_OK);
exit(0);
#else
continue;
#endif
} }
if (0 == strcmp(acIn, "quit")) { if (0 == strcmp(acIn, "quit")) {
register struct passwd *pwd; struct passwd *pwd;
if ('t' == cType) { if ('t' == cType) {
CSTROUT(cfd, "trusted -- terminated\r\n"); fileWrite(csocket, "trusted -- terminated\r\n", -1);
#if TEST_FORK
kill(getppid(), SIGTERM);
#else
fSawQuit = 1; fSawQuit = 1;
#endif
} else if ((char *)0 == pcArgs) { } else if ((char *)0 == pcArgs) {
CSTROUT(cfd, "must be trusted to terminate\r\n"); fileWrite(csocket, "must be trusted to terminate\r\n", -1);
} else if ((struct passwd *)0 == (pwd = getpwuid(0))) { } else if ((struct passwd *)0 == (pwd = getpwuid(0))) {
CSTROUT(cfd, "no root passwd?\r\n"); fileWrite(csocket, "no root passwd?\r\n", -1);
} else if (0 == CheckPass(pwd, (char *)0, pcArgs)) { } else if (0 == CheckPass(pwd, (char *)0, pcArgs)) {
CSTROUT(cfd, "Sorry.\r\n"); fileWrite(csocket, "Sorry.\r\n", -1);
} else { } else {
CSTROUT(cfd, "ok -- terminated\r\n"); fileWrite(csocket, "ok -- terminated\r\n", -1);
#if TEST_FORK
kill(getppid(), SIGTERM);
#else
fSawQuit = 1; fSawQuit = 1;
#endif
} }
(void)close(cfd); (void)fileClose(csocket);
#if TEST_FORK exit(EX_OK);
exit(0);
#else
continue;
#endif
} }
if (0 == strcmp(acIn, "pid")) { if (0 == strcmp(acIn, "pid")) {
#if TEST_FORK
sprintf(acOut, "%d\r\n", (int)getppid());
(void)write(cfd, acOut, strlen(acOut));
exit(0);
#else
sprintf(acOut, "%d\r\n", (int)getpid()); sprintf(acOut, "%d\r\n", (int)getpid());
(void)write(cfd, acOut, strlen(acOut)); (void)fileWrite(csocket, acOut, -1);
(void)close(cfd); (void)fileClose(csocket);
continue; exit(EX_OK);
#endif
} }
if (0 == strcmp(acIn, "groups")) { if (0 == strcmp(acIn, "groups")) {
register int iSep = 1; int iSep = 1;
for (i = 0; i < MAXGRP; ++i) { for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers) if (0 == aGroups[i].imembers)
continue; continue;
sprintf(acOut, ":%d"+iSep, ntohs((u_short)aGroups[i].port)); sprintf(acOut, ":%u" + iSep, ntohs(aGroups[i].port));
(void)write(cfd, acOut, strlen(acOut)); (void)fileWrite(csocket, acOut, -1);
iSep = 0; iSep = 0;
} }
CSTROUT(cfd, "\r\n"); fileWrite(csocket, "\r\n", -1);
(void)close(cfd); (void)fileClose(csocket);
#if TEST_FORK exit(EX_OK);
exit(0);
#else
continue;
#endif
} }
if (0 == strcmp(acIn, "master")) { if (0 == strcmp(acIn, "master")) {
register int iSep = 1; int iSep = 1;
if (0 != iLocal) { if (0 != iLocal) {
sprintf(acOut, "@%s", acMyHost); struct sockaddr_in lcl;
(void)write(cfd, acOut, strlen(acOut)); so = sizeof(lcl);
if (-1 ==
getsockname(fileFDNum(csocket),
(struct sockaddr *)&lcl,
(socklen_t *) & so)) {
fileWrite(csocket,
"getsockname failed, try again later\r\n",
-1);
Error("getsockname: %s", strerror(errno));
exit(EX_UNAVAILABLE);
}
sprintf(acOut, "@%s", inet_ntoa(lcl.sin_addr));
(void)fileWrite(csocket, acOut, -1);
iSep = 0; iSep = 0;
} }
for (pRC = pRCUniq; (REMOTE *)0 != pRC; pRC = pRC->pRCuniq) { for (pRC = pRCUniq; (REMOTE *) 0 != pRC; pRC = pRC->pRCuniq) {
sprintf(acOut, ":@%s"+iSep, pRC->rhost); sprintf(acOut, ":@%s" + iSep, pRC->rhost);
(void)write(cfd, acOut, strlen(acOut)); (void)fileWrite(csocket, acOut, -1);
iSep = 0; iSep = 0;
} }
CSTROUT(cfd, "\r\n"); fileWrite(csocket, "\r\n", -1);
(void)close(cfd); (void)fileClose(csocket);
#if TEST_FORK exit(EX_OK);
exit(0);
#else
continue;
#endif
} }
if (0 == strcmp(acIn, "version")) { if (0 == strcmp(acIn, "version")) {
sprintf(acOut, "version `%s\'\r\n", THIS_VERSION); sprintf(acOut, "version `%s\'\r\n", THIS_VERSION);
(void)write(cfd, acOut, strlen(acOut)); (void)fileWrite(csocket, acOut, -1);
(void)close(cfd); (void)fileClose(csocket);
#if TEST_FORK exit(EX_OK);
exit(0);
#else
continue;
#endif
} }
if (0 != strcmp(acIn, "call")) { if (0 != strcmp(acIn, "call")) {
CSTROUT(cfd, "unknown command\r\n"); fileWrite(csocket, "unknown command\r\n", -1);
(void)close(cfd); (void)fileClose(csocket);
#if TEST_FORK exit(EX_OK);
exit(0);
#else
continue;
#endif
} }
if ((char *)0 == pcArgs) { if ((char *)0 == pcArgs) {
CSTROUT(cfd, "call requires argument\r\n"); fileWrite(csocket, "call requires argument\r\n", -1);
(void)close(cfd); (void)fileClose(csocket);
#if TEST_FORK exit(EX_OK);
exit(0);
#else
continue;
#endif
} }
/* look up the machine to call /* look up the machine to call
*/ */
found = 0; found = 0;
pRCFound = (REMOTE *)0; pRCFound = (REMOTE *) 0;
/* look for a local machine */ /* look for a local machine */
for (i = 0; i < MAXGRP; ++i) { for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers) if (0 == aGroups[i].imembers)
@ -462,7 +510,9 @@ REMOTE
if (0 != strcmp(pcArgs, aGroups[i].pCElist[j].server)) { if (0 != strcmp(pcArgs, aGroups[i].pCElist[j].server)) {
continue; continue;
} }
prnum = ntohs((u_short)aGroups[i].port); prnum = ntohs(aGroups[i].port);
ambiguous = buildString(aGroups[i].pCElist[j].server);
ambiguous = buildString(", ");
++found; ++found;
} }
} }
@ -470,54 +520,66 @@ REMOTE
* duplicates - a bad state to be in. * duplicates - a bad state to be in.
* Does the readcfg.c code even check for dups? * Does the readcfg.c code even check for dups?
*/ */
for (pRC = pRCList; (REMOTE *)0 != pRC; pRC = pRC->pRCnext) { for (pRC = pRCList; (REMOTE *) 0 != pRC; pRC = pRC->pRCnext) {
if (0 != strcmp(pcArgs, pRC->rserver)) { if (0 != strcmp(pcArgs, pRC->rserver)) {
continue; continue;
} }
ambiguous = buildString(pRC->rserver);
ambiguous = buildString(", ");
++found; ++found;
pRCFound = pRC; pRCFound = pRC;
} }
if ( found == 0 ) { /* Then look for substring matches */ if (found == 0) { /* Then look for substring matches */
for (i = 0; i < MAXGRP; ++i) { for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers) if (0 == aGroups[i].imembers)
continue; continue;
for (j = 0; j < aGroups[i].imembers; ++j) { for (j = 0; j < aGroups[i].imembers; ++j) {
if (0 != strncmp(pcArgs, aGroups[i].pCElist[j].server, strlen(pcArgs))) { if (0 !=
strncmp(pcArgs, aGroups[i].pCElist[j].server,
strlen(pcArgs))) {
continue; continue;
} }
prnum = ntohs((u_short)aGroups[i].port); prnum = ntohs(aGroups[i].port);
ambiguous = buildString(aGroups[i].pCElist[j].server);
ambiguous = buildString(", ");
++found; ++found;
} }
} }
/* look for a remote server */ /* look for a remote server */
/* again, looks for dups with local consoles */ /* again, looks for dups with local consoles */
for (pRC = pRCList; (REMOTE *)0 != pRC; pRC = pRC->pRCnext) { for (pRC = pRCList; (REMOTE *) 0 != pRC; pRC = pRC->pRCnext) {
if (0 != strncmp(pcArgs, pRC->rserver, strlen(pcArgs))) { if (0 != strncmp(pcArgs, pRC->rserver, strlen(pcArgs))) {
continue; continue;
} }
ambiguous = buildString(pRC->rserver);
ambiguous = buildString(", ");
++found; ++found;
pRCFound = pRC; pRCFound = pRC;
} }
} }
switch (found) { switch (found) {
case 0: case 0:
sprintf(acOut, "server %s not found\r\n", pcArgs); sprintf(acOut, "console `%s' not found\r\n", pcArgs);
break; break;
case 1: case 1:
if ((REMOTE *)0 != pRCFound) { if ((REMOTE *) 0 != pRCFound) {
sprintf(acOut, "@%s\r\n", pRCFound->rhost); sprintf(acOut, "@%s\r\n", pRCFound->rhost);
} else { } else {
sprintf(acOut, "%d\r\n", prnum); sprintf(acOut, "%u\r\n", prnum);
} }
break; break;
default: default:
sprintf(acOut, "ambiguous server abbreviation, %s\r\n", pcArgs); found = strlen(ambiguous);
ambiguous[found - 2] = '\000';
sprintf(acOut,
"ambiguous console abbreviation, `%s'\r\n\tchoices are %s\r\n",
pcArgs, ambiguous);
break; break;
} }
(void)write(cfd, acOut, strlen(acOut)); buildString((char *)0); /* we're done - clean up */
(void)close(cfd); ambiguous = (char *)0;
#if TEST_FORK (void)fileWrite(csocket, acOut, -1);
exit(0); (void)fileClose(csocket);
#endif exit(EX_OK);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* $Id: master.h,v 5.10 2001-02-21 17:26:06-08 bryan Exp $ * $Id: master.h,v 5.11 2001-07-09 02:16:53-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -38,3 +38,4 @@
* stuff the master process needs * stuff the master process needs
*/ */
extern void Master(); extern void Master();
extern void SignalKids();

View File

@ -1,62 +0,0 @@
/*
* $Id: output.c,v 1.6 2001-07-05 00:09:39-07 bryan Exp $
*
* Copyright conserver.com, 2000-2001
*
* Maintainer/Enhancer: Bryan Stansell (bryan@conserver.com)
*/
#include <stdio.h>
#include <varargs.h>
#include <output.h>
int outputPid = 0;
char *progname = "conserver package";
int thepid = 0;
int fDebug = 0;
void Debug(fmt, va_alist)
char *fmt;
va_dcl
{
va_list ap;
va_start(ap);
if (!fDebug) return;
if (outputPid)
fprintf(stderr, "%s (%d): DEBUG: ", progname, thepid);
else
fprintf(stderr, "%s: DEBUG: ", progname);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n" );
va_end(ap);
}
void Error(fmt, va_alist)
char *fmt;
va_dcl
{
va_list ap;
va_start(ap);
if (outputPid)
fprintf(stderr, "%s (%d): ", progname, thepid);
else
fprintf(stderr, "%s: ", progname);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n" );
va_end(ap);
}
void Info(fmt, va_alist)
char *fmt;
va_dcl
{
va_list ap;
va_start(ap);
if (outputPid)
fprintf(stdout, "%s (%d): ", progname, thepid);
else
fprintf(stdout, "%s: ", progname);
vfprintf(stdout, fmt, ap);
fprintf(stdout, "\n" );
va_end(ap);
}

View File

@ -1,14 +0,0 @@
/*
* $Id: output.h,v 1.2 2001-07-05 00:09:39-07 bryan Exp $
*
* Copyright conserver.com, 2000-2001
*
* Maintainer/Enhancer: Bryan Stansell (bryan@conserver.com)
*/
extern void Debug();
extern void Error();
extern void Info();
extern int outputPid, fDebug;
extern char *progname;
extern int thepid;

View File

@ -1,5 +1,5 @@
/* /*
* $Id: port.h,v 1.26 2001-07-05 00:14:06-07 bryan Exp $ * $Id: port.h,v 1.28 2001-07-17 14:14:36-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -64,32 +64,6 @@
#define OB_SUSP 'Z' /* suspended by server */ #define OB_SUSP 'Z' /* suspended by server */
#define OB_DROP '.' /* dropped by server */ #define OB_DROP '.' /* dropped by server */
/* Due to C's poor man's macros the macro below would break if statements,
* What we want
* macro() { stuff }
* but the syntax gives us
* macro() { stuff };
*
* the extra semicolon breaks if statements!
* Of course, the one we use makes lint scream:
* macro() do { stuff } while (0)
*
* which is a statement and makes if statements safe
*/
#if defined(lint)
extern int shut_up_lint;
#else
# define shut_up_lint 0
#endif
/* this macro efficently outputs a constant string to a fd
* of course it doesn't check the write :-(
*/
#define CSTROUT(Mfd, Mstr) do { \
static char _ac[] = Mstr; \
write(Mfd, _ac, sizeof(_ac)-1); \
} while (shut_up_lint)
/* For legacy compile-time setting of the port... /* For legacy compile-time setting of the port...
*/ */
#if ! defined(DEFPORT) #if ! defined(DEFPORT)

View File

@ -1,5 +1,5 @@
/* /*
* $Id: readcfg.c,v 5.45 2001-07-05 09:06:52-07 bryan Exp $ * $Id: readcfg.c,v 5.61 2001-07-23 00:45:49-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -46,8 +46,9 @@
#include <pwd.h> #include <pwd.h>
#include <compat.h> #include <compat.h>
#include <port.h> #include <port.h>
#include <util.h>
#include <consent.h> #include <consent.h>
#include <client.h> #include <client.h>
#include <group.h> #include <group.h>
@ -55,19 +56,14 @@
#include <readcfg.h> #include <readcfg.h>
#include <master.h> #include <master.h>
#include <main.h> #include <main.h>
#include <output.h>
GRPENT GRPENT aGroups[MAXGRP]; /* even spread is OK */
aGroups[MAXGRP]; /* even spread is OK */ CONSENT aConsoles[MAXGRP * MAXMEMB]; /* gross over allocation */
CONSENT REMOTE *pRCList; /* list of remote consoles we know about */
aConsoles[MAXGRP*MAXMEMB]; /* gross over allocation */
REMOTE
*pRCList; /* list of remote consoles we know about */
int int
iLocal; /* number of local consoles */ iLocal; /* number of local consoles */
ACCESS ACCESS *pACList; /* `who do you love' (or trust) */
*pACList; /* `who do you love' (or trust) */
int int
iAccess; /* how many access restrictions we have */ iAccess; /* how many access restrictions we have */
@ -76,10 +72,10 @@ int
*/ */
int int
parseMark(pcFile, iLine, pcMark, tyme, pCE) parseMark(pcFile, iLine, pcMark, tyme, pCE)
const char *pcFile; const char *pcFile;
const int iLine; const int iLine;
const char *pcMark; const char *pcMark;
CONSENT *pCE; CONSENT *pCE;
{ {
char mark[BUFSIZ]; char mark[BUFSIZ];
char *p, *n = (char *)0; char *p, *n = (char *)0;
@ -87,41 +83,51 @@ CONSENT *pCE;
int factor = 0, pfactor = 0; int factor = 0, pfactor = 0;
int value = 0, pvalue = 0; int value = 0, pvalue = 0;
if ((pcMark == (char *)0) || if ((pcMark == (char *)0) || (*pcMark == '\000'))
(*pcMark == '\000'))
return 0; return 0;
(void)strcpy(mark, pcMark); (void)strcpy(mark, pcMark);
for (p = mark; *p != '\000'; p++) { for (p = mark; *p != '\000'; p++) {
if ( *p == 'a' || *p == 'A' ) { if (*p == 'a' || *p == 'A') {
if ( n != (char *)0 ) { if (n != (char *)0) {
Error( "%s(%d) bad timestamp specification `%s': numeral before `a' (ignoring numeral)", pcFile, iLine, pcMark); Error
("%s(%d) bad timestamp specification `%s': numeral before `a' (ignoring numeral)",
pcFile, iLine, pcMark);
} }
activity = 1; activity = 1;
} else if ( *p == 'm' || *p == 'M' ) { } else if (*p == 'm' || *p == 'M') {
pfactor = 60; pfactor = 60;
} else if ( *p == 'h' || *p == 'H' ) { } else if (*p == 'h' || *p == 'H') {
pfactor = 60 * 60; pfactor = 60 * 60;
} else if ( *p == 'd' || *p == 'D') { } else if (*p == 'd' || *p == 'D') {
pfactor = 60 * 60 * 24; pfactor = 60 * 60 * 24;
} else if ( *p == 'l' || *p == 'L') { } else if (*p == 'l' || *p == 'L') {
pfactor = -1; pfactor = -1;
} else if ( isdigit((int)*p) ) { } else if (isdigit((int)*p)) {
if ( n == (char *)0 ) if (n == (char *)0)
n = p; n = p;
} else if (isspace((int)*p)) {
if (n != (char *)0) {
pfactor = 60;
}
} else { } else {
Error( "%s(%d) bad timestamp specification `%s': unknown character `%c'", pcFile, iLine, pcMark, *p); Error
("%s(%d) bad timestamp specification `%s': unknown character `%c'",
pcFile, iLine, pcMark, *p);
return 0; return 0;
} }
if ( pfactor ) { if (pfactor) {
if ( n == (char *)0 ) { if (n == (char *)0) {
Error( "%s(%d) bad timestamp specification `%s': missing numeric prefix for `%c'", pcFile, iLine, pcMark, *p); Error
("%s(%d) bad timestamp specification `%s': missing numeric prefix for `%c'",
pcFile, iLine, pcMark, *p);
return 0; return 0;
} else { } else {
*p = '\000'; *p = '\000';
pvalue = atoi(n); pvalue = atoi(n);
if ( pvalue < 0 ) { if (pvalue < 0) {
Error( "%s(%d) negative timestamp specification `%s'", pcFile, iLine, pcMark); Error("%s(%d) negative timestamp specification `%s'",
pcFile, iLine, pcMark);
return 0; return 0;
} }
n = (char *)0; n = (char *)0;
@ -132,13 +138,25 @@ CONSENT *pCE;
} }
} }
Debug( "Mark spec of `%s' parsed: factor=%d, value=%d, activity=%d", pcMark, factor, value, activity ); if (n != (char *)0) {
pvalue = atoi(n);
if (pvalue < 0) {
Error("%s(%d) negative timestamp specification `%s'", pcFile,
iLine, pcMark);
return 0;
}
factor = 60;
value = pvalue * factor;
}
if (pCE != (CONSENT *)0) { Debug("Mark spec of `%s' parsed: factor=%d, value=%d, activity=%d",
pcMark, factor, value, activity);
if (pCE != (CONSENT *) 0) {
pCE->activitylog = activity; pCE->activitylog = activity;
if ( factor && value ) { if (factor && value) {
pCE->mark = value; pCE->mark = value;
if ( factor > 0 ) { if (factor > 0) {
pCE->nextMark = tyme + value; pCE->nextMark = tyme + value;
} else { } else {
pCE->nextMark = value; pCE->nextMark = value;
@ -155,15 +173,15 @@ CONSENT *pCE;
* a pointer to the start of the non-space part * a pointer to the start of the non-space part
*/ */
char * char *
pruneSpace( string ) pruneSpace(string)
char *string; char *string;
{ {
char *p; char *p;
char *head = (char *)0; char *head = (char *)0;
char *tail = (char *)0; char *tail = (char *)0;
/* Don't do much if it's crap */ /* Don't do much if it's crap */
if ( string == (char *)0 || *string == '\000' ) if (string == (char *)0 || *string == '\000')
return string; return string;
/* Now for the tricky part - search the string */ /* Now for the tricky part - search the string */
@ -192,36 +210,37 @@ char *string;
*/ */
void void
ReadCfg(pcFile, fp) ReadCfg(pcFile, fp)
char *pcFile; char *pcFile;
register FILE *fp; FILE *fp;
{ {
register GRPENT *pGE; GRPENT *pGE;
register int iG, minG; int iG, minG;
auto int iLine; int iLine;
auto char acIn[BUFSIZ]; unsigned char acIn[BUFSIZ];
char *acStart; char *acStart;
register GRPENT *pGEAll; GRPENT *pGEAll;
register CONSENT *pCE; CONSENT *pCE;
register REMOTE **ppRC; REMOTE **ppRC;
char LogDirectory[MAXLOGLEN]; char LogDirectory[MAXLOGLEN];
time_t tyme; time_t tyme;
char defMark[BUFSIZ]; char defMark[BUFSIZ];
tyme = time((time_t *)0); tyme = time((time_t *) 0);
LogDirectory[0] = '\000'; LogDirectory[0] = '\000';
defMark[0] = '\000';
pGEAll = aGroups; /* fill in these structs */ pGEAll = aGroups; /* fill in these structs */
pCE = aConsoles; pCE = aConsoles;
ppRC = & pRCList; ppRC = &pRCList;
iLocal = 0; iLocal = 0;
iG = minG = 0; iG = minG = 0;
iLine = 0; iLine = 0;
while (fgets(acIn, sizeof(acIn)-1, fp) != NULL) { while (fgets(acIn, sizeof(acIn) - 1, fp) != NULL) {
register char *pcLine, *pcMode, *pcLog, *pcRem, *pcStart, *pcMark; char *pcLine, *pcMode, *pcLog, *pcRem, *pcStart, *pcMark;
++iLine; ++iLine;
acStart = pruneSpace( acIn ); acStart = pruneSpace(acIn);
if ('#' == acStart[0] || '\000' == acStart[0]) { if ('#' == acStart[0] || '\000' == acStart[0]) {
continue; continue;
@ -229,45 +248,48 @@ register FILE *fp;
if ('%' == acStart[0] && '%' == acStart[1] && '\000' == acStart[2]) { if ('%' == acStart[0] && '%' == acStart[1] && '\000' == acStart[2]) {
break; break;
} }
if ( (char *)0 == strchr(acStart, ':') && if ((char *)0 == strchr(acStart, ':') &&
(char *)0 != (pcLine = strchr(acStart, '=')) ) { (char *)0 != (pcLine = strchr(acStart, '='))) {
*pcLine++ = '\000'; *pcLine++ = '\000';
acStart = pruneSpace( acStart ); acStart = pruneSpace(acStart);
pcLine = pruneSpace( pcLine ); pcLine = pruneSpace(pcLine);
if ( 0 == strcmp(acStart, "LOGDIR") ) { if (0 == strcmp(acStart, "LOGDIR")) {
(void)strcpy(LogDirectory, pcLine); (void)strcpy(LogDirectory, pcLine);
} else if ( 0 == strcmp(acStart, "TIMESTAMP") ) { } else if (0 == strcmp(acStart, "TIMESTAMP")) {
if ( parseMark(pcFile, iLine, pcLine, tyme, NULL) ) if (parseMark(pcFile, iLine, pcLine, tyme, NULL))
(void)strcpy(defMark, pcLine); (void)strcpy(defMark, pcLine);
else else
defMark[0] = '\000'; defMark[0] = '\000';
} else if ( 0 == strcmp(acStart, "DOMAINHACK") ) { } else if (0 == strcmp(acStart, "DOMAINHACK")) {
domainHack = 1; domainHack = 1;
} else { } else {
Error( "%s(%d) unknown variable `%s'", pcFile, iLine, acStart); Error("%s(%d) unknown variable `%s'", pcFile, iLine,
acStart);
} }
continue; continue;
} }
if ( (char *)0 == (pcLine = strchr(acStart, ':')) || if ((char *)0 == (pcLine = strchr(acStart, ':')) ||
(char *)0 == (pcMode = strchr(pcLine+1, ':')) || (char *)0 == (pcMode = strchr(pcLine + 1, ':')) ||
(char *)0 == (pcLog = strchr(pcMode+1, ':'))) { (char *)0 == (pcLog = strchr(pcMode + 1, ':'))) {
Error( "%s(%d) bad config line `%s'", pcFile, iLine, acIn); Error("%s(%d) bad config line `%s'", pcFile, iLine, acIn);
continue; continue;
} }
*pcLine++ = '\000'; *pcLine++ = '\000';
*pcMode++ = '\000'; *pcMode++ = '\000';
*pcLog++ = '\000'; *pcLog++ = '\000';
acStart = pruneSpace( acStart ); acStart = pruneSpace(acStart);
pcLine = pruneSpace( pcLine ); pcLine = pruneSpace(pcLine);
pcMode = pruneSpace( pcMode ); pcMode = pruneSpace(pcMode);
pcLog = pruneSpace( pcLog ); pcLog = pruneSpace(pcLog);
if ((char *)0 != (pcMark = strchr(pcLog, ':'))) { if ((char *)0 != (pcMark = strchr(pcLog, ':'))) {
*pcMark++ = '\000'; *pcMark++ = '\000';
pcMark = pruneSpace( pcMark ); pcLog = pruneSpace(pcLog);
pcMark = pruneSpace(pcMark);
/* Skip null intervals */ /* Skip null intervals */
if ( pcMark[0] == '\000' ) pcMark = (char *)0; if (pcMark[0] == '\000')
pcMark = (char *)0;
} }
/* if this server remote? /* if this server remote?
@ -276,41 +298,40 @@ register FILE *fp;
* I'm sure most sites will never use this code (ksb) * I'm sure most sites will never use this code (ksb)
*/ */
if ((char *)0 != (pcRem = strchr(pcLine, '@'))) { if ((char *)0 != (pcRem = strchr(pcLine, '@'))) {
auto struct hostent *hpMe; struct hostent *hpMe;
*pcRem++ = '\000'; *pcRem++ = '\000';
pcLine = pruneSpace( pcLine ); pcLine = pruneSpace(pcLine);
pcRem = pruneSpace( pcRem ); pcRem = pruneSpace(pcRem);
if ((struct hostent *)0 == if ((struct hostent *)0 == (hpMe = gethostbyname(pcRem))) {
(hpMe = gethostbyname(pcRem))) { Error("gethostbyname(%s): %s", pcRem, hstrerror(h_errno));
Error( "gethostbyname(%s): %s", pcRem, hstrerror(h_errno)); exit(EX_UNAVAILABLE);
exit(1);
} }
if (4 != hpMe->h_length || if (4 != hpMe->h_length || AF_INET != hpMe->h_addrtype) {
AF_INET != hpMe->h_addrtype) { Error
Error( "wrong address size (4 != %d) or address family (%d != %d)", hpMe->h_length, AF_INET, hpMe->h_addrtype); ("wrong address size (4 != %d) or address family (%d != %d)",
exit(1); hpMe->h_length, AF_INET, hpMe->h_addrtype);
exit(EX_UNAVAILABLE);
} }
if ( 0 != if (0 !=
#if HAVE_MEMCMP #if HAVE_MEMCMP
memcmp(&acMyAddr[0], hpMe->h_addr, hpMe->h_length) memcmp(&acMyAddr.s_addr, hpMe->h_addr, hpMe->h_length)
#else #else
bcmp(&acMyAddr[0], hpMe->h_addr, hpMe->h_length) bcmp(&acMyAddr.s_addr, hpMe->h_addr, hpMe->h_length)
#endif #endif
) { ) {
register REMOTE *pRCTemp; REMOTE *pRCTemp;
pRCTemp = (REMOTE *)calloc(1, sizeof(REMOTE)); pRCTemp = (REMOTE *) calloc(1, sizeof(REMOTE));
if ((REMOTE *)0 == pRCTemp) { if ((REMOTE *) 0 == pRCTemp) {
CSTROUT(2, "out of memory!\n"); OutOfMem();
exit(32);
} }
(void)strcpy(pRCTemp->rhost, pcRem); (void)strcpy(pRCTemp->rhost, pcRem);
(void)strcpy(pRCTemp->rserver, acStart); (void)strcpy(pRCTemp->rserver, acStart);
*ppRC = pRCTemp; *ppRC = pRCTemp;
ppRC = & pRCTemp->pRCnext; ppRC = &pRCTemp->pRCnext;
if (fVerbose) { if (fVerbose) {
Info("%s remote on %s", acStart, pcRem); Info("%s remote on %s", acStart, pcRem);
} }
@ -324,27 +345,32 @@ register FILE *fp;
++iG; ++iG;
} }
if (iG < minG || iG >= MAXGRP) { if (iG < minG || iG >= MAXGRP) {
Error( "%s(%d) group number out of bounds %d <= %d < %d", pcFile, iLine, minG, iG, MAXGRP); Error("%s(%d) group number out of bounds %d <= %d < %d",
exit(1); pcFile, iLine, minG, iG, MAXGRP);
exit(EX_UNAVAILABLE);
} }
minG = iG; minG = iG;
pGE = pGEAll+iG; pGE = pGEAll + iG;
if (0 == pGE->imembers++) { if (0 == pGE->imembers++) {
pGE->pCElist = pCE; pGE->pCElist = pCE;
} }
if (pGE->imembers > MAXMEMB) { if (pGE->imembers > MAXMEMB) {
Error( "%s(%d) group %d has more than %d members -- but we'll give it a spin", pcFile, iLine, iG, MAXMEMB); Error
("%s(%d) group %d has more than %d members -- but we'll give it a spin",
pcFile, iLine, iG, MAXMEMB);
} }
/* fill in the console entry /* fill in the console entry
*/ */
if (sizeof(aConsoles)/sizeof(CONSENT) == iLocal) { if (sizeof(aConsoles) / sizeof(CONSENT) == iLocal) {
Error( "%s(%d) %d is too many consoles for hard coded tables, adjust MAXGRP or MAXMEMB", pcFile, iLine, iLocal); Error
exit(1); ("%s(%d) %d is too many consoles for hard coded tables, adjust MAXGRP or MAXMEMB",
pcFile, iLine, iLocal);
exit(EX_UNAVAILABLE);
} }
(void)strcpy(pCE->server, acStart); (void)strcpy(pCE->server, acStart);
/* /*
* Here we substitute the console name for any '&' character in the * Here we substitute the console name for any '&' character in the
* logfile name. That way you can just have something like * logfile name. That way you can just have something like
* "/var/console/&" for each of the conserver.cf entries. * "/var/console/&" for each of the conserver.cf entries.
@ -358,54 +384,58 @@ register FILE *fp;
pcStart = pcRem + 1; pcStart = pcRem + 1;
} }
(void)strcat(pCE->lfile, pcStart); (void)strcat(pCE->lfile, pcStart);
if ( LogDirectory[0] && (pCE->lfile)[0] != '/' ) { if (LogDirectory[0] && (pCE->lfile)[0] != '/') {
char lfile[MAXLOGLEN]; char lfile[MAXLOGLEN];
strcpy( lfile, pCE->lfile ); strcpy(lfile, pCE->lfile);
strcpy( pCE->lfile, LogDirectory ); strcpy(pCE->lfile, LogDirectory);
strcat( pCE->lfile, "/" ); strcat(pCE->lfile, "/");
strcat( pCE->lfile, lfile ); strcat(pCE->lfile, lfile);
} }
if ( pcMark ) { if (pcMark) {
(void)parseMark(pcFile, iLine, pcMark, tyme, pCE); (void)parseMark(pcFile, iLine, pcMark, tyme, pCE);
} else { } else {
(void)parseMark(pcFile, iLine, defMark, tyme, pCE); (void)parseMark(pcFile, iLine, defMark, tyme, pCE);
} }
if (pcLine[0] == '!') if (pcLine[0] == '!') {
{ pcLine = pruneSpace(pcLine + 1);
pCE->isNetworkConsole = 1; pCE->isNetworkConsole = 1;
strcpy(pCE->networkConsoleHost, pcLine + 1); pCE->telnetState = 0;
strcpy(pCE->networkConsoleHost, pcLine);
pCE->networkConsolePort = atoi(pcMode); pCE->networkConsolePort = atoi(pcMode);
if (fVerbose) { if (fVerbose) {
Info("%s is network on %s/%d logged to %s", Info("%s is network on %s/%d logged to %s", acStart,
acStart, pCE->networkConsoleHost, pCE->networkConsoleHost, pCE->networkConsolePort,
pCE->networkConsolePort, pCE->lfile); pCE->lfile);
} }
pCE->fvirtual = 0; pCE->fvirtual = 0;
sprintf( pCE->dfile, "%s/%d", pCE->networkConsoleHost, pCE->networkConsolePort ); sprintf(pCE->dfile, "%s/%d", pCE->networkConsoleHost,
pCE->networkConsolePort);
pCE->pbaud = FindBaud("Netwk"); pCE->pbaud = FindBaud("Netwk");
pCE->pparity = FindParity(" "); pCE->pparity = FindParity(" ");
} } else if ('|' == pcLine[0]) {
else if ('|' == pcLine[0]) { pcLine = pruneSpace(pcLine + 1);
pCE->isNetworkConsole = 0; pCE->isNetworkConsole = 0;
pCE->telnetState = 0;
pCE->fvirtual = 1; pCE->fvirtual = 1;
if ((char *)0 == (pCE->pccmd = malloc((strlen(pcLine)|7)+1))) { if ((char *)0 ==
(pCE->pccmd = malloc((strlen(pcLine) | 7) + 1))) {
OutOfMem(); OutOfMem();
} }
(void)strcpy(pCE->pccmd, pcLine+1); (void)strcpy(pCE->pccmd, pcLine);
(void)strcpy(pCE->dfile, "/dev/null"); (void)strcpy(pCE->dfile, "/dev/null");
(void)strcpy(pCE->acslave, "/dev/null"); (void)strcpy(pCE->acslave, "/dev/null");
} else { } else {
pCE->isNetworkConsole = 0; pCE->isNetworkConsole = 0;
pCE->telnetState = 0;
pCE->fvirtual = 0; pCE->fvirtual = 0;
(void)strcpy(pCE->dfile, pcLine); (void)strcpy(pCE->dfile, pcLine);
} }
pCE->ipid = -1; pCE->ipid = -1;
if (!pCE->isNetworkConsole) if (!pCE->isNetworkConsole) {
{
/* find user baud and parity /* find user baud and parity
* default to first table entry for baud and parity * default to first table entry for baud and parity
*/ */
@ -413,27 +443,30 @@ register FILE *fp;
pCE->pparity = FindParity(pcMode); pCE->pparity = FindParity(pcMode);
if (fVerbose) { if (fVerbose) {
if (pCE->fvirtual) if (pCE->fvirtual)
Info("%s with command `%s' logged to %s", acStart, pCE->pccmd, pCE->lfile); Info("%s with command `%s' logged to %s", acStart,
pCE->pccmd, pCE->lfile);
else else
Info("%s is on %s (%s%c) logged to %s", acStart, pCE->dfile, pCE->pbaud->acrate, pCE->pparity->ckey, pCE->lfile); Info("%s is on %s (%s%c) logged to %s", acStart,
pCE->dfile, pCE->pbaud->acrate,
pCE->pparity->ckey, pCE->lfile);
} }
} }
++pCE, ++iLocal; ++pCE, ++iLocal;
} }
*ppRC = (REMOTE *)0; *ppRC = (REMOTE *) 0;
/* make a vector of access restructions /* make a vector of access restructions
*/ */
iG = iAccess = 0; iG = iAccess = 0;
pACList = (ACCESS *)0; pACList = (ACCESS *) 0;
while (fgets(acIn, sizeof(acIn)-1, fp) != NULL) { while (fgets(acIn, sizeof(acIn) - 1, fp) != NULL) {
register char *pcMach, *pcNext, *pcMem; char *pcMach, *pcNext, *pcMem;
auto char cType; char cType;
auto int iLen; int iLen;
++iLine; ++iLine;
acStart = pruneSpace( acIn ); acStart = pruneSpace(acIn);
if ('#' == acStart[0] || '\000' == acStart[0]) { if ('#' == acStart[0] || '\000' == acStart[0]) {
continue; continue;
@ -442,8 +475,8 @@ register FILE *fp;
break; break;
} }
if ((char *)0 == (pcNext = strchr(acStart, ':'))) { if ((char *)0 == (pcNext = strchr(acStart, ':'))) {
Error( "%s(%d) missing colon?", pcFile, iLine); Error("%s(%d) missing colon?", pcFile, iLine);
exit(3); exit(EX_UNAVAILABLE);
} }
do { do {
@ -464,26 +497,105 @@ register FILE *fp;
cType = 't'; cType = 't';
break; break;
default: default:
Error( "%s(%d) unknown access key `%s\'", pcFile, iLine, acStart); Error("%s(%d) unknown access key `%s\'", pcFile, iLine,
exit(3); acStart);
exit(EX_UNAVAILABLE);
} }
while ('\000' != *(pcMach = pcNext)) { while ('\000' != *(pcMach = pcNext)) {
while ('\000' != *pcNext && !isspace((int)(*pcNext))) { int j, isCIDR = 0;
while ('\000' != *pcNext &&
!(isspace((int)(*pcNext)) || ',' == *pcNext)) {
++pcNext; ++pcNext;
} }
while ('\000' != *pcNext && isspace((int)(*pcNext))) { while ('\000' != *pcNext &&
(isspace((int)(*pcNext)) || ',' == *pcNext)) {
*pcNext++ = '\000'; *pcNext++ = '\000';
} }
/* Scan for [0-9./], and stop if you find something else */
for (j = 0; pcMach[j] != '\000'; j++) {
if (!isdigit((int)(pcMach[j])) && pcMach[j] != '/' &&
pcMach[j] != '.') {
break;
}
}
/* Did we see just [0-9./]? If so, CIDR notation */
if (pcMach[j] == '\000') {
/* Do a little checking on the input */
int nCount = 0, sCount = 0, dCount = 0;
char *sPtr = (char *)0, *nPtr = (char *)0;
char cidr[BUFSIZ];
(void)strcpy(cidr, pcMach);
/* Scan for [0-9./], and stop if you find something else */
for (j = 0; cidr[j] != '\000'; j++) {
if (isdigit((int)(cidr[j]))) {
if (nPtr == (char *)0) {
nCount++;
nPtr = cidr + j;
}
} else if (cidr[j] == '/') {
sCount++;
sPtr = cidr + j;
} else if (cidr[j] == '.') {
int num;
dCount++;
if (nPtr == (char *)0) {
Error
("%s(%d) bad access list specification `%s': missing numeral before `.'",
pcFile, iLine, pcMach);
break;
}
cidr[j] = '\000';
num = atoi(nPtr);
if (num < 0 || num > 255) {
Error
("%s(%d) bad access list specification `%s': invalid IP octet `%s'",
pcFile, iLine, pcMach, nPtr);
break;
}
nPtr = (char *)0;
}
}
/* If we got through the whole string, then...
* Gotta check against pcMach 'cause we stompped on stuff in cidr above, so can't
* judge what happened correctly with it.
*/
if (pcMach[j] == '\000') {
if (dCount != 3 || sCount > 1) {
Error
("%s(%d) bad access list specification `%s': must be in a.b.c.d[/n] form",
pcFile, iLine, pcMach);
continue;
}
if (sCount == 1) {
int mask;
mask = atoi(sPtr + 1);
if (mask < 0 || mask > 32) {
Error
("%s(%d) bad access list specification `%s': netmask not from 0 to 32",
pcFile, iLine, pcMach);
continue;
}
}
isCIDR = 1;
} else {
continue;
}
}
if (iAccess < iG) { if (iAccess < iG) {
/* still have room */; /* still have room */ ;
} else if (0 != iG) { } else if (0 != iG) {
iG += 8; iG += 8;
pACList = (ACCESS *)realloc((char *)pACList, iG * sizeof(ACCESS)); pACList =
(ACCESS *) realloc((char *)pACList,
iG * sizeof(ACCESS));
} else { } else {
iG = MAXGRP; iG = MAXGRP;
pACList = (ACCESS *)malloc(iG * sizeof(ACCESS)); pACList = (ACCESS *) malloc(iG * sizeof(ACCESS));
} }
if ((ACCESS *)0 == pACList) { if ((ACCESS *) 0 == pACList) {
OutOfMem(); OutOfMem();
} }
/* use loopback interface for local connections /* use loopback interface for local connections
@ -492,12 +604,13 @@ register FILE *fp;
} }
*/ */
iLen = strlen(pcMach); iLen = strlen(pcMach);
if ((char *)0 == (pcMem = malloc(iLen+1))) { if ((char *)0 == (pcMem = malloc(iLen + 1))) {
OutOfMem(); OutOfMem();
} }
pACList[iAccess].ctrust = cType; pACList[iAccess].ctrust = cType;
pACList[iAccess].ilen = iLen; pACList[iAccess].ilen = iLen;
pACList[iAccess].pcwho = strcpy(pcMem, pcMach); pACList[iAccess].pcwho = strcpy(pcMem, pcMach);
pACList[iAccess].isCIDR = isCIDR;
++iAccess; ++iAccess;
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* $Id: readcfg.h,v 5.10 2001-02-21 17:26:06-08 bryan Exp $ * $Id: readcfg.h,v 5.12 2001-07-06 17:11:47-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -38,14 +38,10 @@
* from a file, into these structures * from a file, into these structures
*/ */
extern GRPENT extern GRPENT aGroups[MAXGRP]; /* group info */
aGroups[MAXGRP]; /* group info */ extern CONSENT aConsoles[MAXGRP * MAXMEMB]; /* console list */
extern CONSENT extern REMOTE *pRCList; /* list of remote consoles we know about */
aConsoles[MAXGRP*MAXMEMB]; /* console list */ extern ACCESS *pACList; /* `who do you love' (or trust) */
extern REMOTE
*pRCList; /* list of remote consoles we know about */
extern ACCESS
*pACList; /* `who do you love' (or trust) */
extern int extern int
iAccess; /* how many access restrictions we have */ iAccess; /* how many access restrictions we have */

484
conserver/util.c Normal file
View File

@ -0,0 +1,484 @@
/*
* $Id: util.c,v 1.19 2001-07-26 00:50:17-07 bryan Exp $
*
* Copyright conserver.com, 2000-2001
*
* Maintainer/Enhancer: Bryan Stansell (bryan@conserver.com)
*/
#include <stdio.h>
#include <varargs.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <config.h>
#include <sys/socket.h>
#include <compat.h>
#include <port.h>
#include <util.h>
int outputPid = 0;
char *progname = "conserver package";
int thepid = 0;
int fDebug = 0;
/* in the routines below (the init code) we can bomb if malloc fails (ksb)
*/
void
OutOfMem()
{
static char acNoMem[] = ": out of memory\n";
write(2, progname, strlen(progname));
write(2, acNoMem, sizeof(acNoMem) - 1);
exit(EX_UNAVAILABLE);
}
char *
buildString(str)
const char *str;
{
static char *msg = (char *)0;
static size_t cursize = 0;
static size_t msgsize = 0;
int len;
if ((char *)0 == str) {
if ((char *)0 != msg) {
free(msg);
msg = (char *)0;
msgsize = cursize = 0;
}
return msg;
}
len = strlen(str);
if (cursize + len >= msgsize) {
if (0 == msgsize) {
msgsize = (len / 1024 + 1) * 1024 * sizeof(char);
msg = (char *)calloc(1, msgsize);
} else {
msgsize += (len / 1024 + 1) * 1024 * sizeof(char);
msg = (char *)realloc(msg, msgsize);
}
if ((char *)0 == msg)
OutOfMem();
}
strcat(msg, str);
cursize += len;
return msg;
}
void
FmtCtlStr(pcIn, pcOut)
char *pcIn;
char *pcOut;
{
unsigned char c;
for (; *pcIn != '\000'; pcIn++) {
c = *pcIn & 0xff;
if (c > 127) {
c -= 128;
*pcOut++ = 'M';
*pcOut++ = '-';
}
if (c < ' ' || c == '\177') {
*pcOut++ = '^';
*pcOut++ = c ^ 0100;
} else {
*pcOut++ = c;
}
}
*pcOut = '\000';
}
void
Debug(fmt, va_alist)
char *fmt;
va_dcl
{
va_list ap;
va_start(ap);
if (!fDebug)
return;
if (outputPid)
fprintf(stderr, "%s (%d): DEBUG: ", progname, thepid);
else
fprintf(stderr, "%s: DEBUG: ", progname);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}
void
Error(fmt, va_alist)
char *fmt;
va_dcl
{
va_list ap;
va_start(ap);
if (outputPid)
fprintf(stderr, "%s (%d): ", progname, thepid);
else
fprintf(stderr, "%s: ", progname);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}
void
Info(fmt, va_alist)
char *fmt;
va_dcl
{
va_list ap;
va_start(ap);
if (outputPid)
fprintf(stdout, "%s (%d): ", progname, thepid);
else
fprintf(stdout, "%s: ", progname);
vfprintf(stdout, fmt, ap);
fprintf(stdout, "\n");
va_end(ap);
}
void
simpleSignal(sig, disp)
int sig;
RETSIGTYPE(*disp) (int);
{
#if HAVE_SIGACTION
struct sigaction sa;
sa.sa_handler = disp;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(sig, &sa, NULL);
#else
(void)signal(sig, disp);
#endif
}
int
maxfiles()
{
int mf;
#ifdef HAVE_SYSCONF
mf = sysconf(_SC_OPEN_MAX);
#else
# ifdef HAVE_GETRLIMIT
struct rlimit rl;
(void)getrlimit(RLIMIT_NOFILE, &rl);
mf = rl.rlim_cur;
# else
# ifdef HAVE_GETDTABLESIZE
mf = getdtablesize();
# else
# ifndef OPEN_MAX
# define OPEN_MAX 64
# endif /* !OPEN_MAX */
mf = OPEN_MAX;
# endif /* HAVE_GETDTABLESIZE */
# endif /* HAVE_GETRLIMIT */
#endif /* HAVE_SYSCONF */
Debug("maxfiles=%d", mf);
return mf;
}
/* Routines for the generic I/O stuff for conserver. This will handle
* all open(), close(), read(), and write() calls.
*/
/* This encapsulates a regular file descriptor in a CONSFILE
* object. Returns a CONSFILE pointer to that object.
*/
CONSFILE *
fileOpenFD(fd, type)
int fd;
enum consFileType type;
{
CONSFILE *cfp;
cfp = (CONSFILE *) calloc(1, sizeof(CONSFILE));
if ((CONSFILE *) 0 == cfp)
OutOfMem();
cfp->ftype = type;
cfp->fd = fd;
Debug("File I/O: Encapsulated fd %d type %d", fd, type);
return cfp;
}
/* This is to "unencapsulate" the file descriptor */
int
fileUnopen(cfp)
CONSFILE *cfp;
{
int retval;
switch (cfp->ftype) {
case simpleFile:
retval = cfp->fd;
break;
case simpleSocket:
retval = cfp->fd;
break;
#ifdef TLS_SUPPORT
case TLSSocket:
retval = cfp->sslfd;
break;
#endif
}
Debug("File I/O: Unopened fd %d", cfp->fd);
free(cfp);
return retval;
}
/* This opens a file like open(2). Returns a CONSFILE pointer
* or a (CONSFILE *)0 on error
*/
CONSFILE *
fileOpen(path, flag, mode)
const char *path;
int flag;
int mode;
{
CONSFILE *cfp;
int fd;
if (-1 == (fd = open(path, flag, mode))) {
Debug("File I/O: Failed to open `%s'", path);
return (CONSFILE *) 0;
}
cfp = (CONSFILE *) calloc(1, sizeof(CONSFILE));
if ((CONSFILE *) 0 == cfp)
OutOfMem();
cfp->ftype = simpleFile;
cfp->fd = fd;
Debug("File I/O: Opened `%s' as fd %d", path, fd);
return cfp;
}
/* Unless otherwise stated, returns the same values as close(2).
* The CONSFILE object passed in *CANNOT* be used once calling
* this function - even if there was an error.
*/
int
fileClose(cfp)
CONSFILE *cfp;
{
int retval;
#if defined(__CYGWIN__)
int client_sock_flags;
struct linger lingeropt;
#endif
switch (cfp->ftype) {
case simpleFile:
retval = close(cfp->fd);
break;
case simpleSocket:
#if defined(__CYGWIN__)
/* flush out the client socket - set it to blocking,
* then write to it
*/
client_sock_flags = fcntl(cfp->fd, F_GETFL, 0);
if (client_sock_flags != -1)
/* enable blocking */
fcntl(cfp->fd, F_SETFL, client_sock_flags & ~O_NONBLOCK);
/* sent it a byte - guaranteed to block - ensure delivery
* of prior data yeah - this is a bit paranoid - try
* without this at first
*/
/* write(cfp->fd, "\n", 1); */
/* this is the guts of the workaround for Winsock close bug */
shutdown(cfp->fd, 1);
/* enable lingering */
lingeropt.l_onoff = 1;
lingeropt.l_linger = 15;
setsockopt(cfp->fd, SOL_SOCKET, SO_LINGER, &lingeropt,
sizeof(lingeropt));
#endif
retval = close(cfp->fd);
break;
#ifdef TLS_SUPPORT
case TLSSocket:
retval = SSL_close(cfp->sslfd);
break;
#endif
}
Debug("File I/O: Closed fd %d", cfp->fd);
free(cfp);
return retval;
}
/* Unless otherwise stated, returns the same values as read(2) */
int
fileRead(cfp, buf, len)
CONSFILE *cfp;
void *buf;
int len;
{
int retval;
switch (cfp->ftype) {
case simpleFile:
retval = read(cfp->fd, buf, len);
break;
case simpleSocket:
retval = read(cfp->fd, buf, len);
break;
#ifdef TLS_SUPPORT
case TLSSocket:
retval = SSL_read(cfp->sslfd, buf, len);
break;
#endif
}
Debug("File I/O: Read %d bytes from fd %d", retval, cfp->fd);
return retval;
}
/* Unless otherwise stated, returns the same values as write(2) */
int
fileWrite(cfp, buf, len)
CONSFILE *cfp;
const char *buf;
int len;
{
int retval;
if (len < 0)
len = strlen(buf);
switch (cfp->ftype) {
case simpleFile:
retval = write(cfp->fd, buf, len);
break;
case simpleSocket:
retval = write(cfp->fd, buf, len);
break;
#ifdef TLS_SUPPORT
case TLSSocket:
retval = SSL_write(cfp->sslfd, buf, len);
break;
#endif
}
Debug("File I/O: Wrote %d bytes to fd %d", retval, cfp->fd);
return retval;
}
/* Unless otherwise stated, returns the same values as fstat(2) */
int
fileStat(cfp, buf)
CONSFILE *cfp;
struct stat *buf;
{
int retval;
switch (cfp->ftype) {
case simpleFile:
retval = fstat(cfp->fd, buf);
break;
case simpleSocket:
retval = fstat(cfp->fd, buf);
break;
#ifdef TLS_SUPPORT
case TLSSocket:
retval = -1;
break;
#endif
}
return retval;
}
/* Unless otherwise stated, returns the same values as lseek(2) */
int
fileSeek(cfp, offset, whence)
CONSFILE *cfp;
off_t offset;
int whence;
{
int retval;
switch (cfp->ftype) {
case simpleFile:
retval = lseek(cfp->fd, offset, whence);
break;
case simpleSocket:
retval = lseek(cfp->fd, offset, whence);
break;
#ifdef TLS_SUPPORT
case TLSSocket:
retval = -1;
break;
#endif
}
return retval;
}
/* Unless otherwise stated, returns the same values as lseek(2) */
int
fileFDNum(cfp)
CONSFILE *cfp;
{
int retval;
switch (cfp->ftype) {
case simpleFile:
retval = cfp->fd;
break;
case simpleSocket:
retval = cfp->fd;
break;
#ifdef TLS_SUPPORT
case TLSSocket:
retval = -1;
break;
#endif
}
return retval;
}
/* Unless otherwise stated, returns the same values as send(2) */
int
fileSend(cfp, msg, len, flags)
CONSFILE *cfp;
const void *msg;
size_t len;
int flags;
{
int retval;
switch (cfp->ftype) {
case simpleFile:
retval = send(cfp->fd, msg, len, flags);
break;
case simpleSocket:
retval = send(cfp->fd, msg, len, flags);
break;
#ifdef TLS_SUPPORT
case TLSSocket:
retval = -1;
break;
#endif
}
return retval;
}

54
conserver/util.h Normal file
View File

@ -0,0 +1,54 @@
/*
* $Id: util.h,v 1.8 2001-07-22 12:54:59-07 bryan Exp $
*
* Copyright conserver.com, 2000-2001
*
* Maintainer/Enhancer: Bryan Stansell (bryan@conserver.com)
*/
/* Struct to wrap information about a "file"...
* This can be a socket, local file, whatever. We do this so
* we can add encryption to sockets (and generalize I/O).
*/
enum consFileType {
simpleFile,
simpleSocket,
#ifdef TLS_SUPPORT
TLSSocket,
#endif
};
typedef struct consFile {
/* Standard socket type stuff */
enum consFileType ftype;
int fd;
#ifdef TLS_SUPPORT
/* TLS/SSL stuff */
SSL_CTX *ctx;
SSL *sslfd;
BIO *sbio;
int ctx_connections;
#endif
/* Add crypto stuff to suit */
} CONSFILE;
extern void Debug();
extern void Error();
extern void Info();
extern int outputPid, fDebug;
extern char *progname;
extern int thepid;
extern void simpleSignal();
extern int maxfiles();
extern void FmtCtlStr();
extern CONSFILE *fileOpenFD();
extern CONSFILE *fileOpen();
extern int fileClose();
extern int fileRead();
extern int fileWrite();
extern int fileStat();
extern int fileSeek();
extern int fileSend();
extern int fileFDNum();
extern void OutOfMem();
extern char *buildString();

View File

@ -1,5 +1,5 @@
/* /*
* $Id: version.h,v 1.25 2001-07-05 08:08:49-07 bryan Exp $ * $Id: version.h,v 1.26 2001-07-26 11:53:55-07 bryan Exp $
* *
* Copyright conserver.com, 2000-2001 * Copyright conserver.com, 2000-2001
* *
@ -14,4 +14,4 @@
@(#) Copyright 2000 conserver.com.\n\ @(#) Copyright 2000 conserver.com.\n\
All rights reserved.\n" All rights reserved.\n"
#define THIS_VERSION "conserver.com version 7.0.3" #define THIS_VERSION "conserver.com version 7.1.0"

View File

@ -25,20 +25,18 @@ LIBS = @LIBS@
### Makefile rules - no user-servicable parts below ### Makefile rules - no user-servicable parts below
CONSOLE_OBJS = console.o ../conserver/output.o CONSOLE_OBJS = console.o ../conserver/util.o
CONSOLE_HDRS = ../config.h $(top_srcdir)/compat.h $(top_srcdir)/conserver/port.h CONSOLE_HDRS = ../config.h $(top_srcdir)/compat.h $(top_srcdir)/conserver/port.h
ALL = console ALL = console
all: $(ALL) all: $(ALL)
.PHONY: clean distclean install
console: $(CONSOLE_OBJS) console: $(CONSOLE_OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o console $(CONSOLE_OBJS) $(LIBS) $(CC) $(CFLAGS) $(LDFLAGS) -o console $(CONSOLE_OBJS) $(LIBS)
../conserver/output.o: ../conserver/util.o:
( cd ../conserver && $(MAKE) $(MAKE_FLAGS) output.o ) || exit 1; ( cd ../conserver && $(MAKE) $(MAKE_FLAGS) util.o ) || exit 1;
.c.o: .c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
@ -55,3 +53,4 @@ install: console
$(MKDIR) $(DESTDIR)$(mandir)/man1 $(MKDIR) $(DESTDIR)$(mandir)/man1
$(INSTALL) console.man $(DESTDIR)$(mandir)/man1/console.1 $(INSTALL) console.man $(DESTDIR)$(mandir)/man1/console.1
.PHONY: clean distclean install

File diff suppressed because it is too large Load Diff

View File

@ -1,194 +1,279 @@
.\" $Id: console.man,v 1.6 2001-07-05 01:39:15-07 bryan Exp $ .\" $Id: console.man,v 1.11 2001-07-26 10:25:24-07 bryan Exp $
.TH CONSOLE 8 "Local" .TH CONSOLE 1 "Local"
.SH NAME .SH NAME
console \- console server client program console \- console server client program
.SH SYNOPSIS .SH SYNOPSIS
\fBconsole\fP [\-\fBaAfFsS\fP] [\-\fBrv\fP] [\-\fBe\fP \fIesc\fP] [\-\fBM\fP \fImach\fP] \fIconsole\fP \fBconsole\fP [\fB\-aAfFGsS\fP] [\fB\-7Dv\fP] [\fB\-M\fP \fImach\fP]
[\fB\-p\fP \fIport\fP] [\fB\-e\fP \fIesc\fP] [\fB\-l\fP \fIuser\fP]
\fIconsole\fP
.br .br
\fBconsole\fP [\-\fBv\fP] [\-\fBhdDPuVwx\fP] [\-\fBb\fP \fImessage\fP] \fBconsole\fP [\fB\-hPrRuVwx\fP] [\fB\-7Dv\fP] [\fB\-M\fP \fImach\fP]
[\fB\-p\fP \fIport\fP] [\fB\-b\fP \fImessage\fP]
.br .br
\fBconsole\fP [\-\fBqQ\fP] [\-\fBM\fP \fImach\fP] \fBconsole\fP [\fB\-qQ\fP] [\fB\-7Dv\fP] [\fB\-M\fP \fImach\fP]
[\fB\-p\fP \fIport\fP]
.SH DESCRIPTION .SH DESCRIPTION
.B Console .B Console
is used to manipulate console terminals remotely or poll running is used to manipulate console terminals remotely or to poll running
\fIconserver\fP(8) daemons for status information. \fBconserver\fP(8) daemons for status information.
.PP
In the first form above,
.B console
asks the user's password before
granting interactive access to a console (on a non-trusted system),
since such a session may provide single-user access.
Only as much of the console name as is required to
identify it uniquely to the server is required.
.PP
For non-interactive options,
.B console
outputs only the requested information and exits.
.PP .PP
.B Console .B Console
queries the user for the their passwd before knows only of a primary
granting interactive access to a console (on a non-trusted system) .B conserver
since such a session may provide single-user access. host
.PP (see the \fB\-M\fP option below),
In the non-interactive mode to which it initially connects.
In a multi-server environment, the primary server may refer
the client to a different server handling the requested console,
or it will provide a list of all servers if required
(as when
.B console .B console
outputs only the requested information. is invoked with the
.RB ` \-r '
option).
.B Console
then opens connections to the appropriate server(s).
It is not necessary for the user of
.B console
to know which server manages which consoles,
as long as
.B console
knows a valid primary server
and all available consoles are listed in the primary server's
configuration file.
.SH OPTIONS .SH OPTIONS
.PP
Options may be given as separate arguments (e.g., \fB\-v -w\fP)
or clustered (e.g., \fB\-vw\fP).
Options and their arguments may be separated by optional white space.
Option arguments containing spaces or other characters special to the shell
must be quoted.
.TP
.B \-7
Strip the high bit off of all data received,
whether from user input or from the server,
before any processing occurs.
Disallows escape sequence characters with the high bit set.
.TP .TP
.B \-a .B \-a
Access a console with a two-way connection (this is the default). Access a console with a two-way (read-write) connection (this is the default).
The connection is dropped to spy mode if someone else is attached read-write.
.TP .TP
.BI \-b message .BI \-b message
Broadcast a \fImessage\fP to all users connected to the console server. Broadcast a \fImessage\fP to all users connected to the console server.
.TP .TP
.B \-d
Display daemon versions. The \fIconsole\fP client connects to each
server to request its version information. The uppercase varient of
this option only requests the primary server's version.
.TP
.B \-D .B \-D
Same as \fB\-d\fP but just acts on the local server. Enable debugging output.
.TP .TP
.BI \-e esc .BI \-e esc
Set the initial two character escape sequence to Set the initial two-character escape sequence to
those represented by \fIesc\fP. those represented by \fIesc\fP.
Any of the forms output by \fIcat\fP(1)'s \-\fBv\fP option Any of the forms output by \fBcat\fP(1)'s \-\fBv\fP option
are accepted. The default value is ``^Ec''. are accepted. The default value is ``\fB^Ec\fP''.
.TP .TP
.B \-f .B \-f
Same as \fB\-a\fP except it will force any existing connection into spy mode. Same as \fB\-a\fP except it will force any existing connection into spy mode.
.TP .TP
.B \-G
Request a raw connection to the group control virtual console;
this is only useful for learning the protocol used by the
interactive sequence.
.TP
.B \-h .B \-h
Display a brief help message. Display a brief help message.
.TP .TP
.BI \-l user .BI \-l user
Sets the username used for authentication to \fIuser\fP. Set the login name used for authentication to \fIuser\fP.
By default, \fBconsole\fP uses $USER if its uid matches the user's real uid,
or $LOGNAME if its uid matches the user's real uid,
or else the name associated with the user's real uid.
.TP .TP
.BI \-M mach .BI \-M mach
The \fIconsole\fP client program polls \fImach\fP as the primary server, The \fBconsole\fP client program polls \fImach\fP as the primary server,
rather than the hard coded default (``console''). rather than the default set at compile time (typically ``\fBconsole\fP'').
The default \fImach\fP may be changed at compile time using the
\fB--with-master\fP option.
.TP .TP
.BI \-p port .BI \-p port
Set the port to connect to. The default \fIport\fP is set at compile time Set the port to connect to. This may be either a port number
using the --with-port option. or a service name. The default \fIport\fP may be changed at compile time
using the \fB--with-port\fP option.
.TP .TP
.B \-P .B \-P
Display the pids of the master daemon processes. Display the pid of the master daemon process on each server.
.TP .TP
.B \-q .B \-q
The \fIconsole\fP client requests the server daemon quit (shutdown). The \fBconsole\fP client requests that the server daemon quit (shut down).
A password is sent in the protocol stream, if none is required for A password is sent in the protocol stream; if none is required for
the local host to shutdown the server just press return. the local host to shut down the server, just press <return>.
.TP .TP
.B \-Q .B \-Q
Same as \fB\-q\fP but just acts on the local server. Same as \fB\-q\fP but just acts on the primary server.
.TP .TP
.B \-r .B \-r
Request a raw connection to the group control virtual console, Display daemon versions. The \fBconsole\fP client connects to each
this is only useful for learning the protocol used by the server to request its version information.
interactive sequence. .TP
.B \-R
Same as \fB\-r\fP but just acts on the primary server.
.TP .TP
.B \-s .B \-s
Requests a read-only (spy mode) connection. Request a read-only (spy mode) connection.
If this mode all the escape sequences (below) work, or report errors, In this mode all the escape sequences (below) work, or report errors,
but all other keyboard input is discarded. but all other keyboard input is discarded.
.TP .TP
.B \-u .B \-u
Show a list of all consoles with status and attached users. Show a list of all consoles with status (`up' or `down')
.TP and attached users (\fIuser\fP@\fIhost\fP if attached read-write,
.B \-U `<spies>' if only users in spy mode, or `<none>').
Same as \fB\-u\fP.
.TP
.B \-V
Output the version of the console client program.
.TP .TP
.B \-v .B \-v
Be more verbose during when building the connection(s). Be more verbose when building the connection(s).
Use this option in combination with any of `show' options (below) Use this option in combination with any of `show' options (below)
for added benefit. for added benefit.
.TP .TP
.B \-w .B \-V
Show a list of all connections to consoles. Output the version and settings of the console client program
and then exit.
.TP .TP
.B \-W .B \-w
Same as \fB\-w\fP. Show a list of all who are currently connected to consoles,
including the hostnames where the \fBconsole\fP connections originate
and the idle times. This is useful to see if anybody is actively
using the console system if it becomes necessary to shut down
\fBconserver\fP.
.TP .TP
.B \-x .B \-x
Show a list of consoles and devices. Show a list of consoles and devices.
.PP .PP
The \fB\-A\fP, \fB\-F\fP, or \fB\-S\fP options have the same effect as The \fB\-A\fP, \fB\-F\fP, or \fB\-S\fP options have the same effect as
their lower case variants. their lower-case variants.
In addition they each request the last 20 lines of the console output after In addition, they each request the last 20 lines of the console output after
making the connection. making the connection (as if `\fB^Ecr\fP' were typed).
.PP
Any default (\fB\-a\fP) connection is dropped to spy mode if
someone else is attached read-write.
.SH "ESCAPE SEQUENCES" .SH "ESCAPE SEQUENCES"
The connection can be controlled by a two character escape sequence, followed The connection can be controlled by a two-character escape sequence, followed
by a command. The default escape sequence is ``control-E c'' by a command. The default escape sequence is ``control-E c''
(octal 005 143). Commands are: (octal 005 143).
.sp (The escape sequences are actually processed by the server; see the
.TS .BR conserver (8)
c l. man page for more information.)
a switch to attach mode Commands are:
c toggle flow control (don't do this)
d down the current console
e change the escape sequence to the next two characters
f force a switch to attach mode
g group info
L toggle logging on/off
l1 send a 3-second serial line break (might halt a Sun)
("ell" then "one", not the L1 key)
o reopen the line to clear errors (silo overflows)
p replay the last 60 lines of output
r replay the last 20 lines of output
s switch to spy mode
u show other users on this port
v show the version of the group server
w who is using this console
x examine this group's devices and modes.
z suspend this connection
? display list of commands
^M continue, ignore the escape sequence
^R replay the last line only
\. disconnect
.TE
.sp .sp
.PD 0
.IP a
attach read-write if nobody already is
.IP c
toggle flow control (don't do this)
.IP d
down the current console
.IP e\fIcc\fP
change the escape sequence to the next two characters
.IP f
forcibly attach read-write
.IP g
group info
.IP L
toggle logging on/off
.IP l1
send a 3-second serial line break (might halt a Sun)
("ell" then "one", not the L1 key)
.IP o
close (if open) and reopen the line (to clear errors (silo overflows))
and the log file
.IP p
replay the last 60 lines of output
.IP r
replay the last 20 lines of output
.IP s
switch to spy mode (read-only)
.IP u
show status of hosts/users in this group
.IP v
show the version of the group server
.IP w
who is using this console
.IP x
examine this group's devices and modes
.IP z
suspend this connection
.IP ?
display list of commands
.IP "^M (return)"
continue, ignore the escape sequence
.IP "^R (ctrl-R)"
replay the last line only
.IP \\\fIooo\fP
send character having octal code \fIooo\fP
(must specify three octal digits)
.IP \.
disconnect
.PD
.PP .PP
If any other character is hit after the escape sequence, all three characters If any other character is hit after the escape sequence, all three characters
will be discarded. will be discarded.
Note that a line break or a down command Note that a line break or a down command
can only be sent from a full two-way attachment. can only be sent from a full two-way attachment.
To send the escape sequence through the connection one must redefine To send the escape sequence through the connection one must redefine
the outer escape sequence. the outer escape sequence, or use \fB^Ec\\\fP\fIooo\fP to send the
first escape character before typing the second character directly.
.PP .PP
In the \-u output, the login \fB<none>\fP indicates no one is In the \fB\-u\fP output, the login ``<none>'' indicates no one is
viewing that console, the login \fB<spies>\fP indicates that viewing that console, and the login ``<spies>'' indicates that
no one has a full two-way attachment. When no one is attached to no one has a full two-way attachment. When no one is attached to
a console its output is cloned to the stdout of the server process. a console its output is cloned to the stdout of the server process
if \fBconserver\fP was started with the \fB\-u\fP option.
.SH EXAMPLES .SH EXAMPLES
.TP .TP
console \-u console \-u
Outputs something like: Outputs something like:
.sp .sp
.RS .RS
.TS .ta 18n 24n
l18 l l.
dumb up <none> dumb up <none>
.br
expert up ksb@mentor expert up ksb@mentor
.br
tyro up <spies> tyro up <spies>
.br
mentor up <none> mentor up <none>
.br
sage up fine@cis sage up fine@cis
.TE .DT
.RE .RE
.sp .IP
The \fB<none>\fP indicates no one is viewing \fIdumb\fP or \fImentor\fP, The \fB<none>\fP indicates no one is viewing \fIdumb\fP or \fImentor\fP,
the \fB<spies>\fP indicates only read-only connections exist for \fItyro\fP, the \fB<spies>\fP indicates only read-only connections exist for \fItyro\fP,
other \fIlogin\fP@\fIhost\fP entries are the currently attached and
other \fIlogin\fP@\fIhost\fP entries indicate users attached read-write to
\fIsage\fP and \fIexpert\fP. \fIsage\fP and \fIexpert\fP.
.TP .TP
console \-w console \-w
Outputs something like: Outputs something like:
.sp .sp
.RS .RS
.TS .ta 18n 26n 32n
l18 l l.
ksb@extra attach 2days expert ksb@extra attach 2days expert
.br
file@cis attach 21:46 sage file@cis attach 21:46 sage
dmr@alice spy 0:04 tyro .br
.TE dmr@alice spy \00:04 tyro
.DT
.RE .RE
.sp .IP
The third column is the idle time of the user. Either hours:minutes or number The third column is the idle time of the user.
of days is displayed. Either \fIhours\fP:\fIminutes\fP or number of days is displayed.
.TP .TP
console \-e \*(lq^[1\*(rq lv426 console \-e \*(lq^[1\*(rq lv426
Requests a connection to the host ``lv426'' with the escape characters Requests a connection to the host ``lv426'' with the escape characters
@ -198,15 +283,17 @@ Connections suspended under Dynix sometimes break the kernel when
resumed. resumed.
.PP .PP
It is possible to create a loop of console connections, with ugly results. It is possible to create a loop of console connections, with ugly results.
Never run \fIconsole\fP from within a console connection (unless you set each Never run \fBconsole\fP from within a console connection (unless you set each
escape sequence differently). escape sequence differently).
.PP .PP
The \fB\-r\fP option doesn't help to explain how connections get built. The \fB\-G\fP option doesn't help to explain how connections get built.
.SH AUTHORS .SH AUTHORS
Thomas A. Fine, Ohio State Computer Science. Thomas A. Fine, Ohio State Computer Science
.br .br
Kevin Braunsdorf, Purdue University Computing Center Kevin Braunsdorf, Purdue University Computing Center
.br .br
Bryan Stansell, conserver.com Bryan Stansell, conserver.com
.SH "SEE ALSO" .SH "SEE ALSO"
conserver.cf(5), conserver(8) .BR conserver.cf (5),
.BR conserver.passwd (5),
.BR conserver (8)

View File

@ -24,7 +24,7 @@
case "$1" in case "$1" in
start) start)
echo -n "Starting conserver: " echo -n "Starting conserver: "
daemon conserver -d -n daemon conserver -d
echo echo
touch /var/lock/subsys/conserver touch /var/lock/subsys/conserver
;; ;;

View File

@ -4,7 +4,7 @@
# #
%define pkg conserver %define pkg conserver
%define ver 7.0.3 %define ver 7.1.0
# define the name of the machine on which the main conserver # define the name of the machine on which the main conserver
# daemon will be running if you don't want to use the default # daemon will be running if you don't want to use the default

View File

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