mirror of
https://github.com/bstansell/conserver.git
synced 2024-12-19 21:07:54 +00:00
Imported from conserver-7.1.0.tar.gz
This commit is contained in:
parent
6617579233
commit
4a15f7082e
58
CHANGES
58
CHANGES
@ -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
45
INSTALL
@ -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 $
|
||||
#
|
||||
|
@ -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
24
TODO
@ -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 $
|
||||
#
|
||||
|
10
acconfig.h
10
acconfig.h
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
65
compat.h
65
compat.h
@ -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
|
||||
|
371
config.h.in
371
config.h.in
@ -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
|
||||
|
||||
|
48
configure.in
48
configure.in
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
65
conserver.cf/conserver.passwd.man
Normal file
65
conserver.cf/conserver.passwd.man
Normal 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.
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
1111
conserver/consent.c
1111
conserver/consent.c
File diff suppressed because it is too large
Load Diff
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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')
|
||||
|
@ -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;
|
||||
}
|
||||
|
3075
conserver/group.c
3075
conserver/group.c
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
|
||||
|
||||
|
681
conserver/main.c
681
conserver/main.c
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
@ -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;
|
@ -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...
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
484
conserver/util.c
Normal 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
54
conserver/util.h
Normal 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();
|
@ -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"
|
||||
|
@ -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
|
||||
|
2012
console/console.c
2012
console/console.c
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||
|
@ -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
|
||||
;;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user