*BSD News Article 82905


Return to BSD News archive

Newsgroups: comp.bugs.2bsd
Path: euryale.cc.adfa.oz.au!newshost.carno.net.au!harbinger.cc.monash.edu.au!news.mira.net.au!news.netspace.net.au!news.mel.connect.com.au!munnari.OZ.AU!spool.mu.edu!uwm.edu!chi-news.cic.net!feed1.news.erols.com!howland.erols.net!news.mathworks.com!uunet!in3.uu.net!nntp.netrex.net!wlbr!moe.2bsd.com!sms
From: sms@moe.2bsd.com (Steven M. Schultz)
Subject: inetd(8) with tcpmux support (#343)
Organization: 2BSD, Simi Valley CA USA
Message-ID: <E0wAxv.9oA@moe.2bsd.com>
Date: Fri, 15 Nov 1996 04:53:55 GMT
Lines: 2280

Subject: inetd(8) with tcpmux support (#343)
Index:	usr.sbin/inetd 2.11BSD

Description:
	The version of inetd(8) in 2.11BSD is the old 4.3BSD version
	which lacks 'tcpmux' support.

Repeat-By:
	Observation.

	Or by enabling tcpmux (tcp port 1) service in /etc/inetd.conf (and
	adding 'tcpmux' to /etc/services) and noting the errors.

Fix:
	The fix was to simply port over the 4.4BSD inetd program from the
	4.4-Lite2 CDrom.  Very few changes were needed - just a couple
	tweeks to compensate for the normal long.vs.int and lack of function
	prototypes.  Register declarations were also added (which reduced
	the size of the program by quite a bit).

	Since this is a complete replacement this is a good time to move
	'inetd' out of /etc (one less program to worry about later on).  This
	means that /etc/rc needs to be updated.

	To install the new version of inetd, cut where indicated and save
	to a file (/tmp/343).  Then:

		cd /tmp
		sh 343
		sh 343.shar
		patch -p0 < 343.patch
		cd /usr/src/usr.sbin/inetd
		make
		make install
		make clean
	
	NOTE:  The patch to inetd.conf may not succeed if your inetd.conf
	       is too different from mine.

		It is possible to 'frontend' tcpmux service with the TCP-
		wrapper program ('tcpd') on a per tcpmux service basis.

	Then kill the currently running 'inetd' process.  Start the new
	one by:

		/usr/sbin/inetd

	Finally clean up by running the provided shell script or executing
	the commands manually:

		sh /tmp/343.sh

	(this removes the old executable, manpage and source file).

	You're all done.  All that's left is to enable 'tcpmux' service if
	you wish to do so.  The manpage provides good examples on how to
	do this.

	As always this and previous updates to 2.11BSD are available via
	anonymous FTP to either FTP.IIPO.GTEGSC.COM or MOE.2BSD.COM in the
	directory /pub/2.11BSD.

==============================cut here======================
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	343.sh
#	343.shar
#	343.patch
# This archive created: Thu Nov 14 20:15:49 1996
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f '343.sh'
then
	echo shar: "will not over-write existing file '343.sh'"
else
sed 's/^Z//' << \SHAR_EOF > '343.sh'
Z#!/bin/sh
Z
Zrm /etc/inetd
Zrm /usr/src/man/man8/inetd.8
Zrm /usr/src/etc/inetd.c
SHAR_EOF
fi
if test -f '343.shar'
then
	echo shar: "will not over-write existing file '343.shar'"
else
sed 's/^Z//' << \SHAR_EOF > '343.shar'
Z#! /bin/sh
Z# This is a shell archive, meaning:
Z# 1. Remove everything above the #! /bin/sh line.
Z# 2. Save the resulting text in a file.
Z# 3. Execute the file with /bin/sh (not csh) to create:
Z#	/usr/src/usr.sbin/inetd
Z# This archive created: Wed Nov 13 21:53:16 1996
Zexport PATH; PATH=/bin:/usr/bin:$PATH
Zif test ! -d '/usr/src/usr.sbin/inetd'
Zthen
Z	mkdir '/usr/src/usr.sbin/inetd'
Zfi
Zcd '/usr/src/usr.sbin/inetd'
Zif test -f 'Makefile'
Zthen
Z	echo shar: "will not over-write existing file 'Makefile'"
Zelse
Zsed 's/^X//' << \SHAR_EOF > 'Makefile'
ZX#
ZX# Public Domain.  1996/11/6 - Steven Schultz
ZX#
ZX#	@(#)Makefile	1.1 (2.11BSD) 1996/11/13
ZX#
ZXCFLAGS=	 -O
ZXSEPFLAG= -i
ZXSRCS=	inetd.c
ZXOBJS=	inetd.o
ZXMAN=	inetd.0
ZXMANSRC=	inetd.8
ZX
ZXall: inetd inetd.0
ZX
ZXinetd: ${OBJS}
ZX	${CC} ${CFLAGS} ${SEPFLAG} -o $@ ${OBJS}
ZX
ZXinetd.0: ${MANSRC}
ZX	/usr/man/manroff ${MANSRC} > ${MAN}
ZX
ZXclean:
ZX	rm -f ${OBJS} ${MAN} inetd tags 
ZX
ZXdepend: ${SRCS}
ZX	mkdep ${CFLAGS} ${SRCS}
ZX
ZXinstall: inetd
ZX	install -c -o bin -g bin -m 444 ${MAN} ${DESTDIR}/usr/man/cat8
ZX	install -s -o root -g bin -m 755 inetd ${DESTDIR}/usr/sbin/inetd
ZX
ZXlint: ${SRCS}
ZX	lint -hax ${SRCS}
ZX
ZXtags: ${SRCS}
ZX	ctags ${SRCS}
ZX# DO NOT DELETE THIS LINE -- mkdep uses it.
ZX# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
ZSHAR_EOF
Zchmod 644 'Makefile'
Zfi
Zif test -f 'inetd.8'
Zthen
Z	echo shar: "will not over-write existing file 'inetd.8'"
Zelse
Zsed 's/^X//' << \SHAR_EOF > 'inetd.8'
ZX.\" Copyright (c) 1985, 1991, 1993, 1994
ZX.\"	The Regents of the University of California.  All rights reserved.
ZX.\"
ZX.\" Redistribution and use in source and binary forms, with or without
ZX.\" modification, are permitted provided that the following conditions
ZX.\" are met:
ZX.\" 1. Redistributions of source code must retain the above copyright
ZX.\"    notice, this list of conditions and the following disclaimer.
ZX.\" 2. Redistributions in binary form must reproduce the above copyright
ZX.\"    notice, this list of conditions and the following disclaimer in the
ZX.\"    documentation and/or other materials provided with the distribution.
ZX.\" 3. All advertising materials mentioning features or use of this software
ZX.\"    must display the following acknowledgement:
ZX.\"	This product includes software developed by the University of
ZX.\"	California, Berkeley and its contributors.
ZX.\" 4. Neither the name of the University nor the names of its contributors
ZX.\"    may be used to endorse or promote products derived from this software
ZX.\"    without specific prior written permission.
ZX.\"
ZX.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
ZX.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
ZX.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ZX.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
ZX.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
ZX.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
ZX.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ZX.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
ZX.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
ZX.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
ZX.\" SUCH DAMAGE.
ZX.\"
ZX.\"     @(#)inetd.8	8.4.1 (2.11BSD) 1996/11/7
ZX.\"
ZX.TH INETD 8 "November 7, 1996"
ZX.UC 7
ZX.SH NAME
ZX\fBinetd\fP \- internet ``super-server''
ZX.SH SYNOPSIS
ZX.B inetd
ZX[\fB\-d\fP]
ZX[\fB\-R\fP \fIrate\fP]
ZX[\fIconfiguration file\fP]
ZX.SH DESCRIPTION
ZXThe
ZX.B inetd
ZXprogram
ZXshould be run at boot time by
ZX.I /etc/rc
ZX(see rc(8)).
ZXIt then listens for connections on certain
ZXinternet sockets.  When a connection is found on one
ZXof its sockets, it decides what service the socket
ZXcorresponds to, and invokes a program to service the request.
ZXThe server program is invoked with the service socket
ZXas its standard input, output and error descriptors.
ZXAfter the program is
ZXfinished,
ZX.B inetd
ZXcontinues to listen on the socket (except in some cases which
ZXwill be described below).  Essentially,
ZX.B inetd
ZXallows running one daemon to invoke several others,
ZXreducing load on the system.
ZX.PP
ZXThe options available for
ZX.B inetd:
ZX.TP 10
ZX.B \-d
ZXTurns on debugging.
ZX.TP 10
ZX\fB\-R\fP \fIrate\fP
ZXSpecifies the maximum number of times a service can be invoked
ZXin one minute; the default is 1000.
ZX.PP
ZXUpon execution,
ZX.B inetd
ZXreads its configuration information from a configuration
ZXfile which, by default, is
ZX\fI/etc/inetd.conf\fP.
ZXThere must be an entry for each field of the configuration
ZXfile, with entries for each field separated by a tab or
ZXa space.  Comments are denoted by a ``#'' at the beginning
ZXof a line.  There must be an entry for each field.  The
ZXfields of the configuration file are as follows:
ZX.PP
ZX.in +0.5i
ZX.nf
ZXservice name
ZXsocket type
ZXprotocol
ZXwait/nowait
ZXuser
ZXserver program
ZXserver program arguments
ZX.br
ZX.fi
ZX.in -0.5i
ZX.PP
ZXThere are two types of services that 
ZX.B inetd
ZXcan start: standard and TCPMUX.
ZXA standard service has a well-known port assigned to it;
ZXit may be a service that implements an official Internet standard or is a
ZXBSD-specific service.
ZXAs described in 
ZXRFC 1078,
ZXTCPMUX services are nonstandard services that do not have a 
ZXwell-known port assigned to them.
ZXThey are invoked from
ZX.B inetd 
ZXwhen a program connects to the
ZX``tcpmux''
ZXwell-known port and specifies
ZXthe service name.  
ZXThis feature is useful for adding locally-developed servers.
ZX.PP
ZXThe
ZX.I service-name
ZXentry is the name of a valid service in
ZXthe file
ZX.IR /etc/services .
ZXFor
ZX``internal''
ZXservices (discussed below), the service
ZXname
ZX.B must
ZXbe the official name of the service (that is, the first entry in
ZX.IR /etc/services ).
ZXFor TCPMUX services, the value of the
ZX.I service-name
ZXfield consists of the string
ZX``tcpmux''
ZXfollowed by a slash and the
ZXlocally-chosen service name. 
ZXThe service names listed in 
ZX.I /etc/services
ZXand the name 
ZX``help''
ZXare reserved.
ZXTry to choose unique names for your TCPMUX services by prefixing them with
ZXyour organization's name and suffixing them with a version number.
ZX.PP
ZXThe
ZX.I socket-type
ZXshould be one of
ZX``stream'',
ZX``dgram'',
ZX``raw'',
ZX``rdm'',
ZXor
ZX``seqpacket'',
ZXdepending on whether the socket is a stream, datagram, raw,
ZXreliably delivered message, or sequenced packet socket.
ZXTCPMUX services must use 
ZX``stream''.
ZX.sp
ZX\fBNOTE:\fP
ZX``rdm'' and ``seqpacket'' are not supported in 2.11BSD.
ZX.br
ZX.PP
ZXThe
ZX.I protocol
ZXmust be a valid protocol as given in
ZX.IR /etc/protocols .
ZXExamples might be
ZX``tcp''
ZXor
ZX``udp''.
ZXTCPMUX services must use 
ZX``tcp''.
ZX.PP
ZXThe
ZX.I wait/nowait
ZXentry specifies whether the server that is invoked by inetd will take over
ZXthe socket associated with the service access point, and thus whether
ZX.B inetd
ZXshould wait for the server to exit before listening for new service
ZXrequests.
ZXDatagram servers must use
ZX``wait'',
ZXas they are always invoked with the original datagram socket bound
ZXto the specified service address.
ZXThese servers must read at least one datagram from the socket
ZXbefore exiting.
ZXIf a datagram server connects
ZXto its peer, freeing the socket so
ZX.B inetd
ZXcan received further messages on the socket, it is said to be
ZXa
ZX``multi-threaded''
ZXserver;
ZXit should read one datagram from the socket and create a new socket
ZXconnected to the peer.
ZXIt should fork, and the parent should then exit
ZXto allow
ZX.B inetd
ZXto check for new service requests to spawn new servers.
ZXDatagram servers which process all incoming datagrams
ZXon a socket and eventually time out are said to be
ZX``single-threaded''.
ZXComsat(8), biff(1) and talkd(8)
ZXare examples of the latter type of
ZXdatagram server.
ZXTftpd(8)
ZXis an example of a multi-threaded datagram server.
ZX.PP
ZXServers using stream sockets generally are multi-threaded and
ZXuse the
ZX``nowait''
ZXentry.
ZXConnection requests for these services are accepted by
ZX.B inetd ,
ZXand the server is given only the newly-accepted socket connected
ZXto a client of the service.
ZXMost stream-based services operate in this manner.
ZXStream-based servers that use
ZX``wait''
ZXare started with the listening service socket, and must accept
ZXat least one connection request before exiting.
ZXSuch a server would normally accept and process incoming connection
ZXrequests until a timeout.
ZXTCPMUX services must use 
ZX``nowait''.
ZX.PP
ZXThe
ZX.I user
ZXentry should contain the user name of the user as whom the server
ZXshould run.  This allows for servers to be given less permission
ZXthan root.
ZX.PP
ZXThe
ZX.I server-program
ZXentry should contain the pathname of the program which is to be
ZXexecuted by
ZX.B inetd
ZXwhen a request is found on its socket.  If
ZX.B inetd
ZXprovides this service internally, this entry should
ZXbe
ZX``internal''.
ZX.PP
ZXThe
ZX.I server program arguments
ZXshould be just as arguments
ZXnormally are, starting with argv[0], which is the name of
ZXthe program.  If the service is provided internally, the
ZXword
ZX``internal''
ZXshould take the place of this entry.
ZX.PP
ZXThe
ZX.B inetd
ZXprogram
ZXprovides several
ZX``trivial''
ZXservices internally by use of
ZXroutines within itself.  These services are
ZX``echo'',
ZX``discard'',
ZX``chargen''
ZX(character generator),
ZX``daytime''
ZX(human readable time), and
ZX``time''
ZX(machine readable time,
ZXin the form of the number of seconds since midnight, January
ZX1, 1900).  All of these services are tcp based.  For
ZXdetails of these services, consult the appropriate
ZXRFC
ZXfrom the Network Information Center.
ZX.PP
ZXThe
ZX.B inetd
ZXprogram
ZXrereads its configuration file when it receives a hangup signal,
ZXSIGHUP.
ZXServices may be added, deleted or modified when the configuration file
ZXis reread.
ZX.SH TCPMUX
ZX.PP
ZXRFC 1078 
ZXdescribes the TCPMUX protocol:
ZX``A TCP client connects to a foreign host on TCP port 1.  It sends the
ZXservice name followed by a carriage-return line-feed <CRLF>.  The
ZXservice name is never case sensitive.  The server replies with a
ZXsingle character indicating positive (+) or negative (\-)
ZXacknowledgment, immediately followed by an optional message of
ZXexplanation, terminated with a <CRLF>.  If the reply was positive,
ZXthe selected protocol begins; otherwise the connection is closed.''
ZXThe program is passed the TCP connection as file descriptors 0 and 1.
ZX.PP
ZXIf the TCPMUX service name begins with a ``+'',
ZX.B inetd
ZXreturns the positive reply for the program.
ZXThis allows you to invoke programs that use stdin/stdout
ZXwithout putting any special server code in them.
ZX.PP
ZXThe special service name
ZX``help''
ZXcauses
ZX.B inetd
ZXto list TCPMUX services in
ZX.IR inetd.conf .
ZX.SH "EXAMPLES"
ZX.PP
ZXHere are several example service entries for the various types of services:
ZX.sp
ZX.nf
ZXftp           stream  tcp   nowait root  /usr/libexec/ftpd       ftpd -l
ZXntalk         dgram   udp   wait   root  /usr/libexec/ntalkd     ntalkd
ZXtcpmux/+date  stream  tcp   nowait guest /bin/date               date
ZXtcpmux/phonebook stream tcp nowait guest /usr/local/phonebook phonebook
ZX.br
ZX.fi
ZX.SH "ERROR MESSAGES"
ZXThe
ZX.B inetd
ZXserver
ZXlogs error messages using
ZXsyslog(3).
ZXImportant error messages and their explanations are:
ZX.sp
ZX\fIservice\fP/\fIprotocol\fP server failing (looping), service terminated.
ZX.br
ZXThe number of requests for the specified service in the past minute
ZXexceeded the limit. The limit exists to prevent a broken program
ZXor a malicious user from swamping the system.
ZXThis message may occur for several reasons:
ZX1) there are lots of hosts requesting the service within a short time period,
ZX2) a 'broken' client program is requesting the service too frequently,
ZX3) a malicious user is running a program to invoke the service in
ZXa 'denial of service' attack, or
ZX4) the invoked service program has an error that causes clients
ZXto retry quickly.
ZXUse the
ZX\fB\-R\fP
ZXoption,
ZXas described above, to change the rate limit.
ZXOnce the limit is reached, the service will be
ZXreenabled automatically in 10 minutes.
ZX.sp
ZX\fIservice\fP/\fIprotocol\fP: No such user '\fIuser\fP', service ignored
ZX.br
ZX\fIservice\fP/\fIprotocol\fP: getpwnam: \fIuser\fP: No such user
ZX.br
ZXNo entry for 
ZX.I user
ZXexists in the 
ZX.I passwd
ZXfile. The first message
ZXoccurs when
ZX.B inetd
ZX(re)reads the configuration file. The second message occurs when the
ZXservice is invoked.
ZX.sp
ZX\fIservice\fP: can't set uid \fInumber\fP
ZX.br
ZX\fIservice\fP: can't set gid \fInumber\fP
ZX.br
ZXThe user or group ID for the entry's 
ZX.I user
ZXis invalid.
ZX.SH SEE ALSO
ZXcomsat(8),
ZXfingerd(8),
ZXftpd(8),
ZXrexecd(8),
ZXrlogind(8),
ZXrshd(8),
ZXtelnetd(8),
ZXtftpd(8)
ZX.SH HISTORY
ZXThe
ZX.B inetd
ZXcommand appeared in
ZX4.3BSD.
ZXTCPMUX is based on code and documentation by Mark Lottor.
ZSHAR_EOF
Zchmod 644 'inetd.8'
Zfi
Zif test -f 'inetd.c'
Zthen
Z	echo shar: "will not over-write existing file 'inetd.c'"
Zelse
Zsed 's/^X//' << \SHAR_EOF > 'inetd.c'
ZX/*
ZX * Copyright (c) 1983, 1991, 1993, 1994
ZX *	The Regents of the University of California.  All rights reserved.
ZX *
ZX * Redistribution and use in source and binary forms, with or without
ZX * modification, are permitted provided that the following conditions
ZX * are met:
ZX * 1. Redistributions of source code must retain the above copyright
ZX *    notice, this list of conditions and the following disclaimer.
ZX * 2. Redistributions in binary form must reproduce the above copyright
ZX *    notice, this list of conditions and the following disclaimer in the
ZX *    documentation and/or other materials provided with the distribution.
ZX * 3. All advertising materials mentioning features or use of this software
ZX *    must display the following acknowledgement:
ZX *	This product includes software developed by the University of
ZX *	California, Berkeley and its contributors.
ZX * 4. Neither the name of the University nor the names of its contributors
ZX *    may be used to endorse or promote products derived from this software
ZX *    without specific prior written permission.
ZX *
ZX * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
ZX * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
ZX * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ZX * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
ZX * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
ZX * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
ZX * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ZX * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
ZX * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
ZX * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
ZX * SUCH DAMAGE.
ZX */
ZX
ZX#if	!defined(lint) && defined(DOSCCS)
ZXstatic char copyright[] =
ZX"@(#) Copyright (c) 1983, 1991, 1993, 1994\n\
ZX	The Regents of the University of California.  All rights reserved.\n";
ZX
ZXstatic char sccsid[] = "@(#)inetd.c	8.4.1 (2.11BSD) 1996/10/30";
ZX#endif /* not lint */
ZX
ZX/*
ZX * Inetd - Internet super-server
ZX *
ZX * This program invokes all internet services as needed.  Connection-oriented
ZX * services are invoked each time a connection is made, by creating a process.
ZX * This process is passed the connection as file descriptor 0 and is expected
ZX * to do a getpeername to find out the source host and port.
ZX *
ZX * Datagram oriented services are invoked when a datagram
ZX * arrives; a process is created and passed a pending message
ZX * on file descriptor 0.  Datagram servers may either connect
ZX * to their peer, freeing up the original socket for inetd
ZX * to receive further messages on, or ``take over the socket'',
ZX * processing all arriving datagrams and, eventually, timing
ZX * out.	 The first type of server is said to be ``multi-threaded'';
ZX * the second type of server ``single-threaded''. 
ZX *
ZX * Inetd uses a configuration file which is read at startup
ZX * and, possibly, at some later time in response to a hangup signal.
ZX * The configuration file is ``free format'' with fields given in the
ZX * order shown below.  Continuation lines for an entry must being with
ZX * a space or tab.  All fields must be present in each entry.
ZX *
ZX *	service name			must be in /etc/services or must
ZX *					name a tcpmux service
ZX *	socket type			stream/dgram/raw/rdm/seqpacket
ZX *	protocol			must be in /etc/protocols
ZX *	wait/nowait			single-threaded/multi-threaded
ZX *	user				user to run daemon as
ZX *	server program			full path name
ZX *	server program arguments	maximum of MAXARGS (20)
ZX *
ZX * TCP services without official port numbers are handled with the
ZX * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
ZX * requests. When a connection is made from a foreign host, the service
ZX * requested is passed to tcpmux, which looks it up in the servtab list
ZX * and returns the proper entry for the service. Tcpmux returns a
ZX * negative reply if the service doesn't exist, otherwise the invoked
ZX * server is expected to return the positive reply if the service type in
ZX * inetd.conf file has the prefix "tcpmux/". If the service type has the
ZX * prefix "tcpmux/+", tcpmux will return the positive reply for the
ZX * process; this is for compatibility with older server code, and also
ZX * allows you to invoke programs that use stdin/stdout without putting any
ZX * special server code in them. Services that use tcpmux are "nowait"
ZX * because they do not have a well-known port and hence cannot listen
ZX * for new requests.
ZX *
ZX * Comment lines are indicated by a `#' in column 1.
ZX */
ZX#include <sys/param.h>
ZX#include <sys/stat.h>
ZX#include <sys/ioctl.h>
ZX#include <sys/socket.h>
ZX#include <sys/wait.h>
ZX#include <sys/time.h>
ZX#include <sys/resource.h>
ZX
ZX#include <netinet/in.h>
ZX#include <arpa/inet.h>
ZX
ZX#include <errno.h>
ZX#include <fcntl.h>
ZX#include <netdb.h>
ZX#include <pwd.h>
ZX#include <signal.h>
ZX#include <stdio.h>
ZX#include <stdlib.h>
ZX#include <string.h>
ZX#include <syslog.h>
ZX#include <unistd.h>
ZX
ZX#include "pathnames.h"
ZX
ZX#define	TOOMANY		40		/* don't start more than TOOMANY */
ZX#define	CNT_INTVL	60		/* servers in CNT_INTVL sec. */
ZX#define	RETRYTIME	(60*10)		/* retry after bind or server fail */
ZX
ZX#define	SIGBLOCK	(sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
ZX
ZX
ZXint	debug = 0;
ZXint	nsock, maxsock;
ZXfd_set	allsock;
ZXint	options;
ZXint	timingout;
ZXint	toomany = TOOMANY;
ZXstruct	servent *sp;
ZX
ZXstruct	servtab {
ZX	char	*se_service;		/* name of service */
ZX	int	se_socktype;		/* type of socket to use */
ZX	char	*se_proto;		/* protocol used */
ZX	short	se_wait;		/* single threaded server */
ZX	short	se_checked;		/* looked at during merge */
ZX	char	*se_user;		/* user name to run as */
ZX	struct	biltin *se_bi;		/* if built-in, description */
ZX	char	*se_server;		/* server program */
ZX#define	MAXARGV 20
ZX	char	*se_argv[MAXARGV+1];	/* program arguments */
ZX	int	se_fd;			/* open descriptor */
ZX	int	se_type;		/* type */
ZX	struct	sockaddr_in se_ctrladdr;/* bound address */
ZX	int	se_count;		/* number started since se_time */
ZX	struct	timeval se_time;	/* start of se_count */
ZX	struct	servtab *se_next;
ZX} *servtab;
ZX
ZX#define NORM_TYPE	0
ZX#define MUX_TYPE	1
ZX#define MUXPLUS_TYPE	2
ZX#define ISMUX(sep)	(((sep)->se_type == MUX_TYPE) || \
ZX			 ((sep)->se_type == MUXPLUS_TYPE))
ZX#define ISMUXPLUS(sep)	((sep)->se_type == MUXPLUS_TYPE)
ZX
ZX/*
ZX * These four definitions are not present (yet) in 2.11BSD.
ZX * Adding 'register' declarations, using a long 'ltmpint' and declaring a
ZX * couple signal functions 'int' rather than 'void' were the only changes 
ZX * necessary to port the program.
ZX*/
ZX#define	__P(x)	()
ZX#define	memmove(dst,src,len)	bcopy(src,dst,len)
ZX#define	SEEK_SET	0	/* L_SET */
ZX#define	LINE_MAX	1024	/* we don't have this in syslimits.h */
ZX
ZXvoid		chargen_dg __P((int, struct servtab *));
ZXvoid		chargen_stream __P((int, struct servtab *));
ZXvoid		close_sep __P((struct servtab *));
ZXint		config __P((int));
ZXvoid		daytime_dg __P((int, struct servtab *));
ZXvoid		daytime_stream __P((int, struct servtab *));
ZXvoid		discard_dg __P((int, struct servtab *));
ZXvoid		discard_stream __P((int, struct servtab *));
ZXvoid		echo_dg __P((int, struct servtab *));
ZXvoid		echo_stream __P((int, struct servtab *));
ZXvoid		endconfig __P((void));
ZXstruct servtab *enter __P((struct servtab *));
ZXvoid		freeconfig __P((struct servtab *));
ZXstruct servtab *getconfigent __P((void));
ZXvoid		machtime_dg __P((int, struct servtab *));
ZXvoid		machtime_stream __P((int, struct servtab *));
ZXchar	       *newstr __P((char *));
ZXchar	       *nextline __P((FILE *));
ZXvoid		print_service __P((char *, struct servtab *));
ZXint		reapchild __P((int));
ZXint		retry __P((int));
ZXint		setconfig __P((void));
ZXvoid		setup __P((struct servtab *));
ZXchar	       *sskip __P((char **));
ZXchar	       *skip __P((char **));
ZXstruct servtab *tcpmux __P((int));
ZX
ZXstruct biltin {
ZX	char	*bi_service;		/* internally provided service name */
ZX	int	bi_socktype;		/* type of socket supported */
ZX	short	bi_fork;		/* 1 if should fork before call */
ZX	short	bi_wait;		/* 1 if should wait for child */
ZX	void	(*bi_fn)();		/* function which performs it */
ZX} biltins[] = {
ZX	/* Echo received data */
ZX	{ "echo",	SOCK_STREAM,	1, 0,	echo_stream },
ZX	{ "echo",	SOCK_DGRAM,	0, 0,	echo_dg },
ZX
ZX	/* Internet /dev/null */
ZX	{ "discard",	SOCK_STREAM,	1, 0,	discard_stream },
ZX	{ "discard",	SOCK_DGRAM,	0, 0,	discard_dg },
ZX
ZX	/* Return 32 bit time since 1970 */
ZX	{ "time",	SOCK_STREAM,	0, 0,	machtime_stream },
ZX	{ "time",	SOCK_DGRAM,	0, 0,	machtime_dg },
ZX
ZX	/* Return human-readable time */
ZX	{ "daytime",	SOCK_STREAM,	0, 0,	daytime_stream },
ZX	{ "daytime",	SOCK_DGRAM,	0, 0,	daytime_dg },
ZX
ZX	/* Familiar character generator */
ZX	{ "chargen",	SOCK_STREAM,	1, 0,	chargen_stream },
ZX	{ "chargen",	SOCK_DGRAM,	0, 0,	chargen_dg },
ZX
ZX	{ "tcpmux",	SOCK_STREAM,	1, 0,	(void (*)())tcpmux },
ZX
ZX	{ NULL }
ZX};
ZX
ZX#define NUMINT	(sizeof(intab) / sizeof(struct inent))
ZXchar	*CONFIG = _PATH_INETDCONF;
ZXchar	**Argv;
ZXchar 	*LastArg;
ZX
ZXint
ZXmain(argc, argv, envp)
ZX	int argc;
ZX	char *argv[], *envp[];
ZX{
ZX	register struct servtab *sep;
ZX	register struct passwd *pwd;
ZX	struct sigvec sv;
ZX	int tmpint, ch, dofork;
ZX	long ltmpint;
ZX	pid_t pid;
ZX	char buf[50];
ZX
ZX	Argv = argv;
ZX	if (envp == 0 || *envp == 0)
ZX		envp = argv;
ZX	while (*envp)
ZX		envp++;
ZX	LastArg = envp[-1] + strlen(envp[-1]);
ZX
ZX	openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
ZX
ZX	while ((ch = getopt(argc, argv, "dR:")) != EOF)
ZX		switch(ch) {
ZX		case 'd':
ZX			debug = 1;
ZX			options |= SO_DEBUG;
ZX			break;
ZX		case 'R': {	/* invocation rate */
ZX			char *p;
ZX
ZX			ltmpint = strtol(optarg, &p, 0);
ZX			if (ltmpint < 1 || ltmpint > 32767L || *p)
ZX				syslog(LOG_ERR,
ZX			         "-R %s: bad value for service invocation rate",
ZX					optarg);
ZX			else
ZX				toomany = (int)ltmpint;
ZX			break;
ZX		}
ZX		case '?':
ZX		default:
ZX			syslog(LOG_ERR,
ZX				"usage: inetd [-d] [-R rate] [conf-file]");
ZX			exit(1);
ZX		}
ZX	argc -= optind;
ZX	argv += optind;
ZX
ZX	if (argc > 0)
ZX		CONFIG = argv[0];
ZX	if (debug == 0) {
ZX		daemon(0, 0);
ZX	}
ZX	memset(&sv, 0, sizeof(sv));
ZX	sv.sv_mask = SIGBLOCK;
ZX	sv.sv_handler = retry;
ZX	sigvec(SIGALRM, &sv, (struct sigvec *)0);
ZX	config(SIGHUP);
ZX	sv.sv_handler = config;
ZX	sigvec(SIGHUP, &sv, (struct sigvec *)0);
ZX	sv.sv_handler = reapchild;
ZX	sigvec(SIGCHLD, &sv, (struct sigvec *)0);
ZX
ZX	{
ZX		/* space for daemons to overwrite environment for ps */
ZX#define	DUMMYSIZE	100
ZX		char dummy[DUMMYSIZE];
ZX
ZX		(void)memset(dummy, 'x', sizeof(DUMMYSIZE) - 1);
ZX		dummy[DUMMYSIZE - 1] = '\0';
ZX		(void)setenv("inetd_dummy", dummy, 1);
ZX	}
ZX
ZX	for (;;) {
ZX	    int n, ctrl;
ZX	    fd_set readable;
ZX
ZX	    if (nsock == 0) {
ZX		(void) sigblock(SIGBLOCK);
ZX		while (nsock == 0)
ZX		    sigpause(0L);
ZX		(void) sigsetmask(0L);
ZX	    }
ZX	    readable = allsock;
ZX	    if ((n = select(maxsock + 1, &readable, (fd_set *)0,
ZX		(fd_set *)0, (struct timeval *)0)) <= 0) {
ZX		    if (n < 0 && errno != EINTR)
ZX			syslog(LOG_WARNING, "select: %m");
ZX		    sleep(1);
ZX		    continue;
ZX	    }
ZX	    for (sep = servtab; n && sep; sep = sep->se_next)
ZX	        if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
ZX		    n--;
ZX		    if (debug)
ZX			    fprintf(stderr, "someone wants %s\n",
ZX				sep->se_service);
ZX		    if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
ZX			    ctrl = accept(sep->se_fd, (struct sockaddr *)0,
ZX				(int *)0);
ZX			    if (debug)
ZX				    fprintf(stderr, "accept, ctrl %d\n", ctrl);
ZX			    if (ctrl < 0) {
ZX				    if (errno != EINTR)
ZX					    syslog(LOG_WARNING,
ZX						"accept (for %s): %m",
ZX						sep->se_service);
ZX				    continue;
ZX			    }
ZX			    /*
ZX			     * Call tcpmux to find the real service to exec.
ZX			     */
ZX			    if (sep->se_bi &&
ZX				sep->se_bi->bi_fn == (void (*)()) tcpmux) {
ZX				    sep = tcpmux(ctrl);
ZX				    if (sep == NULL) {
ZX					    close(ctrl);
ZX					    continue;
ZX				    }
ZX			    }
ZX		    } else
ZX			    ctrl = sep->se_fd;
ZX		    (void) sigblock(SIGBLOCK);
ZX		    pid = 0;
ZX		    dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
ZX		    if (dofork) {
ZX			    if (sep->se_count++ == 0)
ZX				(void)gettimeofday(&sep->se_time,
ZX				    (struct timezone *)0);
ZX			    else if (sep->se_count >= toomany) {
ZX				struct timeval now;
ZX
ZX				(void)gettimeofday(&now, (struct timezone *)0);
ZX				if (now.tv_sec - sep->se_time.tv_sec >
ZX				    CNT_INTVL) {
ZX					sep->se_time = now;
ZX					sep->se_count = 1;
ZX				} else {
ZX					syslog(LOG_ERR,
ZX			"%s/%s server failing (looping), service terminated",
ZX					    sep->se_service, sep->se_proto);
ZX					close_sep(sep);
ZX					sigsetmask(0L);
ZX					if (!timingout) {
ZX						timingout = 1;
ZX						alarm(RETRYTIME);
ZX					}
ZX					continue;
ZX				}
ZX			    }
ZX			    pid = fork();
ZX		    }
ZX		    if (pid < 0) {
ZX			    syslog(LOG_ERR, "fork: %m");
ZX			    if (!sep->se_wait &&
ZX				sep->se_socktype == SOCK_STREAM)
ZX				    close(ctrl);
ZX			    sigsetmask(0L);
ZX			    sleep(1);
ZX			    continue;
ZX		    }
ZX		    if (pid && sep->se_wait) {
ZX			    sep->se_wait = pid;
ZX			    if (sep->se_fd >= 0) {
ZX				FD_CLR(sep->se_fd, &allsock);
ZX			        nsock--;
ZX			    }
ZX		    }
ZX		    sigsetmask(0L);
ZX		    if (pid == 0) {
ZX#ifndef	pdp11
ZX			    if (debug && dofork)
ZX				setsid();
ZX#endif
ZX			    if (dofork) {
ZX				if (debug)
ZX					fprintf(stderr, "+ Closing from %d\n",
ZX						maxsock);
ZX				for (tmpint = maxsock; tmpint > 2; tmpint--)
ZX					if (tmpint != ctrl)
ZX						close(tmpint);
ZX			    }
ZX			    if (sep->se_bi)
ZX				(*sep->se_bi->bi_fn)(ctrl, sep);
ZX			    else {
ZX				if (debug)
ZX					fprintf(stderr, "%d execl %s\n",
ZX					    getpid(), sep->se_server);
ZX				dup2(ctrl, 0);
ZX				close(ctrl);
ZX				dup2(0, 1);
ZX				dup2(0, 2);
ZX				if ((pwd = getpwnam(sep->se_user)) == NULL) {
ZX					syslog(LOG_ERR,
ZX					    "%s/%s: %s: No such user",
ZX						sep->se_service, sep->se_proto,
ZX						sep->se_user);
ZX					if (sep->se_socktype != SOCK_STREAM)
ZX						recv(0, buf, sizeof (buf), 0);
ZX					_exit(1);
ZX				}
ZX				if (pwd->pw_uid) {
ZX					if (setgid(pwd->pw_gid) < 0) {
ZX						syslog(LOG_ERR,
ZX						  "%s: can't set gid %d: %m", 
ZX						  sep->se_service, pwd->pw_gid);
ZX						_exit(1);
ZX					}
ZX					(void) initgroups(pwd->pw_name,
ZX							pwd->pw_gid);
ZX					if (setuid(pwd->pw_uid) < 0) {
ZX						syslog(LOG_ERR,
ZX						  "%s: can't set uid %d: %m", 
ZX						  sep->se_service, pwd->pw_uid);
ZX						_exit(1);
ZX					}
ZX				}
ZX				execv(sep->se_server, sep->se_argv);
ZX				if (sep->se_socktype != SOCK_STREAM)
ZX					recv(0, buf, sizeof (buf), 0);
ZX				syslog(LOG_ERR,
ZX				    "cannot execute %s: %m", sep->se_server);
ZX				_exit(1);
ZX			    }
ZX		    }
ZX		    if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
ZX			    close(ctrl);
ZX		}
ZX	}
ZX}
ZX
ZXint
ZXreapchild(signo)
ZX	int signo;
ZX{
ZX	int status;
ZX	pid_t pid;
ZX	register struct servtab *sep;
ZX
ZX	for (;;) {
ZX		pid = wait3(&status, WNOHANG, (struct rusage *)0);
ZX		if (pid <= 0)
ZX			break;
ZX		if (debug)
ZX			fprintf(stderr, "%d reaped, status %#x\n", 
ZX				pid, status);
ZX		for (sep = servtab; sep; sep = sep->se_next)
ZX			if (sep->se_wait == pid) {
ZX				if (status)
ZX					syslog(LOG_WARNING,
ZX					    "%s: exit status 0x%x",
ZX					    sep->se_server, status);
ZX				if (debug)
ZX					fprintf(stderr, "restored %s, fd %d\n",
ZX					    sep->se_service, sep->se_fd);
ZX				FD_SET(sep->se_fd, &allsock);
ZX				nsock++;
ZX				sep->se_wait = 1;
ZX			}
ZX	}
ZX}
ZX
ZXint
ZXconfig(signo)
ZX	int signo;
ZX{
ZX	register struct servtab *sep, *cp;
ZX	struct servtab **sepp;
ZX	long omask;
ZX
ZX	if (!setconfig()) {
ZX		syslog(LOG_ERR, "%s: %m", CONFIG);
ZX		return;
ZX	}
ZX	for (sep = servtab; sep; sep = sep->se_next)
ZX		sep->se_checked = 0;
ZX	while (cp = getconfigent()) {
ZX		if (getpwnam(cp->se_user) == NULL) {
ZX			syslog(LOG_ERR,
ZX				"%s/%s: No such user '%s', service ignored",
ZX				cp->se_service, cp->se_proto, cp->se_user);
ZX			continue;
ZX		}
ZX		for (sep = servtab; sep; sep = sep->se_next)
ZX			if (strcmp(sep->se_service, cp->se_service) == 0 &&
ZX			    strcmp(sep->se_proto, cp->se_proto) == 0)
ZX				break;
ZX		if (sep != 0) {
ZX			int i;
ZX
ZX			omask = sigblock(SIGBLOCK);
ZX			/*
ZX			 * sep->se_wait may be holding the pid of a daemon
ZX			 * that we're waiting for.  If so, don't overwrite
ZX			 * it unless the config file explicitly says don't 
ZX			 * wait.
ZX			 */
ZX			if (cp->se_bi == 0 && 
ZX			    (sep->se_wait == 1 || cp->se_wait == 0))
ZX				sep->se_wait = cp->se_wait;
ZX#define SWAP(a, b) { char *c = a; a = b; b = c; }
ZX			if (cp->se_user)
ZX				SWAP(sep->se_user, cp->se_user);
ZX			if (cp->se_server)
ZX				SWAP(sep->se_server, cp->se_server);
ZX			for (i = 0; i < MAXARGV; i++)
ZX				SWAP(sep->se_argv[i], cp->se_argv[i]);
ZX			sigsetmask(omask);
ZX			freeconfig(cp);
ZX			if (debug)
ZX				print_service("REDO", sep);
ZX		} else {
ZX			sep = enter(cp);
ZX			if (debug)
ZX				print_service("ADD ", sep);
ZX		}
ZX		sep->se_checked = 1;
ZX		if (ISMUX(sep)) {
ZX			sep->se_fd = -1;
ZX			continue;
ZX		}
ZX		sp = getservbyname(sep->se_service, sep->se_proto);
ZX		if (sp == 0) {
ZX			syslog(LOG_ERR, "%s/%s: unknown service",
ZX			    sep->se_service, sep->se_proto);
ZX			sep->se_checked = 0;
ZX			continue;
ZX		}
ZX		if (sp->s_port != sep->se_ctrladdr.sin_port) {
ZX			sep->se_ctrladdr.sin_family = AF_INET;
ZX			sep->se_ctrladdr.sin_port = sp->s_port;
ZX			if (sep->se_fd >= 0)
ZX				close_sep(sep);
ZX		}
ZX		if (sep->se_fd == -1)
ZX			setup(sep);
ZX	}
ZX	endconfig();
ZX	/*
ZX	 * Purge anything not looked at above.
ZX	 */
ZX	omask = sigblock(SIGBLOCK);
ZX	sepp = &servtab;
ZX	while (sep = *sepp) {
ZX		if (sep->se_checked) {
ZX			sepp = &sep->se_next;
ZX			continue;
ZX		}
ZX		*sepp = sep->se_next;
ZX		if (sep->se_fd >= 0)
ZX			close_sep(sep);
ZX		if (debug)
ZX			print_service("FREE", sep);
ZX		freeconfig(sep);
ZX		free((char *)sep);
ZX	}
ZX	(void) sigsetmask(omask);
ZX}
ZX
ZXint
ZXretry(signo)
ZX	int signo;
ZX{
ZX	register struct servtab *sep;
ZX
ZX	timingout = 0;
ZX	for (sep = servtab; sep; sep = sep->se_next)
ZX		if (sep->se_fd == -1)
ZX			setup(sep);
ZX}
ZX
ZXvoid
ZXsetup(sep)
ZX	register struct servtab *sep;
ZX{
ZX	int on = 1;
ZX
ZX	if ((sep->se_fd = socket(AF_INET, sep->se_socktype, 0)) < 0) {
ZX		if (debug)
ZX			fprintf(stderr, "socket failed on %s/%s: %s\n", 
ZX				sep->se_service, sep->se_proto,
ZX				strerror(errno));
ZX		syslog(LOG_ERR, "%s/%s: socket: %m",
ZX		    sep->se_service, sep->se_proto);
ZX		return;
ZX	}
ZX#define	turnon(fd, opt) \
ZXsetsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
ZX	if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
ZX	    turnon(sep->se_fd, SO_DEBUG) < 0)
ZX		syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
ZX	if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
ZX		syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
ZX#undef turnon
ZX	if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
ZX	    sizeof (sep->se_ctrladdr)) < 0) {
ZX		if (debug)
ZX			fprintf(stderr, "bind failed on %s/%s: %s\n",
ZX				sep->se_service, sep->se_proto,
ZX				strerror(errno));
ZX		syslog(LOG_ERR, "%s/%s: bind: %m",
ZX		    sep->se_service, sep->se_proto);
ZX		(void) close(sep->se_fd);
ZX		sep->se_fd = -1;
ZX		if (!timingout) {
ZX			timingout = 1;
ZX			alarm(RETRYTIME);
ZX		}
ZX		return;
ZX	}
ZX	if (sep->se_socktype == SOCK_STREAM)
ZX		listen(sep->se_fd, 10);
ZX	FD_SET(sep->se_fd, &allsock);
ZX	nsock++;
ZX	if (sep->se_fd > maxsock)
ZX		maxsock = sep->se_fd;
ZX	if (debug) {
ZX		fprintf(stderr, "registered %s on %d\n",
ZX			sep->se_server, sep->se_fd);
ZX	}
ZX}
ZX
ZX/*
ZX * Finish with a service and its socket.
ZX */
ZXvoid
ZXclose_sep(sep)
ZX	register struct servtab *sep;
ZX{
ZX	if (sep->se_fd >= 0) {
ZX		nsock--;
ZX		FD_CLR(sep->se_fd, &allsock);
ZX		(void) close(sep->se_fd);
ZX		sep->se_fd = -1;
ZX	}
ZX	sep->se_count = 0;
ZX	/*
ZX	 * Don't keep the pid of this running deamon: when reapchild()
ZX	 * reaps this pid, it would erroneously increment nsock.
ZX	 */
ZX	if (sep->se_wait > 1)
ZX		sep->se_wait = 1;
ZX}
ZX
ZXstruct servtab *
ZXenter(cp)
ZX	struct servtab *cp;
ZX{
ZX	register struct servtab *sep;
ZX	long omask;
ZX
ZX	sep = (struct servtab *)malloc(sizeof (*sep));
ZX	if (sep == (struct servtab *)0) {
ZX		syslog(LOG_ERR, "Out of memory.");
ZX		exit(-1);
ZX	}
ZX	*sep = *cp;
ZX	sep->se_fd = -1;
ZX	omask = sigblock(SIGBLOCK);
ZX	sep->se_next = servtab;
ZX	servtab = sep;
ZX	sigsetmask(omask);
ZX	return (sep);
ZX}
ZX
ZXFILE	*fconfig = NULL;
ZXstruct	servtab serv;
ZXchar	line[LINE_MAX];
ZX
ZXint
ZXsetconfig()
ZX{
ZX
ZX	if (fconfig != NULL) {
ZX		fseek(fconfig, 0L, SEEK_SET);
ZX		return (1);
ZX	}
ZX	fconfig = fopen(CONFIG, "r");
ZX	return (fconfig != NULL);
ZX}
ZX
ZXvoid
ZXendconfig()
ZX{
ZX	if (fconfig) {
ZX		(void) fclose(fconfig);
ZX		fconfig = NULL;
ZX	}
ZX}
ZX
ZXstruct servtab *
ZXgetconfigent()
ZX{
ZX	register struct servtab *sep = &serv;
ZX	int argc;
ZX	char *cp, *arg;
ZX	static char TCPMUX_TOKEN[] = "tcpmux/";
ZX#define MUX_LEN		(sizeof(TCPMUX_TOKEN)-1)
ZX
ZXmore:
ZX	while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0'))
ZX		;
ZX	if (cp == NULL)
ZX		return ((struct servtab *)0);
ZX	/*
ZX	 * clear the static buffer, since some fields (se_ctrladdr,
ZX	 * for example) don't get initialized here.
ZX	 */
ZX	memset((caddr_t)sep, 0, sizeof *sep);
ZX	arg = skip(&cp);
ZX	if (cp == NULL) {
ZX		/* got an empty line containing just blanks/tabs. */
ZX		goto more;
ZX	}
ZX	if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
ZX		char *c = arg + MUX_LEN;
ZX		if (*c == '+') {
ZX			sep->se_type = MUXPLUS_TYPE;
ZX			c++;
ZX		} else
ZX			sep->se_type = MUX_TYPE;
ZX		sep->se_service = newstr(c);
ZX	} else {
ZX		sep->se_service = newstr(arg);
ZX		sep->se_type = NORM_TYPE;
ZX	}
ZX	arg = sskip(&cp);
ZX	if (strcmp(arg, "stream") == 0)
ZX		sep->se_socktype = SOCK_STREAM;
ZX	else if (strcmp(arg, "dgram") == 0)
ZX		sep->se_socktype = SOCK_DGRAM;
ZX	else if (strcmp(arg, "rdm") == 0)
ZX		sep->se_socktype = SOCK_RDM;
ZX	else if (strcmp(arg, "seqpacket") == 0)
ZX		sep->se_socktype = SOCK_SEQPACKET;
ZX	else if (strcmp(arg, "raw") == 0)
ZX		sep->se_socktype = SOCK_RAW;
ZX	else
ZX		sep->se_socktype = -1;
ZX	sep->se_proto = newstr(sskip(&cp));
ZX	arg = sskip(&cp);
ZX	sep->se_wait = strcmp(arg, "wait") == 0;
ZX	if (ISMUX(sep)) {
ZX		/*
ZX		 * Silently enforce "nowait" for TCPMUX services since
ZX		 * they don't have an assigned port to listen on.
ZX		 */
ZX		sep->se_wait = 0;
ZX
ZX		if (strcmp(sep->se_proto, "tcp")) {
ZX			syslog(LOG_ERR, 
ZX				"%s: bad protocol for tcpmux service %s",
ZX				CONFIG, sep->se_service);
ZX			goto more;
ZX		}
ZX		if (sep->se_socktype != SOCK_STREAM) {
ZX			syslog(LOG_ERR, 
ZX				"%s: bad socket type for tcpmux service %s",
ZX				CONFIG, sep->se_service);
ZX			goto more;
ZX		}
ZX	}
ZX	sep->se_user = newstr(sskip(&cp));
ZX	sep->se_server = newstr(sskip(&cp));
ZX	if (strcmp(sep->se_server, "internal") == 0) {
ZX		struct biltin *bi;
ZX
ZX		for (bi = biltins; bi->bi_service; bi++)
ZX			if (bi->bi_socktype == sep->se_socktype &&
ZX			    strcmp(bi->bi_service, sep->se_service) == 0)
ZX				break;
ZX		if (bi->bi_service == 0) {
ZX			syslog(LOG_ERR, "internal service %s unknown",
ZX				sep->se_service);
ZX			goto more;
ZX		}
ZX		sep->se_bi = bi;
ZX		sep->se_wait = bi->bi_wait;
ZX	} else
ZX		sep->se_bi = NULL;
ZX	argc = 0;
ZX	for (arg = skip(&cp); cp; arg = skip(&cp))
ZX		if (argc < MAXARGV)
ZX			sep->se_argv[argc++] = newstr(arg);
ZX	while (argc <= MAXARGV)
ZX		sep->se_argv[argc++] = NULL;
ZX	return (sep);
ZX}
ZX
ZXvoid
ZXfreeconfig(cp)
ZX	register struct servtab *cp;
ZX{
ZX	int i;
ZX
ZX	if (cp->se_service)
ZX		free(cp->se_service);
ZX	if (cp->se_proto)
ZX		free(cp->se_proto);
ZX	if (cp->se_user)
ZX		free(cp->se_user);
ZX	if (cp->se_server)
ZX		free(cp->se_server);
ZX	for (i = 0; i < MAXARGV; i++)
ZX		if (cp->se_argv[i])
ZX			free(cp->se_argv[i]);
ZX}
ZX
ZX
ZX/*
ZX * Safe skip - if skip returns null, log a syntax error in the
ZX * configuration file and exit.
ZX */
ZXchar *
ZXsskip(cpp)
ZX	char **cpp;
ZX{
ZX	register char *cp;
ZX
ZX	cp = skip(cpp);
ZX	if (cp == NULL) {
ZX		syslog(LOG_ERR, "%s: syntax error", CONFIG);
ZX		exit(-1);
ZX	}
ZX	return (cp);
ZX}
ZX
ZXchar *
ZXskip(cpp)
ZX	char **cpp;
ZX{
ZX	register char *cp = *cpp;
ZX	char *start;
ZX
ZXagain:
ZX	while (*cp == ' ' || *cp == '\t')
ZX		cp++;
ZX	if (*cp == '\0') {
ZX		int c;
ZX
ZX		c = getc(fconfig);
ZX		(void) ungetc(c, fconfig);
ZX		if (c == ' ' || c == '\t')
ZX			if (cp = nextline(fconfig))
ZX				goto again;
ZX		*cpp = (char *)0;
ZX		return ((char *)0);
ZX	}
ZX	start = cp;
ZX	while (*cp && *cp != ' ' && *cp != '\t')
ZX		cp++;
ZX	if (*cp != '\0')
ZX		*cp++ = '\0';
ZX	*cpp = cp;
ZX	return (start);
ZX}
ZX
ZXchar *
ZXnextline(fd)
ZX	FILE *fd;
ZX{
ZX	register char *cp;
ZX
ZX	if (fgets(line, sizeof (line), fd) == NULL)
ZX		return ((char *)0);
ZX	cp = strchr(line, '\n');
ZX	if (cp)
ZX		*cp = '\0';
ZX	return (line);
ZX}
ZX
ZXchar *
ZXnewstr(cp)
ZX	register char *cp;
ZX{
ZX	if (cp = strdup(cp ? cp : ""))
ZX		return (cp);
ZX	syslog(LOG_ERR, "strdup: %m");
ZX	exit(-1);
ZX	/* NOTREACHED */
ZX}
ZX
ZXvoid
ZXsetproctitle(a, s)
ZX	char *a;
ZX	int s;
ZX{
ZX	int size;
ZX	register char *cp;
ZX	struct sockaddr_in sin;
ZX	char buf[80];
ZX
ZX	cp = Argv[0];
ZX	size = sizeof(sin);
ZX	if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
ZX		(void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); 
ZX	else
ZX		(void) sprintf(buf, "-%s", a); 
ZX	strncpy(cp, buf, LastArg - cp);
ZX	cp += strlen(cp);
ZX	while (cp < LastArg)
ZX		*cp++ = ' ';
ZX}
ZX
ZX/*
ZX * Internet services provided internally by inetd:
ZX */
ZX#define	BUFSIZE	8192
ZX
ZX/* ARGSUSED */
ZXvoid
ZXecho_stream(s, sep)		/* Echo service -- echo data back */
ZX	int s;
ZX	struct servtab *sep;
ZX{
ZX	char buffer[BUFSIZE];
ZX	int i;
ZX
ZX	setproctitle(sep->se_service, s);
ZX	while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
ZX	    write(s, buffer, i) > 0)
ZX		;
ZX	exit(0);
ZX}
ZX
ZX/* ARGSUSED */
ZXvoid
ZXecho_dg(s, sep)			/* Echo service -- echo data back */
ZX	int s;
ZX	struct servtab *sep;
ZX{
ZX	char buffer[BUFSIZE];
ZX	int i, size;
ZX	struct sockaddr sa;
ZX
ZX	size = sizeof(sa);
ZX	if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0)
ZX		return;
ZX	(void) sendto(s, buffer, i, 0, &sa, sizeof(sa));
ZX}
ZX
ZX/* ARGSUSED */
ZXvoid
ZXdiscard_stream(s, sep)		/* Discard service -- ignore data */
ZX	int s;
ZX	struct servtab *sep;
ZX{
ZX	int ret;
ZX	char buffer[BUFSIZE];
ZX
ZX	setproctitle(sep->se_service, s);
ZX	while (1) {
ZX		while ((ret = read(s, buffer, sizeof(buffer))) > 0)
ZX			;
ZX		if (ret == 0 || errno != EINTR)
ZX			break;
ZX	}
ZX	exit(0);
ZX}
ZX
ZX/* ARGSUSED */
ZXvoid
ZXdiscard_dg(s, sep)		/* Discard service -- ignore data */
ZX	int s;
ZX	struct servtab *sep;
ZX{
ZX	char buffer[BUFSIZE];
ZX
ZX	(void) read(s, buffer, sizeof(buffer));
ZX}
ZX
ZX#include <ctype.h>
ZX#define LINESIZ 72
ZXchar ring[128];
ZXchar *endring;
ZX
ZXvoid
ZXinitring()
ZX{
ZX	register int i;
ZX
ZX	endring = ring;
ZX
ZX	for (i = 0; i <= 128; ++i)
ZX		if (isprint(i))
ZX			*endring++ = i;
ZX}
ZX
ZX/* ARGSUSED */
ZXvoid
ZXchargen_stream(s, sep)		/* Character generator */
ZX	int s;
ZX	struct servtab *sep;
ZX{
ZX	int len;
ZX	char *rs, text[LINESIZ+2];
ZX
ZX	setproctitle(sep->se_service, s);
ZX
ZX	if (!endring) {
ZX		initring();
ZX		rs = ring;
ZX	}
ZX
ZX	text[LINESIZ] = '\r';
ZX	text[LINESIZ + 1] = '\n';
ZX	for (rs = ring;;) {
ZX		if ((len = endring - rs) >= LINESIZ)
ZX			memmove(text, rs, LINESIZ);
ZX		else {
ZX			memmove(text, rs, len);
ZX			memmove(text + len, ring, LINESIZ - len);
ZX		}
ZX		if (++rs == endring)
ZX			rs = ring;
ZX		if (write(s, text, sizeof(text)) != sizeof(text))
ZX			break;
ZX	}
ZX	exit(0);
ZX}
ZX
ZX/* ARGSUSED */
ZXvoid
ZXchargen_dg(s, sep)		/* Character generator */
ZX	int s;
ZX	struct servtab *sep;
ZX{
ZX	struct sockaddr sa;
ZX	static char *rs;
ZX	int len, size;
ZX	char text[LINESIZ+2];
ZX
ZX	if (endring == 0) {
ZX		initring();
ZX		rs = ring;
ZX	}
ZX
ZX	size = sizeof(sa);
ZX	if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0)
ZX		return;
ZX
ZX	if ((len = endring - rs) >= LINESIZ)
ZX		memmove(text, rs, LINESIZ);
ZX	else {
ZX		memmove(text, rs, len);
ZX		memmove(text + len, ring, LINESIZ - len);
ZX	}
ZX	if (++rs == endring)
ZX		rs = ring;
ZX	text[LINESIZ] = '\r';
ZX	text[LINESIZ + 1] = '\n';
ZX	(void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa));
ZX}
ZX
ZX/*
ZX * Return a machine readable date and time, in the form of the
ZX * number of seconds since midnight, Jan 1, 1900.  Since gettimeofday
ZX * returns the number of seconds since midnight, Jan 1, 1970,
ZX * we must add 2208988800 seconds to this figure to make up for
ZX * some seventy years Bell Labs was asleep.
ZX */
ZX
ZXlong
ZXmachtime()
ZX{
ZX	struct timeval tv;
ZX
ZX	if (gettimeofday(&tv, (struct timezone *)0) < 0) {
ZX		if (debug)
ZX			fprintf(stderr, "Unable to get time of day\n");
ZX		return (0L);
ZX	}
ZX#define	OFFSET ((u_long)25567 * 24*60*60)
ZX	return (htonl((long)(tv.tv_sec + OFFSET)));
ZX#undef OFFSET
ZX}
ZX
ZX/* ARGSUSED */
ZXvoid
ZXmachtime_stream(s, sep)
ZX	int s;
ZX	struct servtab *sep;
ZX{
ZX	long result;
ZX
ZX	result = machtime();
ZX	(void) write(s, (char *) &result, sizeof(result));
ZX}
ZX
ZX/* ARGSUSED */
ZXvoid
ZXmachtime_dg(s, sep)
ZX	int s;
ZX	struct servtab *sep;
ZX{
ZX	long result;
ZX	struct sockaddr sa;
ZX	int size;
ZX
ZX	size = sizeof(sa);
ZX	if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0)
ZX		return;
ZX	result = machtime();
ZX	(void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa));
ZX}
ZX
ZX/* ARGSUSED */
ZXvoid
ZXdaytime_stream(s, sep)		/* Return human-readable time of day */
ZX	int s;
ZX	struct servtab *sep;
ZX{
ZX	char buffer[256];
ZX	time_t clock;
ZX
ZX	clock = time((time_t *) 0);
ZX
ZX	(void) sprintf(buffer, "%.24s\r\n", ctime(&clock));
ZX	(void) write(s, buffer, strlen(buffer));
ZX}
ZX
ZX/* ARGSUSED */
ZXvoid
ZXdaytime_dg(s, sep)		/* Return human-readable time of day */
ZX	int s;
ZX	struct servtab *sep;
ZX{
ZX	char buffer[256];
ZX	time_t clock;
ZX	struct sockaddr sa;
ZX	int size;
ZX
ZX	clock = time((time_t *) 0);
ZX
ZX	size = sizeof(sa);
ZX	if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0)
ZX		return;
ZX	(void) sprintf(buffer, "%.24s\r\n", ctime(&clock));
ZX	(void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa));
ZX}
ZX
ZX/*
ZX * print_service:
ZX *	Dump relevant information to stderr
ZX */
ZXvoid
ZXprint_service(action, sep)
ZX	char *action;
ZX	struct servtab *sep;
ZX{
ZX	fprintf(stderr,
ZX	    "%s: %s proto=%s, wait=%d, user=%s builtin=%x server=%s\n",
ZX	    action, sep->se_service, sep->se_proto,
ZX	    sep->se_wait, sep->se_user, (int)sep->se_bi, sep->se_server);
ZX}
ZX
ZX/*
ZX *  Based on TCPMUX.C by Mark K. Lottor November 1988
ZX *  sri-nic::ps:<mkl>tcpmux.c
ZX */
ZX
ZX
ZXstatic int		/* # of characters upto \r,\n or \0 */
ZXgetline(fd, buf, len)
ZX	int fd;
ZX	register char *buf;
ZX	int len;
ZX{
ZX	int count = 0;
ZX	register int n;
ZX
ZX	do {
ZX		n = read(fd, buf, len-count);
ZX		if (n == 0)
ZX			return (count);
ZX		if (n < 0)
ZX			return (-1);
ZX		while (--n >= 0) {
ZX			if (*buf == '\r' || *buf == '\n' || *buf == '\0')
ZX				return (count);
ZX			count++;
ZX			buf++;
ZX		}
ZX	} while (count < len);
ZX	return (count);
ZX}
ZX
ZX#define MAX_SERV_LEN	(256+2)		/* 2 bytes for \r\n */
ZX
ZX#define strwrite(fd, buf)	(void) write(fd, buf, sizeof(buf)-1)
ZX
ZXstruct servtab *
ZXtcpmux(s)
ZX	int s;
ZX{
ZX	register struct servtab *sep;
ZX	char service[MAX_SERV_LEN+1];
ZX	int len;
ZX
ZX	/* Get requested service name */
ZX	if ((len = getline(s, service, MAX_SERV_LEN)) < 0) {
ZX		strwrite(s, "-Error reading service name\r\n");
ZX		return (NULL);
ZX	}
ZX	service[len] = '\0';
ZX
ZX	if (debug)
ZX		fprintf(stderr, "tcpmux: someone wants %s\n", service);
ZX
ZX	/*
ZX	 * Help is a required command, and lists available services,
ZX	 * one per line.
ZX	 */
ZX	if (!strcasecmp(service, "help")) {
ZX		for (sep = servtab; sep; sep = sep->se_next) {
ZX			if (!ISMUX(sep))
ZX				continue;
ZX			(void)write(s,sep->se_service,strlen(sep->se_service));
ZX			strwrite(s, "\r\n");
ZX		}
ZX		return (NULL);
ZX	}
ZX
ZX	/* Try matching a service in inetd.conf with the request */
ZX	for (sep = servtab; sep; sep = sep->se_next) {
ZX		if (!ISMUX(sep))
ZX			continue;
ZX		if (!strcasecmp(service, sep->se_service)) {
ZX			if (ISMUXPLUS(sep)) {
ZX				strwrite(s, "+Go\r\n");
ZX			}
ZX			return (sep);
ZX		}
ZX	}
ZX	strwrite(s, "-Service not available\r\n");
ZX	return (NULL);
ZX}
ZSHAR_EOF
Zchmod 644 'inetd.c'
Zfi
Zif test -f 'pathnames.h'
Zthen
Z	echo shar: "will not over-write existing file 'pathnames.h'"
Zelse
Zsed 's/^X//' << \SHAR_EOF > 'pathnames.h'
ZX/*
ZX * Copyright (c) 1989, 1993
ZX *	The Regents of the University of California.  All rights reserved.
ZX *
ZX * Redistribution and use in source and binary forms, with or without
ZX * modification, are permitted provided that the following conditions
ZX * are met:
ZX * 1. Redistributions of source code must retain the above copyright
ZX *    notice, this list of conditions and the following disclaimer.
ZX * 2. Redistributions in binary form must reproduce the above copyright
ZX *    notice, this list of conditions and the following disclaimer in the
ZX *    documentation and/or other materials provided with the distribution.
ZX * 3. All advertising materials mentioning features or use of this software
ZX *    must display the following acknowledgement:
ZX *	This product includes software developed by the University of
ZX *	California, Berkeley and its contributors.
ZX * 4. Neither the name of the University nor the names of its contributors
ZX *    may be used to endorse or promote products derived from this software
ZX *    without specific prior written permission.
ZX *
ZX * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
ZX * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
ZX * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ZX * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
ZX * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
ZX * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
ZX * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ZX * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
ZX * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
ZX * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
ZX * SUCH DAMAGE.
ZX *
ZX *	@(#)pathnames.h	8.1 (Berkeley) 6/6/93
ZX */
ZX
ZX#include <paths.h>
ZX
ZX#define	_PATH_INETDCONF	"/etc/inetd.conf"
ZSHAR_EOF
Zchmod 644 'pathnames.h'
Zfi
Zchmod 755 .
Zcd ..
Zexit 0
Z#	End of shell archive
SHAR_EOF
fi
if test -f '343.patch'
then
	echo shar: "will not over-write existing file '343.patch'"
else
sed 's/^Z//' << \SHAR_EOF > '343.patch'
Z*** /etc/rc.old	Sun Oct 27 21:53:36 1996
Z--- /etc/rc	Wed Nov 13 21:48:50 1996
Z***************
Z*** 143,149 ****
Z  	if [ "${named-NO}" != NO ]; then
Z  		/etc/named;		echo -n ' named'>/dev/console 2>&1
Z  	fi
Z! 	/etc/inetd;		echo -n ' inetd'	>/dev/console 2>&1
Z  
Z  	# $rwhod is imported from /etc/netstart;
Z  	# if $rwhod is set to something other than NO, rwhod is run.
Z--- 143,149 ----
Z  	if [ "${named-NO}" != NO ]; then
Z  		/etc/named;		echo -n ' named'>/dev/console 2>&1
Z  	fi
Z! 	/usr/sbin/inetd;		echo -n ' inetd'>/dev/console 2>&1
Z  
Z  	# $rwhod is imported from /etc/netstart;
Z  	# if $rwhod is set to something other than NO, rwhod is run.
Z*** /etc/services.old	Mon May 10 21:35:54 1993
Z--- /etc/services	Wed Nov 13 21:43:02 1996
Z***************
Z*** 1,7 ****
Z! #	@(#)services	1.16 (Berkeley) 86/04/20
Z  #
Z  # Network services, Internet style
Z  #
Z  echo		7/tcp
Z  echo		7/udp
Z  discard		9/tcp		sink null
Z--- 1,8 ----
Z! #	@(#)services	1.16.1 (2.11BSD) 1996/11/13
Z  #
Z  # Network services, Internet style
Z  #
Z+ tcpmux		1/tcp				# TCP port multiplexer (RFC1078)
Z  echo		7/tcp
Z  echo		7/udp
Z  discard		9/tcp		sink null
Z*** /etc/inetd.conf.old	Fri Nov  1 19:11:45 1996
Z--- /etc/inetd.conf	Wed Nov 13 21:45:19 1996
Z***************
Z*** 17,22 ****
Z--- 17,24 ----
Z  discard	stream	tcp	nowait	root	internal
Z  #chargen	stream	tcp	nowait	root	internal
Z  #daytime	stream	tcp	nowait	root	internal
Z+ #tcpmux	stream	tcp	nowait	root	internal
Z+ #tcpmux/+date	stream	tcp	nowait	nobody	/bin/date	date
Z  #time	stream	tcp	nowait	root	internal
Z  echo	dgram	udp	wait	root	internal
Z  #discard	dgram	udp	wait	root	internal
Z*** /usr/src/sys/pdpdist/inetd.conf.old	Fri Nov  1 19:25:03 1996
Z--- /usr/src/sys/pdpdist/inetd.conf	Wed Nov 13 21:47:24 1996
Z***************
Z*** 17,22 ****
Z--- 17,24 ----
Z  #discard	stream	tcp	nowait	root	internal
Z  #chargen	stream	tcp	nowait	root	internal
Z  #daytime	stream	tcp	nowait	root	internal
Z+ #tcpmux	stream	tcp	nowait	root	internal
Z+ #tcpmux/+date	stream	tcp	nowait	nobody	/bin/date	date
Z  #time	stream	tcp	nowait	root	internal
Z  echo	dgram	udp	wait	root	internal
Z  #discard	dgram	udp	wait	root	internal
Z*** /usr/src/sys/pdpdist/services.old	Mon Aug 27 14:29:49 1990
Z--- /usr/src/sys/pdpdist/services	Wed Nov 13 21:46:45 1996
Z***************
Z*** 1,7 ****
Z! #	@(#)services	1.16 (Berkeley) 86/04/20
Z  #
Z  # Network services, Internet style
Z  #
Z  echo		7/tcp
Z  echo		7/udp
Z  discard		9/tcp		sink null
Z--- 1,8 ----
Z! #	@(#)services	1.16.1 (2.11BSD) 1996/11/13
Z  #
Z  # Network services, Internet style
Z  #
Z+ tcpmux		1/tcp				# TCP port multiplexer (RFC1078)
Z  echo		7/tcp
Z  echo		7/udp
Z  discard		9/tcp		sink null
Z*** /usr/src/sys/pdpdist/rc.old	Wed Oct 23 15:28:48 1996
Z--- /usr/src/sys/pdpdist/rc	Wed Nov 13 21:48:20 1996
Z***************
Z*** 1,5 ****
Z  HOME=/; export HOME
Z! PATH=/etc:/bin:/usr/ucb:/usr/bin; export PATH
Z  
Z  # If you have a ram disk configured into your system which is listed in
Z  # /etc/fstab, you'll have to do a mkfs on it here and probably change the
Z--- 1,5 ----
Z  HOME=/; export HOME
Z! PATH=/etc:/bin:/sbin:/usr/sbin:/usr/ucb:/usr/bin; export PATH
Z  
Z  # If you have a ram disk configured into your system which is listed in
Z  # /etc/fstab, you'll have to do a mkfs on it here and probably change the
Z***************
Z*** 127,133 ****
Z  	if [ "${named-NO}" != NO ]; then
Z  		named;			echo -n ' named'>/dev/console 2>&1
Z  	fi
Z! 	inetd;			echo -n ' inetd'	>/dev/console 2>&1
Z  
Z  	# $rwhod is imported from /etc/netstart;
Z  	# if $rwhod is set to something other than NO, rwhod is run.
Z--- 127,133 ----
Z  	if [ "${named-NO}" != NO ]; then
Z  		named;			echo -n ' named'>/dev/console 2>&1
Z  	fi
Z! 	/usr/sbin/inetd;		echo -n ' inetd'>/dev/console 2>&1
Z  
Z  	# $rwhod is imported from /etc/netstart;
Z  	# if $rwhod is set to something other than NO, rwhod is run.
Z*** /usr/src/etc/Makefile.old	Sat Oct 26 23:06:23 1996
Z--- /usr/src/etc/Makefile	Wed Nov 13 21:49:44 1996
Z***************
Z*** 3,9 ****
Z  # All rights reserved.  The Berkeley software License Agreement
Z  # specifies the terms and conditions for redistribution.
Z  #
Z! #	@(#)Makefile	5.14.7 (2.11BSD GTE) 1996/10/21
Z  #
Z  DESTDIR=
Z  CFLAGS=	-O
Z--- 3,9 ----
Z  # All rights reserved.  The Berkeley software License Agreement
Z  # specifies the terms and conditions for redistribution.
Z  #
Z! #	@(#)Makefile	5.14.8 (2.11BSD GTE) 1996/11/13
Z  #
Z  DESTDIR=
Z  CFLAGS=	-O
Z***************
Z*** 24,30 ****
Z  #
Z  STD=	ac accton arff bad144 badsect catman chown clri comsat \
Z  	cron dcheck diskpart dumpfs edquota flcopy \
Z! 	gettable ifconfig icheck inetd init newfs mkfs mknod \
Z  	mkproto ncheck quotaon reboot renice \
Z  	repquota rexecd rmt route rwhod rxformat sa savecore \
Z  	shutdown slattach swapon syslogd telnetd tunefs update
Z--- 24,30 ----
Z  #
Z  STD=	ac accton arff bad144 badsect catman chown clri comsat \
Z  	cron dcheck diskpart dumpfs edquota flcopy \
Z! 	gettable ifconfig icheck init newfs mkfs mknod \
Z  	mkproto ncheck quotaon reboot renice \
Z  	repquota rexecd rmt route rwhod rxformat sa savecore \
Z  	shutdown slattach swapon syslogd telnetd tunefs update
Z*** /usr/src/man/man8/Makefile.old	Fri May 24 20:36:36 1996
Z--- /usr/src/man/man8/Makefile	Wed Nov 13 21:55:11 1996
Z***************
Z*** 14,20 ****
Z  # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
Z  # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
Z  #
Z! #	@(#)Makefile	5.4.4 (2.11BSD) 1996/5/24
Z  #
Z  MDIR=	/usr/man/cat8
Z  SRCS=	XNSrouted.8 ac.8 adduser.8 arff.8 arp.8 autoconfig.8 bad144.8 \
Z--- 14,20 ----
Z  # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
Z  # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
Z  #
Z! #	@(#)Makefile	5.4.5 (2.11BSD) 1996/11/13
Z  #
Z  MDIR=	/usr/man/cat8
Z  SRCS=	XNSrouted.8 ac.8 adduser.8 arff.8 arp.8 autoconfig.8 bad144.8 \
Z***************
Z*** 23,29 ****
Z  	cron.8 dcheck.8 diskpart.8 dmesg.8 drtest.8 dump.8 dumpdir.8 \
Z  	dumpfs.8 edquota.8 format.8 fsck.8 fstat.8 \
Z  	gettable.8 getty.8 htable.8 icheck.8 ifconfig.8 implog.8 \
Z! 	implogd.8 inetd.8 init.8 intro.8 kgmon.8 lpc.8 lpd.8 makedev.8 \
Z  	makekey.8 mkfs.8 mkhosts.8 mklost+found.8 mknod.8 mkproto.8 \
Z  	named.8 ncheck.8 newfs.8 pac.8 pstat.8 quot.8 \
Z  	quotaon.8 rc.8 rdump.8 reboot.8 renice.8 repquota.8 \
Z--- 23,29 ----
Z  	cron.8 dcheck.8 diskpart.8 dmesg.8 drtest.8 dump.8 dumpdir.8 \
Z  	dumpfs.8 edquota.8 format.8 fsck.8 fstat.8 \
Z  	gettable.8 getty.8 htable.8 icheck.8 ifconfig.8 implog.8 \
Z! 	implogd.8 init.8 intro.8 kgmon.8 lpc.8 lpd.8 makedev.8 \
Z  	makekey.8 mkfs.8 mkhosts.8 mklost+found.8 mknod.8 mkproto.8 \
Z  	named.8 ncheck.8 newfs.8 pac.8 pstat.8 quot.8 \
Z  	quotaon.8 rc.8 rdump.8 reboot.8 renice.8 repquota.8 \
Z***************
Z*** 38,44 ****
Z  	cron.0 dcheck.0 diskpart.0 dmesg.0 drtest.0 dump.0 dumpdir.0 \
Z  	dumpfs.0 edquota.0 format.0 fsck.0 fstat.0 \
Z  	gettable.0 getty.0 htable.0 icheck.0 ifconfig.0 implog.0 \
Z! 	implogd.0 inetd.0 init.0 intro.0 kgmon.0 lpc.0 lpd.0 makedev.0 \
Z  	makekey.0 mkfs.0 mkhosts.0 mklost+found.0 mknod.0 mkproto.0 \
Z  	named.0 ncheck.0 newfs.0 pac.0 pstat.0 quot.0 \
Z  	quotaon.0 rc.0 rdump.0 reboot.0 renice.0 repquota.0 \
Z--- 38,44 ----
Z  	cron.0 dcheck.0 diskpart.0 dmesg.0 drtest.0 dump.0 dumpdir.0 \
Z  	dumpfs.0 edquota.0 format.0 fsck.0 fstat.0 \
Z  	gettable.0 getty.0 htable.0 icheck.0 ifconfig.0 implog.0 \
Z! 	implogd.0 init.0 intro.0 kgmon.0 lpc.0 lpd.0 makedev.0 \
Z  	makekey.0 mkfs.0 mkhosts.0 mklost+found.0 mknod.0 mkproto.0 \
Z  	named.0 ncheck.0 newfs.0 pac.0 pstat.0 quot.0 \
Z  	quotaon.0 rc.0 rdump.0 reboot.0 renice.0 repquota.0 \
Z*** /usr/src/usr.sbin/Makefile.old	Thu Oct 24 21:25:01 1996
Z--- /usr/src/usr.sbin/Makefile	Wed Nov 13 21:41:05 1996
Z***************
Z*** 1,13 ****
Z  #
Z  # Public domain - 1996/10/24 - sms
Z  #
Z! #	@(#)Makefile	1.0 (2.11BSD) 1996/10/24
Z  #
Z  DESTDIR=
Z  CFLAGS=	-O
Z  SEPFLAG= -i
Z  
Z! SUBDIR=	lpr makewhatis sendmail
Z  
Z  all:	${SUBDIR}
Z  
Z--- 1,13 ----
Z  #
Z  # Public domain - 1996/10/24 - sms
Z  #
Z! #	@(#)Makefile	1.1 (2.11BSD) 1996/11/13
Z  #
Z  DESTDIR=
Z  CFLAGS=	-O
Z  SEPFLAG= -i
Z  
Z! SUBDIR=	inetd lpr makewhatis sendmail
Z  
Z  all:	${SUBDIR}
Z  
Z*** /usr/src/new/nntp/doc/config.sh.old	Thu Oct 15 21:24:00 1987
Z--- /usr/src/new/nntp/doc/config.sh	Thu Nov 14 20:01:03 1996
Z***************
Z*** 10,17 ****
Z  # ------------- SITE DEPENDENT STUFF ---------------------------
Z  # (modify these lines to suit your system)
Z  #
Z! # the location of inetd on your system (usually /etc/inetd)
Z! MINETD=/etc/inetd
Z  # the location of the inetd configuration file (usually /etc/inetd.conf)
Z  MINETDCONFIG=/etc/inetd.conf
Z  # the location of nntpd following installation (usually /etc/nntpd)
Z--- 10,17 ----
Z  # ------------- SITE DEPENDENT STUFF ---------------------------
Z  # (modify these lines to suit your system)
Z  #
Z! # the location of inetd on your system (usually /usr/sbin/inetd)
Z! MINETD=/usr/sbin/inetd
Z  # the location of the inetd configuration file (usually /etc/inetd.conf)
Z  MINETDCONFIG=/etc/inetd.conf
Z  # the location of nntpd following installation (usually /etc/nntpd)
Z*** /usr/src/usr.bin/uucp/uucp.h.old	Thu Oct 24 11:17:02 1996
Z--- /usr/src/usr.bin/uucp/uucp.h	Thu Nov 14 20:07:04 1996
Z***************
Z*** 140,151 ****
Z  /*#define BSD2_9 	/**/
Z  
Z  /*
Z!  * If you are using /etc/inetd with 4.2bsd, define BSDINETD
Z   */
Z  /* #define BSDINETD	/**/
Z  
Z  /*
Z!  * If you are running 4.3bsd or BRL 4.2, you are running the inetd
Z   */
Z  
Z  #if (defined(BSD4_3) || defined(BRL4_2)) && !defined(BSDINETD)
Z--- 140,151 ----
Z  /*#define BSD2_9 	/**/
Z  
Z  /*
Z!  * If you are using 'inetd' with 4.2bsd, define BSDINETD
Z   */
Z  /* #define BSDINETD	/**/
Z  
Z  /*
Z!  * If you are running 4.3bsd, 2.11bsd or BRL 4.2, you are running 'inetd'
Z   */
Z  
Z  #if (defined(BSD4_3) || defined(BRL4_2)) && !defined(BSDINETD)
Z*** /usr/src/usr.sbin/sendmail.MX/adm/TODO.old	Wed Mar 13 18:07:14 1985
Z--- /usr/src/usr.sbin/sendmail.MX/adm/TODO	Thu Nov 14 20:08:48 1996
Z***************
Z*** 42,48 ****
Z  	cleanqueue -- return expired messages; basic consistency
Z  		checking.
Z  	smtpserver -- process smtp connections, pass to queueup -- this
Z! 		can probably become a simple service a la /etc/inetd.
Z  	addrtest -- essentially "-bt" mode.
Z  	verifyaddr -- verify an address list -- "-bv" mode -- needs a
Z  		"noisy" and a "silent" mode (exit status only).  This
Z--- 42,48 ----
Z  	cleanqueue -- return expired messages; basic consistency
Z  		checking.
Z  	smtpserver -- process smtp connections, pass to queueup -- this
Z! 		can probably become a simple service a la 'inetd'.
Z  	addrtest -- essentially "-bt" mode.
Z  	verifyaddr -- verify an address list -- "-bv" mode -- needs a
Z  		"noisy" and a "silent" mode (exit status only).  This
Z*** /usr/src/usr.sbin/sendmail/adm/TODO.old	Wed Feb 18 01:11:05 1987
Z--- /usr/src/usr.sbin/sendmail/adm/TODO	Thu Nov 14 20:09:43 1996
Z***************
Z*** 42,48 ****
Z  	cleanqueue -- return expired messages; basic consistency
Z  		checking.
Z  	smtpserver -- process smtp connections, pass to queueup -- this
Z! 		can probably become a simple service a la /etc/inetd.
Z  	addrtest -- essentially "-bt" mode.
Z  	verifyaddr -- verify an address list -- "-bv" mode -- needs a
Z  		"noisy" and a "silent" mode (exit status only).  This
Z--- 42,48 ----
Z  	cleanqueue -- return expired messages; basic consistency
Z  		checking.
Z  	smtpserver -- process smtp connections, pass to queueup -- this
Z! 		can probably become a simple service a la 'inetd'.
Z  	addrtest -- essentially "-bt" mode.
Z  	verifyaddr -- verify an address list -- "-bv" mode -- needs a
Z  		"noisy" and a "silent" mode (exit status only).  This
Z*** /usr/doc/2.10/setup.2.11/5.t.old	Thu Oct 24 21:40:43 1996
Z--- /usr/doc/2.10/setup.2.11/5.t	Thu Nov 14 19:54:04 1996
Z***************
Z*** 2,8 ****
Z  .\" All rights reserved.  The Berkeley software License Agreement
Z  .\" specifies the terms and conditions for redistribution.
Z  .\"
Z! .\"	@(#)5.t	2.3 (2.11BSD GTE) 1996/10/24
Z  .\"
Z  .ds lq ``
Z  .ds rq ''
Z--- 2,8 ----
Z  .\" All rights reserved.  The Berkeley software License Agreement
Z  .\" specifies the terms and conditions for redistribution.
Z  .\"
Z! .\"	@(#)5.t	2.4 (2.11BSD GTE) 1996/11/14
Z  .\"
Z  .ds lq ``
Z  .ds rq ''
Z***************
Z*** 352,358 ****
Z  .PP
Z  In \*(2B most of the server programs are started up by a
Z  ``super server'', the Internet daemon.  The Internet
Z! daemon, \fI/etc/inetd\fP, acts as a master server for
Z  programs specified in its configuration file, \fI/etc/inetd.conf\fP,
Z  listening for service requests for these servers, and starting
Z  up the appropriate program whenever a request is received.
Z--- 352,358 ----
Z  .PP
Z  In \*(2B most of the server programs are started up by a
Z  ``super server'', the Internet daemon.  The Internet
Z! daemon, \fI/usr/sbin/inetd\fP, acts as a master server for
Z  programs specified in its configuration file, \fI/etc/inetd.conf\fP,
Z  listening for service requests for these servers, and starting
Z  up the appropriate program whenever a request is received.
Z*** /usr/doc/smm/01.setup/5.t.old	Thu Oct 24 22:05:50 1996
Z--- /usr/doc/smm/01.setup/5.t	Thu Nov 14 19:57:00 1996
Z***************
Z*** 2,8 ****
Z  .\" All rights reserved.  The Berkeley software License Agreement
Z  .\" specifies the terms and conditions for redistribution.
Z  .\"
Z! .\"	@(#)5.t	6.1.1 (2.11BSD) 1996/10/24
Z  .\"
Z  .ds lq ``
Z  .ds rq ''
Z--- 2,8 ----
Z  .\" All rights reserved.  The Berkeley software License Agreement
Z  .\" specifies the terms and conditions for redistribution.
Z  .\"
Z! .\"	@(#)5.t	6.1.2 (2.11BSD) 1996/11/14
Z  .\"
Z  .ds lq ``
Z  .ds rq ''
Z***************
Z*** 327,333 ****
Z  .PP
Z  In \*(4B most of the server programs are started up by a
Z  ``super server'', the Internet daemon.  The Internet
Z! daemon, \fI/etc/inetd\fP, acts as a master server for
Z  programs specified in its configuration file, \fI/etc/inetd.conf\fP,
Z  listening for service requests for these servers, and starting
Z  up the appropriate program whenever a request is received.
Z--- 327,333 ----
Z  .PP
Z  In \*(4B most of the server programs are started up by a
Z  ``super server'', the Internet daemon.  The Internet
Z! daemon, \fI/usr/sbin/inetd\fP, acts as a master server for
Z  programs specified in its configuration file, \fI/etc/inetd.conf\fP,
Z  listening for service requests for these servers, and starting
Z  up the appropriate program whenever a request is received.
Z*** /VERSION.old	Sun Nov  3 17:00:54 1996
Z--- /VERSION	Wed Nov 13 21:38:20 1996
Z***************
Z*** 1,4 ****
Z! Current Patch Level: 342
Z  
Z  2.11 BSD
Z  ============
Z--- 1,4 ----
Z! Current Patch Level: 343
Z  
Z  2.11 BSD
Z  ============
SHAR_EOF
fi
exit 0
#	End of shell archive