mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
BSD 4.4 Lite Libexec Sources
This commit is contained in:
parent
9b50d90275
commit
ea022d1687
107 changed files with 27749 additions and 0 deletions
12
libexec/Makefile
Normal file
12
libexec/Makefile
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||
|
||||
SUBDIR= bugfiler comsat fingerd ftpd getNAME getty kpasswdd lfs_cleanerd \
|
||||
mail.local makekey rexecd rlogind rshd talkd telnetd tftpd uucpd
|
||||
|
||||
.if ${MACHINE} == "hp300"
|
||||
SUBDIR+=rbootd
|
||||
.elif ${MACHINE} == "luna68k"
|
||||
SUBDIR+=rbootd
|
||||
.endif
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
3
libexec/Makefile.inc
Normal file
3
libexec/Makefile.inc
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
|
||||
|
||||
BINDIR?= /usr/libexec
|
||||
17
libexec/bugfiler/Makefile
Normal file
17
libexec/bugfiler/Makefile
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||
|
||||
PROG= bugfiler
|
||||
CFLAGS+=-I${.CURDIR}
|
||||
SRCS= bugfiler.c error.c gethead.c process.c redist.c reply.c
|
||||
BINOWN= root
|
||||
BINMODE=4555
|
||||
MAN1= sendbug.0
|
||||
MAN8= bugfiler.0
|
||||
|
||||
beforeinstall:
|
||||
install -c -o bin -g ${BINGRP} -m 555 \
|
||||
${.CURDIR}/sendbug.sh ${DESTDIR}/usr/bin/sendbug
|
||||
install -c -o bin -g ${BINGRP} -m 444 ${.CURDIR}/bugformat \
|
||||
${DESTDIR}/usr/share/misc
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
92
libexec/bugfiler/bug.h
Normal file
92
libexec/bugfiler/bug.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 1986, 1987, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)bug.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
#define BUGS_HOME "owner-bugs@ucbvax.Berkeley.EDU"
|
||||
#define BUGS_ID "bugs"
|
||||
|
||||
/*
|
||||
* the METOO definition has the bugfiler exit with an error (-1) status
|
||||
* if there's a problem. This causes sendmail to send off a copy of the
|
||||
* report (as failed mail) to the "owner" of the mail alias that executed
|
||||
* the bugfiler. This is great if you would have otherwise lost the bug
|
||||
* report. It's not so great if you get a whole bunch of mail that you
|
||||
* really don't want.
|
||||
*/
|
||||
#define METOO
|
||||
|
||||
/* files */
|
||||
#define ACK_FILE "bug:ack" /* acknowledge file */
|
||||
#define DIST_FILE "bug:redist" /* redistribution file */
|
||||
#define ERROR_FILE "log" /* error file */
|
||||
#define LOCK_FILE "bug:lock" /* lock file name */
|
||||
#define SUMMARY_FILE "summary" /* summary file */
|
||||
#define TMP_BUG "errors/BUG_XXXXXX" /* tmp bug report */
|
||||
#define TMP_DIR "errors" /* tmp directory */
|
||||
|
||||
#define CHN (char *)NULL /* null arg string */
|
||||
#define COMMENT '#' /* comment in redist file */
|
||||
#define EOS (char)NULL /* end of string */
|
||||
#define ERR -1 /* error return */
|
||||
#define MAXLINELEN 200 /* max line length in message */
|
||||
#define NO 0 /* no/false */
|
||||
#define OK 0 /* okay return */
|
||||
#define YES 1 /* yes/true */
|
||||
|
||||
typedef struct {
|
||||
short found, /* line number if found */
|
||||
redist; /* if part of redist headers */
|
||||
int (*valid)(); /* validation routine */
|
||||
short len; /* length of tag */
|
||||
char *tag, /* leading tag */
|
||||
*line; /* actual line */
|
||||
} HEADER;
|
||||
extern HEADER mailhead[];
|
||||
|
||||
#define DATE_TAG 0 /* "Date:" offset */
|
||||
#define FROM_TAG 1 /* "From " offset */
|
||||
#define CFROM_TAG 2 /* "From:" offset */
|
||||
#define INDX_TAG 3 /* "Index:" offset */
|
||||
#define MSG_TAG 4 /* "Message-Id:" offset */
|
||||
#define RPLY_TAG 5 /* "Reply-To:" offset */
|
||||
#define RET_TAG 6 /* "Return-Path:" offset */
|
||||
#define SUBJ_TAG 7 /* "Subject:" offset */
|
||||
#define TO_TAG 8 /* "To:" offset */
|
||||
#define APPAR_TO_TAG 9 /* "Apparently-To:" offset */
|
||||
|
||||
/* so sizeof doesn't return 0 */
|
||||
extern char bfr[MAXBSIZE], /* general I/O buffer */
|
||||
dir[MAXNAMLEN], /* subject and folder */
|
||||
folder[MAXNAMLEN],
|
||||
tmpname[sizeof(TMP_BUG) + 5]; /* temp bug file */
|
||||
290
libexec/bugfiler/bugfiler.8
Normal file
290
libexec/bugfiler/bugfiler.8
Normal file
|
|
@ -0,0 +1,290 @@
|
|||
.\" Copyright (c) 1983, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)bugfiler.8 8.2 (Berkeley) 12/11/93
|
||||
.\"
|
||||
.Dd December 11, 1993
|
||||
.Dt BUGFILER 8
|
||||
.Os BSD 4.2
|
||||
.Sh NAME
|
||||
.Nm bugfiler
|
||||
.Nd file bug reports in folders automatically
|
||||
.Sh SYNOPSIS
|
||||
.Nm bugfiler
|
||||
.Op Fl ar
|
||||
.Op Fl v Ar version
|
||||
.Sh DESCRIPTION
|
||||
.Nm Bugfiler
|
||||
is a program to automatically intercept, acknowledge,
|
||||
redistribute and store bug reports.
|
||||
.Nm Bugfiler
|
||||
is normally invoked
|
||||
by the mail delivery program with a line similar to the following in
|
||||
.Pa /etc/aliases .
|
||||
.Bd -literal -offset indent
|
||||
bugs: "|bugfiler"
|
||||
.Ed
|
||||
.Pp
|
||||
It should be noted that the login
|
||||
.Dq bugs
|
||||
must exist for the bugfiler
|
||||
to run. Unless otherwise noted all paths used by
|
||||
.Nm bugfiler
|
||||
are
|
||||
relative to the home directory of this login.
|
||||
.Nm Bugfiler
|
||||
also
|
||||
expects all of its files and directories to be owned by
|
||||
.Dq bugs .
|
||||
.Pp
|
||||
Available options.
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a
|
||||
Do not send automatic mail acknowledgement to the bug report filer.
|
||||
(The default is to send the acknowledgement with the file
|
||||
.Pa ~bugs/version/bug:ack
|
||||
appended).
|
||||
.It Fl r
|
||||
Do not redistribute.
|
||||
.It Fl v Ar version
|
||||
Override the
|
||||
.Ar version
|
||||
provided within the bug report itself.
|
||||
.El
|
||||
.Pp
|
||||
For the bug report to be correctly filed, it must contain a line
|
||||
in the following format:
|
||||
.Pp
|
||||
.Bd -filled -offset indent -compact
|
||||
.Bl -column Index folder
|
||||
.It Index: Ta Em folder Ta Ar version
|
||||
.El
|
||||
.Ed
|
||||
.Pp
|
||||
The directories
|
||||
.Pa ~bugs/ Ns Ar version
|
||||
and
|
||||
.Pa ~bugs/ Ns Ar version/ Ns Em folder
|
||||
must exist before
|
||||
.Nm bugfiler
|
||||
attempts to store the bug report. Bug
|
||||
reports will be stored in files named by the concatenation of
|
||||
.Ar version ,
|
||||
.Em folder ,
|
||||
and sequential numbers, i.e. if
|
||||
.Ar version
|
||||
is
|
||||
.Dq 4.3 Tn BSD
|
||||
and
|
||||
.Em folder
|
||||
is
|
||||
.Dq ucb
|
||||
the first bug report will be placed in
|
||||
.Pa ~bugs/4.3BSD/ucb/1 .
|
||||
If
|
||||
.Em folder
|
||||
contains more than one component only
|
||||
the first one will be used, e.g. if
|
||||
.Em folder
|
||||
is
|
||||
.Dq bin/from.c
|
||||
or
|
||||
.Dq bin/adb/con.c
|
||||
it will be treated as if it were simply
|
||||
.Dq bin .
|
||||
.Pp
|
||||
.Pp
|
||||
If the
|
||||
.Fl r
|
||||
flag is not supplied, redistribution of the bug reports
|
||||
is done as specified in the file
|
||||
.Pa ~bugs/version/bug:redist .
|
||||
This file
|
||||
is in the format of the
|
||||
.Xr aliases 5
|
||||
file, including comments and
|
||||
entries requiring multiple lines, with the single exception that the
|
||||
.Em folder
|
||||
component of the
|
||||
.Dq Index:
|
||||
line replaces the name to alias.
|
||||
The special folder
|
||||
.Dq all:
|
||||
receives a redistribution of all bug reports
|
||||
sent to this
|
||||
.Ar version .
|
||||
For example, the
|
||||
.Pa bug:redist
|
||||
file
|
||||
.Pp
|
||||
.Bd -literal -offset indent -compact
|
||||
# bigbug gets a copy of everything
|
||||
all: bigbug
|
||||
# ucb folder redistribution list
|
||||
ucb: karels, kjd@coke.berkeley.edu
|
||||
ra@beno.css.gov
|
||||
.Ed
|
||||
.Pp
|
||||
will send copies of all bug reports with
|
||||
.Dq ucb
|
||||
as the
|
||||
.Em folder
|
||||
to bigbug, karels, kjd, and ra.
|
||||
.Pp
|
||||
Reports that cannot be filed, due to an invalid
|
||||
.Dq Index:
|
||||
line or
|
||||
some other error, are placed in the directory
|
||||
.Pa ~bugs/errors .
|
||||
The
|
||||
.Nm bugfiler
|
||||
maintainer should correct these bug reports and then
|
||||
run
|
||||
.Nm bugfiler ,
|
||||
with the corrected report as its standard input,
|
||||
as bug reports with errors are neither acknowledged or redistributed.
|
||||
All reports that
|
||||
.Nm bugfiler
|
||||
handles are logged in
|
||||
.Pa ~bugs/log.
|
||||
.Pp
|
||||
Valid bugs are also logged in the file
|
||||
.Pa ~bugs/version/summary.
|
||||
This file has an entry for each bug report for
|
||||
.Ar version
|
||||
in the
|
||||
format:
|
||||
.Pp
|
||||
.Bd -literal -offset indent -compact
|
||||
Filename Date
|
||||
Subject:
|
||||
Index:
|
||||
Owner: Bugs Bunny
|
||||
Status: Received
|
||||
.Ed
|
||||
.Pp
|
||||
.Li Filename
|
||||
is the concatenation of
|
||||
.Ar version ,
|
||||
.Em folder ,
|
||||
and a number
|
||||
as described above.
|
||||
.Xr Date
|
||||
is the date as reported by the system
|
||||
clock, using
|
||||
.Xr ctime 3 .
|
||||
The
|
||||
.Li Subject:
|
||||
and
|
||||
.Li Index:
|
||||
lines are
|
||||
copies of the
|
||||
.Dq Subject:
|
||||
and
|
||||
.Dq index:
|
||||
lines contained in the bug
|
||||
report. The
|
||||
.Li Owner
|
||||
and
|
||||
.Li Status
|
||||
fields are intended to provide a
|
||||
rudimentary method of tracking the status of bug reports.
|
||||
.Pp
|
||||
The file
|
||||
.Pa ~bugs/bug:lock
|
||||
is the focus of all locking for
|
||||
.Nm bugfiler .
|
||||
If you wish to manipulate any of the log or error files, rename or remove
|
||||
it and
|
||||
.Nm bugfiler
|
||||
will treat all bug reports that it receives as if
|
||||
they were incorrectly formatted, i.e. it will place them in the directory
|
||||
.Pa ~bugs/errors ,
|
||||
for later recovery by the
|
||||
.Nm bugfiler
|
||||
maintainer.
|
||||
Obviously, this file must be created when you first install
|
||||
.Nm bugfiler .
|
||||
.Pp
|
||||
All errors that occur before
|
||||
.Pa ~bugs/log
|
||||
is found are logged into the system
|
||||
log file, using
|
||||
.Xr syslog 8 .
|
||||
.Sh FILES
|
||||
.Bl -tag -width /usr/share/misc/bugformatxx -compact
|
||||
.It Pa ~bugs/bug:ack
|
||||
the acknowledgement message
|
||||
.It Pa ~bugs/bug:redist
|
||||
the redistribution list
|
||||
.It Pa ~bugs/bug:lock
|
||||
the locking file
|
||||
.It Pa ~bugs/errors/BUG_??????
|
||||
bug reports with format errors
|
||||
.It Pa ~bugs/log
|
||||
the log file
|
||||
.It Pa ~bugs/folder/summary
|
||||
the summary files
|
||||
.It Pa /usr/sbin/sendmail
|
||||
the mail delivery program
|
||||
.It Pa /usr/share/misc/bugformat
|
||||
a sample bug report format
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr sendbug 1 ,
|
||||
.Xr aliases 5 ,
|
||||
.Xr syslog 8
|
||||
.Sh BUGS
|
||||
Since mail can be forwarded in a number of different ways,
|
||||
.Nm bugfiler
|
||||
does not recognize forwarded mail and will acknowledge to the forwarder
|
||||
instead of the original sender unless there is a
|
||||
.Dq Reply-To
|
||||
field in the
|
||||
header.
|
||||
.Pp
|
||||
This version of
|
||||
.Nm bugfiler
|
||||
is not compatible with the version
|
||||
released with
|
||||
.Bx 4.3
|
||||
in that it doesn't complain to the sender about
|
||||
incorrectly formatted bug reports.
|
||||
Frankly, we got tired of the profanity, not to mention the extended
|
||||
conversations
|
||||
.Nm bugfiler
|
||||
was holding with
|
||||
.Xr vacation 1 .
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.2 .
|
||||
167
libexec/bugfiler/bugfiler.c
Normal file
167
libexec/bugfiler/bugfiler.c
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Copyright (c) 1983, 1986, 1987, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1983, 1986, 1987, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)bugfiler.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Bug report processing program, designed to be invoked
|
||||
* through aliases(5).
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "bug.h"
|
||||
#include "extern.h"
|
||||
|
||||
char bfr[MAXBSIZE], /* general I/O buffer */
|
||||
tmpname[sizeof(TMP_BUG) + 5]; /* temp bug file */
|
||||
|
||||
static void logit __P((void));
|
||||
static void make_copy __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern char *optarg; /* getopt arguments */
|
||||
register struct passwd *pwd; /* bugs password entry */
|
||||
register int ch; /* getopts char */
|
||||
int do_ack, /* acknowledge bug report */
|
||||
do_redist; /* redistribut BR */
|
||||
char *argversion; /* folder name provided */
|
||||
|
||||
do_ack = do_redist = YES;
|
||||
argversion = NULL;
|
||||
while ((ch = getopt(argc, argv, "av:r")) != EOF)
|
||||
switch(ch) {
|
||||
case 'a':
|
||||
do_ack = NO;
|
||||
break;
|
||||
case 'v':
|
||||
argversion = optarg;
|
||||
break;
|
||||
case 'r':
|
||||
do_redist = NO;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
fputs("usage: bugfiler [-ar] [-v version]\n", stderr);
|
||||
error("usage: bugfiler [-ar] [-v version]", CHN);
|
||||
}
|
||||
|
||||
if (!(pwd = getpwnam(BUGS_ID)))
|
||||
error("can't find bugs login.", BUGS_ID);
|
||||
|
||||
if (chdir(pwd->pw_dir)) /* change to bugs home directory */
|
||||
error("can't chdir to %s.", pwd->pw_dir);
|
||||
|
||||
if (seteuid(pwd->pw_uid))
|
||||
error("can't set id to %s.", BUGS_ID);
|
||||
|
||||
(void)umask(02); /* everything is 664 */
|
||||
seterr(); /* redirect to log file */
|
||||
logit(); /* log report arrival */
|
||||
make_copy(); /* save copy in case */
|
||||
gethead(do_redist);
|
||||
|
||||
if (argversion) /* specific folder requested */
|
||||
(void)strcpy(dir, argversion);
|
||||
|
||||
process();
|
||||
|
||||
if (seteuid(0))
|
||||
error("can't set id to root.", CHN);
|
||||
if (do_ack)
|
||||
reply();
|
||||
if (do_redist)
|
||||
redist();
|
||||
(void)unlink(tmpname);
|
||||
exit(OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* make_copy --
|
||||
* make a copy of bug report in error folder
|
||||
*/
|
||||
static void
|
||||
make_copy()
|
||||
{
|
||||
register int cnt, /* read return value */
|
||||
tfd; /* temp file descriptor */
|
||||
|
||||
if (access(TMP_DIR, F_OK))
|
||||
(void)mkdir(TMP_DIR, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH);
|
||||
(void)strcpy(tmpname, TMP_BUG);
|
||||
if (tfd = mkstemp(tmpname)) {
|
||||
while ((cnt = read(fileno(stdin),
|
||||
bfr, sizeof(bfr))) != ERR && cnt)
|
||||
write(tfd, bfr, cnt);
|
||||
(void)close(tfd);
|
||||
return;
|
||||
}
|
||||
error("can't make copy using %s.", tmpname);
|
||||
}
|
||||
|
||||
/*
|
||||
* logit --
|
||||
* log this run of the bugfiler
|
||||
*/
|
||||
static void
|
||||
logit()
|
||||
{
|
||||
struct timeval tp;
|
||||
char *C1, *C2;
|
||||
|
||||
if (gettimeofday(&tp, (struct timezone *)NULL))
|
||||
error("can't get time of day.", CHN);
|
||||
for (C1 = C2 = ctime(&tp.tv_sec); *C1 && *C1 != '\n'; ++C1);
|
||||
*C1 = EOS;
|
||||
fputs(C2, stderr);
|
||||
}
|
||||
32
libexec/bugfiler/bugformat
Normal file
32
libexec/bugfiler/bugformat
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
Subject: Short summary of the problem (please make this meaningful!)
|
||||
Index: folder 4.4BSD-alpha
|
||||
|
||||
Description:
|
||||
Detailed description of the problem, suggestion, or complaint.
|
||||
Repeat-By:
|
||||
Describe the sequence of events that causes the problem
|
||||
to occur.
|
||||
Fix:
|
||||
Description of how to fix the problem. If you don't know a
|
||||
fix for the problem, don't include this section.
|
||||
|
||||
-------- Remove this line and what's below it, for reference only. --------
|
||||
|
||||
To ensure that your bug report is handled correctly by bugfiler(8),
|
||||
you must replace "folder" (on the line above starting with "Index:")
|
||||
with one of the following values:
|
||||
|
||||
folder ::= bin | doc | etc | games | ideas | include | lib
|
||||
| local | man | misc | new | sys | ucb
|
||||
| usr.bin | usr.lib
|
||||
|
||||
If you're not running 4.3BSD, you should also replace "4.3BSD" on
|
||||
the same line with one of the following values.
|
||||
|
||||
version ::= 4.3BSD | 4.3BSD-tahoe | 4.3BSD-reno | net2
|
||||
| 4.4BSD-alpha
|
||||
|
||||
For example, if your bug concerns the program "/usr/bin/file" and
|
||||
you're currently running 4.3BSD-Reno, you should replace "folder"
|
||||
with "usr.bin/file", and "4.4BSD-alpha" with "4.3BSD-Reno". The folder
|
||||
"ideas" is for suggestions.
|
||||
89
libexec/bugfiler/error.c
Normal file
89
libexec/bugfiler/error.c
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 1986, 1987, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)error.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "bug.h"
|
||||
#include "extern.h"
|
||||
|
||||
static short err_redir; /* stderr redirected */
|
||||
|
||||
/*
|
||||
* seterr --
|
||||
* redirect stderr for error processing
|
||||
*/
|
||||
void
|
||||
seterr()
|
||||
{
|
||||
if (!freopen(ERROR_FILE, "a", stderr))
|
||||
error("can't open error file %s.", ERROR_FILE);
|
||||
err_redir = YES;
|
||||
}
|
||||
|
||||
/*
|
||||
* error --
|
||||
* write errors to log file and die
|
||||
*/
|
||||
void
|
||||
error(fmt, arg)
|
||||
register char *fmt,
|
||||
*arg;
|
||||
{
|
||||
static char logmsg[MAXLINELEN]; /* syslog message */
|
||||
|
||||
if (err_redir) {
|
||||
/* don't combine these, "fmt" may not require "arg" */
|
||||
fprintf(stderr, "\t%s\n\t", tmpname);
|
||||
fprintf(stderr, fmt, arg);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
else {
|
||||
sprintf(logmsg, "bugfiler: %s", fmt);
|
||||
syslog(LOG_ERR, logmsg, arg);
|
||||
}
|
||||
#ifdef METOO
|
||||
exit(ERR);
|
||||
#else
|
||||
exit(OK);
|
||||
#endif
|
||||
}
|
||||
41
libexec/bugfiler/extern.h
Normal file
41
libexec/bugfiler/extern.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
void error __P((char *, char *));
|
||||
void gethead __P((int));
|
||||
int process __P((void));
|
||||
void redist __P((void));
|
||||
void reply __P((void));
|
||||
void seterr __P((void));
|
||||
165
libexec/bugfiler/gethead.c
Normal file
165
libexec/bugfiler/gethead.c
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (c) 1986, 1987, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)gethead.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
#include "bug.h"
|
||||
#include "extern.h"
|
||||
|
||||
static int chk1 __P((char *));
|
||||
static int pbuf __P((char *));
|
||||
|
||||
#define ENT(X) sizeof(X) - 1, X
|
||||
HEADER mailhead[] = { /* mail headers */
|
||||
{ NO, YES, NULL, ENT("Date:"), },
|
||||
{ NO, NO, NULL, ENT("From "), },
|
||||
{ NO, YES, NULL, ENT("From:"), },
|
||||
{ NO, NO, chk1, ENT("Index:"), },
|
||||
{ NO, YES, NULL, ENT("Message-Id:"), },
|
||||
{ NO, YES, NULL, ENT("Reply-To:"), },
|
||||
{ NO, YES, NULL, ENT("Return-Path:"), },
|
||||
{ NO, NO, pbuf, ENT("Subject:"), },
|
||||
{ NO, YES, NULL, ENT("To:"), },
|
||||
{ NO, NO, NULL, ENT("Apparently-To:"), },
|
||||
{ ERR, }
|
||||
};
|
||||
|
||||
FILE *dfp; /* distf file pointer */
|
||||
char dir[MAXNAMLEN], /* subject and folder */
|
||||
folder[MAXNAMLEN];
|
||||
|
||||
/*
|
||||
* gethead --
|
||||
* read mail and bug headers from bug report, construct redist headers
|
||||
*/
|
||||
void
|
||||
gethead(redist)
|
||||
int redist;
|
||||
{
|
||||
register HEADER *hp; /* mail header pointer */
|
||||
|
||||
if (redist) {
|
||||
int fd;
|
||||
char *distf;
|
||||
|
||||
distf = strdup(_PATH_TMP);
|
||||
if (!(fd = mkstemp(distf)) || !(dfp = fdopen(fd, "w+")))
|
||||
error("can't create redistribution file %s.", distf);
|
||||
/* disappear after last reference is closed */
|
||||
(void)unlink(distf);
|
||||
free(distf);
|
||||
}
|
||||
if (!freopen(tmpname, "r", stdin))
|
||||
error("can't read temporary bug file %s.", tmpname);
|
||||
|
||||
while (fgets(bfr, sizeof(bfr), stdin)) {
|
||||
for (hp = mailhead; hp->found != ERR; ++hp)
|
||||
if (!hp->found)
|
||||
if (!strncmp(hp->tag, bfr, hp->len)) {
|
||||
if (hp->valid && !((*(hp->valid))(bfr)))
|
||||
break;
|
||||
if (!(hp->line =
|
||||
malloc((u_int)(strlen(bfr) + 1))))
|
||||
error("malloc failed.", CHN);
|
||||
(void)strcpy(hp->line, bfr);
|
||||
hp->found = YES;
|
||||
break;
|
||||
}
|
||||
if ((hp->found == ERR || hp->redist) && redist)
|
||||
fputs(bfr, dfp);
|
||||
}
|
||||
|
||||
if (!mailhead[INDX_TAG].found)
|
||||
error("no readable \"Index:\" header in bug report.", CHN);
|
||||
}
|
||||
|
||||
/*
|
||||
* chk1 --
|
||||
* parse the "Index:" line into folder and directory
|
||||
*/
|
||||
static int
|
||||
chk1(line)
|
||||
char *line;
|
||||
{
|
||||
register char *C; /* tmp pointer */
|
||||
struct stat sbuf; /* existence check */
|
||||
|
||||
if (sscanf(line, " Index: %s %s ", folder, dir) != 2)
|
||||
return(NO);
|
||||
if (C = strchr(folder, '/')) { /* deal with "bin/from.c" */
|
||||
if (C == folder)
|
||||
return(NO);
|
||||
*C = EOS;
|
||||
}
|
||||
if (stat(dir, &sbuf) || (sbuf.st_mode & S_IFMT) != S_IFDIR)
|
||||
return(NO);
|
||||
(void)pbuf(line);
|
||||
return(YES);
|
||||
}
|
||||
|
||||
/*
|
||||
* pbuf --
|
||||
* kludge so that summary file looks pretty
|
||||
*/
|
||||
static int
|
||||
pbuf(line)
|
||||
char *line;
|
||||
{
|
||||
register char *rp, /* tmp pointers */
|
||||
*wp;
|
||||
|
||||
for (rp = line; *rp == ' ' || *rp == '\t'; ++rp);
|
||||
for (wp = line; *rp; ++wp) {
|
||||
if ((*wp = *rp++) != ' ' && *wp != '\t')
|
||||
continue;
|
||||
*wp = ' ';
|
||||
while (*rp == ' ' || *rp == '\t')
|
||||
++rp;
|
||||
}
|
||||
if (wp[-1] == ' ') /* wp can't == line */
|
||||
--wp;
|
||||
*wp = EOS;
|
||||
return(YES);
|
||||
}
|
||||
38
libexec/bugfiler/pathnames.h
Normal file
38
libexec/bugfiler/pathnames.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
#define MAIL_CMD "/usr/sbin/sendmail -i -t -F \"Bugs Bunny\" -f owner-bugs"
|
||||
#undef _PATH_TMP
|
||||
#define _PATH_TMP "/tmp/BUG_XXXXXX"
|
||||
115
libexec/bugfiler/process.c
Normal file
115
libexec/bugfiler/process.c
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 1986, 1987, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)process.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "bug.h"
|
||||
#include "extern.h"
|
||||
|
||||
char pfile[MAXPATHLEN]; /* permanent file name */
|
||||
|
||||
static int getnext __P((void));
|
||||
|
||||
/*
|
||||
* process --
|
||||
* copy report to permanent file,
|
||||
* update summary file.
|
||||
*/
|
||||
int
|
||||
process()
|
||||
{
|
||||
register int rval; /* read return value */
|
||||
struct timeval tp; /* time of day */
|
||||
int lfd; /* lock file descriptor */
|
||||
|
||||
if (access(LOCK_FILE, R_OK) || (lfd = open(LOCK_FILE, O_RDONLY, 0)) < 0)
|
||||
error("can't find lock file %s.", LOCK_FILE);
|
||||
if (flock(lfd, LOCK_EX))
|
||||
error("can't get lock.", CHN);
|
||||
sprintf(pfile, "%s/%s/%d", dir, folder, getnext());
|
||||
fprintf(stderr, "\t%s\n", pfile);
|
||||
if (!(freopen(pfile, "w", stdout)))
|
||||
error("can't create %s.", pfile);
|
||||
rewind(stdin);
|
||||
while ((rval = read(fileno(stdin), bfr, sizeof(bfr))) != ERR && rval)
|
||||
if (write(fileno(stdout), bfr, rval) != rval)
|
||||
error("write to %s failed.", pfile);
|
||||
|
||||
/* append information to the summary file */
|
||||
sprintf(bfr, "%s/%s", dir, SUMMARY_FILE);
|
||||
if (!(freopen(bfr, "a", stdout)))
|
||||
error("can't append to summary file %s.", bfr);
|
||||
if (gettimeofday(&tp, (struct timezone *)NULL))
|
||||
error("can't get time of day.", CHN);
|
||||
printf("\n%s\t\t%s\t%s\t%s\tOwner: Bugs Bunny\n\tStatus: Received\n",
|
||||
pfile, ctime(&tp.tv_sec), mailhead[INDX_TAG].line,
|
||||
mailhead[SUBJ_TAG].found ? mailhead[SUBJ_TAG].line : "Subject:\n");
|
||||
(void)flock(lfd, LOCK_UN);
|
||||
(void)fclose(stdout);
|
||||
}
|
||||
|
||||
/*
|
||||
* getnext --
|
||||
* get next file name (number)
|
||||
*/
|
||||
static int
|
||||
getnext()
|
||||
{
|
||||
register struct dirent *d; /* directory structure */
|
||||
register DIR *dirp; /* directory pointer */
|
||||
register int highval, newval;
|
||||
register char *p;
|
||||
|
||||
(void)sprintf(bfr, "%s/%s", dir, folder);
|
||||
if (!(dirp = opendir(bfr)))
|
||||
error("can't read folder directory %s.", bfr);
|
||||
for (highval = -1; d = readdir(dirp);) {
|
||||
for (p = d->d_name; *p && isdigit(*p); ++p);
|
||||
if (!*p && (newval = atoi(d->d_name)) > highval)
|
||||
highval = newval;
|
||||
}
|
||||
closedir(dirp);
|
||||
return(++highval);
|
||||
}
|
||||
131
libexec/bugfiler/redist.c
Normal file
131
libexec/bugfiler/redist.c
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 1986, 1987, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)redist.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bug.h"
|
||||
#include "pathnames.h"
|
||||
#include "extern.h"
|
||||
|
||||
/*
|
||||
* redist --
|
||||
* Redistribute a bug report to those people indicated in the
|
||||
* redistribution list file.
|
||||
*/
|
||||
void
|
||||
redist()
|
||||
{
|
||||
extern FILE *dfp; /* dist file fp */
|
||||
extern char pfile[]; /* permanent bug file */
|
||||
register char *C1, *C2;
|
||||
FILE *pf;
|
||||
int group;
|
||||
|
||||
(void)sprintf(bfr, "%s/%s", dir, DIST_FILE);
|
||||
if (!freopen(bfr, "r", stdin))
|
||||
return;
|
||||
for (pf = NULL, group = 0; fgets(bfr, sizeof(bfr), stdin);) {
|
||||
if (C1 = strchr(bfr, '\n'))
|
||||
*C1 = '\0';
|
||||
nextline: if (*bfr == COMMENT ||
|
||||
isspace(*bfr) || !(C1 = index(bfr, ':')))
|
||||
continue;
|
||||
*C1 = EOS;
|
||||
if (!strcmp(bfr, folder) || !strcmp(bfr, "all")) {
|
||||
for (++C1; *C1 && (*C1 == ' ' || *C1 == '\t'); ++C1);
|
||||
if (!*C1) /* if empty list */
|
||||
continue;
|
||||
if (!pf) {
|
||||
if (!(pf = popen(MAIL_CMD, "w")))
|
||||
error("sendmail pipe failed.", CHN);
|
||||
if (mailhead[SUBJ_TAG].found)
|
||||
fprintf(pf,
|
||||
"%s", mailhead[SUBJ_TAG].line);
|
||||
else
|
||||
fprintf(pf,
|
||||
"Subject: Untitled Bug Report\n");
|
||||
if (!mailhead[TO_TAG].line) {
|
||||
if (mailhead[APPAR_TO_TAG].line)
|
||||
fprintf(pf, "To%s",
|
||||
strchr(mailhead[APPAR_TO_TAG].line,
|
||||
':'));
|
||||
else
|
||||
fprintf(pf, "To: %s\n", BUGS_ID);
|
||||
}
|
||||
fputs("Resent-To: ", pf);
|
||||
}
|
||||
/*
|
||||
* write out first entry, then succeeding entries
|
||||
* backward compatible, handles back slashes at end
|
||||
* of line
|
||||
*/
|
||||
if (group++)
|
||||
fputs(", ", pf);
|
||||
for (;;) {
|
||||
if (C2 = strchr(C1, '\\'))
|
||||
*C2 = EOS;
|
||||
fputs(C1, pf);
|
||||
if (!fgets(bfr, sizeof(bfr), stdin))
|
||||
break;
|
||||
if (C1 = strchr(bfr, '\n'))
|
||||
*C1 = '\0';
|
||||
if (*bfr != ' ' && *bfr != '\t')
|
||||
goto nextline;
|
||||
for (C1 = bfr;
|
||||
*C1 && (*C1 == ' ' || *C1 == '\t'); ++C1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!pf)
|
||||
return;
|
||||
|
||||
putc('\n', pf);
|
||||
|
||||
rewind(dfp);
|
||||
/* add Reference header and copy bug report out */
|
||||
while (fgets(bfr, sizeof(bfr), dfp) && *bfr != '\n')
|
||||
fputs(bfr, pf);
|
||||
fprintf(pf, "\n%sReference: %s\n\n", mailhead[INDX_TAG].line, pfile);
|
||||
while (fgets(bfr, sizeof(bfr), dfp))
|
||||
fputs(bfr, pf);
|
||||
(void)pclose(pf);
|
||||
}
|
||||
118
libexec/bugfiler/reply.c
Normal file
118
libexec/bugfiler/reply.c
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (c) 1986, 1987, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)reply.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "bug.h"
|
||||
#include "extern.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
/*
|
||||
* reply --
|
||||
* tell the user we got their silly little bug report
|
||||
*/
|
||||
void
|
||||
reply()
|
||||
{
|
||||
register char *C, /* traveling pointer */
|
||||
*to; /* who we're replying to */
|
||||
register int afd, /* ack file descriptor */
|
||||
rval; /* return value */
|
||||
FILE *pf; /* pipe pointer */
|
||||
|
||||
if (mailhead[RPLY_TAG].found) {
|
||||
for (C = mailhead[RPLY_TAG].line + mailhead[RPLY_TAG].len;
|
||||
*C != '\n' && (*C == ' ' || *C == '\t');++C);
|
||||
if (*C)
|
||||
goto gotone;
|
||||
}
|
||||
if (mailhead[FROM_TAG].found) {
|
||||
for (C = mailhead[FROM_TAG].line + mailhead[FROM_TAG].len;
|
||||
*C != '\n' && (*C == ' ' || *C == '\t');++C);
|
||||
if (*C)
|
||||
goto gotone;
|
||||
}
|
||||
if (mailhead[CFROM_TAG].found) {
|
||||
for (C = mailhead[CFROM_TAG].line + mailhead[CFROM_TAG].len;
|
||||
*C != '\n' && (*C == ' ' || *C == '\t');++C);
|
||||
if (*C)
|
||||
goto gotone;
|
||||
}
|
||||
return;
|
||||
|
||||
/* if it's a foo <XXX>, get the XXX, else get foo (first string) */
|
||||
gotone: if (to = strchr(C, '<'))
|
||||
for (C = ++to;
|
||||
*C != '\n' && *C != ' ' && *C != '\t' && *C != '>';++C);
|
||||
else {
|
||||
to = C;
|
||||
for (to = C++;*C != '\n' && *C != ' ' && *C != '\t';++C);
|
||||
}
|
||||
*C = EOS;
|
||||
|
||||
if (!(pf = popen(MAIL_CMD, "w")))
|
||||
error("sendmail pipe failed.", CHN);
|
||||
|
||||
fprintf(pf, "Reply-To: %s\nFrom: %s (Bugs Bunny)\nTo: %s\n",
|
||||
BUGS_HOME, BUGS_HOME, to);
|
||||
if (mailhead[SUBJ_TAG].found)
|
||||
fprintf(pf, "Subject: Re:%s",
|
||||
mailhead[SUBJ_TAG].line + mailhead[SUBJ_TAG].len);
|
||||
else
|
||||
fputs("Subject: Bug report acknowledgement.\n", pf);
|
||||
if (mailhead[DATE_TAG].found)
|
||||
fprintf(pf, "In-Acknowledgement-Of: Your message of %s",
|
||||
mailhead[DATE_TAG].line + mailhead[DATE_TAG].len);
|
||||
if (mailhead[MSG_TAG].found)
|
||||
fprintf(pf, "\t\t%s", mailhead[MSG_TAG].line);
|
||||
fputs("Precedence: bulk\n\n", pf); /* vacation(1) uses this... */
|
||||
fflush(pf);
|
||||
|
||||
(void)sprintf(bfr, "%s/%s", dir, ACK_FILE);
|
||||
if ((afd = open(bfr, O_RDONLY, 0)) >= 0) {
|
||||
while ((rval = read(afd, bfr, sizeof(bfr))) != ERR && rval)
|
||||
(void)write(fileno(pf), bfr, rval);
|
||||
(void)close(afd);
|
||||
}
|
||||
pclose(pf);
|
||||
}
|
||||
85
libexec/bugfiler/sendbug.1
Normal file
85
libexec/bugfiler/sendbug.1
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
.\" Copyright (c) 1983, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)sendbug.1 8.1 (Berkeley) 6/4/93
|
||||
.\"
|
||||
.Dd June 4, 1993
|
||||
.Dt SENDBUG 1
|
||||
.Os BSD 4.2
|
||||
.Sh NAME
|
||||
.Nm sendbug
|
||||
.Nd mail a system bug report to 4bsd-bugs
|
||||
.Sh SYNOPSIS
|
||||
.Nm sendbug
|
||||
.Op Ar address
|
||||
.Sh DESCRIPTION
|
||||
Bug reports sent to `4bsd-bugs@Berkeley.EDU' are intercepted
|
||||
by a program which expects bug reports to conform to a standard format.
|
||||
.Nm Sendbug
|
||||
is a shell script to help the user compose and mail bug reports
|
||||
in the correct format.
|
||||
.Nm Sendbug
|
||||
works by invoking the editor specified by the environment variable
|
||||
.Ev EDITOR
|
||||
on a temporary copy of the bug report format outline. The user must fill in the
|
||||
appropriate fields and exit the editor.
|
||||
.Nm Sendbug
|
||||
then mails the completed report to `4bsd-bugs@Berkeley.EDU' or the
|
||||
.Ar address
|
||||
specified on the command line.
|
||||
.Sh ENVIRONMENT
|
||||
.Nm Sendbug
|
||||
will utilize the following environment variable if it exists:
|
||||
.Bl -tag -width EDITOR
|
||||
.It Ev EDITOR
|
||||
Specifies the preferred editor. If
|
||||
.Ev EDITOR
|
||||
is not set,
|
||||
.Nm
|
||||
defaults to
|
||||
.Xr vi 1 .
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /usr/share/misc/bugformat -compact
|
||||
.It Pa /usr/share/misc/bugformat
|
||||
Contains the bug report outline.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr vi 1 ,
|
||||
.Xr environ 7 ,
|
||||
.Xr bugfiler 8 ,
|
||||
.Xr sendmail 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm sendbug
|
||||
command
|
||||
appeared in
|
||||
.Bx 4.2 .
|
||||
66
libexec/bugfiler/sendbug.sh
Normal file
66
libexec/bugfiler/sendbug.sh
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#!/bin/sh -
|
||||
#
|
||||
# Copyright (c) 1983, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)sendbug.sh 8.1 (Berkeley) 6/4/93
|
||||
#
|
||||
|
||||
# create a bug report and mail it to '4bsd-bugs'.
|
||||
|
||||
PATH=/bin:/sbin:/usr/sbin:/usr/bin
|
||||
export PATH
|
||||
|
||||
TEMP=/tmp/bug$$
|
||||
FORMAT=/usr/share/misc/bugformat
|
||||
|
||||
# uucp sites should use ": ${BUGADDR=ucbvax!4bsd-bugs}" with a suitable path.
|
||||
: ${BUGADDR=4bsd-bugs@CS.Berkeley.EDU}
|
||||
: ${EDITOR=vi}
|
||||
|
||||
trap 'rm -f $TEMP ; exit 1' 1 2 3 13 15
|
||||
|
||||
cp $FORMAT $TEMP
|
||||
chmod u+w $TEMP
|
||||
if $EDITOR $TEMP
|
||||
then
|
||||
if cmp -s $FORMAT $TEMP
|
||||
then
|
||||
echo "File not changed, no bug report submitted."
|
||||
exit
|
||||
fi
|
||||
case "$#" in
|
||||
0) sendmail -t -oi $BUGADDR < $TEMP ;;
|
||||
*) sendmail -t -oi "$@" < $TEMP ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
rm -f $TEMP
|
||||
6
libexec/comsat/Makefile
Normal file
6
libexec/comsat/Makefile
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||
|
||||
PROG= comsat
|
||||
MAN8= comsat.0
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
96
libexec/comsat/comsat.8
Normal file
96
libexec/comsat/comsat.8
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
.\" Copyright (c) 1983, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)comsat.8 8.1 (Berkeley) 6/4/93
|
||||
.\"
|
||||
.Dd June 4, 1993
|
||||
.Dt COMSAT 8
|
||||
.Os BSD 4.2
|
||||
.Sh NAME
|
||||
.Nm comsat
|
||||
.Nd biff server
|
||||
.Sh SYNOPSIS
|
||||
.Nm comsat
|
||||
.Sh DESCRIPTION
|
||||
.Nm Comsat
|
||||
is the server process which receives reports of incoming mail
|
||||
and notifies users if they have requested this service.
|
||||
.Nm Comsat
|
||||
receives messages on a datagram port associated with the
|
||||
.Dq biff
|
||||
service
|
||||
specification (see
|
||||
.Xr services 5
|
||||
and
|
||||
.Xr inetd 8 ) .
|
||||
The one line messages are of the form:
|
||||
.Pp
|
||||
.Dl user@mailbox-offset
|
||||
.Pp
|
||||
If the
|
||||
.Em user
|
||||
specified is logged in to the system and the associated terminal has
|
||||
the owner execute bit turned on (by a
|
||||
.Dq Li biff y ) ,
|
||||
the
|
||||
.Em offset
|
||||
is used as a seek offset into the appropriate mailbox file and
|
||||
the first 7 lines or 560 characters of the message are printed
|
||||
on the user's terminal. Lines which appear to be part of
|
||||
the message header other than the
|
||||
.Dq From ,
|
||||
.Dq \&To ,
|
||||
.Dq Date ,
|
||||
or
|
||||
.Dq Subject
|
||||
lines are not included in the displayed message.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /var/run/utmp -compact
|
||||
.It Pa /var/run/utmp
|
||||
to find out who's logged on and on what terminals
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr biff 1 ,
|
||||
.Xr inetd 8
|
||||
.Sh BUGS
|
||||
The message header filtering is prone to error.
|
||||
The density of the information presented is near the theoretical minimum.
|
||||
.Pp
|
||||
Users should be notified of mail which arrives on other
|
||||
machines than the one to which they are currently logged in.
|
||||
.Pp
|
||||
The notification should appear in a separate window so it
|
||||
does not mess up the screen.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.2 .
|
||||
284
libexec/comsat/comsat.c
Normal file
284
libexec/comsat/comsat.c
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
* Copyright (c) 1980, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1980, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)comsat.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <paths.h>
|
||||
#include <pwd.h>
|
||||
#include <sgtty.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <utmp.h>
|
||||
|
||||
int debug = 0;
|
||||
#define dsyslog if (debug) syslog
|
||||
|
||||
#define MAXIDLE 120
|
||||
|
||||
char hostname[MAXHOSTNAMELEN];
|
||||
struct utmp *utmp = NULL;
|
||||
time_t lastmsgtime;
|
||||
int nutmp, uf;
|
||||
|
||||
void jkfprintf __P((FILE *, char[], off_t));
|
||||
void mailfor __P((char *));
|
||||
void notify __P((struct utmp *, off_t));
|
||||
void onalrm __P((int));
|
||||
void reapchildren __P((int));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
struct sockaddr_in from;
|
||||
register int cc;
|
||||
int fromlen;
|
||||
char msgbuf[100];
|
||||
|
||||
/* verify proper invocation */
|
||||
fromlen = sizeof(from);
|
||||
if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) {
|
||||
(void)fprintf(stderr,
|
||||
"comsat: getsockname: %s.\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
openlog("comsat", LOG_PID, LOG_DAEMON);
|
||||
if (chdir(_PATH_MAILDIR)) {
|
||||
syslog(LOG_ERR, "chdir: %s: %m", _PATH_MAILDIR);
|
||||
(void) recv(0, msgbuf, sizeof(msgbuf) - 1, 0);
|
||||
exit(1);
|
||||
}
|
||||
if ((uf = open(_PATH_UTMP, O_RDONLY, 0)) < 0) {
|
||||
syslog(LOG_ERR, "open: %s: %m", _PATH_UTMP);
|
||||
(void) recv(0, msgbuf, sizeof(msgbuf) - 1, 0);
|
||||
exit(1);
|
||||
}
|
||||
(void)time(&lastmsgtime);
|
||||
(void)gethostname(hostname, sizeof(hostname));
|
||||
onalrm(0);
|
||||
(void)signal(SIGALRM, onalrm);
|
||||
(void)signal(SIGTTOU, SIG_IGN);
|
||||
(void)signal(SIGCHLD, reapchildren);
|
||||
for (;;) {
|
||||
cc = recv(0, msgbuf, sizeof(msgbuf) - 1, 0);
|
||||
if (cc <= 0) {
|
||||
if (errno != EINTR)
|
||||
sleep(1);
|
||||
errno = 0;
|
||||
continue;
|
||||
}
|
||||
if (!nutmp) /* no one has logged in yet */
|
||||
continue;
|
||||
sigblock(sigmask(SIGALRM));
|
||||
msgbuf[cc] = '\0';
|
||||
(void)time(&lastmsgtime);
|
||||
mailfor(msgbuf);
|
||||
sigsetmask(0L);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
reapchildren(signo)
|
||||
int signo;
|
||||
{
|
||||
while (wait3(NULL, WNOHANG, NULL) > 0);
|
||||
}
|
||||
|
||||
void
|
||||
onalrm(signo)
|
||||
int signo;
|
||||
{
|
||||
static u_int utmpsize; /* last malloced size for utmp */
|
||||
static u_int utmpmtime; /* last modification time for utmp */
|
||||
struct stat statbf;
|
||||
|
||||
if (time(NULL) - lastmsgtime >= MAXIDLE)
|
||||
exit(0);
|
||||
(void)alarm((u_int)15);
|
||||
(void)fstat(uf, &statbf);
|
||||
if (statbf.st_mtime > utmpmtime) {
|
||||
utmpmtime = statbf.st_mtime;
|
||||
if (statbf.st_size > utmpsize) {
|
||||
utmpsize = statbf.st_size + 10 * sizeof(struct utmp);
|
||||
if ((utmp = realloc(utmp, utmpsize)) == NULL) {
|
||||
syslog(LOG_ERR, "%s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
(void)lseek(uf, (off_t)0, L_SET);
|
||||
nutmp = read(uf, utmp, (int)statbf.st_size)/sizeof(struct utmp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mailfor(name)
|
||||
char *name;
|
||||
{
|
||||
register struct utmp *utp = &utmp[nutmp];
|
||||
register char *cp;
|
||||
off_t offset;
|
||||
|
||||
if (!(cp = strchr(name, '@')))
|
||||
return;
|
||||
*cp = '\0';
|
||||
offset = atoi(cp + 1);
|
||||
while (--utp >= utmp)
|
||||
if (!strncmp(utp->ut_name, name, sizeof(utmp[0].ut_name)))
|
||||
notify(utp, offset);
|
||||
}
|
||||
|
||||
static char *cr;
|
||||
|
||||
void
|
||||
notify(utp, offset)
|
||||
register struct utmp *utp;
|
||||
off_t offset;
|
||||
{
|
||||
FILE *tp;
|
||||
struct stat stb;
|
||||
struct sgttyb gttybuf;
|
||||
char tty[20], name[sizeof(utmp[0].ut_name) + 1];
|
||||
|
||||
(void)snprintf(tty, sizeof(tty), "%s%.*s",
|
||||
_PATH_DEV, (int)sizeof(utp->ut_line), utp->ut_line);
|
||||
if (strchr(tty + sizeof(_PATH_DEV) - 1, '/')) {
|
||||
/* A slash is an attempt to break security... */
|
||||
syslog(LOG_AUTH | LOG_NOTICE, "'/' in \"%s\"", tty);
|
||||
return;
|
||||
}
|
||||
if (stat(tty, &stb) || !(stb.st_mode & S_IEXEC)) {
|
||||
dsyslog(LOG_DEBUG, "%s: wrong mode on %s", utp->ut_name, tty);
|
||||
return;
|
||||
}
|
||||
dsyslog(LOG_DEBUG, "notify %s on %s\n", utp->ut_name, tty);
|
||||
if (fork())
|
||||
return;
|
||||
(void)signal(SIGALRM, SIG_DFL);
|
||||
(void)alarm((u_int)30);
|
||||
if ((tp = fopen(tty, "w")) == NULL) {
|
||||
dsyslog(LOG_ERR, "%s: %s", tty, strerror(errno));
|
||||
_exit(-1);
|
||||
}
|
||||
(void)ioctl(fileno(tp), TIOCGETP, >tybuf);
|
||||
cr = (gttybuf.sg_flags&CRMOD) && !(gttybuf.sg_flags&RAW) ?
|
||||
"\n" : "\n\r";
|
||||
(void)strncpy(name, utp->ut_name, sizeof(utp->ut_name));
|
||||
name[sizeof(name) - 1] = '\0';
|
||||
(void)fprintf(tp, "%s\007New mail for %s@%.*s\007 has arrived:%s----%s",
|
||||
cr, name, (int)sizeof(hostname), hostname, cr, cr);
|
||||
jkfprintf(tp, name, offset);
|
||||
(void)fclose(tp);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
jkfprintf(tp, name, offset)
|
||||
register FILE *tp;
|
||||
char name[];
|
||||
off_t offset;
|
||||
{
|
||||
register char *cp, ch;
|
||||
register FILE *fi;
|
||||
register int linecnt, charcnt, inheader;
|
||||
register struct passwd *p;
|
||||
char line[BUFSIZ];
|
||||
|
||||
/* Set effective uid to user in case mail drop is on nfs */
|
||||
if ((p = getpwnam(name)) != NULL)
|
||||
(void) setuid(p->pw_uid);
|
||||
|
||||
if ((fi = fopen(name, "r")) == NULL)
|
||||
return;
|
||||
|
||||
(void)fseek(fi, offset, L_SET);
|
||||
/*
|
||||
* Print the first 7 lines or 560 characters of the new mail
|
||||
* (whichever comes first). Skip header crap other than
|
||||
* From, Subject, To, and Date.
|
||||
*/
|
||||
linecnt = 7;
|
||||
charcnt = 560;
|
||||
inheader = 1;
|
||||
while (fgets(line, sizeof(line), fi) != NULL) {
|
||||
if (inheader) {
|
||||
if (line[0] == '\n') {
|
||||
inheader = 0;
|
||||
continue;
|
||||
}
|
||||
if (line[0] == ' ' || line[0] == '\t' ||
|
||||
strncmp(line, "From:", 5) &&
|
||||
strncmp(line, "Subject:", 8))
|
||||
continue;
|
||||
}
|
||||
if (linecnt <= 0 || charcnt <= 0) {
|
||||
(void)fprintf(tp, "...more...%s", cr);
|
||||
(void)fclose(fi);
|
||||
return;
|
||||
}
|
||||
/* strip weird stuff so can't trojan horse stupid terminals */
|
||||
for (cp = line; (ch = *cp) && ch != '\n'; ++cp, --charcnt) {
|
||||
ch = toascii(ch);
|
||||
if (!isprint(ch) && !isspace(ch))
|
||||
ch |= 0x40;
|
||||
(void)fputc(ch, tp);
|
||||
}
|
||||
(void)fputs(cr, tp);
|
||||
--linecnt;
|
||||
}
|
||||
(void)fprintf(tp, "----%s\n", cr);
|
||||
(void)fclose(fi);
|
||||
}
|
||||
6
libexec/fingerd/Makefile
Normal file
6
libexec/fingerd/Makefile
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||
|
||||
PROG= fingerd
|
||||
MAN8= fingerd.0
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
139
libexec/fingerd/fingerd.8
Normal file
139
libexec/fingerd/fingerd.8
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
.\" Copyright (c) 1980, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)fingerd.8 8.1 (Berkeley) 6/4/93
|
||||
.\"
|
||||
.Dd June 4, 1993
|
||||
.Dt FINGERD 8
|
||||
.Os BSD 4.3
|
||||
.Sh NAME
|
||||
.Nm fingerd
|
||||
.Nd remote user information server
|
||||
.Sh SYNOPSIS
|
||||
.Nm fingerd
|
||||
.Op Fl s
|
||||
.Op Fl l
|
||||
.Op Fl p Ar filename
|
||||
.Sh DESCRIPTION
|
||||
.Nm Fingerd
|
||||
is a simple protocol based on
|
||||
.%T RFC1196
|
||||
that provides an interface to the
|
||||
Name and Finger programs at several network sites.
|
||||
The program is supposed to return a friendly,
|
||||
human-oriented status report on either the system at the moment
|
||||
or a particular person in depth.
|
||||
There is no required format and the
|
||||
protocol consists mostly of specifying a single
|
||||
.Dq command line .
|
||||
.Pp
|
||||
.Nm Fingerd
|
||||
listens for
|
||||
.Tn TCP
|
||||
requests at port 79.
|
||||
Once connected it reads a single command line
|
||||
terminated by a
|
||||
.Aq Tn CRLF
|
||||
which is passed to
|
||||
.Xr finger 1 .
|
||||
.Nm Fingerd
|
||||
closes its connections as soon as the output is finished.
|
||||
.Pp
|
||||
If the line is null (i.e. just a
|
||||
.Aq Tn CRLF
|
||||
is sent) then
|
||||
.Xr finger
|
||||
returns a
|
||||
.Dq default
|
||||
report that lists all people logged into
|
||||
the system at that moment.
|
||||
.Pp
|
||||
If a user name is specified (e.g.
|
||||
.Pf eric Aq Tn CRLF )
|
||||
then the
|
||||
response lists more extended information for only that particular user,
|
||||
whether logged in or not.
|
||||
Allowable
|
||||
.Dq names
|
||||
in the command line include both
|
||||
.Dq login names
|
||||
and
|
||||
.Dq user names .
|
||||
If a name is ambiguous, all possible derivations are returned.
|
||||
.Pp
|
||||
The following options may be passed to
|
||||
.Nm fingerd
|
||||
as server program arguments in
|
||||
.Pa /etc/inetd.conf :
|
||||
.Bl -tag -width Ds
|
||||
.It Fl s
|
||||
Enable secure mode.
|
||||
Queries without a user name are rejected and
|
||||
forwarding of queries to other remote hosts is denied.
|
||||
.It Fl l
|
||||
Enable logging.
|
||||
The name of the host originating the query is reported via
|
||||
.Xr syslog 3
|
||||
at LOG_NOTICE priority.
|
||||
.It Fl p
|
||||
Use an alternate program as the local information provider.
|
||||
The default local program
|
||||
executed by
|
||||
.Nm fingerd
|
||||
is
|
||||
.Xr finger 1 .
|
||||
By specifying a customized local server,
|
||||
this option allows a system manager
|
||||
to have more control over what information is
|
||||
provided to remote sites.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr finger 1
|
||||
.Sh BUGS
|
||||
Connecting directly to the server from a
|
||||
.Tn TIP
|
||||
or an equally narrow-minded
|
||||
.Tn TELNET Ns \-protocol
|
||||
user program can result
|
||||
in meaningless attempts at option negotiation being sent to the
|
||||
server, which will foul up the command line interpretation.
|
||||
.Nm Fingerd
|
||||
should be taught to filter out
|
||||
.Tn IAC Ns \'s
|
||||
and perhaps even respond
|
||||
negatively
|
||||
.Pq Tn IAC WON'T
|
||||
to all option commands received.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.3 .
|
||||
190
libexec/fingerd/fingerd.c
Normal file
190
libexec/fingerd/fingerd.c
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1983, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)fingerd.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include "pathnames.h"
|
||||
|
||||
void err __P((const char *, ...));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register FILE *fp;
|
||||
register int ch;
|
||||
register char *lp;
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in sin;
|
||||
int p[2], logging, secure, sval;
|
||||
#define ENTRIES 50
|
||||
char **ap, *av[ENTRIES + 1], **comp, line[1024], *prog;
|
||||
|
||||
prog = _PATH_FINGER;
|
||||
logging = secure = 0;
|
||||
openlog("fingerd", LOG_PID | LOG_CONS, LOG_DAEMON);
|
||||
opterr = 0;
|
||||
while ((ch = getopt(argc, argv, "slp:")) != EOF)
|
||||
switch (ch) {
|
||||
case 'l':
|
||||
logging = 1;
|
||||
break;
|
||||
case 'p':
|
||||
prog = optarg;
|
||||
break;
|
||||
case 's':
|
||||
secure = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
err("illegal option -- %c", ch);
|
||||
}
|
||||
|
||||
if (logging) {
|
||||
sval = sizeof(sin);
|
||||
if (getpeername(0, (struct sockaddr *)&sin, &sval) < 0)
|
||||
err("getpeername: %s", strerror(errno));
|
||||
if (hp = gethostbyaddr((char *)&sin.sin_addr.s_addr,
|
||||
sizeof(sin.sin_addr.s_addr), AF_INET))
|
||||
lp = hp->h_name;
|
||||
else
|
||||
lp = inet_ntoa(sin.sin_addr);
|
||||
syslog(LOG_NOTICE, "query from %s", lp);
|
||||
}
|
||||
|
||||
if (!fgets(line, sizeof(line), stdin))
|
||||
exit(1);
|
||||
|
||||
comp = &av[1];
|
||||
for (lp = line, ap = &av[2];;) {
|
||||
*ap = strtok(lp, " \t\r\n");
|
||||
if (!*ap) {
|
||||
if (secure && ap == &av[2]) {
|
||||
puts("must provide username\r\n");
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (secure && strchr(*ap, '@')) {
|
||||
puts("fowarding service denied\r\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* RFC742: "/[Ww]" == "-l" */
|
||||
if ((*ap)[0] == '/' && ((*ap)[1] == 'W' || (*ap)[1] == 'w')) {
|
||||
av[1] = "-l";
|
||||
comp = &av[0];
|
||||
}
|
||||
else if (++ap == av + ENTRIES)
|
||||
break;
|
||||
lp = NULL;
|
||||
}
|
||||
|
||||
if (lp = strrchr(prog, '/'))
|
||||
*comp = ++lp;
|
||||
else
|
||||
*comp = prog;
|
||||
if (pipe(p) < 0)
|
||||
err("pipe: %s", strerror(errno));
|
||||
|
||||
switch(vfork()) {
|
||||
case 0:
|
||||
(void)close(p[0]);
|
||||
if (p[1] != 1) {
|
||||
(void)dup2(p[1], 1);
|
||||
(void)close(p[1]);
|
||||
}
|
||||
execv(prog, comp);
|
||||
err("execv: %s: %s", prog, strerror(errno));
|
||||
_exit(1);
|
||||
case -1:
|
||||
err("fork: %s", strerror(errno));
|
||||
}
|
||||
(void)close(p[1]);
|
||||
if (!(fp = fdopen(p[0], "r")))
|
||||
err("fdopen: %s", strerror(errno));
|
||||
while ((ch = getc(fp)) != EOF) {
|
||||
if (ch == '\n')
|
||||
putchar('\r');
|
||||
putchar(ch);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
err(const char *fmt, ...)
|
||||
#else
|
||||
err(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
(void)vsyslog(LOG_ERR, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
36
libexec/fingerd/pathnames.h
Normal file
36
libexec/fingerd/pathnames.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
#define _PATH_FINGER "/usr/bin/finger"
|
||||
9
libexec/ftpd/Makefile
Normal file
9
libexec/ftpd/Makefile
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# @(#)Makefile 8.2 (Berkeley) 4/4/94
|
||||
|
||||
PROG= ftpd
|
||||
CFLAGS+=-DSETPROCTITLE
|
||||
SRCS= ftpd.c ftpcmd.c logwtmp.c popen.c
|
||||
MAN8= ftpd.0
|
||||
CLEANFILES+=ftpcmd.c y.tab.h
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
65
libexec/ftpd/extern.h
Normal file
65
libexec/ftpd/extern.h
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.2 (Berkeley) 4/4/94
|
||||
*/
|
||||
|
||||
void blkfree __P((char **));
|
||||
char **copyblk __P((char **));
|
||||
void cwd __P((char *));
|
||||
void delete __P((char *));
|
||||
void dologout __P((int));
|
||||
void fatal __P((char *));
|
||||
int ftpd_pclose __P((FILE *));
|
||||
FILE *ftpd_popen __P((char *, char *));
|
||||
char *getline __P((char *, int, FILE *));
|
||||
void logwtmp __P((char *, char *, char *));
|
||||
void lreply __P((int, const char *, ...));
|
||||
void makedir __P((char *));
|
||||
void nack __P((char *));
|
||||
void pass __P((char *));
|
||||
void passive __P((void));
|
||||
void perror_reply __P((int, char *));
|
||||
void pwd __P((void));
|
||||
void removedir __P((char *));
|
||||
void renamecmd __P((char *, char *));
|
||||
char *renamefrom __P((char *));
|
||||
void reply __P((int, const char *, ...));
|
||||
void retrieve __P((char *, char *));
|
||||
void send_file_list __P((char *));
|
||||
void setproctitle __P((const char *, ...));
|
||||
void statcmd __P((void));
|
||||
void statfilecmd __P((char *));
|
||||
void store __P((char *, char *, int));
|
||||
void upper __P((char *));
|
||||
void user __P((char *));
|
||||
void yyerror __P((char *));
|
||||
1266
libexec/ftpd/ftpcmd.y
Normal file
1266
libexec/ftpd/ftpcmd.y
Normal file
File diff suppressed because it is too large
Load diff
290
libexec/ftpd/ftpd.8
Normal file
290
libexec/ftpd/ftpd.8
Normal file
|
|
@ -0,0 +1,290 @@
|
|||
.\" Copyright (c) 1985, 1988, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)ftpd.8 8.2 (Berkeley) 4/19/94
|
||||
.\"
|
||||
.Dd April 19, 1994
|
||||
.Dt FTPD 8
|
||||
.Os BSD 4.2
|
||||
.Sh NAME
|
||||
.Nm ftpd
|
||||
.Nd
|
||||
Internet File Transfer Protocol server
|
||||
.Sh SYNOPSIS
|
||||
.Nm ftpd
|
||||
.Op Fl dl
|
||||
.Op Fl T Ar maxtimeout
|
||||
.Op Fl t Ar timeout
|
||||
.Sh DESCRIPTION
|
||||
.Nm Ftpd
|
||||
is the
|
||||
Internet File Transfer Protocol
|
||||
server process. The server uses the
|
||||
.Tn TCP
|
||||
protocol
|
||||
and listens at the port specified in the
|
||||
.Dq ftp
|
||||
service specification; see
|
||||
.Xr services 5 .
|
||||
.Pp
|
||||
Available options:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl d
|
||||
Debugging information is written to the syslog using LOG_FTP.
|
||||
.It Fl l
|
||||
Each successful and failed
|
||||
.Xr ftp 1
|
||||
session is logged using syslog with a facility of LOG_FTP.
|
||||
If this option is specified twice, the retrieve (get), store (put), append,
|
||||
delete, make directory, remove directory and rename operations and
|
||||
their filename arguments are also logged.
|
||||
.It Fl T
|
||||
A client may also request a different timeout period;
|
||||
the maximum period allowed may be set to
|
||||
.Ar timeout
|
||||
seconds with the
|
||||
.Fl T
|
||||
option.
|
||||
The default limit is 2 hours.
|
||||
.It Fl t
|
||||
The inactivity timeout period is set to
|
||||
.Ar timeout
|
||||
seconds (the default is 15 minutes).
|
||||
.El
|
||||
.Pp
|
||||
The file
|
||||
.Pa /etc/nologin
|
||||
can be used to disable ftp access.
|
||||
If the file exists,
|
||||
.Nm
|
||||
displays it and exits.
|
||||
If the file
|
||||
.Pa /etc/ftpwelcome
|
||||
exists,
|
||||
.Nm
|
||||
prints it before issuing the
|
||||
.Dq ready
|
||||
message.
|
||||
If the file
|
||||
.Pa /etc/motd
|
||||
exists,
|
||||
.Nm
|
||||
prints it after a successful login.
|
||||
.Pp
|
||||
The ftp server currently supports the following ftp requests.
|
||||
The case of the requests is ignored.
|
||||
.Bl -column "Request" -offset indent
|
||||
.It Request Ta "Description"
|
||||
.It ABOR Ta "abort previous command"
|
||||
.It ACCT Ta "specify account (ignored)"
|
||||
.It ALLO Ta "allocate storage (vacuously)"
|
||||
.It APPE Ta "append to a file"
|
||||
.It CDUP Ta "change to parent of current working directory"
|
||||
.It CWD Ta "change working directory"
|
||||
.It DELE Ta "delete a file"
|
||||
.It HELP Ta "give help information"
|
||||
.It LIST Ta "give list files in a directory" Pq Dq Li "ls -lgA"
|
||||
.It MKD Ta "make a directory"
|
||||
.It MDTM Ta "show last modification time of file"
|
||||
.It MODE Ta "specify data transfer" Em mode
|
||||
.It NLST Ta "give name list of files in directory"
|
||||
.It NOOP Ta "do nothing"
|
||||
.It PASS Ta "specify password"
|
||||
.It PASV Ta "prepare for server-to-server transfer"
|
||||
.It PORT Ta "specify data connection port"
|
||||
.It PWD Ta "print the current working directory"
|
||||
.It QUIT Ta "terminate session"
|
||||
.It REST Ta "restart incomplete transfer"
|
||||
.It RETR Ta "retrieve a file"
|
||||
.It RMD Ta "remove a directory"
|
||||
.It RNFR Ta "specify rename-from file name"
|
||||
.It RNTO Ta "specify rename-to file name"
|
||||
.It SITE Ta "non-standard commands (see next section)"
|
||||
.It SIZE Ta "return size of file"
|
||||
.It STAT Ta "return status of server"
|
||||
.It STOR Ta "store a file"
|
||||
.It STOU Ta "store a file with a unique name"
|
||||
.It STRU Ta "specify data transfer" Em structure
|
||||
.It SYST Ta "show operating system type of server system"
|
||||
.It TYPE Ta "specify data transfer" Em type
|
||||
.It USER Ta "specify user name"
|
||||
.It XCUP Ta "change to parent of current working directory (deprecated)"
|
||||
.It XCWD Ta "change working directory (deprecated)"
|
||||
.It XMKD Ta "make a directory (deprecated)"
|
||||
.It XPWD Ta "print the current working directory (deprecated)"
|
||||
.It XRMD Ta "remove a directory (deprecated)"
|
||||
.El
|
||||
.Pp
|
||||
The following non-standard or
|
||||
.Tn UNIX
|
||||
specific commands are supported
|
||||
by the
|
||||
SITE request.
|
||||
.Pp
|
||||
.Bl -column Request -offset indent
|
||||
.It Sy Request Ta Sy Description
|
||||
.It UMASK Ta change umask, e.g. ``SITE UMASK 002''
|
||||
.It IDLE Ta set idle-timer, e.g. ``SITE IDLE 60''
|
||||
.It CHMOD Ta change mode of a file, e.g. ``SITE CHMOD 755 filename''
|
||||
.It HELP Ta give help information.
|
||||
.El
|
||||
.Pp
|
||||
The remaining ftp requests specified in Internet RFC 959
|
||||
are
|
||||
recognized, but not implemented.
|
||||
MDTM and SIZE are not specified in RFC 959, but will appear in the
|
||||
next updated FTP RFC.
|
||||
.Pp
|
||||
The ftp server will abort an active file transfer only when the
|
||||
ABOR
|
||||
command is preceded by a Telnet "Interrupt Process" (IP)
|
||||
signal and a Telnet "Synch" signal in the command Telnet stream,
|
||||
as described in Internet RFC 959.
|
||||
If a
|
||||
STAT
|
||||
command is received during a data transfer, preceded by a Telnet IP
|
||||
and Synch, transfer status will be returned.
|
||||
.Pp
|
||||
.Nm Ftpd
|
||||
interprets file names according to the
|
||||
.Dq globbing
|
||||
conventions used by
|
||||
.Xr csh 1 .
|
||||
This allows users to utilize the metacharacters
|
||||
.Dq Li \&*?[]{}~ .
|
||||
.Pp
|
||||
.Nm Ftpd
|
||||
authenticates users according to three rules.
|
||||
.Pp
|
||||
.Bl -enum -offset indent
|
||||
.It
|
||||
The login name must be in the password data base,
|
||||
.Pa /etc/passwd ,
|
||||
and not have a null password.
|
||||
In this case a password must be provided by the client before any
|
||||
file operations may be performed.
|
||||
.It
|
||||
The login name must not appear in the file
|
||||
.Pa /etc/ftpusers .
|
||||
.It
|
||||
The user must have a standard shell returned by
|
||||
.Xr getusershell 3 .
|
||||
.It
|
||||
If the user name is
|
||||
.Dq anonymous
|
||||
or
|
||||
.Dq ftp ,
|
||||
an
|
||||
anonymous ftp account must be present in the password
|
||||
file (user
|
||||
.Dq ftp ) .
|
||||
In this case the user is allowed
|
||||
to log in by specifying any password (by convention an email address for
|
||||
the user should be used as the password).
|
||||
.El
|
||||
.Pp
|
||||
In the last case,
|
||||
.Nm ftpd
|
||||
takes special measures to restrict the client's access privileges.
|
||||
The server performs a
|
||||
.Xr chroot 2
|
||||
to the home directory of the
|
||||
.Dq ftp
|
||||
user.
|
||||
In order that system security is not breached, it is recommended
|
||||
that the
|
||||
.Dq ftp
|
||||
subtree be constructed with care, following these rules:
|
||||
.Bl -tag -width "~ftp/pub" -offset indent
|
||||
.It Pa ~ftp
|
||||
Make the home directory owned by
|
||||
.Dq root
|
||||
and unwritable by anyone.
|
||||
.It Pa ~ftp/bin
|
||||
Make this directory owned by
|
||||
.Dq root
|
||||
and unwritable by anyone (mode 555).
|
||||
The program
|
||||
.Xr ls 1
|
||||
must be present to support the list command.
|
||||
This program should be mode 111.
|
||||
.It Pa ~ftp/etc
|
||||
Make this directory owned by
|
||||
.Dq root
|
||||
and unwritable by anyone (mode 555).
|
||||
The files
|
||||
.Xr passwd 5
|
||||
and
|
||||
.Xr group 5
|
||||
must be present for the
|
||||
.Xr ls
|
||||
command to be able to produce owner names rather than numbers.
|
||||
The password field in
|
||||
.Xr passwd
|
||||
is not used, and should not contain real passwords.
|
||||
The file
|
||||
.Pa motd ,
|
||||
if present, will be printed after a successful login.
|
||||
These files should be mode 444.
|
||||
.It Pa ~ftp/pub
|
||||
Make this directory mode 777 and owned by
|
||||
.Dq ftp .
|
||||
Guests
|
||||
can then place files which are to be accessible via the anonymous
|
||||
account in this directory.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /etc/ftpwelcome -compact
|
||||
.It Pa /etc/ftpusers
|
||||
List of unwelcome/restricted users.
|
||||
.It Pa /etc/ftpwelcome
|
||||
Welcome notice.
|
||||
.It Pa /etc/motd
|
||||
Welcome notice after login.
|
||||
.It Pa /etc/nologin
|
||||
Displayed and access refused.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr ftp 1 ,
|
||||
.Xr getusershell 3 ,
|
||||
.Xr syslogd 8
|
||||
.Sh BUGS
|
||||
The server must run as the super-user
|
||||
to create sockets with privileged port numbers. It maintains
|
||||
an effective user id of the logged in user, reverting to
|
||||
the super-user only when binding addresses to sockets. The
|
||||
possible security holes have been extensively
|
||||
scrutinized, but are possibly incomplete.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.2 .
|
||||
1654
libexec/ftpd/ftpd.c
Normal file
1654
libexec/ftpd/ftpd.c
Normal file
File diff suppressed because it is too large
Load diff
75
libexec/ftpd/logwtmp.c
Normal file
75
libexec/ftpd/logwtmp.c
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)logwtmp.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <utmp.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "extern.h"
|
||||
|
||||
static int fd = -1;
|
||||
|
||||
/*
|
||||
* Modified version of logwtmp that holds wtmp file open
|
||||
* after first call, for use with ftp (which may chroot
|
||||
* after login, but before logout).
|
||||
*/
|
||||
void
|
||||
logwtmp(line, name, host)
|
||||
char *line, *name, *host;
|
||||
{
|
||||
struct utmp ut;
|
||||
struct stat buf;
|
||||
|
||||
if (fd < 0 && (fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0)
|
||||
return;
|
||||
if (fstat(fd, &buf) == 0) {
|
||||
(void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
|
||||
(void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
|
||||
(void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
|
||||
(void)time(&ut.ut_time);
|
||||
if (write(fd, (char *)&ut, sizeof(struct utmp)) !=
|
||||
sizeof(struct utmp))
|
||||
(void)ftruncate(fd, buf.st_size);
|
||||
}
|
||||
}
|
||||
40
libexec/ftpd/pathnames.h
Normal file
40
libexec/ftpd/pathnames.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
#include <paths.h>
|
||||
|
||||
#define _PATH_FTPUSERS "/etc/ftpusers"
|
||||
#define _PATH_FTPWELCOME "/etc/ftpwelcome"
|
||||
#define _PATH_FTPLOGINMESG "/etc/motd"
|
||||
171
libexec/ftpd/popen.c
Normal file
171
libexec/ftpd/popen.c
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software written by Ken Arnold and
|
||||
* published in UNIX Review, Vol. 6, No. 8.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 4/6/94";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <glob.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
/*
|
||||
* Special version of popen which avoids call to shell. This ensures noone
|
||||
* may create a pipe to a hidden program as a side effect of a list or dir
|
||||
* command.
|
||||
*/
|
||||
static int *pids;
|
||||
static int fds;
|
||||
|
||||
FILE *
|
||||
ftpd_popen(program, type)
|
||||
char *program, *type;
|
||||
{
|
||||
char *cp;
|
||||
FILE *iop;
|
||||
int argc, gargc, pdes[2], pid;
|
||||
char **pop, *argv[100], *gargv[1000];
|
||||
|
||||
if (*type != 'r' && *type != 'w' || type[1])
|
||||
return (NULL);
|
||||
|
||||
if (!pids) {
|
||||
if ((fds = getdtablesize()) <= 0)
|
||||
return (NULL);
|
||||
if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
|
||||
return (NULL);
|
||||
memset(pids, 0, fds * sizeof(int));
|
||||
}
|
||||
if (pipe(pdes) < 0)
|
||||
return (NULL);
|
||||
|
||||
/* break up string into pieces */
|
||||
for (argc = 0, cp = program;; cp = NULL)
|
||||
if (!(argv[argc++] = strtok(cp, " \t\n")))
|
||||
break;
|
||||
|
||||
/* glob each piece */
|
||||
gargv[0] = argv[0];
|
||||
for (gargc = argc = 1; argv[argc]; argc++) {
|
||||
glob_t gl;
|
||||
int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
|
||||
|
||||
memset(&gl, 0, sizeof(gl));
|
||||
if (glob(argv[argc], flags, NULL, &gl))
|
||||
gargv[gargc++] = strdup(argv[argc]);
|
||||
else
|
||||
for (pop = gl.gl_pathv; *pop; pop++)
|
||||
gargv[gargc++] = strdup(*pop);
|
||||
globfree(&gl);
|
||||
}
|
||||
gargv[gargc] = NULL;
|
||||
|
||||
iop = NULL;
|
||||
switch(pid = vfork()) {
|
||||
case -1: /* error */
|
||||
(void)close(pdes[0]);
|
||||
(void)close(pdes[1]);
|
||||
goto pfree;
|
||||
/* NOTREACHED */
|
||||
case 0: /* child */
|
||||
if (*type == 'r') {
|
||||
if (pdes[1] != STDOUT_FILENO) {
|
||||
dup2(pdes[1], STDOUT_FILENO);
|
||||
(void)close(pdes[1]);
|
||||
}
|
||||
dup2(STDOUT_FILENO, STDERR_FILENO); /* stderr too! */
|
||||
(void)close(pdes[0]);
|
||||
} else {
|
||||
if (pdes[0] != STDIN_FILENO) {
|
||||
dup2(pdes[0], STDIN_FILENO);
|
||||
(void)close(pdes[0]);
|
||||
}
|
||||
(void)close(pdes[1]);
|
||||
}
|
||||
execv(gargv[0], gargv);
|
||||
_exit(1);
|
||||
}
|
||||
/* parent; assume fdopen can't fail... */
|
||||
if (*type == 'r') {
|
||||
iop = fdopen(pdes[0], type);
|
||||
(void)close(pdes[1]);
|
||||
} else {
|
||||
iop = fdopen(pdes[1], type);
|
||||
(void)close(pdes[0]);
|
||||
}
|
||||
pids[fileno(iop)] = pid;
|
||||
|
||||
pfree: for (argc = 1; gargv[argc] != NULL; argc++)
|
||||
free(gargv[argc]);
|
||||
|
||||
return (iop);
|
||||
}
|
||||
|
||||
int
|
||||
ftpd_pclose(iop)
|
||||
FILE *iop;
|
||||
{
|
||||
int fdes, omask, status;
|
||||
pid_t pid;
|
||||
|
||||
/*
|
||||
* pclose returns -1 if stream is not associated with a
|
||||
* `popened' command, or, if already `pclosed'.
|
||||
*/
|
||||
if (pids == 0 || pids[fdes = fileno(iop)] == 0)
|
||||
return (-1);
|
||||
(void)fclose(iop);
|
||||
omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
|
||||
while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR)
|
||||
continue;
|
||||
(void)sigsetmask(omask);
|
||||
pids[fdes] = 0;
|
||||
if (pid < 0)
|
||||
return (pid);
|
||||
if (WIFEXITED(status))
|
||||
return (WEXITSTATUS(status));
|
||||
return (1);
|
||||
}
|
||||
6
libexec/getNAME/Makefile
Normal file
6
libexec/getNAME/Makefile
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||
|
||||
PROG= getNAME
|
||||
NOMAN= noman
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
339
libexec/getNAME/getNAME.c
Normal file
339
libexec/getNAME/getNAME.c
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
/*-
|
||||
* Copyright (c) 1980, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1980, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)getNAME.c 8.1 (Berkeley) 6/30/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Get name sections from manual pages.
|
||||
* -t for building toc
|
||||
* -i for building intro entries
|
||||
* other apropos database
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int tocrc;
|
||||
int intro;
|
||||
int typeflag;
|
||||
|
||||
void doname __P((char *));
|
||||
void dorefname __P((char *));
|
||||
void getfrom __P((char *));
|
||||
void split __P((char *, char *));
|
||||
void trimln __P((char *));
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern int optind;
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "itw")) != EOF)
|
||||
switch(ch) {
|
||||
case 'i':
|
||||
intro = 1;
|
||||
break;
|
||||
case 't':
|
||||
tocrc = 1;
|
||||
break;
|
||||
case 'w':
|
||||
typeflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (!*argv)
|
||||
usage();
|
||||
|
||||
for (; *argv; ++argv)
|
||||
getfrom(*argv);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
getfrom(pathname)
|
||||
char *pathname;
|
||||
{
|
||||
int i = 0;
|
||||
char *name, *loc;
|
||||
char headbuf[BUFSIZ];
|
||||
char linbuf[BUFSIZ];
|
||||
|
||||
if (freopen(pathname, "r", stdin) == 0) {
|
||||
perror(pathname);
|
||||
return;
|
||||
}
|
||||
if (name = strrchr(pathname, '/'))
|
||||
name++;
|
||||
else
|
||||
name = pathname;
|
||||
for (;;) {
|
||||
if (fgets(headbuf, sizeof headbuf, stdin) == NULL) {
|
||||
if (typeflag)
|
||||
printf("%-60s UNKNOWN\n", pathname);
|
||||
return;
|
||||
}
|
||||
if (headbuf[0] != '.')
|
||||
continue;
|
||||
if ((headbuf[1] == 'T' && headbuf[2] == 'H') ||
|
||||
(headbuf[1] == 't' && headbuf[2] == 'h'))
|
||||
break;
|
||||
if (headbuf[1] == 'D' && headbuf[2] == 't') {
|
||||
if (typeflag) {
|
||||
printf("%-60s NEW\n", pathname);
|
||||
return;
|
||||
}
|
||||
goto newman;
|
||||
}
|
||||
}
|
||||
if (typeflag) {
|
||||
printf("%-60s OLD\n", pathname);
|
||||
return;
|
||||
}
|
||||
for (;;) {
|
||||
if (fgets(linbuf, sizeof linbuf, stdin) == NULL)
|
||||
return;
|
||||
if (linbuf[0] != '.')
|
||||
continue;
|
||||
if (linbuf[1] == 'S' && linbuf[2] == 'H')
|
||||
break;
|
||||
if (linbuf[1] == 's' && linbuf[2] == 'h')
|
||||
break;
|
||||
}
|
||||
trimln(headbuf);
|
||||
if (tocrc)
|
||||
doname(name);
|
||||
if (!tocrc && !intro)
|
||||
printf("%s\t", headbuf);
|
||||
linbuf[0] = '\0';
|
||||
for (;;) {
|
||||
if (fgets(headbuf, sizeof headbuf, stdin) == NULL)
|
||||
break;
|
||||
if (headbuf[0] == '.') {
|
||||
if (headbuf[1] == 'S' && headbuf[2] == 'H')
|
||||
break;
|
||||
if (headbuf[1] == 's' && headbuf[2] == 'h')
|
||||
break;
|
||||
}
|
||||
if (i != 0)
|
||||
strcat(linbuf, " ");
|
||||
i++;
|
||||
trimln(headbuf);
|
||||
strcat(linbuf, headbuf);
|
||||
}
|
||||
if (intro)
|
||||
split(linbuf, name);
|
||||
else
|
||||
printf("%s\n", linbuf);
|
||||
return;
|
||||
|
||||
newman:
|
||||
for (;;) {
|
||||
if (fgets(linbuf, sizeof linbuf, stdin) == NULL)
|
||||
return;
|
||||
if (linbuf[0] != '.')
|
||||
continue;
|
||||
if (linbuf[1] == 'S' && linbuf[2] == 'h')
|
||||
break;
|
||||
}
|
||||
trimln(headbuf);
|
||||
if (tocrc)
|
||||
doname(name);
|
||||
if (!tocrc && !intro)
|
||||
printf(".TH%s\t", &headbuf[3]);
|
||||
linbuf[0] = '\0';
|
||||
for (;;) {
|
||||
if (fgets(headbuf, sizeof headbuf, stdin) == NULL)
|
||||
break;
|
||||
if (headbuf[0] == '.') {
|
||||
if (headbuf[1] == 'S' && headbuf[2] == 'h')
|
||||
break;
|
||||
}
|
||||
if (i != 0)
|
||||
strcat(linbuf, " ");
|
||||
i++;
|
||||
trimln(headbuf);
|
||||
for (loc = strchr(headbuf, ' '); loc; loc = strchr(loc, ' '))
|
||||
if (loc[1] == ',')
|
||||
strcpy(loc, &loc[1]);
|
||||
else
|
||||
loc++;
|
||||
if (headbuf[0] != '.') {
|
||||
strcat(linbuf, headbuf);
|
||||
} else {
|
||||
/*
|
||||
* Get rid of quotes in macros.
|
||||
*/
|
||||
for (loc = strchr(&headbuf[4], '"'); loc; ) {
|
||||
strcpy(loc, &loc[1]);
|
||||
loc = strchr(loc, '"');
|
||||
}
|
||||
/*
|
||||
* Handle cross references
|
||||
*/
|
||||
if (headbuf[1] == 'X' && headbuf[2] == 'r') {
|
||||
for (loc = &headbuf[4]; *loc != ' '; loc++)
|
||||
continue;
|
||||
loc[0] = '(';
|
||||
loc[2] = ')';
|
||||
loc[3] = '\0';
|
||||
}
|
||||
/*
|
||||
* Put dash between names and description.
|
||||
*/
|
||||
if (headbuf[1] == 'N' && headbuf[2] == 'd')
|
||||
strcat(linbuf, "\\- ");
|
||||
/*
|
||||
* Skip over macro names.
|
||||
*/
|
||||
strcat(linbuf, &headbuf[4]);
|
||||
}
|
||||
}
|
||||
if (intro)
|
||||
split(linbuf, name);
|
||||
else
|
||||
printf("%s\n", linbuf);
|
||||
}
|
||||
|
||||
void
|
||||
trimln(cp)
|
||||
register char *cp;
|
||||
{
|
||||
|
||||
while (*cp)
|
||||
cp++;
|
||||
if (*--cp == '\n')
|
||||
*cp = 0;
|
||||
}
|
||||
|
||||
void
|
||||
doname(name)
|
||||
char *name;
|
||||
{
|
||||
register char *dp = name, *ep;
|
||||
|
||||
again:
|
||||
while (*dp && *dp != '.')
|
||||
putchar(*dp++);
|
||||
if (*dp)
|
||||
for (ep = dp+1; *ep; ep++)
|
||||
if (*ep == '.') {
|
||||
putchar(*dp++);
|
||||
goto again;
|
||||
}
|
||||
putchar('(');
|
||||
if (*dp)
|
||||
dp++;
|
||||
while (*dp)
|
||||
putchar (*dp++);
|
||||
putchar(')');
|
||||
putchar(' ');
|
||||
}
|
||||
|
||||
void
|
||||
split(line, name)
|
||||
char *line, *name;
|
||||
{
|
||||
register char *cp, *dp;
|
||||
char *sp, *sep;
|
||||
|
||||
cp = strchr(line, '-');
|
||||
if (cp == 0)
|
||||
return;
|
||||
sp = cp + 1;
|
||||
for (--cp; *cp == ' ' || *cp == '\t' || *cp == '\\'; cp--)
|
||||
;
|
||||
*++cp = '\0';
|
||||
while (*sp && (*sp == ' ' || *sp == '\t'))
|
||||
sp++;
|
||||
for (sep = "", dp = line; dp && *dp; dp = cp, sep = "\n") {
|
||||
cp = strchr(dp, ',');
|
||||
if (cp) {
|
||||
register char *tp;
|
||||
|
||||
for (tp = cp - 1; *tp == ' ' || *tp == '\t'; tp--)
|
||||
;
|
||||
*++tp = '\0';
|
||||
for (++cp; *cp == ' ' || *cp == '\t'; cp++)
|
||||
;
|
||||
}
|
||||
printf("%s%s\t", sep, dp);
|
||||
dorefname(name);
|
||||
printf("\t%s", sp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dorefname(name)
|
||||
char *name;
|
||||
{
|
||||
register char *dp = name, *ep;
|
||||
|
||||
again:
|
||||
while (*dp && *dp != '.')
|
||||
putchar(*dp++);
|
||||
if (*dp)
|
||||
for (ep = dp+1; *ep; ep++)
|
||||
if (*ep == '.') {
|
||||
putchar(*dp++);
|
||||
goto again;
|
||||
}
|
||||
putchar('.');
|
||||
if (*dp)
|
||||
dp++;
|
||||
while (*dp)
|
||||
putchar (*dp++);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: getNAME [-it] file ...\n");
|
||||
exit(1);
|
||||
}
|
||||
10
libexec/getty/Makefile
Normal file
10
libexec/getty/Makefile
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||
|
||||
PROG= getty
|
||||
SRCS= main.c init.c subr.c ttydefaults.c
|
||||
DPADD= ${LIBUTIL}
|
||||
LDADD= -lutil
|
||||
MAN5= gettytab.0 ttys.0
|
||||
MAN8= getty.0
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
56
libexec/getty/extern.h
Normal file
56
libexec/getty/extern.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
struct delayval;
|
||||
|
||||
int adelay __P((int, struct delayval *));
|
||||
char *autobaud __P((void));
|
||||
int delaybits __P((void));
|
||||
void edithost __P((char *));
|
||||
void gendefaults __P((void));
|
||||
int getent __P((char *, char *));
|
||||
int getflag __P((char *));
|
||||
long getnum __P((char *));
|
||||
char *getstr __P((char *, char **));
|
||||
void gettable __P((char *, char *));
|
||||
void makeenv __P((char *[]));
|
||||
char *portselector __P((void));
|
||||
void set_ttydefaults __P((int));
|
||||
void setchars __P((void));
|
||||
void setdefaults __P((void));
|
||||
long setflags __P((int));
|
||||
int speed __P((int));
|
||||
|
||||
int login_tty __P((int)); /* From libutil. */
|
||||
127
libexec/getty/getty.8
Normal file
127
libexec/getty/getty.8
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
.\" Copyright (c) 1980, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)getty.8 8.1 (Berkeley) 6/4/93
|
||||
.\"
|
||||
.Dd June 4, 1993
|
||||
.Dt GETTY 8
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm getty
|
||||
.Nd set terminal mode
|
||||
.Sh SYNOPSIS
|
||||
.Nm getty
|
||||
.Oo
|
||||
.Ar type
|
||||
.Op Ar tty
|
||||
.Oc
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm getty
|
||||
program
|
||||
is called by
|
||||
.Xr init 8
|
||||
to open and initialize the tty line, read a login name, and invoke
|
||||
.Xr login 1 .
|
||||
.Pp
|
||||
The argument
|
||||
.Ar tty
|
||||
is the special device file in
|
||||
.Pa /dev
|
||||
to open for the terminal (for example, ``ttyh0'').
|
||||
If there is no argument or the argument is
|
||||
.Ql Fl ,
|
||||
the tty line is assumed to be open as file descriptor 0.
|
||||
.Pp
|
||||
The
|
||||
.Ar type
|
||||
argument can be used to make
|
||||
.Nm getty
|
||||
treat the terminal line specially.
|
||||
This argument is used as an index into the
|
||||
.Nm gettytab 5
|
||||
database, to determine the characteristics of the line.
|
||||
If there is no argument, or there is no such table, the
|
||||
.Em default
|
||||
table is used.
|
||||
If there is no
|
||||
.Pa /etc/gettytab
|
||||
a set of system defaults is used.
|
||||
If indicated by the table located,
|
||||
.Nm getty
|
||||
will clear the terminal screen,
|
||||
print a banner heading,
|
||||
and prompt for a login name.
|
||||
Usually either the banner or the login prompt will include
|
||||
the system hostname.
|
||||
.Pp
|
||||
Most of the default actions of
|
||||
.Nm getty
|
||||
can be circumvented, or modified, by a suitable
|
||||
.Nm gettytab
|
||||
table.
|
||||
.Pp
|
||||
The
|
||||
.Nm getty
|
||||
program
|
||||
can be set to timeout after some interval,
|
||||
which will cause dial up lines to hang up
|
||||
if the login name is not entered reasonably quickly.
|
||||
.Sh DIAGNOSTICS
|
||||
.Bl -diag
|
||||
.It "ttyxx: No such device or address."
|
||||
.It "ttyxx: No such file or address."
|
||||
A terminal which is turned
|
||||
on in the
|
||||
.Xr ttys
|
||||
file cannot be opened, likely because the requisite
|
||||
lines are either not configured into the system, the associated device
|
||||
was not attached during boot-time system configuration,
|
||||
or the special file in
|
||||
.Pa /dev
|
||||
does not exist.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /etc/gettytab -compact
|
||||
.It Pa /etc/gettytab
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr gettytab 5 ,
|
||||
.Xr init 8 ,
|
||||
.Xr login 1 ,
|
||||
.Xr ioctl 2 ,
|
||||
.Xr tty 4 ,
|
||||
.Xr ttys 5
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm getty
|
||||
program appeared in
|
||||
.At v6 .
|
||||
324
libexec/getty/gettytab.5
Normal file
324
libexec/getty/gettytab.5
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
.\" Copyright (c) 1983, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)gettytab.5 8.4 (Berkeley) 4/19/94
|
||||
.\"
|
||||
.Dd April 19, 1994
|
||||
.Dt GETTYTAB 5
|
||||
.Os BSD 4.2
|
||||
.Sh NAME
|
||||
.Nm gettytab
|
||||
.Nd terminal configuration data base
|
||||
.Sh SYNOPSIS
|
||||
.Nm gettytab
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm gettytab
|
||||
file
|
||||
is a simplified version of the
|
||||
.Xr termcap 5
|
||||
data base
|
||||
used to describe terminal lines.
|
||||
The initial terminal login process
|
||||
.Xr getty 8
|
||||
accesses the
|
||||
.Nm gettytab
|
||||
file each time it starts, allowing simpler
|
||||
reconfiguration of terminal characteristics.
|
||||
Each entry in the data base
|
||||
is used to describe one class of terminals.
|
||||
.Pp
|
||||
There is a default terminal class,
|
||||
.Em default ,
|
||||
that is used to set global defaults for all other classes.
|
||||
(That is, the
|
||||
.Em default
|
||||
entry is read, then the entry for the class required
|
||||
is used to override particular settings.)
|
||||
.Sh CAPABILITIES
|
||||
Refer to
|
||||
.Xr termcap 5
|
||||
for a description of the file layout.
|
||||
The
|
||||
.Em default
|
||||
column below lists defaults obtained if there is
|
||||
no entry in the table obtained, nor one in the special
|
||||
.Em default
|
||||
table.
|
||||
.Bl -column Namexx /usr/bin/login Default
|
||||
.It Sy Name Type Default Description
|
||||
.It "ap bool false terminal uses any parity"
|
||||
.It "bd num 0 backspace delay"
|
||||
.It "bk str 0377 alternate end of line character (input break)"
|
||||
.It "cb bool false use crt backspace mode"
|
||||
.It "cd num 0 carriage-return delay"
|
||||
.It "ce bool false use crt erase algorithm"
|
||||
.It "ck bool false use crt kill algorithm"
|
||||
.It "cl str" Ta Dv NULL Ta
|
||||
.No "screen clear sequence"
|
||||
.It "co bool false console - add"
|
||||
.Ql \en
|
||||
after login prompt
|
||||
.It "ds str" Ta So Li ^Y Sc Ta
|
||||
.No "delayed suspend character"
|
||||
.It "dx bool false set"
|
||||
.Dv DECCTLQ
|
||||
.It "ec bool false leave echo"
|
||||
.Tn OFF
|
||||
.It "ep bool false terminal uses even parity"
|
||||
.It "er str" Ta So Li ^? Sc Ta
|
||||
.No "erase character"
|
||||
.It "et str" Ta So Li ^D Sc Ta
|
||||
.No "end of text"
|
||||
.Pq Dv EOF
|
||||
character
|
||||
.It "ev str" Ta Dv NULL Ta
|
||||
.No "initial environment"
|
||||
.It "f0 num unused tty mode flags to write messages"
|
||||
.It "f1 num unused tty mode flags to read login name"
|
||||
.It "f2 num unused tty mode flags to leave terminal as"
|
||||
.It "fd num 0 form-feed (vertical motion) delay"
|
||||
.It "fl str" Ta So Li ^O Sc Ta
|
||||
.No "output flush character"
|
||||
.It "hc bool false do"
|
||||
.Tn NOT
|
||||
hangup line on last close
|
||||
.It "he str" Ta Dv NULL Ta
|
||||
.No "hostname editing string"
|
||||
.It "hn str hostname hostname"
|
||||
.It "ht bool false terminal has real tabs"
|
||||
.It "ig bool false ignore garbage characters in login name"
|
||||
.It "im str" Ta Dv NULL Ta
|
||||
.No "initial (banner) message"
|
||||
.It "in str" Ta So Li ^C Sc Ta
|
||||
.No "interrupt character"
|
||||
.It "is num unused input speed"
|
||||
.It "kl str" Ta So Li ^U Sc Ta
|
||||
.No "kill character"
|
||||
.It "lc bool false terminal has lower case"
|
||||
.It "lm str login: login prompt"
|
||||
.It "ln str" Ta So Li ^V Sc Ta
|
||||
.No "``literal next'' character"
|
||||
.It "lo str" Ta Pa /usr/bin/login Ta
|
||||
.No "program to exec when name obtained"
|
||||
.It "nd num 0 newline (line-feed) delay"
|
||||
.It "nl bool false terminal has (or might have) a newline character"
|
||||
.It "np bool false terminal uses no parity (i.e. 8-bit characters)"
|
||||
.It "nx str default next table (for auto speed selection)"
|
||||
.It "op bool false terminal uses odd parity"
|
||||
.It "os num unused output speed"
|
||||
.It "pc str" Ta So Li \e0 Sc Ta
|
||||
.No "pad character"
|
||||
.It "pe bool false use printer (hard copy) erase algorithm"
|
||||
.It "pf num 0 delay"
|
||||
between first prompt and following flush (seconds)
|
||||
.It "ps bool false line connected to a"
|
||||
.Tn MICOM
|
||||
port selector
|
||||
.It "qu str" Ta So Li \&^\e Sc Ta
|
||||
.No "quit character"
|
||||
.It "rp str" Ta So Li ^R Sc Ta
|
||||
.No "line retype character"
|
||||
.It "rw bool false do"
|
||||
.Tn NOT
|
||||
use raw for input, use cbreak
|
||||
.It "sp num unused line speed (input and output)"
|
||||
.It "su str" Ta So Li ^Z Sc Ta
|
||||
.No "suspend character"
|
||||
.It "tc str none table continuation"
|
||||
.It "to num 0 timeout (seconds)"
|
||||
.It "tt str" Ta Dv NULL Ta
|
||||
.No "terminal type (for environment)"
|
||||
.It "ub bool false do unbuffered output (of prompts etc)"
|
||||
.It "uc bool false terminal is known upper case only"
|
||||
.It "we str" Ta So Li ^W Sc Ta
|
||||
.No "word erase character"
|
||||
.It "xc bool false do
|
||||
.Tn NOT
|
||||
echo control chars as
|
||||
.Ql ^X
|
||||
.It "xf str" Ta So Li ^S Sc Ta Dv XOFF
|
||||
(stop output) character
|
||||
.It "xn str" Ta So Li ^Q Sc Ta Dv XON
|
||||
(start output) character
|
||||
.El
|
||||
.Pp
|
||||
If no line speed is specified, speed will not be altered
|
||||
from that which prevails when getty is entered.
|
||||
Specifying an input or output speed will override
|
||||
line speed for stated direction only.
|
||||
.Pp
|
||||
Terminal modes to be used for the output of the message,
|
||||
for input of the login name,
|
||||
and to leave the terminal set as upon completion,
|
||||
are derived from the boolean flags specified.
|
||||
If the derivation should prove inadequate,
|
||||
any (or all) of these three may be overridden
|
||||
with one of the
|
||||
.Em \&f0 ,
|
||||
.Em \&f1 ,
|
||||
or
|
||||
.Em \&f2
|
||||
numeric specifications, which can be used to specify
|
||||
(usually in octal, with a leading '0')
|
||||
the exact values of the flags.
|
||||
Local (new tty) flags are set in the top 16 bits
|
||||
of this (32 bit) value.
|
||||
.Pp
|
||||
Should
|
||||
.Xr getty
|
||||
receive a null character
|
||||
(presumed to indicate a line break)
|
||||
it will restart using the table indicated by the
|
||||
.Em nx
|
||||
entry. If there is none, it will re-use its original table.
|
||||
.Pp
|
||||
Delays are specified in milliseconds, the nearest possible
|
||||
delay available in the tty driver will be used.
|
||||
Should greater certainty be desired, delays
|
||||
with values 0, 1, 2, and 3 are interpreted as
|
||||
choosing that particular delay algorithm from the driver.
|
||||
.Pp
|
||||
The
|
||||
.Em \&cl
|
||||
screen clear string may be preceded by a (decimal) number
|
||||
of milliseconds of delay required (a la termcap).
|
||||
This delay is simulated by repeated use of the pad character
|
||||
.Em \&pc .
|
||||
.Pp
|
||||
The initial message, and login message,
|
||||
.Em \&im
|
||||
and
|
||||
.Em \&lm
|
||||
may include the character sequence
|
||||
.Em \&%h
|
||||
or
|
||||
.Em \&%t
|
||||
to obtain
|
||||
the hostname or tty name respectively.
|
||||
.Pf ( Em %%
|
||||
obtains a single '%' character.)
|
||||
The hostname is normally obtained from the system,
|
||||
but may be set by the
|
||||
.Em \&hn
|
||||
table entry.
|
||||
In either case it may be edited with
|
||||
.Em \&he .
|
||||
The
|
||||
.Em \&he
|
||||
string is a sequence of characters, each character that
|
||||
is neither '@' nor '#' is copied into the final hostname.
|
||||
A '@' in the
|
||||
.Em \&he
|
||||
string, causes one character from the real hostname to
|
||||
be copied to the final hostname.
|
||||
A '#' in the
|
||||
.Em \&he
|
||||
string, causes the next character of the real hostname
|
||||
to be skipped.
|
||||
Surplus '@' and '#' characters are ignored.
|
||||
.Pp
|
||||
When getty execs the login process, given
|
||||
in the
|
||||
.Em \&lo
|
||||
string (usually
|
||||
.Dq Pa /usr/bin/login ) ,
|
||||
it will have set
|
||||
the environment to include the terminal type, as indicated
|
||||
by the
|
||||
.Em \&tt
|
||||
string (if it exists).
|
||||
The
|
||||
.Em \&ev
|
||||
string, can be used to enter additional data into
|
||||
the environment.
|
||||
It is a list of comma separated strings, each of which
|
||||
will presumably be of the form
|
||||
.Em name=value .
|
||||
.Pp
|
||||
If a non-zero timeout is specified, with
|
||||
.Em \&to ,
|
||||
then getty will exit within the indicated
|
||||
number of seconds, either having
|
||||
received a login name and passed control
|
||||
to
|
||||
.Xr login ,
|
||||
or having received an alarm signal, and exited.
|
||||
This may be useful to hangup dial in lines.
|
||||
.Pp
|
||||
Output from
|
||||
.Xr getty
|
||||
is even parity unless
|
||||
.Em \&op
|
||||
is specified.
|
||||
The
|
||||
.Em \&op
|
||||
string
|
||||
may be specified with
|
||||
.Em \&ap
|
||||
to allow any parity on input, but generate odd parity output.
|
||||
Note: this only applies while getty is being run,
|
||||
terminal driver limitations prevent a more complete
|
||||
implementation.
|
||||
.Xr Getty
|
||||
does not check parity of input characters in
|
||||
.Dv RAW
|
||||
mode.
|
||||
.Sh SEE ALSO
|
||||
.Xr login 1 ,
|
||||
.Xr termcap 5 ,
|
||||
.Xr getty 8 .
|
||||
.Sh BUGS
|
||||
The special characters (erase, kill, etc.) are reset to system defaults
|
||||
by
|
||||
.Xr login 1 .
|
||||
In
|
||||
.Em all
|
||||
cases, '#' or '^H' typed in a login name will be treated as
|
||||
an erase character, and '@' will be treated as a kill character.
|
||||
.Pp
|
||||
The delay stuff is a real crock.
|
||||
Apart form its general lack of flexibility, some
|
||||
of the delay algorithms are not implemented.
|
||||
The terminal driver should support sane delay settings.
|
||||
.Pp
|
||||
The
|
||||
.Em \&he
|
||||
capability is stupid.
|
||||
.Pp
|
||||
The
|
||||
.Xr termcap
|
||||
format is horrid, something more rational should
|
||||
have been chosen.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm gettytab
|
||||
file format appeared in 4.2BSD.
|
||||
145
libexec/getty/gettytab.h
Normal file
145
libexec/getty/gettytab.h
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright (c) 1983, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)gettytab.h 8.2 (Berkeley) 3/30/94
|
||||
*/
|
||||
|
||||
/*
|
||||
* Getty description definitions.
|
||||
*/
|
||||
struct gettystrs {
|
||||
char *field; /* name to lookup in gettytab */
|
||||
char *defalt; /* value we find by looking in defaults */
|
||||
char *value; /* value that we find there */
|
||||
};
|
||||
|
||||
struct gettynums {
|
||||
char *field; /* name to lookup */
|
||||
long defalt; /* number we find in defaults */
|
||||
long value; /* number we find there */
|
||||
int set; /* we actually got this one */
|
||||
};
|
||||
|
||||
struct gettyflags {
|
||||
char *field; /* name to lookup */
|
||||
char invrt; /* name existing in gettytab --> false */
|
||||
char defalt; /* true/false in defaults */
|
||||
char value; /* true/false flag */
|
||||
char set; /* we found it */
|
||||
};
|
||||
|
||||
/*
|
||||
* String values.
|
||||
*/
|
||||
#define NX gettystrs[0].value
|
||||
#define CL gettystrs[1].value
|
||||
#define IM gettystrs[2].value
|
||||
#define LM gettystrs[3].value
|
||||
#define ER gettystrs[4].value
|
||||
#define KL gettystrs[5].value
|
||||
#define ET gettystrs[6].value
|
||||
#define PC gettystrs[7].value
|
||||
#define TT gettystrs[8].value
|
||||
#define EV gettystrs[9].value
|
||||
#define LO gettystrs[10].value
|
||||
#define HN gettystrs[11].value
|
||||
#define HE gettystrs[12].value
|
||||
#define IN gettystrs[13].value
|
||||
#define QU gettystrs[14].value
|
||||
#define XN gettystrs[15].value
|
||||
#define XF gettystrs[16].value
|
||||
#define BK gettystrs[17].value
|
||||
#define SU gettystrs[18].value
|
||||
#define DS gettystrs[19].value
|
||||
#define RP gettystrs[20].value
|
||||
#define FL gettystrs[21].value
|
||||
#define WE gettystrs[22].value
|
||||
#define LN gettystrs[23].value
|
||||
|
||||
/*
|
||||
* Numeric definitions.
|
||||
*/
|
||||
#define IS gettynums[0].value
|
||||
#define OS gettynums[1].value
|
||||
#define SP gettynums[2].value
|
||||
#define ND gettynums[3].value
|
||||
#define CD gettynums[4].value
|
||||
#define TD gettynums[5].value
|
||||
#define FD gettynums[6].value
|
||||
#define BD gettynums[7].value
|
||||
#define TO gettynums[8].value
|
||||
#define F0 gettynums[9].value
|
||||
#define F0set gettynums[9].set
|
||||
#define F1 gettynums[10].value
|
||||
#define F1set gettynums[10].set
|
||||
#define F2 gettynums[11].value
|
||||
#define F2set gettynums[11].set
|
||||
#define PF gettynums[12].value
|
||||
|
||||
/*
|
||||
* Boolean values.
|
||||
*/
|
||||
#define HT gettyflags[0].value
|
||||
#define NL gettyflags[1].value
|
||||
#define EP gettyflags[2].value
|
||||
#define EPset gettyflags[2].set
|
||||
#define OP gettyflags[3].value
|
||||
#define OPset gettyflags[3].set
|
||||
#define AP gettyflags[4].value
|
||||
#define APset gettyflags[4].set
|
||||
#define EC gettyflags[5].value
|
||||
#define CO gettyflags[6].value
|
||||
#define CB gettyflags[7].value
|
||||
#define CK gettyflags[8].value
|
||||
#define CE gettyflags[9].value
|
||||
#define PE gettyflags[10].value
|
||||
#define RW gettyflags[11].value
|
||||
#define XC gettyflags[12].value
|
||||
#define LC gettyflags[13].value
|
||||
#define UC gettyflags[14].value
|
||||
#define IG gettyflags[15].value
|
||||
#define PS gettyflags[16].value
|
||||
#define HC gettyflags[17].value
|
||||
#define UB gettyflags[18].value
|
||||
#define AB gettyflags[19].value
|
||||
#define DX gettyflags[20].value
|
||||
#define NP gettyflags[21].value
|
||||
|
||||
int getent __P((char *, char *));
|
||||
long getnum __P((char *));
|
||||
int getflag __P((char *));
|
||||
char *getstr __P((char *, char **));
|
||||
|
||||
extern struct gettyflags gettyflags[];
|
||||
extern struct gettynums gettynums[];
|
||||
extern struct gettystrs gettystrs[];
|
||||
extern int hopcount;
|
||||
121
libexec/getty/init.c
Normal file
121
libexec/getty/init.c
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)init.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Getty table initializations.
|
||||
*
|
||||
* Melbourne getty.
|
||||
*/
|
||||
#include <sgtty.h>
|
||||
#include "gettytab.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
extern struct sgttyb tmode;
|
||||
extern struct tchars tc;
|
||||
extern struct ltchars ltc;
|
||||
extern char hostname[];
|
||||
|
||||
struct gettystrs gettystrs[] = {
|
||||
{ "nx" }, /* next table */
|
||||
{ "cl" }, /* screen clear characters */
|
||||
{ "im" }, /* initial message */
|
||||
{ "lm", "login: " }, /* login message */
|
||||
{ "er", &tmode.sg_erase }, /* erase character */
|
||||
{ "kl", &tmode.sg_kill }, /* kill character */
|
||||
{ "et", &tc.t_eofc }, /* eof chatacter (eot) */
|
||||
{ "pc", "" }, /* pad character */
|
||||
{ "tt" }, /* terminal type */
|
||||
{ "ev" }, /* enviroment */
|
||||
{ "lo", _PATH_LOGIN }, /* login program */
|
||||
{ "hn", hostname }, /* host name */
|
||||
{ "he" }, /* host name edit */
|
||||
{ "in", &tc.t_intrc }, /* interrupt char */
|
||||
{ "qu", &tc.t_quitc }, /* quit char */
|
||||
{ "xn", &tc.t_startc }, /* XON (start) char */
|
||||
{ "xf", &tc.t_stopc }, /* XOFF (stop) char */
|
||||
{ "bk", &tc.t_brkc }, /* brk char (alt \n) */
|
||||
{ "su", <c.t_suspc }, /* suspend char */
|
||||
{ "ds", <c.t_dsuspc }, /* delayed suspend */
|
||||
{ "rp", <c.t_rprntc }, /* reprint char */
|
||||
{ "fl", <c.t_flushc }, /* flush output */
|
||||
{ "we", <c.t_werasc }, /* word erase */
|
||||
{ "ln", <c.t_lnextc }, /* literal next */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
struct gettynums gettynums[] = {
|
||||
{ "is" }, /* input speed */
|
||||
{ "os" }, /* output speed */
|
||||
{ "sp" }, /* both speeds */
|
||||
{ "nd" }, /* newline delay */
|
||||
{ "cd" }, /* carriage-return delay */
|
||||
{ "td" }, /* tab delay */
|
||||
{ "fd" }, /* form-feed delay */
|
||||
{ "bd" }, /* backspace delay */
|
||||
{ "to" }, /* timeout */
|
||||
{ "f0" }, /* output flags */
|
||||
{ "f1" }, /* input flags */
|
||||
{ "f2" }, /* user mode flags */
|
||||
{ "pf" }, /* delay before flush at 1st prompt */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
struct gettyflags gettyflags[] = {
|
||||
{ "ht", 0 }, /* has tabs */
|
||||
{ "nl", 1 }, /* has newline char */
|
||||
{ "ep", 0 }, /* even parity */
|
||||
{ "op", 0 }, /* odd parity */
|
||||
{ "ap", 0 }, /* any parity */
|
||||
{ "ec", 1 }, /* no echo */
|
||||
{ "co", 0 }, /* console special */
|
||||
{ "cb", 0 }, /* crt backspace */
|
||||
{ "ck", 0 }, /* crt kill */
|
||||
{ "ce", 0 }, /* crt erase */
|
||||
{ "pe", 0 }, /* printer erase */
|
||||
{ "rw", 1 }, /* don't use raw */
|
||||
{ "xc", 1 }, /* don't ^X ctl chars */
|
||||
{ "lc", 0 }, /* terminal las lower case */
|
||||
{ "uc", 0 }, /* terminal has no lower case */
|
||||
{ "ig", 0 }, /* ignore garbage */
|
||||
{ "ps", 0 }, /* do port selector speed select */
|
||||
{ "hc", 1 }, /* don't set hangup on close */
|
||||
{ "ub", 0 }, /* unbuffered output */
|
||||
{ "ab", 0 }, /* auto-baud detect with '\r' */
|
||||
{ "dx", 0 }, /* set decctlq */
|
||||
{ "np", 0 }, /* no parity at all (8bit chars) */
|
||||
{ 0 }
|
||||
};
|
||||
549
libexec/getty/main.c
Normal file
549
libexec/getty/main.c
Normal file
|
|
@ -0,0 +1,549 @@
|
|||
/*-
|
||||
* Copyright (c) 1980, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1980, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/20/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#define USE_OLD_TTY
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <setjmp.h>
|
||||
#include <sgtty.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "gettytab.h"
|
||||
#include "pathnames.h"
|
||||
#include "extern.h"
|
||||
|
||||
/*
|
||||
* Set the amount of running time that getty should accumulate
|
||||
* before deciding that something is wrong and exit.
|
||||
*/
|
||||
#define GETTY_TIMEOUT 60 /* seconds */
|
||||
|
||||
struct sgttyb tmode = {
|
||||
0, 0, CERASE, CKILL, 0
|
||||
};
|
||||
struct tchars tc = {
|
||||
CINTR, CQUIT, CSTART,
|
||||
CSTOP, CEOF, CBRK,
|
||||
};
|
||||
struct ltchars ltc = {
|
||||
CSUSP, CDSUSP, CRPRNT,
|
||||
CFLUSH, CWERASE, CLNEXT
|
||||
};
|
||||
|
||||
int crmod, digit, lower, upper;
|
||||
|
||||
char hostname[MAXHOSTNAMELEN];
|
||||
char name[16];
|
||||
char dev[] = _PATH_DEV;
|
||||
char ttyn[32];
|
||||
char *portselector();
|
||||
char *ttyname();
|
||||
|
||||
#define OBUFSIZ 128
|
||||
#define TABBUFSIZ 512
|
||||
|
||||
char defent[TABBUFSIZ];
|
||||
char tabent[TABBUFSIZ];
|
||||
|
||||
char *env[128];
|
||||
|
||||
char partab[] = {
|
||||
0001,0201,0201,0001,0201,0001,0001,0201,
|
||||
0202,0004,0003,0205,0005,0206,0201,0001,
|
||||
0201,0001,0001,0201,0001,0201,0201,0001,
|
||||
0001,0201,0201,0001,0201,0001,0001,0201,
|
||||
0200,0000,0000,0200,0000,0200,0200,0000,
|
||||
0000,0200,0200,0000,0200,0000,0000,0200,
|
||||
0000,0200,0200,0000,0200,0000,0000,0200,
|
||||
0200,0000,0000,0200,0000,0200,0200,0000,
|
||||
0200,0000,0000,0200,0000,0200,0200,0000,
|
||||
0000,0200,0200,0000,0200,0000,0000,0200,
|
||||
0000,0200,0200,0000,0200,0000,0000,0200,
|
||||
0200,0000,0000,0200,0000,0200,0200,0000,
|
||||
0000,0200,0200,0000,0200,0000,0000,0200,
|
||||
0200,0000,0000,0200,0000,0200,0200,0000,
|
||||
0200,0000,0000,0200,0000,0200,0200,0000,
|
||||
0000,0200,0200,0000,0200,0000,0000,0201
|
||||
};
|
||||
|
||||
#define ERASE tmode.sg_erase
|
||||
#define KILL tmode.sg_kill
|
||||
#define EOT tc.t_eofc
|
||||
|
||||
jmp_buf timeout;
|
||||
|
||||
static void
|
||||
dingdong()
|
||||
{
|
||||
|
||||
alarm(0);
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
longjmp(timeout, 1);
|
||||
}
|
||||
|
||||
jmp_buf intrupt;
|
||||
|
||||
static void
|
||||
interrupt()
|
||||
{
|
||||
|
||||
signal(SIGINT, interrupt);
|
||||
longjmp(intrupt, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Action to take when getty is running too long.
|
||||
*/
|
||||
void
|
||||
timeoverrun(signo)
|
||||
int signo;
|
||||
{
|
||||
|
||||
syslog(LOG_ERR, "getty exiting due to excessive running time\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int getname __P((void));
|
||||
static void oflush __P((void));
|
||||
static void prompt __P((void));
|
||||
static void putchr __P((int));
|
||||
static void putf __P((char *));
|
||||
static void putpad __P((char *));
|
||||
static void puts __P((char *));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern char **environ;
|
||||
char *tname;
|
||||
long allflags;
|
||||
int repcnt = 0;
|
||||
struct rlimit limit;
|
||||
|
||||
signal(SIGINT, SIG_IGN);
|
||||
/*
|
||||
signal(SIGQUIT, SIG_DFL);
|
||||
*/
|
||||
openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
|
||||
gethostname(hostname, sizeof(hostname));
|
||||
if (hostname[0] == '\0')
|
||||
strcpy(hostname, "Amnesiac");
|
||||
|
||||
/*
|
||||
* Limit running time to deal with broken or dead lines.
|
||||
*/
|
||||
(void)signal(SIGXCPU, timeoverrun);
|
||||
limit.rlim_max = RLIM_INFINITY;
|
||||
limit.rlim_cur = GETTY_TIMEOUT;
|
||||
(void)setrlimit(RLIMIT_CPU, &limit);
|
||||
|
||||
/*
|
||||
* The following is a work around for vhangup interactions
|
||||
* which cause great problems getting window systems started.
|
||||
* If the tty line is "-", we do the old style getty presuming
|
||||
* that the file descriptors are already set up for us.
|
||||
* J. Gettys - MIT Project Athena.
|
||||
*/
|
||||
if (argc <= 2 || strcmp(argv[2], "-") == 0)
|
||||
strcpy(ttyn, ttyname(0));
|
||||
else {
|
||||
int i;
|
||||
|
||||
strcpy(ttyn, dev);
|
||||
strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
|
||||
if (strcmp(argv[0], "+") != 0) {
|
||||
chown(ttyn, 0, 0);
|
||||
chmod(ttyn, 0600);
|
||||
revoke(ttyn);
|
||||
/*
|
||||
* Delay the open so DTR stays down long enough to be detected.
|
||||
*/
|
||||
sleep(2);
|
||||
while ((i = open(ttyn, O_RDWR)) == -1) {
|
||||
if (repcnt % 10 == 0) {
|
||||
syslog(LOG_ERR, "%s: %m", ttyn);
|
||||
closelog();
|
||||
}
|
||||
repcnt++;
|
||||
sleep(60);
|
||||
}
|
||||
login_tty(i);
|
||||
}
|
||||
}
|
||||
|
||||
gettable("default", defent);
|
||||
gendefaults();
|
||||
tname = "default";
|
||||
if (argc > 1)
|
||||
tname = argv[1];
|
||||
for (;;) {
|
||||
int off;
|
||||
|
||||
gettable(tname, tabent);
|
||||
if (OPset || EPset || APset)
|
||||
APset++, OPset++, EPset++;
|
||||
setdefaults();
|
||||
off = 0;
|
||||
ioctl(0, TIOCFLUSH, &off); /* clear out the crap */
|
||||
ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */
|
||||
ioctl(0, FIOASYNC, &off); /* ditto for async mode */
|
||||
if (IS)
|
||||
tmode.sg_ispeed = speed(IS);
|
||||
else if (SP)
|
||||
tmode.sg_ispeed = speed(SP);
|
||||
if (OS)
|
||||
tmode.sg_ospeed = speed(OS);
|
||||
else if (SP)
|
||||
tmode.sg_ospeed = speed(SP);
|
||||
tmode.sg_flags = setflags(0);
|
||||
ioctl(0, TIOCSETP, &tmode);
|
||||
setchars();
|
||||
ioctl(0, TIOCSETC, &tc);
|
||||
if (HC)
|
||||
ioctl(0, TIOCHPCL, 0);
|
||||
if (AB) {
|
||||
extern char *autobaud();
|
||||
|
||||
tname = autobaud();
|
||||
continue;
|
||||
}
|
||||
if (PS) {
|
||||
tname = portselector();
|
||||
continue;
|
||||
}
|
||||
if (CL && *CL)
|
||||
putpad(CL);
|
||||
edithost(HE);
|
||||
if (IM && *IM)
|
||||
putf(IM);
|
||||
if (setjmp(timeout)) {
|
||||
tmode.sg_ispeed = tmode.sg_ospeed = 0;
|
||||
ioctl(0, TIOCSETP, &tmode);
|
||||
exit(1);
|
||||
}
|
||||
if (TO) {
|
||||
signal(SIGALRM, dingdong);
|
||||
alarm(TO);
|
||||
}
|
||||
if (getname()) {
|
||||
register int i;
|
||||
|
||||
oflush();
|
||||
alarm(0);
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
if (name[0] == '-') {
|
||||
puts("user names may not start with '-'.");
|
||||
continue;
|
||||
}
|
||||
if (!(upper || lower || digit))
|
||||
continue;
|
||||
allflags = setflags(2);
|
||||
tmode.sg_flags = allflags & 0xffff;
|
||||
allflags >>= 16;
|
||||
if (crmod || NL)
|
||||
tmode.sg_flags |= CRMOD;
|
||||
if (upper || UC)
|
||||
tmode.sg_flags |= LCASE;
|
||||
if (lower || LC)
|
||||
tmode.sg_flags &= ~LCASE;
|
||||
ioctl(0, TIOCSETP, &tmode);
|
||||
ioctl(0, TIOCSLTC, <c);
|
||||
ioctl(0, TIOCLSET, &allflags);
|
||||
signal(SIGINT, SIG_DFL);
|
||||
for (i = 0; environ[i] != (char *)0; i++)
|
||||
env[i] = environ[i];
|
||||
makeenv(&env[i]);
|
||||
|
||||
/*
|
||||
* this is what login was doing anyway.
|
||||
* soon we rewrite getty completely.
|
||||
*/
|
||||
set_ttydefaults(0);
|
||||
limit.rlim_max = RLIM_INFINITY;
|
||||
limit.rlim_cur = RLIM_INFINITY;
|
||||
(void)setrlimit(RLIMIT_CPU, &limit);
|
||||
execle(LO, "login", "-p", name, (char *) 0, env);
|
||||
syslog(LOG_ERR, "%s: %m", LO);
|
||||
exit(1);
|
||||
}
|
||||
alarm(0);
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
signal(SIGINT, SIG_IGN);
|
||||
if (NX && *NX)
|
||||
tname = NX;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
getname()
|
||||
{
|
||||
register int c;
|
||||
register char *np;
|
||||
char cs;
|
||||
|
||||
/*
|
||||
* Interrupt may happen if we use CBREAK mode
|
||||
*/
|
||||
if (setjmp(intrupt)) {
|
||||
signal(SIGINT, SIG_IGN);
|
||||
return (0);
|
||||
}
|
||||
signal(SIGINT, interrupt);
|
||||
tmode.sg_flags = setflags(0);
|
||||
ioctl(0, TIOCSETP, &tmode);
|
||||
tmode.sg_flags = setflags(1);
|
||||
prompt();
|
||||
if (PF > 0) {
|
||||
oflush();
|
||||
sleep(PF);
|
||||
PF = 0;
|
||||
}
|
||||
ioctl(0, TIOCSETP, &tmode);
|
||||
crmod = digit = lower = upper = 0;
|
||||
np = name;
|
||||
for (;;) {
|
||||
oflush();
|
||||
if (read(STDIN_FILENO, &cs, 1) <= 0)
|
||||
exit(0);
|
||||
if ((c = cs&0177) == 0)
|
||||
return (0);
|
||||
if (c == EOT)
|
||||
exit(1);
|
||||
if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
|
||||
putf("\r\n");
|
||||
break;
|
||||
}
|
||||
if (islower(c))
|
||||
lower = 1;
|
||||
else if (isupper(c))
|
||||
upper = 1;
|
||||
else if (c == ERASE || c == '#' || c == '\b') {
|
||||
if (np > name) {
|
||||
np--;
|
||||
if (tmode.sg_ospeed >= B1200)
|
||||
puts("\b \b");
|
||||
else
|
||||
putchr(cs);
|
||||
}
|
||||
continue;
|
||||
} else if (c == KILL || c == '@') {
|
||||
putchr(cs);
|
||||
putchr('\r');
|
||||
if (tmode.sg_ospeed < B1200)
|
||||
putchr('\n');
|
||||
/* this is the way they do it down under ... */
|
||||
else if (np > name)
|
||||
puts(" \r");
|
||||
prompt();
|
||||
np = name;
|
||||
continue;
|
||||
} else if (isdigit(c))
|
||||
digit++;
|
||||
if (IG && (c <= ' ' || c > 0176))
|
||||
continue;
|
||||
*np++ = c;
|
||||
putchr(cs);
|
||||
}
|
||||
signal(SIGINT, SIG_IGN);
|
||||
*np = 0;
|
||||
if (c == '\r')
|
||||
crmod = 1;
|
||||
if (upper && !lower && !LC || UC)
|
||||
for (np = name; *np; np++)
|
||||
if (isupper(*np))
|
||||
*np = tolower(*np);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static
|
||||
short tmspc10[] = {
|
||||
0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
|
||||
};
|
||||
|
||||
static void
|
||||
putpad(s)
|
||||
register char *s;
|
||||
{
|
||||
register pad = 0;
|
||||
register mspc10;
|
||||
|
||||
if (isdigit(*s)) {
|
||||
while (isdigit(*s)) {
|
||||
pad *= 10;
|
||||
pad += *s++ - '0';
|
||||
}
|
||||
pad *= 10;
|
||||
if (*s == '.' && isdigit(s[1])) {
|
||||
pad += s[1] - '0';
|
||||
s += 2;
|
||||
}
|
||||
}
|
||||
|
||||
puts(s);
|
||||
/*
|
||||
* If no delay needed, or output speed is
|
||||
* not comprehensible, then don't try to delay.
|
||||
*/
|
||||
if (pad == 0)
|
||||
return;
|
||||
if (tmode.sg_ospeed <= 0 ||
|
||||
tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Round up by a half a character frame, and then do the delay.
|
||||
* Too bad there are no user program accessible programmed delays.
|
||||
* Transmitting pad characters slows many terminals down and also
|
||||
* loads the system.
|
||||
*/
|
||||
mspc10 = tmspc10[tmode.sg_ospeed];
|
||||
pad += mspc10 / 2;
|
||||
for (pad /= mspc10; pad > 0; pad--)
|
||||
putchr(*PC);
|
||||
}
|
||||
|
||||
static void
|
||||
puts(s)
|
||||
register char *s;
|
||||
{
|
||||
while (*s)
|
||||
putchr(*s++);
|
||||
}
|
||||
|
||||
char outbuf[OBUFSIZ];
|
||||
int obufcnt = 0;
|
||||
|
||||
static void
|
||||
putchr(cc)
|
||||
int cc;
|
||||
{
|
||||
char c;
|
||||
|
||||
c = cc;
|
||||
if (!NP) {
|
||||
c |= partab[c&0177] & 0200;
|
||||
if (OP)
|
||||
c ^= 0200;
|
||||
}
|
||||
if (!UB) {
|
||||
outbuf[obufcnt++] = c;
|
||||
if (obufcnt >= OBUFSIZ)
|
||||
oflush();
|
||||
} else
|
||||
write(STDOUT_FILENO, &c, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
oflush()
|
||||
{
|
||||
if (obufcnt)
|
||||
write(STDOUT_FILENO, outbuf, obufcnt);
|
||||
obufcnt = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
prompt()
|
||||
{
|
||||
|
||||
putf(LM);
|
||||
if (CO)
|
||||
putchr('\n');
|
||||
}
|
||||
|
||||
static void
|
||||
putf(cp)
|
||||
register char *cp;
|
||||
{
|
||||
extern char editedhost[];
|
||||
time_t t;
|
||||
char *slash, db[100];
|
||||
|
||||
while (*cp) {
|
||||
if (*cp != '%') {
|
||||
putchr(*cp++);
|
||||
continue;
|
||||
}
|
||||
switch (*++cp) {
|
||||
|
||||
case 't':
|
||||
slash = strrchr(ttyn, '/');
|
||||
if (slash == (char *) 0)
|
||||
puts(ttyn);
|
||||
else
|
||||
puts(&slash[1]);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
puts(editedhost);
|
||||
break;
|
||||
|
||||
case 'd': {
|
||||
static char fmt[] = "%l:% %P on %A, %d %B %Y";
|
||||
|
||||
fmt[4] = 'M'; /* I *hate* SCCS... */
|
||||
(void)time(&t);
|
||||
(void)strftime(db, sizeof(db), fmt, localtime(&t));
|
||||
puts(db);
|
||||
break;
|
||||
}
|
||||
|
||||
case '%':
|
||||
putchr('%');
|
||||
break;
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
39
libexec/getty/pathnames.h
Normal file
39
libexec/getty/pathnames.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
#include <paths.h>
|
||||
|
||||
#define _PATH_GETTYTAB "/etc/gettytab"
|
||||
#define _PATH_LOGIN "/usr/bin/login"
|
||||
531
libexec/getty/subr.c
Normal file
531
libexec/getty/subr.c
Normal file
|
|
@ -0,0 +1,531 @@
|
|||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)subr.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Melbourne getty.
|
||||
*/
|
||||
#define USE_OLD_TTY
|
||||
#include <stdlib.h>
|
||||
#include <sgtty.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "gettytab.h"
|
||||
#include "extern.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
extern struct sgttyb tmode;
|
||||
extern struct tchars tc;
|
||||
extern struct ltchars ltc;
|
||||
|
||||
/*
|
||||
* Get a table entry.
|
||||
*/
|
||||
void
|
||||
gettable(name, buf)
|
||||
char *name, *buf;
|
||||
{
|
||||
register struct gettystrs *sp;
|
||||
register struct gettynums *np;
|
||||
register struct gettyflags *fp;
|
||||
long n;
|
||||
char *dba[2];
|
||||
dba[0] = _PATH_GETTYTAB;
|
||||
dba[1] = 0;
|
||||
|
||||
if (cgetent(&buf, dba, name) != 0)
|
||||
return;
|
||||
|
||||
for (sp = gettystrs; sp->field; sp++)
|
||||
cgetstr(buf, sp->field, &sp->value);
|
||||
for (np = gettynums; np->field; np++) {
|
||||
if (cgetnum(buf, np->field, &n) == -1)
|
||||
np->set = 0;
|
||||
else {
|
||||
np->set = 1;
|
||||
np->value = n;
|
||||
}
|
||||
}
|
||||
for (fp = gettyflags; fp->field; fp++) {
|
||||
if (cgetcap(buf, fp->field, ':') == NULL)
|
||||
fp->set = 0;
|
||||
else {
|
||||
fp->set = 1;
|
||||
fp->value = 1 ^ fp->invrt;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("name=\"%s\", buf=\"%s\"\n", name, buf);
|
||||
for (sp = gettystrs; sp->field; sp++)
|
||||
printf("cgetstr: %s=%s\n", sp->field, sp->value);
|
||||
for (np = gettynums; np->field; np++)
|
||||
printf("cgetnum: %s=%d\n", np->field, np->value);
|
||||
for (fp = gettyflags; fp->field; fp++)
|
||||
printf("cgetflags: %s='%c' set='%c'\n", fp->field,
|
||||
fp->value + '0', fp->set + '0');
|
||||
exit(1);
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
void
|
||||
gendefaults()
|
||||
{
|
||||
register struct gettystrs *sp;
|
||||
register struct gettynums *np;
|
||||
register struct gettyflags *fp;
|
||||
|
||||
for (sp = gettystrs; sp->field; sp++)
|
||||
if (sp->value)
|
||||
sp->defalt = sp->value;
|
||||
for (np = gettynums; np->field; np++)
|
||||
if (np->set)
|
||||
np->defalt = np->value;
|
||||
for (fp = gettyflags; fp->field; fp++)
|
||||
if (fp->set)
|
||||
fp->defalt = fp->value;
|
||||
else
|
||||
fp->defalt = fp->invrt;
|
||||
}
|
||||
|
||||
void
|
||||
setdefaults()
|
||||
{
|
||||
register struct gettystrs *sp;
|
||||
register struct gettynums *np;
|
||||
register struct gettyflags *fp;
|
||||
|
||||
for (sp = gettystrs; sp->field; sp++)
|
||||
if (!sp->value)
|
||||
sp->value = sp->defalt;
|
||||
for (np = gettynums; np->field; np++)
|
||||
if (!np->set)
|
||||
np->value = np->defalt;
|
||||
for (fp = gettyflags; fp->field; fp++)
|
||||
if (!fp->set)
|
||||
fp->value = fp->defalt;
|
||||
}
|
||||
|
||||
static char **
|
||||
charnames[] = {
|
||||
&ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
|
||||
&SU, &DS, &RP, &FL, &WE, &LN, 0
|
||||
};
|
||||
|
||||
static char *
|
||||
charvars[] = {
|
||||
&tmode.sg_erase, &tmode.sg_kill, &tc.t_intrc,
|
||||
&tc.t_quitc, &tc.t_startc, &tc.t_stopc,
|
||||
&tc.t_eofc, &tc.t_brkc, <c.t_suspc,
|
||||
<c.t_dsuspc, <c.t_rprntc, <c.t_flushc,
|
||||
<c.t_werasc, <c.t_lnextc, 0
|
||||
};
|
||||
|
||||
void
|
||||
setchars()
|
||||
{
|
||||
register int i;
|
||||
register char *p;
|
||||
|
||||
for (i = 0; charnames[i]; i++) {
|
||||
p = *charnames[i];
|
||||
if (p && *p)
|
||||
*charvars[i] = *p;
|
||||
else
|
||||
*charvars[i] = '\377';
|
||||
}
|
||||
}
|
||||
|
||||
long
|
||||
setflags(n)
|
||||
int n;
|
||||
{
|
||||
register long f;
|
||||
|
||||
switch (n) {
|
||||
case 0:
|
||||
if (F0set)
|
||||
return(F0);
|
||||
break;
|
||||
case 1:
|
||||
if (F1set)
|
||||
return(F1);
|
||||
break;
|
||||
default:
|
||||
if (F2set)
|
||||
return(F2);
|
||||
break;
|
||||
}
|
||||
|
||||
f = 0;
|
||||
|
||||
if (AP)
|
||||
f |= ANYP;
|
||||
else if (OP)
|
||||
f |= ODDP;
|
||||
else if (EP)
|
||||
f |= EVENP;
|
||||
|
||||
if (UC)
|
||||
f |= LCASE;
|
||||
|
||||
if (NL)
|
||||
f |= CRMOD;
|
||||
|
||||
f |= delaybits();
|
||||
|
||||
if (n == 1) { /* read mode flags */
|
||||
if (RW)
|
||||
f |= RAW;
|
||||
else
|
||||
f |= CBREAK;
|
||||
return (f);
|
||||
}
|
||||
|
||||
if (!HT)
|
||||
f |= XTABS;
|
||||
|
||||
if (n == 0)
|
||||
return (f);
|
||||
|
||||
if (CB)
|
||||
f |= CRTBS;
|
||||
|
||||
if (CE)
|
||||
f |= CRTERA;
|
||||
|
||||
if (CK)
|
||||
f |= CRTKIL;
|
||||
|
||||
if (PE)
|
||||
f |= PRTERA;
|
||||
|
||||
if (EC)
|
||||
f |= ECHO;
|
||||
|
||||
if (XC)
|
||||
f |= CTLECH;
|
||||
|
||||
if (DX)
|
||||
f |= DECCTQ;
|
||||
|
||||
return (f);
|
||||
}
|
||||
|
||||
struct delayval {
|
||||
unsigned delay; /* delay in ms */
|
||||
int bits;
|
||||
};
|
||||
|
||||
/*
|
||||
* below are random guesses, I can't be bothered checking
|
||||
*/
|
||||
|
||||
struct delayval crdelay[] = {
|
||||
{ 1, CR1 },
|
||||
{ 2, CR2 },
|
||||
{ 3, CR3 },
|
||||
{ 83, CR1 },
|
||||
{ 166, CR2 },
|
||||
{ 0, CR3 },
|
||||
};
|
||||
|
||||
struct delayval nldelay[] = {
|
||||
{ 1, NL1 }, /* special, calculated */
|
||||
{ 2, NL2 },
|
||||
{ 3, NL3 },
|
||||
{ 100, NL2 },
|
||||
{ 0, NL3 },
|
||||
};
|
||||
|
||||
struct delayval bsdelay[] = {
|
||||
{ 1, BS1 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
struct delayval ffdelay[] = {
|
||||
{ 1, FF1 },
|
||||
{ 1750, FF1 },
|
||||
{ 0, FF1 },
|
||||
};
|
||||
|
||||
struct delayval tbdelay[] = {
|
||||
{ 1, TAB1 },
|
||||
{ 2, TAB2 },
|
||||
{ 3, XTABS }, /* this is expand tabs */
|
||||
{ 100, TAB1 },
|
||||
{ 0, TAB2 },
|
||||
};
|
||||
|
||||
int
|
||||
delaybits()
|
||||
{
|
||||
register int f;
|
||||
|
||||
f = adelay(CD, crdelay);
|
||||
f |= adelay(ND, nldelay);
|
||||
f |= adelay(FD, ffdelay);
|
||||
f |= adelay(TD, tbdelay);
|
||||
f |= adelay(BD, bsdelay);
|
||||
return (f);
|
||||
}
|
||||
|
||||
int
|
||||
adelay(ms, dp)
|
||||
register ms;
|
||||
register struct delayval *dp;
|
||||
{
|
||||
if (ms == 0)
|
||||
return (0);
|
||||
while (dp->delay && ms > dp->delay)
|
||||
dp++;
|
||||
return (dp->bits);
|
||||
}
|
||||
|
||||
char editedhost[32];
|
||||
|
||||
void
|
||||
edithost(pat)
|
||||
register char *pat;
|
||||
{
|
||||
register char *host = HN;
|
||||
register char *res = editedhost;
|
||||
|
||||
if (!pat)
|
||||
pat = "";
|
||||
while (*pat) {
|
||||
switch (*pat) {
|
||||
|
||||
case '#':
|
||||
if (*host)
|
||||
host++;
|
||||
break;
|
||||
|
||||
case '@':
|
||||
if (*host)
|
||||
*res++ = *host++;
|
||||
break;
|
||||
|
||||
default:
|
||||
*res++ = *pat;
|
||||
break;
|
||||
|
||||
}
|
||||
if (res == &editedhost[sizeof editedhost - 1]) {
|
||||
*res = '\0';
|
||||
return;
|
||||
}
|
||||
pat++;
|
||||
}
|
||||
if (*host)
|
||||
strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
|
||||
else
|
||||
*res = '\0';
|
||||
editedhost[sizeof editedhost - 1] = '\0';
|
||||
}
|
||||
|
||||
struct speedtab {
|
||||
int speed;
|
||||
int uxname;
|
||||
} speedtab[] = {
|
||||
{ 50, B50 },
|
||||
{ 75, B75 },
|
||||
{ 110, B110 },
|
||||
{ 134, B134 },
|
||||
{ 150, B150 },
|
||||
{ 200, B200 },
|
||||
{ 300, B300 },
|
||||
{ 600, B600 },
|
||||
{ 1200, B1200 },
|
||||
{ 1800, B1800 },
|
||||
{ 2400, B2400 },
|
||||
{ 4800, B4800 },
|
||||
{ 9600, B9600 },
|
||||
{ 19200, EXTA },
|
||||
{ 19, EXTA }, /* for people who say 19.2K */
|
||||
{ 38400, EXTB },
|
||||
{ 38, EXTB },
|
||||
{ 7200, EXTB }, /* alternative */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
int
|
||||
speed(val)
|
||||
int val;
|
||||
{
|
||||
register struct speedtab *sp;
|
||||
|
||||
if (val <= 15)
|
||||
return (val);
|
||||
|
||||
for (sp = speedtab; sp->speed; sp++)
|
||||
if (sp->speed == val)
|
||||
return (sp->uxname);
|
||||
|
||||
return (B300); /* default in impossible cases */
|
||||
}
|
||||
|
||||
void
|
||||
makeenv(env)
|
||||
char *env[];
|
||||
{
|
||||
static char termbuf[128] = "TERM=";
|
||||
register char *p, *q;
|
||||
register char **ep;
|
||||
|
||||
ep = env;
|
||||
if (TT && *TT) {
|
||||
strcat(termbuf, TT);
|
||||
*ep++ = termbuf;
|
||||
}
|
||||
if (p = EV) {
|
||||
q = p;
|
||||
while (q = strchr(q, ',')) {
|
||||
*q++ = '\0';
|
||||
*ep++ = p;
|
||||
p = q;
|
||||
}
|
||||
if (*p)
|
||||
*ep++ = p;
|
||||
}
|
||||
*ep = (char *)0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This speed select mechanism is written for the Develcon DATASWITCH.
|
||||
* The Develcon sends a string of the form "B{speed}\n" at a predefined
|
||||
* baud rate. This string indicates the user's actual speed.
|
||||
* The routine below returns the terminal type mapped from derived speed.
|
||||
*/
|
||||
struct portselect {
|
||||
char *ps_baud;
|
||||
char *ps_type;
|
||||
} portspeeds[] = {
|
||||
{ "B110", "std.110" },
|
||||
{ "B134", "std.134" },
|
||||
{ "B150", "std.150" },
|
||||
{ "B300", "std.300" },
|
||||
{ "B600", "std.600" },
|
||||
{ "B1200", "std.1200" },
|
||||
{ "B2400", "std.2400" },
|
||||
{ "B4800", "std.4800" },
|
||||
{ "B9600", "std.9600" },
|
||||
{ "B19200", "std.19200" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
char *
|
||||
portselector()
|
||||
{
|
||||
char c, baud[20], *type = "default";
|
||||
register struct portselect *ps;
|
||||
int len;
|
||||
|
||||
alarm(5*60);
|
||||
for (len = 0; len < sizeof (baud) - 1; len++) {
|
||||
if (read(STDIN_FILENO, &c, 1) <= 0)
|
||||
break;
|
||||
c &= 0177;
|
||||
if (c == '\n' || c == '\r')
|
||||
break;
|
||||
if (c == 'B')
|
||||
len = 0; /* in case of leading garbage */
|
||||
baud[len] = c;
|
||||
}
|
||||
baud[len] = '\0';
|
||||
for (ps = portspeeds; ps->ps_baud; ps++)
|
||||
if (strcmp(ps->ps_baud, baud) == 0) {
|
||||
type = ps->ps_type;
|
||||
break;
|
||||
}
|
||||
sleep(2); /* wait for connection to complete */
|
||||
return (type);
|
||||
}
|
||||
|
||||
/*
|
||||
* This auto-baud speed select mechanism is written for the Micom 600
|
||||
* portselector. Selection is done by looking at how the character '\r'
|
||||
* is garbled at the different speeds.
|
||||
*/
|
||||
#include <sys/time.h>
|
||||
|
||||
char *
|
||||
autobaud()
|
||||
{
|
||||
int rfds;
|
||||
struct timeval timeout;
|
||||
char c, *type = "9600-baud";
|
||||
int null = 0;
|
||||
|
||||
ioctl(0, TIOCFLUSH, &null);
|
||||
rfds = 1 << 0;
|
||||
timeout.tv_sec = 5;
|
||||
timeout.tv_usec = 0;
|
||||
if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
|
||||
(fd_set *)NULL, &timeout) <= 0)
|
||||
return (type);
|
||||
if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
|
||||
return (type);
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 20;
|
||||
(void) select(32, (fd_set *)NULL, (fd_set *)NULL,
|
||||
(fd_set *)NULL, &timeout);
|
||||
ioctl(0, TIOCFLUSH, &null);
|
||||
switch (c & 0377) {
|
||||
|
||||
case 0200: /* 300-baud */
|
||||
type = "300-baud";
|
||||
break;
|
||||
|
||||
case 0346: /* 1200-baud */
|
||||
type = "1200-baud";
|
||||
break;
|
||||
|
||||
case 015: /* 2400-baud */
|
||||
case 0215:
|
||||
type = "2400-baud";
|
||||
break;
|
||||
|
||||
default: /* 4800-baud */
|
||||
type = "4800-baud";
|
||||
break;
|
||||
|
||||
case 0377: /* 9600-baud */
|
||||
type = "9600-baud";
|
||||
break;
|
||||
}
|
||||
return (type);
|
||||
}
|
||||
54
libexec/getty/ttydefaults.c
Normal file
54
libexec/getty/ttydefaults.c
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)ttydefaults.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/termios.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
void
|
||||
set_ttydefaults(fd)
|
||||
int fd;
|
||||
{
|
||||
struct termios term;
|
||||
|
||||
tcgetattr(fd, &term);
|
||||
term.c_iflag = TTYDEF_IFLAG;
|
||||
term.c_oflag = TTYDEF_OFLAG;
|
||||
term.c_lflag = TTYDEF_LFLAG;
|
||||
term.c_cflag = TTYDEF_CFLAG;
|
||||
tcsetattr(fd, TCSAFLUSH, &term);
|
||||
}
|
||||
139
libexec/getty/ttys.5
Normal file
139
libexec/getty/ttys.5
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
.\" Copyright (c) 1985, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)ttys.5 8.1 (Berkeley) 6/4/93
|
||||
.\"
|
||||
.Dd June 4, 1993
|
||||
.Dt TTYS 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ttys
|
||||
.Nd terminal initialization information
|
||||
.Sh DESCRIPTION
|
||||
The file
|
||||
.Nm ttys
|
||||
contains information that is used by various routines to initialize
|
||||
and control the use of terminal special files.
|
||||
This information is read with the
|
||||
.Xr getttyent 3
|
||||
library routines.
|
||||
There is one line in the
|
||||
.Nm ttys
|
||||
file per special device file.
|
||||
Fields are separated by tabs and/or spaces.
|
||||
Fields comprised of more than one word should be enclosed in double
|
||||
quotes (``"'').
|
||||
Blank lines and comments may appear anywhere in the file; comments
|
||||
are delimited by hash marks (``#'') and new lines.
|
||||
Any unspecified fields will default to null.
|
||||
.Pp
|
||||
The first field is the
|
||||
name of the terminal special file as it is found in
|
||||
.Pa /dev .
|
||||
.Pp
|
||||
The second field of the file is the command to execute for the line,
|
||||
usually
|
||||
.Xr getty 8 ,
|
||||
which initializes and opens the line, setting the speed, waiting for
|
||||
a user name and executing the
|
||||
.Xr login 1
|
||||
program.
|
||||
It can be, however, any desired command, for example
|
||||
the start up for a window system terminal emulator or some other
|
||||
daemon process, and can contain multiple words if quoted.
|
||||
.Pp
|
||||
The third field is the type of terminal usually connected to that
|
||||
tty line, normally the one found in the
|
||||
.Xr termcap 5
|
||||
data base file.
|
||||
The environment variable
|
||||
.Dv TERM
|
||||
is initialized with the value by
|
||||
either
|
||||
.Xr getty 8
|
||||
or
|
||||
.Xr login 1 .
|
||||
.Pp
|
||||
The remaining fields set flags in the
|
||||
.Fa ty_status
|
||||
entry (see
|
||||
.Xr getttyent 3 )
|
||||
or specify a window system process that
|
||||
.Xr init 8
|
||||
will maintain for the terminal line.
|
||||
.Pp
|
||||
As flag values, the strings ``on'' and ``off'' specify that
|
||||
.Xr init
|
||||
should (should not) execute the command given in the second field,
|
||||
while ``secure'' (if ``on'' is also specified) allows users with a
|
||||
uid of 0 to login on
|
||||
this line.
|
||||
These flag fields should not be quoted.
|
||||
.Pp
|
||||
The string ``window='' may be followed by a quoted command
|
||||
string which
|
||||
.Xr init
|
||||
will execute
|
||||
.Em before
|
||||
starting the command specified by the second field.
|
||||
.Sh EXAMPLES
|
||||
.Bd -literal
|
||||
# root login on console at 1200 baud
|
||||
console "/usr/libexec/getty std.1200" vt100 on secure
|
||||
# dialup at 1200 baud, no root logins
|
||||
ttyd0 "/usr/libexec/getty d1200" dialup on # 555-1234
|
||||
# Mike's terminal: hp2621
|
||||
ttyh0 "/usr/libexec/getty std.9600" hp2621-nl on # 457 Evans
|
||||
# John's terminal: vt100
|
||||
ttyh1 "/usr/libexec/getty std.9600" vt100 on # 459 Evans
|
||||
# terminal emulate/window system
|
||||
ttyv0 "/usr/new/xterm -L :0" vs100 on window="/usr/new/Xvs100 0"
|
||||
# Network pseudo ttys -- don't enable getty
|
||||
ttyp0 none network
|
||||
ttyp1 none network off
|
||||
.Ed
|
||||
.Sh FILES
|
||||
.Bl -tag -width /etc/ttys -compact
|
||||
.It Pa /etc/ttys
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr login 1 ,
|
||||
.Xr getttyent 3 ,
|
||||
.Xr ttyslot 3 ,
|
||||
.Xr gettytab 5 ,
|
||||
.Xr termcap 5 ,
|
||||
.Xr getty 8 ,
|
||||
.Xr init 8
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
file appeared in
|
||||
.At v6 .
|
||||
11
libexec/kpasswdd/Makefile
Normal file
11
libexec/kpasswdd/Makefile
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||
|
||||
PROG= kpasswdd
|
||||
SRCS= kpasswdd.c des_rw.c
|
||||
CFLAGS+=-DCRYPT -DKERBEROS -I${.CURDIR}/../../usr.bin/passwd
|
||||
DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES}
|
||||
LDADD= -lkdb -lkrb -ldes
|
||||
.PATH: ${.CURDIR}/../../usr.bin/rlogin
|
||||
MAN8= kpasswdd.0
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
60
libexec/kpasswdd/kpasswdd.8
Normal file
60
libexec/kpasswdd/kpasswdd.8
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)kpasswdd.8 8.1 (Berkeley) 6/9/93
|
||||
.\"
|
||||
.Dd June 9, 1993
|
||||
.Dt KPASSWDD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm kpasswdd
|
||||
.Nd Kerberos password changing daemon
|
||||
.Sh SYNOPSIS
|
||||
.Nm kpasswdd
|
||||
.Sh DESCRIPTION
|
||||
.Nm Kpasswdd
|
||||
is the server for the
|
||||
.Xr passwd 1
|
||||
program.
|
||||
The server provides a remote password changing facility
|
||||
with Kerberos authentication.
|
||||
A user must provide the old Kerberos password, encrypted
|
||||
in a random session key, to the server.
|
||||
.Nm Kpasswdd
|
||||
runs only on the Kerberos server, as it directly updates the
|
||||
Kerberos database.
|
||||
.Sh SEE ALSO
|
||||
.Xr kerberos 1 ,
|
||||
.Xr passwd 1
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm kpasswdd
|
||||
utility first appeared in 4.4BSD.
|
||||
271
libexec/kpasswdd/kpasswdd.c
Normal file
271
libexec/kpasswdd/kpasswdd.c
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1990, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)kpasswdd.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* kpasswdd - update a principal's passwd field in the Kerberos
|
||||
* database. Called from inetd.
|
||||
* K. Fall
|
||||
* 12-Dec-88
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/signal.h>
|
||||
#include <netinet/in.h>
|
||||
#include <pwd.h>
|
||||
#include <syslog.h>
|
||||
#include <kerberosIV/des.h>
|
||||
#include <kerberosIV/krb.h>
|
||||
#include <kerberosIV/krb_db.h>
|
||||
#include <stdio.h>
|
||||
#include "kpasswd_proto.h"
|
||||
|
||||
static struct kpasswd_data kpwd_data;
|
||||
static des_cblock master_key, key;
|
||||
static Key_schedule master_key_schedule,
|
||||
key_schedule, random_sched;
|
||||
long mkeyversion;
|
||||
AUTH_DAT kdata;
|
||||
static Principal principal_data;
|
||||
static struct update_data ud_data;
|
||||
|
||||
char inst[INST_SZ];
|
||||
char version[9];
|
||||
KTEXT_ST ticket;
|
||||
|
||||
char *progname; /* for the library */
|
||||
|
||||
main()
|
||||
{
|
||||
struct sockaddr_in foreign;
|
||||
int foreign_len = sizeof(foreign);
|
||||
int rval, more;
|
||||
static char name[] = "kpasswdd";
|
||||
|
||||
static struct rlimit rl = { 0, 0 };
|
||||
|
||||
progname = name;
|
||||
openlog("kpasswdd", LOG_CONS | LOG_PID, LOG_AUTH);
|
||||
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGTSTP, SIG_IGN);
|
||||
if (setrlimit(RLIMIT_CORE, &rl) < 0) {
|
||||
syslog(LOG_ERR, "setrlimit: %m");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (getpeername(0, &foreign, &foreign_len) < 0) {
|
||||
syslog(LOG_ERR,"getpeername: %m");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
strcpy(inst, "*");
|
||||
rval = krb_recvauth(
|
||||
0L, /* options--!MUTUAL */
|
||||
0, /* file desc */
|
||||
&ticket, /* client's ticket */
|
||||
SERVICE, /* expected service */
|
||||
inst, /* expected instance */
|
||||
&foreign, /* foreign addr */
|
||||
(struct sockaddr_in *) 0, /* local addr */
|
||||
&kdata, /* returned krb data */
|
||||
"", /* service keys file */
|
||||
(bit_64 *) NULL, /* returned key schedule */
|
||||
version
|
||||
);
|
||||
|
||||
|
||||
if (rval != KSUCCESS) {
|
||||
syslog(LOG_NOTICE, "krb_recvauth: %s", krb_err_txt[rval]);
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (*version == '\0') {
|
||||
/* indicates error on client's side (no tickets, etc.) */
|
||||
cleanup();
|
||||
exit(0);
|
||||
} else if (strcmp(version, "KPWDV0.1") != 0) {
|
||||
syslog(LOG_NOTICE,
|
||||
"kpasswdd version conflict (recv'd %s)",
|
||||
version);
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* get master key */
|
||||
if (kdb_get_master_key(0, master_key, master_key_schedule) != 0) {
|
||||
syslog(LOG_ERR, "couldn't get master key");
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mkeyversion = kdb_get_master_key(NULL, master_key, master_key_schedule);
|
||||
|
||||
if (mkeyversion < 0) {
|
||||
syslog(LOG_NOTICE, "couldn't verify master key");
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* get principal info */
|
||||
rval = kerb_get_principal(
|
||||
kdata.pname,
|
||||
kdata.pinst,
|
||||
&principal_data,
|
||||
1,
|
||||
&more
|
||||
);
|
||||
|
||||
if (rval < 0) {
|
||||
syslog(LOG_NOTICE,
|
||||
"error retrieving principal record for %s.%s",
|
||||
kdata.pname, kdata.pinst);
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (rval != 1 || (more != 0)) {
|
||||
syslog(LOG_NOTICE, "more than 1 dbase entry for %s.%s",
|
||||
kdata.pname, kdata.pinst);
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* get the user's key */
|
||||
|
||||
bcopy(&principal_data.key_low, key, 4);
|
||||
bcopy(&principal_data.key_high, ((long *) key) + 1, 4);
|
||||
kdb_encrypt_key(key, key, master_key, master_key_schedule,
|
||||
DECRYPT);
|
||||
key_sched(key, key_schedule);
|
||||
des_set_key(key, key_schedule);
|
||||
|
||||
|
||||
/* get random key and send it over {random} Kperson */
|
||||
|
||||
random_key(kpwd_data.random_key);
|
||||
strcpy(kpwd_data.secure_msg, SECURE_STRING);
|
||||
if (des_write(0, &kpwd_data, sizeof(kpwd_data)) != sizeof(kpwd_data)) {
|
||||
syslog(LOG_NOTICE, "error writing initial data");
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bzero(key, sizeof(key));
|
||||
bzero(key_schedule, sizeof(key_schedule));
|
||||
|
||||
/* now read update info: { info }Krandom */
|
||||
|
||||
key_sched(kpwd_data.random_key, random_sched);
|
||||
des_set_key(kpwd_data.random_key, random_sched);
|
||||
if (des_read(0, &ud_data, sizeof(ud_data)) != sizeof(ud_data)) {
|
||||
syslog(LOG_NOTICE, "update aborted");
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* validate info string by looking at the embedded string */
|
||||
|
||||
if (strcmp(ud_data.secure_msg, SECURE_STRING) != 0) {
|
||||
syslog(LOG_NOTICE, "invalid update from %s",
|
||||
inet_ntoa(foreign.sin_addr));
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* produce the new key entry in the database { key }Kmaster */
|
||||
string_to_key(ud_data.pw, key);
|
||||
kdb_encrypt_key(key, key,
|
||||
master_key, master_key_schedule,
|
||||
ENCRYPT);
|
||||
bcopy(key, &principal_data.key_low, 4);
|
||||
bcopy(((long *) key) + 1,
|
||||
&principal_data.key_high, 4);
|
||||
bzero(key, sizeof(key));
|
||||
principal_data.key_version++;
|
||||
if (kerb_put_principal(&principal_data, 1)) {
|
||||
syslog(LOG_ERR, "couldn't write new record for %s.%s",
|
||||
principal_data.name, principal_data.instance);
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
syslog(LOG_NOTICE,"wrote new password field for %s.%s from %s",
|
||||
principal_data.name,
|
||||
principal_data.instance,
|
||||
inet_ntoa(foreign.sin_addr)
|
||||
);
|
||||
|
||||
send_ack(0, "Update complete.\n");
|
||||
cleanup();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
bzero(&kpwd_data, sizeof(kpwd_data));
|
||||
bzero(master_key, sizeof(master_key));
|
||||
bzero(master_key_schedule, sizeof(master_key_schedule));
|
||||
bzero(key, sizeof(key));
|
||||
bzero(key_schedule, sizeof(key_schedule));
|
||||
bzero(random_sched, sizeof(random_sched));
|
||||
bzero(&principal_data, sizeof(principal_data));
|
||||
bzero(&ud_data, sizeof(ud_data));
|
||||
}
|
||||
|
||||
send_ack(remote, msg)
|
||||
int remote;
|
||||
char *msg;
|
||||
{
|
||||
int cc;
|
||||
cc = des_write(remote, msg, strlen(msg) + 1);
|
||||
if (cc <= 0) {
|
||||
syslog(LOG_NOTICE, "error writing ack");
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
10
libexec/lfs_cleanerd/Makefile
Normal file
10
libexec/lfs_cleanerd/Makefile
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/5/93
|
||||
|
||||
PROG= lfs_cleanerd
|
||||
CFLAGS+=-I/sys/ufs/lfs -I${.CURDIR} -DDIAGNOSTIC
|
||||
MAN8= lfs_cleanerd.0
|
||||
SRCS= cleanerd.c lfs_cksum.c library.c misc.c print.c
|
||||
|
||||
.PATH: /sys/ufs/lfs
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
168
libexec/lfs_cleanerd/clean.h
Normal file
168
libexec/lfs_cleanerd/clean.h
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)clean.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* The LFS user-level library will be used when writing cleaners and
|
||||
* checkers for LFS file systems. It will have facilities for finding
|
||||
* and parsing LFS segments.
|
||||
*/
|
||||
|
||||
#define DUMP_SUM_HEADER 0x0001
|
||||
#define DUMP_INODE_ADDRS 0x0002
|
||||
#define DUMP_FINFOS 0x0004
|
||||
#define DUMP_ALL 0xFFFF
|
||||
|
||||
#define IFILE_NAME "ifile"
|
||||
|
||||
/*
|
||||
* Cleaner parameters
|
||||
* BUSY_LIM: lower bound of the number of segments currently available
|
||||
* as a percentage of the total number of free segments possibly
|
||||
* available.
|
||||
* IDLE_LIM: Same as BUSY_LIM but used when the system is idle.
|
||||
* MIN_SEGS: Minimum number of segments you should always have.
|
||||
* I have no idea what this should be, but it should probably
|
||||
* be a function of lfsp.
|
||||
* NUM_TO_CLEAN: Number of segments to clean at once. Again, this
|
||||
* should probably be based on the file system size and how
|
||||
* full or empty the segments being cleaned are.
|
||||
*/
|
||||
|
||||
#define BUSY_LIM 0.50
|
||||
#define IDLE_LIM 0.90
|
||||
|
||||
#define MIN_SEGS(lfsp) (3)
|
||||
#define NUM_TO_CLEAN(fsp) (1)
|
||||
|
||||
#define MAXLOADS 3
|
||||
#define ONE_MIN 0
|
||||
#define FIVE_MIN 1
|
||||
#define FIFTEEN_MIN 2
|
||||
|
||||
typedef struct fs_info {
|
||||
struct statfs *fi_statfsp; /* fsstat info from getfsstat */
|
||||
struct lfs fi_lfs; /* superblock */
|
||||
CLEANERINFO *fi_cip; /* Cleaner info from ifile */
|
||||
SEGUSE *fi_segusep; /* segment usage table (from ifile) */
|
||||
IFILE *fi_ifilep; /* ifile table (from ifile) */
|
||||
u_long fi_daddr_shift; /* shift to get byte offset of daddr */
|
||||
u_long fi_ifile_count; /* # entries in the ifile table */
|
||||
off_t fi_ifile_length; /* length of the ifile */
|
||||
} FS_INFO;
|
||||
|
||||
/*
|
||||
* XXX: size (in bytes) of a segment
|
||||
* should lfs_bsize be fsbtodb(fs,1), blksize(fs), or lfs_dsize?
|
||||
*/
|
||||
#define seg_size(fs) ((fs)->lfs_ssize << (fs)->lfs_bshift)
|
||||
|
||||
/* daddr -> byte offset */
|
||||
#define datobyte(fs, da) ((da) << (fs)->fi_daddr_shift)
|
||||
#define bytetoda(fs, byte) ((byte) >> (fs)->fi_daddr_shift)
|
||||
|
||||
#define CLEANSIZE(fsp) (fsp->fi_lfs.lfs_cleansz << fsp->fi_lfs.lfs_bshift)
|
||||
#define SEGTABSIZE(fsp) (fsp->fi_lfs.lfs_segtabsz << fsp->fi_lfs.lfs_bshift)
|
||||
|
||||
#define IFILE_ENTRY(fs, if, i) \
|
||||
((IFILE *)((caddr_t)(if) + ((i) / (fs)->lfs_ifpb << (fs)->lfs_bshift)) \
|
||||
+ (i) % (fs)->lfs_ifpb)
|
||||
|
||||
#define SEGUSE_ENTRY(fs, su, i) \
|
||||
((SEGUSE *)((caddr_t)(su) + (fs)->lfs_bsize * ((i) / (fs)->lfs_sepb)) +\
|
||||
(i) % (fs)->lfs_sepb)
|
||||
|
||||
__BEGIN_DECLS
|
||||
int dump_summary __P((struct lfs *, SEGSUM *, u_long, daddr_t **));
|
||||
void err __P((const int, const char *, ...));
|
||||
int fs_getmntinfo __P((struct statfs **, char *, int));
|
||||
int get __P((int, off_t, void *, size_t));
|
||||
FS_INFO *get_fs_info __P((struct statfs *, int));
|
||||
int lfs_segmapv __P((FS_INFO *, int, caddr_t, BLOCK_INFO **, int *));
|
||||
int mmap_segment __P((FS_INFO *, int, caddr_t *, int));
|
||||
void munmap_segment __P((FS_INFO *, caddr_t, int));
|
||||
void reread_fs_info __P((FS_INFO *, int));
|
||||
void toss __P((void *, int *, size_t,
|
||||
int (*)(const void *, const void *, const void *), void *));
|
||||
|
||||
/*
|
||||
* USEFUL DEBUGGING FUNCTIONS:
|
||||
*/
|
||||
#ifdef VERBOSE
|
||||
#define PRINT_FINFO(fp, ip) { \
|
||||
(void)printf(" %s %s%d version %d nblocks %d\n", \
|
||||
(ip)->if_version > (fp)->fi_version ? "TOSSING" : "KEEPING", \
|
||||
"FINFO for inode: ", (fp)->fi_ino, \
|
||||
(fp)->fi_version, (fp)->fi_nblocks); \
|
||||
fflush(stdout); \
|
||||
}
|
||||
|
||||
#define PRINT_INODE(b, bip) { \
|
||||
(void) printf("\t%s inode: %d daddr: 0x%lx create: %s\n", \
|
||||
b ? "KEEPING" : "TOSSING", (bip)->bi_inode, (bip)->bi_daddr, \
|
||||
ctime((time_t *)&(bip)->bi_segcreate)); \
|
||||
fflush(stdout); \
|
||||
}
|
||||
|
||||
#define PRINT_BINFO(bip) { \
|
||||
(void)printf("\tinode: %d lbn: %d daddr: 0x%lx create: %s\n", \
|
||||
(bip)->bi_inode, (bip)->bi_lbn, (bip)->bi_daddr, \
|
||||
ctime((time_t *)&(bip)->bi_segcreate)); \
|
||||
fflush(stdout); \
|
||||
}
|
||||
|
||||
#define PRINT_SEGUSE(sup, n) { \
|
||||
(void)printf("Segment %d nbytes=%lu\tflags=%c%c%c ninos=%d nsums=%d lastmod: %s\n", \
|
||||
n, (sup)->su_nbytes, \
|
||||
(sup)->su_flags & SEGUSE_DIRTY ? 'D' : 'C', \
|
||||
(sup)->su_flags & SEGUSE_ACTIVE ? 'A' : ' ', \
|
||||
(sup)->su_flags & SEGUSE_SUPERBLOCK ? 'S' : ' ', \
|
||||
(sup)->su_ninos, (sup)->su_nsums, \
|
||||
ctime((time_t *)&(sup)->su_lastmod)); \
|
||||
fflush(stdout); \
|
||||
}
|
||||
|
||||
void dump_super __P((struct lfs *));
|
||||
void dump_cleaner_info __P((void *));
|
||||
void print_SEGSUM __P(( struct lfs *, SEGSUM *));
|
||||
void print_CLEANERINFO __P((CLEANERINFO *));
|
||||
#else
|
||||
#define PRINT_FINFO(fp, ip)
|
||||
#define PRINT_INODE(b, bip)
|
||||
#define PRINT_BINFO(bip)
|
||||
#define PRINT_SEGUSE(sup, n)
|
||||
#define dump_cleaner_info(cip)
|
||||
#define dump_super(lfsp)
|
||||
#endif
|
||||
__END_DECLS
|
||||
498
libexec/lfs_cleanerd/cleanerd.c
Normal file
498
libexec/lfs_cleanerd/cleanerd.c
Normal file
|
|
@ -0,0 +1,498 @@
|
|||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1992, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)cleanerd.c 8.2 (Berkeley) 1/13/94";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ufs/ufs/dinode.h>
|
||||
#include <ufs/lfs/lfs.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "clean.h"
|
||||
char *special = "cleanerd";
|
||||
int do_small = 0;
|
||||
int do_mmap = 0;
|
||||
struct cleaner_stats {
|
||||
int blocks_read;
|
||||
int blocks_written;
|
||||
int segs_cleaned;
|
||||
int segs_empty;
|
||||
int segs_error;
|
||||
} cleaner_stats;
|
||||
|
||||
struct seglist {
|
||||
int sl_id; /* segment number */
|
||||
int sl_cost; /* cleaning cost */
|
||||
char sl_empty; /* is segment empty */
|
||||
};
|
||||
|
||||
struct tossstruct {
|
||||
struct lfs *lfs;
|
||||
int seg;
|
||||
};
|
||||
|
||||
/* function prototypes for system calls; not sure where they should go */
|
||||
int lfs_segwait __P((fsid_t *, struct timeval *));
|
||||
int lfs_segclean __P((fsid_t *, u_long));
|
||||
int lfs_bmapv __P((fsid_t *, BLOCK_INFO *, int));
|
||||
int lfs_markv __P((fsid_t *, BLOCK_INFO *, int));
|
||||
|
||||
/* function prototypes */
|
||||
int bi_tossold __P((const void *, const void *, const void *));
|
||||
int choose_segments __P((FS_INFO *, struct seglist *,
|
||||
int (*)(FS_INFO *, SEGUSE *)));
|
||||
void clean_fs __P((FS_INFO *, int (*)(FS_INFO *, SEGUSE *)));
|
||||
int clean_loop __P((FS_INFO *));
|
||||
int clean_segment __P((FS_INFO *, int));
|
||||
int cost_benefit __P((FS_INFO *, SEGUSE *));
|
||||
int cost_compare __P((const void *, const void *));
|
||||
void sig_report __P((int));
|
||||
|
||||
/*
|
||||
* Cleaning Cost Functions:
|
||||
*
|
||||
* These return the cost of cleaning a segment. The higher the cost value
|
||||
* the better it is to clean the segment, so empty segments have the highest
|
||||
* cost. (It is probably better to think of this as a priority value
|
||||
* instead).
|
||||
*
|
||||
* This is the cost-benefit policy simulated and described in Rosenblum's
|
||||
* 1991 SOSP paper.
|
||||
*/
|
||||
|
||||
int
|
||||
cost_benefit(fsp, su)
|
||||
FS_INFO *fsp; /* file system information */
|
||||
SEGUSE *su;
|
||||
{
|
||||
struct lfs *lfsp;
|
||||
struct timeval t;
|
||||
int age;
|
||||
int live;
|
||||
|
||||
gettimeofday(&t, NULL);
|
||||
|
||||
live = su->su_nbytes;
|
||||
age = t.tv_sec < su->su_lastmod ? 0 : t.tv_sec - su->su_lastmod;
|
||||
|
||||
lfsp = &fsp->fi_lfs;
|
||||
if (live == 0)
|
||||
return (t.tv_sec * lblkno(lfsp, seg_size(lfsp)));
|
||||
else {
|
||||
/*
|
||||
* from lfsSegUsage.c (Mendel's code).
|
||||
* priority calculation is done using INTEGER arithmetic.
|
||||
* sizes are in BLOCKS (that is why we use lblkno below).
|
||||
* age is in seconds.
|
||||
*
|
||||
* priority = ((seg_size - live) * age) / (seg_size + live)
|
||||
*/
|
||||
#ifdef VERBOSE
|
||||
if (live < 0 || live > seg_size(lfsp)) {
|
||||
err(0, "Bad segusage count: %d", live);
|
||||
live = 0;
|
||||
}
|
||||
#endif
|
||||
return (lblkno(lfsp, seg_size(lfsp) - live) * age)
|
||||
/ lblkno(lfsp, seg_size(lfsp) + live);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
FS_INFO *fsp;
|
||||
struct statfs *lstatfsp; /* file system stats */
|
||||
struct timeval timeout; /* sleep timeout */
|
||||
fsid_t fsid;
|
||||
int i, nodaemon;
|
||||
int opt, cmd_err;
|
||||
char *fs_name; /* name of filesystem to clean */
|
||||
extern int optind;
|
||||
|
||||
cmd_err = nodaemon = 0;
|
||||
while ((opt = getopt(argc, argv, "smd")) != EOF) {
|
||||
switch (opt) {
|
||||
case 's': /* small writes */
|
||||
do_small = 1;
|
||||
break;
|
||||
case 'm':
|
||||
do_mmap = 1;
|
||||
break;
|
||||
case 'd':
|
||||
nodaemon = 1;
|
||||
break;
|
||||
default:
|
||||
++cmd_err;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (cmd_err || (argc != 1))
|
||||
err(1, "usage: lfs_cleanerd [-smd] fs_name");
|
||||
|
||||
fs_name = argv[0];
|
||||
|
||||
signal(SIGINT, sig_report);
|
||||
signal(SIGUSR1, sig_report);
|
||||
signal(SIGUSR2, sig_report);
|
||||
if (fs_getmntinfo(&lstatfsp, fs_name, MOUNT_LFS) == 0) {
|
||||
/* didn't find the filesystem */
|
||||
err(1, "lfs_cleanerd: filesystem %s isn't an LFS!", fs_name);
|
||||
}
|
||||
|
||||
if (!nodaemon) /* should we become a daemon, chdir to / & close fd's */
|
||||
if (daemon(0, 0) == -1)
|
||||
err(1, "lfs_cleanerd: couldn't become a daemon!");
|
||||
|
||||
timeout.tv_sec = 5*60; /* five minutes */
|
||||
timeout.tv_usec = 0;
|
||||
fsid.val[0] = 0;
|
||||
fsid.val[1] = 0;
|
||||
|
||||
for (fsp = get_fs_info(lstatfsp, do_mmap); ;
|
||||
reread_fs_info(fsp, do_mmap)) {
|
||||
/*
|
||||
* clean the filesystem, and, if it needed cleaning
|
||||
* (i.e. it returned nonzero) try it again
|
||||
* to make sure that some nasty process hasn't just
|
||||
* filled the disk system up.
|
||||
*/
|
||||
if (clean_loop(fsp))
|
||||
continue;
|
||||
|
||||
#ifdef VERBOSE
|
||||
(void)printf("Cleaner going to sleep.\n");
|
||||
#endif
|
||||
if (lfs_segwait(&fsid, &timeout) < 0)
|
||||
err(0, "lfs_segwait: returned error\n");
|
||||
#ifdef VERBOSE
|
||||
(void)printf("Cleaner waking up.\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* return the number of segments cleaned */
|
||||
int
|
||||
clean_loop(fsp)
|
||||
FS_INFO *fsp; /* file system information */
|
||||
{
|
||||
double loadavg[MAXLOADS];
|
||||
time_t now;
|
||||
u_long max_free_segs;
|
||||
|
||||
/*
|
||||
* Compute the maximum possible number of free segments, given the
|
||||
* number of free blocks.
|
||||
*/
|
||||
max_free_segs = fsp->fi_statfsp->f_bfree / fsp->fi_lfs.lfs_ssize;
|
||||
|
||||
/*
|
||||
* We will clean if there are not enough free blocks or total clean
|
||||
* space is less than BUSY_LIM % of possible clean space.
|
||||
*/
|
||||
now = time((time_t *)NULL);
|
||||
if (fsp->fi_cip->clean < max_free_segs &&
|
||||
(fsp->fi_cip->clean <= MIN_SEGS(&fsp->fi_lfs) ||
|
||||
fsp->fi_cip->clean < max_free_segs * BUSY_LIM)) {
|
||||
printf("Cleaner Running at %s (%d of %d segments available)\n",
|
||||
ctime(&now), fsp->fi_cip->clean, max_free_segs);
|
||||
clean_fs(fsp, cost_benefit);
|
||||
return (1);
|
||||
} else {
|
||||
/*
|
||||
* We will also clean if the system is reasonably idle and
|
||||
* the total clean space is less then IDLE_LIM % of possible
|
||||
* clean space.
|
||||
*/
|
||||
if (getloadavg(loadavg, MAXLOADS) == -1) {
|
||||
perror("getloadavg: failed\n");
|
||||
return (-1);
|
||||
}
|
||||
if (loadavg[ONE_MIN] == 0.0 && loadavg[FIVE_MIN] &&
|
||||
fsp->fi_cip->clean < max_free_segs * IDLE_LIM) {
|
||||
clean_fs(fsp, cost_benefit);
|
||||
printf("Cleaner Running at %s (system idle)\n",
|
||||
ctime(&now));
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
printf("Cleaner Not Running at %s\n", ctime(&now));
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
clean_fs(fsp, cost_func)
|
||||
FS_INFO *fsp; /* file system information */
|
||||
int (*cost_func) __P((FS_INFO *, SEGUSE *));
|
||||
{
|
||||
struct seglist *segs, *sp;
|
||||
int i;
|
||||
|
||||
if ((segs =
|
||||
malloc(fsp->fi_lfs.lfs_nseg * sizeof(struct seglist))) == NULL) {
|
||||
err(0, "malloc failed");
|
||||
return;
|
||||
}
|
||||
i = choose_segments(fsp, segs, cost_func);
|
||||
#ifdef VERBOSE
|
||||
printf("clean_fs: found %d segments to clean in file system %s\n",
|
||||
i, fsp->fi_statfsp->f_mntonname);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
if (i)
|
||||
for (i = MIN(i, NUM_TO_CLEAN(fsp)), sp = segs; i-- ; ++sp) {
|
||||
if (clean_segment(fsp, sp->sl_id) < 0)
|
||||
perror("clean_segment failed");
|
||||
else if (lfs_segclean(&fsp->fi_statfsp->f_fsid,
|
||||
sp->sl_id) < 0)
|
||||
perror("lfs_segclean failed");
|
||||
printf("Completed cleaning segment %d\n", sp->sl_id);
|
||||
}
|
||||
free(segs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Segment with the highest priority get sorted to the beginning of the
|
||||
* list. This sort assumes that empty segments always have a higher
|
||||
* cost/benefit than any utilized segment.
|
||||
*/
|
||||
int
|
||||
cost_compare(a, b)
|
||||
const void *a;
|
||||
const void *b;
|
||||
{
|
||||
return (((struct seglist *)b)->sl_cost -
|
||||
((struct seglist *)a)->sl_cost);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Returns the number of segments to be cleaned with the elements of seglist
|
||||
* filled in.
|
||||
*/
|
||||
int
|
||||
choose_segments(fsp, seglist, cost_func)
|
||||
FS_INFO *fsp;
|
||||
struct seglist *seglist;
|
||||
int (*cost_func) __P((FS_INFO *, SEGUSE *));
|
||||
{
|
||||
struct lfs *lfsp;
|
||||
struct seglist *sp;
|
||||
SEGUSE *sup;
|
||||
int i, nsegs;
|
||||
|
||||
lfsp = &fsp->fi_lfs;
|
||||
|
||||
#ifdef VERBOSE
|
||||
(void)printf("Entering choose_segments\n");
|
||||
#endif
|
||||
dump_super(lfsp);
|
||||
dump_cleaner_info(fsp->fi_cip);
|
||||
|
||||
for (sp = seglist, i = 0; i < lfsp->lfs_nseg; ++i) {
|
||||
sup = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, i);
|
||||
PRINT_SEGUSE(sup, i);
|
||||
if (!(sup->su_flags & SEGUSE_DIRTY) ||
|
||||
sup->su_flags & SEGUSE_ACTIVE)
|
||||
continue;
|
||||
#ifdef VERBOSE
|
||||
(void)printf("\tchoosing segment %d\n", i);
|
||||
#endif
|
||||
sp->sl_cost = (*cost_func)(fsp, sup);
|
||||
sp->sl_id = i;
|
||||
sp->sl_empty = sup->su_nbytes ? 0 : 1;
|
||||
++sp;
|
||||
}
|
||||
nsegs = sp - seglist;
|
||||
qsort(seglist, nsegs, sizeof(struct seglist), cost_compare);
|
||||
#ifdef VERBOSE
|
||||
(void)printf("Returning %d segments\n", nsegs);
|
||||
#endif
|
||||
return (nsegs);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
clean_segment(fsp, id)
|
||||
FS_INFO *fsp; /* file system information */
|
||||
int id; /* segment number */
|
||||
{
|
||||
BLOCK_INFO *block_array, *bp;
|
||||
SEGUSE *sp;
|
||||
struct lfs *lfsp;
|
||||
struct tossstruct t;
|
||||
caddr_t seg_buf;
|
||||
int num_blocks, maxblocks, clean_blocks;
|
||||
|
||||
lfsp = &fsp->fi_lfs;
|
||||
sp = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, id);
|
||||
|
||||
#ifdef VERBOSE
|
||||
(void)printf("cleaning segment %d: contains %lu bytes\n", id,
|
||||
sp->su_nbytes);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
/* XXX could add debugging to verify that segment is really empty */
|
||||
if (sp->su_nbytes == sp->su_nsums * LFS_SUMMARY_SIZE) {
|
||||
++cleaner_stats.segs_empty;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* map the segment into a buffer */
|
||||
if (mmap_segment(fsp, id, &seg_buf, do_mmap) < 0) {
|
||||
err(0, "mmap_segment failed");
|
||||
++cleaner_stats.segs_error;
|
||||
return (-1);
|
||||
}
|
||||
/* get a list of blocks that are contained by the segment */
|
||||
if (lfs_segmapv(fsp, id, seg_buf, &block_array, &num_blocks) < 0) {
|
||||
err(0, "clean_segment: lfs_segmapv failed");
|
||||
++cleaner_stats.segs_error;
|
||||
return (-1);
|
||||
}
|
||||
cleaner_stats.blocks_read += fsp->fi_lfs.lfs_ssize;
|
||||
|
||||
#ifdef VERBOSE
|
||||
(void)printf("lfs_segmapv returned %d blocks\n", num_blocks);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
/* get the current disk address of blocks contained by the segment */
|
||||
if (lfs_bmapv(&fsp->fi_statfsp->f_fsid, block_array, num_blocks) < 0) {
|
||||
perror("clean_segment: lfs_bmapv failed\n");
|
||||
++cleaner_stats.segs_error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now toss any blocks not in the current segment */
|
||||
t.lfs = lfsp;
|
||||
t.seg = id;
|
||||
toss(block_array, &num_blocks, sizeof(BLOCK_INFO), bi_tossold, &t);
|
||||
|
||||
/* Check if last element should be tossed */
|
||||
if (num_blocks && bi_tossold(&t, block_array + num_blocks - 1, NULL))
|
||||
--num_blocks;
|
||||
|
||||
#ifdef VERBOSE
|
||||
{
|
||||
BLOCK_INFO *_bip;
|
||||
u_long *lp;
|
||||
int i;
|
||||
|
||||
(void)printf("after bmapv still have %d blocks\n", num_blocks);
|
||||
fflush(stdout);
|
||||
if (num_blocks)
|
||||
printf("BLOCK INFOS\n");
|
||||
for (_bip = block_array, i=0; i < num_blocks; ++_bip, ++i) {
|
||||
PRINT_BINFO(_bip);
|
||||
lp = (u_long *)_bip->bi_bp;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
cleaner_stats.blocks_written += num_blocks;
|
||||
if (do_small)
|
||||
maxblocks = MAXPHYS / fsp->fi_lfs.lfs_bsize - 1;
|
||||
else
|
||||
maxblocks = num_blocks;
|
||||
|
||||
for (bp = block_array; num_blocks > 0; bp += clean_blocks) {
|
||||
clean_blocks = maxblocks < num_blocks ? maxblocks : num_blocks;
|
||||
if (lfs_markv(&fsp->fi_statfsp->f_fsid,
|
||||
bp, clean_blocks) < 0) {
|
||||
err(0, "clean_segment: lfs_markv failed");
|
||||
++cleaner_stats.segs_error;
|
||||
return (-1);
|
||||
}
|
||||
num_blocks -= clean_blocks;
|
||||
}
|
||||
|
||||
free(block_array);
|
||||
munmap_segment(fsp, seg_buf, do_mmap);
|
||||
++cleaner_stats.segs_cleaned;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bi_tossold(client, a, b)
|
||||
const void *client;
|
||||
const void *a;
|
||||
const void *b;
|
||||
{
|
||||
const struct tossstruct *t;
|
||||
|
||||
t = (struct tossstruct *)client;
|
||||
|
||||
return (((BLOCK_INFO *)a)->bi_daddr == LFS_UNUSED_DADDR ||
|
||||
datosn(t->lfs, ((BLOCK_INFO *)a)->bi_daddr) != t->seg);
|
||||
}
|
||||
|
||||
void
|
||||
sig_report(sig)
|
||||
int sig;
|
||||
{
|
||||
printf("lfs_cleanerd:\t%s%d\n\t\t%s%d\n\t\t%s%d\n\t\t%s%d\n\t\t%s%d\n",
|
||||
"blocks_read ", cleaner_stats.blocks_read,
|
||||
"blocks_written ", cleaner_stats.blocks_written,
|
||||
"segs_cleaned ", cleaner_stats.segs_cleaned,
|
||||
"segs_empty ", cleaner_stats.segs_empty,
|
||||
"seg_error ", cleaner_stats.segs_error);
|
||||
if (sig == SIGUSR2) {
|
||||
cleaner_stats.blocks_read = 0;
|
||||
cleaner_stats.blocks_written = 0;
|
||||
cleaner_stats.segs_cleaned = 0;
|
||||
cleaner_stats.segs_empty = 0;
|
||||
cleaner_stats.segs_error = 0;
|
||||
}
|
||||
if (sig == SIGINT)
|
||||
exit(0);
|
||||
}
|
||||
77
libexec/lfs_cleanerd/lfs_cleanerd.8
Normal file
77
libexec/lfs_cleanerd/lfs_cleanerd.8
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
.\" Copyright (c) 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)lfs_cleanerd.8 8.2 (Berkeley) 12/11/93
|
||||
.\"
|
||||
.Dd "December 11, 1993"
|
||||
.Dt LFS_CLEANERD 8
|
||||
.Os BSD 4.4
|
||||
.Sh NAME
|
||||
.Nm lfs_cleanerd
|
||||
.Nd garbage collect a log-structured file system
|
||||
.Sh SYNOPSIS
|
||||
.Nm lfs_cleanerd
|
||||
.Op Fl ds
|
||||
.Pa node
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm lfs_cleanerd
|
||||
command starts a daemon process which garbage-collects
|
||||
the log-structured file system residing at the point named by
|
||||
.Ar node
|
||||
in the global file system namespace.
|
||||
This command is normally executed by
|
||||
.Xr mount_lfs 8
|
||||
when the log-structured file system is mounted.
|
||||
The daemon will exit within a few minutes
|
||||
of when the file system it was cleaning is unmounted.
|
||||
.Pp
|
||||
Garbage collection on a log-structured file system is done by scanning
|
||||
the file system's segments for active, i.e. referenced, data and copying
|
||||
it to new segments.
|
||||
When all of the active data in a given segment has been copied to a new
|
||||
segment that segment can be marked as empty, thus reclaiming the space
|
||||
taken by the inactive data which was in it.
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl d
|
||||
Run in debug mode.
|
||||
Do not become a daemon process, and print debugging information.
|
||||
.It Fl s
|
||||
When cleaning the file system, read data in small chunks.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr mount_lfs 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm lfs_cleanerd
|
||||
utility first appeared in 4.4BSD.
|
||||
671
libexec/lfs_cleanerd/library.c
Normal file
671
libexec/lfs_cleanerd/library.c
Normal file
|
|
@ -0,0 +1,671 @@
|
|||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)library.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <ufs/ufs/dinode.h>
|
||||
#include <ufs/lfs/lfs.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "clean.h"
|
||||
|
||||
void add_blocks __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t,
|
||||
daddr_t, daddr_t));
|
||||
void add_inodes __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t,
|
||||
daddr_t));
|
||||
int bi_compare __P((const void *, const void *));
|
||||
int bi_toss __P((const void *, const void *, const void *));
|
||||
void get_ifile __P((FS_INFO *, int));
|
||||
int get_superblock __P((FS_INFO *, struct lfs *));
|
||||
int pseg_valid __P((FS_INFO *, SEGSUM *));
|
||||
|
||||
/*
|
||||
* This function will get information on a a filesystem which matches
|
||||
* the name and type given. If a "name" is in a filesystem of the given
|
||||
* type, then buf is filled with that filesystem's info, and the
|
||||
* a non-zero value is returned.
|
||||
*/
|
||||
int
|
||||
fs_getmntinfo(buf, name, type)
|
||||
struct statfs **buf;
|
||||
char *name;
|
||||
int type;
|
||||
{
|
||||
/* allocate space for the filesystem info */
|
||||
*buf = (struct statfs *)malloc(sizeof(struct statfs));
|
||||
if (*buf == NULL)
|
||||
return 0;
|
||||
|
||||
/* grab the filesystem info */
|
||||
if (statfs(name, *buf) < 0) {
|
||||
free(*buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check to see if it's the one we want */
|
||||
if (((*buf)->f_type != type) ||
|
||||
strncmp(name, (*buf)->f_mntonname, MNAMELEN)) {
|
||||
/* "this is not the filesystem you're looking for */
|
||||
free(*buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get all the information available on an LFS file system.
|
||||
* Returns an pointer to an FS_INFO structure, NULL on error.
|
||||
*/
|
||||
FS_INFO *
|
||||
get_fs_info (lstatfsp, use_mmap)
|
||||
struct statfs *lstatfsp; /* IN: pointer to statfs struct */
|
||||
int use_mmap; /* IN: mmap or read */
|
||||
{
|
||||
FS_INFO *fsp;
|
||||
int i;
|
||||
|
||||
fsp = (FS_INFO *)malloc(sizeof(FS_INFO));
|
||||
if (fsp == NULL)
|
||||
return NULL;
|
||||
bzero(fsp, sizeof(FS_INFO));
|
||||
|
||||
fsp->fi_statfsp = lstatfsp;
|
||||
if (get_superblock (fsp, &fsp->fi_lfs))
|
||||
err(1, "get_fs_info: get_superblock failed");
|
||||
fsp->fi_daddr_shift =
|
||||
fsp->fi_lfs.lfs_bshift - fsp->fi_lfs.lfs_fsbtodb;
|
||||
get_ifile (fsp, use_mmap);
|
||||
return (fsp);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are reading the ifile then we need to refresh it. Even if
|
||||
* we are mmapping it, it might have grown. Finally, we need to
|
||||
* refresh the file system information (statfs) info.
|
||||
*/
|
||||
void
|
||||
reread_fs_info(fsp, use_mmap)
|
||||
FS_INFO *fsp; /* IN: prointer fs_infos to reread */
|
||||
int use_mmap;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp))
|
||||
err(1, "reread_fs_info: statfs failed");
|
||||
get_ifile (fsp, use_mmap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the superblock from disk (possibly in face of errors)
|
||||
*/
|
||||
int
|
||||
get_superblock (fsp, sbp)
|
||||
FS_INFO *fsp; /* local file system info structure */
|
||||
struct lfs *sbp;
|
||||
{
|
||||
char mntfromname[MNAMELEN+1];
|
||||
int fid;
|
||||
|
||||
strcpy(mntfromname, "/dev/r");
|
||||
strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5);
|
||||
|
||||
if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
|
||||
err(0, "get_superblock: bad open");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
get(fid, LFS_LABELPAD, sbp, sizeof(struct lfs));
|
||||
close (fid);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will map the ifile into memory. It causes a
|
||||
* fatal error on failure.
|
||||
*/
|
||||
void
|
||||
get_ifile (fsp, use_mmap)
|
||||
FS_INFO *fsp;
|
||||
int use_mmap;
|
||||
|
||||
{
|
||||
struct stat file_stat;
|
||||
caddr_t ifp;
|
||||
char *ifile_name;
|
||||
int count, fid;
|
||||
|
||||
ifp = NULL;
|
||||
ifile_name = malloc(strlen(fsp->fi_statfsp->f_mntonname) +
|
||||
strlen(IFILE_NAME)+2);
|
||||
strcat(strcat(strcpy(ifile_name, fsp->fi_statfsp->f_mntonname), "/"),
|
||||
IFILE_NAME);
|
||||
|
||||
if ((fid = open(ifile_name, O_RDWR, (mode_t)0)) < 0)
|
||||
err(1, "get_ifile: bad open");
|
||||
|
||||
if (fstat (fid, &file_stat))
|
||||
err(1, "get_ifile: fstat failed");
|
||||
|
||||
if (use_mmap && file_stat.st_size == fsp->fi_ifile_length) {
|
||||
(void) close(fid);
|
||||
return;
|
||||
}
|
||||
|
||||
/* get the ifile */
|
||||
if (use_mmap) {
|
||||
if (fsp->fi_cip)
|
||||
munmap((caddr_t)fsp->fi_cip, fsp->fi_ifile_length);
|
||||
ifp = mmap ((caddr_t)0, file_stat.st_size,
|
||||
PROT_READ|PROT_WRITE, 0, fid, (off_t)0);
|
||||
if (ifp == (caddr_t)(-1))
|
||||
err(1, "get_ifile: mmap failed");
|
||||
} else {
|
||||
if (fsp->fi_cip)
|
||||
free(fsp->fi_cip);
|
||||
if (!(ifp = malloc (file_stat.st_size)))
|
||||
err (1, "get_ifile: malloc failed");
|
||||
redo_read:
|
||||
count = read (fid, ifp, (size_t) file_stat.st_size);
|
||||
|
||||
if (count < 0)
|
||||
err(1, "get_ifile: bad ifile read");
|
||||
else if (count < file_stat.st_size) {
|
||||
err(0, "get_ifile");
|
||||
if (lseek(fid, 0, SEEK_SET) < 0)
|
||||
err(1, "get_ifile: bad ifile lseek");
|
||||
goto redo_read;
|
||||
}
|
||||
}
|
||||
fsp->fi_ifile_length = file_stat.st_size;
|
||||
close (fid);
|
||||
|
||||
fsp->fi_cip = (CLEANERINFO *)ifp;
|
||||
fsp->fi_segusep = (SEGUSE *)(ifp + CLEANSIZE(fsp));
|
||||
fsp->fi_ifilep = (IFILE *)((caddr_t)fsp->fi_segusep + SEGTABSIZE(fsp));
|
||||
|
||||
/*
|
||||
* The number of ifile entries is equal to the number of blocks
|
||||
* blocks in the ifile minus the ones allocated to cleaner info
|
||||
* and segment usage table multiplied by the number of ifile
|
||||
* entries per page.
|
||||
*/
|
||||
fsp->fi_ifile_count = (fsp->fi_ifile_length >> fsp->fi_lfs.lfs_bshift -
|
||||
fsp->fi_lfs.lfs_cleansz - fsp->fi_lfs.lfs_segtabsz) *
|
||||
fsp->fi_lfs.lfs_ifpb;
|
||||
|
||||
free (ifile_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will scan a segment and return a list of
|
||||
* <inode, blocknum> pairs which indicate which blocks were
|
||||
* contained as live data within the segment when the segment
|
||||
* summary was read (it may have "died" since then). Any given
|
||||
* pair will be listed at most once.
|
||||
*/
|
||||
int
|
||||
lfs_segmapv(fsp, seg, seg_buf, blocks, bcount)
|
||||
FS_INFO *fsp; /* pointer to local file system information */
|
||||
int seg; /* the segment number */
|
||||
caddr_t seg_buf; /* the buffer containing the segment's data */
|
||||
BLOCK_INFO **blocks; /* OUT: array of block_info for live blocks */
|
||||
int *bcount; /* OUT: number of active blocks in segment */
|
||||
{
|
||||
BLOCK_INFO *bip;
|
||||
SEGSUM *sp;
|
||||
SEGUSE *sup;
|
||||
FINFO *fip;
|
||||
struct lfs *lfsp;
|
||||
caddr_t s, segend;
|
||||
daddr_t pseg_addr, seg_addr;
|
||||
int i, nelem, nblocks, sumsize;
|
||||
time_t timestamp;
|
||||
|
||||
lfsp = &fsp->fi_lfs;
|
||||
nelem = 2 * lfsp->lfs_ssize;
|
||||
if (!(bip = malloc(nelem * sizeof(BLOCK_INFO))))
|
||||
goto err0;
|
||||
|
||||
sup = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, seg);
|
||||
s = seg_buf + (sup->su_flags & SEGUSE_SUPERBLOCK ? LFS_SBPAD : 0);
|
||||
seg_addr = sntoda(lfsp, seg);
|
||||
pseg_addr = seg_addr + (sup->su_flags & SEGUSE_SUPERBLOCK ? btodb(LFS_SBPAD) : 0);
|
||||
#ifdef VERBOSE
|
||||
printf("\tsegment buffer at: 0x%x\tseg_addr 0x%x\n", s, seg_addr);
|
||||
#endif /* VERBOSE */
|
||||
|
||||
*bcount = 0;
|
||||
for (segend = seg_buf + seg_size(lfsp), timestamp = 0; s < segend; ) {
|
||||
sp = (SEGSUM *)s;
|
||||
|
||||
#ifdef VERBOSE
|
||||
printf("\tpartial at: 0x%x\n", pseg_addr);
|
||||
print_SEGSUM(lfsp, sp);
|
||||
fflush(stdout);
|
||||
#endif /* VERBOSE */
|
||||
|
||||
nblocks = pseg_valid(fsp, sp);
|
||||
if (nblocks <= 0)
|
||||
break;
|
||||
|
||||
/* Check if we have hit old data */
|
||||
if (timestamp > ((SEGSUM*)s)->ss_create)
|
||||
break;
|
||||
timestamp = ((SEGSUM*)s)->ss_create;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
/* Verfiy size of summary block */
|
||||
sumsize = sizeof(SEGSUM) +
|
||||
(sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp);
|
||||
for (fip = (FINFO *)(sp + 1); i < sp->ss_nfinfo; ++i) {
|
||||
sumsize += sizeof(FINFO) +
|
||||
(fip->fi_nblocks - 1) * sizeof(daddr_t);
|
||||
fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks]);
|
||||
}
|
||||
if (sumsize > LFS_SUMMARY_SIZE) {
|
||||
fprintf(stderr,
|
||||
"Segment %d summary block too big: %d\n",
|
||||
seg, sumsize);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (*bcount + nblocks + sp->ss_ninos > nelem) {
|
||||
nelem = *bcount + nblocks + sp->ss_ninos;
|
||||
bip = realloc (bip, nelem * sizeof(BLOCK_INFO));
|
||||
if (!bip)
|
||||
goto err0;
|
||||
}
|
||||
add_blocks(fsp, bip, bcount, sp, seg_buf, seg_addr, pseg_addr);
|
||||
add_inodes(fsp, bip, bcount, sp, seg_buf, seg_addr);
|
||||
pseg_addr += fsbtodb(lfsp, nblocks) +
|
||||
bytetoda(fsp, LFS_SUMMARY_SIZE);
|
||||
s += (nblocks << lfsp->lfs_bshift) + LFS_SUMMARY_SIZE;
|
||||
}
|
||||
qsort(bip, *bcount, sizeof(BLOCK_INFO), bi_compare);
|
||||
toss(bip, bcount, sizeof(BLOCK_INFO), bi_toss, NULL);
|
||||
#ifdef VERBOSE
|
||||
{
|
||||
BLOCK_INFO *_bip;
|
||||
int i;
|
||||
|
||||
printf("BLOCK INFOS\n");
|
||||
for (_bip = bip, i=0; i < *bcount; ++_bip, ++i)
|
||||
PRINT_BINFO(_bip);
|
||||
}
|
||||
#endif
|
||||
*blocks = bip;
|
||||
return (0);
|
||||
|
||||
err0: *bcount = 0;
|
||||
return (-1);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* This will parse a partial segment and fill in BLOCK_INFO structures
|
||||
* for each block described in the segment summary. It will not include
|
||||
* blocks or inodes from files with new version numbers.
|
||||
*/
|
||||
void
|
||||
add_blocks (fsp, bip, countp, sp, seg_buf, segaddr, psegaddr)
|
||||
FS_INFO *fsp; /* pointer to super block */
|
||||
BLOCK_INFO *bip; /* Block info array */
|
||||
int *countp; /* IN/OUT: number of blocks in array */
|
||||
SEGSUM *sp; /* segment summmary pointer */
|
||||
caddr_t seg_buf; /* buffer containing segment */
|
||||
daddr_t segaddr; /* address of this segment */
|
||||
daddr_t psegaddr; /* address of this partial segment */
|
||||
{
|
||||
IFILE *ifp;
|
||||
FINFO *fip;
|
||||
caddr_t bp;
|
||||
daddr_t *dp, *iaddrp;
|
||||
int db_per_block, i, j;
|
||||
u_long page_size;
|
||||
|
||||
#ifdef VERBOSE
|
||||
printf("FILE INFOS\n");
|
||||
#endif
|
||||
db_per_block = fsbtodb(&fsp->fi_lfs, 1);
|
||||
page_size = fsp->fi_lfs.lfs_bsize;
|
||||
bp = seg_buf + datobyte(fsp, psegaddr - segaddr) + LFS_SUMMARY_SIZE;
|
||||
bip += *countp;
|
||||
psegaddr += bytetoda(fsp, LFS_SUMMARY_SIZE);
|
||||
iaddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE);
|
||||
--iaddrp;
|
||||
for (fip = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo;
|
||||
++i, fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks])) {
|
||||
|
||||
ifp = IFILE_ENTRY(&fsp->fi_lfs, fsp->fi_ifilep, fip->fi_ino);
|
||||
PRINT_FINFO(fip, ifp);
|
||||
if (ifp->if_version > fip->fi_version)
|
||||
continue;
|
||||
dp = &(fip->fi_blocks[0]);
|
||||
for (j = 0; j < fip->fi_nblocks; j++, dp++) {
|
||||
while (psegaddr == *iaddrp) {
|
||||
psegaddr += db_per_block;
|
||||
bp += page_size;
|
||||
--iaddrp;
|
||||
}
|
||||
bip->bi_inode = fip->fi_ino;
|
||||
bip->bi_lbn = *dp;
|
||||
bip->bi_daddr = psegaddr;
|
||||
bip->bi_segcreate = (time_t)(sp->ss_create);
|
||||
bip->bi_bp = bp;
|
||||
bip->bi_version = ifp->if_version;
|
||||
psegaddr += db_per_block;
|
||||
bp += page_size;
|
||||
++bip;
|
||||
++(*countp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For a particular segment summary, reads the inode blocks and adds
|
||||
* INODE_INFO structures to the array. Returns the number of inodes
|
||||
* actually added.
|
||||
*/
|
||||
void
|
||||
add_inodes (fsp, bip, countp, sp, seg_buf, seg_addr)
|
||||
FS_INFO *fsp; /* pointer to super block */
|
||||
BLOCK_INFO *bip; /* block info array */
|
||||
int *countp; /* pointer to current number of inodes */
|
||||
SEGSUM *sp; /* segsum pointer */
|
||||
caddr_t seg_buf; /* the buffer containing the segment's data */
|
||||
daddr_t seg_addr; /* disk address of seg_buf */
|
||||
{
|
||||
struct dinode *di;
|
||||
struct lfs *lfsp;
|
||||
IFILE *ifp;
|
||||
BLOCK_INFO *bp;
|
||||
daddr_t *daddrp;
|
||||
ino_t inum;
|
||||
int i;
|
||||
|
||||
if (sp->ss_ninos <= 0)
|
||||
return;
|
||||
|
||||
bp = bip + *countp;
|
||||
lfsp = &fsp->fi_lfs;
|
||||
#ifdef VERBOSE
|
||||
(void) printf("INODES:\n");
|
||||
#endif
|
||||
daddrp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE);
|
||||
for (i = 0; i < sp->ss_ninos; ++i) {
|
||||
if (i % INOPB(lfsp) == 0) {
|
||||
--daddrp;
|
||||
di = (struct dinode *)(seg_buf +
|
||||
((*daddrp - seg_addr) << fsp->fi_daddr_shift));
|
||||
} else
|
||||
++di;
|
||||
|
||||
inum = di->di_inumber;
|
||||
bp->bi_lbn = LFS_UNUSED_LBN;
|
||||
bp->bi_inode = inum;
|
||||
bp->bi_daddr = *daddrp;
|
||||
bp->bi_bp = di;
|
||||
bp->bi_segcreate = sp->ss_create;
|
||||
|
||||
if (inum == LFS_IFILE_INUM) {
|
||||
bp->bi_version = 1; /* Ifile version should be 1 */
|
||||
bp++;
|
||||
++(*countp);
|
||||
PRINT_INODE(1, bp);
|
||||
} else {
|
||||
ifp = IFILE_ENTRY(lfsp, fsp->fi_ifilep, inum);
|
||||
PRINT_INODE(ifp->if_daddr == *daddrp, bp);
|
||||
bp->bi_version = ifp->if_version;
|
||||
if (ifp->if_daddr == *daddrp) {
|
||||
bp++;
|
||||
++(*countp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks the summary checksum and the data checksum to determine if the
|
||||
* segment is valid or not. Returns the size of the partial segment if it
|
||||
* is valid, * and 0 otherwise. Use dump_summary to figure out size of the
|
||||
* the partial as well as whether or not the checksum is valid.
|
||||
*/
|
||||
int
|
||||
pseg_valid (fsp, ssp)
|
||||
FS_INFO *fsp; /* pointer to file system info */
|
||||
SEGSUM *ssp; /* pointer to segment summary block */
|
||||
{
|
||||
caddr_t p;
|
||||
int i, nblocks;
|
||||
u_long *datap;
|
||||
|
||||
if ((nblocks = dump_summary(&fsp->fi_lfs, ssp, 0, NULL)) <= 0 ||
|
||||
nblocks > fsp->fi_lfs.lfs_ssize - 1)
|
||||
return(0);
|
||||
|
||||
/* check data/inode block(s) checksum too */
|
||||
datap = (u_long *)malloc(nblocks * sizeof(u_long));
|
||||
p = (caddr_t)ssp + LFS_SUMMARY_SIZE;
|
||||
for (i = 0; i < nblocks; ++i) {
|
||||
datap[i] = *((u_long *)p);
|
||||
p += fsp->fi_lfs.lfs_bsize;
|
||||
}
|
||||
if (cksum ((void *)datap, nblocks * sizeof(u_long)) != ssp->ss_datasum)
|
||||
return (0);
|
||||
|
||||
return (nblocks);
|
||||
}
|
||||
|
||||
|
||||
/* #define MMAP_SEGMENT */
|
||||
/*
|
||||
* read a segment into a memory buffer
|
||||
*/
|
||||
int
|
||||
mmap_segment (fsp, segment, segbuf, use_mmap)
|
||||
FS_INFO *fsp; /* file system information */
|
||||
int segment; /* segment number */
|
||||
caddr_t *segbuf; /* pointer to buffer area */
|
||||
int use_mmap; /* mmap instead of read */
|
||||
{
|
||||
struct lfs *lfsp;
|
||||
int fid; /* fildes for file system device */
|
||||
daddr_t seg_daddr; /* base disk address of segment */
|
||||
off_t seg_byte;
|
||||
size_t ssize;
|
||||
char mntfromname[MNAMELEN+2];
|
||||
|
||||
lfsp = &fsp->fi_lfs;
|
||||
|
||||
/* get the disk address of the beginning of the segment */
|
||||
seg_daddr = sntoda(lfsp, segment);
|
||||
seg_byte = datobyte(fsp, seg_daddr);
|
||||
ssize = seg_size(lfsp);
|
||||
|
||||
strcpy(mntfromname, "/dev/r");
|
||||
strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5);
|
||||
|
||||
if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {
|
||||
err(0, "mmap_segment: bad open");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (use_mmap) {
|
||||
*segbuf = mmap ((caddr_t)0, seg_size(lfsp), PROT_READ,
|
||||
0, fid, seg_byte);
|
||||
if (*(long *)segbuf < 0) {
|
||||
err(0, "mmap_segment: mmap failed");
|
||||
return (NULL);
|
||||
}
|
||||
} else {
|
||||
#ifdef VERBOSE
|
||||
printf("mmap_segment\tseg_daddr: %lu\tseg_size: %lu\tseg_offset: %qu\n",
|
||||
seg_daddr, ssize, seg_byte);
|
||||
#endif
|
||||
/* malloc the space for the buffer */
|
||||
*segbuf = malloc(ssize);
|
||||
if (!*segbuf) {
|
||||
err(0, "mmap_segment: malloc failed");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* read the segment data into the buffer */
|
||||
if (lseek (fid, seg_byte, SEEK_SET) != seg_byte) {
|
||||
err (0, "mmap_segment: bad lseek");
|
||||
free(*segbuf);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (read (fid, *segbuf, ssize) != ssize) {
|
||||
err (0, "mmap_segment: bad read");
|
||||
free(*segbuf);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
close (fid);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
munmap_segment (fsp, seg_buf, use_mmap)
|
||||
FS_INFO *fsp; /* file system information */
|
||||
caddr_t seg_buf; /* pointer to buffer area */
|
||||
int use_mmap; /* mmap instead of read/write */
|
||||
{
|
||||
if (use_mmap)
|
||||
munmap (seg_buf, seg_size(&fsp->fi_lfs));
|
||||
else
|
||||
free (seg_buf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* USEFUL DEBUGGING TOOLS:
|
||||
*/
|
||||
void
|
||||
print_SEGSUM (lfsp, p)
|
||||
struct lfs *lfsp;
|
||||
SEGSUM *p;
|
||||
{
|
||||
if (p)
|
||||
(void) dump_summary(lfsp, p, DUMP_ALL, NULL);
|
||||
else printf("0x0");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
int
|
||||
bi_compare(a, b)
|
||||
const void *a;
|
||||
const void *b;
|
||||
{
|
||||
const BLOCK_INFO *ba, *bb;
|
||||
int diff;
|
||||
|
||||
ba = a;
|
||||
bb = b;
|
||||
|
||||
if (diff = (int)(ba->bi_inode - bb->bi_inode))
|
||||
return (diff);
|
||||
if (diff = (int)(ba->bi_lbn - bb->bi_lbn)) {
|
||||
if (ba->bi_lbn == LFS_UNUSED_LBN)
|
||||
return(-1);
|
||||
else if (bb->bi_lbn == LFS_UNUSED_LBN)
|
||||
return(1);
|
||||
else if (ba->bi_lbn < 0 && bb->bi_lbn >= 0)
|
||||
return(1);
|
||||
else if (bb->bi_lbn < 0 && ba->bi_lbn >= 0)
|
||||
return(-1);
|
||||
else
|
||||
return (diff);
|
||||
}
|
||||
if (diff = (int)(ba->bi_segcreate - bb->bi_segcreate))
|
||||
return (diff);
|
||||
diff = (int)(ba->bi_daddr - bb->bi_daddr);
|
||||
return (diff);
|
||||
}
|
||||
|
||||
int
|
||||
bi_toss(dummy, a, b)
|
||||
const void *dummy;
|
||||
const void *a;
|
||||
const void *b;
|
||||
{
|
||||
const BLOCK_INFO *ba, *bb;
|
||||
|
||||
ba = a;
|
||||
bb = b;
|
||||
|
||||
return(ba->bi_inode == bb->bi_inode && ba->bi_lbn == bb->bi_lbn);
|
||||
}
|
||||
|
||||
void
|
||||
toss(p, nump, size, dotoss, client)
|
||||
void *p;
|
||||
int *nump;
|
||||
size_t size;
|
||||
int (*dotoss) __P((const void *, const void *, const void *));
|
||||
void *client;
|
||||
{
|
||||
int i;
|
||||
void *p1;
|
||||
|
||||
if (*nump == 0)
|
||||
return;
|
||||
|
||||
for (i = *nump; --i > 0;) {
|
||||
p1 = p + size;
|
||||
if (dotoss(client, p, p1)) {
|
||||
memmove(p, p1, i * size);
|
||||
--(*nump);
|
||||
} else
|
||||
p += size;
|
||||
}
|
||||
}
|
||||
94
libexec/lfs_cleanerd/misc.c
Normal file
94
libexec/lfs_cleanerd/misc.c
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
extern char *special;
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
err(const int fatal, const char *fmt, ...)
|
||||
#else
|
||||
err(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
(void)fprintf(stderr, "%s: ", special);
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
if (errno)
|
||||
(void)fprintf(stderr, " %s", strerror(errno));
|
||||
(void)fprintf(stderr, "\n");
|
||||
if (fatal)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
get(fd, off, p, len)
|
||||
int fd;
|
||||
off_t off;
|
||||
void *p;
|
||||
size_t len;
|
||||
{
|
||||
int rbytes;
|
||||
|
||||
if (lseek(fd, off, SEEK_SET) < 0)
|
||||
err(1, "%s: %s", special, strerror(errno));
|
||||
if ((rbytes = read(fd, p, len)) < 0)
|
||||
err(1, "%s: %s", special, strerror(errno));
|
||||
if (rbytes != len)
|
||||
err(1, "%s: short read (%d, not %d)", special, rbytes, len);
|
||||
}
|
||||
218
libexec/lfs_cleanerd/print.c
Normal file
218
libexec/lfs_cleanerd/print.c
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)print.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ucred.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ufs/ufs/dinode.h>
|
||||
#include <ufs/lfs/lfs.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "clean.h"
|
||||
|
||||
/*
|
||||
* Print out a summary block; return number of blocks in segment; 0
|
||||
* for empty segment or corrupt segment.
|
||||
* Returns a pointer to the array of inode addresses.
|
||||
*/
|
||||
int
|
||||
dump_summary(lfsp, sp, flags, iaddrp)
|
||||
struct lfs *lfsp;
|
||||
SEGSUM *sp;
|
||||
u_long flags;
|
||||
daddr_t **iaddrp;
|
||||
{
|
||||
int i, j, numblocks;
|
||||
daddr_t *dp;
|
||||
|
||||
FINFO *fp;
|
||||
int ck;
|
||||
|
||||
if (sp->ss_sumsum != (ck = cksum(&sp->ss_datasum,
|
||||
LFS_SUMMARY_SIZE - sizeof(sp->ss_sumsum))))
|
||||
return(-1);
|
||||
|
||||
if (flags & DUMP_SUM_HEADER) {
|
||||
(void)printf(" %s0x%X\t%s%d\t%s%d\n %s0x%X\t%s0x%X",
|
||||
"next ", sp->ss_next,
|
||||
"nfinfo ", sp->ss_nfinfo,
|
||||
"ninos ", sp->ss_ninos,
|
||||
"sumsum ", sp->ss_sumsum,
|
||||
"datasum ", sp->ss_datasum );
|
||||
(void)printf("\tcreate %s", ctime((time_t *)&sp->ss_create));
|
||||
}
|
||||
|
||||
numblocks = (sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp);
|
||||
|
||||
/* Dump out inode disk addresses */
|
||||
if (flags & DUMP_INODE_ADDRS)
|
||||
printf(" Inode addresses:");
|
||||
|
||||
dp = (daddr_t *)((caddr_t)sp + LFS_SUMMARY_SIZE);
|
||||
for (--dp, i = 0; i < sp->ss_ninos; --dp)
|
||||
if (flags & DUMP_INODE_ADDRS) {
|
||||
(void)printf("\t0x%lx", *dp);
|
||||
if (++i % 7 == 0)
|
||||
(void)printf("\n");
|
||||
} else
|
||||
++i;
|
||||
if (iaddrp)
|
||||
*iaddrp = ++dp;
|
||||
if (flags & DUMP_INODE_ADDRS)
|
||||
printf("\n");
|
||||
|
||||
for (fp = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo; ++i) {
|
||||
numblocks += fp->fi_nblocks;
|
||||
if (flags & DUMP_FINFOS) {
|
||||
(void)printf(" %s%d version %d nblocks %d\n",
|
||||
"FINFO for inode: ", fp->fi_ino,
|
||||
fp->fi_version, fp->fi_nblocks);
|
||||
dp = &(fp->fi_blocks[0]);
|
||||
for (j = 0; j < fp->fi_nblocks; j++, dp++) {
|
||||
(void)printf("\t%d", *dp);
|
||||
if ((j % 8) == 7)
|
||||
(void)printf("\n");
|
||||
}
|
||||
if ((j % 8) != 0)
|
||||
(void)printf("\n");
|
||||
fp = (FINFO *)dp;
|
||||
} else {
|
||||
fp = (FINFO *)(&fp->fi_blocks[fp->fi_nblocks]);
|
||||
}
|
||||
}
|
||||
return (numblocks);
|
||||
}
|
||||
|
||||
#ifdef VERBOSE
|
||||
void
|
||||
dump_cleaner_info(ipage)
|
||||
void *ipage;
|
||||
{
|
||||
CLEANERINFO *cip;
|
||||
|
||||
cip = (CLEANERINFO *)ipage;
|
||||
(void)printf("segments clean\t%d\tsegments dirty\t%d\n\n",
|
||||
cip->clean, cip->dirty);
|
||||
}
|
||||
|
||||
void
|
||||
dump_super(lfsp)
|
||||
struct lfs *lfsp;
|
||||
{
|
||||
int i;
|
||||
|
||||
(void)printf("%s0x%X\t%s0x%X\t%s%d\t%s%d\n",
|
||||
"magic ", lfsp->lfs_magic,
|
||||
"version ", lfsp->lfs_version,
|
||||
"size ", lfsp->lfs_size,
|
||||
"ssize ", lfsp->lfs_ssize);
|
||||
(void)printf("%s%d\t\t%s%d\t%s%d\t%s%d\n",
|
||||
"dsize ", lfsp->lfs_dsize,
|
||||
"bsize ", lfsp->lfs_bsize,
|
||||
"fsize ", lfsp->lfs_fsize,
|
||||
"frag ", lfsp->lfs_frag);
|
||||
|
||||
(void)printf("%s%d\t\t%s%d\t%s%d\t%s%d\n",
|
||||
"minfree ", lfsp->lfs_minfree,
|
||||
"inopb ", lfsp->lfs_inopb,
|
||||
"ifpb ", lfsp->lfs_ifpb,
|
||||
"nindir ", lfsp->lfs_nindir);
|
||||
|
||||
(void)printf("%s%d\t\t%s%d\t%s%d\t%s%d\n",
|
||||
"nseg ", lfsp->lfs_nseg,
|
||||
"nspf ", lfsp->lfs_nspf,
|
||||
"cleansz ", lfsp->lfs_cleansz,
|
||||
"segtabsz ", lfsp->lfs_segtabsz);
|
||||
|
||||
(void)printf("%s0x%X\t%s%d\t%s0x%X\t%s%d\n",
|
||||
"segmask ", lfsp->lfs_segmask,
|
||||
"segshift ", lfsp->lfs_segshift,
|
||||
"bmask ", lfsp->lfs_bmask,
|
||||
"bshift ", lfsp->lfs_bshift);
|
||||
|
||||
(void)printf("%s0x%X\t\t%s%d\t%s0x%X\t%s%d\n",
|
||||
"ffmask ", lfsp->lfs_ffmask,
|
||||
"ffshift ", lfsp->lfs_ffshift,
|
||||
"fbmask ", lfsp->lfs_fbmask,
|
||||
"fbshift ", lfsp->lfs_fbshift);
|
||||
|
||||
(void)printf("%s%d\t\t%s0x%X\t%s0x%qx\n",
|
||||
"fsbtodb ", lfsp->lfs_fsbtodb,
|
||||
"cksum ", lfsp->lfs_cksum,
|
||||
"maxfilesize ", lfsp->lfs_maxfilesize);
|
||||
|
||||
(void)printf("Superblock disk addresses:\t");
|
||||
for (i = 0; i < LFS_MAXNUMSB; i++) {
|
||||
(void)printf(" 0x%X", lfsp->lfs_sboffs[i]);
|
||||
if ( i == (LFS_MAXNUMSB >> 1))
|
||||
(void)printf("\n\t\t\t\t");
|
||||
}
|
||||
(void)printf("\n");
|
||||
|
||||
(void)printf("Checkpoint Info\n");
|
||||
(void)printf("%s%d\t%s0x%X\t%s%d\n",
|
||||
"free ", lfsp->lfs_free,
|
||||
"idaddr ", lfsp->lfs_idaddr,
|
||||
"ifile ", lfsp->lfs_ifile);
|
||||
(void)printf("%s%d\t%s%d\t%s%d\n",
|
||||
"bfree ", lfsp->lfs_bfree,
|
||||
"avail ", lfsp->lfs_avail,
|
||||
"uinodes ", lfsp->lfs_uinodes);
|
||||
(void)printf("%s%d\t%s0x%X\t%s0x%X\n%s0x%X\t%s0x%X\t",
|
||||
"nfiles ", lfsp->lfs_nfiles,
|
||||
"lastseg ", lfsp->lfs_lastseg,
|
||||
"nextseg ", lfsp->lfs_nextseg,
|
||||
"curseg ", lfsp->lfs_curseg,
|
||||
"offset ", lfsp->lfs_offset);
|
||||
(void)printf("tstamp %s", ctime((time_t *)&lfsp->lfs_tstamp));
|
||||
(void)printf("\nIn-Memory Information\n");
|
||||
(void)printf("%s%d\t%s0x%X\t%s%d\t%s%d\t%s%d\n",
|
||||
"seglock ", lfsp->lfs_seglock,
|
||||
"iocount ", lfsp->lfs_iocount,
|
||||
"writer ", lfsp->lfs_writer,
|
||||
"dirops ", lfsp->lfs_dirops,
|
||||
"doifile ", lfsp->lfs_doifile );
|
||||
(void)printf("%s%d\t%s%d\t%s0x%X\t%s%d\n",
|
||||
"nactive ", lfsp->lfs_nactive,
|
||||
"fmod ", lfsp->lfs_fmod,
|
||||
"clean ", lfsp->lfs_clean,
|
||||
"ronly ", lfsp->lfs_ronly);
|
||||
}
|
||||
#endif /* VERBOSE */
|
||||
9
libexec/mail.local/Makefile
Normal file
9
libexec/mail.local/Makefile
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 7/19/93
|
||||
|
||||
PROG= mail.local
|
||||
MAN8= mail.local.0
|
||||
BINOWN= root
|
||||
BINMODE=4555
|
||||
INSTALLFLAGS=-fschg
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
105
libexec/mail.local/mail.local.8
Normal file
105
libexec/mail.local/mail.local.8
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)mail.local.8 8.2 (Berkeley) 12/11/93
|
||||
.\"
|
||||
.Dd December 11, 1993
|
||||
.Dt MAIL.LOCAL 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mail.local
|
||||
.Nd store mail in a mailbox
|
||||
.Sh SYNOPSIS
|
||||
.Nm mail.local
|
||||
.Op Fl f Ar from
|
||||
.Ar user ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm Mail.local
|
||||
reads the standard input up to an end-of-file and appends it to each
|
||||
.Ar user's
|
||||
.Pa mail
|
||||
file.
|
||||
The
|
||||
.Ar user
|
||||
must be a valid user name.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width xxxfrom
|
||||
.It Fl f Ar from
|
||||
Specify the sender's name.
|
||||
.El
|
||||
.Pp
|
||||
Individual mail messages in the mailbox are delimited by an empty
|
||||
line followed by a line beginning with the string ``From ''.
|
||||
A line containing the string ``From '', the sender's name and a time stamp
|
||||
is prepended to each delivered mail message.
|
||||
A blank line is appended to each message.
|
||||
A greater-than character (``>'') is prepended to any line in the message
|
||||
which could be mistaken for a ``From '' delimiter line.
|
||||
.Pp
|
||||
The mail files are exclusively locked with
|
||||
.Xr flock 2
|
||||
while mail is appended.
|
||||
.Pp
|
||||
If the ``biff'' service is returned by
|
||||
.Xr getservbyname 3 ,
|
||||
the biff server is notified of delivered mail.
|
||||
.Pp
|
||||
The
|
||||
.Nm mail.local
|
||||
utility exits 0 on success, and >0 if an error occurs.
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width indent
|
||||
.It Ev TZ
|
||||
Used to set the appropriate time zone on the timestamp.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /tmp/local.XXXXXX -compact
|
||||
.It Pa /tmp/local.XXXXXX
|
||||
temporary files
|
||||
.It Pa /var/mail/user
|
||||
user's mailbox directory
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr mail 1 ,
|
||||
.Xr xsend 1 ,
|
||||
.Xr flock 2 ,
|
||||
.Xr getservbyname 3 ,
|
||||
.Xr comsat 8 ,
|
||||
.Xr sendmail 8
|
||||
.Sh HISTORY
|
||||
A superset of
|
||||
.Nm mail.local
|
||||
(handling mailbox reading as well as mail delivery)
|
||||
appeared in
|
||||
.At v7 .
|
||||
as the program
|
||||
.Nm mail .
|
||||
511
libexec/mail.local/mail.local.c
Normal file
511
libexec/mail.local/mail.local.c
Normal file
|
|
@ -0,0 +1,511 @@
|
|||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1990, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)mail.local.c 8.6 (Berkeley) 4/8/94";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "pathnames.h"
|
||||
|
||||
int eval = EX_OK; /* sysexits.h error value. */
|
||||
|
||||
void deliver __P((int, char *));
|
||||
void e_to_sys __P((int));
|
||||
__dead void err __P((const char *, ...));
|
||||
void notifybiff __P((char *));
|
||||
int store __P((char *));
|
||||
void usage __P((void));
|
||||
void vwarn __P((const char *, _BSD_VA_LIST_));
|
||||
void warn __P((const char *, ...));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
struct passwd *pw;
|
||||
int ch, fd;
|
||||
uid_t uid;
|
||||
char *from;
|
||||
|
||||
openlog("mail.local", 0, LOG_MAIL);
|
||||
|
||||
from = NULL;
|
||||
while ((ch = getopt(argc, argv, "df:r:")) != EOF)
|
||||
switch(ch) {
|
||||
case 'd': /* Backward compatible. */
|
||||
break;
|
||||
case 'f':
|
||||
case 'r': /* Backward compatible. */
|
||||
if (from != NULL) {
|
||||
warn("multiple -f options");
|
||||
usage();
|
||||
}
|
||||
from = optarg;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (!*argv)
|
||||
usage();
|
||||
|
||||
/*
|
||||
* If from not specified, use the name from getlogin() if the
|
||||
* uid matches, otherwise, use the name from the password file
|
||||
* corresponding to the uid.
|
||||
*/
|
||||
uid = getuid();
|
||||
if (!from && (!(from = getlogin()) ||
|
||||
!(pw = getpwnam(from)) || pw->pw_uid != uid))
|
||||
from = (pw = getpwuid(uid)) ? pw->pw_name : "???";
|
||||
|
||||
/*
|
||||
* There is no way to distinguish the error status of one delivery
|
||||
* from the rest of the deliveries. So, if we failed hard on one
|
||||
* or more deliveries, but had no failures on any of the others, we
|
||||
* return a hard failure. If we failed temporarily on one or more
|
||||
* deliveries, we return a temporary failure regardless of the other
|
||||
* failures. This results in the delivery being reattempted later
|
||||
* at the expense of repeated failures and multiple deliveries.
|
||||
*/
|
||||
for (fd = store(from); *argv; ++argv)
|
||||
deliver(fd, *argv);
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
int
|
||||
store(from)
|
||||
char *from;
|
||||
{
|
||||
FILE *fp;
|
||||
time_t tval;
|
||||
int fd, eline;
|
||||
char *tn, line[2048];
|
||||
|
||||
tn = strdup(_PATH_LOCTMP);
|
||||
if ((fd = mkstemp(tn)) == -1 || (fp = fdopen(fd, "w+")) == NULL) {
|
||||
e_to_sys(errno);
|
||||
err("unable to open temporary file");
|
||||
}
|
||||
(void)unlink(tn);
|
||||
free(tn);
|
||||
|
||||
(void)time(&tval);
|
||||
(void)fprintf(fp, "From %s %s", from, ctime(&tval));
|
||||
|
||||
line[0] = '\0';
|
||||
for (eline = 1; fgets(line, sizeof(line), stdin);) {
|
||||
if (line[0] == '\n')
|
||||
eline = 1;
|
||||
else {
|
||||
if (eline && line[0] == 'F' &&
|
||||
!memcmp(line, "From ", 5))
|
||||
(void)putc('>', fp);
|
||||
eline = 0;
|
||||
}
|
||||
(void)fprintf(fp, "%s", line);
|
||||
if (ferror(fp)) {
|
||||
e_to_sys(errno);
|
||||
err("temporary file write error");
|
||||
}
|
||||
}
|
||||
|
||||
/* If message not newline terminated, need an extra. */
|
||||
if (!strchr(line, '\n'))
|
||||
(void)putc('\n', fp);
|
||||
/* Output a newline; note, empty messages are allowed. */
|
||||
(void)putc('\n', fp);
|
||||
|
||||
if (fflush(fp) == EOF || ferror(fp)) {
|
||||
e_to_sys(errno);
|
||||
err("temporary file write error");
|
||||
}
|
||||
return (fd);
|
||||
}
|
||||
|
||||
void
|
||||
deliver(fd, name)
|
||||
int fd;
|
||||
char *name;
|
||||
{
|
||||
struct stat fsb, sb;
|
||||
struct passwd *pw;
|
||||
int mbfd, nr, nw, off;
|
||||
char biffmsg[100], buf[8*1024], path[MAXPATHLEN];
|
||||
off_t curoff;
|
||||
|
||||
/*
|
||||
* Disallow delivery to unknown names -- special mailboxes can be
|
||||
* handled in the sendmail aliases file.
|
||||
*/
|
||||
if (!(pw = getpwnam(name))) {
|
||||
if (eval != EX_TEMPFAIL)
|
||||
eval = EX_UNAVAILABLE;
|
||||
warn("unknown name: %s", name);
|
||||
return;
|
||||
}
|
||||
|
||||
(void)snprintf(path, sizeof(path), "%s/%s", _PATH_MAILDIR, name);
|
||||
|
||||
/*
|
||||
* If the mailbox is linked or a symlink, fail. There's an obvious
|
||||
* race here, that the file was replaced with a symbolic link after
|
||||
* the lstat returned, but before the open. We attempt to detect
|
||||
* this by comparing the original stat information and information
|
||||
* returned by an fstat of the file descriptor returned by the open.
|
||||
*
|
||||
* NB: this is a symptom of a larger problem, that the mail spooling
|
||||
* directory is writeable by the wrong users. If that directory is
|
||||
* writeable, system security is compromised for other reasons, and
|
||||
* it cannot be fixed here.
|
||||
*
|
||||
* If we created the mailbox, set the owner/group. If that fails,
|
||||
* just return. Another process may have already opened it, so we
|
||||
* can't unlink it. Historically, binmail set the owner/group at
|
||||
* each mail delivery. We no longer do this, assuming that if the
|
||||
* ownership or permissions were changed there was a reason.
|
||||
*
|
||||
* XXX
|
||||
* open(2) should support flock'ing the file.
|
||||
*/
|
||||
tryagain:
|
||||
if (lstat(path, &sb)) {
|
||||
mbfd = open(path,
|
||||
O_APPEND|O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
|
||||
if (mbfd == -1) {
|
||||
if (errno == EEXIST)
|
||||
goto tryagain;
|
||||
} else if (fchown(mbfd, pw->pw_uid, pw->pw_gid)) {
|
||||
e_to_sys(errno);
|
||||
warn("chown %u.%u: %s", pw->pw_uid, pw->pw_gid, name);
|
||||
return;
|
||||
}
|
||||
} else if (sb.st_nlink != 1 || S_ISLNK(sb.st_mode)) {
|
||||
e_to_sys(errno);
|
||||
warn("%s: linked file", path);
|
||||
return;
|
||||
} else {
|
||||
mbfd = open(path, O_APPEND|O_WRONLY, 0);
|
||||
if (mbfd != -1 &&
|
||||
(fstat(mbfd, &fsb) || fsb.st_nlink != 1 ||
|
||||
S_ISLNK(fsb.st_mode) || sb.st_dev != fsb.st_dev ||
|
||||
sb.st_ino != fsb.st_ino)) {
|
||||
warn("%s: file changed after open", path);
|
||||
(void)close(mbfd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mbfd == -1) {
|
||||
e_to_sys(errno);
|
||||
warn("%s: %s", path, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wait until we can get a lock on the file. */
|
||||
if (flock(mbfd, LOCK_EX)) {
|
||||
e_to_sys(errno);
|
||||
warn("%s: %s", path, strerror(errno));
|
||||
goto err1;
|
||||
}
|
||||
|
||||
/* Get the starting offset of the new message for biff. */
|
||||
curoff = lseek(mbfd, (off_t)0, SEEK_END);
|
||||
(void)snprintf(biffmsg, sizeof(biffmsg), "%s@%qd\n", name, curoff);
|
||||
|
||||
/* Copy the message into the file. */
|
||||
if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) {
|
||||
e_to_sys(errno);
|
||||
warn("temporary file: %s", strerror(errno));
|
||||
goto err1;
|
||||
}
|
||||
while ((nr = read(fd, buf, sizeof(buf))) > 0)
|
||||
for (off = 0; off < nr; nr -= nw, off += nw)
|
||||
if ((nw = write(mbfd, buf + off, nr)) < 0) {
|
||||
e_to_sys(errno);
|
||||
warn("%s: %s", path, strerror(errno));
|
||||
goto err2;;
|
||||
}
|
||||
if (nr < 0) {
|
||||
e_to_sys(errno);
|
||||
warn("temporary file: %s", strerror(errno));
|
||||
goto err2;;
|
||||
}
|
||||
|
||||
/* Flush to disk, don't wait for update. */
|
||||
if (fsync(mbfd)) {
|
||||
e_to_sys(errno);
|
||||
warn("%s: %s", path, strerror(errno));
|
||||
err2: (void)ftruncate(mbfd, curoff);
|
||||
err1: (void)close(mbfd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Close and check -- NFS doesn't write until the close. */
|
||||
if (close(mbfd)) {
|
||||
e_to_sys(errno);
|
||||
warn("%s: %s", path, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
notifybiff(biffmsg);
|
||||
}
|
||||
|
||||
void
|
||||
notifybiff(msg)
|
||||
char *msg;
|
||||
{
|
||||
static struct sockaddr_in addr;
|
||||
static int f = -1;
|
||||
struct hostent *hp;
|
||||
struct servent *sp;
|
||||
int len;
|
||||
|
||||
if (!addr.sin_family) {
|
||||
/* Be silent if biff service not available. */
|
||||
if (!(sp = getservbyname("biff", "udp")))
|
||||
return;
|
||||
if (!(hp = gethostbyname("localhost"))) {
|
||||
warn("localhost: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
addr.sin_family = hp->h_addrtype;
|
||||
memmove(&addr.sin_addr, hp->h_addr, hp->h_length);
|
||||
addr.sin_port = sp->s_port;
|
||||
}
|
||||
if (f < 0 && (f = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||
warn("socket: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
len = strlen(msg) + 1;
|
||||
if (sendto(f, msg, len, 0, (struct sockaddr *)&addr, sizeof(addr))
|
||||
!= len)
|
||||
warn("sendto biff: %s", strerror(errno));
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
eval = EX_USAGE;
|
||||
err("usage: mail.local [-f from] user ...");
|
||||
}
|
||||
|
||||
#if __STDC__
|
||||
void
|
||||
err(const char *fmt, ...)
|
||||
#else
|
||||
void
|
||||
err(fmt, va_alist)
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
vwarn(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
exit(eval);
|
||||
}
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
warn(const char *fmt, ...)
|
||||
#else
|
||||
warn(fmt, va_alist)
|
||||
const char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
vwarn(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
vwarn(fmt, ap)
|
||||
const char *fmt;
|
||||
_BSD_VA_LIST_ ap;
|
||||
{
|
||||
/*
|
||||
* Log the message to stderr.
|
||||
*
|
||||
* Don't use LOG_PERROR as an openlog() flag to do this,
|
||||
* it's not portable enough.
|
||||
*/
|
||||
if (eval != EX_USAGE)
|
||||
(void)fprintf(stderr, "mail.local: ");
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
|
||||
/* Log the message to syslog. */
|
||||
vsyslog(LOG_ERR, fmt, ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* e_to_sys --
|
||||
* Guess which errno's are temporary. Gag me.
|
||||
*/
|
||||
void
|
||||
e_to_sys(num)
|
||||
int num;
|
||||
{
|
||||
/* Temporary failures override hard errors. */
|
||||
if (eval == EX_TEMPFAIL)
|
||||
return;
|
||||
|
||||
switch(num) { /* Hopefully temporary errors. */
|
||||
#ifdef EAGAIN
|
||||
case EAGAIN: /* Resource temporarily unavailable */
|
||||
#endif
|
||||
#ifdef EDQUOT
|
||||
case EDQUOT: /* Disc quota exceeded */
|
||||
#endif
|
||||
#ifdef EBUSY
|
||||
case EBUSY: /* Device busy */
|
||||
#endif
|
||||
#ifdef EPROCLIM
|
||||
case EPROCLIM: /* Too many processes */
|
||||
#endif
|
||||
#ifdef EUSERS
|
||||
case EUSERS: /* Too many users */
|
||||
#endif
|
||||
#ifdef ECONNABORTED
|
||||
case ECONNABORTED: /* Software caused connection abort */
|
||||
#endif
|
||||
#ifdef ECONNREFUSED
|
||||
case ECONNREFUSED: /* Connection refused */
|
||||
#endif
|
||||
#ifdef ECONNRESET
|
||||
case ECONNRESET: /* Connection reset by peer */
|
||||
#endif
|
||||
#ifdef EDEADLK
|
||||
case EDEADLK: /* Resource deadlock avoided */
|
||||
#endif
|
||||
#ifdef EFBIG
|
||||
case EFBIG: /* File too large */
|
||||
#endif
|
||||
#ifdef EHOSTDOWN
|
||||
case EHOSTDOWN: /* Host is down */
|
||||
#endif
|
||||
#ifdef EHOSTUNREACH
|
||||
case EHOSTUNREACH: /* No route to host */
|
||||
#endif
|
||||
#ifdef EMFILE
|
||||
case EMFILE: /* Too many open files */
|
||||
#endif
|
||||
#ifdef ENETDOWN
|
||||
case ENETDOWN: /* Network is down */
|
||||
#endif
|
||||
#ifdef ENETRESET
|
||||
case ENETRESET: /* Network dropped connection on reset */
|
||||
#endif
|
||||
#ifdef ENETUNREACH
|
||||
case ENETUNREACH: /* Network is unreachable */
|
||||
#endif
|
||||
#ifdef ENFILE
|
||||
case ENFILE: /* Too many open files in system */
|
||||
#endif
|
||||
#ifdef ENOBUFS
|
||||
case ENOBUFS: /* No buffer space available */
|
||||
#endif
|
||||
#ifdef ENOMEM
|
||||
case ENOMEM: /* Cannot allocate memory */
|
||||
#endif
|
||||
#ifdef ENOSPC
|
||||
case ENOSPC: /* No space left on device */
|
||||
#endif
|
||||
#ifdef EROFS
|
||||
case EROFS: /* Read-only file system */
|
||||
#endif
|
||||
#ifdef ESTALE
|
||||
case ESTALE: /* Stale NFS file handle */
|
||||
#endif
|
||||
#ifdef ETIMEDOUT
|
||||
case ETIMEDOUT: /* Connection timed out */
|
||||
#endif
|
||||
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
|
||||
case EWOULDBLOCK: /* Operation would block. */
|
||||
#endif
|
||||
eval = EX_TEMPFAIL;
|
||||
break;
|
||||
default:
|
||||
eval = EX_UNAVAILABLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
37
libexec/mail.local/pathnames.h
Normal file
37
libexec/mail.local/pathnames.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
#include <paths.h>
|
||||
|
||||
#define _PATH_LOCTMP "/tmp/local.XXXXXX"
|
||||
11
libexec/rbootd/Makefile
Normal file
11
libexec/rbootd/Makefile
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||
|
||||
PROG= rbootd
|
||||
SRCS= bpf.c conf.c parseconf.c rbootd.c rmpproto.c utils.c
|
||||
MAN8= rbootd.0
|
||||
|
||||
afterinstall:
|
||||
(cd ${.CURDIR}/bootdir && install -c -o ${BINOWN} -g ${BINGRP} \
|
||||
-m 444 * ${DESTDIR}/usr/mdec/)
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
422
libexec/rbootd/bpf.c
Normal file
422
libexec/rbootd/bpf.c
Normal file
|
|
@ -0,0 +1,422 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)bpf.c 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: bpf.c 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)bpf.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/bpf.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include "defs.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
static int BpfFd = -1;
|
||||
static unsigned BpfLen = 0;
|
||||
static u_char *BpfPkt = NULL;
|
||||
|
||||
/*
|
||||
** BpfOpen -- Open and initialize a BPF device.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** File descriptor of opened BPF device (for select() etc).
|
||||
**
|
||||
** Side Effects:
|
||||
** If an error is encountered, the program terminates here.
|
||||
*/
|
||||
int
|
||||
BpfOpen()
|
||||
{
|
||||
struct ifreq ifr;
|
||||
char bpfdev[32];
|
||||
int n = 0;
|
||||
|
||||
/*
|
||||
* Open the first available BPF device.
|
||||
*/
|
||||
do {
|
||||
(void) sprintf(bpfdev, _PATH_BPF, n++);
|
||||
BpfFd = open(bpfdev, O_RDWR);
|
||||
} while (BpfFd < 0 && (errno == EBUSY || errno == EPERM));
|
||||
|
||||
if (BpfFd < 0) {
|
||||
syslog(LOG_ERR, "bpf: no available devices: %m");
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set interface name for bpf device, get data link layer
|
||||
* type and make sure it's type Ethernet.
|
||||
*/
|
||||
(void) strncpy(ifr.ifr_name, IntfName, sizeof(ifr.ifr_name));
|
||||
if (ioctl(BpfFd, BIOCSETIF, (caddr_t)&ifr) < 0) {
|
||||
syslog(LOG_ERR, "bpf: ioctl(BIOCSETIF,%s): %m", IntfName);
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure we are dealing with an Ethernet device.
|
||||
*/
|
||||
if (ioctl(BpfFd, BIOCGDLT, (caddr_t)&n) < 0) {
|
||||
syslog(LOG_ERR, "bpf: ioctl(BIOCGDLT): %m");
|
||||
Exit(0);
|
||||
}
|
||||
if (n != DLT_EN10MB) {
|
||||
syslog(LOG_ERR,"bpf: %s: data-link type %d unsupported",
|
||||
IntfName, n);
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* On read(), return packets immediately (do not buffer them).
|
||||
*/
|
||||
n = 1;
|
||||
if (ioctl(BpfFd, BIOCIMMEDIATE, (caddr_t)&n) < 0) {
|
||||
syslog(LOG_ERR, "bpf: ioctl(BIOCIMMEDIATE): %m");
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to enable the chip/driver's multicast address filter to
|
||||
* grab our RMP address. If this fails, try promiscuous mode.
|
||||
* If this fails, there's no way we are going to get any RMP
|
||||
* packets so just exit here.
|
||||
*/
|
||||
#ifdef MSG_EOR
|
||||
ifr.ifr_addr.sa_len = RMP_ADDRLEN + 2;
|
||||
#endif
|
||||
ifr.ifr_addr.sa_family = AF_UNSPEC;
|
||||
bcopy(&RmpMcastAddr[0], (char *)&ifr.ifr_addr.sa_data[0], RMP_ADDRLEN);
|
||||
if (ioctl(BpfFd, SIOCADDMULTI, (caddr_t)&ifr) < 0) {
|
||||
syslog(LOG_WARNING,
|
||||
"bpf: can't add mcast addr (%m), setting promiscuous mode");
|
||||
|
||||
if (ioctl(BpfFd, BIOCPROMISC, (caddr_t)0) < 0) {
|
||||
syslog(LOG_ERR, "bpf: can't set promiscuous mode: %m");
|
||||
Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask BPF how much buffer space it requires and allocate one.
|
||||
*/
|
||||
if (ioctl(BpfFd, BIOCGBLEN, (caddr_t)&BpfLen) < 0) {
|
||||
syslog(LOG_ERR, "bpf: ioctl(BIOCGBLEN): %m");
|
||||
Exit(0);
|
||||
}
|
||||
if (BpfPkt == NULL)
|
||||
BpfPkt = (u_char *)malloc(BpfLen);
|
||||
|
||||
if (BpfPkt == NULL) {
|
||||
syslog(LOG_ERR, "bpf: out of memory (%u bytes for bpfpkt)",
|
||||
BpfLen);
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a little program to snarf RMP Boot packets and stuff
|
||||
* it down BPF's throat (i.e. set up the packet filter).
|
||||
*/
|
||||
{
|
||||
#define RMP ((struct rmp_packet *)0)
|
||||
static struct bpf_insn bpf_insn[] = {
|
||||
{ BPF_LD|BPF_B|BPF_ABS, 0, 0, (long)&RMP->hp_llc.dsap },
|
||||
{ BPF_JMP|BPF_JEQ|BPF_K, 0, 5, IEEE_DSAP_HP },
|
||||
{ BPF_LD|BPF_H|BPF_ABS, 0, 0, (long)&RMP->hp_llc.cntrl },
|
||||
{ BPF_JMP|BPF_JEQ|BPF_K, 0, 3, IEEE_CNTL_HP },
|
||||
{ BPF_LD|BPF_H|BPF_ABS, 0, 0, (long)&RMP->hp_llc.dxsap },
|
||||
{ BPF_JMP|BPF_JEQ|BPF_K, 0, 1, HPEXT_DXSAP },
|
||||
{ BPF_RET|BPF_K, 0, 0, RMP_MAX_PACKET },
|
||||
{ BPF_RET|BPF_K, 0, 0, 0x0 }
|
||||
};
|
||||
#undef RMP
|
||||
static struct bpf_program bpf_pgm = {
|
||||
sizeof(bpf_insn)/sizeof(bpf_insn[0]), bpf_insn
|
||||
};
|
||||
|
||||
if (ioctl(BpfFd, BIOCSETF, (caddr_t)&bpf_pgm) < 0) {
|
||||
syslog(LOG_ERR, "bpf: ioctl(BIOCSETF): %m");
|
||||
Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
return(BpfFd);
|
||||
}
|
||||
|
||||
/*
|
||||
** BPF GetIntfName -- Return the name of a network interface attached to
|
||||
** the system, or 0 if none can be found. The interface
|
||||
** must be configured up; the lowest unit number is
|
||||
** preferred; loopback is ignored.
|
||||
**
|
||||
** Parameters:
|
||||
** errmsg - if no network interface found, *errmsg explains why.
|
||||
**
|
||||
** Returns:
|
||||
** A (static) pointer to interface name, or NULL on error.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
*/
|
||||
char *
|
||||
BpfGetIntfName(errmsg)
|
||||
char **errmsg;
|
||||
{
|
||||
struct ifreq ibuf[8], *ifrp, *ifend, *mp;
|
||||
struct ifconf ifc;
|
||||
int fd;
|
||||
int minunit, n;
|
||||
char *cp;
|
||||
static char device[sizeof(ifrp->ifr_name)];
|
||||
static char errbuf[128] = "No Error!";
|
||||
|
||||
if (errmsg != NULL)
|
||||
*errmsg = errbuf;
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
(void) strcpy(errbuf, "bpf: socket: %m");
|
||||
return(NULL);
|
||||
}
|
||||
ifc.ifc_len = sizeof ibuf;
|
||||
ifc.ifc_buf = (caddr_t)ibuf;
|
||||
|
||||
#ifdef OSIOCGIFCONF
|
||||
if (ioctl(fd, OSIOCGIFCONF, (char *)&ifc) < 0 ||
|
||||
ifc.ifc_len < sizeof(struct ifreq)) {
|
||||
(void) strcpy(errbuf, "bpf: ioctl(OSIOCGIFCONF): %m");
|
||||
return(NULL);
|
||||
}
|
||||
#else
|
||||
if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
|
||||
ifc.ifc_len < sizeof(struct ifreq)) {
|
||||
(void) strcpy(errbuf, "bpf: ioctl(SIOCGIFCONF): %m");
|
||||
return(NULL);
|
||||
}
|
||||
#endif
|
||||
ifrp = ibuf;
|
||||
ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
|
||||
|
||||
mp = 0;
|
||||
minunit = 666;
|
||||
for (; ifrp < ifend; ++ifrp) {
|
||||
if (ioctl(fd, SIOCGIFFLAGS, (char *)ifrp) < 0) {
|
||||
(void) strcpy(errbuf, "bpf: ioctl(SIOCGIFFLAGS): %m");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* If interface is down or this is the loopback interface,
|
||||
* ignore it.
|
||||
*/
|
||||
if ((ifrp->ifr_flags & IFF_UP) == 0 ||
|
||||
#ifdef IFF_LOOPBACK
|
||||
(ifrp->ifr_flags & IFF_LOOPBACK))
|
||||
#else
|
||||
(strcmp(ifrp->ifr_name, "lo0") == 0))
|
||||
#endif
|
||||
continue;
|
||||
|
||||
for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp)
|
||||
;
|
||||
n = atoi(cp);
|
||||
if (n < minunit) {
|
||||
minunit = n;
|
||||
mp = ifrp;
|
||||
}
|
||||
}
|
||||
|
||||
(void) close(fd);
|
||||
if (mp == 0) {
|
||||
(void) strcpy(errbuf, "bpf: no interfaces found");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
(void) strcpy(device, mp->ifr_name);
|
||||
return(device);
|
||||
}
|
||||
|
||||
/*
|
||||
** BpfRead -- Read packets from a BPF device and fill in `rconn'.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - filled in with next packet.
|
||||
** doread - is True if we can issue a read() syscall.
|
||||
**
|
||||
** Returns:
|
||||
** True if `rconn' contains a new packet, False otherwise.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
*/
|
||||
int
|
||||
BpfRead(rconn, doread)
|
||||
RMPCONN *rconn;
|
||||
int doread;
|
||||
{
|
||||
register int datlen, caplen, hdrlen;
|
||||
static u_char *bp = NULL, *ep = NULL;
|
||||
int cc;
|
||||
|
||||
/*
|
||||
* The read() may block, or it may return one or more packets.
|
||||
* We let the caller decide whether or not we can issue a read().
|
||||
*/
|
||||
if (doread) {
|
||||
if ((cc = read(BpfFd, (char *)BpfPkt, (int)BpfLen)) < 0) {
|
||||
syslog(LOG_ERR, "bpf: read: %m");
|
||||
return(0);
|
||||
} else {
|
||||
bp = BpfPkt;
|
||||
ep = BpfPkt + cc;
|
||||
}
|
||||
}
|
||||
|
||||
#define bhp ((struct bpf_hdr *)bp)
|
||||
/*
|
||||
* If there is a new packet in the buffer, stuff it into `rconn'
|
||||
* and return a success indication.
|
||||
*/
|
||||
if (bp < ep) {
|
||||
datlen = bhp->bh_datalen;
|
||||
caplen = bhp->bh_caplen;
|
||||
hdrlen = bhp->bh_hdrlen;
|
||||
|
||||
if (caplen != datlen)
|
||||
syslog(LOG_ERR,
|
||||
"bpf: short packet dropped (%d of %d bytes)",
|
||||
caplen, datlen);
|
||||
else if (caplen > sizeof(struct rmp_packet))
|
||||
syslog(LOG_ERR, "bpf: large packet dropped (%d bytes)",
|
||||
caplen);
|
||||
else {
|
||||
rconn->rmplen = caplen;
|
||||
bcopy((char *)&bhp->bh_tstamp, (char *)&rconn->tstamp,
|
||||
sizeof(struct timeval));
|
||||
bcopy((char *)bp + hdrlen, (char *)&rconn->rmp, caplen);
|
||||
}
|
||||
bp += BPF_WORDALIGN(caplen + hdrlen);
|
||||
return(1);
|
||||
}
|
||||
#undef bhp
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
** BpfWrite -- Write packet to BPF device.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - packet to send.
|
||||
**
|
||||
** Returns:
|
||||
** True if write succeeded, False otherwise.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
*/
|
||||
int
|
||||
BpfWrite(rconn)
|
||||
RMPCONN *rconn;
|
||||
{
|
||||
if (write(BpfFd, (char *)&rconn->rmp, rconn->rmplen) < 0) {
|
||||
syslog(LOG_ERR, "write: %s: %m", EnetStr(rconn));
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
** BpfClose -- Close a BPF device.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
*/
|
||||
void
|
||||
BpfClose()
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
if (BpfPkt != NULL) {
|
||||
free((char *)BpfPkt);
|
||||
BpfPkt = NULL;
|
||||
}
|
||||
|
||||
if (BpfFd == -1)
|
||||
return;
|
||||
|
||||
#ifdef MSG_EOR
|
||||
ifr.ifr_addr.sa_len = RMP_ADDRLEN + 2;
|
||||
#endif
|
||||
ifr.ifr_addr.sa_family = AF_UNSPEC;
|
||||
bcopy(&RmpMcastAddr[0], (char *)&ifr.ifr_addr.sa_data[0], RMP_ADDRLEN);
|
||||
if (ioctl(BpfFd, SIOCDELMULTI, (caddr_t)&ifr) < 0)
|
||||
(void) ioctl(BpfFd, BIOCPROMISC, (caddr_t)0);
|
||||
|
||||
(void) close(BpfFd);
|
||||
BpfFd = -1;
|
||||
}
|
||||
90
libexec/rbootd/conf.c
Normal file
90
libexec/rbootd/conf.c
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)conf.c 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: conf.c 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)conf.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
/*
|
||||
** Define (and possibly initialize) global variables here.
|
||||
**
|
||||
** Caveat:
|
||||
** The maximum number of bootable files (`char *BootFiles[]') is
|
||||
** limited to C_MAXFILE (i.e. the maximum number of files that
|
||||
** can be spec'd in the configuration file). This was done to
|
||||
** simplify the boot file search code.
|
||||
*/
|
||||
|
||||
char *ProgName; /* path-stripped argv[0] */
|
||||
char MyHost[MAXHOSTNAMELEN+1]; /* host name */
|
||||
int MyPid; /* process id */
|
||||
int DebugFlg = 0; /* set true if debugging */
|
||||
int BootAny = 0; /* set true if we boot anyone */
|
||||
|
||||
char *ConfigFile = NULL; /* configuration file */
|
||||
char *DfltConfig = _PATH_RBOOTDCONF; /* default configuration file */
|
||||
char *PidFile = _PATH_RBOOTDPID; /* file w/pid of server */
|
||||
char *BootDir = _PATH_RBOOTDLIB; /* directory w/boot files */
|
||||
char *DbgFile = _PATH_RBOOTDDBG; /* debug output file */
|
||||
|
||||
FILE *DbgFp = NULL; /* debug file pointer */
|
||||
char *IntfName = NULL; /* intf we are attached to */
|
||||
|
||||
u_short SessionID = 0; /* generated session ID */
|
||||
|
||||
char *BootFiles[C_MAXFILE]; /* list of boot files */
|
||||
|
||||
CLIENT *Clients = NULL; /* list of addrs we'll accept */
|
||||
RMPCONN *RmpConns = NULL; /* list of active connections */
|
||||
|
||||
char RmpMcastAddr[RMP_ADDRLEN] = RMP_ADDR; /* RMP multicast address */
|
||||
185
libexec/rbootd/defs.h
Normal file
185
libexec/rbootd/defs.h
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)defs.h 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: defs.h 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#include "rmp.h"
|
||||
#include "rmp_var.h"
|
||||
|
||||
/*
|
||||
** Common #define's and external variables. All other files should
|
||||
** include this.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This may be defined in <sys/param.h>, if not, it's defined here.
|
||||
*/
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SIGUSR1 and SIGUSR2 are defined in <signal.h> for 4.3BSD systems.
|
||||
*/
|
||||
#ifndef SIGUSR1
|
||||
#define SIGUSR1 SIGEMT
|
||||
#endif
|
||||
#ifndef SIGUSR2
|
||||
#define SIGUSR2 SIGFPE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These can be faster & more efficient than strcmp()/strncmp()...
|
||||
*/
|
||||
#define STREQN(s1,s2) ((*s1 == *s2) && (strcmp(s1,s2) == 0))
|
||||
#define STRNEQN(s1,s2,n) ((*s1 == *s2) && (strncmp(s1,s2,n) == 0))
|
||||
|
||||
/*
|
||||
* Configuration file limitations.
|
||||
*/
|
||||
#define C_MAXFILE 10 /* max number of boot-able files */
|
||||
#define C_LINELEN 1024 /* max length of line */
|
||||
|
||||
/*
|
||||
* Direction of packet (used as argument to DispPkt).
|
||||
*/
|
||||
#define DIR_RCVD 0
|
||||
#define DIR_SENT 1
|
||||
#define DIR_NONE 2
|
||||
|
||||
/*
|
||||
* These need not be functions, so...
|
||||
*/
|
||||
#define FreeStr(str) free(str)
|
||||
#define FreeClient(cli) free(cli)
|
||||
#define GenSessID() (++SessionID ? SessionID: ++SessionID)
|
||||
|
||||
/*
|
||||
* Converting an Ethernet address to a string is done in many routines.
|
||||
* Using `rmp.hp_hdr.saddr' works because this field is *never* changed;
|
||||
* it will *always* contain the source address of the packet.
|
||||
*/
|
||||
#define EnetStr(rptr) GetEtherAddr(&(rptr)->rmp.hp_hdr.saddr[0])
|
||||
|
||||
/*
|
||||
* Every machine we can boot will have one of these allocated for it
|
||||
* (unless there are no restrictions on who we can boot).
|
||||
*/
|
||||
typedef struct client_s {
|
||||
u_char addr[RMP_ADDRLEN]; /* addr of machine */
|
||||
char *files[C_MAXFILE]; /* boot-able files */
|
||||
struct client_s *next; /* ptr to next */
|
||||
} CLIENT;
|
||||
|
||||
/*
|
||||
* Every active connection has one of these allocated for it.
|
||||
*/
|
||||
typedef struct rmpconn_s {
|
||||
struct rmp_packet rmp; /* RMP packet */
|
||||
int rmplen; /* length of packet */
|
||||
struct timeval tstamp; /* last time active */
|
||||
int bootfd; /* open boot file */
|
||||
struct rmpconn_s *next; /* ptr to next */
|
||||
} RMPCONN;
|
||||
|
||||
/*
|
||||
* All these variables are defined in "conf.c".
|
||||
*/
|
||||
extern char *ProgName; /* path-stripped argv[0] */
|
||||
extern char MyHost[]; /* this hosts' name */
|
||||
extern int MyPid; /* this processes' ID */
|
||||
extern int DebugFlg; /* set true if debugging */
|
||||
extern int BootAny; /* set true if we can boot anyone */
|
||||
|
||||
extern char *ConfigFile; /* configuration file */
|
||||
extern char *DfltConfig; /* default configuration file */
|
||||
extern char *DbgFile; /* debug output file */
|
||||
extern char *PidFile; /* file containing pid of server */
|
||||
extern char *BootDir; /* directory w/boot files */
|
||||
|
||||
extern FILE *DbgFp; /* debug file pointer */
|
||||
extern char *IntfName; /* interface we are attached to */
|
||||
|
||||
extern u_short SessionID; /* generated session ID */
|
||||
|
||||
extern char *BootFiles[]; /* list of boot files */
|
||||
|
||||
extern CLIENT *Clients; /* list of addrs we'll accept */
|
||||
extern RMPCONN *RmpConns; /* list of active connections */
|
||||
|
||||
extern char RmpMcastAddr[]; /* RMP multicast address */
|
||||
|
||||
void AddConn __P((RMPCONN *));
|
||||
int BootDone __P((RMPCONN *));
|
||||
void BpfClose __P((void));
|
||||
char *BpfGetIntfName __P((char **));
|
||||
int BpfOpen __P((void));
|
||||
int BpfRead __P((RMPCONN *, int));
|
||||
int BpfWrite __P((RMPCONN *));
|
||||
void DebugOff __P((int));
|
||||
void DebugOn __P((int));
|
||||
void DispPkt __P((RMPCONN *, int));
|
||||
void DoTimeout __P((void));
|
||||
void DspFlnm __P((u_int, char *));
|
||||
void Exit __P((int));
|
||||
CLIENT *FindClient __P((RMPCONN *));
|
||||
RMPCONN *FindConn __P((RMPCONN *));
|
||||
void FreeClients __P((void));
|
||||
void FreeConn __P((RMPCONN *));
|
||||
void FreeConns __P((void));
|
||||
int GetBootFiles __P((void));
|
||||
char *GetEtherAddr __P((u_char *));
|
||||
CLIENT *NewClient __P((u_char *));
|
||||
RMPCONN *NewConn __P((RMPCONN *));
|
||||
char *NewStr __P((char *));
|
||||
u_char *ParseAddr __P((char *));
|
||||
int ParseConfig __P((void));
|
||||
void ProcessPacket __P((RMPCONN *, CLIENT *));
|
||||
void ReConfig __P((int));
|
||||
void RemoveConn __P((RMPCONN *));
|
||||
int SendBootRepl __P((struct rmp_packet *, RMPCONN *, char *[]));
|
||||
int SendFileNo __P((struct rmp_packet *, RMPCONN *, char *[]));
|
||||
int SendPacket __P((RMPCONN *));
|
||||
int SendReadRepl __P((RMPCONN *));
|
||||
int SendServerID __P((RMPCONN *));
|
||||
359
libexec/rbootd/parseconf.c
Normal file
359
libexec/rbootd/parseconf.c
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)parseconf.c 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: parseconf.c 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)parseconf.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include "defs.h"
|
||||
|
||||
/*
|
||||
** ParseConfig -- parse the config file into linked list of clients.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** 1 on success, 0 otherwise.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Linked list of clients will be (re)allocated.
|
||||
**
|
||||
** Warnings:
|
||||
** - GetBootFiles() must be called before this routine
|
||||
** to create a linked list of default boot files.
|
||||
*/
|
||||
int
|
||||
ParseConfig()
|
||||
{
|
||||
FILE *fp;
|
||||
CLIENT *client;
|
||||
u_char *addr;
|
||||
char line[C_LINELEN];
|
||||
register char *cp, *bcp;
|
||||
register int i, j;
|
||||
int omask, linecnt = 0;
|
||||
|
||||
if (BootAny) /* ignore config file */
|
||||
return(1);
|
||||
|
||||
FreeClients(); /* delete old list of clients */
|
||||
|
||||
if ((fp = fopen(ConfigFile, "r")) == NULL) {
|
||||
syslog(LOG_ERR, "ParseConfig: can't open config file (%s)",
|
||||
ConfigFile);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* We've got to block SIGHUP to prevent reconfiguration while
|
||||
* dealing with the linked list of Clients. This can be done
|
||||
* when actually linking the new client into the list, but
|
||||
* this could have unexpected results if the server was HUP'd
|
||||
* whilst reconfiguring. Hence, it is done here.
|
||||
*/
|
||||
omask = sigblock(sigmask(SIGHUP));
|
||||
|
||||
/*
|
||||
* GETSTR positions `bcp' at the start of the current token,
|
||||
* and null terminates it. `cp' is positioned at the start
|
||||
* of the next token. spaces & commas are separators.
|
||||
*/
|
||||
#define GETSTR while (isspace(*cp) || *cp == ',') cp++; \
|
||||
bcp = cp; \
|
||||
while (*cp && *cp!=',' && !isspace(*cp)) cp++; \
|
||||
if (*cp) *cp++ = '\0'
|
||||
|
||||
/*
|
||||
* For each line, parse it into a new CLIENT struct.
|
||||
*/
|
||||
while (fgets(line, C_LINELEN, fp) != NULL) {
|
||||
linecnt++; /* line counter */
|
||||
|
||||
if (*line == '\0' || *line == '#') /* ignore comment */
|
||||
continue;
|
||||
|
||||
if ((cp = index(line,'#')) != NULL) /* trash comments */
|
||||
*cp = '\0';
|
||||
|
||||
cp = line; /* init `cp' */
|
||||
GETSTR; /* get RMP addr */
|
||||
if (bcp == cp) /* all delimiters */
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Get an RMP address from a string. Abort on failure.
|
||||
*/
|
||||
if ((addr = ParseAddr(bcp)) == NULL) {
|
||||
syslog(LOG_ERR,
|
||||
"ParseConfig: line %d: cant parse <%s>",
|
||||
linecnt, bcp);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((client = NewClient(addr)) == NULL) /* alloc new client */
|
||||
continue;
|
||||
|
||||
GETSTR; /* get first file */
|
||||
|
||||
/*
|
||||
* If no boot files are spec'd, use the default list.
|
||||
* Otherwise, validate each file (`bcp') against the
|
||||
* list of boot-able files.
|
||||
*/
|
||||
i = 0;
|
||||
if (bcp == cp) /* no files spec'd */
|
||||
for (; i < C_MAXFILE && BootFiles[i] != NULL; i++)
|
||||
client->files[i] = BootFiles[i];
|
||||
else {
|
||||
do {
|
||||
/*
|
||||
* For each boot file spec'd, make sure it's
|
||||
* in our list. If so, include a pointer to
|
||||
* it in the CLIENT's list of boot files.
|
||||
*/
|
||||
for (j = 0; ; j++) {
|
||||
if (j==C_MAXFILE||BootFiles[j]==NULL) {
|
||||
syslog(LOG_ERR, "ParseConfig: line %d: no boot file (%s)",
|
||||
linecnt, bcp);
|
||||
break;
|
||||
}
|
||||
if (STREQN(BootFiles[j], bcp)) {
|
||||
if (i < C_MAXFILE)
|
||||
client->files[i++] =
|
||||
BootFiles[j];
|
||||
else
|
||||
syslog(LOG_ERR, "ParseConfig: line %d: too many boot files (%s)",
|
||||
linecnt, bcp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
GETSTR; /* get next file */
|
||||
} while (bcp != cp);
|
||||
|
||||
/*
|
||||
* Restricted list of boot files were spec'd,
|
||||
* however, none of them were found. Since we
|
||||
* apparently cant let them boot "just anything",
|
||||
* the entire record is invalidated.
|
||||
*/
|
||||
if (i == 0) {
|
||||
FreeClient(client);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Link this client into the linked list of clients.
|
||||
* SIGHUP has already been blocked.
|
||||
*/
|
||||
if (Clients)
|
||||
client->next = Clients;
|
||||
Clients = client;
|
||||
}
|
||||
|
||||
(void) fclose(fp); /* close config file */
|
||||
|
||||
(void) sigsetmask(omask); /* reset signal mask */
|
||||
|
||||
return(1); /* return success */
|
||||
}
|
||||
|
||||
/*
|
||||
** ParseAddr -- Parse a string containing an RMP address.
|
||||
**
|
||||
** This routine is fairly liberal at parsing an RMP address. The
|
||||
** address must contain 6 octets consisting of between 0 and 2 hex
|
||||
** chars (upper/lower case) separated by colons. If two colons are
|
||||
** together (e.g. "::", the octet between them is recorded as being
|
||||
** zero. Hence, the following addrs are all valid and parse to the
|
||||
** same thing:
|
||||
**
|
||||
** 08:00:09:00:66:ad 8::9:0:66:AD 8::9::66:aD
|
||||
**
|
||||
** For clarity, an RMP address is really an Ethernet address, but
|
||||
** since the HP boot code uses IEEE 802.3, it's really an IEEE
|
||||
** 802.3 address. Of course, all of these are identical.
|
||||
**
|
||||
** Parameters:
|
||||
** str - string representation of an RMP address.
|
||||
**
|
||||
** Returns:
|
||||
** pointer to a static array of RMP_ADDRLEN bytes.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
**
|
||||
** Warnings:
|
||||
** - The return value points to a static buffer; it must
|
||||
** be copied if it's to be saved.
|
||||
** - For speed, we assume a u_char consists of 8 bits.
|
||||
*/
|
||||
u_char *
|
||||
ParseAddr(str)
|
||||
char *str;
|
||||
{
|
||||
static u_char addr[RMP_ADDRLEN];
|
||||
register char *cp;
|
||||
register unsigned i;
|
||||
register int part, subpart;
|
||||
|
||||
bzero((char *)&addr[0], RMP_ADDRLEN); /* zero static buffer */
|
||||
|
||||
part = subpart = 0;
|
||||
for (cp = str; *cp; cp++) {
|
||||
/*
|
||||
* A colon (`:') must be used to delimit each octet.
|
||||
*/
|
||||
if (*cp == ':') {
|
||||
if (++part == RMP_ADDRLEN) /* too many parts */
|
||||
return(NULL);
|
||||
subpart = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert hex character to an integer.
|
||||
*/
|
||||
if (isdigit(*cp))
|
||||
i = *cp - '0';
|
||||
else {
|
||||
i = (isupper(*cp)? tolower(*cp): *cp) - 'a' + 10;
|
||||
if (i < 10 || i > 15) /* not a hex char */
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (subpart++) {
|
||||
if (subpart > 2) /* too many hex chars */
|
||||
return(NULL);
|
||||
addr[part] <<= 4;
|
||||
}
|
||||
addr[part] |= i;
|
||||
}
|
||||
|
||||
if (part != (RMP_ADDRLEN-1)) /* too few parts */
|
||||
return(NULL);
|
||||
|
||||
return(&addr[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
** GetBootFiles -- record list of files in current (boot) directory.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Number of boot files on success, 0 on failure.
|
||||
**
|
||||
** Side Effects:
|
||||
** Strings in `BootFiles' are freed/allocated.
|
||||
**
|
||||
** Warnings:
|
||||
** - After this routine is called, ParseConfig() must be
|
||||
** called to re-order it's list of boot file pointers.
|
||||
*/
|
||||
int
|
||||
GetBootFiles()
|
||||
{
|
||||
DIR *dfd;
|
||||
struct stat statb;
|
||||
register struct dirent *dp;
|
||||
register int i;
|
||||
|
||||
/*
|
||||
* Free the current list of boot files.
|
||||
*/
|
||||
for (i = 0; i < C_MAXFILE && BootFiles[i] != NULL; i++) {
|
||||
FreeStr(BootFiles[i]);
|
||||
BootFiles[i] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open current directory to read boot file names.
|
||||
*/
|
||||
if ((dfd = opendir(".")) == NULL) { /* open BootDir */
|
||||
syslog(LOG_ERR, "GetBootFiles: can't open directory (%s)\n",
|
||||
BootDir);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read each boot file name and allocate space for it in the
|
||||
* list of boot files (BootFiles). All boot files read after
|
||||
* C_MAXFILE will be ignored.
|
||||
*/
|
||||
i = 0;
|
||||
for (dp = readdir(dfd); dp != NULL; dp = readdir(dfd)) {
|
||||
if (stat(dp->d_name, &statb) < 0 ||
|
||||
(statb.st_mode & S_IFMT) != S_IFREG)
|
||||
continue;
|
||||
if (i == C_MAXFILE)
|
||||
syslog(LOG_ERR,
|
||||
"GetBootFiles: too many boot files (%s ignored)",
|
||||
dp->d_name);
|
||||
else if ((BootFiles[i] = NewStr(dp->d_name)) != NULL)
|
||||
i++;
|
||||
}
|
||||
|
||||
(void) closedir(dfd); /* close BootDir */
|
||||
|
||||
if (i == 0) /* cant find any boot files */
|
||||
syslog(LOG_ERR, "GetBootFiles: no boot files (%s)\n", BootDir);
|
||||
|
||||
return(i);
|
||||
}
|
||||
51
libexec/rbootd/pathnames.h
Normal file
51
libexec/rbootd/pathnames.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: pathnames.h 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#define _PATH_BPF "/dev/bpf%d"
|
||||
#define _PATH_RBOOTDCONF "/etc/rbootd.conf"
|
||||
#define _PATH_RBOOTDDBG "/tmp/rbootd.dbg"
|
||||
#define _PATH_RBOOTDLIB "/usr/mdec/rbootd"
|
||||
#define _PATH_RBOOTDPID "/var/run/rbootd.pid"
|
||||
156
libexec/rbootd/rbootd.8
Normal file
156
libexec/rbootd/rbootd.8
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
.\" Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
.\" for Software Science (CSS).
|
||||
.\" Copyright (c) 1992, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" the Center for Software Science of the University of Utah Computer
|
||||
.\" Science Department. CSS requests users of this software to return
|
||||
.\" to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
.\" CSS redistribution rights.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)rbootd.8 8.2 (Berkeley) 12/11/93
|
||||
.\"
|
||||
.\" Utah $Hdr: rbootd.man 3.1 92/07/06$
|
||||
.\" Author: Jeff Forys, University of Utah CSS
|
||||
.\"
|
||||
.Dd "December 11, 1993"
|
||||
.Dt RBOOTD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rbootd
|
||||
.Nd HP remote boot server
|
||||
.Sh SYNOPSIS
|
||||
.Nm rbootd
|
||||
.Op Fl ad
|
||||
.Op Fl i Ar interface
|
||||
.Op config_file
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm rbootd
|
||||
utility services boot requests from Hewlett-Packard workstations over a
|
||||
local area network.
|
||||
All boot files must reside in the boot file directory; further, if a
|
||||
client supplies path information in its boot request, it will be silently
|
||||
stripped away before processing.
|
||||
By default,
|
||||
.Nm rbootd
|
||||
only responds to requests from machines listed in its configuration file.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Fl
|
||||
.It Fl a
|
||||
Respond to boot requests from any machine.
|
||||
The configuration file is ignored if this option is specified.
|
||||
.It Fl d
|
||||
Run
|
||||
.Nm rbootd
|
||||
in debug mode.
|
||||
Packets sent and received are displayed to the terminal.
|
||||
.It Fl i Ar interface
|
||||
Service boot requests on specified interface.
|
||||
If unspecified,
|
||||
.Nm rbootd
|
||||
searches the system interface list for the lowest numbered, configured
|
||||
``up'' interface (excluding loopback).
|
||||
Ties are broken by choosing the earliest match.
|
||||
.El
|
||||
.Pp
|
||||
Specifying
|
||||
.Ar config_file
|
||||
on the command line causes
|
||||
.Nm rbootd
|
||||
to use a different configuration file from the default.
|
||||
.Pp
|
||||
The configuration file is a text file where each line describes a particular
|
||||
machine.
|
||||
A line must start with a machine's Ethernet address followed by an optional
|
||||
list of boot file names.
|
||||
An Ethernet address is specified in hexadecimal with each of its six octets
|
||||
separated by a colon.
|
||||
The boot file names come from the boot file directory.
|
||||
The ethernet address and boot file(s) must be separated by white-space
|
||||
and/or comma characters.
|
||||
A pound sign causes the remainder of a line to be ignored.
|
||||
.Pp
|
||||
Here is a sample configuration file:
|
||||
.Bl -column 08:00:09:0:66:ad SYSHPBSD,SYSHPUX "# vandy (anything)"
|
||||
.It #
|
||||
.It # ethernet addr boot file(s) comments
|
||||
.It #
|
||||
.It 08:00:09:0:66:ad SYSHPBSD # snake (4.3BSD)
|
||||
.It 08:00:09:0:59:5b # vandy (anything)
|
||||
.It 8::9:1:C6:75 SYSHPBSD,SYSHPUX # jaguar (either)
|
||||
.El
|
||||
.Pp
|
||||
.Nm Rbootd
|
||||
logs status and error messages via
|
||||
.Xr syslog 3 .
|
||||
A startup message is always logged, and in the case of fatal errors (or
|
||||
deadly signals) a message is logged announcing the server's termination.
|
||||
In general, a non-fatal error is handled by ignoring the event that caused
|
||||
it (e.g. an invalid Ethernet address in the config file causes that line
|
||||
to be invalidated).
|
||||
.Pp
|
||||
The following signals have the specified effect when sent to the server
|
||||
process using the
|
||||
.Xr kill 1
|
||||
command:
|
||||
.Bl -tag -width SIGUSR1 -offset -compact
|
||||
.It SIGHUP
|
||||
Drop all active connections and reconfigure.
|
||||
.It SIGUSR1
|
||||
Turn on debugging, do nothing if already on.
|
||||
.It SIGUSR2
|
||||
Turn off debugging, do nothing if already off.
|
||||
.El
|
||||
.Sh "FILES"
|
||||
.Bl -tag -width /usr/libexec/rbootd -compact
|
||||
.It /dev/bpf#
|
||||
packet-filter device
|
||||
.It /etc/rbootd.conf
|
||||
configuration file
|
||||
.It /tmp/rbootd.dbg
|
||||
debug output
|
||||
.It /usr/mdec/rbootd
|
||||
directory containing boot files
|
||||
.It /var/run/rbootd.pid
|
||||
process id
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr kill 1 ,
|
||||
.Xr socket 2 ,
|
||||
.Xr signal 3 ,
|
||||
.Xr syslog 3 ,
|
||||
.Xr rmp 4
|
||||
.Sh BUGS
|
||||
If multiple servers are started on the same interface, each will receive
|
||||
and respond to the same boot packets.
|
||||
508
libexec/rbootd/rbootd.c
Normal file
508
libexec/rbootd/rbootd.c
Normal file
|
|
@ -0,0 +1,508 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)rbootd.c 8.2 (Berkeley) 2/22/94
|
||||
*
|
||||
* Utah $Hdr: rbootd.c 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1992, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)rbootd.c 8.2 (Berkeley) 2/22/94";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include "defs.h"
|
||||
|
||||
|
||||
/* fd mask macros (backward compatibility with 4.2BSD) */
|
||||
#ifndef FD_SET
|
||||
#ifdef notdef
|
||||
typedef struct fd_set { /* this should already be in 4.2 */
|
||||
int fds_bits[1];
|
||||
} fd_set;
|
||||
#endif
|
||||
#define FD_ZERO(p) ((p)->fds_bits[0] = 0)
|
||||
#define FD_SET(n, p) ((p)->fds_bits[0] |= (1 << (n)))
|
||||
#define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1 << (n)))
|
||||
#define FD_ISSET(n, p) ((p)->fds_bits[0] & (1 << (n)))
|
||||
#endif
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int c, fd, omask, maxfds;
|
||||
fd_set rset;
|
||||
|
||||
/*
|
||||
* Find what name we are running under.
|
||||
*/
|
||||
ProgName = (ProgName = rindex(argv[0],'/')) ? ++ProgName : *argv;
|
||||
|
||||
/*
|
||||
* Close any open file descriptors.
|
||||
* Temporarily leave stdin & stdout open for `-d',
|
||||
* and stderr open for any pre-syslog error messages.
|
||||
*/
|
||||
{
|
||||
int i, nfds = getdtablesize();
|
||||
|
||||
for (i = 0; i < nfds; i++)
|
||||
if (i != fileno(stdin) && i != fileno(stdout) &&
|
||||
i != fileno(stderr))
|
||||
(void) close(i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse any arguments.
|
||||
*/
|
||||
while ((c = getopt(argc, argv, "adi:")) != EOF)
|
||||
switch(c) {
|
||||
case 'a':
|
||||
BootAny++;
|
||||
break;
|
||||
case 'd':
|
||||
DebugFlg++;
|
||||
break;
|
||||
case 'i':
|
||||
IntfName = optarg;
|
||||
break;
|
||||
}
|
||||
for (; optind < argc; optind++) {
|
||||
if (ConfigFile == NULL)
|
||||
ConfigFile = argv[optind];
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"%s: too many config files (`%s' ignored)\n",
|
||||
ProgName, argv[optind]);
|
||||
}
|
||||
}
|
||||
|
||||
if (ConfigFile == NULL) /* use default config file */
|
||||
ConfigFile = DfltConfig;
|
||||
|
||||
if (DebugFlg) {
|
||||
DbgFp = stdout; /* output to stdout */
|
||||
|
||||
(void) signal(SIGUSR1, SIG_IGN); /* dont muck w/DbgFp */
|
||||
(void) signal(SIGUSR2, SIG_IGN);
|
||||
} else {
|
||||
(void) fclose(stdin); /* dont need these */
|
||||
(void) fclose(stdout);
|
||||
|
||||
/*
|
||||
* Fork off a child to do the work & exit.
|
||||
*/
|
||||
switch(fork()) {
|
||||
case -1: /* fork failed */
|
||||
fprintf(stderr, "%s: ", ProgName);
|
||||
perror("fork");
|
||||
Exit(0);
|
||||
case 0: /* this is the CHILD */
|
||||
break;
|
||||
default: /* this is the PARENT */
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to disassociate from the current tty.
|
||||
*/
|
||||
{
|
||||
char *devtty = "/dev/tty";
|
||||
int i;
|
||||
|
||||
if ((i = open(devtty, O_RDWR)) < 0) {
|
||||
/* probably already disassociated */
|
||||
if (setpgrp(0, 0) < 0) {
|
||||
fprintf(stderr, "%s: ", ProgName);
|
||||
perror("setpgrp");
|
||||
}
|
||||
} else {
|
||||
if (ioctl(i, (u_long)TIOCNOTTY, (char *)0) < 0){
|
||||
fprintf(stderr, "%s: ", ProgName);
|
||||
perror("ioctl");
|
||||
}
|
||||
(void) close(i);
|
||||
}
|
||||
}
|
||||
|
||||
(void) signal(SIGUSR1, DebugOn);
|
||||
(void) signal(SIGUSR2, DebugOff);
|
||||
}
|
||||
|
||||
(void) fclose(stderr); /* finished with it */
|
||||
|
||||
#ifdef SYSLOG4_2
|
||||
openlog(ProgName, LOG_PID);
|
||||
#else
|
||||
openlog(ProgName, LOG_PID, LOG_DAEMON);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If no interface was specified, get one now.
|
||||
*
|
||||
* This is convoluted because we want to get the default interface
|
||||
* name for the syslog("restarted") message. If BpfGetIntfName()
|
||||
* runs into an error, it will return a syslog-able error message
|
||||
* (in `errmsg') which will be displayed here.
|
||||
*/
|
||||
if (IntfName == NULL) {
|
||||
char *errmsg;
|
||||
|
||||
if ((IntfName = BpfGetIntfName(&errmsg)) == NULL) {
|
||||
syslog(LOG_NOTICE, "restarted (??)");
|
||||
syslog(LOG_ERR, errmsg);
|
||||
Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
syslog(LOG_NOTICE, "restarted (%s)", IntfName);
|
||||
|
||||
(void) signal(SIGHUP, ReConfig);
|
||||
(void) signal(SIGINT, Exit);
|
||||
(void) signal(SIGTERM, Exit);
|
||||
|
||||
/*
|
||||
* Grab our host name and pid.
|
||||
*/
|
||||
if (gethostname(MyHost, MAXHOSTNAMELEN) < 0) {
|
||||
syslog(LOG_ERR, "gethostname: %m");
|
||||
Exit(0);
|
||||
}
|
||||
MyHost[MAXHOSTNAMELEN] = '\0';
|
||||
|
||||
MyPid = getpid();
|
||||
|
||||
/*
|
||||
* Write proc's pid to a file.
|
||||
*/
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen(PidFile, "w")) != NULL) {
|
||||
(void) fprintf(fp, "%d\n", MyPid);
|
||||
(void) fclose(fp);
|
||||
} else {
|
||||
syslog(LOG_WARNING, "fopen: failed (%s)", PidFile);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* All boot files are relative to the boot directory, we might
|
||||
* as well chdir() there to make life easier.
|
||||
*/
|
||||
if (chdir(BootDir) < 0) {
|
||||
syslog(LOG_ERR, "chdir: %m (%s)", BootDir);
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initial configuration.
|
||||
*/
|
||||
omask = sigblock(sigmask(SIGHUP)); /* prevent reconfig's */
|
||||
if (GetBootFiles() == 0) /* get list of boot files */
|
||||
Exit(0);
|
||||
if (ParseConfig() == 0) /* parse config file */
|
||||
Exit(0);
|
||||
|
||||
/*
|
||||
* Open and initialize a BPF device for the appropriate interface.
|
||||
* If an error is encountered, a message is displayed and Exit()
|
||||
* is called.
|
||||
*/
|
||||
fd = BpfOpen();
|
||||
|
||||
(void) sigsetmask(omask); /* allow reconfig's */
|
||||
|
||||
/*
|
||||
* Main loop: receive a packet, determine where it came from,
|
||||
* and if we service this host, call routine to handle request.
|
||||
*/
|
||||
maxfds = fd + 1;
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(fd, &rset);
|
||||
for (;;) {
|
||||
struct timeval timeout;
|
||||
fd_set r;
|
||||
int nsel;
|
||||
|
||||
r = rset;
|
||||
|
||||
if (RmpConns == NULL) { /* timeout isnt necessary */
|
||||
nsel = select(maxfds, &r, (fd_set *)0, (fd_set *)0,
|
||||
(struct timeval *)0);
|
||||
} else {
|
||||
timeout.tv_sec = RMP_TIMEOUT;
|
||||
timeout.tv_usec = 0;
|
||||
nsel = select(maxfds, &r, (fd_set *)0, (fd_set *)0,
|
||||
&timeout);
|
||||
}
|
||||
|
||||
if (nsel < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
syslog(LOG_ERR, "select: %m");
|
||||
Exit(0);
|
||||
} else if (nsel == 0) { /* timeout */
|
||||
DoTimeout(); /* clear stale conns */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FD_ISSET(fd, &r)) {
|
||||
RMPCONN rconn;
|
||||
CLIENT *client, *FindClient();
|
||||
int doread = 1;
|
||||
|
||||
while (BpfRead(&rconn, doread)) {
|
||||
doread = 0;
|
||||
|
||||
if (DbgFp != NULL) /* display packet */
|
||||
DispPkt(&rconn,DIR_RCVD);
|
||||
|
||||
omask = sigblock(sigmask(SIGHUP));
|
||||
|
||||
/*
|
||||
* If we do not restrict service, set the
|
||||
* client to NULL (ProcessPacket() handles
|
||||
* this). Otherwise, check that we can
|
||||
* service this host; if not, log a message
|
||||
* and ignore the packet.
|
||||
*/
|
||||
if (BootAny) {
|
||||
client = NULL;
|
||||
} else if ((client=FindClient(&rconn))==NULL) {
|
||||
syslog(LOG_INFO,
|
||||
"%s: boot packet ignored",
|
||||
EnetStr(&rconn));
|
||||
(void) sigsetmask(omask);
|
||||
continue;
|
||||
}
|
||||
|
||||
ProcessPacket(&rconn,client);
|
||||
|
||||
(void) sigsetmask(omask);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** DoTimeout -- Free any connections that have timed out.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Timed out connections in `RmpConns' will be freed.
|
||||
*/
|
||||
void
|
||||
DoTimeout()
|
||||
{
|
||||
register RMPCONN *rtmp;
|
||||
struct timeval now;
|
||||
|
||||
(void) gettimeofday(&now, (struct timezone *)0);
|
||||
|
||||
/*
|
||||
* For each active connection, if RMP_TIMEOUT seconds have passed
|
||||
* since the last packet was sent, delete the connection.
|
||||
*/
|
||||
for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next)
|
||||
if ((rtmp->tstamp.tv_sec + RMP_TIMEOUT) < now.tv_sec) {
|
||||
syslog(LOG_WARNING, "%s: connection timed out (%u)",
|
||||
EnetStr(rtmp), rtmp->rmp.r_type);
|
||||
RemoveConn(rtmp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** FindClient -- Find client associated with a packet.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - the new packet.
|
||||
**
|
||||
** Returns:
|
||||
** Pointer to client info if found, NULL otherwise.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
**
|
||||
** Warnings:
|
||||
** - This routine must be called with SIGHUP blocked since
|
||||
** a reconfigure can invalidate the information returned.
|
||||
*/
|
||||
|
||||
CLIENT *
|
||||
FindClient(rconn)
|
||||
register RMPCONN *rconn;
|
||||
{
|
||||
register CLIENT *ctmp;
|
||||
|
||||
for (ctmp = Clients; ctmp != NULL; ctmp = ctmp->next)
|
||||
if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0],
|
||||
(char *)&ctmp->addr[0], RMP_ADDRLEN) == 0)
|
||||
break;
|
||||
|
||||
return(ctmp);
|
||||
}
|
||||
|
||||
/*
|
||||
** Exit -- Log an error message and exit.
|
||||
**
|
||||
** Parameters:
|
||||
** sig - caught signal (or zero if not dying on a signal).
|
||||
**
|
||||
** Returns:
|
||||
** Does not return.
|
||||
**
|
||||
** Side Effects:
|
||||
** - This process ceases to exist.
|
||||
*/
|
||||
void
|
||||
Exit(sig)
|
||||
int sig;
|
||||
{
|
||||
if (sig > 0)
|
||||
syslog(LOG_ERR, "going down on signal %d", sig);
|
||||
else
|
||||
syslog(LOG_ERR, "going down with fatal error");
|
||||
BpfClose();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
** ReConfig -- Get new list of boot files and reread config files.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - All active connections are dropped.
|
||||
** - List of boot-able files is changed.
|
||||
** - List of clients is changed.
|
||||
**
|
||||
** Warnings:
|
||||
** - This routine must be called with SIGHUP blocked.
|
||||
*/
|
||||
void
|
||||
ReConfig(signo)
|
||||
int signo;
|
||||
{
|
||||
syslog(LOG_NOTICE, "reconfiguring boot server");
|
||||
|
||||
FreeConns();
|
||||
|
||||
if (GetBootFiles() == 0)
|
||||
Exit(0);
|
||||
|
||||
if (ParseConfig() == 0)
|
||||
Exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
** DebugOff -- Turn off debugging.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Debug file is closed.
|
||||
*/
|
||||
void
|
||||
DebugOff(signo)
|
||||
int signo;
|
||||
{
|
||||
if (DbgFp != NULL)
|
||||
(void) fclose(DbgFp);
|
||||
|
||||
DbgFp = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
** DebugOn -- Turn on debugging.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Debug file is opened/truncated if not already opened,
|
||||
** otherwise do nothing.
|
||||
*/
|
||||
void
|
||||
DebugOn(signo)
|
||||
int signo;
|
||||
{
|
||||
if (DbgFp == NULL) {
|
||||
if ((DbgFp = fopen(DbgFile, "w")) == NULL)
|
||||
syslog(LOG_ERR, "can't open debug file (%s)", DbgFile);
|
||||
}
|
||||
}
|
||||
95
libexec/rbootd/rmp.h
Normal file
95
libexec/rbootd/rmp.h
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)rmp.h 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: rmp.h 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define MIN/MAX sizes of RMP (ethernet) packet.
|
||||
* For ease of computation, the 4 octet CRC field is not included.
|
||||
*
|
||||
* MCLBYTES is for bpfwrite(); it is adamant about using a cluster.
|
||||
*/
|
||||
|
||||
#define RMP_MAX_PACKET MIN(1514,MCLBYTES)
|
||||
#define RMP_MIN_PACKET 60
|
||||
|
||||
/*
|
||||
* Define RMP/Ethernet Multicast address (9:0:9:0:0:4) and its length.
|
||||
*/
|
||||
#define RMP_ADDR { 0x9, 0x0, 0x9, 0x0, 0x0, 0x4 }
|
||||
#define RMP_ADDRLEN 6
|
||||
|
||||
/*
|
||||
* Define IEEE802.2 (Logical Link Control) information.
|
||||
*/
|
||||
#define IEEE_DSAP_HP 0xF8 /* Destination Service Access Point */
|
||||
#define IEEE_SSAP_HP 0xF8 /* Source Service Access Point */
|
||||
#define IEEE_CNTL_HP 0x0300 /* Type 1 / I format control information */
|
||||
|
||||
#define HPEXT_DXSAP 0x608 /* HP Destination Service Access Point */
|
||||
#define HPEXT_SXSAP 0x609 /* HP Source Service Access Point */
|
||||
|
||||
/*
|
||||
* 802.3-style "Ethernet" header.
|
||||
*/
|
||||
|
||||
struct hp_hdr {
|
||||
u_char daddr[RMP_ADDRLEN];
|
||||
u_char saddr[RMP_ADDRLEN];
|
||||
u_short len;
|
||||
};
|
||||
|
||||
/*
|
||||
* HP uses 802.2 LLC with their own local extensions. This struct makes
|
||||
* sence out of this data (encapsulated in the above 802.3 packet).
|
||||
*/
|
||||
|
||||
struct hp_llc {
|
||||
u_char dsap; /* 802.2 DSAP */
|
||||
u_char ssap; /* 802.2 SSAP */
|
||||
u_short cntrl; /* 802.2 control field */
|
||||
u_short filler; /* HP filler (must be zero) */
|
||||
u_short dxsap; /* HP extended DSAP */
|
||||
u_short sxsap; /* HP extended SSAP */
|
||||
};
|
||||
244
libexec/rbootd/rmp_var.h
Normal file
244
libexec/rbootd/rmp_var.h
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)rmp_var.h 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: rmp_var.h 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Possible values for "rmp_type" fields.
|
||||
*/
|
||||
|
||||
#define RMP_BOOT_REQ 1 /* boot request packet */
|
||||
#define RMP_BOOT_REPL 129 /* boot reply packet */
|
||||
#define RMP_READ_REQ 2 /* read request packet */
|
||||
#define RMP_READ_REPL 130 /* read reply packet */
|
||||
#define RMP_BOOT_DONE 3 /* boot complete packet */
|
||||
|
||||
/*
|
||||
* Useful constants.
|
||||
*/
|
||||
|
||||
#define RMP_VERSION 2 /* protocol version */
|
||||
#define RMP_TIMEOUT 600 /* timeout connection after ten minutes */
|
||||
#define RMP_PROBESID 0xffff /* session ID for probes */
|
||||
#define RMP_HOSTLEN 13 /* max length of server's name */
|
||||
#define RMP_MACHLEN 20 /* length of machine type field */
|
||||
|
||||
/*
|
||||
* RMP error codes
|
||||
*/
|
||||
|
||||
#define RMP_E_OKAY 0
|
||||
#define RMP_E_EOF 2 /* read reply: returned end of file */
|
||||
#define RMP_E_ABORT 3 /* abort operation */
|
||||
#define RMP_E_BUSY 4 /* boot reply: server busy */
|
||||
#define RMP_E_TIMEOUT 5 /* lengthen time out (not implemented) */
|
||||
#define RMP_E_NOFILE 16 /* boot reply: file does not exist */
|
||||
#define RMP_E_OPENFILE 17 /* boot reply: file open failed */
|
||||
#define RMP_E_NODFLT 18 /* boot reply: default file does not exist */
|
||||
#define RMP_E_OPENDFLT 19 /* boot reply: default file open failed */
|
||||
#define RMP_E_BADSID 25 /* read reply: bad session ID */
|
||||
#define RMP_E_BADPACKET 27 /* Bad packet detected */
|
||||
|
||||
/*
|
||||
* RMPDATALEN is the maximum number of data octets that can be stuffed
|
||||
* into an RMP packet. This excludes the 802.2 LLC w/HP extensions.
|
||||
*/
|
||||
#define RMPDATALEN (RMP_MAX_PACKET - (sizeof(struct hp_hdr) + \
|
||||
sizeof(struct hp_llc)))
|
||||
|
||||
/*
|
||||
* Define sizes of packets we send. Boot and Read replies are variable
|
||||
* in length depending on the length of `s'.
|
||||
*
|
||||
* Also, define how much space `restofpkt' can take up for outgoing
|
||||
* Boot and Read replies. Boot Request packets are effectively
|
||||
* limited to 255 bytes due to the preceding 1-byte length field.
|
||||
*/
|
||||
|
||||
#define RMPBOOTSIZE(s) (sizeof(struct hp_hdr) + sizeof(struct hp_llc) + \
|
||||
sizeof(struct rmp_boot_repl) + s - sizeof(restofpkt))
|
||||
#define RMPREADSIZE(s) (sizeof(struct hp_hdr) + sizeof(struct hp_llc) + \
|
||||
sizeof(struct rmp_read_repl) + s - sizeof(restofpkt) \
|
||||
- sizeof(u_char))
|
||||
#define RMPDONESIZE (sizeof(struct hp_hdr) + sizeof(struct hp_llc) + \
|
||||
sizeof(struct rmp_boot_done))
|
||||
#define RMPBOOTDATA 255
|
||||
#define RMPREADDATA (RMPDATALEN - \
|
||||
(2*sizeof(u_char)+sizeof(u_short)+sizeof(u_word)))
|
||||
|
||||
/*
|
||||
* This protocol defines some field sizes as "rest of ethernet packet".
|
||||
* There is no easy way to specify this in C, so we use a one character
|
||||
* field to denote it, and index past it to the end of the packet.
|
||||
*/
|
||||
|
||||
typedef char restofpkt;
|
||||
|
||||
/*
|
||||
* Due to the RMP packet layout, we'll run into alignment problems
|
||||
* on machines that cant access words on half-word boundaries. If
|
||||
* you know that your machine does not suffer from this problem,
|
||||
* add it to the hp300 #define below.
|
||||
*
|
||||
* The following macros are used to deal with this problem:
|
||||
* WORDZE(w) Return True if u_word `w' is zero, False otherwise.
|
||||
* ZEROWORD(w) Set u_word `w' to zero.
|
||||
* COPYWORD(w1,w2) Copy u_word `w1' to `w2'.
|
||||
* GETWORD(w,i) Copy u_word `w' into int `i'.
|
||||
* PUTWORD(i,w) Copy int `i' into u_word `w'.
|
||||
*
|
||||
* N.B. We do not support little endian alignment-challenged machines.
|
||||
*/
|
||||
#if defined(vax) || defined(tahoe) || defined(hp300)
|
||||
|
||||
typedef u_int u_word;
|
||||
|
||||
#define WORDZE(w) ((w) == 0)
|
||||
#define ZEROWORD(w) (w) = 0
|
||||
#define COPYWORD(w1,w2) (w2) = (w1)
|
||||
#define GETWORD(w, i) (i) = (w)
|
||||
#define PUTWORD(i, w) (w) = (i)
|
||||
|
||||
#else
|
||||
|
||||
#define _WORD_HIGHPART 0 /* XXX: assume Big Endian for now */
|
||||
#define _WORD_LOWPART 1
|
||||
|
||||
typedef struct _uword { u_short val[2]; } u_word;
|
||||
|
||||
#define WORDZE(w) \
|
||||
((w.val[_WORD_HIGHPART] == 0) && (w.val[_WORD_LOWPART] == 0))
|
||||
#define ZEROWORD(w) \
|
||||
(w).val[_WORD_HIGHPART] = (w).val[_WORD_LOWPART] = 0
|
||||
#define COPYWORD(w1, w2) \
|
||||
{ (w2).val[_WORD_HIGHPART] = (w1).val[_WORD_HIGHPART]; \
|
||||
(w2).val[_WORD_LOWPART] = (w1).val[_WORD_LOWPART]; \
|
||||
}
|
||||
#define GETWORD(w, i) \
|
||||
(i) = (((u_int)(w).val[_WORD_HIGHPART]) << 16) | (w).val[_WORD_LOWPART]
|
||||
#define PUTWORD(i, w) \
|
||||
{ (w).val[_WORD_HIGHPART] = (u_short) (((i) >> 16) & 0xffff); \
|
||||
(w).val[_WORD_LOWPART] = (u_short) (i & 0xffff); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Packet structures.
|
||||
*/
|
||||
|
||||
struct rmp_raw { /* generic RMP packet */
|
||||
u_char rmp_type; /* packet type */
|
||||
u_char rmp_rawdata[RMPDATALEN-1];
|
||||
};
|
||||
|
||||
struct rmp_boot_req { /* boot request */
|
||||
u_char rmp_type; /* packet type (RMP_BOOT_REQ) */
|
||||
u_char rmp_retcode; /* return code (0) */
|
||||
u_word rmp_seqno; /* sequence number (real time clock) */
|
||||
u_short rmp_session; /* session id (normally 0) */
|
||||
u_short rmp_version; /* protocol version (RMP_VERSION) */
|
||||
char rmp_machtype[RMP_MACHLEN]; /* machine type */
|
||||
u_char rmp_flnmsize; /* length of rmp_flnm */
|
||||
restofpkt rmp_flnm; /* name of file to be read */
|
||||
};
|
||||
|
||||
struct rmp_boot_repl { /* boot reply */
|
||||
u_char rmp_type; /* packet type (RMP_BOOT_REPL) */
|
||||
u_char rmp_retcode; /* return code (normally 0) */
|
||||
u_word rmp_seqno; /* sequence number (from boot req) */
|
||||
u_short rmp_session; /* session id (generated) */
|
||||
u_short rmp_version; /* protocol version (RMP_VERSION) */
|
||||
u_char rmp_flnmsize; /* length of rmp_flnm */
|
||||
restofpkt rmp_flnm; /* name of file (from boot req) */
|
||||
};
|
||||
|
||||
struct rmp_read_req { /* read request */
|
||||
u_char rmp_type; /* packet type (RMP_READ_REQ) */
|
||||
u_char rmp_retcode; /* return code (0) */
|
||||
u_word rmp_offset; /* file relative byte offset */
|
||||
u_short rmp_session; /* session id (from boot repl) */
|
||||
u_short rmp_size; /* max no of bytes to send */
|
||||
};
|
||||
|
||||
struct rmp_read_repl { /* read reply */
|
||||
u_char rmp_type; /* packet type (RMP_READ_REPL) */
|
||||
u_char rmp_retcode; /* return code (normally 0) */
|
||||
u_word rmp_offset; /* byte offset (from read req) */
|
||||
u_short rmp_session; /* session id (from read req) */
|
||||
restofpkt rmp_data; /* data (max size from read req) */
|
||||
u_char rmp_unused; /* padding to 16-bit boundary */
|
||||
};
|
||||
|
||||
struct rmp_boot_done { /* boot complete */
|
||||
u_char rmp_type; /* packet type (RMP_BOOT_DONE) */
|
||||
u_char rmp_retcode; /* return code (0) */
|
||||
u_word rmp_unused; /* not used (0) */
|
||||
u_short rmp_session; /* session id (from read repl) */
|
||||
};
|
||||
|
||||
struct rmp_packet {
|
||||
struct hp_hdr hp_hdr;
|
||||
struct hp_llc hp_llc;
|
||||
union {
|
||||
struct rmp_boot_req rmp_brq; /* boot request */
|
||||
struct rmp_boot_repl rmp_brpl; /* boot reply */
|
||||
struct rmp_read_req rmp_rrq; /* read request */
|
||||
struct rmp_read_repl rmp_rrpl; /* read reply */
|
||||
struct rmp_boot_done rmp_done; /* boot complete */
|
||||
struct rmp_raw rmp_raw; /* raw data */
|
||||
} rmp_proto;
|
||||
};
|
||||
|
||||
/*
|
||||
* Make life easier...
|
||||
*/
|
||||
|
||||
#define r_type rmp_proto.rmp_raw.rmp_type
|
||||
#define r_data rmp_proto.rmp_raw.rmp_data
|
||||
#define r_brq rmp_proto.rmp_brq
|
||||
#define r_brpl rmp_proto.rmp_brpl
|
||||
#define r_rrq rmp_proto.rmp_rrq
|
||||
#define r_rrpl rmp_proto.rmp_rrpl
|
||||
#define r_done rmp_proto.rmp_done
|
||||
593
libexec/rbootd/rmpproto.c
Normal file
593
libexec/rbootd/rmpproto.c
Normal file
|
|
@ -0,0 +1,593 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)rmpproto.c 8.1 (Berkeley) 6/4/93
|
||||
*
|
||||
* Utah $Hdr: rmpproto.c 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)rmpproto.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include "defs.h"
|
||||
|
||||
/*
|
||||
** ProcessPacket -- determine packet type and do what's required.
|
||||
**
|
||||
** An RMP BOOT packet has been received. Look at the type field
|
||||
** and process Boot Requests, Read Requests, and Boot Complete
|
||||
** packets. Any other type will be dropped with a warning msg.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - the new connection
|
||||
** client - list of files available to this host
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - If this is a valid boot request, it will be added to
|
||||
** the linked list of outstanding requests (RmpConns).
|
||||
** - If this is a valid boot complete, its associated
|
||||
** entry in RmpConns will be deleted.
|
||||
** - Also, unless we run out of memory, a reply will be
|
||||
** sent to the host that sent the packet.
|
||||
*/
|
||||
void
|
||||
ProcessPacket(rconn, client)
|
||||
RMPCONN *rconn;
|
||||
CLIENT *client;
|
||||
{
|
||||
struct rmp_packet *rmp;
|
||||
RMPCONN *rconnout;
|
||||
|
||||
rmp = &rconn->rmp; /* cache pointer to RMP packet */
|
||||
|
||||
switch(rmp->r_type) { /* do what we came here to do */
|
||||
case RMP_BOOT_REQ: /* boot request */
|
||||
if ((rconnout = NewConn(rconn)) == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If the Session ID is 0xffff, this is a "probe"
|
||||
* packet and we do not want to add the connection
|
||||
* to the linked list of active connections. There
|
||||
* are two types of probe packets, if the Sequence
|
||||
* Number is 0 they want to know our host name, o/w
|
||||
* they want the name of the file associated with
|
||||
* the number spec'd by the Sequence Number.
|
||||
*
|
||||
* If this is an actual boot request, open the file
|
||||
* and send a reply. If SendBootRepl() does not
|
||||
* return 0, add the connection to the linked list
|
||||
* of active connections, otherwise delete it since
|
||||
* an error was encountered.
|
||||
*/
|
||||
if (rmp->r_brq.rmp_session == RMP_PROBESID) {
|
||||
if (WORDZE(rmp->r_brq.rmp_seqno))
|
||||
(void) SendServerID(rconnout);
|
||||
else
|
||||
(void) SendFileNo(rmp, rconnout,
|
||||
client? client->files:
|
||||
BootFiles);
|
||||
FreeConn(rconnout);
|
||||
} else {
|
||||
if (SendBootRepl(rmp, rconnout,
|
||||
client? client->files: BootFiles))
|
||||
AddConn(rconnout);
|
||||
else
|
||||
FreeConn(rconnout);
|
||||
}
|
||||
break;
|
||||
|
||||
case RMP_BOOT_REPL: /* boot reply (not valid) */
|
||||
syslog(LOG_WARNING, "%s: sent a boot reply",
|
||||
EnetStr(rconn));
|
||||
break;
|
||||
|
||||
case RMP_READ_REQ: /* read request */
|
||||
/*
|
||||
* Send a portion of the boot file.
|
||||
*/
|
||||
(void) SendReadRepl(rconn);
|
||||
break;
|
||||
|
||||
case RMP_READ_REPL: /* read reply (not valid) */
|
||||
syslog(LOG_WARNING, "%s: sent a read reply",
|
||||
EnetStr(rconn));
|
||||
break;
|
||||
|
||||
case RMP_BOOT_DONE: /* boot complete */
|
||||
/*
|
||||
* Remove the entry from the linked list of active
|
||||
* connections.
|
||||
*/
|
||||
(void) BootDone(rconn);
|
||||
break;
|
||||
|
||||
default: /* unknown RMP packet type */
|
||||
syslog(LOG_WARNING, "%s: unknown packet type (%u)",
|
||||
EnetStr(rconn), rmp->r_type);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** SendServerID -- send our host name to who ever requested it.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - the reply packet to be formatted.
|
||||
**
|
||||
** Returns:
|
||||
** 1 on success, 0 on failure.
|
||||
**
|
||||
** Side Effects:
|
||||
** none.
|
||||
*/
|
||||
int
|
||||
SendServerID(rconn)
|
||||
RMPCONN *rconn;
|
||||
{
|
||||
register struct rmp_packet *rpl;
|
||||
register char *src, *dst;
|
||||
register u_char *size;
|
||||
|
||||
rpl = &rconn->rmp; /* cache ptr to RMP packet */
|
||||
|
||||
/*
|
||||
* Set up assorted fields in reply packet.
|
||||
*/
|
||||
rpl->r_brpl.rmp_type = RMP_BOOT_REPL;
|
||||
rpl->r_brpl.rmp_retcode = RMP_E_OKAY;
|
||||
ZEROWORD(rpl->r_brpl.rmp_seqno);
|
||||
rpl->r_brpl.rmp_session = 0;
|
||||
rpl->r_brpl.rmp_version = RMP_VERSION;
|
||||
|
||||
size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of host name */
|
||||
|
||||
/*
|
||||
* Copy our host name into the reply packet incrementing the
|
||||
* length as we go. Stop at RMP_HOSTLEN or the first dot.
|
||||
*/
|
||||
src = MyHost;
|
||||
dst = (char *) &rpl->r_brpl.rmp_flnm;
|
||||
for (*size = 0; *size < RMP_HOSTLEN; (*size)++) {
|
||||
if (*src == '.' || *src == '\0')
|
||||
break;
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */
|
||||
|
||||
return(SendPacket(rconn)); /* send packet */
|
||||
}
|
||||
|
||||
/*
|
||||
** SendFileNo -- send the name of a bootable file to the requester.
|
||||
**
|
||||
** Parameters:
|
||||
** req - RMP BOOT packet containing the request.
|
||||
** rconn - the reply packet to be formatted.
|
||||
** filelist - list of files available to the requester.
|
||||
**
|
||||
** Returns:
|
||||
** 1 on success, 0 on failure.
|
||||
**
|
||||
** Side Effects:
|
||||
** none.
|
||||
*/
|
||||
int
|
||||
SendFileNo(req, rconn, filelist)
|
||||
struct rmp_packet *req;
|
||||
RMPCONN *rconn;
|
||||
char *filelist[];
|
||||
{
|
||||
register struct rmp_packet *rpl;
|
||||
register char *src, *dst;
|
||||
register u_char *size, i;
|
||||
|
||||
GETWORD(req->r_brpl.rmp_seqno, i); /* SeqNo is really FileNo */
|
||||
rpl = &rconn->rmp; /* cache ptr to RMP packet */
|
||||
|
||||
/*
|
||||
* Set up assorted fields in reply packet.
|
||||
*/
|
||||
rpl->r_brpl.rmp_type = RMP_BOOT_REPL;
|
||||
PUTWORD(i, rpl->r_brpl.rmp_seqno);
|
||||
i--;
|
||||
rpl->r_brpl.rmp_session = 0;
|
||||
rpl->r_brpl.rmp_version = RMP_VERSION;
|
||||
|
||||
size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of filename */
|
||||
*size = 0; /* init length to zero */
|
||||
|
||||
/*
|
||||
* Copy the file name into the reply packet incrementing the
|
||||
* length as we go. Stop at end of string or when RMPBOOTDATA
|
||||
* characters have been copied. Also, set return code to
|
||||
* indicate success or "no more files".
|
||||
*/
|
||||
if (i < C_MAXFILE && filelist[i] != NULL) {
|
||||
src = filelist[i];
|
||||
dst = (char *)&rpl->r_brpl.rmp_flnm;
|
||||
for (; *src && *size < RMPBOOTDATA; (*size)++) {
|
||||
if (*src == '\0')
|
||||
break;
|
||||
*dst++ = *src++;
|
||||
}
|
||||
rpl->r_brpl.rmp_retcode = RMP_E_OKAY;
|
||||
} else
|
||||
rpl->r_brpl.rmp_retcode = RMP_E_NODFLT;
|
||||
|
||||
rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */
|
||||
|
||||
return(SendPacket(rconn)); /* send packet */
|
||||
}
|
||||
|
||||
/*
|
||||
** SendBootRepl -- open boot file and respond to boot request.
|
||||
**
|
||||
** Parameters:
|
||||
** req - RMP BOOT packet containing the request.
|
||||
** rconn - the reply packet to be formatted.
|
||||
** filelist - list of files available to the requester.
|
||||
**
|
||||
** Returns:
|
||||
** 1 on success, 0 on failure.
|
||||
**
|
||||
** Side Effects:
|
||||
** none.
|
||||
*/
|
||||
int
|
||||
SendBootRepl(req, rconn, filelist)
|
||||
struct rmp_packet *req;
|
||||
RMPCONN *rconn;
|
||||
char *filelist[];
|
||||
{
|
||||
int retval;
|
||||
char *filename, filepath[RMPBOOTDATA+1];
|
||||
RMPCONN *oldconn;
|
||||
register struct rmp_packet *rpl;
|
||||
register char *src, *dst1, *dst2;
|
||||
register u_char i;
|
||||
|
||||
/*
|
||||
* If another connection already exists, delete it since we
|
||||
* are obviously starting again.
|
||||
*/
|
||||
if ((oldconn = FindConn(rconn)) != NULL) {
|
||||
syslog(LOG_WARNING, "%s: dropping existing connection",
|
||||
EnetStr(oldconn));
|
||||
RemoveConn(oldconn);
|
||||
}
|
||||
|
||||
rpl = &rconn->rmp; /* cache ptr to RMP packet */
|
||||
|
||||
/*
|
||||
* Set up assorted fields in reply packet.
|
||||
*/
|
||||
rpl->r_brpl.rmp_type = RMP_BOOT_REPL;
|
||||
COPYWORD(req->r_brq.rmp_seqno, rpl->r_brpl.rmp_seqno);
|
||||
rpl->r_brpl.rmp_session = GenSessID();
|
||||
rpl->r_brpl.rmp_version = RMP_VERSION;
|
||||
rpl->r_brpl.rmp_flnmsize = req->r_brq.rmp_flnmsize;
|
||||
|
||||
/*
|
||||
* Copy file name to `filepath' string, and into reply packet.
|
||||
*/
|
||||
src = &req->r_brq.rmp_flnm;
|
||||
dst1 = filepath;
|
||||
dst2 = &rpl->r_brpl.rmp_flnm;
|
||||
for (i = 0; i < req->r_brq.rmp_flnmsize; i++)
|
||||
*dst1++ = *dst2++ = *src++;
|
||||
*dst1 = '\0';
|
||||
|
||||
/*
|
||||
* If we are booting HP-UX machines, their secondary loader will
|
||||
* ask for files like "/hp-ux". As a security measure, we do not
|
||||
* allow boot files to lay outside the boot directory (unless they
|
||||
* are purposely link'd out. So, make `filename' become the path-
|
||||
* stripped file name and spoof the client into thinking that it
|
||||
* really got what it wanted.
|
||||
*/
|
||||
filename = (filename = rindex(filepath,'/'))? ++filename: filepath;
|
||||
|
||||
/*
|
||||
* Check that this is a valid boot file name.
|
||||
*/
|
||||
for (i = 0; i < C_MAXFILE && filelist[i] != NULL; i++)
|
||||
if (STREQN(filename, filelist[i]))
|
||||
goto match;
|
||||
|
||||
/*
|
||||
* Invalid boot file name, set error and send reply packet.
|
||||
*/
|
||||
rpl->r_brpl.rmp_retcode = RMP_E_NOFILE;
|
||||
retval = 0;
|
||||
goto sendpkt;
|
||||
|
||||
match:
|
||||
/*
|
||||
* This is a valid boot file. Open the file and save the file
|
||||
* descriptor associated with this connection and set success
|
||||
* indication. If the file couldnt be opened, set error:
|
||||
* "no such file or dir" - RMP_E_NOFILE
|
||||
* "file table overflow" - RMP_E_BUSY
|
||||
* "too many open files" - RMP_E_BUSY
|
||||
* anything else - RMP_E_OPENFILE
|
||||
*/
|
||||
if ((rconn->bootfd = open(filename, O_RDONLY, 0600)) < 0) {
|
||||
rpl->r_brpl.rmp_retcode = (errno == ENOENT)? RMP_E_NOFILE:
|
||||
(errno == EMFILE || errno == ENFILE)? RMP_E_BUSY:
|
||||
RMP_E_OPENFILE;
|
||||
retval = 0;
|
||||
} else {
|
||||
rpl->r_brpl.rmp_retcode = RMP_E_OKAY;
|
||||
retval = 1;
|
||||
}
|
||||
|
||||
sendpkt:
|
||||
syslog(LOG_INFO, "%s: request to boot %s (%s)",
|
||||
EnetStr(rconn), filename, retval? "granted": "denied");
|
||||
|
||||
rconn->rmplen = RMPBOOTSIZE(rpl->r_brpl.rmp_flnmsize);
|
||||
|
||||
return (retval & SendPacket(rconn));
|
||||
}
|
||||
|
||||
/*
|
||||
** SendReadRepl -- send a portion of the boot file to the requester.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - the reply packet to be formatted.
|
||||
**
|
||||
** Returns:
|
||||
** 1 on success, 0 on failure.
|
||||
**
|
||||
** Side Effects:
|
||||
** none.
|
||||
*/
|
||||
int
|
||||
SendReadRepl(rconn)
|
||||
RMPCONN *rconn;
|
||||
{
|
||||
int retval;
|
||||
RMPCONN *oldconn;
|
||||
register struct rmp_packet *rpl, *req;
|
||||
register int size = 0;
|
||||
int madeconn = 0;
|
||||
|
||||
/*
|
||||
* Find the old connection. If one doesnt exist, create one only
|
||||
* to return the error code.
|
||||
*/
|
||||
if ((oldconn = FindConn(rconn)) == NULL) {
|
||||
if ((oldconn = NewConn(rconn)) == NULL)
|
||||
return(0);
|
||||
syslog(LOG_ERR, "SendReadRepl: no active connection (%s)",
|
||||
EnetStr(rconn));
|
||||
madeconn++;
|
||||
}
|
||||
|
||||
req = &rconn->rmp; /* cache ptr to request packet */
|
||||
rpl = &oldconn->rmp; /* cache ptr to reply packet */
|
||||
|
||||
if (madeconn) { /* no active connection above; abort */
|
||||
rpl->r_rrpl.rmp_retcode = RMP_E_ABORT;
|
||||
retval = 1;
|
||||
goto sendpkt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure Session ID's match.
|
||||
*/
|
||||
if (req->r_rrq.rmp_session !=
|
||||
((rpl->r_type == RMP_BOOT_REPL)? rpl->r_brpl.rmp_session:
|
||||
rpl->r_rrpl.rmp_session)) {
|
||||
syslog(LOG_ERR, "SendReadRepl: bad session id (%s)",
|
||||
EnetStr(rconn));
|
||||
rpl->r_rrpl.rmp_retcode = RMP_E_BADSID;
|
||||
retval = 1;
|
||||
goto sendpkt;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the requester asks for more data than we can fit,
|
||||
* silently clamp the request size down to RMPREADDATA.
|
||||
*
|
||||
* N.B. I do not know if this is "legal", however it seems
|
||||
* to work. This is necessary for bpfwrite() on machines
|
||||
* with MCLBYTES less than 1514.
|
||||
*/
|
||||
if (req->r_rrq.rmp_size > RMPREADDATA)
|
||||
req->r_rrq.rmp_size = RMPREADDATA;
|
||||
|
||||
/*
|
||||
* Position read head on file according to info in request packet.
|
||||
*/
|
||||
GETWORD(req->r_rrq.rmp_offset, size);
|
||||
if (lseek(oldconn->bootfd, (off_t)size, L_SET) < 0) {
|
||||
syslog(LOG_ERR, "SendReadRepl: lseek: %m (%s)",
|
||||
EnetStr(rconn));
|
||||
rpl->r_rrpl.rmp_retcode = RMP_E_ABORT;
|
||||
retval = 1;
|
||||
goto sendpkt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read data directly into reply packet.
|
||||
*/
|
||||
if ((size = read(oldconn->bootfd, &rpl->r_rrpl.rmp_data,
|
||||
(int) req->r_rrq.rmp_size)) <= 0) {
|
||||
if (size < 0) {
|
||||
syslog(LOG_ERR, "SendReadRepl: read: %m (%s)",
|
||||
EnetStr(rconn));
|
||||
rpl->r_rrpl.rmp_retcode = RMP_E_ABORT;
|
||||
} else {
|
||||
rpl->r_rrpl.rmp_retcode = RMP_E_EOF;
|
||||
}
|
||||
retval = 1;
|
||||
goto sendpkt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set success indication.
|
||||
*/
|
||||
rpl->r_rrpl.rmp_retcode = RMP_E_OKAY;
|
||||
|
||||
sendpkt:
|
||||
/*
|
||||
* Set up assorted fields in reply packet.
|
||||
*/
|
||||
rpl->r_rrpl.rmp_type = RMP_READ_REPL;
|
||||
COPYWORD(req->r_rrq.rmp_offset, rpl->r_rrpl.rmp_offset);
|
||||
rpl->r_rrpl.rmp_session = req->r_rrq.rmp_session;
|
||||
|
||||
oldconn->rmplen = RMPREADSIZE(size); /* set size of packet */
|
||||
|
||||
retval &= SendPacket(oldconn); /* send packet */
|
||||
|
||||
if (madeconn) /* clean up after ourself */
|
||||
FreeConn(oldconn);
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/*
|
||||
** BootDone -- free up memory allocated for a connection.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - incoming boot complete packet.
|
||||
**
|
||||
** Returns:
|
||||
** 1 on success, 0 on failure.
|
||||
**
|
||||
** Side Effects:
|
||||
** none.
|
||||
*/
|
||||
int
|
||||
BootDone(rconn)
|
||||
RMPCONN *rconn;
|
||||
{
|
||||
RMPCONN *oldconn;
|
||||
struct rmp_packet *rpl;
|
||||
|
||||
/*
|
||||
* If we cant find the connection, ignore the request.
|
||||
*/
|
||||
if ((oldconn = FindConn(rconn)) == NULL) {
|
||||
syslog(LOG_ERR, "BootDone: no existing connection (%s)",
|
||||
EnetStr(rconn));
|
||||
return(0);
|
||||
}
|
||||
|
||||
rpl = &oldconn->rmp; /* cache ptr to RMP packet */
|
||||
|
||||
/*
|
||||
* Make sure Session ID's match.
|
||||
*/
|
||||
if (rconn->rmp.r_rrq.rmp_session !=
|
||||
((rpl->r_type == RMP_BOOT_REPL)? rpl->r_brpl.rmp_session:
|
||||
rpl->r_rrpl.rmp_session)) {
|
||||
syslog(LOG_ERR, "BootDone: bad session id (%s)",
|
||||
EnetStr(rconn));
|
||||
return(0);
|
||||
}
|
||||
|
||||
RemoveConn(oldconn); /* remove connection */
|
||||
|
||||
syslog(LOG_INFO, "%s: boot complete", EnetStr(rconn));
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
** SendPacket -- send an RMP packet to a remote host.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - packet to be sent.
|
||||
**
|
||||
** Returns:
|
||||
** 1 on success, 0 on failure.
|
||||
**
|
||||
** Side Effects:
|
||||
** none.
|
||||
*/
|
||||
int
|
||||
SendPacket(rconn)
|
||||
register RMPCONN *rconn;
|
||||
{
|
||||
/*
|
||||
* Set Ethernet Destination address to Source (BPF and the enet
|
||||
* driver will take care of getting our source address set).
|
||||
*/
|
||||
bcopy((char *)&rconn->rmp.hp_hdr.saddr[0],
|
||||
(char *)&rconn->rmp.hp_hdr.daddr[0], RMP_ADDRLEN);
|
||||
rconn->rmp.hp_hdr.len = rconn->rmplen - sizeof(struct hp_hdr);
|
||||
|
||||
/*
|
||||
* Reverse 802.2/HP Extended Source & Destination Access Pts.
|
||||
*/
|
||||
rconn->rmp.hp_llc.dxsap = HPEXT_SXSAP;
|
||||
rconn->rmp.hp_llc.sxsap = HPEXT_DXSAP;
|
||||
|
||||
/*
|
||||
* Last time this connection was active.
|
||||
*/
|
||||
(void) gettimeofday(&rconn->tstamp, (struct timezone *)0);
|
||||
|
||||
if (DbgFp != NULL) /* display packet */
|
||||
DispPkt(rconn,DIR_SENT);
|
||||
|
||||
/*
|
||||
* Send RMP packet to remote host.
|
||||
*/
|
||||
return(BpfWrite(rconn));
|
||||
}
|
||||
557
libexec/rbootd/utils.c
Normal file
557
libexec/rbootd/utils.c
Normal file
|
|
@ -0,0 +1,557 @@
|
|||
/*
|
||||
* Copyright (c) 1988, 1992 The University of Utah and the Center
|
||||
* for Software Science (CSS).
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Center for Software Science of the University of Utah Computer
|
||||
* Science Department. CSS requests users of this software to return
|
||||
* to css-dist@cs.utah.edu any improvements that they make and grant
|
||||
* CSS redistribution rights.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)utils.c 8.2 (Berkeley) 2/22/94
|
||||
*
|
||||
* Utah $Hdr: utils.c 3.1 92/07/06$
|
||||
* Author: Jeff Forys, University of Utah CSS
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)utils.c 8.2 (Berkeley) 2/22/94";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include "defs.h"
|
||||
|
||||
/*
|
||||
** DispPkt -- Display the contents of an RMPCONN packet.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - packet to be displayed.
|
||||
** direct - direction packet is going (DIR_*).
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
*/
|
||||
void
|
||||
DispPkt(rconn, direct)
|
||||
RMPCONN *rconn;
|
||||
int direct;
|
||||
{
|
||||
static char BootFmt[] = "\t\tRetCode:%u SeqNo:%lx SessID:%x Vers:%u";
|
||||
static char ReadFmt[] = "\t\tRetCode:%u Offset:%lx SessID:%x\n";
|
||||
|
||||
struct tm *tmp;
|
||||
register struct rmp_packet *rmp;
|
||||
int i, omask;
|
||||
u_int t;
|
||||
|
||||
/*
|
||||
* Since we will be working with RmpConns as well as DbgFp, we
|
||||
* must block signals that can affect either.
|
||||
*/
|
||||
omask = sigblock(sigmask(SIGHUP)|sigmask(SIGUSR1)|sigmask(SIGUSR2));
|
||||
|
||||
if (DbgFp == NULL) { /* sanity */
|
||||
(void) sigsetmask(omask);
|
||||
return;
|
||||
}
|
||||
|
||||
/* display direction packet is going using '>>>' or '<<<' */
|
||||
fputs((direct==DIR_RCVD)?"<<< ":(direct==DIR_SENT)?">>> ":"", DbgFp);
|
||||
|
||||
/* display packet timestamp */
|
||||
tmp = localtime((time_t *)&rconn->tstamp.tv_sec);
|
||||
fprintf(DbgFp, "%02d:%02d:%02d.%06ld ", tmp->tm_hour, tmp->tm_min,
|
||||
tmp->tm_sec, rconn->tstamp.tv_usec);
|
||||
|
||||
/* display src or dst addr and information about network interface */
|
||||
fprintf(DbgFp, "Addr: %s Intf: %s\n", EnetStr(rconn), IntfName);
|
||||
|
||||
rmp = &rconn->rmp;
|
||||
|
||||
/* display IEEE 802.2 Logical Link Control header */
|
||||
(void) fprintf(DbgFp, "\t802.2 LLC: DSAP:%x SSAP:%x CTRL:%x\n",
|
||||
rmp->hp_llc.dsap, rmp->hp_llc.ssap, rmp->hp_llc.cntrl);
|
||||
|
||||
/* display HP extensions to 802.2 Logical Link Control header */
|
||||
(void) fprintf(DbgFp, "\tHP Ext: DXSAP:%x SXSAP:%x\n",
|
||||
rmp->hp_llc.dxsap, rmp->hp_llc.sxsap);
|
||||
|
||||
/*
|
||||
* Display information about RMP packet using type field to
|
||||
* determine what kind of packet this is.
|
||||
*/
|
||||
switch(rmp->r_type) {
|
||||
case RMP_BOOT_REQ: /* boot request */
|
||||
(void) fprintf(DbgFp, "\tBoot Request:");
|
||||
GETWORD(rmp->r_brq.rmp_seqno, t);
|
||||
if (rmp->r_brq.rmp_session == RMP_PROBESID) {
|
||||
if (WORDZE(rmp->r_brq.rmp_seqno))
|
||||
fputs(" (Send Server ID)", DbgFp);
|
||||
else
|
||||
fprintf(DbgFp," (Send Filename #%u)",t);
|
||||
}
|
||||
(void) fputc('\n', DbgFp);
|
||||
(void) fprintf(DbgFp, BootFmt, rmp->r_brq.rmp_retcode,
|
||||
t, rmp->r_brq.rmp_session,
|
||||
rmp->r_brq.rmp_version);
|
||||
(void) fprintf(DbgFp, "\n\t\tMachine Type: ");
|
||||
for (i = 0; i < RMP_MACHLEN; i++)
|
||||
(void) fputc(rmp->r_brq.rmp_machtype[i], DbgFp);
|
||||
DspFlnm(rmp->r_brq.rmp_flnmsize, &rmp->r_brq.rmp_flnm);
|
||||
break;
|
||||
case RMP_BOOT_REPL: /* boot reply */
|
||||
fprintf(DbgFp, "\tBoot Reply:\n");
|
||||
GETWORD(rmp->r_brpl.rmp_seqno, t);
|
||||
(void) fprintf(DbgFp, BootFmt, rmp->r_brpl.rmp_retcode,
|
||||
t, rmp->r_brpl.rmp_session,
|
||||
rmp->r_brpl.rmp_version);
|
||||
DspFlnm(rmp->r_brpl.rmp_flnmsize,&rmp->r_brpl.rmp_flnm);
|
||||
break;
|
||||
case RMP_READ_REQ: /* read request */
|
||||
(void) fprintf(DbgFp, "\tRead Request:\n");
|
||||
GETWORD(rmp->r_rrq.rmp_offset, t);
|
||||
(void) fprintf(DbgFp, ReadFmt, rmp->r_rrq.rmp_retcode,
|
||||
t, rmp->r_rrq.rmp_session);
|
||||
(void) fprintf(DbgFp, "\t\tNoOfBytes: %u\n",
|
||||
rmp->r_rrq.rmp_size);
|
||||
break;
|
||||
case RMP_READ_REPL: /* read reply */
|
||||
(void) fprintf(DbgFp, "\tRead Reply:\n");
|
||||
GETWORD(rmp->r_rrpl.rmp_offset, t);
|
||||
(void) fprintf(DbgFp, ReadFmt, rmp->r_rrpl.rmp_retcode,
|
||||
t, rmp->r_rrpl.rmp_session);
|
||||
(void) fprintf(DbgFp, "\t\tNoOfBytesSent: %d\n",
|
||||
rconn->rmplen - RMPREADSIZE(0));
|
||||
break;
|
||||
case RMP_BOOT_DONE: /* boot complete */
|
||||
(void) fprintf(DbgFp, "\tBoot Complete:\n");
|
||||
(void) fprintf(DbgFp, "\t\tRetCode:%u SessID:%x\n",
|
||||
rmp->r_done.rmp_retcode,
|
||||
rmp->r_done.rmp_session);
|
||||
break;
|
||||
default: /* ??? */
|
||||
(void) fprintf(DbgFp, "\tUnknown Type:(%d)\n",
|
||||
rmp->r_type);
|
||||
}
|
||||
(void) fputc('\n', DbgFp);
|
||||
(void) fflush(DbgFp);
|
||||
|
||||
(void) sigsetmask(omask); /* reset old signal mask */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** GetEtherAddr -- convert an RMP (Ethernet) address into a string.
|
||||
**
|
||||
** An RMP BOOT packet has been received. Look at the type field
|
||||
** and process Boot Requests, Read Requests, and Boot Complete
|
||||
** packets. Any other type will be dropped with a warning msg.
|
||||
**
|
||||
** Parameters:
|
||||
** addr - array of RMP_ADDRLEN bytes.
|
||||
**
|
||||
** Returns:
|
||||
** Pointer to static string representation of `addr'.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
**
|
||||
** Warnings:
|
||||
** - The return value points to a static buffer; it must
|
||||
** be copied if it's to be saved.
|
||||
** - For speed, we assume a u_char consists of 8 bits.
|
||||
*/
|
||||
char *
|
||||
GetEtherAddr(addr)
|
||||
u_char *addr;
|
||||
{
|
||||
static char Hex[] = "0123456789abcdef";
|
||||
static char etherstr[RMP_ADDRLEN*3];
|
||||
register int i;
|
||||
register char *cp1, *cp2;
|
||||
|
||||
/*
|
||||
* For each byte in `addr', convert it to "<hexchar><hexchar>:".
|
||||
* The last byte does not get a trailing `:' appended.
|
||||
*/
|
||||
i = 0;
|
||||
cp1 = (char *)addr;
|
||||
cp2 = etherstr;
|
||||
for(;;) {
|
||||
*cp2++ = Hex[*cp1 >> 4 & 0xf];
|
||||
*cp2++ = Hex[*cp1++ & 0xf];
|
||||
if (++i == RMP_ADDRLEN)
|
||||
break;
|
||||
*cp2++ = ':';
|
||||
}
|
||||
*cp2 = '\0';
|
||||
|
||||
return(etherstr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** DispFlnm -- Print a string of bytes to DbgFp (often, a file name).
|
||||
**
|
||||
** Parameters:
|
||||
** size - number of bytes to print.
|
||||
** flnm - address of first byte.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Characters are sent to `DbgFp'.
|
||||
*/
|
||||
void
|
||||
DspFlnm(size, flnm)
|
||||
register u_int size;
|
||||
register char *flnm;
|
||||
{
|
||||
register int i;
|
||||
|
||||
(void) fprintf(DbgFp, "\n\t\tFile Name (%d): <", size);
|
||||
for (i = 0; i < size; i++)
|
||||
(void) fputc(*flnm++, DbgFp);
|
||||
(void) fputs(">\n", DbgFp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** NewClient -- allocate memory for a new CLIENT.
|
||||
**
|
||||
** Parameters:
|
||||
** addr - RMP (Ethernet) address of new client.
|
||||
**
|
||||
** Returns:
|
||||
** Ptr to new CLIENT or NULL if we ran out of memory.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Memory will be malloc'd for the new CLIENT.
|
||||
** - If malloc() fails, a log message will be generated.
|
||||
*/
|
||||
CLIENT *
|
||||
NewClient(addr)
|
||||
u_char *addr;
|
||||
{
|
||||
CLIENT *ctmp;
|
||||
|
||||
if ((ctmp = (CLIENT *) malloc(sizeof(CLIENT))) == NULL) {
|
||||
syslog(LOG_ERR, "NewClient: out of memory (%s)",
|
||||
GetEtherAddr(addr));
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
bzero(ctmp, sizeof(CLIENT));
|
||||
bcopy(addr, &ctmp->addr[0], RMP_ADDRLEN);
|
||||
return(ctmp);
|
||||
}
|
||||
|
||||
/*
|
||||
** FreeClient -- free linked list of Clients.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - All malloc'd memory associated with the linked list of
|
||||
** CLIENTS will be free'd; `Clients' will be set to NULL.
|
||||
**
|
||||
** Warnings:
|
||||
** - This routine must be called with SIGHUP blocked.
|
||||
*/
|
||||
void
|
||||
FreeClients()
|
||||
{
|
||||
register CLIENT *ctmp;
|
||||
|
||||
while (Clients != NULL) {
|
||||
ctmp = Clients;
|
||||
Clients = Clients->next;
|
||||
FreeClient(ctmp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** NewStr -- allocate memory for a character array.
|
||||
**
|
||||
** Parameters:
|
||||
** str - null terminated character array.
|
||||
**
|
||||
** Returns:
|
||||
** Ptr to new character array or NULL if we ran out of memory.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Memory will be malloc'd for the new character array.
|
||||
** - If malloc() fails, a log message will be generated.
|
||||
*/
|
||||
char *
|
||||
NewStr(str)
|
||||
char *str;
|
||||
{
|
||||
char *stmp;
|
||||
|
||||
if ((stmp = (char *)malloc((unsigned) (strlen(str)+1))) == NULL) {
|
||||
syslog(LOG_ERR, "NewStr: out of memory (%s)", str);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
(void) strcpy(stmp, str);
|
||||
return(stmp);
|
||||
}
|
||||
|
||||
/*
|
||||
** To save time, NewConn and FreeConn maintain a cache of one RMPCONN
|
||||
** in `LastFree' (defined below).
|
||||
*/
|
||||
|
||||
static RMPCONN *LastFree = NULL;
|
||||
|
||||
/*
|
||||
** NewConn -- allocate memory for a new RMPCONN connection.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - initialization template for new connection.
|
||||
**
|
||||
** Returns:
|
||||
** Ptr to new RMPCONN or NULL if we ran out of memory.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Memory may be malloc'd for the new RMPCONN (if not cached).
|
||||
** - If malloc() fails, a log message will be generated.
|
||||
*/
|
||||
RMPCONN *
|
||||
NewConn(rconn)
|
||||
RMPCONN *rconn;
|
||||
{
|
||||
RMPCONN *rtmp;
|
||||
|
||||
if (LastFree == NULL) { /* nothing cached; make a new one */
|
||||
if ((rtmp = (RMPCONN *) malloc(sizeof(RMPCONN))) == NULL) {
|
||||
syslog(LOG_ERR, "NewConn: out of memory (%s)",
|
||||
EnetStr(rconn));
|
||||
return(NULL);
|
||||
}
|
||||
} else { /* use the cached RMPCONN */
|
||||
rtmp = LastFree;
|
||||
LastFree = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy template into `rtmp', init file descriptor to `-1' and
|
||||
* set ptr to next elem NULL.
|
||||
*/
|
||||
bcopy((char *)rconn, (char *)rtmp, sizeof(RMPCONN));
|
||||
rtmp->bootfd = -1;
|
||||
rtmp->next = NULL;
|
||||
|
||||
return(rtmp);
|
||||
}
|
||||
|
||||
/*
|
||||
** FreeConn -- Free memory associated with an RMPCONN connection.
|
||||
**
|
||||
** Parameters:
|
||||
** rtmp - ptr to RMPCONN to be free'd.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - Memory associated with `rtmp' may be free'd (or cached).
|
||||
** - File desc associated with `rtmp->bootfd' will be closed.
|
||||
*/
|
||||
void
|
||||
FreeConn(rtmp)
|
||||
register RMPCONN *rtmp;
|
||||
{
|
||||
/*
|
||||
* If the file descriptor is in use, close the file.
|
||||
*/
|
||||
if (rtmp->bootfd >= 0) {
|
||||
(void) close(rtmp->bootfd);
|
||||
rtmp->bootfd = -1;
|
||||
}
|
||||
|
||||
if (LastFree == NULL) /* cache for next time */
|
||||
rtmp = LastFree;
|
||||
else /* already one cached; free this one */
|
||||
free((char *)rtmp);
|
||||
}
|
||||
|
||||
/*
|
||||
** FreeConns -- free linked list of RMPCONN connections.
|
||||
**
|
||||
** Parameters:
|
||||
** None.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - All malloc'd memory associated with the linked list of
|
||||
** connections will be free'd; `RmpConns' will be set to NULL.
|
||||
** - If LastFree is != NULL, it too will be free'd & NULL'd.
|
||||
**
|
||||
** Warnings:
|
||||
** - This routine must be called with SIGHUP blocked.
|
||||
*/
|
||||
void
|
||||
FreeConns()
|
||||
{
|
||||
register RMPCONN *rtmp;
|
||||
|
||||
while (RmpConns != NULL) {
|
||||
rtmp = RmpConns;
|
||||
RmpConns = RmpConns->next;
|
||||
FreeConn(rtmp);
|
||||
}
|
||||
|
||||
if (LastFree != NULL) {
|
||||
free((char *)LastFree);
|
||||
LastFree = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** AddConn -- Add a connection to the linked list of connections.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - connection to be added.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - RmpConn will point to new connection.
|
||||
**
|
||||
** Warnings:
|
||||
** - This routine must be called with SIGHUP blocked.
|
||||
*/
|
||||
void
|
||||
AddConn(rconn)
|
||||
register RMPCONN *rconn;
|
||||
{
|
||||
if (RmpConns != NULL)
|
||||
rconn->next = RmpConns;
|
||||
RmpConns = rconn;
|
||||
}
|
||||
|
||||
/*
|
||||
** FindConn -- Find a connection in the linked list of connections.
|
||||
**
|
||||
** We use the RMP (Ethernet) address as the basis for determining
|
||||
** if this is the same connection. According to the Remote Maint
|
||||
** Protocol, we can only have one connection with any machine.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - connection to be found.
|
||||
**
|
||||
** Returns:
|
||||
** Matching connection from linked list or NULL if not found.
|
||||
**
|
||||
** Side Effects:
|
||||
** None.
|
||||
**
|
||||
** Warnings:
|
||||
** - This routine must be called with SIGHUP blocked.
|
||||
*/
|
||||
RMPCONN *
|
||||
FindConn(rconn)
|
||||
register RMPCONN *rconn;
|
||||
{
|
||||
register RMPCONN *rtmp;
|
||||
|
||||
for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next)
|
||||
if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0],
|
||||
(char *)&rtmp->rmp.hp_hdr.saddr[0], RMP_ADDRLEN) == 0)
|
||||
break;
|
||||
|
||||
return(rtmp);
|
||||
}
|
||||
|
||||
/*
|
||||
** RemoveConn -- Remove a connection from the linked list of connections.
|
||||
**
|
||||
** Parameters:
|
||||
** rconn - connection to be removed.
|
||||
**
|
||||
** Returns:
|
||||
** Nothing.
|
||||
**
|
||||
** Side Effects:
|
||||
** - If found, an RMPCONN will cease to exist and it will
|
||||
** be removed from the linked list.
|
||||
**
|
||||
** Warnings:
|
||||
** - This routine must be called with SIGHUP blocked.
|
||||
*/
|
||||
void
|
||||
RemoveConn(rconn)
|
||||
register RMPCONN *rconn;
|
||||
{
|
||||
register RMPCONN *thisrconn, *lastrconn;
|
||||
|
||||
if (RmpConns == rconn) { /* easy case */
|
||||
RmpConns = RmpConns->next;
|
||||
FreeConn(rconn);
|
||||
} else { /* must traverse linked list */
|
||||
lastrconn = RmpConns; /* set back ptr */
|
||||
thisrconn = lastrconn->next; /* set current ptr */
|
||||
while (thisrconn != NULL) {
|
||||
if (rconn == thisrconn) { /* found it */
|
||||
lastrconn->next = thisrconn->next;
|
||||
FreeConn(thisrconn);
|
||||
break;
|
||||
}
|
||||
lastrconn = thisrconn;
|
||||
thisrconn = thisrconn->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
6
libexec/rexecd/Makefile
Normal file
6
libexec/rexecd/Makefile
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||
|
||||
PROG= rexecd
|
||||
MAN8= rexecd.0
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
148
libexec/rexecd/rexecd.8
Normal file
148
libexec/rexecd/rexecd.8
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
.\" Copyright (c) 1983, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)rexecd.8 8.2 (Berkeley) 12/11/93
|
||||
.\"
|
||||
.Dd December 11, 1993
|
||||
.Dt REXECD 8
|
||||
.Os BSD 4.2
|
||||
.Sh NAME
|
||||
.Nm rexecd
|
||||
.Nd remote execution server
|
||||
.Sh SYNOPSIS
|
||||
.Nm rexecd
|
||||
.Sh DESCRIPTION
|
||||
.Nm Rexecd
|
||||
is the server for the
|
||||
.Xr rexec 3
|
||||
routine. The server provides remote execution facilities
|
||||
with authentication based on user names and
|
||||
passwords.
|
||||
.Pp
|
||||
.Nm Rexecd
|
||||
listens for service requests at the port indicated in
|
||||
the ``exec'' service specification; see
|
||||
.Xr services 5 .
|
||||
When a service request is received the following protocol
|
||||
is initiated:
|
||||
.Bl -enum
|
||||
.It
|
||||
The server reads characters from the socket up
|
||||
to a NUL
|
||||
.Pq Ql \e0
|
||||
byte. The resultant string is
|
||||
interpreted as an
|
||||
.Tn ASCII
|
||||
number, base 10.
|
||||
.It
|
||||
If the number received in step 1 is non-zero,
|
||||
it is interpreted as the port number of a secondary
|
||||
stream to be used for the
|
||||
.Em stderr .
|
||||
A second connection is then created to the specified
|
||||
port on the client's machine.
|
||||
.It
|
||||
A NUL terminated user name of at most 16 characters
|
||||
is retrieved on the initial socket.
|
||||
.It
|
||||
A NUL terminated, unencrypted password of at most
|
||||
16 characters is retrieved on the initial socket.
|
||||
.It
|
||||
A NUL terminated command to be passed to a
|
||||
shell is retrieved on the initial socket. The length of
|
||||
the command is limited by the upper bound on the size of
|
||||
the system's argument list.
|
||||
.It
|
||||
.Nm Rexecd
|
||||
then validates the user as is done at login time
|
||||
and, if the authentication was successful, changes
|
||||
to the user's home directory, and establishes the user
|
||||
and group protections of the user.
|
||||
If any of these steps fail the connection is
|
||||
aborted with a diagnostic message returned.
|
||||
.It
|
||||
A NUL byte is returned on the initial socket
|
||||
and the command line is passed to the normal login
|
||||
shell of the user. The
|
||||
shell inherits the network connections established
|
||||
by
|
||||
.Nm rexecd .
|
||||
.El
|
||||
.Sh DIAGNOSTICS
|
||||
Except for the last one listed below,
|
||||
all diagnostic messages are returned on the initial socket,
|
||||
after which any network connections are closed.
|
||||
An error is indicated by a leading byte with a value of
|
||||
1 (0 is returned in step 7 above upon successful completion
|
||||
of all the steps prior to the command execution).
|
||||
.Pp
|
||||
.Bl -tag -width Ds
|
||||
.It Sy username too long
|
||||
The name is
|
||||
longer than 16 characters.
|
||||
.It Sy password too long
|
||||
The password is longer than 16 characters.
|
||||
.It Sy command too long
|
||||
The command line passed exceeds the size of the argument
|
||||
list (as configured into the system).
|
||||
.It Sy Login incorrect.
|
||||
No password file entry for the user name existed.
|
||||
.It Sy Password incorrect.
|
||||
The wrong password was supplied.
|
||||
.It Sy \&No remote directory.
|
||||
The
|
||||
.Xr chdir
|
||||
command to the home directory failed.
|
||||
.It Sy Try again.
|
||||
A
|
||||
.Xr fork
|
||||
by the server failed.
|
||||
.It Sy <shellname>: ...
|
||||
The user's login shell could not be started.
|
||||
This message is returned
|
||||
on the connection associated with the
|
||||
.Em stderr ,
|
||||
and is not preceded by a flag byte.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr rexec 3
|
||||
.Sh BUGS
|
||||
Indicating ``Login incorrect'' as opposed to ``Password incorrect''
|
||||
is a security breach which allows people to probe a system for users
|
||||
with null passwords.
|
||||
.Pp
|
||||
A facility to allow all data and password exchanges to be encrypted should be
|
||||
present.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.2 .
|
||||
259
libexec/rexecd/rexecd.c
Normal file
259
libexec/rexecd/rexecd.c
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1983, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)rexecd.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <paths.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*VARARGS1*/
|
||||
int error();
|
||||
|
||||
/*
|
||||
* remote execute server:
|
||||
* username\0
|
||||
* password\0
|
||||
* command\0
|
||||
* data
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct sockaddr_in from;
|
||||
int fromlen;
|
||||
|
||||
fromlen = sizeof (from);
|
||||
if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
|
||||
(void)fprintf(stderr,
|
||||
"rexecd: getpeername: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
doit(0, &from);
|
||||
}
|
||||
|
||||
char username[20] = "USER=";
|
||||
char homedir[64] = "HOME=";
|
||||
char shell[64] = "SHELL=";
|
||||
char path[sizeof(_PATH_DEFPATH) + sizeof("PATH=")] = "PATH=";
|
||||
char *envinit[] =
|
||||
{homedir, shell, path, username, 0};
|
||||
char **environ;
|
||||
|
||||
struct sockaddr_in asin = { AF_INET };
|
||||
|
||||
doit(f, fromp)
|
||||
int f;
|
||||
struct sockaddr_in *fromp;
|
||||
{
|
||||
char cmdbuf[NCARGS+1], *cp, *namep;
|
||||
char user[16], pass[16];
|
||||
struct passwd *pwd;
|
||||
int s;
|
||||
u_short port;
|
||||
int pv[2], pid, ready, readfrom, cc;
|
||||
char buf[BUFSIZ], sig;
|
||||
int one = 1;
|
||||
|
||||
(void) signal(SIGINT, SIG_DFL);
|
||||
(void) signal(SIGQUIT, SIG_DFL);
|
||||
(void) signal(SIGTERM, SIG_DFL);
|
||||
#ifdef DEBUG
|
||||
{ int t = open(_PATH_TTY, 2);
|
||||
if (t >= 0) {
|
||||
ioctl(t, TIOCNOTTY, (char *)0);
|
||||
(void) close(t);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
dup2(f, 0);
|
||||
dup2(f, 1);
|
||||
dup2(f, 2);
|
||||
(void) alarm(60);
|
||||
port = 0;
|
||||
for (;;) {
|
||||
char c;
|
||||
if (read(f, &c, 1) != 1)
|
||||
exit(1);
|
||||
if (c == 0)
|
||||
break;
|
||||
port = port * 10 + c - '0';
|
||||
}
|
||||
(void) alarm(0);
|
||||
if (port != 0) {
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s < 0)
|
||||
exit(1);
|
||||
if (bind(s, (struct sockaddr *)&asin, sizeof (asin)) < 0)
|
||||
exit(1);
|
||||
(void) alarm(60);
|
||||
fromp->sin_port = htons(port);
|
||||
if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0)
|
||||
exit(1);
|
||||
(void) alarm(0);
|
||||
}
|
||||
getstr(user, sizeof(user), "username");
|
||||
getstr(pass, sizeof(pass), "password");
|
||||
getstr(cmdbuf, sizeof(cmdbuf), "command");
|
||||
setpwent();
|
||||
pwd = getpwnam(user);
|
||||
if (pwd == NULL) {
|
||||
error("Login incorrect.\n");
|
||||
exit(1);
|
||||
}
|
||||
endpwent();
|
||||
if (*pwd->pw_passwd != '\0') {
|
||||
namep = crypt(pass, pwd->pw_passwd);
|
||||
if (strcmp(namep, pwd->pw_passwd)) {
|
||||
error("Password incorrect.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (chdir(pwd->pw_dir) < 0) {
|
||||
error("No remote directory.\n");
|
||||
exit(1);
|
||||
}
|
||||
(void) write(2, "\0", 1);
|
||||
if (port) {
|
||||
(void) pipe(pv);
|
||||
pid = fork();
|
||||
if (pid == -1) {
|
||||
error("Try again.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (pid) {
|
||||
(void) close(0); (void) close(1); (void) close(2);
|
||||
(void) close(f); (void) close(pv[1]);
|
||||
readfrom = (1<<s) | (1<<pv[0]);
|
||||
ioctl(pv[1], FIONBIO, (char *)&one);
|
||||
/* should set s nbio! */
|
||||
do {
|
||||
ready = readfrom;
|
||||
(void) select(16, (fd_set *)&ready,
|
||||
(fd_set *)NULL, (fd_set *)NULL,
|
||||
(struct timeval *)NULL);
|
||||
if (ready & (1<<s)) {
|
||||
if (read(s, &sig, 1) <= 0)
|
||||
readfrom &= ~(1<<s);
|
||||
else
|
||||
killpg(pid, sig);
|
||||
}
|
||||
if (ready & (1<<pv[0])) {
|
||||
cc = read(pv[0], buf, sizeof (buf));
|
||||
if (cc <= 0) {
|
||||
shutdown(s, 1+1);
|
||||
readfrom &= ~(1<<pv[0]);
|
||||
} else
|
||||
(void) write(s, buf, cc);
|
||||
}
|
||||
} while (readfrom);
|
||||
exit(0);
|
||||
}
|
||||
setpgrp(0, getpid());
|
||||
(void) close(s); (void)close(pv[0]);
|
||||
dup2(pv[1], 2);
|
||||
}
|
||||
if (*pwd->pw_shell == '\0')
|
||||
pwd->pw_shell = _PATH_BSHELL;
|
||||
if (f > 2)
|
||||
(void) close(f);
|
||||
(void) setgid((gid_t)pwd->pw_gid);
|
||||
initgroups(pwd->pw_name, pwd->pw_gid);
|
||||
(void) setuid((uid_t)pwd->pw_uid);
|
||||
(void)strcat(path, _PATH_DEFPATH);
|
||||
environ = envinit;
|
||||
strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
|
||||
strncat(shell, pwd->pw_shell, sizeof(shell)-7);
|
||||
strncat(username, pwd->pw_name, sizeof(username)-6);
|
||||
cp = strrchr(pwd->pw_shell, '/');
|
||||
if (cp)
|
||||
cp++;
|
||||
else
|
||||
cp = pwd->pw_shell;
|
||||
execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
|
||||
perror(pwd->pw_shell);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
error(fmt, a1, a2, a3)
|
||||
char *fmt;
|
||||
int a1, a2, a3;
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
|
||||
buf[0] = 1;
|
||||
(void) sprintf(buf+1, fmt, a1, a2, a3);
|
||||
(void) write(2, buf, strlen(buf));
|
||||
}
|
||||
|
||||
getstr(buf, cnt, err)
|
||||
char *buf;
|
||||
int cnt;
|
||||
char *err;
|
||||
{
|
||||
char c;
|
||||
|
||||
do {
|
||||
if (read(0, &c, 1) != 1)
|
||||
exit(1);
|
||||
*buf++ = c;
|
||||
if (--cnt == 0) {
|
||||
error("%s too long\n", err);
|
||||
exit(1);
|
||||
}
|
||||
} while (c != 0);
|
||||
}
|
||||
11
libexec/rlogind/Makefile
Normal file
11
libexec/rlogind/Makefile
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||
|
||||
PROG= rlogind
|
||||
CFLAGS+=-DKERBEROS -DCRYPT
|
||||
SRCS= rlogind.c des_rw.c
|
||||
MAN8= rlogind.0
|
||||
DPADD= ${LIBUTIL} ${LIBKRB} ${LIBDES}
|
||||
LDADD= -lutil -lkrb -ldes
|
||||
.PATH: ${.CURDIR}/../../usr.bin/rlogin
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
38
libexec/rlogind/pathnames.h
Normal file
38
libexec/rlogind/pathnames.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
#include <paths.h>
|
||||
|
||||
#define _PATH_LOGIN "/usr/bin/login"
|
||||
168
libexec/rlogind/rlogind.8
Normal file
168
libexec/rlogind/rlogind.8
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
.\" Copyright (c) 1983, 1989, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)rlogind.8 8.1 (Berkeley) 6/4/93
|
||||
.\"
|
||||
.Dd June 4, 1993
|
||||
.Dt RLOGIND 8
|
||||
.Os BSD 4.2
|
||||
.Sh NAME
|
||||
.Nm rlogind
|
||||
.Nd remote login server
|
||||
.Sh SYNOPSIS
|
||||
.Nm rlogind
|
||||
.Op Fl aln
|
||||
.Sh DESCRIPTION
|
||||
.Nm Rlogind
|
||||
is the server for the
|
||||
.Xr rlogin 1
|
||||
program. The server provides a remote login facility
|
||||
with authentication based on privileged port numbers from trusted hosts.
|
||||
.Pp
|
||||
Options supported by
|
||||
.Nm rlogind :
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a
|
||||
Ask hostname for verification.
|
||||
.It Fl l
|
||||
Prevent any authentication based on the user's
|
||||
.Dq Pa .rhosts
|
||||
file, unless the user is logging in as the superuser.
|
||||
.It Fl n
|
||||
Disable keep-alive messages.
|
||||
.El
|
||||
.Pp
|
||||
.Nm Rlogind
|
||||
listens for service requests at the port indicated in
|
||||
the ``login'' service specification; see
|
||||
.Xr services 5 .
|
||||
When a service request is received the following protocol
|
||||
is initiated:
|
||||
.Bl -enum
|
||||
.It
|
||||
The server checks the client's source port.
|
||||
If the port is not in the range 512-1023, the server
|
||||
aborts the connection.
|
||||
.It
|
||||
The server checks the client's source address
|
||||
and requests the corresponding host name (see
|
||||
.Xr gethostbyaddr 3 ,
|
||||
.Xr hosts 5
|
||||
and
|
||||
.Xr named 8 ) .
|
||||
If the hostname cannot be determined,
|
||||
the dot-notation representation of the host address is used.
|
||||
If the hostname is in the same domain as the server (according to
|
||||
the last two components of the domain name),
|
||||
or if the
|
||||
.Fl a
|
||||
option is given,
|
||||
the addresses for the hostname are requested,
|
||||
verifying that the name and address correspond.
|
||||
Normal authentication is bypassed if the address verification fails.
|
||||
.El
|
||||
.Pp
|
||||
Once the source port and address have been checked,
|
||||
.Nm rlogind
|
||||
proceeds with the authentication process described in
|
||||
.Xr rshd 8 .
|
||||
It then allocates a pseudo terminal (see
|
||||
.Xr pty 4 ) ,
|
||||
and manipulates file descriptors so that the slave
|
||||
half of the pseudo terminal becomes the
|
||||
.Em stdin ,
|
||||
.Em stdout ,
|
||||
and
|
||||
.Em stderr
|
||||
for a login process.
|
||||
The login process is an instance of the
|
||||
.Xr login 1
|
||||
program, invoked with the
|
||||
.Fl f
|
||||
option if authentication has succeeded.
|
||||
If automatic authentication fails, the user is
|
||||
prompted to log in as if on a standard terminal line.
|
||||
.Pp
|
||||
The parent of the login process manipulates the master side of
|
||||
the pseudo terminal, operating as an intermediary
|
||||
between the login process and the client instance of the
|
||||
.Xr rlogin
|
||||
program. In normal operation, the packet protocol described
|
||||
in
|
||||
.Xr pty 4
|
||||
is invoked to provide
|
||||
.Ql ^S/^Q
|
||||
type facilities and propagate
|
||||
interrupt signals to the remote programs. The login process
|
||||
propagates the client terminal's baud rate and terminal type,
|
||||
as found in the environment variable,
|
||||
.Ql Ev TERM ;
|
||||
see
|
||||
.Xr environ 7 .
|
||||
The screen or window size of the terminal is requested from the client,
|
||||
and window size changes from the client are propagated to the pseudo terminal.
|
||||
.Pp
|
||||
Transport-level keepalive messages are enabled unless the
|
||||
.Fl n
|
||||
option is present.
|
||||
The use of keepalive messages allows sessions to be timed out
|
||||
if the client crashes or becomes unreachable.
|
||||
.Sh DIAGNOSTICS
|
||||
All initial diagnostic messages are indicated
|
||||
by a leading byte with a value of 1,
|
||||
after which any network connections are closed.
|
||||
If there are no errors before
|
||||
.Xr login
|
||||
is invoked, a null byte is returned as in indication of success.
|
||||
.Bl -tag -width Ds
|
||||
.It Sy Try again.
|
||||
A
|
||||
.Xr fork
|
||||
by the server failed.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr login 1 ,
|
||||
.Xr ruserok 3 ,
|
||||
.Xr rshd 8
|
||||
.Sh BUGS
|
||||
The authentication procedure used here assumes the integrity
|
||||
of each client machine and the connecting medium. This is
|
||||
insecure, but is useful in an ``open'' environment.
|
||||
.Pp
|
||||
A facility to allow all data exchanges to be encrypted should be
|
||||
present.
|
||||
.Pp
|
||||
A more extensible protocol should be used.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.2 .
|
||||
759
libexec/rlogind/rlogind.c
Normal file
759
libexec/rlogind/rlogind.c
Normal file
|
|
@ -0,0 +1,759 @@
|
|||
/*-
|
||||
* Copyright (c) 1983, 1988, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1983, 1988, 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)rlogind.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* remote login server:
|
||||
* \0
|
||||
* remuser\0
|
||||
* locuser\0
|
||||
* terminal_type/speed\0
|
||||
* data
|
||||
*/
|
||||
|
||||
#define FD_SETSIZE 16 /* don't need many bits for select */
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <pwd.h>
|
||||
#include <syslog.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "pathnames.h"
|
||||
|
||||
#ifndef TIOCPKT_WINDOW
|
||||
#define TIOCPKT_WINDOW 0x80
|
||||
#endif
|
||||
|
||||
#ifdef KERBEROS
|
||||
#include <kerberosIV/des.h>
|
||||
#include <kerberosIV/krb.h>
|
||||
#define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n"
|
||||
|
||||
AUTH_DAT *kdata;
|
||||
KTEXT ticket;
|
||||
u_char auth_buf[sizeof(AUTH_DAT)];
|
||||
u_char tick_buf[sizeof(KTEXT_ST)];
|
||||
Key_schedule schedule;
|
||||
int doencrypt, retval, use_kerberos, vacuous;
|
||||
|
||||
#define ARGSTR "alnkvx"
|
||||
#else
|
||||
#define ARGSTR "aln"
|
||||
#endif /* KERBEROS */
|
||||
|
||||
char *env[2];
|
||||
#define NMAX 30
|
||||
char lusername[NMAX+1], rusername[NMAX+1];
|
||||
static char term[64] = "TERM=";
|
||||
#define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */
|
||||
int keepalive = 1;
|
||||
int check_all = 0;
|
||||
|
||||
struct passwd *pwd;
|
||||
|
||||
void doit __P((int, struct sockaddr_in *));
|
||||
int control __P((int, char *, int));
|
||||
void protocol __P((int, int));
|
||||
void cleanup __P((int));
|
||||
void fatal __P((int, char *, int));
|
||||
int do_rlogin __P((struct sockaddr_in *));
|
||||
void getstr __P((char *, int, char *));
|
||||
void setup_term __P((int));
|
||||
int do_krb_login __P((struct sockaddr_in *));
|
||||
void usage __P((void));
|
||||
int local_domain __P((char *));
|
||||
char *topdomain __P((char *));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern int __check_rhosts_file;
|
||||
struct sockaddr_in from;
|
||||
int ch, fromlen, on;
|
||||
|
||||
openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH);
|
||||
|
||||
opterr = 0;
|
||||
while ((ch = getopt(argc, argv, ARGSTR)) != EOF)
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
check_all = 1;
|
||||
break;
|
||||
case 'l':
|
||||
__check_rhosts_file = 0;
|
||||
break;
|
||||
case 'n':
|
||||
keepalive = 0;
|
||||
break;
|
||||
#ifdef KERBEROS
|
||||
case 'k':
|
||||
use_kerberos = 1;
|
||||
break;
|
||||
case 'v':
|
||||
vacuous = 1;
|
||||
break;
|
||||
#ifdef CRYPT
|
||||
case 'x':
|
||||
doencrypt = 1;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
#ifdef KERBEROS
|
||||
if (use_kerberos && vacuous) {
|
||||
usage();
|
||||
fatal(STDERR_FILENO, "only one of -k and -v allowed", 0);
|
||||
}
|
||||
#endif
|
||||
fromlen = sizeof (from);
|
||||
if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
|
||||
syslog(LOG_ERR,"Can't get peer name of remote host: %m");
|
||||
fatal(STDERR_FILENO, "Can't get peer name of remote host", 1);
|
||||
}
|
||||
on = 1;
|
||||
if (keepalive &&
|
||||
setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0)
|
||||
syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
|
||||
on = IPTOS_LOWDELAY;
|
||||
if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
|
||||
syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
|
||||
doit(0, &from);
|
||||
}
|
||||
|
||||
int child;
|
||||
int netf;
|
||||
char line[MAXPATHLEN];
|
||||
int confirmed;
|
||||
|
||||
struct winsize win = { 0, 0, 0, 0 };
|
||||
|
||||
|
||||
void
|
||||
doit(f, fromp)
|
||||
int f;
|
||||
struct sockaddr_in *fromp;
|
||||
{
|
||||
int master, pid, on = 1;
|
||||
int authenticated = 0;
|
||||
register struct hostent *hp;
|
||||
char hostname[2 * MAXHOSTNAMELEN + 1];
|
||||
char c;
|
||||
|
||||
alarm(60);
|
||||
read(f, &c, 1);
|
||||
|
||||
if (c != 0)
|
||||
exit(1);
|
||||
#ifdef KERBEROS
|
||||
if (vacuous)
|
||||
fatal(f, "Remote host requires Kerberos authentication", 0);
|
||||
#endif
|
||||
|
||||
alarm(0);
|
||||
fromp->sin_port = ntohs((u_short)fromp->sin_port);
|
||||
hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof(struct in_addr),
|
||||
fromp->sin_family);
|
||||
if (hp)
|
||||
(void)strcpy(hostname, hp->h_name);
|
||||
else
|
||||
(void)strcpy(hostname, inet_ntoa(fromp->sin_addr));
|
||||
|
||||
#ifdef KERBEROS
|
||||
if (use_kerberos) {
|
||||
retval = do_krb_login(fromp);
|
||||
if (retval == 0)
|
||||
authenticated++;
|
||||
else if (retval > 0)
|
||||
fatal(f, krb_err_txt[retval], 0);
|
||||
write(f, &c, 1);
|
||||
confirmed = 1; /* we sent the null! */
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (fromp->sin_family != AF_INET ||
|
||||
fromp->sin_port >= IPPORT_RESERVED ||
|
||||
fromp->sin_port < IPPORT_RESERVED/2) {
|
||||
syslog(LOG_NOTICE, "Connection from %s on illegal port",
|
||||
inet_ntoa(fromp->sin_addr));
|
||||
fatal(f, "Permission denied", 0);
|
||||
}
|
||||
#ifdef IP_OPTIONS
|
||||
{
|
||||
u_char optbuf[BUFSIZ/3], *cp;
|
||||
char lbuf[BUFSIZ], *lp;
|
||||
int optsize = sizeof(optbuf), ipproto;
|
||||
struct protoent *ip;
|
||||
|
||||
if ((ip = getprotobyname("ip")) != NULL)
|
||||
ipproto = ip->p_proto;
|
||||
else
|
||||
ipproto = IPPROTO_IP;
|
||||
if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf,
|
||||
&optsize) == 0 && optsize != 0) {
|
||||
lp = lbuf;
|
||||
for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)
|
||||
sprintf(lp, " %2.2x", *cp);
|
||||
syslog(LOG_NOTICE,
|
||||
"Connection received using IP options (ignored):%s",
|
||||
lbuf);
|
||||
if (setsockopt(0, ipproto, IP_OPTIONS,
|
||||
(char *)NULL, optsize) != 0) {
|
||||
syslog(LOG_ERR,
|
||||
"setsockopt IP_OPTIONS NULL: %m");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (do_rlogin(fromp) == 0)
|
||||
authenticated++;
|
||||
}
|
||||
if (confirmed == 0) {
|
||||
write(f, "", 1);
|
||||
confirmed = 1; /* we sent the null! */
|
||||
}
|
||||
#ifdef KERBEROS
|
||||
#ifdef CRYPT
|
||||
if (doencrypt)
|
||||
(void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE) - 1);
|
||||
#endif
|
||||
#endif
|
||||
netf = f;
|
||||
|
||||
pid = forkpty(&master, line, NULL, &win);
|
||||
if (pid < 0) {
|
||||
if (errno == ENOENT)
|
||||
fatal(f, "Out of ptys", 0);
|
||||
else
|
||||
fatal(f, "Forkpty", 1);
|
||||
}
|
||||
if (pid == 0) {
|
||||
if (f > 2) /* f should always be 0, but... */
|
||||
(void) close(f);
|
||||
setup_term(0);
|
||||
if (authenticated) {
|
||||
#ifdef KERBEROS
|
||||
if (use_kerberos && (pwd->pw_uid == 0))
|
||||
syslog(LOG_INFO|LOG_AUTH,
|
||||
"ROOT Kerberos login from %s.%s@%s on %s\n",
|
||||
kdata->pname, kdata->pinst, kdata->prealm,
|
||||
hostname);
|
||||
#endif
|
||||
|
||||
execl(_PATH_LOGIN, "login", "-p",
|
||||
"-h", hostname, "-f", lusername, (char *)NULL);
|
||||
} else
|
||||
execl(_PATH_LOGIN, "login", "-p",
|
||||
"-h", hostname, lusername, (char *)NULL);
|
||||
fatal(STDERR_FILENO, _PATH_LOGIN, 1);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
#ifdef CRYPT
|
||||
#ifdef KERBEROS
|
||||
/*
|
||||
* If encrypted, don't turn on NBIO or the des read/write
|
||||
* routines will croak.
|
||||
*/
|
||||
|
||||
if (!doencrypt)
|
||||
#endif
|
||||
#endif
|
||||
ioctl(f, FIONBIO, &on);
|
||||
ioctl(master, FIONBIO, &on);
|
||||
ioctl(master, TIOCPKT, &on);
|
||||
signal(SIGCHLD, cleanup);
|
||||
protocol(f, master);
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
cleanup(0);
|
||||
}
|
||||
|
||||
char magic[2] = { 0377, 0377 };
|
||||
char oobdata[] = {TIOCPKT_WINDOW};
|
||||
|
||||
/*
|
||||
* Handle a "control" request (signaled by magic being present)
|
||||
* in the data stream. For now, we are only willing to handle
|
||||
* window size changes.
|
||||
*/
|
||||
int
|
||||
control(pty, cp, n)
|
||||
int pty;
|
||||
char *cp;
|
||||
int n;
|
||||
{
|
||||
struct winsize w;
|
||||
|
||||
if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's')
|
||||
return (0);
|
||||
oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */
|
||||
bcopy(cp+4, (char *)&w, sizeof(w));
|
||||
w.ws_row = ntohs(w.ws_row);
|
||||
w.ws_col = ntohs(w.ws_col);
|
||||
w.ws_xpixel = ntohs(w.ws_xpixel);
|
||||
w.ws_ypixel = ntohs(w.ws_ypixel);
|
||||
(void)ioctl(pty, TIOCSWINSZ, &w);
|
||||
return (4+sizeof (w));
|
||||
}
|
||||
|
||||
/*
|
||||
* rlogin "protocol" machine.
|
||||
*/
|
||||
void
|
||||
protocol(f, p)
|
||||
register int f, p;
|
||||
{
|
||||
char pibuf[1024+1], fibuf[1024], *pbp, *fbp;
|
||||
register pcc = 0, fcc = 0;
|
||||
int cc, nfd, n;
|
||||
char cntl;
|
||||
|
||||
/*
|
||||
* Must ignore SIGTTOU, otherwise we'll stop
|
||||
* when we try and set slave pty's window shape
|
||||
* (our controlling tty is the master pty).
|
||||
*/
|
||||
(void) signal(SIGTTOU, SIG_IGN);
|
||||
send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */
|
||||
if (f > p)
|
||||
nfd = f + 1;
|
||||
else
|
||||
nfd = p + 1;
|
||||
if (nfd > FD_SETSIZE) {
|
||||
syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE");
|
||||
fatal(f, "internal error (select mask too small)", 0);
|
||||
}
|
||||
for (;;) {
|
||||
fd_set ibits, obits, ebits, *omask;
|
||||
|
||||
FD_ZERO(&ebits);
|
||||
FD_ZERO(&ibits);
|
||||
FD_ZERO(&obits);
|
||||
omask = (fd_set *)NULL;
|
||||
if (fcc) {
|
||||
FD_SET(p, &obits);
|
||||
omask = &obits;
|
||||
} else
|
||||
FD_SET(f, &ibits);
|
||||
if (pcc >= 0)
|
||||
if (pcc) {
|
||||
FD_SET(f, &obits);
|
||||
omask = &obits;
|
||||
} else
|
||||
FD_SET(p, &ibits);
|
||||
FD_SET(p, &ebits);
|
||||
if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
fatal(f, "select", 1);
|
||||
}
|
||||
if (n == 0) {
|
||||
/* shouldn't happen... */
|
||||
sleep(5);
|
||||
continue;
|
||||
}
|
||||
#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
|
||||
if (FD_ISSET(p, &ebits)) {
|
||||
cc = read(p, &cntl, 1);
|
||||
if (cc == 1 && pkcontrol(cntl)) {
|
||||
cntl |= oobdata[0];
|
||||
send(f, &cntl, 1, MSG_OOB);
|
||||
if (cntl & TIOCPKT_FLUSHWRITE) {
|
||||
pcc = 0;
|
||||
FD_CLR(p, &ibits);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (FD_ISSET(f, &ibits)) {
|
||||
#ifdef CRYPT
|
||||
#ifdef KERBEROS
|
||||
if (doencrypt)
|
||||
fcc = des_read(f, fibuf, sizeof(fibuf));
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
fcc = read(f, fibuf, sizeof(fibuf));
|
||||
if (fcc < 0 && errno == EWOULDBLOCK)
|
||||
fcc = 0;
|
||||
else {
|
||||
register char *cp;
|
||||
int left, n;
|
||||
|
||||
if (fcc <= 0)
|
||||
break;
|
||||
fbp = fibuf;
|
||||
|
||||
top:
|
||||
for (cp = fibuf; cp < fibuf+fcc-1; cp++)
|
||||
if (cp[0] == magic[0] &&
|
||||
cp[1] == magic[1]) {
|
||||
left = fcc - (cp-fibuf);
|
||||
n = control(p, cp, left);
|
||||
if (n) {
|
||||
left -= n;
|
||||
if (left > 0)
|
||||
bcopy(cp+n, cp, left);
|
||||
fcc -= n;
|
||||
goto top; /* n^2 */
|
||||
}
|
||||
}
|
||||
FD_SET(p, &obits); /* try write */
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(p, &obits) && fcc > 0) {
|
||||
cc = write(p, fbp, fcc);
|
||||
if (cc > 0) {
|
||||
fcc -= cc;
|
||||
fbp += cc;
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(p, &ibits)) {
|
||||
pcc = read(p, pibuf, sizeof (pibuf));
|
||||
pbp = pibuf;
|
||||
if (pcc < 0 && errno == EWOULDBLOCK)
|
||||
pcc = 0;
|
||||
else if (pcc <= 0)
|
||||
break;
|
||||
else if (pibuf[0] == 0) {
|
||||
pbp++, pcc--;
|
||||
#ifdef CRYPT
|
||||
#ifdef KERBEROS
|
||||
if (!doencrypt)
|
||||
#endif
|
||||
#endif
|
||||
FD_SET(f, &obits); /* try write */
|
||||
} else {
|
||||
if (pkcontrol(pibuf[0])) {
|
||||
pibuf[0] |= oobdata[0];
|
||||
send(f, &pibuf[0], 1, MSG_OOB);
|
||||
}
|
||||
pcc = 0;
|
||||
}
|
||||
}
|
||||
if ((FD_ISSET(f, &obits)) && pcc > 0) {
|
||||
#ifdef CRYPT
|
||||
#ifdef KERBEROS
|
||||
if (doencrypt)
|
||||
cc = des_write(f, pbp, pcc);
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
cc = write(f, pbp, pcc);
|
||||
if (cc < 0 && errno == EWOULDBLOCK) {
|
||||
/*
|
||||
* This happens when we try write after read
|
||||
* from p, but some old kernels balk at large
|
||||
* writes even when select returns true.
|
||||
*/
|
||||
if (!FD_ISSET(p, &ibits))
|
||||
sleep(5);
|
||||
continue;
|
||||
}
|
||||
if (cc > 0) {
|
||||
pcc -= cc;
|
||||
pbp += cc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cleanup(signo)
|
||||
int signo;
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = line + sizeof(_PATH_DEV) - 1;
|
||||
if (logout(p))
|
||||
logwtmp(p, "", "");
|
||||
(void)chmod(line, 0666);
|
||||
(void)chown(line, 0, 0);
|
||||
*p = 'p';
|
||||
(void)chmod(line, 0666);
|
||||
(void)chown(line, 0, 0);
|
||||
shutdown(netf, 2);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
fatal(f, msg, syserr)
|
||||
int f;
|
||||
char *msg;
|
||||
int syserr;
|
||||
{
|
||||
int len;
|
||||
char buf[BUFSIZ], *bp = buf;
|
||||
|
||||
/*
|
||||
* Prepend binary one to message if we haven't sent
|
||||
* the magic null as confirmation.
|
||||
*/
|
||||
if (!confirmed)
|
||||
*bp++ = '\01'; /* error indicator */
|
||||
if (syserr)
|
||||
len = sprintf(bp, "rlogind: %s: %s.\r\n",
|
||||
msg, strerror(errno));
|
||||
else
|
||||
len = sprintf(bp, "rlogind: %s.\r\n", msg);
|
||||
(void) write(f, buf, bp + len - buf);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
do_rlogin(dest)
|
||||
struct sockaddr_in *dest;
|
||||
{
|
||||
getstr(rusername, sizeof(rusername), "remuser too long");
|
||||
getstr(lusername, sizeof(lusername), "locuser too long");
|
||||
getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long");
|
||||
|
||||
pwd = getpwnam(lusername);
|
||||
if (pwd == NULL)
|
||||
return (-1);
|
||||
if (pwd->pw_uid == 0)
|
||||
return (-1);
|
||||
/* XXX why don't we syslog() failure? */
|
||||
return (iruserok(dest->sin_addr.s_addr, 0, rusername, lusername));
|
||||
}
|
||||
|
||||
void
|
||||
getstr(buf, cnt, errmsg)
|
||||
char *buf;
|
||||
int cnt;
|
||||
char *errmsg;
|
||||
{
|
||||
char c;
|
||||
|
||||
do {
|
||||
if (read(0, &c, 1) != 1)
|
||||
exit(1);
|
||||
if (--cnt < 0)
|
||||
fatal(STDOUT_FILENO, errmsg, 0);
|
||||
*buf++ = c;
|
||||
} while (c != 0);
|
||||
}
|
||||
|
||||
extern char **environ;
|
||||
|
||||
void
|
||||
setup_term(fd)
|
||||
int fd;
|
||||
{
|
||||
register char *cp = index(term+ENVSIZE, '/');
|
||||
char *speed;
|
||||
struct termios tt;
|
||||
|
||||
#ifndef notyet
|
||||
tcgetattr(fd, &tt);
|
||||
if (cp) {
|
||||
*cp++ = '\0';
|
||||
speed = cp;
|
||||
cp = index(speed, '/');
|
||||
if (cp)
|
||||
*cp++ = '\0';
|
||||
cfsetspeed(&tt, atoi(speed));
|
||||
}
|
||||
|
||||
tt.c_iflag = TTYDEF_IFLAG;
|
||||
tt.c_oflag = TTYDEF_OFLAG;
|
||||
tt.c_lflag = TTYDEF_LFLAG;
|
||||
tcsetattr(fd, TCSAFLUSH, &tt);
|
||||
#else
|
||||
if (cp) {
|
||||
*cp++ = '\0';
|
||||
speed = cp;
|
||||
cp = index(speed, '/');
|
||||
if (cp)
|
||||
*cp++ = '\0';
|
||||
tcgetattr(fd, &tt);
|
||||
cfsetspeed(&tt, atoi(speed));
|
||||
tcsetattr(fd, TCSAFLUSH, &tt);
|
||||
}
|
||||
#endif
|
||||
|
||||
env[0] = term;
|
||||
env[1] = 0;
|
||||
environ = env;
|
||||
}
|
||||
|
||||
#ifdef KERBEROS
|
||||
#define VERSION_SIZE 9
|
||||
|
||||
/*
|
||||
* Do the remote kerberos login to the named host with the
|
||||
* given inet address
|
||||
*
|
||||
* Return 0 on valid authorization
|
||||
* Return -1 on valid authentication, no authorization
|
||||
* Return >0 for error conditions
|
||||
*/
|
||||
int
|
||||
do_krb_login(dest)
|
||||
struct sockaddr_in *dest;
|
||||
{
|
||||
int rc;
|
||||
char instance[INST_SZ], version[VERSION_SIZE];
|
||||
long authopts = 0L; /* !mutual */
|
||||
struct sockaddr_in faddr;
|
||||
|
||||
kdata = (AUTH_DAT *) auth_buf;
|
||||
ticket = (KTEXT) tick_buf;
|
||||
|
||||
instance[0] = '*';
|
||||
instance[1] = '\0';
|
||||
|
||||
#ifdef CRYPT
|
||||
if (doencrypt) {
|
||||
rc = sizeof(faddr);
|
||||
if (getsockname(0, (struct sockaddr *)&faddr, &rc))
|
||||
return (-1);
|
||||
authopts = KOPT_DO_MUTUAL;
|
||||
rc = krb_recvauth(
|
||||
authopts, 0,
|
||||
ticket, "rcmd",
|
||||
instance, dest, &faddr,
|
||||
kdata, "", schedule, version);
|
||||
des_set_key(kdata->session, schedule);
|
||||
|
||||
} else
|
||||
#endif
|
||||
rc = krb_recvauth(
|
||||
authopts, 0,
|
||||
ticket, "rcmd",
|
||||
instance, dest, (struct sockaddr_in *) 0,
|
||||
kdata, "", (bit_64 *) 0, version);
|
||||
|
||||
if (rc != KSUCCESS)
|
||||
return (rc);
|
||||
|
||||
getstr(lusername, sizeof(lusername), "locuser");
|
||||
/* get the "cmd" in the rcmd protocol */
|
||||
getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type");
|
||||
|
||||
pwd = getpwnam(lusername);
|
||||
if (pwd == NULL)
|
||||
return (-1);
|
||||
|
||||
/* returns nonzero for no access */
|
||||
if (kuserok(kdata, lusername) != 0)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
|
||||
}
|
||||
#endif /* KERBEROS */
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
#ifdef KERBEROS
|
||||
syslog(LOG_ERR, "usage: rlogind [-aln] [-k | -v]");
|
||||
#else
|
||||
syslog(LOG_ERR, "usage: rlogind [-aln]");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether host h is in our local domain,
|
||||
* defined as sharing the last two components of the domain part,
|
||||
* or the entire domain part if the local domain has only one component.
|
||||
* If either name is unqualified (contains no '.'),
|
||||
* assume that the host is local, as it will be
|
||||
* interpreted as such.
|
||||
*/
|
||||
int
|
||||
local_domain(h)
|
||||
char *h;
|
||||
{
|
||||
char localhost[MAXHOSTNAMELEN];
|
||||
char *p1, *p2;
|
||||
|
||||
localhost[0] = 0;
|
||||
(void) gethostname(localhost, sizeof(localhost));
|
||||
p1 = topdomain(localhost);
|
||||
p2 = topdomain(h);
|
||||
if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
char *
|
||||
topdomain(h)
|
||||
char *h;
|
||||
{
|
||||
register char *p;
|
||||
char *maybe = NULL;
|
||||
int dots = 0;
|
||||
|
||||
for (p = h + strlen(h); p >= h; p--) {
|
||||
if (*p == '.') {
|
||||
if (++dots == 2)
|
||||
return (p);
|
||||
maybe = p;
|
||||
}
|
||||
}
|
||||
return (maybe);
|
||||
}
|
||||
11
libexec/rshd/Makefile
Normal file
11
libexec/rshd/Makefile
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||
|
||||
PROG= rshd
|
||||
CFLAGS+=-DKERBEROS -DCRYPT
|
||||
SRCS= rshd.c des_rw.c
|
||||
MAN8= rshd.0
|
||||
DPADD= ${LIBKRB} ${LIBDES}
|
||||
LDADD= -lkrb -ldes
|
||||
.PATH: ${.CURDIR}/../../usr.bin/rlogin
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
209
libexec/rshd/rshd.8
Normal file
209
libexec/rshd/rshd.8
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
.\" Copyright (c) 1983, 1989, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)rshd.8 8.1 (Berkeley) 6/4/93
|
||||
.\"
|
||||
.Dd June 4, 1993
|
||||
.Dt RSHD 8
|
||||
.Os BSD 4.2
|
||||
.Sh NAME
|
||||
.Nm rshd
|
||||
.Nd remote shell server
|
||||
.Sh SYNOPSIS
|
||||
.Nm rshd
|
||||
.Op Fl alnL
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm rshd
|
||||
server
|
||||
is the server for the
|
||||
.Xr rcmd 3
|
||||
routine and, consequently, for the
|
||||
.Xr rsh 1
|
||||
program. The server provides remote execution facilities
|
||||
with authentication based on privileged port numbers from trusted hosts.
|
||||
.Pp
|
||||
The
|
||||
.Nm rshd
|
||||
server
|
||||
listens for service requests at the port indicated in
|
||||
the ``cmd'' service specification; see
|
||||
.Xr services 5 .
|
||||
When a service request is received the following protocol
|
||||
is initiated:
|
||||
.Bl -enum
|
||||
.It
|
||||
The server checks the client's source port.
|
||||
If the port is not in the range 512-1023, the server
|
||||
aborts the connection.
|
||||
.It
|
||||
The server reads characters from the socket up
|
||||
to a null (`\e0') byte. The resultant string is
|
||||
interpreted as an
|
||||
.Tn ASCII
|
||||
number, base 10.
|
||||
.It
|
||||
If the number received in step 2 is non-zero,
|
||||
it is interpreted as the port number of a secondary
|
||||
stream to be used for the
|
||||
.Em stderr .
|
||||
A second connection is then created to the specified
|
||||
port on the client's machine. The source port of this
|
||||
second connection is also in the range 512-1023.
|
||||
.It
|
||||
The server checks the client's source address
|
||||
and requests the corresponding host name (see
|
||||
.Xr gethostbyaddr 3 ,
|
||||
.Xr hosts 5
|
||||
and
|
||||
.Xr named 8 ) .
|
||||
If the hostname cannot be determined,
|
||||
the dot-notation representation of the host address is used.
|
||||
If the hostname is in the same domain as the server (according to
|
||||
the last two components of the domain name),
|
||||
or if the
|
||||
.Fl a
|
||||
option is given,
|
||||
the addresses for the hostname are requested,
|
||||
verifying that the name and address correspond.
|
||||
If address verification fails, the connection is aborted
|
||||
with the message, ``Host address mismatch.''
|
||||
.It
|
||||
A null terminated user name of at most 16 characters
|
||||
is retrieved on the initial socket. This user name
|
||||
is interpreted as the user identity on the
|
||||
.Em client Ns 's
|
||||
machine.
|
||||
.It
|
||||
A null terminated user name of at most 16 characters
|
||||
is retrieved on the initial socket. This user name
|
||||
is interpreted as a user identity to use on the
|
||||
.Sy server Ns 's
|
||||
machine.
|
||||
.It
|
||||
A null terminated command to be passed to a
|
||||
shell is retrieved on the initial socket. The length of
|
||||
the command is limited by the upper bound on the size of
|
||||
the system's argument list.
|
||||
.It
|
||||
.Nm Rshd
|
||||
then validates the user using
|
||||
.Xr ruserok 3 ,
|
||||
which uses the file
|
||||
.Pa /etc/hosts.equiv
|
||||
and the
|
||||
.Pa .rhosts
|
||||
file found in the user's home directory. The
|
||||
.Fl l
|
||||
option prevents
|
||||
.Xr ruserok 3
|
||||
from doing any validation based on the user's ``.rhosts'' file,
|
||||
unless the user is the superuser.
|
||||
.It
|
||||
If the file
|
||||
.Pa /etc/nologin
|
||||
exists and the user is not the superuser,
|
||||
the connection is closed.
|
||||
.It
|
||||
A null byte is returned on the initial socket
|
||||
and the command line is passed to the normal login
|
||||
shell of the user. The
|
||||
shell inherits the network connections established
|
||||
by
|
||||
.Nm rshd .
|
||||
.El
|
||||
.Pp
|
||||
Transport-level keepalive messages are enabled unless the
|
||||
.Fl n
|
||||
option is present.
|
||||
The use of keepalive messages allows sessions to be timed out
|
||||
if the client crashes or becomes unreachable.
|
||||
.Pp
|
||||
The
|
||||
.Fl L
|
||||
option causes all successful accesses to be logged to
|
||||
.Xr syslogd 8
|
||||
as
|
||||
.Li auth.info
|
||||
messages.
|
||||
.Sh DIAGNOSTICS
|
||||
Except for the last one listed below,
|
||||
all diagnostic messages
|
||||
are returned on the initial socket,
|
||||
after which any network connections are closed.
|
||||
An error is indicated by a leading byte with a value of
|
||||
1 (0 is returned in step 10 above upon successful completion
|
||||
of all the steps prior to the execution of the login shell).
|
||||
.Bl -tag -width indent
|
||||
.It Sy Locuser too long.
|
||||
The name of the user on the client's machine is
|
||||
longer than 16 characters.
|
||||
.It Sy Ruser too long.
|
||||
The name of the user on the remote machine is
|
||||
longer than 16 characters.
|
||||
.It Sy Command too long .
|
||||
The command line passed exceeds the size of the argument
|
||||
list (as configured into the system).
|
||||
.It Sy Login incorrect.
|
||||
No password file entry for the user name existed.
|
||||
.It Sy Remote directory.
|
||||
The
|
||||
.Xr chdir
|
||||
command to the home directory failed.
|
||||
.It Sy Permission denied.
|
||||
The authentication procedure described above failed.
|
||||
.It Sy Can't make pipe.
|
||||
The pipe needed for the
|
||||
.Em stderr ,
|
||||
wasn't created.
|
||||
.It Sy Can't fork; try again.
|
||||
A
|
||||
.Xr fork
|
||||
by the server failed.
|
||||
.It Sy <shellname>: ...
|
||||
The user's login shell could not be started. This message is returned
|
||||
on the connection associated with the
|
||||
.Em stderr ,
|
||||
and is not preceded by a flag byte.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr rsh 1 ,
|
||||
.Xr rcmd 3 ,
|
||||
.Xr ruserok 3
|
||||
.Sh BUGS
|
||||
The authentication procedure used here assumes the integrity
|
||||
of each client machine and the connecting medium. This is
|
||||
insecure, but is useful in an ``open'' environment.
|
||||
.Pp
|
||||
A facility to allow all data exchanges to be encrypted should be
|
||||
present.
|
||||
.Pp
|
||||
A more extensible protocol (such as Telnet) should be used.
|
||||
783
libexec/rshd/rshd.c
Normal file
783
libexec/rshd/rshd.c
Normal file
|
|
@ -0,0 +1,783 @@
|
|||
/*-
|
||||
* Copyright (c) 1988, 1989, 1992, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1988, 1989, 1992, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)rshd.c 8.2 (Berkeley) 4/6/94";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* remote shell server:
|
||||
* [port]\0
|
||||
* remuser\0
|
||||
* locuser\0
|
||||
* command\0
|
||||
* data
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int keepalive = 1;
|
||||
int check_all;
|
||||
int log_success; /* If TRUE, log all successful accesses */
|
||||
int sent_null;
|
||||
|
||||
void doit __P((struct sockaddr_in *));
|
||||
void error __P((const char *, ...));
|
||||
void getstr __P((char *, int, char *));
|
||||
int local_domain __P((char *));
|
||||
char *topdomain __P((char *));
|
||||
void usage __P((void));
|
||||
|
||||
#ifdef KERBEROS
|
||||
#include <kerberosIV/des.h>
|
||||
#include <kerberosIV/krb.h>
|
||||
#define VERSION_SIZE 9
|
||||
#define SECURE_MESSAGE "This rsh session is using DES encryption for all transmissions.\r\n"
|
||||
#define OPTIONS "alnkvxL"
|
||||
char authbuf[sizeof(AUTH_DAT)];
|
||||
char tickbuf[sizeof(KTEXT_ST)];
|
||||
int doencrypt, use_kerberos, vacuous;
|
||||
Key_schedule schedule;
|
||||
#else
|
||||
#define OPTIONS "alnL"
|
||||
#endif
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern int __check_rhosts_file;
|
||||
struct linger linger;
|
||||
int ch, on = 1, fromlen;
|
||||
struct sockaddr_in from;
|
||||
|
||||
openlog("rshd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
|
||||
|
||||
opterr = 0;
|
||||
while ((ch = getopt(argc, argv, OPTIONS)) != EOF)
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
check_all = 1;
|
||||
break;
|
||||
case 'l':
|
||||
__check_rhosts_file = 0;
|
||||
break;
|
||||
case 'n':
|
||||
keepalive = 0;
|
||||
break;
|
||||
#ifdef KERBEROS
|
||||
case 'k':
|
||||
use_kerberos = 1;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
vacuous = 1;
|
||||
break;
|
||||
|
||||
#ifdef CRYPT
|
||||
case 'x':
|
||||
doencrypt = 1;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
case 'L':
|
||||
log_success = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
#ifdef KERBEROS
|
||||
if (use_kerberos && vacuous) {
|
||||
syslog(LOG_ERR, "only one of -k and -v allowed");
|
||||
exit(2);
|
||||
}
|
||||
#ifdef CRYPT
|
||||
if (doencrypt && !use_kerberos) {
|
||||
syslog(LOG_ERR, "-k is required for -x");
|
||||
exit(2);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
fromlen = sizeof (from);
|
||||
if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
|
||||
syslog(LOG_ERR, "getpeername: %m");
|
||||
_exit(1);
|
||||
}
|
||||
if (keepalive &&
|
||||
setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
|
||||
sizeof(on)) < 0)
|
||||
syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
|
||||
linger.l_onoff = 1;
|
||||
linger.l_linger = 60; /* XXX */
|
||||
if (setsockopt(0, SOL_SOCKET, SO_LINGER, (char *)&linger,
|
||||
sizeof (linger)) < 0)
|
||||
syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m");
|
||||
doit(&from);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
char username[20] = "USER=";
|
||||
char homedir[64] = "HOME=";
|
||||
char shell[64] = "SHELL=";
|
||||
char path[100] = "PATH=";
|
||||
char *envinit[] =
|
||||
{homedir, shell, path, username, 0};
|
||||
char **environ;
|
||||
|
||||
void
|
||||
doit(fromp)
|
||||
struct sockaddr_in *fromp;
|
||||
{
|
||||
extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */
|
||||
struct hostent *hp;
|
||||
struct passwd *pwd;
|
||||
u_short port;
|
||||
fd_set ready, readfrom;
|
||||
int cc, nfd, pv[2], pid, s;
|
||||
int one = 1;
|
||||
char *hostname, *errorstr, *errorhost;
|
||||
char *cp, sig, buf[BUFSIZ];
|
||||
char cmdbuf[NCARGS+1], locuser[16], remuser[16];
|
||||
char remotehost[2 * MAXHOSTNAMELEN + 1];
|
||||
|
||||
#ifdef KERBEROS
|
||||
AUTH_DAT *kdata = (AUTH_DAT *) NULL;
|
||||
KTEXT ticket = (KTEXT) NULL;
|
||||
char instance[INST_SZ], version[VERSION_SIZE];
|
||||
struct sockaddr_in fromaddr;
|
||||
int rc;
|
||||
long authopts;
|
||||
int pv1[2], pv2[2];
|
||||
fd_set wready, writeto;
|
||||
|
||||
fromaddr = *fromp;
|
||||
#endif
|
||||
|
||||
(void) signal(SIGINT, SIG_DFL);
|
||||
(void) signal(SIGQUIT, SIG_DFL);
|
||||
(void) signal(SIGTERM, SIG_DFL);
|
||||
#ifdef DEBUG
|
||||
{ int t = open(_PATH_TTY, 2);
|
||||
if (t >= 0) {
|
||||
ioctl(t, TIOCNOTTY, (char *)0);
|
||||
(void) close(t);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fromp->sin_port = ntohs((u_short)fromp->sin_port);
|
||||
if (fromp->sin_family != AF_INET) {
|
||||
syslog(LOG_ERR, "malformed \"from\" address (af %d)\n",
|
||||
fromp->sin_family);
|
||||
exit(1);
|
||||
}
|
||||
#ifdef IP_OPTIONS
|
||||
{
|
||||
u_char optbuf[BUFSIZ/3], *cp;
|
||||
char lbuf[BUFSIZ], *lp;
|
||||
int optsize = sizeof(optbuf), ipproto;
|
||||
struct protoent *ip;
|
||||
|
||||
if ((ip = getprotobyname("ip")) != NULL)
|
||||
ipproto = ip->p_proto;
|
||||
else
|
||||
ipproto = IPPROTO_IP;
|
||||
if (!getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, &optsize) &&
|
||||
optsize != 0) {
|
||||
lp = lbuf;
|
||||
for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)
|
||||
sprintf(lp, " %2.2x", *cp);
|
||||
syslog(LOG_NOTICE,
|
||||
"Connection received from %s using IP options (ignored):%s",
|
||||
inet_ntoa(fromp->sin_addr), lbuf);
|
||||
if (setsockopt(0, ipproto, IP_OPTIONS,
|
||||
(char *)NULL, optsize) != 0) {
|
||||
syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef KERBEROS
|
||||
if (!use_kerberos)
|
||||
#endif
|
||||
if (fromp->sin_port >= IPPORT_RESERVED ||
|
||||
fromp->sin_port < IPPORT_RESERVED/2) {
|
||||
syslog(LOG_NOTICE|LOG_AUTH,
|
||||
"Connection from %s on illegal port %u",
|
||||
inet_ntoa(fromp->sin_addr),
|
||||
fromp->sin_port);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
(void) alarm(60);
|
||||
port = 0;
|
||||
for (;;) {
|
||||
char c;
|
||||
if ((cc = read(STDIN_FILENO, &c, 1)) != 1) {
|
||||
if (cc < 0)
|
||||
syslog(LOG_NOTICE, "read: %m");
|
||||
shutdown(0, 1+1);
|
||||
exit(1);
|
||||
}
|
||||
if (c== 0)
|
||||
break;
|
||||
port = port * 10 + c - '0';
|
||||
}
|
||||
|
||||
(void) alarm(0);
|
||||
if (port != 0) {
|
||||
int lport = IPPORT_RESERVED - 1;
|
||||
s = rresvport(&lport);
|
||||
if (s < 0) {
|
||||
syslog(LOG_ERR, "can't get stderr port: %m");
|
||||
exit(1);
|
||||
}
|
||||
#ifdef KERBEROS
|
||||
if (!use_kerberos)
|
||||
#endif
|
||||
if (port >= IPPORT_RESERVED) {
|
||||
syslog(LOG_ERR, "2nd port not reserved\n");
|
||||
exit(1);
|
||||
}
|
||||
fromp->sin_port = htons(port);
|
||||
if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) {
|
||||
syslog(LOG_INFO, "connect second port %d: %m", port);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef KERBEROS
|
||||
if (vacuous) {
|
||||
error("rshd: remote host requires Kerberos authentication\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef notdef
|
||||
/* from inetd, socket is already on 0, 1, 2 */
|
||||
dup2(f, 0);
|
||||
dup2(f, 1);
|
||||
dup2(f, 2);
|
||||
#endif
|
||||
errorstr = NULL;
|
||||
hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr),
|
||||
fromp->sin_family);
|
||||
if (hp) {
|
||||
/*
|
||||
* If name returned by gethostbyaddr is in our domain,
|
||||
* attempt to verify that we haven't been fooled by someone
|
||||
* in a remote net; look up the name and check that this
|
||||
* address corresponds to the name.
|
||||
*/
|
||||
hostname = hp->h_name;
|
||||
#ifdef KERBEROS
|
||||
if (!use_kerberos)
|
||||
#endif
|
||||
if (check_all || local_domain(hp->h_name)) {
|
||||
strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1);
|
||||
remotehost[sizeof(remotehost) - 1] = 0;
|
||||
errorhost = remotehost;
|
||||
hp = gethostbyname(remotehost);
|
||||
if (hp == NULL) {
|
||||
syslog(LOG_INFO,
|
||||
"Couldn't look up address for %s",
|
||||
remotehost);
|
||||
errorstr =
|
||||
"Couldn't look up address for your host (%s)\n";
|
||||
hostname = inet_ntoa(fromp->sin_addr);
|
||||
} else for (; ; hp->h_addr_list++) {
|
||||
if (hp->h_addr_list[0] == NULL) {
|
||||
syslog(LOG_NOTICE,
|
||||
"Host addr %s not listed for host %s",
|
||||
inet_ntoa(fromp->sin_addr),
|
||||
hp->h_name);
|
||||
errorstr =
|
||||
"Host address mismatch for %s\n";
|
||||
hostname = inet_ntoa(fromp->sin_addr);
|
||||
break;
|
||||
}
|
||||
if (!bcmp(hp->h_addr_list[0],
|
||||
(caddr_t)&fromp->sin_addr,
|
||||
sizeof(fromp->sin_addr))) {
|
||||
hostname = hp->h_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
errorhost = hostname = inet_ntoa(fromp->sin_addr);
|
||||
|
||||
#ifdef KERBEROS
|
||||
if (use_kerberos) {
|
||||
kdata = (AUTH_DAT *) authbuf;
|
||||
ticket = (KTEXT) tickbuf;
|
||||
authopts = 0L;
|
||||
strcpy(instance, "*");
|
||||
version[VERSION_SIZE - 1] = '\0';
|
||||
#ifdef CRYPT
|
||||
if (doencrypt) {
|
||||
struct sockaddr_in local_addr;
|
||||
rc = sizeof(local_addr);
|
||||
if (getsockname(0, (struct sockaddr *)&local_addr,
|
||||
&rc) < 0) {
|
||||
syslog(LOG_ERR, "getsockname: %m");
|
||||
error("rlogind: getsockname: %m");
|
||||
exit(1);
|
||||
}
|
||||
authopts = KOPT_DO_MUTUAL;
|
||||
rc = krb_recvauth(authopts, 0, ticket,
|
||||
"rcmd", instance, &fromaddr,
|
||||
&local_addr, kdata, "", schedule,
|
||||
version);
|
||||
des_set_key(kdata->session, schedule);
|
||||
} else
|
||||
#endif
|
||||
rc = krb_recvauth(authopts, 0, ticket, "rcmd",
|
||||
instance, &fromaddr,
|
||||
(struct sockaddr_in *) 0,
|
||||
kdata, "", (bit_64 *) 0, version);
|
||||
if (rc != KSUCCESS) {
|
||||
error("Kerberos authentication failure: %s\n",
|
||||
krb_err_txt[rc]);
|
||||
exit(1);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
getstr(remuser, sizeof(remuser), "remuser");
|
||||
|
||||
getstr(locuser, sizeof(locuser), "locuser");
|
||||
getstr(cmdbuf, sizeof(cmdbuf), "command");
|
||||
setpwent();
|
||||
pwd = getpwnam(locuser);
|
||||
if (pwd == NULL) {
|
||||
syslog(LOG_INFO|LOG_AUTH,
|
||||
"%s@%s as %s: unknown login. cmd='%.80s'",
|
||||
remuser, hostname, locuser, cmdbuf);
|
||||
if (errorstr == NULL)
|
||||
errorstr = "Login incorrect.\n";
|
||||
goto fail;
|
||||
}
|
||||
if (chdir(pwd->pw_dir) < 0) {
|
||||
(void) chdir("/");
|
||||
#ifdef notdef
|
||||
syslog(LOG_INFO|LOG_AUTH,
|
||||
"%s@%s as %s: no home directory. cmd='%.80s'",
|
||||
remuser, hostname, locuser, cmdbuf);
|
||||
error("No remote directory.\n");
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef KERBEROS
|
||||
if (use_kerberos) {
|
||||
if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') {
|
||||
if (kuserok(kdata, locuser) != 0) {
|
||||
syslog(LOG_INFO|LOG_AUTH,
|
||||
"Kerberos rsh denied to %s.%s@%s",
|
||||
kdata->pname, kdata->pinst, kdata->prealm);
|
||||
error("Permission denied.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
|
||||
if (errorstr ||
|
||||
pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
|
||||
iruserok(fromp->sin_addr.s_addr, pwd->pw_uid == 0,
|
||||
remuser, locuser) < 0) {
|
||||
if (__rcmd_errstr)
|
||||
syslog(LOG_INFO|LOG_AUTH,
|
||||
"%s@%s as %s: permission denied (%s). cmd='%.80s'",
|
||||
remuser, hostname, locuser, __rcmd_errstr,
|
||||
cmdbuf);
|
||||
else
|
||||
syslog(LOG_INFO|LOG_AUTH,
|
||||
"%s@%s as %s: permission denied. cmd='%.80s'",
|
||||
remuser, hostname, locuser, cmdbuf);
|
||||
fail:
|
||||
if (errorstr == NULL)
|
||||
errorstr = "Permission denied.\n";
|
||||
error(errorstr, errorhost);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pwd->pw_uid && !access(_PATH_NOLOGIN, F_OK)) {
|
||||
error("Logins currently disabled.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
(void) write(STDERR_FILENO, "\0", 1);
|
||||
sent_null = 1;
|
||||
|
||||
if (port) {
|
||||
if (pipe(pv) < 0) {
|
||||
error("Can't make pipe.\n");
|
||||
exit(1);
|
||||
}
|
||||
#ifdef CRYPT
|
||||
#ifdef KERBEROS
|
||||
if (doencrypt) {
|
||||
if (pipe(pv1) < 0) {
|
||||
error("Can't make 2nd pipe.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (pipe(pv2) < 0) {
|
||||
error("Can't make 3rd pipe.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
pid = fork();
|
||||
if (pid == -1) {
|
||||
error("Can't fork; try again.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (pid) {
|
||||
#ifdef CRYPT
|
||||
#ifdef KERBEROS
|
||||
if (doencrypt) {
|
||||
static char msg[] = SECURE_MESSAGE;
|
||||
(void) close(pv1[1]);
|
||||
(void) close(pv2[1]);
|
||||
des_write(s, msg, sizeof(msg) - 1);
|
||||
|
||||
} else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
(void) close(0);
|
||||
(void) close(1);
|
||||
}
|
||||
(void) close(2);
|
||||
(void) close(pv[1]);
|
||||
|
||||
FD_ZERO(&readfrom);
|
||||
FD_SET(s, &readfrom);
|
||||
FD_SET(pv[0], &readfrom);
|
||||
if (pv[0] > s)
|
||||
nfd = pv[0];
|
||||
else
|
||||
nfd = s;
|
||||
#ifdef CRYPT
|
||||
#ifdef KERBEROS
|
||||
if (doencrypt) {
|
||||
FD_ZERO(&writeto);
|
||||
FD_SET(pv2[0], &writeto);
|
||||
FD_SET(pv1[0], &readfrom);
|
||||
|
||||
nfd = MAX(nfd, pv2[0]);
|
||||
nfd = MAX(nfd, pv1[0]);
|
||||
} else
|
||||
#endif
|
||||
#endif
|
||||
ioctl(pv[0], FIONBIO, (char *)&one);
|
||||
|
||||
/* should set s nbio! */
|
||||
nfd++;
|
||||
do {
|
||||
ready = readfrom;
|
||||
#ifdef CRYPT
|
||||
#ifdef KERBEROS
|
||||
if (doencrypt) {
|
||||
wready = writeto;
|
||||
if (select(nfd, &ready,
|
||||
&wready, (fd_set *) 0,
|
||||
(struct timeval *) 0) < 0)
|
||||
break;
|
||||
} else
|
||||
#endif
|
||||
#endif
|
||||
if (select(nfd, &ready, (fd_set *)0,
|
||||
(fd_set *)0, (struct timeval *)0) < 0)
|
||||
break;
|
||||
if (FD_ISSET(s, &ready)) {
|
||||
int ret;
|
||||
#ifdef CRYPT
|
||||
#ifdef KERBEROS
|
||||
if (doencrypt)
|
||||
ret = des_read(s, &sig, 1);
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
ret = read(s, &sig, 1);
|
||||
if (ret <= 0)
|
||||
FD_CLR(s, &readfrom);
|
||||
else
|
||||
killpg(pid, sig);
|
||||
}
|
||||
if (FD_ISSET(pv[0], &ready)) {
|
||||
errno = 0;
|
||||
cc = read(pv[0], buf, sizeof(buf));
|
||||
if (cc <= 0) {
|
||||
shutdown(s, 1+1);
|
||||
FD_CLR(pv[0], &readfrom);
|
||||
} else {
|
||||
#ifdef CRYPT
|
||||
#ifdef KERBEROS
|
||||
if (doencrypt)
|
||||
(void)
|
||||
des_write(s, buf, cc);
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
(void)
|
||||
write(s, buf, cc);
|
||||
}
|
||||
}
|
||||
#ifdef CRYPT
|
||||
#ifdef KERBEROS
|
||||
if (doencrypt && FD_ISSET(pv1[0], &ready)) {
|
||||
errno = 0;
|
||||
cc = read(pv1[0], buf, sizeof(buf));
|
||||
if (cc <= 0) {
|
||||
shutdown(pv1[0], 1+1);
|
||||
FD_CLR(pv1[0], &readfrom);
|
||||
} else
|
||||
(void) des_write(STDOUT_FILENO,
|
||||
buf, cc);
|
||||
}
|
||||
|
||||
if (doencrypt && FD_ISSET(pv2[0], &wready)) {
|
||||
errno = 0;
|
||||
cc = des_read(STDIN_FILENO,
|
||||
buf, sizeof(buf));
|
||||
if (cc <= 0) {
|
||||
shutdown(pv2[0], 1+1);
|
||||
FD_CLR(pv2[0], &writeto);
|
||||
} else
|
||||
(void) write(pv2[0], buf, cc);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} while (FD_ISSET(s, &readfrom) ||
|
||||
#ifdef CRYPT
|
||||
#ifdef KERBEROS
|
||||
(doencrypt && FD_ISSET(pv1[0], &readfrom)) ||
|
||||
#endif
|
||||
#endif
|
||||
FD_ISSET(pv[0], &readfrom));
|
||||
exit(0);
|
||||
}
|
||||
setpgrp(0, getpid());
|
||||
(void) close(s);
|
||||
(void) close(pv[0]);
|
||||
#ifdef CRYPT
|
||||
#ifdef KERBEROS
|
||||
if (doencrypt) {
|
||||
close(pv1[0]); close(pv2[0]);
|
||||
dup2(pv1[1], 1);
|
||||
dup2(pv2[1], 0);
|
||||
close(pv1[1]);
|
||||
close(pv2[1]);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
dup2(pv[1], 2);
|
||||
close(pv[1]);
|
||||
}
|
||||
if (*pwd->pw_shell == '\0')
|
||||
pwd->pw_shell = _PATH_BSHELL;
|
||||
#if BSD > 43
|
||||
if (setlogin(pwd->pw_name) < 0)
|
||||
syslog(LOG_ERR, "setlogin() failed: %m");
|
||||
#endif
|
||||
(void) setgid((gid_t)pwd->pw_gid);
|
||||
initgroups(pwd->pw_name, pwd->pw_gid);
|
||||
(void) setuid((uid_t)pwd->pw_uid);
|
||||
environ = envinit;
|
||||
strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
|
||||
strcat(path, _PATH_DEFPATH);
|
||||
strncat(shell, pwd->pw_shell, sizeof(shell)-7);
|
||||
strncat(username, pwd->pw_name, sizeof(username)-6);
|
||||
cp = strrchr(pwd->pw_shell, '/');
|
||||
if (cp)
|
||||
cp++;
|
||||
else
|
||||
cp = pwd->pw_shell;
|
||||
endpwent();
|
||||
if (log_success || pwd->pw_uid == 0) {
|
||||
#ifdef KERBEROS
|
||||
if (use_kerberos)
|
||||
syslog(LOG_INFO|LOG_AUTH,
|
||||
"Kerberos shell from %s.%s@%s on %s as %s, cmd='%.80s'",
|
||||
kdata->pname, kdata->pinst, kdata->prealm,
|
||||
hostname, locuser, cmdbuf);
|
||||
else
|
||||
#endif
|
||||
syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'",
|
||||
remuser, hostname, locuser, cmdbuf);
|
||||
}
|
||||
execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
|
||||
perror(pwd->pw_shell);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Report error to client. Note: can't be used until second socket has
|
||||
* connected to client, or older clients will hang waiting for that
|
||||
* connection first.
|
||||
*/
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
error(const char *fmt, ...)
|
||||
#else
|
||||
error(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
int len;
|
||||
char *bp, buf[BUFSIZ];
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
bp = buf;
|
||||
if (sent_null == 0) {
|
||||
*bp++ = 1;
|
||||
len = 1;
|
||||
} else
|
||||
len = 0;
|
||||
(void)vsnprintf(bp, sizeof(buf) - 1, fmt, ap);
|
||||
(void)write(STDERR_FILENO, buf, len + strlen(bp));
|
||||
}
|
||||
|
||||
void
|
||||
getstr(buf, cnt, err)
|
||||
char *buf, *err;
|
||||
int cnt;
|
||||
{
|
||||
char c;
|
||||
|
||||
do {
|
||||
if (read(STDIN_FILENO, &c, 1) != 1)
|
||||
exit(1);
|
||||
*buf++ = c;
|
||||
if (--cnt == 0) {
|
||||
error("%s too long\n", err);
|
||||
exit(1);
|
||||
}
|
||||
} while (c != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether host h is in our local domain,
|
||||
* defined as sharing the last two components of the domain part,
|
||||
* or the entire domain part if the local domain has only one component.
|
||||
* If either name is unqualified (contains no '.'),
|
||||
* assume that the host is local, as it will be
|
||||
* interpreted as such.
|
||||
*/
|
||||
int
|
||||
local_domain(h)
|
||||
char *h;
|
||||
{
|
||||
char localhost[MAXHOSTNAMELEN];
|
||||
char *p1, *p2;
|
||||
|
||||
localhost[0] = 0;
|
||||
(void) gethostname(localhost, sizeof(localhost));
|
||||
p1 = topdomain(localhost);
|
||||
p2 = topdomain(h);
|
||||
if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
char *
|
||||
topdomain(h)
|
||||
char *h;
|
||||
{
|
||||
char *p, *maybe = NULL;
|
||||
int dots = 0;
|
||||
|
||||
for (p = h + strlen(h); p >= h; p--) {
|
||||
if (*p == '.') {
|
||||
if (++dots == 2)
|
||||
return (p);
|
||||
maybe = p;
|
||||
}
|
||||
}
|
||||
return (maybe);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
|
||||
syslog(LOG_ERR, "usage: rshd [-%s]", OPTIONS);
|
||||
exit(2);
|
||||
}
|
||||
8
libexec/talkd/Makefile
Normal file
8
libexec/talkd/Makefile
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||
|
||||
PROG= ntalkd
|
||||
SRCS= talkd.c announce.c process.c table.c print.c ttymsg.c
|
||||
.PATH: ${.CURDIR}/../../usr.bin/wall
|
||||
MAN8= talkd.0
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
159
libexec/talkd/announce.c
Normal file
159
libexec/talkd/announce.c
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)announce.c 8.2 (Berkeley) 1/7/94";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
#include <protocols/talkd.h>
|
||||
#include <sgtty.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <paths.h>
|
||||
|
||||
extern char hostname[];
|
||||
|
||||
/*
|
||||
* Announce an invitation to talk.
|
||||
*/
|
||||
|
||||
/*
|
||||
* See if the user is accepting messages. If so, announce that
|
||||
* a talk is requested.
|
||||
*/
|
||||
announce(request, remote_machine)
|
||||
CTL_MSG *request;
|
||||
char *remote_machine;
|
||||
{
|
||||
char full_tty[32];
|
||||
FILE *tf;
|
||||
struct stat stbuf;
|
||||
|
||||
(void)snprintf(full_tty, sizeof(full_tty),
|
||||
"%s%s", _PATH_DEV, request->r_tty);
|
||||
if (stat(full_tty, &stbuf) < 0 || (stbuf.st_mode&020) == 0)
|
||||
return (PERMISSION_DENIED);
|
||||
return (print_mesg(request->r_tty, tf, request, remote_machine));
|
||||
}
|
||||
|
||||
#define max(a,b) ( (a) > (b) ? (a) : (b) )
|
||||
#define N_LINES 5
|
||||
#define N_CHARS 120
|
||||
|
||||
/*
|
||||
* Build a block of characters containing the message.
|
||||
* It is sent blank filled and in a single block to
|
||||
* try to keep the message in one piece if the recipient
|
||||
* in in vi at the time
|
||||
*/
|
||||
print_mesg(tty, tf, request, remote_machine)
|
||||
char *tty;
|
||||
FILE *tf;
|
||||
CTL_MSG *request;
|
||||
char *remote_machine;
|
||||
{
|
||||
struct timeval clock;
|
||||
struct timezone zone;
|
||||
struct tm *localtime();
|
||||
struct tm *localclock;
|
||||
struct iovec iovec;
|
||||
char line_buf[N_LINES][N_CHARS];
|
||||
int sizes[N_LINES];
|
||||
char big_buf[N_LINES*N_CHARS];
|
||||
char *bptr, *lptr, *ttymsg();
|
||||
int i, j, max_size;
|
||||
|
||||
i = 0;
|
||||
max_size = 0;
|
||||
gettimeofday(&clock, &zone);
|
||||
localclock = localtime( &clock.tv_sec );
|
||||
(void)sprintf(line_buf[i], " ");
|
||||
sizes[i] = strlen(line_buf[i]);
|
||||
max_size = max(max_size, sizes[i]);
|
||||
i++;
|
||||
(void)sprintf(line_buf[i], "Message from Talk_Daemon@%s at %d:%02d ...",
|
||||
hostname, localclock->tm_hour , localclock->tm_min );
|
||||
sizes[i] = strlen(line_buf[i]);
|
||||
max_size = max(max_size, sizes[i]);
|
||||
i++;
|
||||
(void)sprintf(line_buf[i], "talk: connection requested by %s@%s",
|
||||
request->l_name, remote_machine);
|
||||
sizes[i] = strlen(line_buf[i]);
|
||||
max_size = max(max_size, sizes[i]);
|
||||
i++;
|
||||
(void)sprintf(line_buf[i], "talk: respond with: talk %s@%s",
|
||||
request->l_name, remote_machine);
|
||||
sizes[i] = strlen(line_buf[i]);
|
||||
max_size = max(max_size, sizes[i]);
|
||||
i++;
|
||||
(void)sprintf(line_buf[i], " ");
|
||||
sizes[i] = strlen(line_buf[i]);
|
||||
max_size = max(max_size, sizes[i]);
|
||||
i++;
|
||||
bptr = big_buf;
|
||||
*bptr++ = ''; /* send something to wake them up */
|
||||
*bptr++ = '\r'; /* add a \r in case of raw mode */
|
||||
*bptr++ = '\n';
|
||||
for (i = 0; i < N_LINES; i++) {
|
||||
/* copy the line into the big buffer */
|
||||
lptr = line_buf[i];
|
||||
while (*lptr != '\0')
|
||||
*(bptr++) = *(lptr++);
|
||||
/* pad out the rest of the lines with blanks */
|
||||
for (j = sizes[i]; j < max_size + 2; j++)
|
||||
*(bptr++) = ' ';
|
||||
*(bptr++) = '\r'; /* add a \r in case of raw mode */
|
||||
*(bptr++) = '\n';
|
||||
}
|
||||
*bptr = '\0';
|
||||
iovec.iov_base = big_buf;
|
||||
iovec.iov_len = bptr - big_buf;
|
||||
/*
|
||||
* we choose a timeout of RING_WAIT-5 seconds so that we don't
|
||||
* stack up processes trying to write messages to a tty
|
||||
* that is permanently blocked.
|
||||
*/
|
||||
if (ttymsg(&iovec, 1, tty, RING_WAIT - 5) != NULL)
|
||||
return (FAILED);
|
||||
|
||||
return (SUCCESS);
|
||||
}
|
||||
86
libexec/talkd/print.c
Normal file
86
libexec/talkd/print.c
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)print.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/* debug print routines */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <protocols/talkd.h>
|
||||
#include <syslog.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static char *types[] =
|
||||
{ "leave_invite", "look_up", "delete", "announce" };
|
||||
#define NTYPES (sizeof (types) / sizeof (types[0]))
|
||||
static char *answers[] =
|
||||
{ "success", "not_here", "failed", "machine_unknown", "permission_denied",
|
||||
"unknown_request", "badversion", "badaddr", "badctladdr" };
|
||||
#define NANSWERS (sizeof (answers) / sizeof (answers[0]))
|
||||
|
||||
print_request(cp, mp)
|
||||
char *cp;
|
||||
register CTL_MSG *mp;
|
||||
{
|
||||
char tbuf[80], *tp;
|
||||
|
||||
if (mp->type > NTYPES) {
|
||||
(void)sprintf(tbuf, "type %d", mp->type);
|
||||
tp = tbuf;
|
||||
} else
|
||||
tp = types[mp->type];
|
||||
syslog(LOG_DEBUG, "%s: %s: id %d, l_user %s, r_user %s, r_tty %s",
|
||||
cp, tp, mp->id_num, mp->l_name, mp->r_name, mp->r_tty);
|
||||
}
|
||||
|
||||
print_response(cp, rp)
|
||||
char *cp;
|
||||
register CTL_RESPONSE *rp;
|
||||
{
|
||||
char tbuf[80], *tp, abuf[80], *ap;
|
||||
|
||||
if (rp->type > NTYPES) {
|
||||
(void)sprintf(tbuf, "type %d", rp->type);
|
||||
tp = tbuf;
|
||||
} else
|
||||
tp = types[rp->type];
|
||||
if (rp->answer > NANSWERS) {
|
||||
(void)sprintf(abuf, "answer %d", rp->answer);
|
||||
ap = abuf;
|
||||
} else
|
||||
ap = answers[rp->answer];
|
||||
syslog(LOG_DEBUG, "%s: %s: %s, id %d", cp, tp, ap, ntohl(rp->id_num));
|
||||
}
|
||||
219
libexec/talkd/process.c
Normal file
219
libexec/talkd/process.c
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)process.c 8.2 (Berkeley) 11/16/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* process.c handles the requests, which can be of three types:
|
||||
* ANNOUNCE - announce to a user that a talk is wanted
|
||||
* LEAVE_INVITE - insert the request into the table
|
||||
* LOOK_UP - look up to see if a request is waiting in
|
||||
* in the table for the local user
|
||||
* DELETE - delete invitation
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <protocols/talkd.h>
|
||||
#include <netdb.h>
|
||||
#include <syslog.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <paths.h>
|
||||
|
||||
CTL_MSG *find_request();
|
||||
CTL_MSG *find_match();
|
||||
|
||||
process_request(mp, rp)
|
||||
register CTL_MSG *mp;
|
||||
register CTL_RESPONSE *rp;
|
||||
{
|
||||
register CTL_MSG *ptr;
|
||||
extern int debug;
|
||||
|
||||
rp->vers = TALK_VERSION;
|
||||
rp->type = mp->type;
|
||||
rp->id_num = htonl(0);
|
||||
if (mp->vers != TALK_VERSION) {
|
||||
syslog(LOG_WARNING, "Bad protocol version %d", mp->vers);
|
||||
rp->answer = BADVERSION;
|
||||
return;
|
||||
}
|
||||
mp->id_num = ntohl(mp->id_num);
|
||||
mp->addr.sa_family = ntohs(mp->addr.sa_family);
|
||||
if (mp->addr.sa_family != AF_INET) {
|
||||
syslog(LOG_WARNING, "Bad address, family %d",
|
||||
mp->addr.sa_family);
|
||||
rp->answer = BADADDR;
|
||||
return;
|
||||
}
|
||||
mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family);
|
||||
if (mp->ctl_addr.sa_family != AF_INET) {
|
||||
syslog(LOG_WARNING, "Bad control address, family %d",
|
||||
mp->ctl_addr.sa_family);
|
||||
rp->answer = BADCTLADDR;
|
||||
return;
|
||||
}
|
||||
mp->pid = ntohl(mp->pid);
|
||||
if (debug)
|
||||
print_request("process_request", mp);
|
||||
switch (mp->type) {
|
||||
|
||||
case ANNOUNCE:
|
||||
do_announce(mp, rp);
|
||||
break;
|
||||
|
||||
case LEAVE_INVITE:
|
||||
ptr = find_request(mp);
|
||||
if (ptr != (CTL_MSG *)0) {
|
||||
rp->id_num = htonl(ptr->id_num);
|
||||
rp->answer = SUCCESS;
|
||||
} else
|
||||
insert_table(mp, rp);
|
||||
break;
|
||||
|
||||
case LOOK_UP:
|
||||
ptr = find_match(mp);
|
||||
if (ptr != (CTL_MSG *)0) {
|
||||
rp->id_num = htonl(ptr->id_num);
|
||||
rp->addr = ptr->addr;
|
||||
rp->addr.sa_family = htons(ptr->addr.sa_family);
|
||||
rp->answer = SUCCESS;
|
||||
} else
|
||||
rp->answer = NOT_HERE;
|
||||
break;
|
||||
|
||||
case DELETE:
|
||||
rp->answer = delete_invite(mp->id_num);
|
||||
break;
|
||||
|
||||
default:
|
||||
rp->answer = UNKNOWN_REQUEST;
|
||||
break;
|
||||
}
|
||||
if (debug)
|
||||
print_response("process_request", rp);
|
||||
}
|
||||
|
||||
do_announce(mp, rp)
|
||||
register CTL_MSG *mp;
|
||||
CTL_RESPONSE *rp;
|
||||
{
|
||||
struct hostent *hp;
|
||||
CTL_MSG *ptr;
|
||||
int result;
|
||||
|
||||
/* see if the user is logged */
|
||||
result = find_user(mp->r_name, mp->r_tty);
|
||||
if (result != SUCCESS) {
|
||||
rp->answer = result;
|
||||
return;
|
||||
}
|
||||
#define satosin(sa) ((struct sockaddr_in *)(sa))
|
||||
hp = gethostbyaddr((char *)&satosin(&mp->ctl_addr)->sin_addr,
|
||||
sizeof (struct in_addr), AF_INET);
|
||||
if (hp == (struct hostent *)0) {
|
||||
rp->answer = MACHINE_UNKNOWN;
|
||||
return;
|
||||
}
|
||||
ptr = find_request(mp);
|
||||
if (ptr == (CTL_MSG *) 0) {
|
||||
insert_table(mp, rp);
|
||||
rp->answer = announce(mp, hp->h_name);
|
||||
return;
|
||||
}
|
||||
if (mp->id_num > ptr->id_num) {
|
||||
/*
|
||||
* This is an explicit re-announce, so update the id_num
|
||||
* field to avoid duplicates and re-announce the talk.
|
||||
*/
|
||||
ptr->id_num = new_id();
|
||||
rp->id_num = htonl(ptr->id_num);
|
||||
rp->answer = announce(mp, hp->h_name);
|
||||
} else {
|
||||
/* a duplicated request, so ignore it */
|
||||
rp->id_num = htonl(ptr->id_num);
|
||||
rp->answer = SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
#include <utmp.h>
|
||||
|
||||
/*
|
||||
* Search utmp for the local user
|
||||
*/
|
||||
find_user(name, tty)
|
||||
char *name, *tty;
|
||||
{
|
||||
struct utmp ubuf;
|
||||
int status;
|
||||
FILE *fd;
|
||||
struct stat statb;
|
||||
char line[sizeof(ubuf.ut_line) + 1];
|
||||
char ftty[sizeof(_PATH_DEV) - 1 + sizeof(line)];
|
||||
|
||||
if ((fd = fopen(_PATH_UTMP, "r")) == NULL) {
|
||||
fprintf(stderr, "talkd: can't read %s.\n", _PATH_UTMP);
|
||||
return (FAILED);
|
||||
}
|
||||
#define SCMPN(a, b) strncmp(a, b, sizeof (a))
|
||||
status = NOT_HERE;
|
||||
(void) strcpy(ftty, _PATH_DEV);
|
||||
while (fread((char *) &ubuf, sizeof ubuf, 1, fd) == 1)
|
||||
if (SCMPN(ubuf.ut_name, name) == 0) {
|
||||
strncpy(line, ubuf.ut_line, sizeof(ubuf.ut_line));
|
||||
line[sizeof(ubuf.ut_line)] = '\0';
|
||||
if (*tty == '\0') {
|
||||
status = PERMISSION_DENIED;
|
||||
/* no particular tty was requested */
|
||||
(void) strcpy(ftty + sizeof(_PATH_DEV) - 1,
|
||||
line);
|
||||
if (stat(ftty, &statb) == 0) {
|
||||
if (!(statb.st_mode & 020))
|
||||
continue;
|
||||
(void) strcpy(tty, line);
|
||||
status = SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (strcmp(line, tty) == 0) {
|
||||
status = SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(fd);
|
||||
return (status);
|
||||
}
|
||||
233
libexec/talkd/table.c
Normal file
233
libexec/talkd/table.c
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)table.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Routines to handle insertion, deletion, etc on the table
|
||||
* of requests kept by the daemon. Nothing fancy here, linear
|
||||
* search on a double-linked list. A time is kept with each
|
||||
* entry so that overly old invitations can be eliminated.
|
||||
*
|
||||
* Consider this a mis-guided attempt at modularity
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <protocols/talkd.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */
|
||||
|
||||
#define NIL ((TABLE_ENTRY *)0)
|
||||
|
||||
extern int debug;
|
||||
struct timeval tp;
|
||||
struct timezone txp;
|
||||
|
||||
typedef struct table_entry TABLE_ENTRY;
|
||||
|
||||
struct table_entry {
|
||||
CTL_MSG request;
|
||||
long time;
|
||||
TABLE_ENTRY *next;
|
||||
TABLE_ENTRY *last;
|
||||
};
|
||||
|
||||
TABLE_ENTRY *table = NIL;
|
||||
CTL_MSG *find_request();
|
||||
CTL_MSG *find_match();
|
||||
|
||||
/*
|
||||
* Look in the table for an invitation that matches the current
|
||||
* request looking for an invitation
|
||||
*/
|
||||
CTL_MSG *
|
||||
find_match(request)
|
||||
register CTL_MSG *request;
|
||||
{
|
||||
register TABLE_ENTRY *ptr;
|
||||
time_t current_time;
|
||||
|
||||
gettimeofday(&tp, &txp);
|
||||
current_time = tp.tv_sec;
|
||||
if (debug)
|
||||
print_request("find_match", request);
|
||||
for (ptr = table; ptr != NIL; ptr = ptr->next) {
|
||||
if ((ptr->time - current_time) > MAX_LIFE) {
|
||||
/* the entry is too old */
|
||||
if (debug)
|
||||
print_request("deleting expired entry",
|
||||
&ptr->request);
|
||||
delete(ptr);
|
||||
continue;
|
||||
}
|
||||
if (debug)
|
||||
print_request("", &ptr->request);
|
||||
if (strcmp(request->l_name, ptr->request.r_name) == 0 &&
|
||||
strcmp(request->r_name, ptr->request.l_name) == 0 &&
|
||||
ptr->request.type == LEAVE_INVITE)
|
||||
return (&ptr->request);
|
||||
}
|
||||
return ((CTL_MSG *)0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for an identical request, as opposed to a complimentary
|
||||
* one as find_match does
|
||||
*/
|
||||
CTL_MSG *
|
||||
find_request(request)
|
||||
register CTL_MSG *request;
|
||||
{
|
||||
register TABLE_ENTRY *ptr;
|
||||
time_t current_time;
|
||||
|
||||
gettimeofday(&tp, &txp);
|
||||
current_time = tp.tv_sec;
|
||||
/*
|
||||
* See if this is a repeated message, and check for
|
||||
* out of date entries in the table while we are it.
|
||||
*/
|
||||
if (debug)
|
||||
print_request("find_request", request);
|
||||
for (ptr = table; ptr != NIL; ptr = ptr->next) {
|
||||
if ((ptr->time - current_time) > MAX_LIFE) {
|
||||
/* the entry is too old */
|
||||
if (debug)
|
||||
print_request("deleting expired entry",
|
||||
&ptr->request);
|
||||
delete(ptr);
|
||||
continue;
|
||||
}
|
||||
if (debug)
|
||||
print_request("", &ptr->request);
|
||||
if (strcmp(request->r_name, ptr->request.r_name) == 0 &&
|
||||
strcmp(request->l_name, ptr->request.l_name) == 0 &&
|
||||
request->type == ptr->request.type &&
|
||||
request->pid == ptr->request.pid) {
|
||||
/* update the time if we 'touch' it */
|
||||
ptr->time = current_time;
|
||||
return (&ptr->request);
|
||||
}
|
||||
}
|
||||
return ((CTL_MSG *)0);
|
||||
}
|
||||
|
||||
insert_table(request, response)
|
||||
CTL_MSG *request;
|
||||
CTL_RESPONSE *response;
|
||||
{
|
||||
register TABLE_ENTRY *ptr;
|
||||
time_t current_time;
|
||||
|
||||
gettimeofday(&tp, &txp);
|
||||
current_time = tp.tv_sec;
|
||||
request->id_num = new_id();
|
||||
response->id_num = htonl(request->id_num);
|
||||
/* insert a new entry into the top of the list */
|
||||
ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY));
|
||||
if (ptr == NIL) {
|
||||
syslog(LOG_ERR, "insert_table: Out of memory");
|
||||
_exit(1);
|
||||
}
|
||||
ptr->time = current_time;
|
||||
ptr->request = *request;
|
||||
ptr->next = table;
|
||||
if (ptr->next != NIL)
|
||||
ptr->next->last = ptr;
|
||||
ptr->last = NIL;
|
||||
table = ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a unique non-zero sequence number
|
||||
*/
|
||||
new_id()
|
||||
{
|
||||
static int current_id = 0;
|
||||
|
||||
current_id = (current_id + 1) % MAX_ID;
|
||||
/* 0 is reserved, helps to pick up bugs */
|
||||
if (current_id == 0)
|
||||
current_id = 1;
|
||||
return (current_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete the invitation with id 'id_num'
|
||||
*/
|
||||
delete_invite(id_num)
|
||||
int id_num;
|
||||
{
|
||||
register TABLE_ENTRY *ptr;
|
||||
|
||||
ptr = table;
|
||||
if (debug)
|
||||
syslog(LOG_DEBUG, "delete_invite(%d)", id_num);
|
||||
for (ptr = table; ptr != NIL; ptr = ptr->next) {
|
||||
if (ptr->request.id_num == id_num)
|
||||
break;
|
||||
if (debug)
|
||||
print_request("", &ptr->request);
|
||||
}
|
||||
if (ptr != NIL) {
|
||||
delete(ptr);
|
||||
return (SUCCESS);
|
||||
}
|
||||
return (NOT_HERE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Classic delete from a double-linked list
|
||||
*/
|
||||
delete(ptr)
|
||||
register TABLE_ENTRY *ptr;
|
||||
{
|
||||
|
||||
if (debug)
|
||||
print_request("delete", &ptr->request);
|
||||
if (table == ptr)
|
||||
table = ptr->next;
|
||||
else if (ptr->last != NIL)
|
||||
ptr->last->next = ptr->next;
|
||||
if (ptr->next != NIL)
|
||||
ptr->next->last = ptr->last;
|
||||
free((char *)ptr);
|
||||
}
|
||||
75
libexec/talkd/talkd.8
Normal file
75
libexec/talkd/talkd.8
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
.\" Copyright (c) 1983, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)talkd.8 8.2 (Berkeley) 12/11/93
|
||||
.\"
|
||||
.Dd December 11, 1993
|
||||
.Dt TALKD 8
|
||||
.Os BSD 4.3
|
||||
.Sh NAME
|
||||
.Nm talkd
|
||||
.Nd remote user communication server
|
||||
.Sh SYNOPSIS
|
||||
.Nm talkd
|
||||
.Sh DESCRIPTION
|
||||
.Nm Talkd
|
||||
is the server that notifies a user that someone else wants to
|
||||
initiate a conversation.
|
||||
It acts as a repository of invitations, responding to requests
|
||||
by clients wishing to rendezvous to hold a conversation.
|
||||
In normal operation, a client, the caller,
|
||||
initiates a rendezvous by sending a
|
||||
.Tn CTL_MSG
|
||||
to the server of
|
||||
type
|
||||
.Tn LOOK_UP
|
||||
(see
|
||||
.Aq Pa protocols/talkd.h ) .
|
||||
This causes the server to search its invitation
|
||||
tables to check if an invitation currently exists for the caller
|
||||
(to speak to the callee specified in the message).
|
||||
If the lookup fails,
|
||||
the caller then sends an
|
||||
.Tn ANNOUNCE
|
||||
message causing the server to
|
||||
broadcast an announcement on the callee's login ports requesting contact.
|
||||
When the callee responds, the local server uses the
|
||||
recorded invitation to respond with the appropriate rendezvous
|
||||
address and the caller and callee client programs establish a
|
||||
stream connection through which the conversation takes place.
|
||||
.Sh SEE ALSO
|
||||
.Xr talk 1 ,
|
||||
.Xr write 1
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.3 .
|
||||
127
libexec/talkd/talkd.c
Normal file
127
libexec/talkd/talkd.c
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Copyright (c) 1983, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1983, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)talkd.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* The top level of the daemon, the format is heavily borrowed
|
||||
* from rwhod.c. Basically: find out who and where you are;
|
||||
* disconnect all descriptors and ttys, and then endless
|
||||
* loop on waiting for and processing requests
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <protocols/talkd.h>
|
||||
#include <signal.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <paths.h>
|
||||
|
||||
CTL_MSG request;
|
||||
CTL_RESPONSE response;
|
||||
|
||||
int sockt;
|
||||
int debug = 0;
|
||||
void timeout();
|
||||
long lastmsgtime;
|
||||
|
||||
char hostname[32];
|
||||
|
||||
#define TIMEOUT 30
|
||||
#define MAXIDLE 120
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register CTL_MSG *mp = &request;
|
||||
int cc;
|
||||
|
||||
if (getuid()) {
|
||||
fprintf(stderr, "%s: getuid: not super-user\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
openlog("talkd", LOG_PID, LOG_DAEMON);
|
||||
if (gethostname(hostname, sizeof (hostname) - 1) < 0) {
|
||||
syslog(LOG_ERR, "gethostname: %m");
|
||||
_exit(1);
|
||||
}
|
||||
if (chdir(_PATH_DEV) < 0) {
|
||||
syslog(LOG_ERR, "chdir: %s: %m", _PATH_DEV);
|
||||
_exit(1);
|
||||
}
|
||||
if (argc > 1 && strcmp(argv[1], "-d") == 0)
|
||||
debug = 1;
|
||||
signal(SIGALRM, timeout);
|
||||
alarm(TIMEOUT);
|
||||
for (;;) {
|
||||
extern int errno;
|
||||
|
||||
cc = recv(0, (char *)mp, sizeof (*mp), 0);
|
||||
if (cc != sizeof (*mp)) {
|
||||
if (cc < 0 && errno != EINTR)
|
||||
syslog(LOG_WARNING, "recv: %m");
|
||||
continue;
|
||||
}
|
||||
lastmsgtime = time(0);
|
||||
process_request(mp, &response);
|
||||
/* can block here, is this what I want? */
|
||||
cc = sendto(sockt, (char *)&response,
|
||||
sizeof (response), 0, (struct sockaddr *)&mp->ctl_addr,
|
||||
sizeof (mp->ctl_addr));
|
||||
if (cc != sizeof (response))
|
||||
syslog(LOG_WARNING, "sendto: %m");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
timeout()
|
||||
{
|
||||
|
||||
if (time(0) - lastmsgtime >= MAXIDLE)
|
||||
_exit(0);
|
||||
alarm(TIMEOUT);
|
||||
}
|
||||
36
libexec/telnetd/Makefile
Normal file
36
libexec/telnetd/Makefile
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# @(#)Makefile 8.2 (Berkeley) 12/15/93
|
||||
|
||||
PROG= telnetd
|
||||
CFLAGS+=-DLINEMODE -DKLUDGELINEMODE -DUSE_TERMIO -DDIAGNOSTICS
|
||||
CFLAGS+=-DOLD_ENVIRON -DENV_HACK
|
||||
CFLAGS+=-DAUTHENTICATION -DENCRYPTION -I${.CURDIR}/../../lib
|
||||
SRCS= authenc.c global.c slc.c state.c sys_term.c telnetd.c \
|
||||
termstat.c utility.c
|
||||
DPADD= ${LIBUTIL} ${LIBTERM}
|
||||
LDADD= -lutil -ltermcap -ltelnet
|
||||
LDADD+= -lkrb -ldes
|
||||
MAN8= telnetd.0
|
||||
|
||||
# These are the sources that have encryption stuff in them.
|
||||
CRYPT_SRC= authenc.c ext.h state.c telnetd.c termstat.c
|
||||
CRYPT_SRC+= utility.c Makefile
|
||||
NOCRYPT_DIR=${.CURDIR}/Nocrypt
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
nocrypt:
|
||||
#ifdef ENCRYPTION
|
||||
@for i in ${CRYPT_SRC}; do \
|
||||
if [ ! -d ${NOCRYPT_DIR} ]; then \
|
||||
echo Creating subdirectory ${NOCRYPT_DIR}; \
|
||||
mkdir ${NOCRYPT_DIR}; \
|
||||
fi; \
|
||||
echo ${NOCRYPT_DIR}/$$i; \
|
||||
unifdef -UENCRYPTION ${.CURDIR}/$$i | \
|
||||
sed "s/ || defined(ENCRYPTION)//" > ${NOCRYPT_DIR}/$$i; \
|
||||
done
|
||||
|
||||
placeholder:
|
||||
#else /* ENCRYPTION */
|
||||
@echo "Encryption code already removed."
|
||||
#endif /* ENCRYPTION */
|
||||
91
libexec/telnetd/authenc.c
Normal file
91
libexec/telnetd/authenc.c
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)authenc.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#if defined(AUTHENTICATION) || defined(ENCRYPTION)
|
||||
#include "telnetd.h"
|
||||
#include <libtelnet/misc.h>
|
||||
|
||||
int
|
||||
net_write(str, len)
|
||||
unsigned char *str;
|
||||
int len;
|
||||
{
|
||||
if (nfrontp + len < netobuf + BUFSIZ) {
|
||||
bcopy((void *)str, (void *)nfrontp, len);
|
||||
nfrontp += len;
|
||||
return(len);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void
|
||||
net_encrypt()
|
||||
{
|
||||
#ifdef ENCRYPTION
|
||||
char *s = (nclearto > nbackp) ? nclearto : nbackp;
|
||||
if (s < nfrontp && encrypt_output) {
|
||||
(*encrypt_output)((unsigned char *)s, nfrontp - s);
|
||||
}
|
||||
nclearto = nfrontp;
|
||||
#endif /* ENCRYPTION */
|
||||
}
|
||||
|
||||
int
|
||||
telnet_spin()
|
||||
{
|
||||
ttloop();
|
||||
return(0);
|
||||
}
|
||||
|
||||
char *
|
||||
telnet_getenv(val)
|
||||
char *val;
|
||||
{
|
||||
extern char *getenv();
|
||||
return(getenv(val));
|
||||
}
|
||||
|
||||
char *
|
||||
telnet_gets(prompt, result, length, echo)
|
||||
char *prompt;
|
||||
char *result;
|
||||
int length;
|
||||
int echo;
|
||||
{
|
||||
return((char *)0);
|
||||
}
|
||||
#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
|
||||
296
libexec/telnetd/defs.h
Normal file
296
libexec/telnetd/defs.h
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)defs.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* Telnet server defines
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#ifndef BSD
|
||||
# define BSD 43
|
||||
#endif
|
||||
|
||||
#if defined(CRAY) && !defined(LINEMODE)
|
||||
# define SYSV_TERMIO
|
||||
# define LINEMODE
|
||||
# define KLUDGELINEMODE
|
||||
# define DIAGNOSTICS
|
||||
# if defined(UNICOS50) && !defined(UNICOS5)
|
||||
# define UNICOS5
|
||||
# endif
|
||||
# if !defined(UNICOS5)
|
||||
# define BFTPDAEMON
|
||||
# define HAS_IP_TOS
|
||||
# endif
|
||||
#endif /* CRAY */
|
||||
#if defined(UNICOS5) && !defined(NO_SETSID)
|
||||
# define NO_SETSID
|
||||
#endif
|
||||
|
||||
#if defined(PRINTOPTIONS) && defined(DIAGNOSTICS)
|
||||
#define TELOPTS
|
||||
#define TELCMDS
|
||||
#define SLC_NAMES
|
||||
#endif
|
||||
|
||||
#if defined(SYSV_TERMIO) && !defined(USE_TERMIO)
|
||||
# define USE_TERMIO
|
||||
#endif
|
||||
|
||||
#include <sys/socket.h>
|
||||
#ifndef CRAY
|
||||
#include <sys/wait.h>
|
||||
#endif /* CRAY */
|
||||
#include <fcntl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#ifndef FILIO_H
|
||||
#include <sys/ioctl.h>
|
||||
#else
|
||||
#include <sys/filio.h>
|
||||
#endif
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <arpa/telnet.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef __STDC__
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <syslog.h>
|
||||
#ifndef LOG_DAEMON
|
||||
#define LOG_DAEMON 0
|
||||
#endif
|
||||
#ifndef LOG_ODELAY
|
||||
#define LOG_ODELAY 0
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#ifndef NO_STRING_H
|
||||
#include <string.h>
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#ifndef USE_TERMIO
|
||||
#include <sgtty.h>
|
||||
#else
|
||||
# ifdef SYSV_TERMIO
|
||||
# include <termio.h>
|
||||
# else
|
||||
# include <termios.h>
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(USE_TERMIO) || defined(NO_CC_T)
|
||||
typedef unsigned char cc_t;
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX_VDISABLE
|
||||
# ifdef VDISABLE
|
||||
# define _POSIX_VDISABLE VDISABLE
|
||||
# else
|
||||
# define _POSIX_VDISABLE ((unsigned char)'\377')
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CRAY
|
||||
# ifdef CRAY1
|
||||
# include <sys/pty.h>
|
||||
# ifndef FD_ZERO
|
||||
# include <sys/select.h>
|
||||
# endif /* FD_ZERO */
|
||||
# endif /* CRAY1 */
|
||||
|
||||
#include <memory.h>
|
||||
#endif /* CRAY */
|
||||
|
||||
#ifdef __hpux
|
||||
#include <sys/ptyio.h>
|
||||
#endif
|
||||
|
||||
#if !defined(TIOCSCTTY) && defined(TCSETCTTY)
|
||||
# define TIOCSCTTY TCSETCTTY
|
||||
#endif
|
||||
|
||||
#ifndef FD_SET
|
||||
#ifndef HAVE_fd_set
|
||||
typedef struct fd_set { int fds_bits[1]; } fd_set;
|
||||
#endif
|
||||
|
||||
#define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n)))
|
||||
#define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n)))
|
||||
#define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n)))
|
||||
#define FD_ZERO(p) ((p)->fds_bits[0] = 0)
|
||||
#endif /* FD_SET */
|
||||
|
||||
/*
|
||||
* I/O data buffers defines
|
||||
*/
|
||||
#define NETSLOP 64
|
||||
#ifdef CRAY
|
||||
#undef BUFSIZ
|
||||
#define BUFSIZ 2048
|
||||
#endif
|
||||
|
||||
#define NIACCUM(c) { *netip++ = c; \
|
||||
ncc++; \
|
||||
}
|
||||
|
||||
/* clock manipulations */
|
||||
#define settimer(x) (clocks.x = ++clocks.system)
|
||||
#define sequenceIs(x,y) (clocks.x < clocks.y)
|
||||
|
||||
/*
|
||||
* Linemode support states, in decreasing order of importance
|
||||
*/
|
||||
#define REAL_LINEMODE 0x04
|
||||
#define KLUDGE_OK 0x03
|
||||
#define NO_AUTOKLUDGE 0x02
|
||||
#define KLUDGE_LINEMODE 0x01
|
||||
#define NO_LINEMODE 0x00
|
||||
|
||||
/*
|
||||
* Structures of information for each special character function.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned char flag; /* the flags for this function */
|
||||
cc_t val; /* the value of the special character */
|
||||
} slcent, *Slcent;
|
||||
|
||||
typedef struct {
|
||||
slcent defset; /* the default settings */
|
||||
slcent current; /* the current settings */
|
||||
cc_t *sptr; /* a pointer to the char in */
|
||||
/* system data structures */
|
||||
} slcfun, *Slcfun;
|
||||
|
||||
#ifdef DIAGNOSTICS
|
||||
/*
|
||||
* Diagnostics capabilities
|
||||
*/
|
||||
#define TD_REPORT 0x01 /* Report operations to client */
|
||||
#define TD_EXERCISE 0x02 /* Exercise client's implementation */
|
||||
#define TD_NETDATA 0x04 /* Display received data stream */
|
||||
#define TD_PTYDATA 0x08 /* Display data passed to pty */
|
||||
#define TD_OPTIONS 0x10 /* Report just telnet options */
|
||||
#endif /* DIAGNOSTICS */
|
||||
|
||||
/*
|
||||
* We keep track of each side of the option negotiation.
|
||||
*/
|
||||
|
||||
#define MY_STATE_WILL 0x01
|
||||
#define MY_WANT_STATE_WILL 0x02
|
||||
#define MY_STATE_DO 0x04
|
||||
#define MY_WANT_STATE_DO 0x08
|
||||
|
||||
/*
|
||||
* Macros to check the current state of things
|
||||
*/
|
||||
|
||||
#define my_state_is_do(opt) (options[opt]&MY_STATE_DO)
|
||||
#define my_state_is_will(opt) (options[opt]&MY_STATE_WILL)
|
||||
#define my_want_state_is_do(opt) (options[opt]&MY_WANT_STATE_DO)
|
||||
#define my_want_state_is_will(opt) (options[opt]&MY_WANT_STATE_WILL)
|
||||
|
||||
#define my_state_is_dont(opt) (!my_state_is_do(opt))
|
||||
#define my_state_is_wont(opt) (!my_state_is_will(opt))
|
||||
#define my_want_state_is_dont(opt) (!my_want_state_is_do(opt))
|
||||
#define my_want_state_is_wont(opt) (!my_want_state_is_will(opt))
|
||||
|
||||
#define set_my_state_do(opt) (options[opt] |= MY_STATE_DO)
|
||||
#define set_my_state_will(opt) (options[opt] |= MY_STATE_WILL)
|
||||
#define set_my_want_state_do(opt) (options[opt] |= MY_WANT_STATE_DO)
|
||||
#define set_my_want_state_will(opt) (options[opt] |= MY_WANT_STATE_WILL)
|
||||
|
||||
#define set_my_state_dont(opt) (options[opt] &= ~MY_STATE_DO)
|
||||
#define set_my_state_wont(opt) (options[opt] &= ~MY_STATE_WILL)
|
||||
#define set_my_want_state_dont(opt) (options[opt] &= ~MY_WANT_STATE_DO)
|
||||
#define set_my_want_state_wont(opt) (options[opt] &= ~MY_WANT_STATE_WILL)
|
||||
|
||||
/*
|
||||
* Tricky code here. What we want to know is if the MY_STATE_WILL
|
||||
* and MY_WANT_STATE_WILL bits have the same value. Since the two
|
||||
* bits are adjacent, a little arithmatic will show that by adding
|
||||
* in the lower bit, the upper bit will be set if the two bits were
|
||||
* different, and clear if they were the same.
|
||||
*/
|
||||
#define my_will_wont_is_changing(opt) \
|
||||
((options[opt]+MY_STATE_WILL) & MY_WANT_STATE_WILL)
|
||||
|
||||
#define my_do_dont_is_changing(opt) \
|
||||
((options[opt]+MY_STATE_DO) & MY_WANT_STATE_DO)
|
||||
|
||||
/*
|
||||
* Make everything symetrical
|
||||
*/
|
||||
|
||||
#define HIS_STATE_WILL MY_STATE_DO
|
||||
#define HIS_WANT_STATE_WILL MY_WANT_STATE_DO
|
||||
#define HIS_STATE_DO MY_STATE_WILL
|
||||
#define HIS_WANT_STATE_DO MY_WANT_STATE_WILL
|
||||
|
||||
#define his_state_is_do my_state_is_will
|
||||
#define his_state_is_will my_state_is_do
|
||||
#define his_want_state_is_do my_want_state_is_will
|
||||
#define his_want_state_is_will my_want_state_is_do
|
||||
|
||||
#define his_state_is_dont my_state_is_wont
|
||||
#define his_state_is_wont my_state_is_dont
|
||||
#define his_want_state_is_dont my_want_state_is_wont
|
||||
#define his_want_state_is_wont my_want_state_is_dont
|
||||
|
||||
#define set_his_state_do set_my_state_will
|
||||
#define set_his_state_will set_my_state_do
|
||||
#define set_his_want_state_do set_my_want_state_will
|
||||
#define set_his_want_state_will set_my_want_state_do
|
||||
|
||||
#define set_his_state_dont set_my_state_wont
|
||||
#define set_his_state_wont set_my_state_dont
|
||||
#define set_his_want_state_dont set_my_want_state_wont
|
||||
#define set_his_want_state_wont set_my_want_state_dont
|
||||
|
||||
#define his_will_wont_is_changing my_do_dont_is_changing
|
||||
#define his_do_dont_is_changing my_will_wont_is_changing
|
||||
240
libexec/telnetd/ext.h
Normal file
240
libexec/telnetd/ext.h
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ext.h 8.2 (Berkeley) 12/15/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* Telnet server variable declarations
|
||||
*/
|
||||
extern char options[256];
|
||||
extern char do_dont_resp[256];
|
||||
extern char will_wont_resp[256];
|
||||
extern int linemode; /* linemode on/off */
|
||||
#ifdef LINEMODE
|
||||
extern int uselinemode; /* what linemode to use (on/off) */
|
||||
extern int editmode; /* edit modes in use */
|
||||
extern int useeditmode; /* edit modes to use */
|
||||
extern int alwayslinemode; /* command line option */
|
||||
# ifdef KLUDGELINEMODE
|
||||
extern int lmodetype; /* Client support for linemode */
|
||||
# endif /* KLUDGELINEMODE */
|
||||
#endif /* LINEMODE */
|
||||
extern int flowmode; /* current flow control state */
|
||||
extern int restartany; /* restart output on any character state */
|
||||
#ifdef DIAGNOSTICS
|
||||
extern int diagnostic; /* telnet diagnostic capabilities */
|
||||
#endif /* DIAGNOSTICS */
|
||||
#ifdef BFTPDAEMON
|
||||
extern int bftpd; /* behave as bftp daemon */
|
||||
#endif /* BFTPDAEMON */
|
||||
#if defined(SecurID)
|
||||
extern int require_SecurID;
|
||||
#endif
|
||||
#if defined(AUTHENTICATION)
|
||||
extern int auth_level;
|
||||
#endif
|
||||
|
||||
extern slcfun slctab[NSLC + 1]; /* slc mapping table */
|
||||
|
||||
char *terminaltype;
|
||||
|
||||
/*
|
||||
* I/O data buffers, pointers, and counters.
|
||||
*/
|
||||
extern char ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp;
|
||||
|
||||
extern char netibuf[BUFSIZ], *netip;
|
||||
|
||||
extern char netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp;
|
||||
extern char *neturg; /* one past last bye of urgent data */
|
||||
|
||||
extern int pcc, ncc;
|
||||
|
||||
#if defined(CRAY2) && defined(UNICOS5)
|
||||
extern int unpcc; /* characters left unprocessed by CRAY-2 terminal routine */
|
||||
extern char *unptyip; /* pointer to remaining characters in buffer */
|
||||
#endif
|
||||
|
||||
extern int pty, net;
|
||||
extern char *line;
|
||||
extern int SYNCHing; /* we are in TELNET SYNCH mode */
|
||||
|
||||
#ifndef P
|
||||
# ifdef __STDC__
|
||||
# define P(x) x
|
||||
# else
|
||||
# define P(x) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
extern void
|
||||
_termstat P((void)),
|
||||
add_slc P((int, int, int)),
|
||||
check_slc P((void)),
|
||||
change_slc P((int, int, int)),
|
||||
cleanup P((int)),
|
||||
clientstat P((int, int, int)),
|
||||
copy_termbuf P((char *, int)),
|
||||
deferslc P((void)),
|
||||
defer_terminit P((void)),
|
||||
do_opt_slc P((unsigned char *, int)),
|
||||
doeof P((void)),
|
||||
dooption P((int)),
|
||||
dontoption P((int)),
|
||||
edithost P((char *, char *)),
|
||||
fatal P((int, char *)),
|
||||
fatalperror P((int, char *)),
|
||||
get_slc_defaults P((void)),
|
||||
init_env P((void)),
|
||||
init_termbuf P((void)),
|
||||
interrupt P((void)),
|
||||
localstat P((void)),
|
||||
flowstat P((void)),
|
||||
netclear P((void)),
|
||||
netflush P((void)),
|
||||
#ifdef DIAGNOSTICS
|
||||
printoption P((char *, int)),
|
||||
printdata P((char *, char *, int)),
|
||||
printsub P((int, unsigned char *, int)),
|
||||
#endif
|
||||
ptyflush P((void)),
|
||||
putchr P((int)),
|
||||
putf P((char *, char *)),
|
||||
recv_ayt P((void)),
|
||||
send_do P((int, int)),
|
||||
send_dont P((int, int)),
|
||||
send_slc P((void)),
|
||||
send_status P((void)),
|
||||
send_will P((int, int)),
|
||||
send_wont P((int, int)),
|
||||
sendbrk P((void)),
|
||||
sendsusp P((void)),
|
||||
set_termbuf P((void)),
|
||||
start_login P((char *, int, char *)),
|
||||
start_slc P((int)),
|
||||
#if defined(AUTHENTICATION)
|
||||
start_slave P((char *)),
|
||||
#else
|
||||
start_slave P((char *, int, char *)),
|
||||
#endif
|
||||
suboption P((void)),
|
||||
telrcv P((void)),
|
||||
ttloop P((void)),
|
||||
tty_binaryin P((int)),
|
||||
tty_binaryout P((int));
|
||||
|
||||
extern int
|
||||
end_slc P((unsigned char **)),
|
||||
getnpty P((void)),
|
||||
#ifndef convex
|
||||
getpty P((int *)),
|
||||
#endif
|
||||
login_tty P((int)),
|
||||
spcset P((int, cc_t *, cc_t **)),
|
||||
stilloob P((int)),
|
||||
terminit P((void)),
|
||||
termstat P((void)),
|
||||
tty_flowmode P((void)),
|
||||
tty_restartany P((void)),
|
||||
tty_isbinaryin P((void)),
|
||||
tty_isbinaryout P((void)),
|
||||
tty_iscrnl P((void)),
|
||||
tty_isecho P((void)),
|
||||
tty_isediting P((void)),
|
||||
tty_islitecho P((void)),
|
||||
tty_isnewmap P((void)),
|
||||
tty_israw P((void)),
|
||||
tty_issofttab P((void)),
|
||||
tty_istrapsig P((void)),
|
||||
tty_linemode P((void));
|
||||
|
||||
extern void
|
||||
tty_rspeed P((int)),
|
||||
tty_setecho P((int)),
|
||||
tty_setedit P((int)),
|
||||
tty_setlinemode P((int)),
|
||||
tty_setlitecho P((int)),
|
||||
tty_setsig P((int)),
|
||||
tty_setsofttab P((int)),
|
||||
tty_tspeed P((int)),
|
||||
willoption P((int)),
|
||||
wontoption P((int)),
|
||||
writenet P((unsigned char *, int));
|
||||
|
||||
#ifdef ENCRYPTION
|
||||
extern void (*encrypt_output) P((unsigned char *, int));
|
||||
extern int (*decrypt_input) P((int));
|
||||
extern char *nclearto;
|
||||
#endif /* ENCRYPTION */
|
||||
|
||||
|
||||
/*
|
||||
* The following are some clocks used to decide how to interpret
|
||||
* the relationship between various variables.
|
||||
*/
|
||||
|
||||
extern struct {
|
||||
int
|
||||
system, /* what the current time is */
|
||||
echotoggle, /* last time user entered echo character */
|
||||
modenegotiated, /* last time operating mode negotiated */
|
||||
didnetreceive, /* last time we read data from network */
|
||||
ttypesubopt, /* ttype subopt is received */
|
||||
tspeedsubopt, /* tspeed subopt is received */
|
||||
environsubopt, /* environ subopt is received */
|
||||
oenvironsubopt, /* old environ subopt is received */
|
||||
xdisplocsubopt, /* xdisploc subopt is received */
|
||||
baseline, /* time started to do timed action */
|
||||
gotDM; /* when did we last see a data mark */
|
||||
} clocks;
|
||||
|
||||
|
||||
#if defined(CRAY2) && defined(UNICOS5)
|
||||
extern int needtermstat;
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_IM
|
||||
# ifdef CRAY
|
||||
# define DEFAULT_IM "\r\n\r\nCray UNICOS (%h) (%t)\r\n\r\r\n\r"
|
||||
# else
|
||||
# ifdef sun
|
||||
# define DEFAULT_IM "\r\n\r\nSunOS UNIX (%h) (%t)\r\n\r\r\n\r"
|
||||
# else
|
||||
# ifdef ultrix
|
||||
# define DEFAULT_IM "\r\n\r\nULTRIX (%h) (%t)\r\n\r\r\n\r"
|
||||
# else
|
||||
# define DEFAULT_IM "\r\n\r\n4.4 BSD UNIX (%h) (%t)\r\n\r\r\n\r"
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
48
libexec/telnetd/global.c
Normal file
48
libexec/telnetd/global.c
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)global.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Allocate global variables. We do this
|
||||
* by including the header file that defines
|
||||
* them all as externs, but first we define
|
||||
* the keyword "extern" to be nothing, so that
|
||||
* we will actually allocate the space.
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
#define extern
|
||||
#include "ext.h"
|
||||
55
libexec/telnetd/pathnames.h
Normal file
55
libexec/telnetd/pathnames.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
#if BSD > 43
|
||||
|
||||
# include <paths.h>
|
||||
|
||||
# ifndef _PATH_LOGIN
|
||||
# define _PATH_LOGIN "/usr/bin/login"
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
# define _PATH_TTY "/dev/tty"
|
||||
# ifndef _PATH_LOGIN
|
||||
# define _PATH_LOGIN "/bin/login"
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef BFTPDAEMON
|
||||
#define BFTPPATH "/usr/ucb/bftp"
|
||||
#endif /* BFTPDAEMON */
|
||||
493
libexec/telnetd/slc.c
Normal file
493
libexec/telnetd/slc.c
Normal file
|
|
@ -0,0 +1,493 @@
|
|||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)slc.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "telnetd.h"
|
||||
|
||||
#ifdef LINEMODE
|
||||
/*
|
||||
* local varibles
|
||||
*/
|
||||
static unsigned char *def_slcbuf = (unsigned char *)0;
|
||||
static int def_slclen = 0;
|
||||
static int slcchange; /* change to slc is requested */
|
||||
static unsigned char *slcptr; /* pointer into slc buffer */
|
||||
static unsigned char slcbuf[NSLC*6]; /* buffer for slc negotiation */
|
||||
|
||||
/*
|
||||
* send_slc
|
||||
*
|
||||
* Write out the current special characters to the client.
|
||||
*/
|
||||
void
|
||||
send_slc()
|
||||
{
|
||||
register int i;
|
||||
|
||||
/*
|
||||
* Send out list of triplets of special characters
|
||||
* to client. We only send info on the characters
|
||||
* that are currently supported.
|
||||
*/
|
||||
for (i = 1; i <= NSLC; i++) {
|
||||
if ((slctab[i].defset.flag & SLC_LEVELBITS) == SLC_NOSUPPORT)
|
||||
continue;
|
||||
add_slc((unsigned char)i, slctab[i].current.flag,
|
||||
slctab[i].current.val);
|
||||
}
|
||||
|
||||
} /* end of send_slc */
|
||||
|
||||
/*
|
||||
* default_slc
|
||||
*
|
||||
* Set pty special characters to all the defaults.
|
||||
*/
|
||||
void
|
||||
default_slc()
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 1; i <= NSLC; i++) {
|
||||
slctab[i].current.val = slctab[i].defset.val;
|
||||
if (slctab[i].current.val == (cc_t)(_POSIX_VDISABLE))
|
||||
slctab[i].current.flag = SLC_NOSUPPORT;
|
||||
else
|
||||
slctab[i].current.flag = slctab[i].defset.flag;
|
||||
if (slctab[i].sptr) {
|
||||
*(slctab[i].sptr) = slctab[i].defset.val;
|
||||
}
|
||||
}
|
||||
slcchange = 1;
|
||||
|
||||
} /* end of default_slc */
|
||||
#endif /* LINEMODE */
|
||||
|
||||
/*
|
||||
* get_slc_defaults
|
||||
*
|
||||
* Initialize the slc mapping table.
|
||||
*/
|
||||
void
|
||||
get_slc_defaults()
|
||||
{
|
||||
register int i;
|
||||
|
||||
init_termbuf();
|
||||
|
||||
for (i = 1; i <= NSLC; i++) {
|
||||
slctab[i].defset.flag =
|
||||
spcset(i, &slctab[i].defset.val, &slctab[i].sptr);
|
||||
slctab[i].current.flag = SLC_NOSUPPORT;
|
||||
slctab[i].current.val = 0;
|
||||
}
|
||||
|
||||
} /* end of get_slc_defaults */
|
||||
|
||||
#ifdef LINEMODE
|
||||
/*
|
||||
* add_slc
|
||||
*
|
||||
* Add an slc triplet to the slc buffer.
|
||||
*/
|
||||
void
|
||||
add_slc(func, flag, val)
|
||||
register char func, flag;
|
||||
register cc_t val;
|
||||
{
|
||||
|
||||
if ((*slcptr++ = (unsigned char)func) == 0xff)
|
||||
*slcptr++ = 0xff;
|
||||
|
||||
if ((*slcptr++ = (unsigned char)flag) == 0xff)
|
||||
*slcptr++ = 0xff;
|
||||
|
||||
if ((*slcptr++ = (unsigned char)val) == 0xff)
|
||||
*slcptr++ = 0xff;
|
||||
|
||||
} /* end of add_slc */
|
||||
|
||||
/*
|
||||
* start_slc
|
||||
*
|
||||
* Get ready to process incoming slc's and respond to them.
|
||||
*
|
||||
* The parameter getit is non-zero if it is necessary to grab a copy
|
||||
* of the terminal control structures.
|
||||
*/
|
||||
void
|
||||
start_slc(getit)
|
||||
register int getit;
|
||||
{
|
||||
|
||||
slcchange = 0;
|
||||
if (getit)
|
||||
init_termbuf();
|
||||
(void) sprintf((char *)slcbuf, "%c%c%c%c",
|
||||
IAC, SB, TELOPT_LINEMODE, LM_SLC);
|
||||
slcptr = slcbuf + 4;
|
||||
|
||||
} /* end of start_slc */
|
||||
|
||||
/*
|
||||
* end_slc
|
||||
*
|
||||
* Finish up the slc negotiation. If something to send, then send it.
|
||||
*/
|
||||
int
|
||||
end_slc(bufp)
|
||||
register unsigned char **bufp;
|
||||
{
|
||||
register int len;
|
||||
void netflush();
|
||||
|
||||
/*
|
||||
* If a change has occured, store the new terminal control
|
||||
* structures back to the terminal driver.
|
||||
*/
|
||||
if (slcchange) {
|
||||
set_termbuf();
|
||||
}
|
||||
|
||||
/*
|
||||
* If the pty state has not yet been fully processed and there is a
|
||||
* deferred slc request from the client, then do not send any
|
||||
* sort of slc negotiation now. We will respond to the client's
|
||||
* request very soon.
|
||||
*/
|
||||
if (def_slcbuf && (terminit() == 0)) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (slcptr > (slcbuf + 4)) {
|
||||
if (bufp) {
|
||||
*bufp = &slcbuf[4];
|
||||
return(slcptr - slcbuf - 4);
|
||||
} else {
|
||||
(void) sprintf((char *)slcptr, "%c%c", IAC, SE);
|
||||
slcptr += 2;
|
||||
len = slcptr - slcbuf;
|
||||
writenet(slcbuf, len);
|
||||
netflush(); /* force it out immediately */
|
||||
DIAG(TD_OPTIONS, printsub('>', slcbuf+2, len-2););
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
|
||||
} /* end of end_slc */
|
||||
|
||||
/*
|
||||
* process_slc
|
||||
*
|
||||
* Figure out what to do about the client's slc
|
||||
*/
|
||||
void
|
||||
process_slc(func, flag, val)
|
||||
register unsigned char func, flag;
|
||||
register cc_t val;
|
||||
{
|
||||
register int hislevel, mylevel, ack;
|
||||
|
||||
/*
|
||||
* Ensure that we know something about this function
|
||||
*/
|
||||
if (func > NSLC) {
|
||||
add_slc(func, SLC_NOSUPPORT, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the special case requests of 0 SLC_DEFAULT 0
|
||||
* and 0 SLC_VARIABLE 0. Be a little forgiving here, don't
|
||||
* worry about whether the value is actually 0 or not.
|
||||
*/
|
||||
if (func == 0) {
|
||||
if ((flag = flag & SLC_LEVELBITS) == SLC_DEFAULT) {
|
||||
default_slc();
|
||||
send_slc();
|
||||
} else if (flag == SLC_VARIABLE) {
|
||||
send_slc();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Appears to be a function that we know something about. So
|
||||
* get on with it and see what we know.
|
||||
*/
|
||||
|
||||
hislevel = flag & SLC_LEVELBITS;
|
||||
mylevel = slctab[func].current.flag & SLC_LEVELBITS;
|
||||
ack = flag & SLC_ACK;
|
||||
/*
|
||||
* ignore the command if:
|
||||
* the function value and level are the same as what we already have;
|
||||
* or the level is the same and the ack bit is set
|
||||
*/
|
||||
if (hislevel == mylevel && (val == slctab[func].current.val || ack)) {
|
||||
return;
|
||||
} else if (ack) {
|
||||
/*
|
||||
* If we get here, we got an ack, but the levels don't match.
|
||||
* This shouldn't happen. If it does, it is probably because
|
||||
* we have sent two requests to set a variable without getting
|
||||
* a response between them, and this is the first response.
|
||||
* So, ignore it, and wait for the next response.
|
||||
*/
|
||||
return;
|
||||
} else {
|
||||
change_slc(func, flag, val);
|
||||
}
|
||||
|
||||
} /* end of process_slc */
|
||||
|
||||
/*
|
||||
* change_slc
|
||||
*
|
||||
* Process a request to change one of our special characters.
|
||||
* Compare client's request with what we are capable of supporting.
|
||||
*/
|
||||
void
|
||||
change_slc(func, flag, val)
|
||||
register char func, flag;
|
||||
register cc_t val;
|
||||
{
|
||||
register int hislevel, mylevel;
|
||||
|
||||
hislevel = flag & SLC_LEVELBITS;
|
||||
mylevel = slctab[func].defset.flag & SLC_LEVELBITS;
|
||||
/*
|
||||
* If client is setting a function to NOSUPPORT
|
||||
* or DEFAULT, then we can easily and directly
|
||||
* accomodate the request.
|
||||
*/
|
||||
if (hislevel == SLC_NOSUPPORT) {
|
||||
slctab[func].current.flag = flag;
|
||||
slctab[func].current.val = (cc_t)_POSIX_VDISABLE;
|
||||
flag |= SLC_ACK;
|
||||
add_slc(func, flag, val);
|
||||
return;
|
||||
}
|
||||
if (hislevel == SLC_DEFAULT) {
|
||||
/*
|
||||
* Special case here. If client tells us to use
|
||||
* the default on a function we don't support, then
|
||||
* return NOSUPPORT instead of what we may have as a
|
||||
* default level of DEFAULT.
|
||||
*/
|
||||
if (mylevel == SLC_DEFAULT) {
|
||||
slctab[func].current.flag = SLC_NOSUPPORT;
|
||||
} else {
|
||||
slctab[func].current.flag = slctab[func].defset.flag;
|
||||
}
|
||||
slctab[func].current.val = slctab[func].defset.val;
|
||||
add_slc(func, slctab[func].current.flag,
|
||||
slctab[func].current.val);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Client wants us to change to a new value or he
|
||||
* is telling us that he can't change to our value.
|
||||
* Some of the slc's we support and can change,
|
||||
* some we do support but can't change,
|
||||
* and others we don't support at all.
|
||||
* If we can change it then we have a pointer to
|
||||
* the place to put the new value, so change it,
|
||||
* otherwise, continue the negotiation.
|
||||
*/
|
||||
if (slctab[func].sptr) {
|
||||
/*
|
||||
* We can change this one.
|
||||
*/
|
||||
slctab[func].current.val = val;
|
||||
*(slctab[func].sptr) = val;
|
||||
slctab[func].current.flag = flag;
|
||||
flag |= SLC_ACK;
|
||||
slcchange = 1;
|
||||
add_slc(func, flag, val);
|
||||
} else {
|
||||
/*
|
||||
* It is not possible for us to support this
|
||||
* request as he asks.
|
||||
*
|
||||
* If our level is DEFAULT, then just ack whatever was
|
||||
* sent.
|
||||
*
|
||||
* If he can't change and we can't change,
|
||||
* then degenerate to NOSUPPORT.
|
||||
*
|
||||
* Otherwise we send our level back to him, (CANTCHANGE
|
||||
* or NOSUPPORT) and if CANTCHANGE, send
|
||||
* our value as well.
|
||||
*/
|
||||
if (mylevel == SLC_DEFAULT) {
|
||||
slctab[func].current.flag = flag;
|
||||
slctab[func].current.val = val;
|
||||
flag |= SLC_ACK;
|
||||
} else if (hislevel == SLC_CANTCHANGE &&
|
||||
mylevel == SLC_CANTCHANGE) {
|
||||
flag &= ~SLC_LEVELBITS;
|
||||
flag |= SLC_NOSUPPORT;
|
||||
slctab[func].current.flag = flag;
|
||||
} else {
|
||||
flag &= ~SLC_LEVELBITS;
|
||||
flag |= mylevel;
|
||||
slctab[func].current.flag = flag;
|
||||
if (mylevel == SLC_CANTCHANGE) {
|
||||
slctab[func].current.val =
|
||||
slctab[func].defset.val;
|
||||
val = slctab[func].current.val;
|
||||
}
|
||||
|
||||
}
|
||||
add_slc(func, flag, val);
|
||||
}
|
||||
|
||||
} /* end of change_slc */
|
||||
|
||||
#if defined(USE_TERMIO) && (VEOF == VMIN)
|
||||
cc_t oldeofc = '\004';
|
||||
#endif
|
||||
|
||||
/*
|
||||
* check_slc
|
||||
*
|
||||
* Check the special characters in use and notify the client if any have
|
||||
* changed. Only those characters that are capable of being changed are
|
||||
* likely to have changed. If a local change occurs, kick the support level
|
||||
* and flags up to the defaults.
|
||||
*/
|
||||
void
|
||||
check_slc()
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 1; i <= NSLC; i++) {
|
||||
#if defined(USE_TERMIO) && (VEOF == VMIN)
|
||||
/*
|
||||
* In a perfect world this would be a neat little
|
||||
* function. But in this world, we should not notify
|
||||
* client of changes to the VEOF char when
|
||||
* ICANON is off, because it is not representing
|
||||
* a special character.
|
||||
*/
|
||||
if (i == SLC_EOF) {
|
||||
if (!tty_isediting())
|
||||
continue;
|
||||
else if (slctab[i].sptr)
|
||||
oldeofc = *(slctab[i].sptr);
|
||||
}
|
||||
#endif /* defined(USE_TERMIO) && defined(SYSV_TERMIO) */
|
||||
if (slctab[i].sptr &&
|
||||
(*(slctab[i].sptr) != slctab[i].current.val)) {
|
||||
slctab[i].current.val = *(slctab[i].sptr);
|
||||
if (*(slctab[i].sptr) == (cc_t)_POSIX_VDISABLE)
|
||||
slctab[i].current.flag = SLC_NOSUPPORT;
|
||||
else
|
||||
slctab[i].current.flag = slctab[i].defset.flag;
|
||||
add_slc((unsigned char)i, slctab[i].current.flag,
|
||||
slctab[i].current.val);
|
||||
}
|
||||
}
|
||||
|
||||
} /* check_slc */
|
||||
|
||||
/*
|
||||
* do_opt_slc
|
||||
*
|
||||
* Process an slc option buffer. Defer processing of incoming slc's
|
||||
* until after the terminal state has been processed. Save the first slc
|
||||
* request that comes along, but discard all others.
|
||||
*
|
||||
* ptr points to the beginning of the buffer, len is the length.
|
||||
*/
|
||||
void
|
||||
do_opt_slc(ptr, len)
|
||||
register unsigned char *ptr;
|
||||
register int len;
|
||||
{
|
||||
register unsigned char func, flag;
|
||||
cc_t val;
|
||||
register unsigned char *end = ptr + len;
|
||||
|
||||
if (terminit()) { /* go ahead */
|
||||
while (ptr < end) {
|
||||
func = *ptr++;
|
||||
if (ptr >= end) break;
|
||||
flag = *ptr++;
|
||||
if (ptr >= end) break;
|
||||
val = (cc_t)*ptr++;
|
||||
|
||||
process_slc(func, flag, val);
|
||||
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* save this slc buffer if it is the first, otherwise dump
|
||||
* it.
|
||||
*/
|
||||
if (def_slcbuf == (unsigned char *)0) {
|
||||
def_slclen = len;
|
||||
def_slcbuf = (unsigned char *)malloc((unsigned)len);
|
||||
if (def_slcbuf == (unsigned char *)0)
|
||||
return; /* too bad */
|
||||
bcopy(ptr, def_slcbuf, len);
|
||||
}
|
||||
}
|
||||
|
||||
} /* end of do_opt_slc */
|
||||
|
||||
/*
|
||||
* deferslc
|
||||
*
|
||||
* Do slc stuff that was deferred.
|
||||
*/
|
||||
void
|
||||
deferslc()
|
||||
{
|
||||
if (def_slcbuf) {
|
||||
start_slc(1);
|
||||
do_opt_slc(def_slcbuf, def_slclen);
|
||||
(void) end_slc(0);
|
||||
free(def_slcbuf);
|
||||
def_slcbuf = (unsigned char *)0;
|
||||
def_slclen = 0;
|
||||
}
|
||||
|
||||
} /* end of deferslc */
|
||||
|
||||
#endif /* LINEMODE */
|
||||
1620
libexec/telnetd/state.c
Normal file
1620
libexec/telnetd/state.c
Normal file
File diff suppressed because it is too large
Load diff
2135
libexec/telnetd/sys_term.c
Normal file
2135
libexec/telnetd/sys_term.c
Normal file
File diff suppressed because it is too large
Load diff
605
libexec/telnetd/telnetd.8
Normal file
605
libexec/telnetd/telnetd.8
Normal file
|
|
@ -0,0 +1,605 @@
|
|||
.\" Copyright (c) 1983, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)telnetd.8 8.3 (Berkeley) 3/1/94
|
||||
.\"
|
||||
.Dd March 1, 1994
|
||||
.Dt TELNETD 8
|
||||
.Os BSD 4.2
|
||||
.Sh NAME
|
||||
.Nm telnetd
|
||||
.Nd DARPA
|
||||
.Tn TELNET
|
||||
protocol server
|
||||
.Sh SYNOPSIS
|
||||
.Nm /usr/libexec/telnetd
|
||||
.Op Fl BUhlkns
|
||||
.Op Fl D Ar debugmode
|
||||
.Op Fl I Ns Ar initid
|
||||
.Op Fl S Ar tos
|
||||
.Op Fl X Ar authtype
|
||||
.Op Fl a Ar authmode
|
||||
.Op Fl edebug
|
||||
.Op Fl r Ns Ar lowpty-highpty
|
||||
.Op Fl u Ar len
|
||||
.Op Fl debug Op Ar port
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm telnetd
|
||||
command is a server which supports the
|
||||
.Tn DARPA
|
||||
standard
|
||||
.Tn TELNET
|
||||
virtual terminal protocol.
|
||||
.Nm Telnetd
|
||||
is normally invoked by the internet server (see
|
||||
.Xr inetd 8 )
|
||||
for requests to connect to the
|
||||
.Tn TELNET
|
||||
port as indicated by the
|
||||
.Pa /etc/services
|
||||
file (see
|
||||
.Xr services 5 ) .
|
||||
The
|
||||
.Fl debug
|
||||
option may be used to start up
|
||||
.Nm telnetd
|
||||
manually, instead of through
|
||||
.Xr inetd 8 .
|
||||
If started up this way,
|
||||
.Ar port
|
||||
may be specified to run
|
||||
.Nm telnetd
|
||||
on an alternate
|
||||
.Tn TCP
|
||||
port number.
|
||||
.Pp
|
||||
The
|
||||
.Nm telnetd
|
||||
command accepts the following options:
|
||||
.Bl -tag -width "-a authmode"
|
||||
.It Fl a Ar authmode
|
||||
This option may be used for specifying what mode should
|
||||
be used for authentication.
|
||||
Note that this option is only useful if
|
||||
.Nm telnetd
|
||||
has been compiled with support for the
|
||||
.Dv AUTHENTICATION
|
||||
option.
|
||||
There are several valid values for
|
||||
.Ar authmode:
|
||||
.Bl -tag -width debug
|
||||
.It debug
|
||||
Turns on authentication debugging code.
|
||||
.It user
|
||||
Only allow connections when the remote user
|
||||
can provide valid authentication information
|
||||
to identify the remote user,
|
||||
and is allowed access to the specified account
|
||||
without providing a password.
|
||||
.It valid
|
||||
Only allow connections when the remote user
|
||||
can provide valid authentication information
|
||||
to identify the remote user.
|
||||
The
|
||||
.Xr login 1
|
||||
command will provide any additional user verification
|
||||
needed if the remote user is not allowed automatic
|
||||
access to the specified account.
|
||||
.It other
|
||||
Only allow connections that supply some authentication information.
|
||||
This option is currently not supported
|
||||
by any of the existing authentication mechanisms,
|
||||
and is thus the same as specifying
|
||||
.Fl a
|
||||
.Cm valid .
|
||||
.It none
|
||||
This is the default state.
|
||||
Authentication information is not required.
|
||||
If no or insufficient authentication information
|
||||
is provided, then the
|
||||
.Xr login 1
|
||||
program will provide the necessary user
|
||||
verification.
|
||||
.It off
|
||||
This disables the authentication code.
|
||||
All user verification will happen through the
|
||||
.Xr login 1
|
||||
program.
|
||||
.El
|
||||
.It Fl B
|
||||
Specifies bftp server mode. In this mode,
|
||||
.Nm telnetd
|
||||
causes login to start a
|
||||
.Xr bftp 1
|
||||
session rather than the user's
|
||||
normal shell. In bftp daemon mode normal
|
||||
logins are not supported, and it must be used
|
||||
on a port other than the normal
|
||||
.Tn TELNET
|
||||
port.
|
||||
.It Fl D Ar debugmode
|
||||
This option may be used for debugging purposes.
|
||||
This allows
|
||||
.Nm telnetd
|
||||
to print out debugging information
|
||||
to the connection, allowing the user to see what
|
||||
.Nm telnetd
|
||||
is doing.
|
||||
There are several possible values for
|
||||
.Ar debugmode:
|
||||
.Bl -tag -width exercise
|
||||
.It Cm options
|
||||
Prints information about the negotiation of
|
||||
.Tn TELNET
|
||||
options.
|
||||
.It Cm report
|
||||
Prints the
|
||||
.Cm options
|
||||
information, plus some additional information
|
||||
about what processing is going on.
|
||||
.It Cm netdata
|
||||
Displays the data stream received by
|
||||
.Nm telnetd.
|
||||
.It Cm ptydata
|
||||
Displays data written to the pty.
|
||||
.It Cm exercise
|
||||
Has not been implemented yet.
|
||||
.El
|
||||
.It Fl debug
|
||||
Enables debugging on each socket created by
|
||||
.Nm telnetd
|
||||
(see
|
||||
.Dv SO_DEBUG
|
||||
in
|
||||
.Xr socket 2 ) .
|
||||
.It Fl edebug
|
||||
If
|
||||
.Nm telnetd
|
||||
has been compiled with support for data encryption, then the
|
||||
.Fl edebug
|
||||
option may be used to enable encryption debugging code.
|
||||
.It Fl h
|
||||
Disables the printing of host-specific information before
|
||||
login has been completed.
|
||||
.It Fl I Ar initid
|
||||
This option is only applicable to
|
||||
.Tn UNICOS
|
||||
systems prior to 7.0.
|
||||
It specifies the
|
||||
.Dv ID
|
||||
from
|
||||
.Pa /etc/inittab
|
||||
to use when init starts login sessions. The default
|
||||
.Dv ID
|
||||
is
|
||||
.Dv fe.
|
||||
.It Fl k
|
||||
This option is only useful if
|
||||
.Nm telnetd
|
||||
has been compiled with both linemode and kludge linemode
|
||||
support. If the
|
||||
.Fl k
|
||||
option is specified, then if the remote client does not
|
||||
support the
|
||||
.Dv LINEMODE
|
||||
option, then
|
||||
.Nm telnetd
|
||||
will operate in character at a time mode.
|
||||
It will still support kludge linemode, but will only
|
||||
go into kludge linemode if the remote client requests
|
||||
it.
|
||||
(This is done by by the client sending
|
||||
.Dv DONT SUPPRESS-GO-AHEAD
|
||||
and
|
||||
.Dv DONT ECHO . )
|
||||
The
|
||||
.Fl k
|
||||
option is most useful when there are remote clients
|
||||
that do not support kludge linemode, but pass the heuristic
|
||||
(if they respond with
|
||||
.Dv WILL TIMING-MARK
|
||||
in response to a
|
||||
.Dv DO TIMING-MARK)
|
||||
for kludge linemode support.
|
||||
.It Fl l
|
||||
Specifies line mode. Tries to force clients to use line-
|
||||
at-a-time mode.
|
||||
If the
|
||||
.Dv LINEMODE
|
||||
option is not supported, it will go
|
||||
into kludge linemode.
|
||||
.It Fl n
|
||||
Disable
|
||||
.Dv TCP
|
||||
keep-alives. Normally
|
||||
.Nm telnetd
|
||||
enables the
|
||||
.Tn TCP
|
||||
keep-alive mechanism to probe connections that
|
||||
have been idle for some period of time to determine
|
||||
if the client is still there, so that idle connections
|
||||
from machines that have crashed or can no longer
|
||||
be reached may be cleaned up.
|
||||
.It Fl r Ar lowpty-highpty
|
||||
This option is only enabled when
|
||||
.Nm telnetd
|
||||
is compiled for
|
||||
.Dv UNICOS.
|
||||
It specifies an inclusive range of pseudo-terminal devices to
|
||||
use. If the system has sysconf variable
|
||||
.Dv _SC_CRAY_NPTY
|
||||
configured, the default pty search range is 0 to
|
||||
.Dv _SC_CRAY_NPTY;
|
||||
otherwise, the default range is 0 to 128. Either
|
||||
.Ar lowpty
|
||||
or
|
||||
.Ar highpty
|
||||
may be omitted to allow changing
|
||||
either end of the search range. If
|
||||
.Ar lowpty
|
||||
is omitted, the - character is still required so that
|
||||
.Nm telnetd
|
||||
can differentiate
|
||||
.Ar highpty
|
||||
from
|
||||
.Ar lowpty .
|
||||
.It Fl s
|
||||
This option is only enabled if
|
||||
.Nm telnetd
|
||||
is compiled with support for
|
||||
.Tn SecurID
|
||||
cards.
|
||||
It causes the
|
||||
.Fl s
|
||||
option to be passed on to
|
||||
.Xr login 1 ,
|
||||
and thus is only useful if
|
||||
.Xr login 1
|
||||
supports the
|
||||
.Fl s
|
||||
flag to indicate that only
|
||||
.Tn SecurID
|
||||
validated logins are allowed, and is
|
||||
usually useful for controlling remote logins
|
||||
from outside of a firewall.
|
||||
.It Fl S Ar tos
|
||||
.It Fl u Ar len
|
||||
This option is used to specify the size of the field
|
||||
in the
|
||||
.Dv utmp
|
||||
structure that holds the remote host name.
|
||||
If the resolved host name is longer than
|
||||
.Ar len ,
|
||||
the dotted decimal value will be used instead.
|
||||
This allows hosts with very long host names that
|
||||
overflow this field to still be uniquely identified.
|
||||
Specifying
|
||||
.Fl u0
|
||||
indicates that only dotted decimal addresses
|
||||
should be put into the
|
||||
.Pa utmp
|
||||
file.
|
||||
.It Fl U
|
||||
This option causes
|
||||
.Nm telnetd
|
||||
to refuse connections from addresses that
|
||||
cannot be mapped back into a symbolic name
|
||||
via the
|
||||
.Xr gethostbyaddr 3
|
||||
routine.
|
||||
.It Fl X Ar authtype
|
||||
This option is only valid if
|
||||
.Nm telnetd
|
||||
has been built with support for the authentication option.
|
||||
It disables the use of
|
||||
.Ar authtype
|
||||
authentication, and
|
||||
can be used to temporarily disable
|
||||
a specific authentication type without having to recompile
|
||||
.Nm telnetd .
|
||||
.El
|
||||
.Pp
|
||||
.Nm Telnetd
|
||||
operates by allocating a pseudo-terminal device (see
|
||||
.Xr pty 4 )
|
||||
for a client, then creating a login process which has
|
||||
the slave side of the pseudo-terminal as
|
||||
.Dv stdin ,
|
||||
.Dv stdout
|
||||
and
|
||||
.Dv stderr .
|
||||
.Nm Telnetd
|
||||
manipulates the master side of the pseudo-terminal,
|
||||
implementing the
|
||||
.Tn TELNET
|
||||
protocol and passing characters
|
||||
between the remote client and the login process.
|
||||
.Pp
|
||||
When a
|
||||
.Tn TELNET
|
||||
session is started up,
|
||||
.Nm telnetd
|
||||
sends
|
||||
.Tn TELNET
|
||||
options to the client side indicating
|
||||
a willingness to do the
|
||||
following
|
||||
.Tn TELNET
|
||||
options, which are described in more detail below:
|
||||
.Bd -literal -offset indent
|
||||
DO AUTHENTICATION
|
||||
WILL ENCRYPT
|
||||
DO TERMINAL TYPE
|
||||
DO TSPEED
|
||||
DO XDISPLOC
|
||||
DO NEW-ENVIRON
|
||||
DO ENVIRON
|
||||
WILL SUPPRESS GO AHEAD
|
||||
DO ECHO
|
||||
DO LINEMODE
|
||||
DO NAWS
|
||||
WILL STATUS
|
||||
DO LFLOW
|
||||
DO TIMING-MARK
|
||||
.Ed
|
||||
.Pp
|
||||
The pseudo-terminal allocated to the client is configured
|
||||
to operate in \*(lqcooked\*(rq mode, and with
|
||||
.Dv XTABS and
|
||||
.Dv CRMOD
|
||||
enabled (see
|
||||
.Xr tty 4 ) .
|
||||
.Pp
|
||||
.Nm Telnetd
|
||||
has support for enabling locally the following
|
||||
.Tn TELNET
|
||||
options:
|
||||
.Bl -tag -width "DO AUTHENTICATION"
|
||||
.It "WILL ECHO"
|
||||
When the
|
||||
.Dv LINEMODE
|
||||
option is enabled, a
|
||||
.Dv WILL ECHO
|
||||
or
|
||||
.Dv WONT ECHO
|
||||
will be sent to the client to indicate the
|
||||
current state of terminal echoing.
|
||||
When terminal echo is not desired, a
|
||||
.Dv WILL ECHO
|
||||
is sent to indicate that
|
||||
.Tn telnetd
|
||||
will take care of echoing any data that needs to be
|
||||
echoed to the terminal, and then nothing is echoed.
|
||||
When terminal echo is desired, a
|
||||
.Dv WONT ECHO
|
||||
is sent to indicate that
|
||||
.Tn telnetd
|
||||
will not be doing any terminal echoing, so the
|
||||
client should do any terminal echoing that is needed.
|
||||
.It "WILL BINARY"
|
||||
Indicates that the client is willing to send a
|
||||
8 bits of data, rather than the normal 7 bits
|
||||
of the Network Virtual Terminal.
|
||||
.It "WILL SGA"
|
||||
Indicates that it will not be sending
|
||||
.Dv IAC GA,
|
||||
go ahead, commands.
|
||||
.It "WILL STATUS"
|
||||
Indicates a willingness to send the client, upon
|
||||
request, of the current status of all
|
||||
.Tn TELNET
|
||||
options.
|
||||
.It "WILL TIMING-MARK"
|
||||
Whenever a
|
||||
.Dv DO TIMING-MARK
|
||||
command is received, it is always responded
|
||||
to with a
|
||||
.Dv WILL TIMING-MARK
|
||||
.It "WILL LOGOUT"
|
||||
When a
|
||||
.Dv DO LOGOUT
|
||||
is received, a
|
||||
.Dv WILL LOGOUT
|
||||
is sent in response, and the
|
||||
.Tn TELNET
|
||||
session is shut down.
|
||||
.It "WILL ENCRYPT"
|
||||
Only sent if
|
||||
.Nm telnetd
|
||||
is compiled with support for data encryption, and
|
||||
indicates a willingness to decrypt
|
||||
the data stream.
|
||||
.El
|
||||
.Pp
|
||||
.Nm Telnetd
|
||||
has support for enabling remotely the following
|
||||
.Tn TELNET
|
||||
options:
|
||||
.Bl -tag -width "DO AUTHENTICATION"
|
||||
.It "DO BINARY"
|
||||
Sent to indicate that
|
||||
.Tn telnetd
|
||||
is willing to receive an 8 bit data stream.
|
||||
.It "DO LFLOW"
|
||||
Requests that the client handle flow control
|
||||
characters remotely.
|
||||
.It "DO ECHO"
|
||||
This is not really supported, but is sent to identify a 4.2BSD
|
||||
.Xr telnet 1
|
||||
client, which will improperly respond with
|
||||
.Dv WILL ECHO.
|
||||
If a
|
||||
.Dv WILL ECHO
|
||||
is received, a
|
||||
.Dv DONT ECHO
|
||||
will be sent in response.
|
||||
.It "DO TERMINAL-TYPE"
|
||||
Indicates a desire to be able to request the
|
||||
name of the type of terminal that is attached
|
||||
to the client side of the connection.
|
||||
.It "DO SGA"
|
||||
Indicates that it does not need to receive
|
||||
.Dv IAC GA,
|
||||
the go ahead command.
|
||||
.It "DO NAWS"
|
||||
Requests that the client inform the server when
|
||||
the window (display) size changes.
|
||||
.It "DO TERMINAL-SPEED"
|
||||
Indicates a desire to be able to request information
|
||||
about the speed of the serial line to which
|
||||
the client is attached.
|
||||
.It "DO XDISPLOC"
|
||||
Indicates a desire to be able to request the name
|
||||
of the X windows display that is associated with
|
||||
the telnet client.
|
||||
.It "DO NEW-ENVIRON"
|
||||
Indicates a desire to be able to request environment
|
||||
variable information, as described in RFC 1572.
|
||||
.It "DO ENVIRON"
|
||||
Indicates a desire to be able to request environment
|
||||
variable information, as described in RFC 1408.
|
||||
.It "DO LINEMODE"
|
||||
Only sent if
|
||||
.Nm telnetd
|
||||
is compiled with support for linemode, and
|
||||
requests that the client do line by line processing.
|
||||
.It "DO TIMING-MARK"
|
||||
Only sent if
|
||||
.Nm telnetd
|
||||
is compiled with support for both linemode and
|
||||
kludge linemode, and the client responded with
|
||||
.Dv WONT LINEMODE.
|
||||
If the client responds with
|
||||
.Dv WILL TM,
|
||||
the it is assumed that the client supports
|
||||
kludge linemode.
|
||||
Note that the
|
||||
.Op Fl k
|
||||
option can be used to disable this.
|
||||
.It "DO AUTHENTICATION"
|
||||
Only sent if
|
||||
.Nm telnetd
|
||||
is compiled with support for authentication, and
|
||||
indicates a willingness to receive authentication
|
||||
information for automatic login.
|
||||
.It "DO ENCRYPT"
|
||||
Only sent if
|
||||
.Nm telnetd
|
||||
is compiled with support for data encryption, and
|
||||
indicates a willingness to decrypt
|
||||
the data stream.
|
||||
.Sh ENVIRONMENT
|
||||
.Sh FILES
|
||||
.Pa /etc/services
|
||||
.br
|
||||
.Pa /etc/inittab
|
||||
(UNICOS systems only)
|
||||
.br
|
||||
.Pa /etc/iptos
|
||||
(if supported)
|
||||
.br
|
||||
.Pa /usr/ucb/bftp
|
||||
(if supported)
|
||||
.Sh "SEE ALSO"
|
||||
.Xr telnet 1 ,
|
||||
.Xr login 1 ,
|
||||
.Xr bftp 1
|
||||
(if supported)
|
||||
.Sh STANDARDS
|
||||
.Bl -tag -compact -width RFC-1572
|
||||
.It Cm RFC-854
|
||||
.Tn TELNET
|
||||
PROTOCOL SPECIFICATION
|
||||
.It Cm RFC-855
|
||||
TELNET OPTION SPECIFICATIONS
|
||||
.It Cm RFC-856
|
||||
TELNET BINARY TRANSMISSION
|
||||
.It Cm RFC-857
|
||||
TELNET ECHO OPTION
|
||||
.It Cm RFC-858
|
||||
TELNET SUPPRESS GO AHEAD OPTION
|
||||
.It Cm RFC-859
|
||||
TELNET STATUS OPTION
|
||||
.It Cm RFC-860
|
||||
TELNET TIMING MARK OPTION
|
||||
.It Cm RFC-861
|
||||
TELNET EXTENDED OPTIONS - LIST OPTION
|
||||
.It Cm RFC-885
|
||||
TELNET END OF RECORD OPTION
|
||||
.It Cm RFC-1073
|
||||
Telnet Window Size Option
|
||||
.It Cm RFC-1079
|
||||
Telnet Terminal Speed Option
|
||||
.It Cm RFC-1091
|
||||
Telnet Terminal-Type Option
|
||||
.It Cm RFC-1096
|
||||
Telnet X Display Location Option
|
||||
.It Cm RFC-1123
|
||||
Requirements for Internet Hosts -- Application and Support
|
||||
.It Cm RFC-1184
|
||||
Telnet Linemode Option
|
||||
.It Cm RFC-1372
|
||||
Telnet Remote Flow Control Option
|
||||
.It Cm RFC-1416
|
||||
Telnet Authentication Option
|
||||
.It Cm RFC-1411
|
||||
Telnet Authentication: Kerberos Version 4
|
||||
.It Cm RFC-1412
|
||||
Telnet Authentication: SPX
|
||||
.It Cm RFC-1571
|
||||
Telnet Environment Option Interoperability Issues
|
||||
.It Cm RFC-1572
|
||||
Telnet Environment Option
|
||||
.Sh BUGS
|
||||
Some
|
||||
.Tn TELNET
|
||||
commands are only partially implemented.
|
||||
.Pp
|
||||
Because of bugs in the original 4.2 BSD
|
||||
.Xr telnet 1 ,
|
||||
.Nm telnetd
|
||||
performs some dubious protocol exchanges to try to discover if the remote
|
||||
client is, in fact, a 4.2 BSD
|
||||
.Xr telnet 1 .
|
||||
.Pp
|
||||
Binary mode
|
||||
has no common interpretation except between similar operating systems
|
||||
(Unix in this case).
|
||||
.Pp
|
||||
The terminal type name received from the remote client is converted to
|
||||
lower case.
|
||||
.Pp
|
||||
.Nm Telnetd
|
||||
never sends
|
||||
.Tn TELNET
|
||||
.Dv IAC GA
|
||||
(go ahead) commands.
|
||||
1582
libexec/telnetd/telnetd.c
Normal file
1582
libexec/telnetd/telnetd.c
Normal file
File diff suppressed because it is too large
Load diff
49
libexec/telnetd/telnetd.h
Normal file
49
libexec/telnetd/telnetd.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)telnetd.h 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
|
||||
#include "defs.h"
|
||||
#include "ext.h"
|
||||
|
||||
#ifdef DIAGNOSTICS
|
||||
#define DIAG(a,b) if (diagnostic & (a)) b
|
||||
#else
|
||||
#define DIAG(a,b)
|
||||
#endif
|
||||
|
||||
/* other external variables */
|
||||
extern char **environ;
|
||||
extern int errno;
|
||||
|
||||
660
libexec/telnetd/termstat.c
Normal file
660
libexec/telnetd/termstat.c
Normal file
|
|
@ -0,0 +1,660 @@
|
|||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)termstat.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "telnetd.h"
|
||||
|
||||
/*
|
||||
* local variables
|
||||
*/
|
||||
int def_tspeed = -1, def_rspeed = -1;
|
||||
#ifdef TIOCSWINSZ
|
||||
int def_row = 0, def_col = 0;
|
||||
#endif
|
||||
#ifdef LINEMODE
|
||||
static int _terminit = 0;
|
||||
#endif /* LINEMODE */
|
||||
|
||||
#if defined(CRAY2) && defined(UNICOS5)
|
||||
int newmap = 1; /* nonzero if \n maps to ^M^J */
|
||||
#endif
|
||||
|
||||
#ifdef LINEMODE
|
||||
/*
|
||||
* localstat
|
||||
*
|
||||
* This function handles all management of linemode.
|
||||
*
|
||||
* Linemode allows the client to do the local editing of data
|
||||
* and send only complete lines to the server. Linemode state is
|
||||
* based on the state of the pty driver. If the pty is set for
|
||||
* external processing, then we can use linemode. Further, if we
|
||||
* can use real linemode, then we can look at the edit control bits
|
||||
* in the pty to determine what editing the client should do.
|
||||
*
|
||||
* Linemode support uses the following state flags to keep track of
|
||||
* current and desired linemode state.
|
||||
* alwayslinemode : true if -l was specified on the telnetd
|
||||
* command line. It means to have linemode on as much as
|
||||
* possible.
|
||||
*
|
||||
* lmodetype: signifies whether the client can
|
||||
* handle real linemode, or if use of kludgeomatic linemode
|
||||
* is preferred. It will be set to one of the following:
|
||||
* REAL_LINEMODE : use linemode option
|
||||
* NO_KLUDGE : don't initiate kludge linemode.
|
||||
* KLUDGE_LINEMODE : use kludge linemode
|
||||
* NO_LINEMODE : client is ignorant of linemode
|
||||
*
|
||||
* linemode, uselinemode : linemode is true if linemode
|
||||
* is currently on, uselinemode is the state that we wish
|
||||
* to be in. If another function wishes to turn linemode
|
||||
* on or off, it sets or clears uselinemode.
|
||||
*
|
||||
* editmode, useeditmode : like linemode/uselinemode, but
|
||||
* these contain the edit mode states (edit and trapsig).
|
||||
*
|
||||
* The state variables correspond to some of the state information
|
||||
* in the pty.
|
||||
* linemode:
|
||||
* In real linemode, this corresponds to whether the pty
|
||||
* expects external processing of incoming data.
|
||||
* In kludge linemode, this more closely corresponds to the
|
||||
* whether normal processing is on or not. (ICANON in
|
||||
* system V, or COOKED mode in BSD.)
|
||||
* If the -l option was specified (alwayslinemode), then
|
||||
* an attempt is made to force external processing on at
|
||||
* all times.
|
||||
*
|
||||
* The following heuristics are applied to determine linemode
|
||||
* handling within the server.
|
||||
* 1) Early on in starting up the server, an attempt is made
|
||||
* to negotiate the linemode option. If this succeeds
|
||||
* then lmodetype is set to REAL_LINEMODE and all linemode
|
||||
* processing occurs in the context of the linemode option.
|
||||
* 2) If the attempt to negotiate the linemode option failed,
|
||||
* and the "-k" (don't initiate kludge linemode) isn't set,
|
||||
* then we try to use kludge linemode. We test for this
|
||||
* capability by sending "do Timing Mark". If a positive
|
||||
* response comes back, then we assume that the client
|
||||
* understands kludge linemode (ech!) and the
|
||||
* lmodetype flag is set to KLUDGE_LINEMODE.
|
||||
* 3) Otherwise, linemode is not supported at all and
|
||||
* lmodetype remains set to NO_LINEMODE (which happens
|
||||
* to be 0 for convenience).
|
||||
* 4) At any time a command arrives that implies a higher
|
||||
* state of linemode support in the client, we move to that
|
||||
* linemode support.
|
||||
*
|
||||
* A short explanation of kludge linemode is in order here.
|
||||
* 1) The heuristic to determine support for kludge linemode
|
||||
* is to send a do timing mark. We assume that a client
|
||||
* that supports timing marks also supports kludge linemode.
|
||||
* A risky proposition at best.
|
||||
* 2) Further negotiation of linemode is done by changing the
|
||||
* the server's state regarding SGA. If server will SGA,
|
||||
* then linemode is off, if server won't SGA, then linemode
|
||||
* is on.
|
||||
*/
|
||||
void
|
||||
localstat()
|
||||
{
|
||||
void netflush();
|
||||
int need_will_echo = 0;
|
||||
|
||||
#if defined(CRAY2) && defined(UNICOS5)
|
||||
/*
|
||||
* Keep track of that ol' CR/NL mapping while we're in the
|
||||
* neighborhood.
|
||||
*/
|
||||
newmap = tty_isnewmap();
|
||||
#endif /* defined(CRAY2) && defined(UNICOS5) */
|
||||
|
||||
/*
|
||||
* Check for state of BINARY options.
|
||||
*/
|
||||
if (tty_isbinaryin()) {
|
||||
if (his_want_state_is_wont(TELOPT_BINARY))
|
||||
send_do(TELOPT_BINARY, 1);
|
||||
} else {
|
||||
if (his_want_state_is_will(TELOPT_BINARY))
|
||||
send_dont(TELOPT_BINARY, 1);
|
||||
}
|
||||
|
||||
if (tty_isbinaryout()) {
|
||||
if (my_want_state_is_wont(TELOPT_BINARY))
|
||||
send_will(TELOPT_BINARY, 1);
|
||||
} else {
|
||||
if (my_want_state_is_will(TELOPT_BINARY))
|
||||
send_wont(TELOPT_BINARY, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for changes to flow control if client supports it.
|
||||
*/
|
||||
flowstat();
|
||||
|
||||
/*
|
||||
* Check linemode on/off state
|
||||
*/
|
||||
uselinemode = tty_linemode();
|
||||
|
||||
/*
|
||||
* If alwayslinemode is on, and pty is changing to turn it off, then
|
||||
* force linemode back on.
|
||||
*/
|
||||
if (alwayslinemode && linemode && !uselinemode) {
|
||||
uselinemode = 1;
|
||||
tty_setlinemode(uselinemode);
|
||||
}
|
||||
|
||||
#ifdef ENCRYPTION
|
||||
/*
|
||||
* If the terminal is not echoing, but editing is enabled,
|
||||
* something like password input is going to happen, so
|
||||
* if we the other side is not currently sending encrypted
|
||||
* data, ask the other side to start encrypting.
|
||||
*/
|
||||
if (his_state_is_will(TELOPT_ENCRYPT)) {
|
||||
static int enc_passwd = 0;
|
||||
if (uselinemode && !tty_isecho() && tty_isediting()
|
||||
&& (enc_passwd == 0) && !decrypt_input) {
|
||||
encrypt_send_request_start();
|
||||
enc_passwd = 1;
|
||||
} else if (enc_passwd) {
|
||||
encrypt_send_request_end();
|
||||
enc_passwd = 0;
|
||||
}
|
||||
}
|
||||
#endif /* ENCRYPTION */
|
||||
|
||||
/*
|
||||
* Do echo mode handling as soon as we know what the
|
||||
* linemode is going to be.
|
||||
* If the pty has echo turned off, then tell the client that
|
||||
* the server will echo. If echo is on, then the server
|
||||
* will echo if in character mode, but in linemode the
|
||||
* client should do local echoing. The state machine will
|
||||
* not send anything if it is unnecessary, so don't worry
|
||||
* about that here.
|
||||
*
|
||||
* If we need to send the WILL ECHO (because echo is off),
|
||||
* then delay that until after we have changed the MODE.
|
||||
* This way, when the user is turning off both editing
|
||||
* and echo, the client will get editing turned off first.
|
||||
* This keeps the client from going into encryption mode
|
||||
* and then right back out if it is doing auto-encryption
|
||||
* when passwords are being typed.
|
||||
*/
|
||||
if (uselinemode) {
|
||||
if (tty_isecho())
|
||||
send_wont(TELOPT_ECHO, 1);
|
||||
else
|
||||
need_will_echo = 1;
|
||||
#ifdef KLUDGELINEMODE
|
||||
if (lmodetype == KLUDGE_OK)
|
||||
lmodetype = KLUDGE_LINEMODE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* If linemode is being turned off, send appropriate
|
||||
* command and then we're all done.
|
||||
*/
|
||||
if (!uselinemode && linemode) {
|
||||
# ifdef KLUDGELINEMODE
|
||||
if (lmodetype == REAL_LINEMODE) {
|
||||
# endif /* KLUDGELINEMODE */
|
||||
send_dont(TELOPT_LINEMODE, 1);
|
||||
# ifdef KLUDGELINEMODE
|
||||
} else if (lmodetype == KLUDGE_LINEMODE)
|
||||
send_will(TELOPT_SGA, 1);
|
||||
# endif /* KLUDGELINEMODE */
|
||||
send_will(TELOPT_ECHO, 1);
|
||||
linemode = uselinemode;
|
||||
goto done;
|
||||
}
|
||||
|
||||
# ifdef KLUDGELINEMODE
|
||||
/*
|
||||
* If using real linemode check edit modes for possible later use.
|
||||
* If we are in kludge linemode, do the SGA negotiation.
|
||||
*/
|
||||
if (lmodetype == REAL_LINEMODE) {
|
||||
# endif /* KLUDGELINEMODE */
|
||||
useeditmode = 0;
|
||||
if (tty_isediting())
|
||||
useeditmode |= MODE_EDIT;
|
||||
if (tty_istrapsig())
|
||||
useeditmode |= MODE_TRAPSIG;
|
||||
if (tty_issofttab())
|
||||
useeditmode |= MODE_SOFT_TAB;
|
||||
if (tty_islitecho())
|
||||
useeditmode |= MODE_LIT_ECHO;
|
||||
# ifdef KLUDGELINEMODE
|
||||
} else if (lmodetype == KLUDGE_LINEMODE) {
|
||||
if (tty_isediting() && uselinemode)
|
||||
send_wont(TELOPT_SGA, 1);
|
||||
else
|
||||
send_will(TELOPT_SGA, 1);
|
||||
}
|
||||
# endif /* KLUDGELINEMODE */
|
||||
|
||||
/*
|
||||
* Negotiate linemode on if pty state has changed to turn it on.
|
||||
* Send appropriate command and send along edit mode, then all done.
|
||||
*/
|
||||
if (uselinemode && !linemode) {
|
||||
# ifdef KLUDGELINEMODE
|
||||
if (lmodetype == KLUDGE_LINEMODE) {
|
||||
send_wont(TELOPT_SGA, 1);
|
||||
} else if (lmodetype == REAL_LINEMODE) {
|
||||
# endif /* KLUDGELINEMODE */
|
||||
send_do(TELOPT_LINEMODE, 1);
|
||||
/* send along edit modes */
|
||||
(void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB,
|
||||
TELOPT_LINEMODE, LM_MODE, useeditmode,
|
||||
IAC, SE);
|
||||
nfrontp += 7;
|
||||
editmode = useeditmode;
|
||||
# ifdef KLUDGELINEMODE
|
||||
}
|
||||
# endif /* KLUDGELINEMODE */
|
||||
linemode = uselinemode;
|
||||
goto done;
|
||||
}
|
||||
|
||||
# ifdef KLUDGELINEMODE
|
||||
/*
|
||||
* None of what follows is of any value if not using
|
||||
* real linemode.
|
||||
*/
|
||||
if (lmodetype < REAL_LINEMODE)
|
||||
goto done;
|
||||
# endif /* KLUDGELINEMODE */
|
||||
|
||||
if (linemode && his_state_is_will(TELOPT_LINEMODE)) {
|
||||
/*
|
||||
* If edit mode changed, send edit mode.
|
||||
*/
|
||||
if (useeditmode != editmode) {
|
||||
/*
|
||||
* Send along appropriate edit mode mask.
|
||||
*/
|
||||
(void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB,
|
||||
TELOPT_LINEMODE, LM_MODE, useeditmode,
|
||||
IAC, SE);
|
||||
nfrontp += 7;
|
||||
editmode = useeditmode;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check for changes to special characters in use.
|
||||
*/
|
||||
start_slc(0);
|
||||
check_slc();
|
||||
(void) end_slc(0);
|
||||
}
|
||||
|
||||
done:
|
||||
if (need_will_echo)
|
||||
send_will(TELOPT_ECHO, 1);
|
||||
/*
|
||||
* Some things should be deferred until after the pty state has
|
||||
* been set by the local process. Do those things that have been
|
||||
* deferred now. This only happens once.
|
||||
*/
|
||||
if (_terminit == 0) {
|
||||
_terminit = 1;
|
||||
defer_terminit();
|
||||
}
|
||||
|
||||
netflush();
|
||||
set_termbuf();
|
||||
return;
|
||||
|
||||
} /* end of localstat */
|
||||
#endif /* LINEMODE */
|
||||
|
||||
/*
|
||||
* flowstat
|
||||
*
|
||||
* Check for changes to flow control
|
||||
*/
|
||||
void
|
||||
flowstat()
|
||||
{
|
||||
if (his_state_is_will(TELOPT_LFLOW)) {
|
||||
if (tty_flowmode() != flowmode) {
|
||||
flowmode = tty_flowmode();
|
||||
(void) sprintf(nfrontp, "%c%c%c%c%c%c",
|
||||
IAC, SB, TELOPT_LFLOW,
|
||||
flowmode ? LFLOW_ON : LFLOW_OFF,
|
||||
IAC, SE);
|
||||
nfrontp += 6;
|
||||
}
|
||||
if (tty_restartany() != restartany) {
|
||||
restartany = tty_restartany();
|
||||
(void) sprintf(nfrontp, "%c%c%c%c%c%c",
|
||||
IAC, SB, TELOPT_LFLOW,
|
||||
restartany ? LFLOW_RESTART_ANY
|
||||
: LFLOW_RESTART_XON,
|
||||
IAC, SE);
|
||||
nfrontp += 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* clientstat
|
||||
*
|
||||
* Process linemode related requests from the client.
|
||||
* Client can request a change to only one of linemode, editmode or slc's
|
||||
* at a time, and if using kludge linemode, then only linemode may be
|
||||
* affected.
|
||||
*/
|
||||
void
|
||||
clientstat(code, parm1, parm2)
|
||||
register int code, parm1, parm2;
|
||||
{
|
||||
void netflush();
|
||||
|
||||
/*
|
||||
* Get a copy of terminal characteristics.
|
||||
*/
|
||||
init_termbuf();
|
||||
|
||||
/*
|
||||
* Process request from client. code tells what it is.
|
||||
*/
|
||||
switch (code) {
|
||||
#ifdef LINEMODE
|
||||
case TELOPT_LINEMODE:
|
||||
/*
|
||||
* Don't do anything unless client is asking us to change
|
||||
* modes.
|
||||
*/
|
||||
uselinemode = (parm1 == WILL);
|
||||
if (uselinemode != linemode) {
|
||||
# ifdef KLUDGELINEMODE
|
||||
/*
|
||||
* If using kludge linemode, make sure that
|
||||
* we can do what the client asks.
|
||||
* We can not turn off linemode if alwayslinemode
|
||||
* and the ICANON bit is set.
|
||||
*/
|
||||
if (lmodetype == KLUDGE_LINEMODE) {
|
||||
if (alwayslinemode && tty_isediting()) {
|
||||
uselinemode = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Quit now if we can't do it.
|
||||
*/
|
||||
if (uselinemode == linemode)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If using real linemode and linemode is being
|
||||
* turned on, send along the edit mode mask.
|
||||
*/
|
||||
if (lmodetype == REAL_LINEMODE && uselinemode)
|
||||
# else /* KLUDGELINEMODE */
|
||||
if (uselinemode)
|
||||
# endif /* KLUDGELINEMODE */
|
||||
{
|
||||
useeditmode = 0;
|
||||
if (tty_isediting())
|
||||
useeditmode |= MODE_EDIT;
|
||||
if (tty_istrapsig)
|
||||
useeditmode |= MODE_TRAPSIG;
|
||||
if (tty_issofttab())
|
||||
useeditmode |= MODE_SOFT_TAB;
|
||||
if (tty_islitecho())
|
||||
useeditmode |= MODE_LIT_ECHO;
|
||||
(void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC,
|
||||
SB, TELOPT_LINEMODE, LM_MODE,
|
||||
useeditmode, IAC, SE);
|
||||
nfrontp += 7;
|
||||
editmode = useeditmode;
|
||||
}
|
||||
|
||||
|
||||
tty_setlinemode(uselinemode);
|
||||
|
||||
linemode = uselinemode;
|
||||
|
||||
if (!linemode)
|
||||
send_will(TELOPT_ECHO, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case LM_MODE:
|
||||
{
|
||||
register int ack, changed;
|
||||
|
||||
/*
|
||||
* Client has sent along a mode mask. If it agrees with
|
||||
* what we are currently doing, ignore it; if not, it could
|
||||
* be viewed as a request to change. Note that the server
|
||||
* will change to the modes in an ack if it is different from
|
||||
* what we currently have, but we will not ack the ack.
|
||||
*/
|
||||
useeditmode &= MODE_MASK;
|
||||
ack = (useeditmode & MODE_ACK);
|
||||
useeditmode &= ~MODE_ACK;
|
||||
|
||||
if (changed = (useeditmode ^ editmode)) {
|
||||
/*
|
||||
* This check is for a timing problem. If the
|
||||
* state of the tty has changed (due to the user
|
||||
* application) we need to process that info
|
||||
* before we write in the state contained in the
|
||||
* ack!!! This gets out the new MODE request,
|
||||
* and when the ack to that command comes back
|
||||
* we'll set it and be in the right mode.
|
||||
*/
|
||||
if (ack)
|
||||
localstat();
|
||||
if (changed & MODE_EDIT)
|
||||
tty_setedit(useeditmode & MODE_EDIT);
|
||||
|
||||
if (changed & MODE_TRAPSIG)
|
||||
tty_setsig(useeditmode & MODE_TRAPSIG);
|
||||
|
||||
if (changed & MODE_SOFT_TAB)
|
||||
tty_setsofttab(useeditmode & MODE_SOFT_TAB);
|
||||
|
||||
if (changed & MODE_LIT_ECHO)
|
||||
tty_setlitecho(useeditmode & MODE_LIT_ECHO);
|
||||
|
||||
set_termbuf();
|
||||
|
||||
if (!ack) {
|
||||
(void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC,
|
||||
SB, TELOPT_LINEMODE, LM_MODE,
|
||||
useeditmode|MODE_ACK,
|
||||
IAC, SE);
|
||||
nfrontp += 7;
|
||||
}
|
||||
|
||||
editmode = useeditmode;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} /* end of case LM_MODE */
|
||||
#endif /* LINEMODE */
|
||||
|
||||
case TELOPT_NAWS:
|
||||
#ifdef TIOCSWINSZ
|
||||
{
|
||||
struct winsize ws;
|
||||
|
||||
def_col = parm1;
|
||||
def_row = parm2;
|
||||
#ifdef LINEMODE
|
||||
/*
|
||||
* Defer changing window size until after terminal is
|
||||
* initialized.
|
||||
*/
|
||||
if (terminit() == 0)
|
||||
return;
|
||||
#endif /* LINEMODE */
|
||||
|
||||
/*
|
||||
* Change window size as requested by client.
|
||||
*/
|
||||
|
||||
ws.ws_col = parm1;
|
||||
ws.ws_row = parm2;
|
||||
(void) ioctl(pty, TIOCSWINSZ, (char *)&ws);
|
||||
}
|
||||
#endif /* TIOCSWINSZ */
|
||||
|
||||
break;
|
||||
|
||||
case TELOPT_TSPEED:
|
||||
{
|
||||
def_tspeed = parm1;
|
||||
def_rspeed = parm2;
|
||||
#ifdef LINEMODE
|
||||
/*
|
||||
* Defer changing the terminal speed.
|
||||
*/
|
||||
if (terminit() == 0)
|
||||
return;
|
||||
#endif /* LINEMODE */
|
||||
/*
|
||||
* Change terminal speed as requested by client.
|
||||
* We set the receive speed first, so that if we can't
|
||||
* store seperate receive and transmit speeds, the transmit
|
||||
* speed will take precedence.
|
||||
*/
|
||||
tty_rspeed(parm2);
|
||||
tty_tspeed(parm1);
|
||||
set_termbuf();
|
||||
|
||||
break;
|
||||
|
||||
} /* end of case TELOPT_TSPEED */
|
||||
|
||||
default:
|
||||
/* What? */
|
||||
break;
|
||||
} /* end of switch */
|
||||
|
||||
#if defined(CRAY2) && defined(UNICOS5)
|
||||
/*
|
||||
* Just in case of the likely event that we changed the pty state.
|
||||
*/
|
||||
rcv_ioctl();
|
||||
#endif /* defined(CRAY2) && defined(UNICOS5) */
|
||||
|
||||
netflush();
|
||||
|
||||
} /* end of clientstat */
|
||||
|
||||
#if defined(CRAY2) && defined(UNICOS5)
|
||||
void
|
||||
termstat()
|
||||
{
|
||||
needtermstat = 1;
|
||||
}
|
||||
|
||||
void
|
||||
_termstat()
|
||||
{
|
||||
needtermstat = 0;
|
||||
init_termbuf();
|
||||
localstat();
|
||||
rcv_ioctl();
|
||||
}
|
||||
#endif /* defined(CRAY2) && defined(UNICOS5) */
|
||||
|
||||
#ifdef LINEMODE
|
||||
/*
|
||||
* defer_terminit
|
||||
*
|
||||
* Some things should not be done until after the login process has started
|
||||
* and all the pty modes are set to what they are supposed to be. This
|
||||
* function is called when the pty state has been processed for the first time.
|
||||
* It calls other functions that do things that were deferred in each module.
|
||||
*/
|
||||
void
|
||||
defer_terminit()
|
||||
{
|
||||
|
||||
/*
|
||||
* local stuff that got deferred.
|
||||
*/
|
||||
if (def_tspeed != -1) {
|
||||
clientstat(TELOPT_TSPEED, def_tspeed, def_rspeed);
|
||||
def_tspeed = def_rspeed = 0;
|
||||
}
|
||||
|
||||
#ifdef TIOCSWINSZ
|
||||
if (def_col || def_row) {
|
||||
struct winsize ws;
|
||||
|
||||
bzero((char *)&ws, sizeof(ws));
|
||||
ws.ws_col = def_col;
|
||||
ws.ws_row = def_row;
|
||||
(void) ioctl(pty, TIOCSWINSZ, (char *)&ws);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The only other module that currently defers anything.
|
||||
*/
|
||||
deferslc();
|
||||
|
||||
} /* end of defer_terminit */
|
||||
|
||||
/*
|
||||
* terminit
|
||||
*
|
||||
* Returns true if the pty state has been processed yet.
|
||||
*/
|
||||
int
|
||||
terminit()
|
||||
{
|
||||
return(_terminit);
|
||||
|
||||
} /* end of terminit */
|
||||
#endif /* LINEMODE */
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue