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
=======
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):
- "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>
@ -8,9 +59,10 @@ version 7.0.3 (Jul 5, 2001):
- 'attached', 'detached', and 'bumped' actions now written to
console logs that have 'a' in timestamp-spec field
- 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
- 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
connect to and listen on (--with-port still sets the default)
- Added logfile output when going into daemon mode
@ -154,5 +206,5 @@ before version 6.05:
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 $
#

45
INSTALL
View File

@ -1,15 +1,41 @@
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
- Download conserver (http://www.conserver.com/) and unpack
- Download conserver (http://www.conserver.com/) and unpack
- Run './configure'
- Run './configure'
- If all is well, run 'make install'
- If all is well, run 'make install'
- Now set up config files, etc. (see below)
- Now set up config files, etc. (see below)
Detailed Instructions
@ -19,13 +45,14 @@ Detailed Instructions
unique options:
--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-cffile=CFFILE Specify config filename [conserver.cf]
--with-pwdfile=PWDFILE Specify password filename [conserver.passwd]
--with-cffile=CFFILE Specify config filename [conserver.cf]
--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-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]
--disable-8bit Disable 8bit data path
--with-timeout=TIMEOUT Specify connect() timeout in seconds [10]
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!
#
# $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
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
- non-dynamic memory allocation
- no IPC for coordinated updates
@ -49,14 +59,10 @@ Bryan Stansell
- "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
- 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>
@ -66,10 +72,6 @@ Bryan Stansell
- 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>
- 9600baud log replay?
@ -87,5 +89,5 @@ Bryan Stansell
- 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
/*
* Base socket used for secondary channel
*/
#undef DEFBASEPORT
/*
* Hostname of console server
*/
@ -33,11 +38,6 @@
*/
#undef MAXGRP
/*
* Clear parity (high-bit) [true/false setting]
*/
#undef CPARITY
/*
* TCP connection timeout
*/

View File

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

View File

@ -1,27 +1,6 @@
#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
# include <string.h>
# include <stdlib.h>
@ -84,20 +63,40 @@ typedef long fd_set;
# include <sys/ttold.h>
#endif
/* which type does wait(2) take for status location
*/
#if HAVE_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
#ifdef HAVE_SIGACTION
extern void Set_signal(int isg, RETSIGTYPE (*disp)(int));
#if HAVE_SYS_WAIT_H
# 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
# define Set_signal(sig, disp) (void)signal((sig), (disp))
#define EX_OK 0
#define EX_UNAVAILABLE 69
#define EX_TEMPFAIL 75
#endif
#include <errno.h>
@ -215,6 +214,6 @@ extern char *h_errlist[];
#ifndef ONOCR
#define ONOCR 0
#endif
#ifndef ONLRET
#define ONLRET 0
#ifndef ONLRET
#define ONLRET 0
#endif

View File

@ -1,38 +1,14 @@
/* 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
*/
#undef DEFPORT
/*
* Base socket used for secondary channel
*/
#undef DEFBASEPORT
/*
* Hostname of console server
*/
@ -63,11 +39,6 @@
*/
#undef MAXGRP
/*
* Clear parity (high-bit) [true/false setting]
*/
#undef CPARITY
/*
* TCP connection timeout
*/
@ -78,165 +49,219 @@
*/
#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
/* Define if you have the <getopt.h> header file. */
/* 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. */
#undef HAVE_GETOPT_H
/* Define if you have the <sgtty.h> header file. */
#undef HAVE_SGTTY_H
/* Define if you have the `getpassphrase' function. */
#undef HAVE_GETPASSPHRASE
/* Define if you have the <shadow.h> header file. */
#undef HAVE_SHADOW_H
/* Define if you have the `getrlimit' function. */
#undef HAVE_GETRLIMIT
/* Define if you have the <stropts.h> header file. */
#undef HAVE_STROPTS_H
/* Define if you have the `getsid' function. */
#undef HAVE_GETSID
/* Define if you have the <sys/audit.h> header file. */
#undef HAVE_SYS_AUDIT_H
/* Define if you have the `getspnam' function. */
#undef HAVE_GETSPNAM
/* Define if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define if you have the `getuserattr' function. */
#undef HAVE_GETUSERATTR
/* Define if you have the <sys/ioctl_compat.h> header file. */
#undef HAVE_SYS_IOCTL_COMPAT_H
/* Define if you have the `getutent' function. */
#undef HAVE_GETUTENT
/* Define if you have the <sys/proc.h> header file. */
#undef HAVE_SYS_PROC_H
/* Define if you have the `grantpt' function. */
#undef HAVE_GRANTPT
/* Define if you have the <sys/resource.h> header file. */
#undef HAVE_SYS_RESOURCE_H
/* Define if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define if you have the <sys/ttold.h> header file. */
#undef HAVE_SYS_TTOLD_H
/* Define if you have the <sys/uio.h> header file. */
#undef HAVE_SYS_UIO_H
/* Define if you have the <sys/vlimit.h> header file. */
#undef HAVE_SYS_VLIMIT_H
/* Define if you have the <termio.h> header file. */
#undef HAVE_TERMIO_H
/* Define if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H
/* Define if you have the <ttyent.h> header file. */
#undef HAVE_TTYENT_H
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define if you have the <usersec.h> header file. */
#undef HAVE_USERSEC_H
/* Define if you have the crypt library (-lcrypt). */
/* Define if you have the `crypt' library (-lcrypt). */
#undef HAVE_LIBCRYPT
/* Define if you have the nsl library (-lnsl). */
/* Define if you have the `nsl' library (-lnsl). */
#undef HAVE_LIBNSL
/* Define if you have the socket library (-lsocket). */
/* 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. */
#undef HAVE_SGTTY_H
/* Define if you have the <shadow.h> header file. */
#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. */
#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. */
#undef HAVE_SYS_AUDIT_H
/* Define if you have the <sys/ioctl_compat.h> header file. */
#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. */
#undef HAVE_SYS_PROC_H
/* Define if you have the <sys/resource.h> header file. */
#undef HAVE_SYS_RESOURCE_H
/* Define if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define if you have the <sys/ttold.h> header file. */
#undef HAVE_SYS_TTOLD_H
/* Define if you have the <sys/uio.h> header file. */
#undef HAVE_SYS_UIO_H
/* Define if you have the <sys/vlimit.h> header file. */
#undef HAVE_SYS_VLIMIT_H
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
#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. */
#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. */
#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. */
#undef HAVE_UNISTD_H
/* Define if you have the `unlockpt' function. */
#undef HAVE_UNLOCKPT
/* Define if you have the <usersec.h> header file. */
#undef HAVE_USERSEC_H
/* 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
/* 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 */
#undef sig_atomic_t
/* Define if <sys/socket.h> does not define socklen_t */
#undef socklen_t

4700
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@ AC_SUBST(MKDIR)
dnl ### Custom settings. ############################################
AC_MSG_CHECKING(for port number specification)
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
AC_DEFINE_UNQUOTED(DEFPORT, "$withval")
AC_MSG_RESULT(port '$withval')
@ -25,9 +25,22 @@ AC_ARG_WITH(port,
[AC_DEFINE_UNQUOTED(DEFPORT, "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_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
AC_DEFINE_UNQUOTED(MASTERHOST, "$withval")
AC_MSG_RESULT('$withval')
@ -40,7 +53,7 @@ AC_ARG_WITH(master,
AC_MSG_CHECKING(for configuration filename)
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
AC_DEFINE_UNQUOTED(CONFIGFILE, "$withval")
AC_MSG_RESULT('$withval')
@ -53,7 +66,7 @@ AC_ARG_WITH(cffile,
AC_MSG_CHECKING(for password filename)
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
AC_DEFINE_UNQUOTED(PASSWDFILE, "$withval")
AC_MSG_RESULT('$withval')
@ -66,7 +79,7 @@ AC_ARG_WITH(pwdfile,
AC_MSG_CHECKING(for log filename)
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
AC_DEFINE_UNQUOTED(LOGFILEPATH, "$withval")
AC_MSG_RESULT('$withval')
@ -79,7 +92,7 @@ AC_ARG_WITH(logfile,
AC_MSG_CHECKING(for PID filename)
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
AC_DEFINE_UNQUOTED(PIDFILE, "$withval")
AC_MSG_RESULT('$withval')
@ -92,7 +105,7 @@ AC_ARG_WITH(pidfile,
AC_MSG_CHECKING(for MAXMEMB setting)
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
AC_DEFINE_UNQUOTED(MAXMEMB, $withval)
AC_MSG_RESULT($withval)
@ -105,7 +118,7 @@ AC_ARG_WITH(maxmemb,
AC_MSG_CHECKING(for MAXGRP setting)
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
AC_DEFINE_UNQUOTED(MAXGRP, $withval)
AC_MSG_RESULT($withval)
@ -116,22 +129,9 @@ AC_ARG_WITH(maxgrp,
[AC_DEFINE_UNQUOTED(MAXGRP, 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_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
AC_DEFINE_UNQUOTED(CONNECTTIMEOUT, $withval)
AC_MSG_RESULT($withval)
@ -172,7 +172,7 @@ if test "$ac_cv_header_termios_h" != "yes"; then
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_SYS_WAIT
AC_TYPE_MODE_T
@ -218,7 +218,7 @@ AC_CHECK_LIB(crypt,crypt)
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

View File

@ -14,8 +14,6 @@ MKDIR = @MKDIR@
all:
.PHONY: clean distclean install
clean:
rm -f *~ *.o $(ALL) core
@ -23,6 +21,8 @@ distclean: clean
rm -f Makefile
install:
$(MKDIR) $(DESTDIR)$(mandir)/man8
$(INSTALL) conserver.cf.man $(DESTDIR)$(mandir)/man8/conserver.cf.8
$(MKDIR) $(DESTDIR)$(mandir)/man5
$(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
.TH CONSERVER.CF 4 "Local"
.TH CONSERVER.CF 5 "Local"
.SH NAME
conserver.cf \- table of server console terminals used by conserver(8)
conserver.cf \- console configuration file for conserver(8)
.SH SYNOPSIS
.br
LOGDIR=\fIlogdirectory\fP
.BI \s-1LOGDIR\s0= logdirectory
.br
TIMESTAMP=\fItimestamp-spec\fP
.BI \s-1TIMESTAMP\s0= timestamp-spec
.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
\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
\fIserver\fP:|\fIcommand\fP[@\fIconserver\fP]::\fIlogfile\fP:\fItimestamp-spec\fP
\fIname\fP:|\fIcommand\fP[@\fIconserver\fP]::\fIlogfile\fP:\fItimestamp-spec\fP
.br
\fB%%\fP
.br
@ -21,128 +21,155 @@ TIMESTAMP=\fItimestamp-spec\fP
.SH DESCRIPTION
.B Conserver.cf
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.
Blank lines are ignored.
.PP
The first section of the file has lines that are separated into
six colon-separated fields:
.PP
\fIserver\fP name - this doesn't have to be the name of the server;
it is used to refer to the server when using the console program.
.PP
\fIdevice\fP file name - the full path name of the device for this server.
five colon-separated fields. Leading and trailing white space in each
field is ignored.
.TP
.I name
the unique name by which this connection is referred to
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.
Speed may be given as an integer,
parity only requires the first letter of any of: even, odd, mark, space.
For no parity, use the character `p'.
.PP
!\fIhost\fP - the hostname of the server to connect to.
.TP
.BI ! termserver
the hostname of the terminal server to connect to.
A socket connection will be made to port \fIport\fP (an integer).
.TP
.BI | command
the command to invoke on the console server.
.PP
|\fIcommand\fP - the command to invoke on the console server.
.PP
\fIdevice\fP, !\fIhost\fP, and |\fIcommand\fP may contain a remote
console server name (ex. \fIhost\fP@\fIconserver\fP) in which case
the conserver will send connections for this server to \fIconserver\fP.
.PP
\fIlogfile\fP - the full path name of file where all output from
this server is logged. Any occurance of `&' will be replaced with
the \fIserver\fP name. Any path that doesn't begin with a `/' will
have \fIlogdirectory\fP (value of LOGDIR) prepended to it.
.PP
\fItimestamp-spec\fP - specifies the time between
timestamps applied to the console log file and activity logging.
\fIdevice\fP, !\fItermserver\fP, and |\fIcommand\fP may be followed by
a remote console server name in the form ``\fB@\fP\fIconserver\fP'',
in which case the conserver daemon will send connections for \fIname\fP
to the conserver running on the host named \fIconserver\fP.
When the ``\fB@\fP\fIconserver\fP'' notation is used,
\fBconserver\fP recognizes consoles it should manage locally
by comparing the IP address of \fIconserver\fP
against the IP address of the name returned by gethostname().
Thus, it will recognize host aliases, but not names that map to
different IP addresses that may exist on the same host,
so care must be used in specifying the hostname.
Since \fBconserver\fP does recognize its own hostname,
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
[\fImark-interval\fP(\fIm\fP|\fIh\fP|\fId\fP|\fIl\fP)][\fIa\fP].
The timestamps look like `[-- MARK -- Mon Jan 25 14:46:56 PST 1999]'. The `m',
`h', and `d' tags specify `minutes', `hours', and `days'. The `l' tag
[\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 `\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
`[Mon Jan 25 14:46:56 PST 1999]' to
be placed every \fImark-interval\fP lines (a newline character signifies
a new line). So, `5h' specifies every 5 hours and `2l' specifies every
two lines. An `a' can be specified to add activity logs to the
logfile: `attached', `detached', and `bumped' messages.
.PP
A default \fItimestamp-spec\fP can be specified by using the TIMESTAMP=
syntax. All consoles below the TIMESTAMP= line will have use that
\fItimestamp-spec\fP unless overridden. To turn off marks for a specific
a new line). So, `5h' specifies every five hours and `2l' specifies every
two lines.
An `\fBa\fP' can be specified to add logs of
`attached', `detached', and `bumped' actions,
including the user's name and the host from which the
\fBconsole\fP connection was made,
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.
.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
The next section of the file contains a list of hosts and addresses
which are allowed to connect to the console server. Three levels
of access all allowed, ``trust'', ``allow'',
and ``refuse''.
The access modifier is followed by a colon and a list of addresses or
host names.
Any complete suffix of a host name my be used to allow access for all hosts
which are allowed to connect to the console server.
.B Conserver
looks for the first match in the config file
for a client's IP address (or network),
or hostname (or domain) if it is able to do a reverse lookup on the IP address,
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.
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'.
For IP addresses, optional netmasks may be specified. For example `192.168.1.0'
will allow the class C space of 192.168.1.0. `192.168.1.0/25' will only allow
For IP addresses, optional netmask lengths may be specified
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).
.SH EXAMPLE
# server:path:baud:/usr/adm/logfile:mark
.br
# name:path:baud:/usr/adm/logfile:mark
.nf
LOGDIR=/tmp
.br
#
.br
# This logs to /tmp/treelog...
.br
tree:/dev/ttyj0:9600e:&log:
.br
#
.br
# This logs to /tmp/fishlog...
.br
fish:/dev/ttyj1:4800e:fishlog:
.br
#
.br
# Now we're defaulting to /var/tmp for logfiles...
.br
LOGDIR=/var/tmp
.br
#
.br
# So, this is /var/tmp/birdlog
.br
bird:/dev/ttyj2:4800m:&log:
.br
#
.br
# And this is /var/tmp/solarlog...
.br
solar:|telnet solar::solarlog:
.br
#
.br
# Now things are all in /var/consoles/<console name>
.br
LOGDIR=/var/consoles
.br
shell:|::&:
.br
#
.br
# This opens a connection to port 2003 of ts1...
.br
# These open connections to ports 2003 and 2004 of ts1...
tribe:!ts1:2003:&:
.br
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:&:
.br
%%
.br
#
# 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
.br
refuse: badhost.cc.purdue.edu
allow: cc.purdue.edu stat.cc.purdue.edu
.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.
</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>
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
@ -139,18 +186,6 @@ original authors and I couldn't come up with a good replacement for the
GNAC name - sad, but true.
</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>
<P>
@ -159,6 +194,24 @@ Check the
file for instructions.
</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>
<P>

View File

@ -26,18 +26,16 @@ LIBS = @LIBS@
### Makefile rules - no user-servicable parts below
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 \
$(srcdir)/client.h $(srcdir)/consent.h $(srcdir)/group.h \
$(srcdir)/main.h $(srcdir)/master.h $(srcdir)/readcfg.h \
$(srcdir)/output.h
$(srcdir)/util.h
ALL = conserver
all: $(ALL)
.PHONY: clean distclean install
conserver: $(CONSERVER_OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o conserver $(CONSERVER_OBJS) $(LIBS)
@ -57,3 +55,5 @@ install: conserver
$(INSTALL) conserver.man $(DESTDIR)$(mandir)/man8/conserver.8
$(MKDIR) $(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
*
@ -51,30 +51,18 @@
#include <pwd.h>
#include <compat.h>
#include <port.h>
#include <util.h>
#include <access.h>
#include <consent.h>
#include <client.h>
#include <group.h>
#include <readcfg.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
* passed as a character string representing an address in the Internet
* standard `.' notation, optionally followed by a slash and an integer
@ -89,8 +77,8 @@ OutOfMem()
*/
int
AddrCmp(addr, pattern)
struct in_addr *addr;
char *pattern;
struct in_addr *addr;
char *pattern;
{
unsigned long int hostaddr, pattern_addr, netmask;
char buf[200], *p, *slash_posn;
@ -98,21 +86,20 @@ char *pattern;
slash_posn = strchr(pattern, '/');
if (slash_posn != NULL) {
if (strlen(pattern) >= sizeof(buf))
return 1; /* too long to handle */
return 1; /* too long to handle */
strncpy(buf, pattern, sizeof(buf));
buf[slash_posn-pattern] = '\0'; /* isolate the address */
buf[slash_posn - pattern] = '\0'; /* isolate the address */
p = buf;
}
else
} else
p = pattern;
pattern_addr = inet_addr(p);
if (pattern_addr == -1)
return 1; /* malformed address */
return 1; /* malformed address */
if (slash_posn) {
/* 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)
netmask = 0x80000000 | (netmask >> 1);
} else {
@ -125,107 +112,112 @@ char *pattern;
else if (IN_CLASSC(ia))
netmask = IN_CLASSC_NET;
else
return 1; /* unsupported address class */
return 1; /* unsupported address class */
}
netmask = htonl(netmask);
if (~netmask & pattern_addr)
netmask = 0xffffffff; /* compare entire addresses */
hostaddr = *(unsigned long int*)addr;
netmask = 0xffffffff; /* compare entire addresses */
hostaddr = *(unsigned long int *)addr;
Debug( "Access check: host=%lx(%lx/%lx)", hostaddr & netmask, hostaddr, netmask );
Debug( "Access check: acl=%lx(%lx/%lx)", pattern_addr & netmask, pattern_addr, netmask );
Debug("Access check: host=%lx(%lx/%lx)", hostaddr & netmask,
hostaddr, netmask);
Debug("Access check: acl=%lx(%lx/%lx)", pattern_addr & netmask,
pattern_addr, netmask);
return (hostaddr & netmask) != (pattern_addr & netmask);
}
/* return the access type for a given host entry (ksb)
*/
char
AccType(addr,hname)
struct in_addr *addr;
char *hname;
AccType(addr, hname)
struct in_addr *addr;
char *hname;
{
register int i;
register char *pcName;
register int len;
int i;
char *pcName;
int len;
if ( fDebug ) {
if (hname)
Debug( "Access check: hostname=%s, ip=%s", hname, inet_ntoa(*addr) );
else
Debug( "Access check: hostname=<unresolvable>, ip=%s", inet_ntoa(*addr) );
if (fDebug) {
if (hname)
Debug("Access check: hostname=%s, ip=%s", hname,
inet_ntoa(*addr));
else
Debug("Access check: hostname=<unresolvable>, ip=%s",
inet_ntoa(*addr));
}
for (i = 0; i < iAccess; ++i) {
Debug("Access check: who=%s, trust=%c", pACList[i].pcwho,
pACList[i].ctrust);
if (pACList[i].isCIDR != 0) {
if (0 == AddrCmp(addr, pACList[i].pcwho)) {
return pACList[i].ctrust;
}
continue;
}
for (i = 0; i < iAccess; ++i) {
Debug( "Access check: who=%s, trust=%c", pACList[i].pcwho, pACList[i].ctrust );
if (isdigit((int)(pACList[i].pcwho[0]))) {
if (0 == AddrCmp(addr, pACList[i].pcwho)) {
return pACList[i].ctrust;
}
continue;
if (hname && hname[0] != '\000') {
pcName = hname;
len = strlen(pcName);
while (len >= pACList[i].ilen) {
Debug("Access check: name=%s", pcName);
if (0 == strcmp(pcName, pACList[i].pcwho)) {
return pACList[i].ctrust;
}
if (hname && hname[0] != '\000') {
pcName = hname;
len = strlen(pcName);
while (len >= pACList[i].ilen) {
Debug( "Access check: name=%s", pcName );
if (0 == strcmp(pcName, pACList[i].pcwho)) {
return pACList[i].ctrust;
}
pcName = strchr(pcName, '.');
if ((char *)0 == pcName) {
break;
}
++pcName;
len = strlen(pcName);
}
pcName = strchr(pcName, '.');
if ((char *)0 == pcName) {
break;
}
++pcName;
len = strlen(pcName);
}
}
return chDefAcc;
}
return chDefAcc;
}
/* we know iAccess == 0, we want to setup a nice default access list (ksb)
*/
void
SetDefAccess(hpLocal)
struct hostent *hpLocal;
struct hostent *hpLocal;
{
register char *pcWho, *pcDomain;
register int iLen;
char *addr;
struct in_addr *aptr;
char *pcWho, *pcDomain;
int iLen;
char *addr;
struct in_addr *aptr;
aptr = (struct in_addr *)(hpLocal->h_addr);
addr = inet_ntoa(*aptr);
pACList = (ACCESS *)calloc(3, sizeof(ACCESS));
if ((ACCESS *)0 == pACList) {
OutOfMem();
}
if ((char *)0 == (pcWho = malloc(strlen(addr)+1))) {
OutOfMem();
}
strcpy(pcWho, addr);
pACList[iAccess].ctrust = 'a';
pACList[iAccess].ilen = strlen(pcWho);
pACList[iAccess].pcwho = pcWho;
aptr = (struct in_addr *)(hpLocal->h_addr);
addr = inet_ntoa(*aptr);
pACList = (ACCESS *) calloc(3, sizeof(ACCESS));
if ((ACCESS *) 0 == pACList) {
OutOfMem();
}
if ((char *)0 == (pcWho = malloc(strlen(addr) + 1))) {
OutOfMem();
}
strcpy(pcWho, addr);
pACList[iAccess].ctrust = 'a';
pACList[iAccess].ilen = strlen(pcWho);
pACList[iAccess].pcwho = pcWho;
Debug( "Access list prime: trust=%c, who=%s", pACList[iAccess].ctrust,
pACList[iAccess].pcwho );
Debug("Access list prime: trust=%c, who=%s", pACList[iAccess].ctrust,
pACList[iAccess].pcwho);
iAccess++;
iAccess++;
if ((char *)0 == (pcDomain = strchr(hpLocal->h_name, '.'))) {
return;
}
++pcDomain;
iLen = strlen(pcDomain);
pcWho = malloc(iLen+1);
pACList[iAccess].ctrust = 'a';
pACList[iAccess].ilen = iLen;
pACList[iAccess].pcwho = strcpy(pcWho, pcDomain);
if ((char *)0 == (pcDomain = strchr(hpLocal->h_name, '.'))) {
return;
}
++pcDomain;
iLen = strlen(pcDomain);
pcWho = malloc(iLen + 1);
pACList[iAccess].ctrust = 'a';
pACList[iAccess].ilen = iLen;
pACList[iAccess].pcwho = strcpy(pcWho, pcDomain);
Debug( "Access list prime: trust=%c, who=%s", pACList[iAccess].ctrust,
pACList[iAccess].pcwho );
Debug("Access list prime: trust=%c, who=%s", pACList[iAccess].ctrust,
pACList[iAccess].pcwho);
iAccess++;
iAccess++;
}
/* thread ther list of uniq console server machines, aliases for (ksb)
@ -233,27 +225,26 @@ struct hostent *hpLocal;
*/
REMOTE *
FindUniq(pRCAll)
register REMOTE *pRCAll;
REMOTE *pRCAll;
{
register REMOTE *pRC;
REMOTE *pRC;
/* INV: tail of the list we are building always contains only
* uniq hosts, or the empty list.
*/
if ((REMOTE *)0 == pRCAll) {
return (REMOTE *)0;
/* INV: tail of the list we are building always contains only
* uniq hosts, or the empty list.
*/
if ((REMOTE *) 0 == pRCAll) {
return (REMOTE *) 0;
}
pRCAll->pRCuniq = FindUniq(pRCAll->pRCnext);
/* if it is in the returned list of uniq hosts, return that list
* else add us by returning our node
*/
for (pRC = pRCAll->pRCuniq; (REMOTE *) 0 != pRC; pRC = pRC->pRCuniq) {
if (0 == strcmp(pRC->rhost, pRCAll->rhost)) {
return pRCAll->pRCuniq;
}
pRCAll->pRCuniq = FindUniq(pRCAll->pRCnext);
/* if it is in the returned list of uniq hosts, return that list
* else add us by returning our node
*/
for (pRC = pRCAll->pRCuniq; (REMOTE *)0 != pRC; pRC = pRC->pRCuniq) {
if (0 == strcmp(pRC->rhost, pRCAll->rhost)) {
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
*
@ -38,19 +38,19 @@
*/
typedef struct access {
char ctrust; /* how much do we trust the host */
int ilen; /* length (strlen) of pcwho */
char *pcwho; /* what is the hosts name/ip number */
char ctrust; /* how much do we trust the host */
int ilen; /* length (strlen) of pcwho */
char *pcwho; /* what is the hosts name/ip number */
int isCIDR; /* is this a CIDR addr (or hostname?) */
} ACCESS;
typedef struct remote { /* console at another host */
struct remote *pRCnext; /* next remote console we know about */
struct remote *pRCuniq; /* list of uniq remote servers */
char rserver[32]; /* remote server name */
char rhost[256]; /* remote host to call to get it */
typedef struct remote { /* console at another host */
struct remote *pRCnext; /* next remote console we know about */
struct remote *pRCuniq; /* list of uniq remote servers */
char rserver[32]; /* remote server name */
char rhost[256]; /* remote host to call to get it */
} REMOTE;
extern void OutOfMem();
extern REMOTE *FindUniq();
extern char AccType();
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
*
@ -50,8 +50,9 @@
#include <pwd.h>
#include <compat.h>
#include <port.h>
#include <util.h>
#include <consent.h>
#include <client.h>
#include <group.h>
@ -61,29 +62,29 @@
*/
CONSCLIENT *
FindWrite(pCL)
CONSCLIENT *pCL;
CONSCLIENT *pCL;
{
/* return the first guy to have the `want write' bit set
* (tell him of the promotion, too) we could look for the
* most recent or some such... I guess it doesn't matter that
* much.
*/
for (/*passed in*/; (CONSCLIENT *)0 != pCL; pCL = pCL->pCLnext) {
if (!pCL->fwantwr)
continue;
if (!pCL->pCEto->fup || pCL->pCEto->fronly)
break;
pCL->fwantwr = 0;
pCL->fwr = 1;
if ( pCL->pCEto->nolog ) {
CSTROUT(pCL->fd, "\r\n[attached (nologging)]\r\n");
} else {
CSTROUT(pCL->fd, "\r\n[attached]\r\n");
}
tagLogfile(pCL->pCEto, "%s attached", pCL->acid);
return pCL;
/* return the first guy to have the `want write' bit set
* (tell him of the promotion, too) we could look for the
* most recent or some such... I guess it doesn't matter that
* much.
*/
for ( /*passed in */ ; (CONSCLIENT *) 0 != pCL; pCL = pCL->pCLnext) {
if (!pCL->fwantwr)
continue;
if (!pCL->pCEto->fup || pCL->pCEto->fronly)
break;
pCL->fwantwr = 0;
pCL->fwr = 1;
if (pCL->pCEto->nolog) {
fileWrite(pCL->fd, "\r\n[attached (nologging)]\r\n", -1);
} else {
fileWrite(pCL->fd, "\r\n[attached]\r\n", -1);
}
return (CONSCLIENT *)0;
tagLogfile(pCL->pCEto, "%s attached", pCL->acid);
return pCL;
}
return (CONSCLIENT *) 0;
}
/* show a character as a string so the user cannot mistake it for (ksb)
@ -93,34 +94,34 @@ CONSCLIENT *pCL;
*/
char *
FmtCtl(ci, pcIn)
int ci;
char *pcIn;
int ci;
char *pcIn;
{
register char *pcOut = pcIn;
unsigned char c;
char *pcOut = pcIn;
unsigned char c;
c = ci & 0xff;
if (c > 127) {
c -= 128;
*pcOut++ = 'M';
*pcOut++ = '-';
}
c = ci & 0xff;
if (c > 127) {
c -= 128;
*pcOut++ = 'M';
*pcOut++ = '-';
}
if (c < ' ' || c == '\177') {
*pcOut++ = '^';
*pcOut++ = c ^ 0100;
*pcOut = '\000';
} else if (c == ' ') {
(void)strcpy(pcOut, "<space>");
} else if (c == '^') {
(void)strcpy(pcOut, "<circumflex>");
} else if (c == '\\') {
(void)strcpy(pcOut, "<backslash>");
} else {
*pcOut++ = c;
*pcOut = '\000';
}
return pcIn;
if (c < ' ' || c == '\177') {
*pcOut++ = '^';
*pcOut++ = c ^ 0100;
*pcOut = '\000';
} else if (c == ' ') {
(void)strcpy(pcOut, "<space>");
} else if (c == '^') {
(void)strcpy(pcOut, "<circumflex>");
} else if (c == '\\') {
(void)strcpy(pcOut, "<backslash>");
} else {
*pcOut++ = c;
*pcOut = '\000';
}
return pcIn;
}
/* replay last iBack lines of the log file upon connect to console (ksb)
@ -131,58 +132,60 @@ char *pcIn;
*/
void
Replay(fdLog, fdOut, iBack)
int fdLog, fdOut, iBack;
CONSFILE *fdLog;
CONSFILE *fdOut;
int iBack;
{
register int tot, nCr;
register char *pc;
register off_t where;
auto char bf[MAXREPLAY+2];
auto struct stat stLog;
int tot, nCr;
char *pc;
off_t where;
char bf[MAXREPLAY + 2];
struct stat stLog;
if (-1 == fdLog) {
CSTROUT(fdOut, "[no log file on this console]\r\n");
return;
}
if ((CONSFILE *) 0 == fdLog) {
fileWrite(fdOut, "[no log file on this console]\r\n", -1);
return;
}
/* find the size of the file
*/
if (0 != fstat(fdLog, & stLog)) {
return;
}
/* find the size of the file
*/
if (0 != fileStat(fdLog, &stLog)) {
return;
}
if (MAXREPLAY > stLog.st_size) {
where = 0L;
} else {
where = stLog.st_size - MAXREPLAY;
}
if (MAXREPLAY > stLog.st_size) {
where = 0L;
} else {
where = stLog.st_size - MAXREPLAY;
}
#if defined(SEEK_SET)
/* PTX and maybe other Posix systems
*/
if (lseek(fdLog, where, SEEK_SET) < 0) {
return;
}
/* PTX and maybe other Posix systems
*/
if (fileSeek(fdLog, where, SEEK_SET) < 0) {
return;
}
#else
if (lseek(fdLog, where, L_SET) < 0) {
return;
}
if (fileSeek(fdLog, where, L_SET) < 0) {
return;
}
#endif
if ((tot = read(fdLog, bf, MAXREPLAY)) <= 0) {
return;
}
bf[tot] = '@';
if ((tot = fileRead(fdLog, bf, MAXREPLAY)) <= 0) {
return;
}
bf[tot] = '@';
pc = & bf[tot];
nCr = 0;
while (--pc != bf) {
if ('\n' == *pc && iBack == nCr++) {
++pc; /* get rid of a blank line */
break;
}
pc = &bf[tot];
nCr = 0;
while (--pc != bf) {
if ('\n' == *pc && iBack == nCr++) {
++pc; /* get rid of a blank line */
break;
}
}
(void)write(fdOut, pc, tot-(pc - bf));
(void)fileWrite(fdOut, pc, tot - (pc - bf));
}
@ -191,91 +194,90 @@ int fdLog, fdOut, iBack;
#define WHEN_SPY 0x01
#define WHEN_ATTACH 0x02
#define WHEN_VT100 0x04
#define WHEN_EXPERT 0x08 /* ZZZ no way to set his yet */
#define WHEN_EXPERT 0x08 /* ZZZ no way to set his yet */
#define WHEN_ALWAYS 0x40
#define HALFLINE 40
typedef struct HLnode {
int iwhen;
char actext[HALFLINE];
int iwhen;
char actext[HALFLINE];
} HELP;
static HELP aHLTable[] = {
{ WHEN_ALWAYS, ". disconnect"},
{ WHEN_ALWAYS, "a attach read/write"},
{ WHEN_ATTACH, "c toggle flow control"},
{ WHEN_ATTACH, "d down a console"},
{ WHEN_ALWAYS, "e change escape sequence"},
{ WHEN_ALWAYS, "f force attach read/write"},
{ WHEN_ALWAYS, "g group info"},
{ WHEN_ATTACH, "L toggle logging on/off"},
{ WHEN_ATTACH, "l1 send break (halt host!)"},
{ WHEN_ALWAYS, "o (re)open the tty and log file"},
{ WHEN_ALWAYS, "p replay the last 60 lines"},
{ WHEN_ALWAYS, "r replay the last 20 lines"},
{ WHEN_ATTACH, "s spy read only"},
{ WHEN_ALWAYS, "u show host status"},
{ WHEN_ALWAYS, "v show version info"},
{ WHEN_ALWAYS, "w who is on this console"},
{ WHEN_ALWAYS, "x show console baud info"},
{ WHEN_ALWAYS, "z suspend the connection"},
{ WHEN_ALWAYS, "<cr> ignore/abort command"},
{ WHEN_ALWAYS, "? print this message"},
{ WHEN_ALWAYS, "^R short replay"},
{ WHEN_ATTACH, "\\ooo send character by octal code"},
{ WHEN_EXPERT, "^I toggle tab expansion"},
{ WHEN_EXPERT, "; change to another console"},
{ WHEN_EXPERT, "+(-) do (not) drop line"},
{ WHEN_VT100, "PF1 print this message"},
{ WHEN_VT100, "PF2 disconnect"},
{ WHEN_VT100, "PF3 replay the last 20 lines"},
{ WHEN_VT100, "PF4 spy read only"}
{WHEN_ALWAYS, ". disconnect"},
{WHEN_ALWAYS, "a attach read/write"},
{WHEN_ATTACH, "c toggle flow control"},
{WHEN_ATTACH, "d down a console"},
{WHEN_ALWAYS, "e change escape sequence"},
{WHEN_ALWAYS, "f force attach read/write"},
{WHEN_ALWAYS, "g group info"},
{WHEN_ATTACH, "L toggle logging on/off"},
{WHEN_ATTACH, "l1 send break (halt host!)"},
{WHEN_ALWAYS, "o (re)open the tty and log file"},
{WHEN_ALWAYS, "p replay the last 60 lines"},
{WHEN_ALWAYS, "r replay the last 20 lines"},
{WHEN_ATTACH, "s spy read only"},
{WHEN_ALWAYS, "u show host status"},
{WHEN_ALWAYS, "v show version info"},
{WHEN_ALWAYS, "w who is on this console"},
{WHEN_ALWAYS, "x show console baud info"},
{WHEN_ALWAYS, "z suspend the connection"},
{WHEN_ALWAYS, "<cr> ignore/abort command"},
{WHEN_ALWAYS, "? print this message"},
{WHEN_ALWAYS, "^R short replay"},
{WHEN_ATTACH, "\\ooo send character by octal code"},
{WHEN_EXPERT, "^I toggle tab expansion"},
{WHEN_EXPERT, "; change to another console"},
{WHEN_EXPERT, "+(-) do (not) drop line"},
{WHEN_VT100, "PF1 print this message"},
{WHEN_VT100, "PF2 disconnect"},
{WHEN_VT100, "PF3 replay the last 20 lines"},
{WHEN_VT100, "PF4 spy read only"}
};
/* list the commands we know for the user (ksb)
*/
void
HelpUser(pCL)
CONSCLIENT *pCL;
CONSCLIENT *pCL;
{
register int i, j, iCmp;
static char
acH1[] = "help]\r\n",
acH2[] = "help spy mode]\r\n",
acEoln[] = "\r\n";
auto char acLine[HALFLINE*2+3];
int i, j, iCmp;
static char
acH1[] = "help]\r\n", acH2[] = "help spy mode]\r\n", acEoln[] =
"\r\n";
char acLine[HALFLINE * 2 + 3];
iCmp = WHEN_ALWAYS|WHEN_SPY;
if (pCL->fwr) {
(void)write(pCL->fd, acH1, sizeof(acH1)-1);
iCmp |= WHEN_ATTACH;
} else {
(void)write(pCL->fd, acH2, sizeof(acH2)-1);
}
if ('\033' == pCL->ic[0] && 'O' == pCL->ic[1]) {
iCmp |= WHEN_VT100;
}
iCmp = WHEN_ALWAYS | WHEN_SPY;
if (pCL->fwr) {
(void)fileWrite(pCL->fd, acH1, sizeof(acH1) - 1);
iCmp |= WHEN_ATTACH;
} else {
(void)fileWrite(pCL->fd, acH2, sizeof(acH2) - 1);
}
if ('\033' == pCL->ic[0] && 'O' == pCL->ic[1]) {
iCmp |= WHEN_VT100;
}
acLine[0] = '\000';
for (i = 0; i < sizeof(aHLTable) / sizeof(HELP); ++i) {
if (0 == (aHLTable[i].iwhen & iCmp)) {
continue;
}
if ('\000' == acLine[0]) {
acLine[0] = ' ';
(void)strcpy(acLine + 1, aHLTable[i].actext);
continue;
}
for (j = strlen(acLine); j < HALFLINE + 1; ++j) {
acLine[j] = ' ';
}
(void)strcpy(acLine + j, aHLTable[i].actext);
(void)strcat(acLine + j, acEoln);
(void)fileWrite(pCL->fd, acLine, -1);
acLine[0] = '\000';
for (i = 0; i < sizeof(aHLTable)/sizeof(HELP); ++i) {
if (0 == (aHLTable[i].iwhen & iCmp)) {
continue;
}
if ('\000' == acLine[0]) {
acLine[0] = ' ';
(void)strcpy(acLine+1, aHLTable[i].actext);
continue;
}
for (j = strlen(acLine); j < HALFLINE+1; ++j) {
acLine[j] = ' ';
}
(void)strcpy(acLine+j, aHLTable[i].actext);
(void)strcat(acLine+j, acEoln);
(void)write(pCL->fd, acLine, strlen(acLine));
acLine[0] = '\000';
}
if ('\000' != acLine[0]) {
(void)strcat(acLine, acEoln);
(void)write(pCL->fd, acLine, strlen(acLine));
}
}
if ('\000' != acLine[0]) {
(void)strcat(acLine, acEoln);
(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
*
@ -35,46 +35,46 @@
*/
/* states for a server fsm
*/
#define S_NORMAL 0 /* just pass character */
#define S_ESC1 1 /* first escape character received */
#define S_CMD 2 /* second interrupt character received */
#define S_CATTN 3 /* change 1 escape character to next input char */
#define S_CESC 4 /* change 2 escape character to next input char */
#define S_HALT1 5 /* we have a halt sequence in progress */
#define S_SUSP 6 /* we are suspened, first char wakes us up */
#define S_IDENT 7 /* probational connection (who is this) */
#define S_HOST 8 /* still needs a host name to connect */
#define S_PASSWD 9 /* still needs a passwd to connect */
#define S_QUOTE 10 /* send any character we can spell */
#define S_BCAST 11 /* send a broadcast message to all connections */
#define S_NORMAL 0 /* just pass character */
#define S_ESC1 1 /* first escape character received */
#define S_CMD 2 /* second interrupt character received */
#define S_CATTN 3 /* change 1 escape character to next input char */
#define S_CESC 4 /* change 2 escape character to next input char */
#define S_HALT1 5 /* we have a halt sequence in progress */
#define S_SUSP 6 /* we are suspened, first char wakes us up */
#define S_IDENT 7 /* probational connection (who is this) */
#define S_HOST 8 /* still needs a host name to connect */
#define S_PASSWD 9 /* still needs a passwd to connect */
#define S_QUOTE 10 /* send any character we can spell */
#define S_BCAST 11 /* send a broadcast message to all connections */
typedef struct client { /* Connection Information: */
int fd; /* file descriptor */
short fcon; /* currently connect or not */
short fwr; /* (client) write enable flag */
short fwantwr; /* (client) wants to write */
short fecho; /* echo commands (not set by machines) */
char acid[128]; /* login and location of client */
time_t tym; /* time of connect */
time_t typetym; /* time of last keystroke */
char actym[32]; /* pre-formatted time */
struct consent
*pCEwant, /* what machine we would like to be on */
*pCEto; /* host a client gets output from */
struct client
**ppCLbscan, /* back link for scan ptr */
*pCLscan, /* next client fd to scan after select */
**ppCLbnext, /* back link for next ptr */
*pCLnext; /* next person on this list */
char ic[2]; /* two character escape sequence */
char iState; /* state for fsm in server */
char caccess; /* did we trust the remote machine */
char accmd[MAXSERVLEN+1];/* the command the user issued */
int icursor; /* the length of the command issused */
char msg[1024]; /* the broadcast message */
int mcursor; /* the length of the message */
struct sockaddr_in
cnct_port; /* where from */
typedef struct client { /* Connection Information: */
CONSFILE *fd; /* file descriptor */
short fcon; /* currently connect or not */
short fwr; /* (client) write enable flag */
short fwantwr; /* (client) wants to write */
short fecho; /* echo commands (not set by machines) */
char acid[128]; /* login and location of client */
char peername[128]; /* location of client */
time_t tym; /* time of connect */
time_t typetym; /* time of last keystroke */
char actym[32]; /* pre-formatted time */
struct consent
*pCEwant, /* what machine we would like to be on */
*pCEto; /* host a client gets output from */
struct client
**ppCLbscan, /* back link for scan ptr */
*pCLscan, /* next client fd to scan after select */
**ppCLbnext, /* back link for next ptr */
*pCLnext; /* next person on this list */
char ic[2]; /* two character escape sequence */
char iState; /* state for fsm in server */
char caccess; /* did we trust the remote machine */
char accmd[MAXSERVLEN + 1]; /* the command the user issued */
int icursor; /* the length of the command issused */
char msg[1024]; /* the broadcast message */
struct sockaddr_in
cnct_port; /* where from */
} CONSCLIENT;
extern char *FmtCtl();

File diff suppressed because it is too large Load Diff

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
*
@ -40,55 +40,56 @@
/* stuff to keep track of a console entry
*/
typedef struct baud { /* a baud rate table */
char acrate[8];
int irate;
typedef struct baud { /* a baud rate table */
char acrate[8];
int irate;
} BAUD;
typedef struct parity { /* a parity bits table */
char ckey;
int iset;
int iclr;
typedef struct parity { /* a parity bits table */
char ckey;
int iset;
int iclr;
} PARITY;
#define MAXSERVLEN 32 /* max length of server name */
#define MAXDEVLEN 512 /* max length of /dev/ttyax */
#define MAXLOGLEN 1024 /* max length of /usr/adm/consoles/foo */
#define MAXTTYLINE (133*2) /* max length of a single buf'd line */
#define ALARMTIME 60 /* time between chimes */
#define MAXSERVLEN 32 /* max length of server name */
#define MAXDEVLEN 512 /* max length of /dev/ttyax */
#define MAXLOGLEN 1024 /* max length of /usr/adm/consoles/foo */
#define MAXTTYLINE (133*2) /* max length of a single buf'd line */
#define ALARMTIME 60 /* time between chimes */
typedef struct consent { /* console information */
char server[MAXSERVLEN];/* server name */
char dfile[MAXDEVLEN]; /* device file */
char lfile[MAXLOGLEN]; /* log file */
BAUD *pbaud; /* the baud on this console port */
PARITY *pparity; /* the parity on this line */
int mark; /* Mark (chime) interval */
long nextMark; /* Next mark (chime) time */
typedef struct consent { /* console information */
char server[MAXSERVLEN]; /* server name */
char dfile[MAXDEVLEN]; /* device file */
char lfile[MAXLOGLEN]; /* log file */
BAUD *pbaud; /* the baud on this console port */
PARITY *pparity; /* the parity on this line */
int mark; /* Mark (chime) interval */
long nextMark; /* Next mark (chime) time */
/* Used if network console */
int isNetworkConsole;
char networkConsoleHost[MAXSERVLEN];
int networkConsolePort;
/* Used if network console */
int isNetworkConsole;
char networkConsoleHost[MAXSERVLEN];
int networkConsolePort;
int telnetState;
/* used if virtual console */
char acslave[MAXDEVLEN];/* pseudo-device slave side */
int fvirtual; /* is a pty device we use as a console */
char *pccmd; /* virtual console command */
int ipid; /* pid of virtual command */
/* used if virtual console */
char acslave[MAXDEVLEN]; /* pseudo-device slave side */
int fvirtual; /* is a pty device we use as a console */
char *pccmd; /* virtual console command */
int ipid; /* pid of virtual command */
/* only used in child */
int nolog; /* don't log output */
int fdlog; /* the local log file */
int fdtty; /* the port to talk to machine on */
int activitylog; /* log attach/detach/bump */
short int fup; /* we setup this line? */
short int fronly; /* we can only read this console */
short int iend; /* like icursor in CONSCLIENT */
short int inamelen; /* strlen(server) */
struct client *pCLon; /* clients on this console */
struct client *pCLwr; /* client that is writting on console */
char acline[132*2+2]; /* max chars we will call a line */
/* only used in child */
int nolog; /* don't log output */
CONSFILE *fdlog; /* the local log file */
int fdtty; /* the port to talk to machine on */
int activitylog; /* log attach/detach/bump */
short int fup; /* we setup this line? */
short int fronly; /* we can only read this console */
short int iend; /* like icursor in CONSCLIENT */
short int inamelen; /* strlen(server) */
struct client *pCLon; /* clients on this console */
struct client *pCLwr; /* client that is writting on console */
char acline[132 * 2 + 2]; /* max chars we will call a line */
} CONSENT;
extern PARITY *FindParity();
@ -97,8 +98,8 @@ extern void ConsInit();
extern void ConsDown();
struct hostcache {
char hostname[MAXSERVLEN];
struct hostcache *next;
char hostname[MAXSERVLEN];
struct hostcache *next;
};
extern int CheckHostCache();

View File

@ -1,57 +1,139 @@
.\" @(#)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"
.SH NAME
conserver \- console server daemon
.SH SYNOPSIS
.B conserver [\-\fBdDhinsvV\fP] [\-\fBa\fP \fItype\fP] [\-\fBM\fP \fIaddr\fP]
.B [\-\fBp\fP \fIport\fP] [\-\fBC\fP \fIconfig\fP] [\-\fBP\fP \fIpasswd\fP]
.B [\-\fBL\fP \fIlogfile\fP]
\fBconserver\fP [\fB\-7dDhinuvV\fP] [\fB\-a\fP \fItype\fP]
[\fB\-M\fP \fIaddr\fP] [\fB\-p\fP \fIport\fP] [\fB\-b\fP \fIport\fP]
[\fB\-C\fP \fIconfig\fP] [\fB\-P\fP \fIpasswd\fP]
[\fB\-L\fP \fIlogfile\fP]
.SH DESCRIPTION
.B Conserver
is the daemon for the
.IR console (1)
program.
It provides remote access to the server consoles,
and logs all console data.
Slave hosts which have no current connection might produce important
error messages; these unloved errors are labeled with a machine name
and output on stdout.
is the daemon that manages
remote access to system consoles by multiple users via the
.BR console (1)
client program
and logs all console output.
It can connect to consoles via local serial ports
or terminal servers that allow network access,
or to any external program.
.PP
When started, it forks a child for each group in /etc/conserver.cf and
assigns each process a port number to listen on. The \fIconsole\fP
client program communicates with the master console server to find
the host and port the child is listening on.
When started,
.B conserver
reads its
.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
.B Conserver
completely controls any connection to a controlled host.
All handling of escape sequenes is done by the server,
except the suspend sequence which is
sent as an out-of-band command to the client.
All escape sequences given by the user to \fBconsole\fP
are passed to the server without interpretation.
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
The \fBconserver\fP parent process will automatically respawn any child
process that dies. If the parent process receives a SIGTERM, it will
propagate the signal to its children, shutting everything down. The
parent will also propagate the SIGHUP and SIGUSR1 signals. A SIGHUP
will cause all the console logfiles to be closed and
then reopened (no reread of the configuration file is done). A SIGUSR1
will cause the server to try and connect to any consoles marked as
process that dies. The following signals are propagated by the parent
process to its children.
.TP
SIGTERM
close all connections and exit.
.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)
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
.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
.B \-a
Set the default access type.
.B \-7
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
.BI \-C config
This option points the server at a different configuration file.
The default \fIconfig\fP is set at compile time using the
--with-cffile option.
Read configuration information from the file \fIconfig\fP.
The default \fIconfig\fP may be changed at compile time using the
\fB--with-cffile\fP option.
.TP
.B \-d
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
.B \-D
Enable debugging output, sent to stderr.
@ -60,41 +142,75 @@ Enable debugging output, sent to stderr.
Output a brief help message.
.TP
.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
.BI \-L logfile
This option points the server at a different logfile path. The default
\fIlogfile\fP is set at compile time using the --with-logfile option.
Log errors and informational messages to \fIlogfile\fP
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
.BI \-M addr
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.
.TP
.B \-n
The \fIconserver\fP will \fBnot\fP output unloved console output to
stdout.
Obsolete (now a no-op); see \fB\-u\fP.
.TP
.BI \-p port
Set the port to listen on. The default \fIport\fP is set at compile time
using the --with-port option.
Set the TCP port for the master process to listen on.
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
.BI \-P passwd
This option points the server at a different password file. The default
\fIpasswd\fP is set at compile time using the --with-pwdfile option.
Read the table of authorized user data from the file \fIpasswd\fP.
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
.B \-v
Echo the configuration as it is being read (be verbose).
.TP
.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
.TS
l l.
/etc/conserver.cf description of console terminal lines
/etc/conserver.passwd users allowed to access consoles
\fIstdout\fP unloved console errors
.TE
.PP
The following default file locations may be overridden
at compile time or by the command-line options described above.
Run \fBconserver \-V\fP (with no other options) to see
the defaults set at compile time.
.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
Thomas A. Fine, Ohio State Computer Science
.br
@ -102,4 +218,6 @@ Kevin S Braunsdorf, Purdue University Computing Center
.br
Bryan Stansell, conserver.com
.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
'start')
LF=/var/log/conserver.log
echo "Starting console server daemon"
[ -f $LF ] && mv $LF $LF.old
conserver -n -d > $LF 2>&1
conserver -d
;;
'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
*
@ -24,7 +24,6 @@
#include <sys/socket.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <syslog.h>
#include <signal.h>
#include <netdb.h>
@ -32,191 +31,188 @@
#include <ctype.h>
#include <compat.h>
#include <port.h>
#include <util.h>
#if 0
static char *__pty_host;
static char *__pty_fmt;
/* Allocate some space for the results of getpseudotty */
#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 defined(HAVE_PTSNAME) && defined(HAVE_GRANTPT) && defined(HAVE_UNLOCKPT)
#if defined(linux)
extern char *ptsname();
extern int grantpt();
extern int unlockpt();
#endif
#if ! HAVE_PTSNAME
/*
* 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
* everything that uses pty's. For the most part, we'll be trying to
* 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
static char chartwo[] =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
#endif /* ! HAVE_PTSNAME */
# 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)
*/
static int
getpseudotty(slave, master)
char **master, **slave;
{
int fd;
char *pcName;
if (0 > (fd = open("/dev/ptc", O_RDWR|O_NDELAY, 0))) {
return -1;
}
if ((char *)0 == (pcName = ttyname(fd))) {
return -1;
}
(void)strcpy(acSlave, pcName);
*slave = acSlave;
(void)strcpy(acMaster, pcName);
acMaster[7] = 'c';
*master = acMaster;
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;
char **master, **slave;
{
int fd;
char *pcName;
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;
}
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 (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
if ((char *) 0 == (pcName = ptsname(fd))) {
return -1;
}
grantpt(fd); /* change permission of slave */
(void)strcpy(acSlave, pcName);
*slave = acSlave;
#if HAVE_SIGACTION
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
Error("sigprocmask(SIG_SETMASK): %s", strerror(errno));
#else
simpleSignal(SIGCHLD, FlagReapVirt);
#endif
return fd;
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
* 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
* make /dev/ptyq* the "free" pty's.
*/
# else
/* all the world's a vax ;-) */
static char charone[] = "prstuvwxyzPQRSTUVWq";
static char chartwo[] =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
# if defined(_AIX)
/*
* get a pty for the user (emulate the neato sequent call) (mm)
*/
static int
getpseudotty(slave, master)
char **master, **slave;
{
int fd;
char *pcName;
if (0 > (fd = open("/dev/ptc", O_RDWR | O_NDELAY, 0))) {
return -1;
}
if ((char *)0 == (pcName = ttyname(fd))) {
return -1;
}
(void)strcpy(acSlave, pcName);
*slave = acSlave;
(void)strcpy(acMaster, pcName);
acMaster[7] = 'c';
*master = acMaster;
return fd;
}
# else
/*
* get a pty for the user (emulate the neato sequent call) (ksb)
*/
static int
getpseudotty(slave, master)
char **master, **slave;
char **master, **slave;
{
static char *pcOne = charone, *pcTwo = chartwo;
auto int fd, iLoop, iIndex = sizeof("/dev/pty")-1;
auto char *pcOld1;
auto struct stat statBuf;
static char *pcOne = charone, *pcTwo = chartwo;
int fd, iLoop, iIndex = sizeof("/dev/pty") - 1;
char *pcOld1;
struct stat statBuf;
iLoop = 0;
pcOld1 = pcOne;
for (;;) {
if ('\000' == *++pcTwo) {
pcTwo = chartwo;
if ('\000' == *++pcOne) {
pcOne = charone;
if (pcOld1 == pcOne && ++iLoop > 1 || iLoop > 32)
return -1;
}
}
acMaster[iIndex] = *pcOne;
acMaster[iIndex+1] = *pcTwo;
/*
* Remeber we are root - stat the file
* to see if it exists before we open it
* for read/write - if it doesn't we don't
* have any pty's left in the row
*/
if (-1 == stat(acMaster, &statBuf) || S_IFCHR != (statBuf.st_mode&S_IFMT)) {
pcTwo = "l";
continue;
}
if (0 > (fd = open(acMaster, O_RDWR|O_NDELAY, 0))) {
continue;
}
acSlave[iIndex] = *pcOne;
acSlave[iIndex+1] = *pcTwo;
if (-1 == access(acSlave, F_OK)) {
(void) close(fd);
continue;
}
break;
iLoop = 0;
pcOld1 = pcOne;
for (;;) {
if ('\000' == *++pcTwo) {
pcTwo = chartwo;
if ('\000' == *++pcOne) {
pcOne = charone;
if ((pcOld1 == pcOne && ++iLoop > 1) || (iLoop > 32))
return -1;
}
}
*master = acMaster;
*slave = acSlave;
return fd;
acMaster[iIndex] = *pcOne;
acMaster[iIndex + 1] = *pcTwo;
/*
* Remeber we are root - stat the file
* to see if it exists before we open it
* for read/write - if it doesn't we don't
* have any pty's left in the row
*/
if (-1 == stat(acMaster, &statBuf) ||
S_IFCHR != (statBuf.st_mode & S_IFMT)) {
pcTwo = "l";
continue;
}
if (0 > (fd = open(acMaster, O_RDWR | O_NDELAY, 0))) {
continue;
}
acSlave[iIndex] = *pcOne;
acSlave[iIndex + 1] = *pcTwo;
if (-1 == access(acSlave, F_OK)) {
(void)close(fd);
continue;
}
break;
}
*master = acMaster;
*slave = acSlave;
return fd;
}
# endif /* PTX version */
# endif /* _AIX */
# endif /* !HAVE_GETPSEUDO */
# endif /* _AIX */
#endif
/*
* get a Joe pty bacause the daemon is not with us, sadly. (ksb)
*/
int
FallBack(pcSlave, pcMaster)
char *pcSlave, *pcMaster;
char *pcSlave, *pcMaster;
{
auto int fd;
auto char *pcTSlave, *pcTMaster;
int fd;
char *pcTSlave, *pcTMaster;
if (-1 == (fd = getpseudotty(& pcTSlave, & pcTMaster))) {
return -1;
}
(void) strcpy(pcSlave, pcTSlave);
(void) strcpy(pcMaster, pcTMaster);
return fd;
if (-1 == (fd = getpseudotty(&pcTSlave, &pcTMaster))) {
return -1;
}
(void)strcpy(pcSlave, pcTSlave);
(void)strcpy(pcMaster, pcTMaster);
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
*
@ -34,15 +34,15 @@
* 4. This notice may not be removed or altered.
*/
#define MAXPSWDLEN 16 /* max length of encrypted password */
#define MAXPSWDLEN 16 /* max length of encrypted password */
typedef struct grpent { /* group info */
int port; /* port group listens on */
int pid; /* pid of server for group */
int imembers; /* number of consoles in this group */
CONSENT *pCElist; /* list of consoles in this group */
CONSCLIENT *pCLall; /* all clients to scan after select */
char passwd[MAXPSWDLEN];/* encrypted password for this group */
typedef struct grpent { /* group info */
unsigned short port; /* port group listens on */
int pid; /* pid of server for group */
int imembers; /* number of consoles in this group */
CONSENT *pCElist; /* list of consoles in this group */
CONSCLIENT *pCLall; /* all clients to scan after select */
char passwd[MAXPSWDLEN]; /* encrypted password for this group */
} 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
*
@ -44,8 +44,9 @@
#include <pwd.h>
#include <compat.h>
#include <port.h>
#include <util.h>
#include <consent.h>
#include <client.h>
#include <group.h>
@ -53,27 +54,29 @@
#include <access.h>
#include <readcfg.h>
#include <version.h>
#include <output.h>
int fAll = 1, fVerbose = 0, fSoftcar = 0, fNoinit = 0, fVersion = 0;
int fDaemon = 0;
int fAll = 0, fVerbose = 0, fSoftcar = 0, fNoinit = 0, fVersion =
0, fStrip = 0, fDaemon = 0, fUseLogfile = 0;
char chDefAcc = 'r';
#define FULLCFPATH SYSCONFDIR "/" CONFIGFILE;
#define FULLPDPATH SYSCONFDIR "/" PASSWDFILE;
#define FULLCFPATH SYSCONFDIR "/" CONFIGFILE
#define FULLPDPATH SYSCONFDIR "/" PASSWDFILE
char *pcLogfile = LOGFILEPATH;
char *pcConfig = FULLCFPATH;
char *pcPasswd = FULLPDPATH;
char *pcPort = DEFPORT;
char *pcBasePort = DEFBASEPORT;
int domainHack = 0;
char *pcAddress = NULL;
unsigned long bindAddr;
unsigned int bindPort;
unsigned int bindBasePort;
struct sockaddr_in in_port;
char acMyAddr[4]; /* "\200\76\7\1" */
char acMyHost[256]; /* staff.cc.purdue.edu */
struct in_addr acMyAddr;
char acMyHost[256]; /* staff.cc.purdue.edu */
void
reopenLogfile()
@ -84,10 +87,13 @@ reopenLogfile()
* after that, all bets are off...probably not see the errors (well,
* aside from the tail of the old logfile, if it was rolled).
*/
if (!fUseLogfile)
return;
close(1);
if (1 != open(pcLogfile, O_WRONLY|O_CREAT|O_APPEND, 0644)) {
Error( "open: %s: %s", pcLogfile, strerror(errno));
exit(1);
if (1 != open(pcLogfile, O_WRONLY | O_CREAT | O_APPEND, 0644)) {
Error("open: %s: %s", pcLogfile, strerror(errno));
exit(EX_TEMPFAIL);
}
close(2);
dup(1);
@ -98,99 +104,94 @@ reopenLogfile()
static void
daemonize()
{
int res;
FILE *fp;
int res;
FILE *fp;
#if !HAVE_SETSID
int td;
int td;
#endif
(void) signal(SIGQUIT, SIG_IGN);
(void) signal(SIGINT, SIG_IGN);
simpleSignal(SIGQUIT, SIG_IGN);
simpleSignal(SIGINT, SIG_IGN);
#if defined(SIGTTOU)
(void) signal(SIGTTOU, SIG_IGN);
simpleSignal(SIGTTOU, SIG_IGN);
#endif
#if defined(SIGTSTP)
(void) signal(SIGTSTP, SIG_IGN);
simpleSignal(SIGTSTP, SIG_IGN);
#endif
(void)fflush(stdout);
(void)fflush(stderr);
(void)fflush(stdout);
(void)fflush(stderr);
switch (res = fork()) {
switch (res = fork()) {
case -1:
Error( "fork: %s", strerror(errno));
exit(1);
Error("fork: %s", strerror(errno));
exit(EX_UNAVAILABLE);
case 0:
thepid = getpid();
break;
thepid = getpid();
break;
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();
/* Further disassociate this process from the terminal
* Maybe this will allow you to start a daemon from rsh,
* i.e. with no controlling terminal.
*/
/* Further disassociate this process from the terminal
* Maybe this will allow you to start a daemon from rsh,
* i.e. with no controlling terminal.
*/
#if HAVE_SETSID
(void)setsid();
(void)setsid();
#else
(void) setpgrp(0, getpid());
(void)setpgrp(0, getpid());
/* lose our controlling terminal
*/
if (-1 != (td = open("/dev/tty", O_RDWR, 0600))) {
(void)ioctl(td, TIOCNOTTY, (char *)0);
close(td);
}
/* lose our controlling terminal
*/
if (-1 != (td = open("/dev/tty", O_RDWR, 0600))) {
(void)ioctl(td, TIOCNOTTY, (char *)0);
close(td);
}
#endif
fp = fopen(PIDFILE, "w");
if ( fp ) {
fprintf(fp, "%d\n", (int) getpid());
fclose(fp);
} else {
Error("can't write pid to %s", PIDFILE);
}
fp = fopen(PIDFILE, "w");
if (fp) {
fprintf(fp, "%d\n", (int)getpid());
fclose(fp);
} else {
Error("can't write pid to %s", PIDFILE);
}
}
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[] = {
"a type set the default access type",
"C config give a new config file to the server process",
"d become a daemon, output to logfile (see -L)",
"D enable debug output, sent to stderr",
"h output this message",
"i init console connections on demand",
"L logfile give a new logfile path to the server process",
"M addr address to listen on (all addresses by default)",
"n do not output summary stream to stdout",
"p port port to listen on",
"P passwd give a new passwd file to the server process",
"v be verbose on startup",
"V output version info",
(char *)0
"7 strip the high bit of all console data",
"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",
"d become a daemon, redirecting stdout/stderr to logfile",
"D enable debug output, sent to stderr",
"h output this message",
"i initialize console connections on demand",
"L logfile give a new logfile path to the server process",
"M addr address to listen on (all addresses by default)",
"n obsolete - see -u",
"p port port to listen on",
"P passwd give a new passwd file to the server process",
"u copy \"unloved\" console data to stdout",
"v be verbose on startup",
"V output version info",
(char *)0
};
/* output a long message to the user (ksb)
*/
static void
Usage(ppc)
char **ppc;
char **ppc;
{
for (/* passed */; (char *)0 != *ppc; ++ppc)
fprintf(stderr, "\t%s\n", *ppc);
for ( /* passed */ ; (char *)0 != *ppc; ++ppc)
fprintf(stderr, "\t%s\n", *ppc);
}
/* show the user our version info (ksb)
@ -198,47 +199,68 @@ char **ppc;
static void
Version()
{
auto char acA1[16], acA2[16];
int i;
char acA1[16], acA2[16];
int i;
outputPid = 0;
outputPid = 0;
Info("%s", THIS_VERSION);
Info("default access type `%c\'", chDefAcc);
Info("default escape sequence `%s%s\'", FmtCtl(DEFATTN, acA1), FmtCtl(DEFESC, acA2));
Info("configuration in `%s\'", pcConfig);
Info("password in `%s\'", pcPasswd);
Info("logfile is `%s\'", pcLogfile);
Info("pidfile is `%s\'", PIDFILE);
Info("limited to %d group%s with %d member%s", MAXGRP, MAXGRP == 1 ? "" : "s", MAXMEMB, MAXMEMB == 1 ? "" : "s");
#if CPARITY
Info("high-bit of data stripped (7-bit clean)");
#else
Info("high-bit of data *not* stripped (8-bit clean)");
#endif
Info("%s", THIS_VERSION);
Info("default access type `%c\'", chDefAcc);
Info("default escape sequence `%s%s\'", FmtCtl(DEFATTN, acA1),
FmtCtl(DEFESC, acA2));
Info("configuration in `%s\'", pcConfig);
Info("password in `%s\'", pcPasswd);
Info("logfile is `%s\'", pcLogfile);
Info("pidfile is `%s\'", PIDFILE);
Info("limited to %d group%s with %d member%s", MAXGRP,
MAXGRP == 1 ? "" : "s", MAXMEMB, MAXMEMB == 1 ? "" : "s");
/* Look for non-numeric characters */
for (i=0;pcPort[i] != '\000';i++)
if (!isdigit((int)pcPort[i])) break;
/* Look for non-numeric characters */
for (i = 0; pcPort[i] != '\000'; i++)
if (!isdigit((int)pcPort[i]))
break;
if ( pcPort[i] == '\000' ) {
/* numeric only */
bindPort = atoi( pcPort );
Info("on port %u (referenced as `%s')", bindPort, pcPort);
if (pcPort[i] == '\000') {
/* numeric only */
bindPort = atoi(pcPort);
Info("on port %u (referenced as `%s')", bindPort, pcPort);
} else {
/* non-numeric only */
struct servent *pSE;
if ((struct servent *)0 == (pSE = getservbyname(pcPort, "tcp"))) {
Error("getservbyname: %s: %s", pcPort, strerror(errno));
} else {
/* non-numeric only */
struct servent *pSE;
if ((struct servent *)0 == (pSE = getservbyname(pcPort, "tcp"))) {
Error("getservbyname: %s: %s", pcPort, strerror(errno));
} else {
bindPort = ntohs((u_short)pSE->s_port);
Info("on port %u (referenced as `%s')", bindPort, pcPort);
}
bindPort = ntohs((u_short) pSE->s_port);
Info("on port %u (referenced as `%s')", bindPort, pcPort);
}
}
if (fVerbose)
printf(COPYRIGHT);
exit(1);
/* 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)
printf(COPYRIGHT);
exit(EX_OK);
}
/* find out where/who we are (ksb)
@ -251,244 +273,289 @@ Version()
*/
int
main(argc, argv)
int argc;
char **argv;
int argc;
char **argv;
{
register int i, j;
register FILE *fpConfig;
auto struct hostent *hpMe;
static char acOpts[] = "a:C:dDhiM:np:P:sVv";
extern int optopt;
extern char *optarg;
auto REMOTE
*pRCUniq; /* list of uniq console servers */
int i, j;
FILE *fpConfig;
struct hostent *hpMe;
static char acOpts[] = "7a:b:C:dDhiL:M:np:P:suVv";
extern int optopt;
extern char *optarg;
REMOTE *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 */
thepid = getpid();
if ((char *)0 == (progname = strrchr(argv[0], '/'))) {
progname = argv[0];
} else {
++progname;
}
thepid = getpid();
if ((char *)0 == (progname = strrchr(argv[0], '/'))) {
progname = argv[0];
} else {
++progname;
}
(void)setpwent();
(void)setpwent();
#if HAVE_SETLINEBUF
setlinebuf(stdout);
setlinebuf(stderr);
setlinebuf(stdout);
setlinebuf(stderr);
#endif
#if HAVE_SETVBUF
setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
#endif
(void)gethostname(acMyHost, sizeof(acMyHost));
if ((struct hostent *)0 == (hpMe = gethostbyname(acMyHost))) {
Error( "gethostbyname(%s): %s", acMyHost, hstrerror(h_errno));
exit(1);
}
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);
exit(1);
}
(void)gethostname(acMyHost, sizeof(acMyHost));
if ((struct hostent *)0 == (hpMe = gethostbyname(acMyHost))) {
Error("gethostbyname(%s): %s", acMyHost, hstrerror(h_errno));
exit(EX_UNAVAILABLE);
}
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);
exit(EX_UNAVAILABLE);
}
#if HAVE_MEMCPY
(void)memcpy(&acMyAddr[0], hpMe->h_addr, hpMe->h_length);
(void)memcpy(&acMyAddr, hpMe->h_addr, hpMe->h_length);
#else
(void)bcopy(hpMe->h_addr, &acMyAddr[0], hpMe->h_length);
(void)bcopy(hpMe->h_addr, &acMyAddr, hpMe->h_length);
#endif
while (EOF != (i = getopt(argc, argv, acOpts))) {
switch (i) {
case 'a':
chDefAcc = '\000' == *optarg ? 'r' : *optarg;
if (isupper((int)(chDefAcc))) {
chDefAcc = tolower(chDefAcc);
}
switch (chDefAcc) {
case 'r':
case 'a':
case 't':
break;
default:
Error( "unknown access type `%s\'", optarg);
exit(3);
}
break;
case 'C':
pcConfig = optarg;
break;
case 'p':
pcPort = optarg;
break;
case 'P':
pcPasswd = optarg;
break;
case 'd':
fDaemon = 1;
break;
case 'D':
fDebug = 1;
break;
case 'h':
fprintf(stderr, "%s: usage%s\n", progname, u_terse);
Usage(apcLong);
exit(0);
case 'i':
fNoinit = 1;
break;
case 'L':
pcLogfile = optarg;
break;
case 'M':
pcAddress = optarg;
break;
case 'n':
fAll = 0;
break;
case 's':
fSoftcar ^= 1;
break;
case 'V':
fVersion = 1;
break;
case 'v':
fVerbose = 1;
break;
case '\?':
fprintf(stderr, "%s: usage%s\n", progname, u_terse);
exit(1);
default:
Error( "option %c needs a parameter", optopt);
exit(1);
while (EOF != (i = getopt(argc, argv, acOpts))) {
switch (i) {
case '7':
fStrip = 1;
break;
case 'a':
chDefAcc = '\000' == *optarg ? 'r' : *optarg;
if (isupper((int)(chDefAcc))) {
chDefAcc = tolower(chDefAcc);
}
switch (chDefAcc) {
case 'r':
case 'a':
case 't':
break;
default:
Error("unknown access type `%s\'", optarg);
exit(EX_UNAVAILABLE);
}
break;
case 'b':
pcBasePort = optarg;
break;
case 'C':
pcConfig = optarg;
break;
case 'd':
fDaemon = 1;
fUseLogfile = 1;
break;
case 'D':
fDebug = 1;
break;
case 'h':
fprintf(stderr, "%s: usage%s\n", progname, u_terse);
Usage(apcLong);
exit(EX_OK);
case 'i':
fNoinit = 1;
break;
case 'L':
pcLogfile = optarg;
break;
case 'M':
pcAddress = optarg;
break;
case 'n':
/* noop now */
break;
case 'p':
pcPort = optarg;
break;
case 'P':
pcPasswd = optarg;
break;
case 's':
fSoftcar ^= 1;
break;
case 'u':
fAll = 1;
break;
case 'V':
fVersion = 1;
break;
case 'v':
fVerbose = 1;
break;
case '\?':
fprintf(stderr, "%s: usage%s\n", progname, u_terse);
exit(EX_UNAVAILABLE);
default:
Error("option %c needs a parameter", optopt);
exit(EX_UNAVAILABLE);
}
}
if (fVersion) {
Version();
exit(0);
}
/* 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 (fDaemon) {
daemonize();
}
if (fVersion) {
Version();
exit(EX_OK);
}
if (fDaemon) {
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 (0 != geteuid()) {
Error( "Warning: Running as a non-root user - any shadow password usage will most likely fail!" );
}
if (0 != geteuid()) {
Error
("Warning: Running as a non-root user - any shadow password usage will most likely fail!");
}
#endif
/* read the config file
*/
if ((FILE *)0 == (fpConfig = fopen(pcConfig, "r"))) {
Error( "fopen: %s: %s", pcConfig, strerror(errno));
exit(1);
}
/* read the config file
*/
if ((FILE *) 0 == (fpConfig = fopen(pcConfig, "r"))) {
Error("fopen: %s: %s", pcConfig, strerror(errno));
exit(EX_UNAVAILABLE);
}
#if HAVE_FLOCK
/* we lock the configuration file so that two identical
* conservers will not be running together (but two with
* different configurations can run on the same host).
*/
if (-1 == flock(fileno(fpConfig), LOCK_NB|LOCK_EX)) {
Error( "%s is locked, won\'t run more than one conserver?", pcConfig);
exit(3);
}
/* we lock the configuration file so that two identical
* conservers will not be running together (but two with
* different configurations can run on the same host).
*/
if (-1 == flock(fileno(fpConfig), LOCK_NB | LOCK_EX)) {
Error("%s is locked, won\'t run more than one conserver?",
pcConfig);
exit(EX_UNAVAILABLE);
}
#endif
ReadCfg(pcConfig, fpConfig);
ReadCfg(pcConfig, fpConfig);
if ( pcAddress == NULL ) {
bindAddr = (unsigned long)INADDR_ANY;
if (pcAddress == NULL) {
bindAddr = (unsigned long)INADDR_ANY;
} else {
if ((bindAddr = inet_addr(pcAddress)) == -1) {
Error("inet_addr: %s: %s", pcAddress, "invalid IP address");
exit(EX_UNAVAILABLE);
}
}
Debug("Bind address set to `%s'",
inet_ntoa(*(struct in_addr *)&bindAddr));
if (pcPort == NULL) {
Error("Severe error: pcPort is NULL???? How can that be?");
exit(EX_UNAVAILABLE);
}
/* Look for non-numeric characters */
for (i = 0; pcPort[i] != '\000'; i++)
if (!isdigit((int)pcPort[i]))
break;
if (pcPort[i] == '\000') {
/* numeric only */
bindPort = atoi(pcPort);
} else {
/* non-numeric only */
struct servent *pSE;
if ((struct servent *)0 == (pSE = getservbyname(pcPort, "tcp"))) {
Error("getservbyname: %s: %s", pcPort, strerror(errno));
exit(EX_UNAVAILABLE);
} else {
if ((bindAddr = inet_addr(pcAddress)) == -1) {
Error("inet_addr: %s: %s", pcAddress, "invalid IP address");
exit(1);
}
bindPort = ntohs((u_short) pSE->s_port);
}
Debug( "Bind address set to `%s'", inet_ntoa(*(struct in_addr *)&bindAddr) );
}
if ( pcPort == NULL )
{
Error( "Severe error: pcPort is NULL???? How can that be?" );
exit(1);
}
/* Look for non-numeric characters */
for (i = 0; pcBasePort[i] != '\000'; i++)
if (!isdigit((int)pcBasePort[i]))
break;
/* Look for non-numeric characters */
for (i=0;pcPort[i] != '\000';i++)
if (!isdigit((int)pcPort[i])) break;
if ( pcPort[i] == '\000' ) {
/* numeric only */
bindPort = atoi( pcPort );
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 {
/* non-numeric only */
struct servent *pSE;
if ((struct servent *)0 == (pSE = getservbyname(pcPort, "tcp"))) {
Debug("getservbyname: %s: %s", pcPort, strerror(errno));
exit(1);
} else {
bindPort = ntohs((u_short)pSE->s_port);
}
bindBasePort = ntohs((u_short) pSE->s_port);
}
}
/* if no one can use us we need to come up with a default
*/
if (0 == iAccess) {
SetDefAccess(hpMe);
/* if no one can use us we need to come up with a default
*/
if (0 == iAccess) {
SetDefAccess(hpMe);
}
/* spawn all the children, so fix kids has an initial pid
*/
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
if (aGroups[i].imembers) {
Spawn(&aGroups[i]);
}
/* spawn all the children, so fix kids has an initial pid
*/
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
if (aGroups[i].imembers) {
Spawn(& aGroups[i]);
}
if (fVerbose) {
Info("group %d on port %d", i, ntohs((u_short)aGroups[i].port));
}
for (j = 0; j < aGroups[i].imembers; ++j) {
if (-1 != aGroups[i].pCElist[j].fdtty)
(void)close(aGroups[i].pCElist[j].fdtty);
}
}
if (fVerbose) {
for (i = 0; i < iAccess; ++i) {
Info("access type '%c' for \"%s\"", pACList[i].ctrust, pACList[i].pcwho);
}
Info("group #%d pid %d on port %u", i, aGroups[i].pid,
ntohs(aGroups[i].port));
}
pRCUniq = FindUniq(pRCList);
/* output unique console server peers?
*/
if (fVerbose) {
register REMOTE *pRC;
for (pRC = pRCUniq; (REMOTE *)0 != pRC; pRC = pRC->pRCuniq) {
Info("peer server on `%s'", pRC->rhost);
}
for (j = 0; j < aGroups[i].imembers; ++j) {
if (-1 != aGroups[i].pCElist[j].fdtty)
(void)close(aGroups[i].pCElist[j].fdtty);
}
}
(void)fflush(stdout);
(void)fflush(stderr);
Master(pRCUniq);
/* stop putting kids back, and shoot them
*/
(void)signal(SIGCHLD, SIG_DFL);
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
if (-1 == kill(aGroups[i].pid, SIGTERM)) {
Error( "kill: %s", strerror(errno));
}
if (fVerbose) {
for (i = 0; i < iAccess; ++i) {
Info("access type '%c' for \"%s\"", pACList[i].ctrust,
pACList[i].pcwho);
}
}
(void)endpwent();
(void)fclose(fpConfig);
exit(0);
pRCUniq = FindUniq(pRCList);
/* output unique console server peers?
*/
if (fVerbose) {
REMOTE *pRC;
for (pRC = pRCUniq; (REMOTE *) 0 != pRC; pRC = pRC->pRCuniq) {
Info("peer server on `%s'", pRC->rhost);
}
}
(void)fflush(stdout);
(void)fflush(stderr);
Master(pRCUniq);
/* stop putting kids back, and shoot them
*/
simpleSignal(SIGCHLD, SIG_DFL);
SignalKids(SIGTERM);
Info("Stopped at %s", strtime(NULL));
(void)endpwent();
(void)fclose(fpConfig);
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
*
@ -37,15 +37,16 @@
/* program options and stuff
*/
extern char rcsid[];
extern int fAll, fVerbose, fSoftcar, fNoinit, fInteractive;
extern int fAll, fVerbose, fSoftcar, fNoinit, fInteractive, fStrip,
fDaemon;
extern char chDefAcc;
extern unsigned long bindAddr;
extern unsigned int bindPort;
extern unsigned int bindPort, bindBasePort;
extern char *pcLogfile;
extern char *pcConfig;
extern char *pcPasswd;
extern struct sockaddr_in in_port;
extern char acMyHost[];
extern char acMyAddr[];
extern struct in_addr acMyAddr;
extern int domainHack;
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
*
@ -35,6 +35,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <ctype.h>
@ -42,8 +43,9 @@
#include <pwd.h>
#include <compat.h>
#include <port.h>
#include <util.h>
#include <consent.h>
#include <client.h>
#include <group.h>
@ -52,7 +54,6 @@
#include <readcfg.h>
#include <version.h>
#include <main.h>
#include <output.h>
@ -61,11 +62,11 @@ static sig_atomic_t fSawQuit, fSawHUP, fSawUSR1, fSawCHLD;
static RETSIGTYPE
FlagSawCHLD(sig)
int sig;
int sig;
{
fSawCHLD = 1;
fSawCHLD = 1;
#if !HAVE_SIGACTION
(void)signal(SIGCHLD, FlagSawCHLD);
simpleSignal(SIGCHLD, FlagSawCHLD);
#endif
}
@ -75,64 +76,107 @@ FlagSawCHLD(sig)
static void
FixKids()
{
register int i, pid;
auto int UWbuf;
int i, pid;
int UWbuf;
#if HAVE_WAIT3
while (-1 != (pid = wait3(& UWbuf, WNOHANG, (struct rusage *)0))) {
#else
while (-1 != (pid = wait(& UWbuf))) {
#endif
if (0 == pid) {
break;
}
/* stopped child is just continuted
*/
if (WIFSTOPPED(UWbuf) && 0 == kill(pid, SIGCONT)) {
continue;
}
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
if (pid != aGroups[i].pid)
continue;
/* this kid kid is dead, start another
*/
Spawn(& aGroups[i]);
Info("%s: exit(%d), restarted %s", aGroups[i].pCElist[0].server, WEXITSTATUS(UWbuf), strtime(NULL));
}
while (-1 != (pid = waitpid(-1, &UWbuf, WNOHANG))) {
if (0 == pid) {
break;
}
/* stopped child is just continuted
*/
if (WIFSTOPPED(UWbuf) && 0 == kill(pid, SIGCONT)) {
continue;
}
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
if (pid != aGroups[i].pid)
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
*/
Spawn(&aGroups[i]);
if (fVerbose) {
Info("group #%d pid %d on port %u", i, aGroups[i].pid,
ntohs(aGroups[i].port));
}
}
}
}
/* kill all the kids and exit.
* Called when master process receives SIGTERM
*/
static RETSIGTYPE
QuitIt(arg)
int arg;
FlagQuitIt(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
FlagSawHUP(arg)
int arg;
int arg;
{
fSawHUP = 1;
fSawHUP = 1;
#if !HAVE_SIGACTION
(void)signal(SIGHUP, FlagSawHUP);
simpleSignal(SIGHUP, FlagSawHUP);
#endif
}
static RETSIGTYPE
FlagSawUSR1(arg)
int arg;
int arg;
{
fSawUSR1 = 1;
fSawUSR1 = 1;
#if !HAVE_SIGACTION
(void)signal(SIGUSR1, FlagSawUSR1);
simpleSignal(SIGUSR1, FlagSawUSR1);
#endif
}
@ -140,16 +184,17 @@ FlagSawUSR1(arg)
*/
void
SignalKids(arg)
int arg;
int arg;
{
int i;
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
if (-1 == kill(aGroups[i].pid, arg)) {
Error("kill: %s", strerror(errno));
}
int i;
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers || -1 == aGroups[i].pid)
continue;
Debug("Sending pid %d signal %d", aGroups[i].pid, arg);
if (-1 == kill(aGroups[i].pid, arg)) {
Error("kill: %s", strerror(errno));
}
}
}
@ -157,367 +202,384 @@ SignalKids(arg)
*/
void
Master(pRCUniq)
REMOTE
*pRCUniq; /* list of uniq console servers */
REMOTE *pRCUniq; /* list of uniq console servers */
{
register char *pcArgs;
register int i, j, cfd;
register REMOTE *pRC, *pRCFound;
register int nr, prnum = 0, found, msfd;
register struct hostent *hpPeer;
auto char cType;
auto int so;
auto fd_set rmask, rmaster;
auto char acIn[1024], acOut[BUFSIZ];
auto struct sockaddr_in master_port, response_port;
int true = 1;
char *pcArgs;
int i, j, cfd;
CONSFILE *csocket;
REMOTE *pRC, *pRCFound;
int nr, found, msfd;
unsigned short prnum = 0;
struct hostent *hpPeer;
char cType;
int so;
fd_set rmask, rmaster;
unsigned char acIn[1024], acOut[BUFSIZ];
struct sockaddr_in master_port, response_port;
int true = 1;
int pid;
char *ambiguous = (char *)0;
/* set up signal handler */
/* set up signal handler */
#if defined(SIGPOLL)
signal(SIGPOLL, SIG_IGN);
simpleSignal(SIGPOLL, SIG_IGN);
#endif
Set_signal(SIGCHLD, FlagSawCHLD);
Set_signal(SIGTERM, QuitIt);
Set_signal(SIGUSR1, FlagSawUSR1);
Set_signal(SIGHUP, FlagSawHUP);
simpleSignal(SIGCHLD, FlagSawCHLD);
simpleSignal(SIGTERM, FlagQuitIt);
simpleSignal(SIGUSR1, FlagSawUSR1);
simpleSignal(SIGHUP, FlagSawHUP);
if (!fDaemon)
simpleSignal(SIGINT, FlagSawINT);
/* set up port for master to listen on
*/
/* set up port for master to listen on
*/
#if HAVE_MEMSET
(void)memset((void *)&master_port, 0, sizeof(master_port));
(void)memset((void *)&master_port, 0, sizeof(master_port));
#else
(void)bzero((char *)&master_port, sizeof(master_port));
(void)bzero((char *)&master_port, sizeof(master_port));
#endif
master_port.sin_family = AF_INET;
*(u_long *)&master_port.sin_addr = bindAddr;
master_port.sin_port = htons(bindPort);
master_port.sin_family = AF_INET;
master_port.sin_addr.s_addr = bindAddr;
master_port.sin_port = htons(bindPort);
if ((msfd=socket(AF_INET, SOCK_STREAM, 0)) < 0) {
Error("socket: %s", strerror(errno));
return;
}
if ((msfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
Error("socket: %s", strerror(errno));
return;
}
#if HAVE_SETSOCKOPT
if (setsockopt(msfd, SOL_SOCKET, SO_REUSEADDR, (char *)&true, sizeof(true))<0) {
Error("setsockopt: %s", strerror(errno));
return;
}
if (setsockopt
(msfd, SOL_SOCKET, SO_REUSEADDR, (char *)&true,
sizeof(true)) < 0) {
Error("setsockopt: %s", strerror(errno));
return;
}
#endif
if (bind(msfd, (struct sockaddr *)&master_port, sizeof(master_port))<0) {
Error("bind: %s", strerror(errno));
return;
if (bind(msfd, (struct sockaddr *)&master_port, sizeof(master_port)) <
0) {
Error("bind: %s", strerror(errno));
return;
}
if (listen(msfd, SOMAXCONN) < 0) {
Error("listen: %s", strerror(errno));
}
FD_ZERO(&rmaster);
FD_SET(msfd, &rmaster);
for (fSawQuit = 0; !fSawQuit; /* can't close here :-( */ ) {
if (fSawCHLD) {
fSawCHLD = 0;
FixKids();
}
if (listen(msfd, SOMAXCONN) < 0) {
Error("listen: %s", strerror(errno));
if (fSawHUP) {
fSawHUP = 0;
reopenLogfile();
SignalKids(SIGHUP);
}
if (fSawUSR1) {
fSawUSR1 = 0;
SignalKids(SIGUSR1);
}
if (fSawQuit) { /* Something above set the quit flag */
break;
}
FD_ZERO(&rmaster);
FD_SET(msfd, &rmaster);
for (fSawQuit = 0; !fSawQuit; /* can't close here :-( */) {
if (fSawCHLD) {
fSawCHLD = 0;
FixKids();
}
if (fSawHUP) {
fSawHUP = 0;
reopenLogfile();
SignalKids(SIGHUP);
}
if (fSawUSR1) {
fSawUSR1 = 0;
SignalKids(SIGUSR1);
}
rmask = rmaster;
rmask = rmaster;
if (-1 ==
select(msfd + 1, &rmask, (fd_set *) 0, (fd_set *) 0,
(struct timeval *)0)) {
if (errno != EINTR) {
Error("select: %s", strerror(errno));
}
continue;
}
if (!FD_ISSET(msfd, &rmask)) {
continue;
}
so = sizeof(response_port);
cfd =
accept(msfd, (struct sockaddr *)&response_port,
(socklen_t *) & so);
if (cfd < 0) {
Error("accept: %s", strerror(errno));
continue;
}
if ((CONSFILE *) 0 == (csocket = fileOpenFD(cfd, simpleSocket))) {
Error("fileOpenFD: %s", strerror(errno));
close(cfd);
continue;
}
if (-1 == select(msfd+1, &rmask, (fd_set *)0, (fd_set *)0, (struct timeval *)0)) {
if ( errno != EINTR ) {
Error("select: %s", strerror(errno));
}
continue;
}
if (!FD_ISSET(msfd, &rmask)) {
continue;
}
so = sizeof(response_port);
cfd = accept(msfd, (struct sockaddr *)&response_port, (socklen_t *)&so);
if (cfd < 0) {
Error("accept: %s", strerror(errno));
continue;
}
so = sizeof(in_port);
if (-1 ==
getpeername(fileFDNum(csocket), (struct sockaddr *)&in_port,
(socklen_t *) & so)) {
fileWrite(csocket, "getpeername failed\r\n", -1);
(void)fileClose(csocket);
continue;
}
so = sizeof(in_port.sin_addr);
if ((struct hostent *)0 ==
(hpPeer =
gethostbyaddr((char *)&in_port.sin_addr, so, AF_INET))) {
cType = AccType(&in_port.sin_addr, NULL);
} else {
cType = AccType(&in_port.sin_addr, hpPeer->h_name);
}
if ('r' == cType) {
fileWrite(csocket, "access from your host refused\r\n", -1);
(void)fileClose(csocket);
continue;
}
(void)fflush(stdin);
(void)fflush(stderr);
switch (pid = fork()) {
case -1:
fileWrite(csocket, "fork failed, try again later\r\n", -1);
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;
case 0:
thepid = getpid();
break;
}
so = sizeof(in_port);
if (-1 == getpeername(cfd, (struct sockaddr *)&in_port, (socklen_t *)&so)) {
CSTROUT(cfd, "getpeername failed\r\n");
(void)close(cfd);
continue;
/* handle the connection
* (port lookup, who, users, or quit)
*/
fileWrite(csocket, "ok\r\n", -1);
for (i = 0; i < sizeof(acIn); /* i+=nr */ ) {
if (0 >=
(nr = fileRead(csocket, &acIn[i], sizeof(acIn) - 1 - i))) {
i = 0;
break;
}
i += nr;
if ('\n' == acIn[i - 1]) {
acIn[i] = '\000';
--i;
break;
}
}
if (i > 0 && '\n' == acIn[i - 1]) {
acIn[--i] = '\000';
}
if (i > 0 && '\r' == acIn[i - 1]) {
acIn[--i] = '\000';
}
if (0 == i) {
Error("lost connection");
(void)fileClose(csocket);
exit(EX_OK);
}
if ((char *)0 != (pcArgs = strchr(acIn, ':'))) {
*pcArgs++ = '\000';
} else if ((char *)0 != (pcArgs = strchr(acIn, ' '))) {
*pcArgs++ = '\000';
}
if (0 == strcmp(acIn, "help")) {
static char *apcHelp[] = {
"call provide port for given machine\r\n",
"groups provide ports for group leaders\r\n",
"help this help message\r\n",
"master provide a list of master servers\r\n",
"pid provide pid of master process\r\n",
"quit terminate conserver\r\n",
"version provide version info for server\r\n",
(char *)0
};
char **ppc;
for (ppc = apcHelp; (char *)0 != *ppc; ++ppc) {
(void)fileWrite(csocket, *ppc, -1);
}
(void)fileClose(csocket);
exit(EX_OK);
}
if (0 == strcmp(acIn, "quit")) {
struct passwd *pwd;
if ('t' == cType) {
fileWrite(csocket, "trusted -- terminated\r\n", -1);
fSawQuit = 1;
} else if ((char *)0 == pcArgs) {
fileWrite(csocket, "must be trusted to terminate\r\n", -1);
} else if ((struct passwd *)0 == (pwd = getpwuid(0))) {
fileWrite(csocket, "no root passwd?\r\n", -1);
} else if (0 == CheckPass(pwd, (char *)0, pcArgs)) {
fileWrite(csocket, "Sorry.\r\n", -1);
} else {
fileWrite(csocket, "ok -- terminated\r\n", -1);
fSawQuit = 1;
}
(void)fileClose(csocket);
exit(EX_OK);
}
if (0 == strcmp(acIn, "pid")) {
sprintf(acOut, "%d\r\n", (int)getpid());
(void)fileWrite(csocket, acOut, -1);
(void)fileClose(csocket);
exit(EX_OK);
}
if (0 == strcmp(acIn, "groups")) {
int iSep = 1;
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
sprintf(acOut, ":%u" + iSep, ntohs(aGroups[i].port));
(void)fileWrite(csocket, acOut, -1);
iSep = 0;
}
fileWrite(csocket, "\r\n", -1);
(void)fileClose(csocket);
exit(EX_OK);
}
if (0 == strcmp(acIn, "master")) {
int iSep = 1;
if (0 != iLocal) {
struct sockaddr_in lcl;
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);
}
so = sizeof(in_port.sin_addr);
if ((struct hostent *)0 == (hpPeer = gethostbyaddr((char *)&in_port.sin_addr, so, AF_INET))) {
cType = AccType(&in_port.sin_addr, NULL);
sprintf(acOut, "@%s", inet_ntoa(lcl.sin_addr));
(void)fileWrite(csocket, acOut, -1);
iSep = 0;
}
for (pRC = pRCUniq; (REMOTE *) 0 != pRC; pRC = pRC->pRCuniq) {
sprintf(acOut, ":@%s" + iSep, pRC->rhost);
(void)fileWrite(csocket, acOut, -1);
iSep = 0;
}
fileWrite(csocket, "\r\n", -1);
(void)fileClose(csocket);
exit(EX_OK);
}
if (0 == strcmp(acIn, "version")) {
sprintf(acOut, "version `%s\'\r\n", THIS_VERSION);
(void)fileWrite(csocket, acOut, -1);
(void)fileClose(csocket);
exit(EX_OK);
}
if (0 != strcmp(acIn, "call")) {
fileWrite(csocket, "unknown command\r\n", -1);
(void)fileClose(csocket);
exit(EX_OK);
}
if ((char *)0 == pcArgs) {
fileWrite(csocket, "call requires argument\r\n", -1);
(void)fileClose(csocket);
exit(EX_OK);
}
/* look up the machine to call
*/
found = 0;
pRCFound = (REMOTE *) 0;
/* look for a local machine */
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
for (j = 0; j < aGroups[i].imembers; ++j) {
if (0 != strcmp(pcArgs, aGroups[i].pCElist[j].server)) {
continue;
}
prnum = ntohs(aGroups[i].port);
ambiguous = buildString(aGroups[i].pCElist[j].server);
ambiguous = buildString(", ");
++found;
}
}
/* Purposefully hunt for another match - this will detect
* duplicates - a bad state to be in.
* Does the readcfg.c code even check for dups?
*/
for (pRC = pRCList; (REMOTE *) 0 != pRC; pRC = pRC->pRCnext) {
if (0 != strcmp(pcArgs, pRC->rserver)) {
continue;
}
ambiguous = buildString(pRC->rserver);
ambiguous = buildString(", ");
++found;
pRCFound = pRC;
}
if (found == 0) { /* Then look for substring matches */
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
for (j = 0; j < aGroups[i].imembers; ++j) {
if (0 !=
strncmp(pcArgs, aGroups[i].pCElist[j].server,
strlen(pcArgs))) {
continue;
}
prnum = ntohs(aGroups[i].port);
ambiguous = buildString(aGroups[i].pCElist[j].server);
ambiguous = buildString(", ");
++found;
}
}
/* look for a remote server */
/* again, looks for dups with local consoles */
for (pRC = pRCList; (REMOTE *) 0 != pRC; pRC = pRC->pRCnext) {
if (0 != strncmp(pcArgs, pRC->rserver, strlen(pcArgs))) {
continue;
}
ambiguous = buildString(pRC->rserver);
ambiguous = buildString(", ");
++found;
pRCFound = pRC;
}
}
switch (found) {
case 0:
sprintf(acOut, "console `%s' not found\r\n", pcArgs);
break;
case 1:
if ((REMOTE *) 0 != pRCFound) {
sprintf(acOut, "@%s\r\n", pRCFound->rhost);
} else {
cType = AccType(&in_port.sin_addr, hpPeer->h_name);
sprintf(acOut, "%u\r\n", prnum);
}
if ('r' == cType) {
CSTROUT(cfd, "access from your host refused\r\n");
(void)close(cfd);
continue;
}
#if TEST_FORK
/* we should fork here, or timeout
*/
switch(fork()) {
default:
(void)close(cfd);
continue;
case -1:
CSTROUT(cfd, "fork failed, try again\r\n");
(void)close(cfd);
continue;
case 0:
thepid = getpid();
break;
}
#endif
/* handle the connection
* (port lookup, who, users, or quit)
*/
CSTROUT(cfd, "ok\r\n");
for (i = 0; i < sizeof(acIn); /* i+=nr */) {
if (0 >= (nr = read(cfd, &acIn[i], sizeof(acIn)-1-i))) {
i = 0;
break;
}
i += nr;
if ('\n' == acIn[i-1]) {
acIn[i] = '\000';
--i;
break;
}
}
if (i > 0 && '\n' == acIn[i-1]) {
acIn[--i] = '\000';
}
if (i > 0 && '\r' == acIn[i-1]) {
acIn[--i] = '\000';
}
if (0 == i) {
Error("lost connection");
(void)close(cfd);
#if TEST_FORK
exit(1);
#else
continue;
#endif
}
if ((char *)0 != (pcArgs = strchr(acIn, ':'))) {
*pcArgs++ = '\000';
} else if ((char *)0 != (pcArgs = strchr(acIn, ' '))) {
*pcArgs++ = '\000';
}
if (0 == strcmp(acIn, "help")) {
static char *apcHelp[] = {
"call provide port for given machine\r\n",
"groups provide ports for group leaders\r\n",
"help this help message\r\n",
"master provide a list of master servers\r\n",
"pid provide pid of master process\r\n",
"quit terminate conserver\r\n",
"version provide version info for server\r\n",
(char *)0
};
register char **ppc;
for (ppc = apcHelp; (char *)0 != *ppc; ++ppc) {
(void)write(cfd, *ppc, strlen(*ppc));
}
(void)close(cfd);
#if TEST_FORK
exit(0);
#else
continue;
#endif
}
if (0 == strcmp(acIn, "quit")) {
register struct passwd *pwd;
if ('t' == cType) {
CSTROUT(cfd, "trusted -- terminated\r\n");
#if TEST_FORK
kill(getppid(), SIGTERM);
#else
fSawQuit = 1;
#endif
} else if ((char *)0 == pcArgs) {
CSTROUT(cfd, "must be trusted to terminate\r\n");
} else if ((struct passwd *)0 == (pwd = getpwuid(0))) {
CSTROUT(cfd, "no root passwd?\r\n");
} else if (0 == CheckPass(pwd, (char *)0, pcArgs)) {
CSTROUT(cfd, "Sorry.\r\n");
} else {
CSTROUT(cfd, "ok -- terminated\r\n");
#if TEST_FORK
kill(getppid(), SIGTERM);
#else
fSawQuit = 1;
#endif
}
(void)close(cfd);
#if TEST_FORK
exit(0);
#else
continue;
#endif
}
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());
(void)write(cfd, acOut, strlen(acOut));
(void)close(cfd);
continue;
#endif
}
if (0 == strcmp(acIn, "groups")) {
register int iSep = 1;
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
sprintf(acOut, ":%d"+iSep, ntohs((u_short)aGroups[i].port));
(void)write(cfd, acOut, strlen(acOut));
iSep = 0;
}
CSTROUT(cfd, "\r\n");
(void)close(cfd);
#if TEST_FORK
exit(0);
#else
continue;
#endif
}
if (0 == strcmp(acIn, "master")) {
register int iSep = 1;
if (0 != iLocal) {
sprintf(acOut, "@%s", acMyHost);
(void)write(cfd, acOut, strlen(acOut));
iSep = 0;
}
for (pRC = pRCUniq; (REMOTE *)0 != pRC; pRC = pRC->pRCuniq) {
sprintf(acOut, ":@%s"+iSep, pRC->rhost);
(void)write(cfd, acOut, strlen(acOut));
iSep = 0;
}
CSTROUT(cfd, "\r\n");
(void)close(cfd);
#if TEST_FORK
exit(0);
#else
continue;
#endif
}
if (0 == strcmp(acIn, "version")) {
sprintf(acOut, "version `%s\'\r\n", THIS_VERSION);
(void)write(cfd, acOut, strlen(acOut));
(void)close(cfd);
#if TEST_FORK
exit(0);
#else
continue;
#endif
}
if (0 != strcmp(acIn, "call")) {
CSTROUT(cfd, "unknown command\r\n");
(void)close(cfd);
#if TEST_FORK
exit(0);
#else
continue;
#endif
}
if ((char *)0 == pcArgs) {
CSTROUT(cfd, "call requires argument\r\n");
(void)close(cfd);
#if TEST_FORK
exit(0);
#else
continue;
#endif
}
/* look up the machine to call
*/
found = 0;
pRCFound = (REMOTE *)0;
/* look for a local machine */
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
for (j = 0; j < aGroups[i].imembers; ++j) {
if (0 != strcmp(pcArgs, aGroups[i].pCElist[j].server)) {
continue;
}
prnum = ntohs((u_short)aGroups[i].port);
++found;
}
}
/* Purposefully hunt for another match - this will detect
* duplicates - a bad state to be in.
* Does the readcfg.c code even check for dups?
*/
for (pRC = pRCList; (REMOTE *)0 != pRC; pRC = pRC->pRCnext) {
if (0 != strcmp(pcArgs, pRC->rserver)) {
continue;
}
++found;
pRCFound = pRC;
}
if ( found == 0 ) { /* Then look for substring matches */
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
for (j = 0; j < aGroups[i].imembers; ++j) {
if (0 != strncmp(pcArgs, aGroups[i].pCElist[j].server, strlen(pcArgs))) {
continue;
}
prnum = ntohs((u_short)aGroups[i].port);
++found;
}
}
/* look for a remote server */
/* again, looks for dups with local consoles */
for (pRC = pRCList; (REMOTE *)0 != pRC; pRC = pRC->pRCnext) {
if (0 != strncmp(pcArgs, pRC->rserver, strlen(pcArgs))) {
continue;
}
++found;
pRCFound = pRC;
}
}
switch (found) {
case 0:
sprintf(acOut, "server %s not found\r\n", pcArgs);
break;
case 1:
if ((REMOTE *)0 != pRCFound) {
sprintf(acOut, "@%s\r\n", pRCFound->rhost);
} else {
sprintf(acOut, "%d\r\n", prnum);
}
break;
default:
sprintf(acOut, "ambiguous server abbreviation, %s\r\n", pcArgs);
break;
}
(void)write(cfd, acOut, strlen(acOut));
(void)close(cfd);
#if TEST_FORK
exit(0);
#endif
break;
default:
found = strlen(ambiguous);
ambiguous[found - 2] = '\000';
sprintf(acOut,
"ambiguous console abbreviation, `%s'\r\n\tchoices are %s\r\n",
pcArgs, ambiguous);
break;
}
buildString((char *)0); /* we're done - clean up */
ambiguous = (char *)0;
(void)fileWrite(csocket, acOut, -1);
(void)fileClose(csocket);
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
*
@ -38,3 +38,4 @@
* stuff the master process needs
*/
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
*
@ -61,34 +61,8 @@
/* communication constants
*/
#define OB_SUSP 'Z' /* suspended 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)
#define OB_SUSP 'Z' /* suspended by server */
#define OB_DROP '.' /* dropped by server */
/* For legacy compile-time setting of the port...
*/

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
*
@ -46,8 +46,9 @@
#include <pwd.h>
#include <compat.h>
#include <port.h>
#include <util.h>
#include <consent.h>
#include <client.h>
#include <group.h>
@ -55,31 +56,26 @@
#include <readcfg.h>
#include <master.h>
#include <main.h>
#include <output.h>
GRPENT
aGroups[MAXGRP]; /* even spread is OK */
CONSENT
aConsoles[MAXGRP*MAXMEMB]; /* gross over allocation */
REMOTE
*pRCList; /* list of remote consoles we know about */
GRPENT aGroups[MAXGRP]; /* even spread is OK */
CONSENT aConsoles[MAXGRP * MAXMEMB]; /* gross over allocation */
REMOTE *pRCList; /* list of remote consoles we know about */
int
iLocal; /* number of local consoles */
iLocal; /* number of local consoles */
ACCESS
*pACList; /* `who do you love' (or trust) */
ACCESS *pACList; /* `who do you love' (or trust) */
int
iAccess; /* how many access restrictions we have */
iAccess; /* how many access restrictions we have */
/* Parse the [number(m|h|d|l)[a]] spec
* return 0 on invalid spec, non-zero on valid spec
*/
int
parseMark(pcFile, iLine, pcMark, tyme, pCE)
const char *pcFile;
const int iLine;
const char *pcMark;
CONSENT *pCE;
const char *pcFile;
const int iLine;
const char *pcMark;
CONSENT *pCE;
{
char mark[BUFSIZ];
char *p, *n = (char *)0;
@ -87,41 +83,51 @@ CONSENT *pCE;
int factor = 0, pfactor = 0;
int value = 0, pvalue = 0;
if ((pcMark == (char *)0) ||
(*pcMark == '\000'))
if ((pcMark == (char *)0) || (*pcMark == '\000'))
return 0;
(void)strcpy(mark, pcMark);
for (p = mark; *p != '\000'; p++) {
if ( *p == 'a' || *p == 'A' ) {
if ( n != (char *)0 ) {
Error( "%s(%d) bad timestamp specification `%s': numeral before `a' (ignoring numeral)", pcFile, iLine, pcMark);
if (*p == 'a' || *p == 'A') {
if (n != (char *)0) {
Error
("%s(%d) bad timestamp specification `%s': numeral before `a' (ignoring numeral)",
pcFile, iLine, pcMark);
}
activity = 1;
} else if ( *p == 'm' || *p == 'M' ) {
} else if (*p == 'm' || *p == 'M') {
pfactor = 60;
} else if ( *p == 'h' || *p == 'H' ) {
} else if (*p == 'h' || *p == 'H') {
pfactor = 60 * 60;
} else if ( *p == 'd' || *p == 'D') {
} else if (*p == 'd' || *p == 'D') {
pfactor = 60 * 60 * 24;
} else if ( *p == 'l' || *p == 'L') {
} else if (*p == 'l' || *p == 'L') {
pfactor = -1;
} else if ( isdigit((int)*p) ) {
if ( n == (char *)0 )
} else if (isdigit((int)*p)) {
if (n == (char *)0)
n = p;
} else if (isspace((int)*p)) {
if (n != (char *)0) {
pfactor = 60;
}
} 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;
}
if ( pfactor ) {
if ( n == (char *)0 ) {
Error( "%s(%d) bad timestamp specification `%s': missing numeric prefix for `%c'", pcFile, iLine, pcMark, *p);
if (pfactor) {
if (n == (char *)0) {
Error
("%s(%d) bad timestamp specification `%s': missing numeric prefix for `%c'",
pcFile, iLine, pcMark, *p);
return 0;
} else {
*p = '\000';
pvalue = atoi(n);
if ( pvalue < 0 ) {
Error( "%s(%d) negative timestamp specification `%s'", pcFile, iLine, pcMark);
if (pvalue < 0) {
Error("%s(%d) negative timestamp specification `%s'",
pcFile, iLine, pcMark);
return 0;
}
n = (char *)0;
@ -132,19 +138,31 @@ 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;
if ( factor && value ) {
if (factor && value) {
pCE->mark = value;
if ( factor > 0 ) {
if (factor > 0) {
pCE->nextMark = tyme + value;
} else {
pCE->nextMark = value;
}
} else {
pCE->nextMark = pCE->mark = 0;
pCE->nextMark = pCE->mark = 0;
}
}
@ -155,26 +173,26 @@ CONSENT *pCE;
* a pointer to the start of the non-space part
*/
char *
pruneSpace( string )
char *string;
pruneSpace(string)
char *string;
{
char *p;
char *head = (char *)0;
char *tail = (char *)0;
/* Don't do much if it's crap */
if ( string == (char *)0 || *string == '\000' )
if (string == (char *)0 || *string == '\000')
return string;
/* Now for the tricky part - search the string */
for (p = string; *p != '\000'; p++) {
if (isspace((int)(*p))) {
if (tail == (char *)0)
tail = p; /* possible end of string */
tail = p; /* possible end of string */
} else {
if (head == (char *)0)
head = p; /* found the start */
tail = (char *)0; /* reset tail */
head = p; /* found the start */
tail = (char *)0; /* reset tail */
}
}
@ -192,313 +210,408 @@ char *string;
*/
void
ReadCfg(pcFile, fp)
char *pcFile;
register FILE *fp;
char *pcFile;
FILE *fp;
{
register GRPENT *pGE;
register int iG, minG;
auto int iLine;
auto char acIn[BUFSIZ];
char *acStart;
register GRPENT *pGEAll;
register CONSENT *pCE;
register REMOTE **ppRC;
char LogDirectory[MAXLOGLEN];
time_t tyme;
char defMark[BUFSIZ];
GRPENT *pGE;
int iG, minG;
int iLine;
unsigned char acIn[BUFSIZ];
char *acStart;
GRPENT *pGEAll;
CONSENT *pCE;
REMOTE **ppRC;
char LogDirectory[MAXLOGLEN];
time_t tyme;
char defMark[BUFSIZ];
tyme = time((time_t *)0);
LogDirectory[0] = '\000';
pGEAll = aGroups; /* fill in these structs */
pCE = aConsoles;
ppRC = & pRCList;
iLocal = 0;
tyme = time((time_t *) 0);
LogDirectory[0] = '\000';
defMark[0] = '\000';
pGEAll = aGroups; /* fill in these structs */
pCE = aConsoles;
ppRC = &pRCList;
iLocal = 0;
iG = minG = 0;
iLine = 0;
while (fgets(acIn, sizeof(acIn)-1, fp) != NULL) {
register char *pcLine, *pcMode, *pcLog, *pcRem, *pcStart, *pcMark;
iG = minG = 0;
iLine = 0;
while (fgets(acIn, sizeof(acIn) - 1, fp) != NULL) {
char *pcLine, *pcMode, *pcLog, *pcRem, *pcStart, *pcMark;
++iLine;
++iLine;
acStart = pruneSpace( acIn );
acStart = pruneSpace(acIn);
if ('#' == acStart[0] || '\000' == acStart[0]) {
continue;
}
if ('%' == acStart[0] && '%' == acStart[1] && '\000' == acStart[2]) {
break;
}
if ( (char *)0 == strchr(acStart, ':') &&
(char *)0 != (pcLine = strchr(acStart, '=')) ) {
*pcLine++ = '\000';
acStart = pruneSpace( acStart );
pcLine = pruneSpace( pcLine );
if ( 0 == strcmp(acStart, "LOGDIR") ) {
(void)strcpy(LogDirectory, pcLine);
} else if ( 0 == strcmp(acStart, "TIMESTAMP") ) {
if ( parseMark(pcFile, iLine, pcLine, tyme, NULL) )
(void)strcpy(defMark, pcLine);
else
defMark[0] = '\000';
} else if ( 0 == strcmp(acStart, "DOMAINHACK") ) {
domainHack = 1;
} else {
Error( "%s(%d) unknown variable `%s'", pcFile, iLine, acStart);
}
continue;
}
if ( (char *)0 == (pcLine = strchr(acStart, ':')) ||
(char *)0 == (pcMode = strchr(pcLine+1, ':')) ||
(char *)0 == (pcLog = strchr(pcMode+1, ':'))) {
Error( "%s(%d) bad config line `%s'", pcFile, iLine, acIn);
continue;
}
*pcLine++ = '\000';
*pcMode++ = '\000';
*pcLog++ = '\000';
acStart = pruneSpace( acStart );
pcLine = pruneSpace( pcLine );
pcMode = pruneSpace( pcMode );
pcLog = pruneSpace( pcLog );
if ((char *)0 != (pcMark = strchr(pcLog, ':'))) {
*pcMark++ = '\000';
pcMark = pruneSpace( pcMark );
/* Skip null intervals */
if ( pcMark[0] == '\000' ) pcMark = (char *)0;
}
/* if this server remote?
* (contains an '@host' where host is not us)
* if so just add it to a linked list of remote hosts
* I'm sure most sites will never use this code (ksb)
*/
if ((char *)0 != (pcRem = strchr(pcLine, '@'))) {
auto struct hostent *hpMe;
*pcRem++ = '\000';
pcLine = pruneSpace( pcLine );
pcRem = pruneSpace( pcRem );
if ((struct hostent *)0 ==
(hpMe = gethostbyname(pcRem))) {
Error( "gethostbyname(%s): %s", pcRem, hstrerror(h_errno));
exit(1);
}
if (4 != hpMe->h_length ||
AF_INET != hpMe->h_addrtype) {
Error( "wrong address size (4 != %d) or address family (%d != %d)", hpMe->h_length, AF_INET, hpMe->h_addrtype);
exit(1);
}
if ( 0 !=
#if HAVE_MEMCMP
memcmp(&acMyAddr[0], hpMe->h_addr, hpMe->h_length)
#else
bcmp(&acMyAddr[0], hpMe->h_addr, hpMe->h_length)
#endif
) {
register REMOTE *pRCTemp;
pRCTemp = (REMOTE *)calloc(1, sizeof(REMOTE));
if ((REMOTE *)0 == pRCTemp) {
CSTROUT(2, "out of memory!\n");
exit(32);
}
(void)strcpy(pRCTemp->rhost, pcRem);
(void)strcpy(pRCTemp->rserver, acStart);
*ppRC = pRCTemp;
ppRC = & pRCTemp->pRCnext;
if (fVerbose) {
Info("%s remote on %s", acStart, pcRem);
}
continue;
}
}
/* take the same group as the last line, by default
*/
if (MAXMEMB == pGEAll[iG].imembers) {
++iG;
}
if (iG < minG || iG >= MAXGRP) {
Error( "%s(%d) group number out of bounds %d <= %d < %d", pcFile, iLine, minG, iG, MAXGRP);
exit(1);
}
minG = iG;
pGE = pGEAll+iG;
if (0 == pGE->imembers++) {
pGE->pCElist = pCE;
}
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);
}
/* fill in the console entry
*/
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);
exit(1);
}
(void)strcpy(pCE->server, acStart);
/*
* Here we substitute the console name for any '&' character in the
* logfile name. That way you can just have something like
* "/var/console/&" for each of the conserver.cf entries.
*/
*(pCE->lfile) = '\000';
pcStart = pcLog;
while ((char *)0 != (pcRem = strchr(pcStart, '&'))) {
*pcRem = '\000';
(void)strcat(pCE->lfile, pcStart);
(void)strcat(pCE->lfile, acStart);
pcStart = pcRem + 1;
}
(void)strcat(pCE->lfile, pcStart);
if ( LogDirectory[0] && (pCE->lfile)[0] != '/' ) {
char lfile[MAXLOGLEN];
strcpy( lfile, pCE->lfile );
strcpy( pCE->lfile, LogDirectory );
strcat( pCE->lfile, "/" );
strcat( pCE->lfile, lfile );
}
if ( pcMark ) {
(void)parseMark(pcFile, iLine, pcMark, tyme, pCE);
} else {
(void)parseMark(pcFile, iLine, defMark, tyme, pCE);
}
if (pcLine[0] == '!')
{
pCE->isNetworkConsole = 1;
strcpy(pCE->networkConsoleHost, pcLine + 1);
pCE->networkConsolePort = atoi(pcMode);
if (fVerbose) {
Info("%s is network on %s/%d logged to %s",
acStart, pCE->networkConsoleHost,
pCE->networkConsolePort, pCE->lfile);
}
pCE->fvirtual = 0;
sprintf( pCE->dfile, "%s/%d", pCE->networkConsoleHost, pCE->networkConsolePort );
pCE->pbaud = FindBaud("Netwk");
pCE->pparity = FindParity(" ");
}
else if ('|' == pcLine[0]) {
pCE->isNetworkConsole = 0;
pCE->fvirtual = 1;
if ((char *)0 == (pCE->pccmd = malloc((strlen(pcLine)|7)+1))) {
OutOfMem();
}
(void)strcpy(pCE->pccmd, pcLine+1);
(void)strcpy(pCE->dfile, "/dev/null");
(void)strcpy(pCE->acslave, "/dev/null");
} else {
pCE->isNetworkConsole = 0;
pCE->fvirtual = 0;
(void)strcpy(pCE->dfile, pcLine);
}
pCE->ipid = -1;
if (!pCE->isNetworkConsole)
{
/* find user baud and parity
* default to first table entry for baud and parity
*/
pCE->pbaud = FindBaud(pcMode);
pCE->pparity = FindParity(pcMode);
if (fVerbose) {
if (pCE->fvirtual)
Info("%s with command `%s' logged to %s", acStart, pCE->pccmd, pCE->lfile);
else
Info("%s is on %s (%s%c) logged to %s", acStart, pCE->dfile, pCE->pbaud->acrate, pCE->pparity->ckey, pCE->lfile);
}
}
++pCE, ++iLocal;
if ('#' == acStart[0] || '\000' == acStart[0]) {
continue;
}
*ppRC = (REMOTE *)0;
if ('%' == acStart[0] && '%' == acStart[1] && '\000' == acStart[2]) {
break;
}
if ((char *)0 == strchr(acStart, ':') &&
(char *)0 != (pcLine = strchr(acStart, '='))) {
*pcLine++ = '\000';
acStart = pruneSpace(acStart);
pcLine = pruneSpace(pcLine);
if (0 == strcmp(acStart, "LOGDIR")) {
(void)strcpy(LogDirectory, pcLine);
} else if (0 == strcmp(acStart, "TIMESTAMP")) {
if (parseMark(pcFile, iLine, pcLine, tyme, NULL))
(void)strcpy(defMark, pcLine);
else
defMark[0] = '\000';
} else if (0 == strcmp(acStart, "DOMAINHACK")) {
domainHack = 1;
} else {
Error("%s(%d) unknown variable `%s'", pcFile, iLine,
acStart);
}
continue;
}
if ((char *)0 == (pcLine = strchr(acStart, ':')) ||
(char *)0 == (pcMode = strchr(pcLine + 1, ':')) ||
(char *)0 == (pcLog = strchr(pcMode + 1, ':'))) {
Error("%s(%d) bad config line `%s'", pcFile, iLine, acIn);
continue;
}
*pcLine++ = '\000';
*pcMode++ = '\000';
*pcLog++ = '\000';
/* make a vector of access restructions
acStart = pruneSpace(acStart);
pcLine = pruneSpace(pcLine);
pcMode = pruneSpace(pcMode);
pcLog = pruneSpace(pcLog);
if ((char *)0 != (pcMark = strchr(pcLog, ':'))) {
*pcMark++ = '\000';
pcLog = pruneSpace(pcLog);
pcMark = pruneSpace(pcMark);
/* Skip null intervals */
if (pcMark[0] == '\000')
pcMark = (char *)0;
}
/* if this server remote?
* (contains an '@host' where host is not us)
* if so just add it to a linked list of remote hosts
* I'm sure most sites will never use this code (ksb)
*/
iG = iAccess = 0;
pACList = (ACCESS *)0;
while (fgets(acIn, sizeof(acIn)-1, fp) != NULL) {
register char *pcMach, *pcNext, *pcMem;
auto char cType;
auto int iLen;
if ((char *)0 != (pcRem = strchr(pcLine, '@'))) {
struct hostent *hpMe;
++iLine;
*pcRem++ = '\000';
pcLine = pruneSpace(pcLine);
pcRem = pruneSpace(pcRem);
acStart = pruneSpace( acIn );
if ((struct hostent *)0 == (hpMe = gethostbyname(pcRem))) {
Error("gethostbyname(%s): %s", pcRem, hstrerror(h_errno));
exit(EX_UNAVAILABLE);
}
if (4 != hpMe->h_length || AF_INET != hpMe->h_addrtype) {
Error
("wrong address size (4 != %d) or address family (%d != %d)",
hpMe->h_length, AF_INET, hpMe->h_addrtype);
exit(EX_UNAVAILABLE);
}
if ('#' == acStart[0] || '\000' == acStart[0]) {
continue;
}
if ('%' == acStart[0] && '%' == acStart[1] && '\000' == acStart[2]) {
break;
}
if ((char *)0 == (pcNext = strchr(acStart, ':'))) {
Error( "%s(%d) missing colon?", pcFile, iLine);
exit(3);
}
if (0 !=
#if HAVE_MEMCMP
memcmp(&acMyAddr.s_addr, hpMe->h_addr, hpMe->h_length)
#else
bcmp(&acMyAddr.s_addr, hpMe->h_addr, hpMe->h_length)
#endif
) {
do {
*pcNext++ = '\000';
} while (isspace((int)(*pcNext)));
switch (acStart[0]) {
case 'a': /* allowed, allow, allows */
case 'A':
cType = 'a';
break;
case 'r': /* rejected, refused, refuse */
case 'R':
cType = 'r';
break;
case 't': /* trust, trusted, trusts */
case 'T':
cType = 't';
break;
default:
Error( "%s(%d) unknown access key `%s\'", pcFile, iLine, acStart);
exit(3);
REMOTE *pRCTemp;
pRCTemp = (REMOTE *) calloc(1, sizeof(REMOTE));
if ((REMOTE *) 0 == pRCTemp) {
OutOfMem();
}
while ('\000' != *(pcMach = pcNext)) {
while ('\000' != *pcNext && !isspace((int)(*pcNext))) {
++pcNext;
}
while ('\000' != *pcNext && isspace((int)(*pcNext))) {
*pcNext++ = '\000';
}
if (iAccess < iG) {
/* still have room */;
} else if (0 != iG) {
iG += 8;
pACList = (ACCESS *)realloc((char *)pACList, iG * sizeof(ACCESS));
} else {
iG = MAXGRP;
pACList = (ACCESS *)malloc(iG * sizeof(ACCESS));
}
if ((ACCESS *)0 == pACList) {
OutOfMem();
}
/* use loopback interface for local connections
if (0 == strcmp(pcMach, acMyHost)) {
pcMach = "127.0.0.1";
}
*/
iLen = strlen(pcMach);
if ((char *)0 == (pcMem = malloc(iLen+1))) {
OutOfMem();
}
pACList[iAccess].ctrust = cType;
pACList[iAccess].ilen = iLen;
pACList[iAccess].pcwho = strcpy(pcMem, pcMach);
++iAccess;
(void)strcpy(pRCTemp->rhost, pcRem);
(void)strcpy(pRCTemp->rserver, acStart);
*ppRC = pRCTemp;
ppRC = &pRCTemp->pRCnext;
if (fVerbose) {
Info("%s remote on %s", acStart, pcRem);
}
continue;
}
}
/* take the same group as the last line, by default
*/
if (MAXMEMB == pGEAll[iG].imembers) {
++iG;
}
if (iG < minG || iG >= MAXGRP) {
Error("%s(%d) group number out of bounds %d <= %d < %d",
pcFile, iLine, minG, iG, MAXGRP);
exit(EX_UNAVAILABLE);
}
minG = iG;
pGE = pGEAll + iG;
if (0 == pGE->imembers++) {
pGE->pCElist = pCE;
}
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);
}
/* fill in the console entry
*/
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);
exit(EX_UNAVAILABLE);
}
(void)strcpy(pCE->server, acStart);
/*
* Here we substitute the console name for any '&' character in the
* logfile name. That way you can just have something like
* "/var/console/&" for each of the conserver.cf entries.
*/
*(pCE->lfile) = '\000';
pcStart = pcLog;
while ((char *)0 != (pcRem = strchr(pcStart, '&'))) {
*pcRem = '\000';
(void)strcat(pCE->lfile, pcStart);
(void)strcat(pCE->lfile, acStart);
pcStart = pcRem + 1;
}
(void)strcat(pCE->lfile, pcStart);
if (LogDirectory[0] && (pCE->lfile)[0] != '/') {
char lfile[MAXLOGLEN];
strcpy(lfile, pCE->lfile);
strcpy(pCE->lfile, LogDirectory);
strcat(pCE->lfile, "/");
strcat(pCE->lfile, lfile);
}
if (pcMark) {
(void)parseMark(pcFile, iLine, pcMark, tyme, pCE);
} else {
(void)parseMark(pcFile, iLine, defMark, tyme, pCE);
}
if (pcLine[0] == '!') {
pcLine = pruneSpace(pcLine + 1);
pCE->isNetworkConsole = 1;
pCE->telnetState = 0;
strcpy(pCE->networkConsoleHost, pcLine);
pCE->networkConsolePort = atoi(pcMode);
if (fVerbose) {
Info("%s is network on %s/%d logged to %s", acStart,
pCE->networkConsoleHost, pCE->networkConsolePort,
pCE->lfile);
}
pCE->fvirtual = 0;
sprintf(pCE->dfile, "%s/%d", pCE->networkConsoleHost,
pCE->networkConsolePort);
pCE->pbaud = FindBaud("Netwk");
pCE->pparity = FindParity(" ");
} else if ('|' == pcLine[0]) {
pcLine = pruneSpace(pcLine + 1);
pCE->isNetworkConsole = 0;
pCE->telnetState = 0;
pCE->fvirtual = 1;
if ((char *)0 ==
(pCE->pccmd = malloc((strlen(pcLine) | 7) + 1))) {
OutOfMem();
}
(void)strcpy(pCE->pccmd, pcLine);
(void)strcpy(pCE->dfile, "/dev/null");
(void)strcpy(pCE->acslave, "/dev/null");
} else {
pCE->isNetworkConsole = 0;
pCE->telnetState = 0;
pCE->fvirtual = 0;
(void)strcpy(pCE->dfile, pcLine);
}
pCE->ipid = -1;
if (!pCE->isNetworkConsole) {
/* find user baud and parity
* default to first table entry for baud and parity
*/
pCE->pbaud = FindBaud(pcMode);
pCE->pparity = FindParity(pcMode);
if (fVerbose) {
if (pCE->fvirtual)
Info("%s with command `%s' logged to %s", acStart,
pCE->pccmd, pCE->lfile);
else
Info("%s is on %s (%s%c) logged to %s", acStart,
pCE->dfile, pCE->pbaud->acrate,
pCE->pparity->ckey, pCE->lfile);
}
}
++pCE, ++iLocal;
}
*ppRC = (REMOTE *) 0;
/* make a vector of access restructions
*/
iG = iAccess = 0;
pACList = (ACCESS *) 0;
while (fgets(acIn, sizeof(acIn) - 1, fp) != NULL) {
char *pcMach, *pcNext, *pcMem;
char cType;
int iLen;
++iLine;
acStart = pruneSpace(acIn);
if ('#' == acStart[0] || '\000' == acStart[0]) {
continue;
}
if ('%' == acStart[0] && '%' == acStart[1] && '\000' == acStart[2]) {
break;
}
if ((char *)0 == (pcNext = strchr(acStart, ':'))) {
Error("%s(%d) missing colon?", pcFile, iLine);
exit(EX_UNAVAILABLE);
}
do {
*pcNext++ = '\000';
} while (isspace((int)(*pcNext)));
switch (acStart[0]) {
case 'a': /* allowed, allow, allows */
case 'A':
cType = 'a';
break;
case 'r': /* rejected, refused, refuse */
case 'R':
cType = 'r';
break;
case 't': /* trust, trusted, trusts */
case 'T':
cType = 't';
break;
default:
Error("%s(%d) unknown access key `%s\'", pcFile, iLine,
acStart);
exit(EX_UNAVAILABLE);
}
while ('\000' != *(pcMach = pcNext)) {
int j, isCIDR = 0;
while ('\000' != *pcNext &&
!(isspace((int)(*pcNext)) || ',' == *pcNext)) {
++pcNext;
}
while ('\000' != *pcNext &&
(isspace((int)(*pcNext)) || ',' == *pcNext)) {
*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) {
/* still have room */ ;
} else if (0 != iG) {
iG += 8;
pACList =
(ACCESS *) realloc((char *)pACList,
iG * sizeof(ACCESS));
} else {
iG = MAXGRP;
pACList = (ACCESS *) malloc(iG * sizeof(ACCESS));
}
if ((ACCESS *) 0 == pACList) {
OutOfMem();
}
/* use loopback interface for local connections
if (0 == strcmp(pcMach, acMyHost)) {
pcMach = "127.0.0.1";
}
*/
iLen = strlen(pcMach);
if ((char *)0 == (pcMem = malloc(iLen + 1))) {
OutOfMem();
}
pACList[iAccess].ctrust = cType;
pACList[iAccess].ilen = iLen;
pACList[iAccess].pcwho = strcpy(pcMem, pcMach);
pACList[iAccess].isCIDR = isCIDR;
++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
*
@ -38,18 +38,14 @@
* from a file, into these structures
*/
extern GRPENT
aGroups[MAXGRP]; /* group info */
extern CONSENT
aConsoles[MAXGRP*MAXMEMB]; /* console list */
extern REMOTE
*pRCList; /* list of remote consoles we know about */
extern ACCESS
*pACList; /* `who do you love' (or trust) */
extern GRPENT aGroups[MAXGRP]; /* group info */
extern CONSENT aConsoles[MAXGRP * MAXMEMB]; /* console list */
extern REMOTE *pRCList; /* list of remote consoles we know about */
extern ACCESS *pACList; /* `who do you love' (or trust) */
extern int
iAccess; /* how many access restrictions we have */
iAccess; /* how many access restrictions we have */
extern int
iLocal; /* how many local consoles we have */
iLocal; /* how many local consoles we have */
extern void ReadCfg();

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
*
@ -14,4 +14,4 @@
@(#) Copyright 2000 conserver.com.\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
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
ALL = console
all: $(ALL)
.PHONY: clean distclean install
console: $(CONSOLE_OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o console $(CONSOLE_OBJS) $(LIBS)
../conserver/output.o:
( cd ../conserver && $(MAKE) $(MAKE_FLAGS) output.o ) || exit 1;
../conserver/util.o:
( cd ../conserver && $(MAKE) $(MAKE_FLAGS) util.o ) || exit 1;
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
@ -55,3 +53,4 @@ install: console
$(MKDIR) $(DESTDIR)$(mandir)/man1
$(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 $
.TH CONSOLE 8 "Local"
.\" $Id: console.man,v 1.11 2001-07-26 10:25:24-07 bryan Exp $
.TH CONSOLE 1 "Local"
.SH NAME
console \- console server client program
.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
\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
\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
.B Console
is used to manipulate console terminals remotely or poll running
\fIconserver\fP(8) daemons for status information.
is used to manipulate console terminals remotely or to poll running
\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
.B Console
queries the user for the their passwd before
granting interactive access to a console (on a non-trusted system)
since such a session may provide single-user access.
.PP
In the non-interactive mode
knows only of a primary
.B conserver
host
(see the \fB\-M\fP option below),
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
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
.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
.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
.BI \-b message
Broadcast a \fImessage\fP to all users connected to the console server.
.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
Same as \fB\-d\fP but just acts on the local server.
Enable debugging output.
.TP
.BI \-e esc
Set the initial two character escape sequence to
Set the initial two-character escape sequence to
those represented by \fIesc\fP.
Any of the forms output by \fIcat\fP(1)'s \-\fBv\fP option
are accepted. The default value is ``^Ec''.
Any of the forms output by \fBcat\fP(1)'s \-\fBv\fP option
are accepted. The default value is ``\fB^Ec\fP''.
.TP
.B \-f
Same as \fB\-a\fP except it will force any existing connection into spy mode.
.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
Display a brief help message.
.TP
.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
.BI \-M mach
The \fIconsole\fP client program polls \fImach\fP as the primary server,
rather than the hard coded default (``console'').
The \fBconsole\fP client program polls \fImach\fP as the primary server,
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
.BI \-p port
Set the port to connect to. The default \fIport\fP is set at compile time
using the --with-port option.
Set the port to connect to. This may be either a port number
or a service name. The default \fIport\fP may be changed at compile time
using the \fB--with-port\fP option.
.TP
.B \-P
Display the pids of the master daemon processes.
Display the pid of the master daemon process on each server.
.TP
.B \-q
The \fIconsole\fP client requests the server daemon quit (shutdown).
A password is sent in the protocol stream, if none is required for
the local host to shutdown the server just press return.
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
the local host to shut down the server, just press <return>.
.TP
.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
.B \-r
Request a raw connection to the group control virtual console,
this is only useful for learning the protocol used by the
interactive sequence.
Display daemon versions. The \fBconsole\fP client connects to each
server to request its version information.
.TP
.B \-R
Same as \fB\-r\fP but just acts on the primary server.
.TP
.B \-s
Requests a read-only (spy mode) connection.
If this mode all the escape sequences (below) work, or report errors,
Request a read-only (spy mode) connection.
In this mode all the escape sequences (below) work, or report errors,
but all other keyboard input is discarded.
.TP
.B \-u
Show a list of all consoles with status and attached users.
.TP
.B \-U
Same as \fB\-u\fP.
.TP
.B \-V
Output the version of the console client program.
Show a list of all consoles with status (`up' or `down')
and attached users (\fIuser\fP@\fIhost\fP if attached read-write,
`<spies>' if only users in spy mode, or `<none>').
.TP
.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)
for added benefit.
.TP
.B \-w
Show a list of all connections to consoles.
.B \-V
Output the version and settings of the console client program
and then exit.
.TP
.B \-W
Same as \fB\-w\fP.
.B \-w
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
.B \-x
Show a list of consoles and devices.
.PP
The \fB\-A\fP, \fB\-F\fP, or \fB\-S\fP options have the same effect as
their lower case variants.
In addition they each request the last 20 lines of the console output after
making the connection.
.PP
Any default (\fB\-a\fP) connection is dropped to spy mode if
someone else is attached read-write.
their lower-case variants.
In addition, they each request the last 20 lines of the console output after
making the connection (as if `\fB^Ecr\fP' were typed).
.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''
(octal 005 143). Commands are:
.sp
.TS
c l.
a switch to attach mode
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
(octal 005 143).
(The escape sequences are actually processed by the server; see the
.BR conserver (8)
man page for more information.)
Commands are:
.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
If any other character is hit after the escape sequence, all three characters
will be discarded.
Note that a line break or a down command
can only be sent from a full two-way attachment.
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
In the \-u output, the login \fB<none>\fP indicates no one is
viewing that console, the login \fB<spies>\fP indicates that
In the \fB\-u\fP output, the login ``<none>'' indicates no one is
viewing that console, and the login ``<spies>'' indicates that
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
.TP
console \-u
Outputs something like:
.sp
.RS
.TS
l18 l l.
.ta 18n 24n
dumb up <none>
.br
expert up ksb@mentor
.br
tyro up <spies>
.br
mentor up <none>
.br
sage up fine@cis
.TE
.DT
.RE
.sp
.IP
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,
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.
.TP
console \-w
Outputs something like:
.sp
.RS
.TS
l18 l l.
ksb@extra attach 2days expert
file@cis attach 21:46 sage
dmr@alice spy 0:04 tyro
.TE
.ta 18n 26n 32n
ksb@extra attach 2days expert
.br
file@cis attach 21:46 sage
.br
dmr@alice spy \00:04 tyro
.DT
.RE
.sp
The third column is the idle time of the user. Either hours:minutes or number
of days is displayed.
.IP
The third column is the idle time of the user.
Either \fIhours\fP:\fIminutes\fP or number of days is displayed.
.TP
console \-e \*(lq^[1\*(rq lv426
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.
.PP
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).
.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
Thomas A. Fine, Ohio State Computer Science.
Thomas A. Fine, Ohio State Computer Science
.br
Kevin Braunsdorf, Purdue University Computing Center
.br
Bryan Stansell, conserver.com
.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
start)
echo -n "Starting conserver: "
daemon conserver -d -n
daemon conserver -d
echo
touch /var/lock/subsys/conserver
;;

View File

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

View File

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