mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-01 12:19:28 +00:00
This commit was generated by cvs2svn to compensate for changes in r27241,
which included commits to RCS files with non-trunk default branches.
This commit is contained in:
commit
aac7bd5670
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=27242
7
usr.bin/apropos/Makefile
Normal file
7
usr.bin/apropos/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= apropos
|
||||
SRCS= apropos.c config.c
|
||||
.PATH: ${.CURDIR}/../man
|
||||
|
||||
.include <bsd.prog.mk>
|
120
usr.bin/apropos/apropos.1
Normal file
120
usr.bin/apropos/apropos.1
Normal file
@ -0,0 +1,120 @@
|
||||
.\" Copyright (c) 1989, 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.
|
||||
.\"
|
||||
.\" @(#)apropos.1 8.1 (Berkeley) 6/29/93
|
||||
.\"
|
||||
.Dd June 29, 1993
|
||||
.Dt APROPOS 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm apropos
|
||||
.Nd locate commands by keyword lookup
|
||||
.Sh SYNOPSIS
|
||||
.Nm apropos
|
||||
.Op Fl M Ar path
|
||||
.Op Fl m Ar path
|
||||
.Ar keyword ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm Apropos
|
||||
shows which manual pages contain instances of any of the given
|
||||
.Ar keyword(s)
|
||||
in their title line.
|
||||
Each word is considered separately and case of letters is ignored.
|
||||
Words which are part of other words are considered; when looking for
|
||||
.Dq compile ,
|
||||
.Nm apropos
|
||||
will also list all instances of
|
||||
.Dq compiler .
|
||||
.Pp
|
||||
If the line output by
|
||||
.Nm apropos
|
||||
starts
|
||||
.Dq Li name(section) ...
|
||||
you can enter
|
||||
.Dq Li man section name
|
||||
to get
|
||||
its documentation.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width flag
|
||||
.It Fl M
|
||||
Override the list of standard directories
|
||||
.Nm apropos
|
||||
searches for a database named
|
||||
.Pa whatis.db .
|
||||
The supplied
|
||||
.Ar path
|
||||
must be a colon
|
||||
.Dq \&:
|
||||
separated list of directories.
|
||||
This search path may also be set using the environment variable
|
||||
.Ev MANPATH .
|
||||
.It Fl m
|
||||
Augment the list of standard directories
|
||||
.Nm apropos
|
||||
searches for its database.
|
||||
The supplied
|
||||
.Ar path
|
||||
must be a colon
|
||||
.Dq \&:
|
||||
separated list of directories.
|
||||
These directories will be searched before the standard directories,
|
||||
or the directories supplied with the
|
||||
.Fl M
|
||||
option or the
|
||||
.Ev MANPATH
|
||||
environment variable.
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width MANPATH
|
||||
.It Ev MANPATH
|
||||
The standard search path used by
|
||||
.Xr man 1
|
||||
may be overridden by specifying a path in the
|
||||
.Ev MANPATH
|
||||
environment variable.
|
||||
The format of the path is a colon
|
||||
.Dq \&:
|
||||
separated list of directories.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width whatis.db -compact
|
||||
.It Pa whatis.db
|
||||
name of the apropos database
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr man 1 ,
|
||||
.Xr whatis 1 ,
|
||||
.Xr whereis 1
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm apropos
|
||||
command appeared in
|
||||
.Bx 3.0 .
|
224
usr.bin/apropos/apropos.c
Normal file
224
usr.bin/apropos/apropos.c
Normal file
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (c) 1987, 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) 1987, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)apropos.c 8.8 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../man/config.h"
|
||||
#include "../man/pathnames.h"
|
||||
|
||||
static int *found, foundman;
|
||||
|
||||
void apropos __P((char **, char *, int));
|
||||
void lowstr __P((char *, char *));
|
||||
int match __P((char *, char *));
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
ENTRY *ep;
|
||||
TAG *tp;
|
||||
int ch, rv;
|
||||
char *conffile, **p, *p_augment, *p_path;
|
||||
|
||||
conffile = NULL;
|
||||
p_augment = p_path = NULL;
|
||||
while ((ch = getopt(argc, argv, "C:M:m:P:")) != EOF)
|
||||
switch (ch) {
|
||||
case 'C':
|
||||
conffile = optarg;
|
||||
break;
|
||||
case 'M':
|
||||
case 'P': /* backward compatible */
|
||||
p_path = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
p_augment = optarg;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argv += optind;
|
||||
argc -= optind;
|
||||
|
||||
if (argc < 1)
|
||||
usage();
|
||||
|
||||
if ((found = malloc((u_int)argc * sizeof(int))) == NULL)
|
||||
err(1, NULL);
|
||||
memset(found, 0, argc * sizeof(int));
|
||||
|
||||
for (p = argv; *p; ++p) /* convert to lower-case */
|
||||
lowstr(*p, *p);
|
||||
|
||||
if (p_augment)
|
||||
apropos(argv, p_augment, 1);
|
||||
if (p_path || (p_path = getenv("MANPATH")))
|
||||
apropos(argv, p_path, 1);
|
||||
else {
|
||||
config(conffile);
|
||||
ep = (tp = getlist("_whatdb")) == NULL ?
|
||||
NULL : tp->list.tqh_first;
|
||||
for (; ep != NULL; ep = ep->q.tqe_next)
|
||||
apropos(argv, ep->s, 0);
|
||||
}
|
||||
|
||||
if (!foundman)
|
||||
errx(1, "no %s file found", _PATH_WHATIS);
|
||||
|
||||
rv = 1;
|
||||
for (p = argv; *p; ++p)
|
||||
if (found[p - argv])
|
||||
rv = 0;
|
||||
else
|
||||
(void)printf("%s: nothing appropriate\n", *p);
|
||||
exit(rv);
|
||||
}
|
||||
|
||||
void
|
||||
apropos(argv, path, buildpath)
|
||||
char **argv, *path;
|
||||
int buildpath;
|
||||
{
|
||||
char *end, *name, **p;
|
||||
char buf[LINE_MAX + 1], wbuf[LINE_MAX + 1];
|
||||
|
||||
for (name = path; name; name = end) { /* through name list */
|
||||
if (end = strchr(name, ':'))
|
||||
*end++ = '\0';
|
||||
|
||||
if (buildpath) {
|
||||
char hold[MAXPATHLEN + 1];
|
||||
|
||||
(void)sprintf(hold, "%s/%s", name, _PATH_WHATIS);
|
||||
name = hold;
|
||||
}
|
||||
|
||||
if (!freopen(name, "r", stdin))
|
||||
continue;
|
||||
|
||||
foundman = 1;
|
||||
|
||||
/* for each file found */
|
||||
while (fgets(buf, sizeof(buf), stdin)) {
|
||||
if (!strchr(buf, '\n')) {
|
||||
warnx("%s: line too long", name);
|
||||
continue;
|
||||
}
|
||||
lowstr(buf, wbuf);
|
||||
for (p = argv; *p; ++p)
|
||||
if (match(wbuf, *p)) {
|
||||
(void)printf("%s", buf);
|
||||
found[p - argv] = 1;
|
||||
|
||||
/* only print line once */
|
||||
while (*++p)
|
||||
if (match(wbuf, *p))
|
||||
found[p - argv] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* match --
|
||||
* match anywhere the string appears
|
||||
*/
|
||||
int
|
||||
match(bp, str)
|
||||
char *bp, *str;
|
||||
{
|
||||
int len;
|
||||
char test;
|
||||
|
||||
if (!*bp)
|
||||
return (0);
|
||||
/* backward compatible: everything matches empty string */
|
||||
if (!*str)
|
||||
return (1);
|
||||
for (test = *str++, len = strlen(str); *bp;)
|
||||
if (test == *bp++ && !strncmp(bp, str, len))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* lowstr --
|
||||
* convert a string to lower case
|
||||
*/
|
||||
void
|
||||
lowstr(from, to)
|
||||
char *from, *to;
|
||||
{
|
||||
char ch;
|
||||
|
||||
while ((ch = *from++) && ch != '\n')
|
||||
*to++ = isupper(ch) ? tolower(ch) : ch;
|
||||
*to = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* usage --
|
||||
* print usage message and die
|
||||
*/
|
||||
void
|
||||
usage()
|
||||
{
|
||||
|
||||
(void)fprintf(stderr,
|
||||
"usage: apropos [-C file] [-M path] [-m path] keyword ...\n");
|
||||
exit(1);
|
||||
}
|
146
usr.bin/ar/ar.5.5
Normal file
146
usr.bin/ar/ar.5.5
Normal file
@ -0,0 +1,146 @@
|
||||
.\" Copyright (c) 1990, 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.
|
||||
.\"
|
||||
.\" @(#)ar.5.5 8.2 (Berkeley) 6/1/94
|
||||
.\"
|
||||
.Dd June 1, 1994
|
||||
.Dt AR 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ar
|
||||
.Nd archive (library) file format
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <ar.h>
|
||||
.Sh DESCRIPTION
|
||||
The archive command
|
||||
.Nm ar
|
||||
combines several files into one.
|
||||
Archives are mainly used as libraries of object files intended to be
|
||||
loaded using the link-editor
|
||||
.Xr ld 1 .
|
||||
.Pp
|
||||
A file created with
|
||||
.Nm ar
|
||||
begins with the ``magic'' string "!<arch>\en".
|
||||
The rest of the archive is made up of objects, each of which is composed
|
||||
of a header for a file, a possible file name, and the file contents.
|
||||
The header is portable between machine architectures, and, if the file
|
||||
contents are printable, the archive is itself printable.
|
||||
.Pp
|
||||
The header is made up of six variable length
|
||||
.Tn ASCII
|
||||
fields, followed by a
|
||||
two character trailer.
|
||||
The fields are the object name (16 characters), the file last modification
|
||||
time (12 characters), the user and group id's (each 6 characters), the file
|
||||
mode (8 characters) and the file size (10 characters).
|
||||
All numeric fields are in decimal, except for the file mode which is in
|
||||
octal.
|
||||
.Pp
|
||||
The modification time is the file
|
||||
.Fa st_mtime
|
||||
field, i.e.,
|
||||
.Dv CUT
|
||||
seconds since
|
||||
the epoch.
|
||||
The user and group id's are the file
|
||||
.Fa st_uid
|
||||
and
|
||||
.Fa st_gid
|
||||
fields.
|
||||
The file mode is the file
|
||||
.Fa st_mode
|
||||
field.
|
||||
The file size is the file
|
||||
.Fa st_size
|
||||
field.
|
||||
The two-byte trailer is the string "\`\en".
|
||||
.Pp
|
||||
Only the name field has any provision for overflow.
|
||||
If any file name is more than 16 characters in length or contains an
|
||||
embedded space, the string "#1/" followed by the
|
||||
.Tn ASCII
|
||||
length of the
|
||||
name is written in the name field.
|
||||
The file size (stored in the archive header) is incremented by the length
|
||||
of the name.
|
||||
The name is then written immediately following the archive header.
|
||||
.Pp
|
||||
Any unused characters in any of these fields are written as space
|
||||
characters.
|
||||
If any fields are their particular maximum number of characters in
|
||||
length, there will be no separation between the fields.
|
||||
.Pp
|
||||
Objects in the archive are always an even number of bytes long; files
|
||||
which are an odd number of bytes long are padded with a newline (``\en'')
|
||||
character, although the size in the header does not reflect this.
|
||||
.Sh SEE ALSO
|
||||
.Xr ar 1 ,
|
||||
.Xr stat 2
|
||||
.Sh HISTORY
|
||||
There have been at least four
|
||||
.Nm ar
|
||||
formats.
|
||||
The first was denoted by the leading ``magic'' number 0177555 (stored as
|
||||
type int).
|
||||
These archives were almost certainly created on a 16-bit machine, and
|
||||
contain headers made up of five fields.
|
||||
The fields are the object name (8 characters), the file last modification
|
||||
time (type long), the user id (type char), the file mode (type char) and
|
||||
the file size (type unsigned int).
|
||||
Files were padded to an even number of bytes.
|
||||
.Pp
|
||||
The second was denoted by the leading ``magic'' number 0177545 (stored as
|
||||
type int).
|
||||
These archives may have been created on either 16 or 32-bit machines, and
|
||||
contain headers made up of six fields.
|
||||
The fields are the object name (14 characters), the file last modification
|
||||
time (type long), the user and group id's (each type char), the file mode
|
||||
(type int) and the file size (type long).
|
||||
Files were padded to an even number of bytes.
|
||||
For more information on converting from this format see
|
||||
.Xr arcv 8 .
|
||||
.ne 1i
|
||||
.Pp
|
||||
The current archive format (without support for long character names and
|
||||
names with embedded spaces) was introduced in
|
||||
.Bx 4.0 .
|
||||
The headers were the same as the current format, with the exception that
|
||||
names longer than 16 characters were truncated, and names with embedded
|
||||
spaces (and often trailing spaces) were not supported.
|
||||
It has been extended for these reasons,
|
||||
as described above.
|
||||
This format first appeared in 4.4BSD.
|
||||
.Sh COMPATIBILITY
|
||||
No archive format is currently specified by any standard.
|
||||
.At V
|
||||
has historically distributed archives in a different format from
|
||||
all of the above.
|
7
usr.bin/ld/Makefile
Normal file
7
usr.bin/ld/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= ld
|
||||
SRCS= ld.c cplus-dem.c
|
||||
NOMAN= noman
|
||||
|
||||
.include <bsd.prog.mk>
|
970
usr.bin/ld/cplus-dem.c
Normal file
970
usr.bin/ld/cplus-dem.c
Normal file
@ -0,0 +1,970 @@
|
||||
/*-
|
||||
* This code is derived from software copyrighted by the Free Software
|
||||
* Foundation.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)cplus-dem.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/* Demangler for GNU C++
|
||||
Copyright (C) 1989 Free Software Foundation, Inc.
|
||||
written by James Clark (jjc@jclark.uucp)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* This is for g++ 1.36.1 (November 6 version). It will probably
|
||||
require changes for any other version.
|
||||
|
||||
Modified for g++ 1.36.2 (November 18 version). */
|
||||
|
||||
/* This file exports one function
|
||||
|
||||
char *cplus_demangle (const char *name)
|
||||
|
||||
If `name' is a mangled function name produced by g++, then
|
||||
a pointer to a malloced string giving a C++ representation
|
||||
of the name will be returned; otherwise NULL will be returned.
|
||||
It is the caller's responsibility to free the string which
|
||||
is returned.
|
||||
|
||||
For example,
|
||||
|
||||
cplus_demangle ("_foo__1Ai")
|
||||
|
||||
returns
|
||||
|
||||
"A::foo(int)"
|
||||
|
||||
This file imports xmalloc and xrealloc, which are like malloc and
|
||||
realloc except that they generate a fatal error if there is no
|
||||
available memory. */
|
||||
|
||||
/* #define nounderscore 1 /* define this is names don't start with _ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef USG
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#else
|
||||
#include <strings.h>
|
||||
#define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
|
||||
#define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
|
||||
#define strchr index
|
||||
#define strrchr rindex
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
extern char *cplus_demangle (const char *type);
|
||||
#else
|
||||
extern char *cplus_demangle ();
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
extern char *xmalloc (int);
|
||||
extern char *xrealloc (char *, int);
|
||||
#else
|
||||
extern char *xmalloc ();
|
||||
extern char *xrealloc ();
|
||||
#endif
|
||||
|
||||
static char **typevec = 0;
|
||||
static int ntypes = 0;
|
||||
static int typevec_size = 0;
|
||||
|
||||
static struct {
|
||||
const char *in;
|
||||
const char *out;
|
||||
} optable[] = {
|
||||
"new", " new",
|
||||
"delete", " delete",
|
||||
"ne", "!=",
|
||||
"eq", "==",
|
||||
"ge", ">=",
|
||||
"gt", ">",
|
||||
"le", "<=",
|
||||
"lt", "<",
|
||||
"plus", "+",
|
||||
"minus", "-",
|
||||
"mult", "*",
|
||||
"convert", "+", /* unary + */
|
||||
"negate", "-", /* unary - */
|
||||
"trunc_mod", "%",
|
||||
"trunc_div", "/",
|
||||
"truth_andif", "&&",
|
||||
"truth_orif", "||",
|
||||
"truth_not", "!",
|
||||
"postincrement", "++",
|
||||
"postdecrement", "--",
|
||||
"bit_ior", "|",
|
||||
"bit_xor", "^",
|
||||
"bit_and", "&",
|
||||
"bit_not", "~",
|
||||
"call", "()",
|
||||
"cond", "?:",
|
||||
"alshift", "<<",
|
||||
"arshift", ">>",
|
||||
"component", "->",
|
||||
"indirect", "*",
|
||||
"method_call", "->()",
|
||||
"addr", "&", /* unary & */
|
||||
"array", "[]",
|
||||
"nop", "", /* for operator= */
|
||||
};
|
||||
|
||||
/* Beware: these aren't '\0' terminated. */
|
||||
|
||||
typedef struct {
|
||||
char *b; /* pointer to start of string */
|
||||
char *p; /* pointer after last character */
|
||||
char *e; /* pointer after end of allocated space */
|
||||
} string;
|
||||
|
||||
#ifdef __STDC__
|
||||
static void string_need (string *s, int n);
|
||||
static void string_delete (string *s);
|
||||
static void string_init (string *s);
|
||||
static void string_clear (string *s);
|
||||
static int string_empty (string *s);
|
||||
static void string_append (string *p, const char *s);
|
||||
static void string_appends (string *p, string *s);
|
||||
static void string_appendn (string *p, const char *s, int n);
|
||||
static void string_prepend (string *p, const char *s);
|
||||
#if 0
|
||||
static void string_prepends (string *p, string *s);
|
||||
#endif
|
||||
static void string_prependn (string *p, const char *s, int n);
|
||||
static int get_count (const char **type, int *count);
|
||||
static int do_args (const char **type, string *decl);
|
||||
static int do_type (const char **type, string *result);
|
||||
static int do_arg (const char **type, string *result);
|
||||
static int do_args (const char **type, string *decl);
|
||||
static void munge_function_name (string *name);
|
||||
static void remember_type (const char *type, int len);
|
||||
#else
|
||||
static void string_need ();
|
||||
static void string_delete ();
|
||||
static void string_init ();
|
||||
static void string_clear ();
|
||||
static int string_empty ();
|
||||
static void string_append ();
|
||||
static void string_appends ();
|
||||
static void string_appendn ();
|
||||
static void string_prepend ();
|
||||
static void string_prepends ();
|
||||
static void string_prependn ();
|
||||
static int get_count ();
|
||||
static int do_args ();
|
||||
static int do_type ();
|
||||
static int do_arg ();
|
||||
static int do_args ();
|
||||
static void munge_function_name ();
|
||||
static void remember_type ();
|
||||
#endif
|
||||
|
||||
char *
|
||||
cplus_demangle (type)
|
||||
const char *type;
|
||||
{
|
||||
string decl;
|
||||
int n;
|
||||
int success = 0;
|
||||
int constructor = 0;
|
||||
int const_flag = 0;
|
||||
int i;
|
||||
const char *p;
|
||||
#ifndef LONGERNAMES
|
||||
const char *premangle;
|
||||
#endif
|
||||
|
||||
if (type == NULL || *type == '\0')
|
||||
return NULL;
|
||||
#ifndef nounderscore
|
||||
if (*type++ != '_')
|
||||
return NULL;
|
||||
#endif
|
||||
p = type;
|
||||
while (*p != '\0' && !(*p == '_' && p[1] == '_'))
|
||||
p++;
|
||||
if (*p == '\0')
|
||||
{
|
||||
/* destructor */
|
||||
if (type[0] == '_' && type[1] == '$' && type[2] == '_')
|
||||
{
|
||||
int n = (strlen (type) - 3)*2 + 3 + 2 + 1;
|
||||
char *tem = (char *) xmalloc (n);
|
||||
strcpy (tem, type + 3);
|
||||
strcat (tem, "::~");
|
||||
strcat (tem, type + 3);
|
||||
strcat (tem, "()");
|
||||
return tem;
|
||||
}
|
||||
/* static data member */
|
||||
if (*type != '_' && (p = strchr (type, '$')) != NULL)
|
||||
{
|
||||
int n = strlen (type) + 2;
|
||||
char *tem = (char *) xmalloc (n);
|
||||
memcpy (tem, type, p - type);
|
||||
strcpy (tem + (p - type), "::");
|
||||
strcpy (tem + (p - type) + 2, p + 1);
|
||||
return tem;
|
||||
}
|
||||
/* virtual table */
|
||||
if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == '$')
|
||||
{
|
||||
int n = strlen (type + 4) + 14 + 1;
|
||||
char *tem = (char *) xmalloc (n);
|
||||
strcpy (tem, type + 4);
|
||||
strcat (tem, " virtual table");
|
||||
return tem;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
string_init (&decl);
|
||||
|
||||
if (p == type)
|
||||
{
|
||||
if (!isdigit (p[2]))
|
||||
{
|
||||
string_delete (&decl);
|
||||
return NULL;
|
||||
}
|
||||
constructor = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
string_appendn (&decl, type, p - type);
|
||||
munge_function_name (&decl);
|
||||
}
|
||||
p += 2;
|
||||
|
||||
#ifndef LONGERNAMES
|
||||
premangle = p;
|
||||
#endif
|
||||
switch (*p)
|
||||
{
|
||||
case 'C':
|
||||
/* a const member function */
|
||||
if (!isdigit (p[1]))
|
||||
{
|
||||
string_delete (&decl);
|
||||
return NULL;
|
||||
}
|
||||
p += 1;
|
||||
const_flag = 1;
|
||||
/* fall through */
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
n = 0;
|
||||
do
|
||||
{
|
||||
n *= 10;
|
||||
n += *p - '0';
|
||||
p += 1;
|
||||
}
|
||||
while (isdigit (*p));
|
||||
if (strlen (p) < n)
|
||||
{
|
||||
string_delete (&decl);
|
||||
return NULL;
|
||||
}
|
||||
if (constructor)
|
||||
{
|
||||
string_appendn (&decl, p, n);
|
||||
string_append (&decl, "::");
|
||||
string_appendn (&decl, p, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
string_prepend (&decl, "::");
|
||||
string_prependn (&decl, p, n);
|
||||
}
|
||||
p += n;
|
||||
#ifndef LONGERNAMES
|
||||
remember_type (premangle, p - premangle);
|
||||
#endif
|
||||
success = do_args (&p, &decl);
|
||||
if (const_flag)
|
||||
string_append (&decl, " const");
|
||||
break;
|
||||
case 'F':
|
||||
p += 1;
|
||||
success = do_args (&p, &decl);
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < ntypes; i++)
|
||||
if (typevec[i] != NULL)
|
||||
free (typevec[i]);
|
||||
ntypes = 0;
|
||||
if (typevec != NULL)
|
||||
{
|
||||
free ((char *)typevec);
|
||||
typevec = NULL;
|
||||
typevec_size = 0;
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
string_appendn (&decl, "", 1);
|
||||
return decl.b;
|
||||
}
|
||||
else
|
||||
{
|
||||
string_delete (&decl);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
get_count (type, count)
|
||||
const char **type;
|
||||
int *count;
|
||||
{
|
||||
if (!isdigit (**type))
|
||||
return 0;
|
||||
*count = **type - '0';
|
||||
*type += 1;
|
||||
/* see flush_repeats in cplus-method.c */
|
||||
if (isdigit (**type))
|
||||
{
|
||||
const char *p = *type;
|
||||
int n = *count;
|
||||
do
|
||||
{
|
||||
n *= 10;
|
||||
n += *p - '0';
|
||||
p += 1;
|
||||
}
|
||||
while (isdigit (*p));
|
||||
if (*p == '_')
|
||||
{
|
||||
*type = p + 1;
|
||||
*count = n;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* result will be initialised here; it will be freed on failure */
|
||||
|
||||
static int
|
||||
do_type (type, result)
|
||||
const char **type;
|
||||
string *result;
|
||||
{
|
||||
int n;
|
||||
int done;
|
||||
int non_empty = 0;
|
||||
int success;
|
||||
string decl;
|
||||
const char *remembered_type;
|
||||
|
||||
string_init (&decl);
|
||||
string_init (result);
|
||||
|
||||
done = 0;
|
||||
success = 1;
|
||||
while (success && !done)
|
||||
{
|
||||
int member;
|
||||
switch (**type)
|
||||
{
|
||||
case 'P':
|
||||
*type += 1;
|
||||
string_prepend (&decl, "*");
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
*type += 1;
|
||||
string_prepend (&decl, "&");
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
*type += 1;
|
||||
if (!get_count (type, &n) || n >= ntypes)
|
||||
success = 0;
|
||||
else
|
||||
{
|
||||
remembered_type = typevec[n];
|
||||
type = &remembered_type;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
*type += 1;
|
||||
if (!string_empty (&decl) && decl.b[0] == '*')
|
||||
{
|
||||
string_prepend (&decl, "(");
|
||||
string_append (&decl, ")");
|
||||
}
|
||||
if (!do_args (type, &decl) || **type != '_')
|
||||
success = 0;
|
||||
else
|
||||
*type += 1;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
case 'O':
|
||||
{
|
||||
int constp = 0;
|
||||
int volatilep = 0;
|
||||
|
||||
member = **type == 'M';
|
||||
*type += 1;
|
||||
if (!isdigit (**type))
|
||||
{
|
||||
success = 0;
|
||||
break;
|
||||
}
|
||||
n = 0;
|
||||
do
|
||||
{
|
||||
n *= 10;
|
||||
n += **type - '0';
|
||||
*type += 1;
|
||||
}
|
||||
while (isdigit (**type));
|
||||
if (strlen (*type) < n)
|
||||
{
|
||||
success = 0;
|
||||
break;
|
||||
}
|
||||
string_append (&decl, ")");
|
||||
string_prepend (&decl, "::");
|
||||
string_prependn (&decl, *type, n);
|
||||
string_prepend (&decl, "(");
|
||||
*type += n;
|
||||
if (member)
|
||||
{
|
||||
if (**type == 'C')
|
||||
{
|
||||
*type += 1;
|
||||
constp = 1;
|
||||
}
|
||||
if (**type == 'V')
|
||||
{
|
||||
*type += 1;
|
||||
volatilep = 1;
|
||||
}
|
||||
if (*(*type)++ != 'F')
|
||||
{
|
||||
success = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((member && !do_args (type, &decl)) || **type != '_')
|
||||
{
|
||||
success = 0;
|
||||
break;
|
||||
}
|
||||
*type += 1;
|
||||
if (constp)
|
||||
{
|
||||
if (non_empty)
|
||||
string_append (&decl, " ");
|
||||
else
|
||||
non_empty = 1;
|
||||
string_append (&decl, "const");
|
||||
}
|
||||
if (volatilep)
|
||||
{
|
||||
if (non_empty)
|
||||
string_append (&decl, " ");
|
||||
else
|
||||
non_empty = 1;
|
||||
string_append (&decl, "volatilep");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'C':
|
||||
if ((*type)[1] == 'P')
|
||||
{
|
||||
*type += 1;
|
||||
if (!string_empty (&decl))
|
||||
string_prepend (&decl, " ");
|
||||
string_prepend (&decl, "const");
|
||||
break;
|
||||
}
|
||||
|
||||
/* fall through */
|
||||
default:
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done = 0;
|
||||
non_empty = 0;
|
||||
while (success && !done)
|
||||
{
|
||||
switch (**type)
|
||||
{
|
||||
case 'C':
|
||||
*type += 1;
|
||||
if (non_empty)
|
||||
string_append (result, " ");
|
||||
else
|
||||
non_empty = 1;
|
||||
string_append (result, "const");
|
||||
break;
|
||||
case 'U':
|
||||
*type += 1;
|
||||
if (non_empty)
|
||||
string_append (result, " ");
|
||||
else
|
||||
non_empty = 1;
|
||||
string_append (result, "unsigned");
|
||||
break;
|
||||
case 'V':
|
||||
*type += 1;
|
||||
if (non_empty)
|
||||
string_append (result, " ");
|
||||
else
|
||||
non_empty = 1;
|
||||
string_append (result, "volatile");
|
||||
break;
|
||||
default:
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
switch (**type)
|
||||
{
|
||||
case '\0':
|
||||
case '_':
|
||||
break;
|
||||
case 'v':
|
||||
*type += 1;
|
||||
if (non_empty)
|
||||
string_append (result, " ");
|
||||
string_append (result, "void");
|
||||
break;
|
||||
case 'x':
|
||||
*type += 1;
|
||||
if (non_empty)
|
||||
string_append (result, " ");
|
||||
string_append (result, "long long");
|
||||
break;
|
||||
case 'l':
|
||||
*type += 1;
|
||||
if (non_empty)
|
||||
string_append (result, " ");
|
||||
string_append (result, "long");
|
||||
break;
|
||||
case 'i':
|
||||
*type += 1;
|
||||
if (non_empty)
|
||||
string_append (result, " ");
|
||||
string_append (result, "int");
|
||||
break;
|
||||
case 's':
|
||||
*type += 1;
|
||||
if (non_empty)
|
||||
string_append (result, " ");
|
||||
string_append (result, "short");
|
||||
break;
|
||||
case 'c':
|
||||
*type += 1;
|
||||
if (non_empty)
|
||||
string_append (result, " ");
|
||||
string_append (result, "char");
|
||||
break;
|
||||
case 'r':
|
||||
*type += 1;
|
||||
if (non_empty)
|
||||
string_append (result, " ");
|
||||
string_append (result, "long double");
|
||||
break;
|
||||
case 'd':
|
||||
*type += 1;
|
||||
if (non_empty)
|
||||
string_append (result, " ");
|
||||
string_append (result, "double");
|
||||
break;
|
||||
case 'f':
|
||||
*type += 1;
|
||||
if (non_empty)
|
||||
string_append (result, " ");
|
||||
string_append (result, "float");
|
||||
break;
|
||||
case 'G':
|
||||
*type += 1;
|
||||
if (!isdigit (**type))
|
||||
{
|
||||
success = 0;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
n = 0;
|
||||
do
|
||||
{
|
||||
n *= 10;
|
||||
n += **type - '0';
|
||||
*type += 1;
|
||||
}
|
||||
while (isdigit (**type));
|
||||
if (strlen (*type) < n)
|
||||
{
|
||||
success = 0;
|
||||
break;
|
||||
}
|
||||
if (non_empty)
|
||||
string_append (result, " ");
|
||||
string_appendn (result, *type, n);
|
||||
*type += n;
|
||||
break;
|
||||
default:
|
||||
success = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
if (!string_empty (&decl))
|
||||
{
|
||||
string_append (result, " ");
|
||||
string_appends (result, &decl);
|
||||
}
|
||||
string_delete (&decl);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
string_delete (&decl);
|
||||
string_delete (result);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* `result' will be initialised in do_type; it will be freed on failure */
|
||||
|
||||
static int
|
||||
do_arg (type, result)
|
||||
const char **type;
|
||||
string *result;
|
||||
{
|
||||
const char *start = *type;
|
||||
|
||||
if (!do_type (type, result))
|
||||
return 0;
|
||||
remember_type (start, *type - start);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
remember_type (start, len)
|
||||
const char *start;
|
||||
int len;
|
||||
{
|
||||
char *tem;
|
||||
|
||||
if (ntypes >= typevec_size)
|
||||
{
|
||||
if (typevec_size == 0)
|
||||
{
|
||||
typevec_size = 3;
|
||||
typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
typevec_size *= 2;
|
||||
typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
|
||||
}
|
||||
}
|
||||
tem = (char *) xmalloc (len + 1);
|
||||
memcpy (tem, start, len);
|
||||
tem[len] = '\0';
|
||||
typevec[ntypes++] = tem;
|
||||
}
|
||||
|
||||
/* `decl' must be already initialised, usually non-empty;
|
||||
it won't be freed on failure */
|
||||
|
||||
static int
|
||||
do_args (type, decl)
|
||||
const char **type;
|
||||
string *decl;
|
||||
{
|
||||
string arg;
|
||||
int need_comma = 0;
|
||||
|
||||
string_append (decl, "(");
|
||||
|
||||
while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
|
||||
{
|
||||
if (**type == 'N')
|
||||
{
|
||||
int r;
|
||||
int t;
|
||||
*type += 1;
|
||||
if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
|
||||
return 0;
|
||||
while (--r >= 0)
|
||||
{
|
||||
const char *tem = typevec[t];
|
||||
if (need_comma)
|
||||
string_append (decl, ", ");
|
||||
if (!do_arg (&tem, &arg))
|
||||
return 0;
|
||||
string_appends (decl, &arg);
|
||||
string_delete (&arg);
|
||||
need_comma = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (need_comma)
|
||||
string_append (decl, ", ");
|
||||
if (!do_arg (type, &arg))
|
||||
return 0;
|
||||
string_appends (decl, &arg);
|
||||
string_delete (&arg);
|
||||
need_comma = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (**type == 'v')
|
||||
*type += 1;
|
||||
else if (**type == 'e')
|
||||
{
|
||||
*type += 1;
|
||||
if (need_comma)
|
||||
string_append (decl, ",");
|
||||
string_append (decl, "...");
|
||||
}
|
||||
|
||||
string_append (decl, ")");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
munge_function_name (name)
|
||||
string *name;
|
||||
{
|
||||
if (!string_empty (name) && name->p - name->b >= 3
|
||||
&& name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
|
||||
{
|
||||
int i;
|
||||
/* see if it's an assignment expression */
|
||||
if (name->p - name->b >= 10 /* op$assign_ */
|
||||
&& memcmp (name->b + 3, "assign_", 7) == 0)
|
||||
{
|
||||
for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
|
||||
{
|
||||
int len = name->p - name->b - 10;
|
||||
if (strlen (optable[i].in) == len
|
||||
&& memcmp (optable[i].in, name->b + 10, len) == 0)
|
||||
{
|
||||
string_clear (name);
|
||||
string_append (name, "operator");
|
||||
string_append (name, optable[i].out);
|
||||
string_append (name, "=");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
|
||||
{
|
||||
int len = name->p - name->b - 3;
|
||||
if (strlen (optable[i].in) == len
|
||||
&& memcmp (optable[i].in, name->b + 3, len) == 0)
|
||||
{
|
||||
string_clear (name);
|
||||
string_append (name, "operator");
|
||||
string_append (name, optable[i].out);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (!string_empty (name) && name->p - name->b >= 5
|
||||
&& memcmp (name->b, "type$", 5) == 0)
|
||||
{
|
||||
/* type conversion operator */
|
||||
string type;
|
||||
const char *tem = name->b + 5;
|
||||
if (do_type (&tem, &type))
|
||||
{
|
||||
string_clear (name);
|
||||
string_append (name, "operator ");
|
||||
string_appends (name, &type);
|
||||
string_delete (&type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* a mini string-handling package */
|
||||
|
||||
static void
|
||||
string_need (s, n)
|
||||
string *s;
|
||||
int n;
|
||||
{
|
||||
if (s->b == NULL)
|
||||
{
|
||||
if (n < 32)
|
||||
n = 32;
|
||||
s->p = s->b = (char *) xmalloc (n);
|
||||
s->e = s->b + n;
|
||||
}
|
||||
else if (s->e - s->p < n)
|
||||
{
|
||||
int tem = s->p - s->b;
|
||||
n += tem;
|
||||
n *= 2;
|
||||
s->b = (char *) xrealloc (s->b, n);
|
||||
s->p = s->b + tem;
|
||||
s->e = s->b + n;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
string_delete (s)
|
||||
string *s;
|
||||
{
|
||||
if (s->b != NULL)
|
||||
{
|
||||
free (s->b);
|
||||
s->b = s->e = s->p = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
string_init (s)
|
||||
string *s;
|
||||
{
|
||||
s->b = s->p = s->e = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
string_clear (s)
|
||||
string *s;
|
||||
{
|
||||
s->p = s->b;
|
||||
}
|
||||
|
||||
static int
|
||||
string_empty (s)
|
||||
string *s;
|
||||
{
|
||||
return s->b == s->p;
|
||||
}
|
||||
|
||||
static void
|
||||
string_append (p, s)
|
||||
string *p;
|
||||
const char *s;
|
||||
{
|
||||
int n;
|
||||
if (s == NULL || *s == '\0')
|
||||
return;
|
||||
n = strlen (s);
|
||||
string_need (p, n);
|
||||
memcpy (p->p, s, n);
|
||||
p->p += n;
|
||||
}
|
||||
|
||||
static void
|
||||
string_appends (p, s)
|
||||
string *p, *s;
|
||||
{
|
||||
int n;
|
||||
if (s->b == s->p)
|
||||
return;
|
||||
n = s->p - s->b;
|
||||
string_need (p, n);
|
||||
memcpy (p->p, s->b, n);
|
||||
p->p += n;
|
||||
}
|
||||
|
||||
static void
|
||||
string_appendn (p, s, n)
|
||||
string *p;
|
||||
const char *s;
|
||||
int n;
|
||||
{
|
||||
if (n == 0)
|
||||
return;
|
||||
string_need (p, n);
|
||||
memcpy (p->p, s, n);
|
||||
p->p += n;
|
||||
}
|
||||
|
||||
static void
|
||||
string_prepend (p, s)
|
||||
string *p;
|
||||
const char *s;
|
||||
{
|
||||
if (s == NULL || *s == '\0')
|
||||
return;
|
||||
string_prependn (p, s, strlen (s));
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
string_prepends (p, s)
|
||||
string *p, *s;
|
||||
{
|
||||
if (s->b == s->p)
|
||||
return;
|
||||
string_prependn (p, s->b, s->p - s->b);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
string_prependn (p, s, n)
|
||||
string *p;
|
||||
const char *s;
|
||||
int n;
|
||||
{
|
||||
char *q;
|
||||
|
||||
if (n == 0)
|
||||
return;
|
||||
string_need (p, n);
|
||||
for (q = p->p - 1; q >= p->b; q--)
|
||||
q[n] = q[0];
|
||||
memcpy (p->b, s, n);
|
||||
p->p += n;
|
||||
}
|
4718
usr.bin/ld/ld.c
Normal file
4718
usr.bin/ld/ld.c
Normal file
File diff suppressed because it is too large
Load Diff
358
usr.bin/ld/symseg.h
Normal file
358
usr.bin/ld/symseg.h
Normal file
@ -0,0 +1,358 @@
|
||||
/*-
|
||||
*
|
||||
* This code is derived from software copyrighted by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* @(#)symseg.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
/* GDB symbol table format definitions.
|
||||
Copyright (C) 1987, 1988 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* Format of GDB symbol table data.
|
||||
There is one symbol segment for each source file or
|
||||
independant compilation. These segments are simply concatenated
|
||||
to form the GDB symbol table. A zero word where the beginning
|
||||
of a segment is expected indicates there are no more segments.
|
||||
|
||||
Format of a symbol segment:
|
||||
|
||||
The symbol segment begins with a word containing 1
|
||||
if it is in the format described here. Other formats may
|
||||
be designed, with other code numbers.
|
||||
|
||||
The segment contains many objects which point at each other.
|
||||
The pointers are offsets in bytes from the beginning of the segment.
|
||||
Thus, each segment can be loaded into core and its pointers relocated
|
||||
to make valid in-core pointers.
|
||||
|
||||
All the data objects in the segment can be found indirectly from
|
||||
one of them, the root object, of type `struct symbol_root'.
|
||||
It appears at the beginning of the segment.
|
||||
|
||||
The total size of the segment, in bytes, appears as the `length'
|
||||
field of this object. This size includes the size of the
|
||||
root object.
|
||||
|
||||
All the object data types are defined here to contain pointer types
|
||||
appropriate for in-core use on a relocated symbol segment.
|
||||
Casts to and from type int are required for working with
|
||||
unrelocated symbol segments such as are found in the file.
|
||||
|
||||
The ldsymaddr word is filled in by the loader to contain
|
||||
the offset (in bytes) within the ld symbol table
|
||||
of the first nonglobal symbol from this compilation.
|
||||
This makes it possible to match those symbols
|
||||
(which contain line number information) reliably with
|
||||
the segment they go with.
|
||||
|
||||
Core addresses within the program that appear in the symbol segment
|
||||
are not relocated by the loader. They are inserted by the assembler
|
||||
and apply to addresses as output by the assembler, so GDB must
|
||||
relocate them when it loads the symbol segment. It gets the information
|
||||
on how to relocate from the textrel, datarel, bssrel, databeg and bssbeg
|
||||
words of the root object.
|
||||
|
||||
The words textrel, datarel and bssrel
|
||||
are filled in by ld with the amounts to relocate within-the-file
|
||||
text, data and bss addresses by; databeg and bssbeg can be
|
||||
used to tell which kind of relocation an address needs. */
|
||||
|
||||
enum language {language_c};
|
||||
|
||||
struct symbol_root
|
||||
{
|
||||
int format; /* Data format version */
|
||||
int length; /* # bytes in this symbol segment */
|
||||
int ldsymoff; /* Offset in ld symtab of this file's syms */
|
||||
int textrel; /* Relocation for text addresses */
|
||||
int datarel; /* Relocation for data addresses */
|
||||
int bssrel; /* Relocation for bss addresses */
|
||||
char *filename; /* Name of main source file compiled */
|
||||
char *filedir; /* Name of directory it was reached from */
|
||||
struct blockvector *blockvector; /* Vector of all symbol-naming blocks */
|
||||
struct typevector *typevector; /* Vector of all data types */
|
||||
enum language language; /* Code identifying the language used */
|
||||
char *version; /* Version info. Not fully specified */
|
||||
char *compilation; /* Compilation info. Not fully specified */
|
||||
int databeg; /* Address within the file of data start */
|
||||
int bssbeg; /* Address within the file of bss start */
|
||||
struct sourcevector *sourcevector; /* Vector of line-number info */
|
||||
};
|
||||
|
||||
/* All data types of symbols in the compiled program
|
||||
are represented by `struct type' objects.
|
||||
All of these objects are pointed to by the typevector.
|
||||
The type vector may have empty slots that contain zero. */
|
||||
|
||||
struct typevector
|
||||
{
|
||||
int length; /* Number of types described */
|
||||
struct type *type[1];
|
||||
};
|
||||
|
||||
/* Different kinds of data types are distinguished by the `code' field. */
|
||||
|
||||
enum type_code
|
||||
{
|
||||
TYPE_CODE_UNDEF, /* Not used; catches errors */
|
||||
TYPE_CODE_PTR, /* Pointer type */
|
||||
TYPE_CODE_ARRAY, /* Array type, lower bound zero */
|
||||
TYPE_CODE_STRUCT, /* C struct or Pascal record */
|
||||
TYPE_CODE_UNION, /* C union or Pascal variant part */
|
||||
TYPE_CODE_ENUM, /* Enumeration type */
|
||||
TYPE_CODE_FUNC, /* Function type */
|
||||
TYPE_CODE_INT, /* Integer type */
|
||||
TYPE_CODE_FLT, /* Floating type */
|
||||
TYPE_CODE_VOID, /* Void type (values zero length) */
|
||||
TYPE_CODE_SET, /* Pascal sets */
|
||||
TYPE_CODE_RANGE, /* Range (integers within spec'd bounds) */
|
||||
TYPE_CODE_PASCAL_ARRAY, /* Array with explicit type of index */
|
||||
};
|
||||
|
||||
/* This appears in a type's flags word for an unsigned integer type. */
|
||||
#define TYPE_FLAG_UNSIGNED 1
|
||||
|
||||
/* Other flag bits are used with GDB. */
|
||||
|
||||
struct type
|
||||
{
|
||||
/* Code for kind of type */
|
||||
enum type_code code;
|
||||
/* Name of this type, or zero if none.
|
||||
This is used for printing only.
|
||||
Type names specified as input are defined by symbols. */
|
||||
char *name;
|
||||
/* Length in bytes of storage for a value of this type */
|
||||
int length;
|
||||
/* For a pointer type, describes the type of object pointed to.
|
||||
For an array type, describes the type of the elements.
|
||||
For a function type, describes the type of the value.
|
||||
Unused otherwise. */
|
||||
struct type *target_type;
|
||||
/* Type that is a pointer to this type.
|
||||
Zero if no such pointer-to type is known yet.
|
||||
The debugger may add the address of such a type
|
||||
if it has to construct one later. */
|
||||
struct type *pointer_type;
|
||||
/* Type that is a function returning this type.
|
||||
Zero if no such function type is known here.
|
||||
The debugger may add the address of such a type
|
||||
if it has to construct one later. */
|
||||
struct type *function_type;
|
||||
/* Flags about this type. */
|
||||
short flags;
|
||||
/* Number of fields described for this type */
|
||||
short nfields;
|
||||
/* For structure and union types, a description of each field.
|
||||
For set and pascal array types, there is one "field",
|
||||
whose type is the domain type of the set or array.
|
||||
For range types, there are two "fields",
|
||||
the minimum and maximum values (both inclusive).
|
||||
For enum types, each possible value is described by one "field".
|
||||
For range types, there are two "fields", that record constant values
|
||||
(inclusive) for the minimum and maximum.
|
||||
|
||||
Using a pointer to a separate array of fields
|
||||
allows all types to have the same size, which is useful
|
||||
because we can allocate the space for a type before
|
||||
we know what to put in it. */
|
||||
struct field
|
||||
{
|
||||
/* Position of this field, counting in bits from start of
|
||||
containing structure. For a function type, this is the
|
||||
position in the argument list of this argument.
|
||||
For a range bound or enum value, this is the value itself. */
|
||||
int bitpos;
|
||||
/* Size of this field, in bits, or zero if not packed.
|
||||
For an unpacked field, the field's type's length
|
||||
says how many bytes the field occupies. */
|
||||
int bitsize;
|
||||
/* In a struct or enum type, type of this field.
|
||||
In a function type, type of this argument.
|
||||
In an array type, the domain-type of the array. */
|
||||
struct type *type;
|
||||
/* Name of field, value or argument.
|
||||
Zero for range bounds and array domains. */
|
||||
char *name;
|
||||
} *fields;
|
||||
};
|
||||
|
||||
/* All of the name-scope contours of the program
|
||||
are represented by `struct block' objects.
|
||||
All of these objects are pointed to by the blockvector.
|
||||
|
||||
Each block represents one name scope.
|
||||
Each lexical context has its own block.
|
||||
|
||||
The first two blocks in the blockvector are special.
|
||||
The first one contains all the symbols defined in this compilation
|
||||
whose scope is the entire program linked together.
|
||||
The second one contains all the symbols whose scope is the
|
||||
entire compilation excluding other separate compilations.
|
||||
In C, these correspond to global symbols and static symbols.
|
||||
|
||||
Each block records a range of core addresses for the code that
|
||||
is in the scope of the block. The first two special blocks
|
||||
give, for the range of code, the entire range of code produced
|
||||
by the compilation that the symbol segment belongs to.
|
||||
|
||||
The blocks appear in the blockvector
|
||||
in order of increasing starting-address,
|
||||
and, within that, in order of decreasing ending-address.
|
||||
|
||||
This implies that within the body of one function
|
||||
the blocks appear in the order of a depth-first tree walk. */
|
||||
|
||||
struct blockvector
|
||||
{
|
||||
/* Number of blocks in the list. */
|
||||
int nblocks;
|
||||
/* The blocks themselves. */
|
||||
struct block *block[1];
|
||||
};
|
||||
|
||||
struct block
|
||||
{
|
||||
/* Addresses in the executable code that are in this block.
|
||||
Note: in an unrelocated symbol segment in a file,
|
||||
these are always zero. They can be filled in from the
|
||||
N_LBRAC and N_RBRAC symbols in the loader symbol table. */
|
||||
int startaddr, endaddr;
|
||||
/* The symbol that names this block,
|
||||
if the block is the body of a function;
|
||||
otherwise, zero.
|
||||
Note: In an unrelocated symbol segment in an object file,
|
||||
this field may be zero even when the block has a name.
|
||||
That is because the block is output before the name
|
||||
(since the name resides in a higher block).
|
||||
Since the symbol does point to the block (as its value),
|
||||
it is possible to find the block and set its name properly. */
|
||||
struct symbol *function;
|
||||
/* The `struct block' for the containing block, or 0 if none. */
|
||||
/* Note that in an unrelocated symbol segment in an object file
|
||||
this pointer may be zero when the correct value should be
|
||||
the second special block (for symbols whose scope is one compilation).
|
||||
This is because the compiler ouptuts the special blocks at the
|
||||
very end, after the other blocks. */
|
||||
struct block *superblock;
|
||||
/* Number of local symbols. */
|
||||
int nsyms;
|
||||
/* The symbols. */
|
||||
struct symbol *sym[1];
|
||||
};
|
||||
|
||||
/* Represent one symbol name; a variable, constant, function or typedef. */
|
||||
|
||||
/* Different name spaces for symbols. Looking up a symbol specifies
|
||||
a namespace and ignores symbol definitions in other name spaces.
|
||||
|
||||
VAR_NAMESPACE is the usual namespace.
|
||||
In C, this contains variables, function names, typedef names
|
||||
and enum type values.
|
||||
|
||||
STRUCT_NAMESPACE is used in C to hold struct, union and enum type names.
|
||||
Thus, if `struct foo' is used in a C program,
|
||||
it produces a symbol named `foo' in the STRUCT_NAMESPACE.
|
||||
|
||||
LABEL_NAMESPACE may be used for names of labels (for gotos);
|
||||
currently it is not used and labels are not recorded at all. */
|
||||
|
||||
/* For a non-global symbol allocated statically,
|
||||
the correct core address cannot be determined by the compiler.
|
||||
The compiler puts an index number into the symbol's value field.
|
||||
This index number can be matched with the "desc" field of
|
||||
an entry in the loader symbol table. */
|
||||
|
||||
enum namespace
|
||||
{
|
||||
UNDEF_NAMESPACE, VAR_NAMESPACE, STRUCT_NAMESPACE, LABEL_NAMESPACE,
|
||||
};
|
||||
|
||||
/* An address-class says where to find the value of the symbol in core. */
|
||||
|
||||
enum address_class
|
||||
{
|
||||
LOC_UNDEF, /* Not used; catches errors */
|
||||
LOC_CONST, /* Value is constant int */
|
||||
LOC_STATIC, /* Value is at fixed address */
|
||||
LOC_REGISTER, /* Value is in register */
|
||||
LOC_ARG, /* Value is at spec'd position in arglist */
|
||||
LOC_LOCAL, /* Value is at spec'd pos in stack frame */
|
||||
LOC_TYPEDEF, /* Value not used; definition in SYMBOL_TYPE
|
||||
Symbols in the namespace STRUCT_NAMESPACE
|
||||
all have this class. */
|
||||
LOC_LABEL, /* Value is address in the code */
|
||||
LOC_BLOCK, /* Value is address of a `struct block'.
|
||||
Function names have this class. */
|
||||
LOC_EXTERNAL, /* Value is at address not in this compilation.
|
||||
This is used for .comm symbols
|
||||
and for extern symbols within functions.
|
||||
Inside GDB, this is changed to LOC_STATIC once the
|
||||
real address is obtained from a loader symbol. */
|
||||
LOC_CONST_BYTES /* Value is a constant byte-sequence. */
|
||||
};
|
||||
|
||||
struct symbol
|
||||
{
|
||||
/* Symbol name */
|
||||
char *name;
|
||||
/* Name space code. */
|
||||
enum namespace namespace;
|
||||
/* Address class */
|
||||
enum address_class class;
|
||||
/* Data type of value */
|
||||
struct type *type;
|
||||
/* constant value, or address if static, or register number,
|
||||
or offset in arguments, or offset in stack frame. */
|
||||
union
|
||||
{
|
||||
long value;
|
||||
struct block *block; /* for LOC_BLOCK */
|
||||
char *bytes; /* for LOC_CONST_BYTES */
|
||||
}
|
||||
value;
|
||||
};
|
||||
|
||||
/* Source-file information.
|
||||
This describes the relation between source files and line numbers
|
||||
and addresses in the program text. */
|
||||
|
||||
struct sourcevector
|
||||
{
|
||||
int length; /* Number of source files described */
|
||||
struct source *source[1]; /* Descriptions of the files */
|
||||
};
|
||||
|
||||
/* Line number and address of one line. */
|
||||
|
||||
struct line
|
||||
{
|
||||
int linenum;
|
||||
int address;
|
||||
};
|
||||
|
||||
/* All the information on one source file. */
|
||||
|
||||
struct source
|
||||
{
|
||||
char *name; /* Name of file */
|
||||
int nlines; /* Number of lines that follow */
|
||||
struct line lines[1]; /* Information on each line */
|
||||
};
|
475
usr.bin/m4/serv.c
Normal file
475
usr.bin/m4/serv.c
Normal file
@ -0,0 +1,475 @@
|
||||
/*
|
||||
* Copyright (c) 1989
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Ozan Yigit.
|
||||
*
|
||||
* 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[] = "@(#)serv.c 5.4 (Berkeley) 1/21/94";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* serv.c
|
||||
* Facility: m4 macro processor
|
||||
* by: oz
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "mdef.h"
|
||||
#include "extr.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
extern ndptr lookup();
|
||||
extern ndptr addent();
|
||||
|
||||
char *dumpfmt = "`%s'\t`%s'\n"; /* format string for dumpdef */
|
||||
|
||||
/*
|
||||
* expand - user-defined macro expansion
|
||||
*
|
||||
*/
|
||||
expand(argv, argc)
|
||||
register char *argv[];
|
||||
register int argc;
|
||||
{
|
||||
register char *t;
|
||||
register char *p;
|
||||
register int n;
|
||||
register int argno;
|
||||
|
||||
t = argv[0]; /* defn string as a whole */
|
||||
p = t;
|
||||
while (*p)
|
||||
p++;
|
||||
p--; /* last character of defn */
|
||||
while (p > t) {
|
||||
if (*(p-1) != ARGFLAG)
|
||||
putback(*p);
|
||||
else {
|
||||
switch (*p) {
|
||||
|
||||
case '#':
|
||||
pbnum(argc-2);
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if ((argno = *p - '0') < argc-1)
|
||||
pbstr(argv[argno+1]);
|
||||
break;
|
||||
case '*':
|
||||
for (n = argc - 1; n > 2; n--) {
|
||||
pbstr(argv[n]);
|
||||
putback(',');
|
||||
}
|
||||
pbstr(argv[2]);
|
||||
break;
|
||||
default :
|
||||
putback(*p);
|
||||
break;
|
||||
}
|
||||
p--;
|
||||
}
|
||||
p--;
|
||||
}
|
||||
if (p == t) /* do last character */
|
||||
putback(*p);
|
||||
}
|
||||
|
||||
/*
|
||||
* dodefine - install definition in the table
|
||||
*
|
||||
*/
|
||||
dodefine(name, defn)
|
||||
register char *name;
|
||||
register char *defn;
|
||||
{
|
||||
register ndptr p;
|
||||
|
||||
if (!*name)
|
||||
error("m4: null definition.");
|
||||
if (strcmp(name, defn) == 0)
|
||||
error("m4: recursive definition.");
|
||||
if ((p = lookup(name)) == nil)
|
||||
p = addent(name);
|
||||
else if (p->defn != null)
|
||||
free(p->defn);
|
||||
if (!*defn)
|
||||
p->defn = null;
|
||||
else
|
||||
p->defn = strdup(defn);
|
||||
p->type = MACRTYPE;
|
||||
}
|
||||
|
||||
/*
|
||||
* dodefn - push back a quoted definition of
|
||||
* the given name.
|
||||
*/
|
||||
|
||||
dodefn(name)
|
||||
char *name;
|
||||
{
|
||||
register ndptr p;
|
||||
|
||||
if ((p = lookup(name)) != nil && p->defn != null) {
|
||||
putback(rquote);
|
||||
pbstr(p->defn);
|
||||
putback(lquote);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dopushdef - install a definition in the hash table
|
||||
* without removing a previous definition. Since
|
||||
* each new entry is entered in *front* of the
|
||||
* hash bucket, it hides a previous definition from
|
||||
* lookup.
|
||||
*/
|
||||
dopushdef(name, defn)
|
||||
register char *name;
|
||||
register char *defn;
|
||||
{
|
||||
register ndptr p;
|
||||
|
||||
if (!*name)
|
||||
error("m4: null definition");
|
||||
if (strcmp(name, defn) == 0)
|
||||
error("m4: recursive definition.");
|
||||
p = addent(name);
|
||||
if (!*defn)
|
||||
p->defn = null;
|
||||
else
|
||||
p->defn = strdup(defn);
|
||||
p->type = MACRTYPE;
|
||||
}
|
||||
|
||||
/*
|
||||
* dodumpdef - dump the specified definitions in the hash
|
||||
* table to stderr. If nothing is specified, the entire
|
||||
* hash table is dumped.
|
||||
*
|
||||
*/
|
||||
dodump(argv, argc)
|
||||
register char *argv[];
|
||||
register int argc;
|
||||
{
|
||||
register int n;
|
||||
ndptr p;
|
||||
|
||||
if (argc > 2) {
|
||||
for (n = 2; n < argc; n++)
|
||||
if ((p = lookup(argv[n])) != nil)
|
||||
fprintf(stderr, dumpfmt, p->name,
|
||||
p->defn);
|
||||
}
|
||||
else {
|
||||
for (n = 0; n < HASHSIZE; n++)
|
||||
for (p = hashtab[n]; p != nil; p = p->nxtptr)
|
||||
fprintf(stderr, dumpfmt, p->name,
|
||||
p->defn);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* doifelse - select one of two alternatives - loop.
|
||||
*
|
||||
*/
|
||||
doifelse(argv,argc)
|
||||
register char *argv[];
|
||||
register int argc;
|
||||
{
|
||||
cycle {
|
||||
if (strcmp(argv[2], argv[3]) == 0)
|
||||
pbstr(argv[4]);
|
||||
else if (argc == 6)
|
||||
pbstr(argv[5]);
|
||||
else if (argc > 6) {
|
||||
argv += 3;
|
||||
argc -= 3;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* doinclude - include a given file.
|
||||
*
|
||||
*/
|
||||
doincl(ifile)
|
||||
char *ifile;
|
||||
{
|
||||
if (ilevel+1 == MAXINP)
|
||||
error("m4: too many include files.");
|
||||
if ((infile[ilevel+1] = fopen(ifile, "r")) != NULL) {
|
||||
ilevel++;
|
||||
return (1);
|
||||
}
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef EXTENDED
|
||||
/*
|
||||
* dopaste - include a given file without any
|
||||
* macro processing.
|
||||
*/
|
||||
dopaste(pfile)
|
||||
char *pfile;
|
||||
{
|
||||
FILE *pf;
|
||||
register int c;
|
||||
|
||||
if ((pf = fopen(pfile, "r")) != NULL) {
|
||||
while((c = getc(pf)) != EOF)
|
||||
putc(c, active);
|
||||
(void) fclose(pf);
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* dochq - change quote characters
|
||||
*
|
||||
*/
|
||||
dochq(argv, argc)
|
||||
register char *argv[];
|
||||
register int argc;
|
||||
{
|
||||
if (argc > 2) {
|
||||
if (*argv[2])
|
||||
lquote = *argv[2];
|
||||
if (argc > 3) {
|
||||
if (*argv[3])
|
||||
rquote = *argv[3];
|
||||
}
|
||||
else
|
||||
rquote = lquote;
|
||||
}
|
||||
else {
|
||||
lquote = LQUOTE;
|
||||
rquote = RQUOTE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dochc - change comment characters
|
||||
*
|
||||
*/
|
||||
dochc(argv, argc)
|
||||
register char *argv[];
|
||||
register int argc;
|
||||
{
|
||||
if (argc > 2) {
|
||||
if (*argv[2])
|
||||
scommt = *argv[2];
|
||||
if (argc > 3) {
|
||||
if (*argv[3])
|
||||
ecommt = *argv[3];
|
||||
}
|
||||
else
|
||||
ecommt = ECOMMT;
|
||||
}
|
||||
else {
|
||||
scommt = SCOMMT;
|
||||
ecommt = ECOMMT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dodivert - divert the output to a temporary file
|
||||
*
|
||||
*/
|
||||
dodiv(n)
|
||||
register int n;
|
||||
{
|
||||
if (n < 0 || n >= MAXOUT)
|
||||
n = 0; /* bitbucket */
|
||||
if (outfile[n] == NULL) {
|
||||
m4temp[UNIQUE] = n + '0';
|
||||
if ((outfile[n] = fopen(m4temp, "w")) == NULL)
|
||||
error("m4: cannot divert.");
|
||||
}
|
||||
oindex = n;
|
||||
active = outfile[n];
|
||||
}
|
||||
|
||||
/*
|
||||
* doundivert - undivert a specified output, or all
|
||||
* other outputs, in numerical order.
|
||||
*/
|
||||
doundiv(argv, argc)
|
||||
register char *argv[];
|
||||
register int argc;
|
||||
{
|
||||
register int ind;
|
||||
register int n;
|
||||
|
||||
if (argc > 2) {
|
||||
for (ind = 2; ind < argc; ind++) {
|
||||
n = atoi(argv[ind]);
|
||||
if (n > 0 && n < MAXOUT && outfile[n] != NULL)
|
||||
getdiv(n);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
for (n = 1; n < MAXOUT; n++)
|
||||
if (outfile[n] != NULL)
|
||||
getdiv(n);
|
||||
}
|
||||
|
||||
/*
|
||||
* dosub - select substring
|
||||
*
|
||||
*/
|
||||
dosub (argv, argc)
|
||||
register char *argv[];
|
||||
register int argc;
|
||||
{
|
||||
register char *ap, *fc, *k;
|
||||
register int nc;
|
||||
|
||||
if (argc < 5)
|
||||
nc = MAXTOK;
|
||||
else
|
||||
#ifdef EXPR
|
||||
nc = expr(argv[4]);
|
||||
#else
|
||||
nc = atoi(argv[4]);
|
||||
#endif
|
||||
ap = argv[2]; /* target string */
|
||||
#ifdef EXPR
|
||||
fc = ap + expr(argv[3]); /* first char */
|
||||
#else
|
||||
fc = ap + atoi(argv[3]); /* first char */
|
||||
#endif
|
||||
if (fc >= ap && fc < ap+strlen(ap))
|
||||
for (k = fc+min(nc,strlen(fc))-1; k >= fc; k--)
|
||||
putback(*k);
|
||||
}
|
||||
|
||||
/*
|
||||
* map:
|
||||
* map every character of s1 that is specified in from
|
||||
* into s3 and replace in s. (source s1 remains untouched)
|
||||
*
|
||||
* This is a standard implementation of map(s,from,to) function of ICON
|
||||
* language. Within mapvec, we replace every character of "from" with
|
||||
* the corresponding character in "to". If "to" is shorter than "from",
|
||||
* than the corresponding entries are null, which means that those
|
||||
* characters dissapear altogether. Furthermore, imagine
|
||||
* map(dest, "sourcestring", "srtin", "rn..*") type call. In this case,
|
||||
* `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s'
|
||||
* ultimately maps to `*'. In order to achieve this effect in an efficient
|
||||
* manner (i.e. without multiple passes over the destination string), we
|
||||
* loop over mapvec, starting with the initial source character. if the
|
||||
* character value (dch) in this location is different than the source
|
||||
* character (sch), sch becomes dch, once again to index into mapvec, until
|
||||
* the character value stabilizes (i.e. sch = dch, in other words
|
||||
* mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary
|
||||
* character, it will stabilize, since mapvec[0] == 0 at all times. At the
|
||||
* end, we restore mapvec* back to normal where mapvec[n] == n for
|
||||
* 0 <= n <= 127. This strategy, along with the restoration of mapvec, is
|
||||
* about 5 times faster than any algorithm that makes multiple passes over
|
||||
* destination string.
|
||||
*
|
||||
*/
|
||||
|
||||
map(dest,src,from,to)
|
||||
register char *dest;
|
||||
register char *src;
|
||||
register char *from;
|
||||
register char *to;
|
||||
{
|
||||
register char *tmp;
|
||||
register char sch, dch;
|
||||
static char mapvec[128] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
|
||||
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
||||
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
|
||||
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
|
||||
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
|
||||
84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
|
||||
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
|
||||
108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
|
||||
120, 121, 122, 123, 124, 125, 126, 127
|
||||
};
|
||||
|
||||
if (*src) {
|
||||
tmp = from;
|
||||
/*
|
||||
* create a mapping between "from" and "to"
|
||||
*/
|
||||
while (*from)
|
||||
mapvec[*from++] = (*to) ? *to++ : (char) 0;
|
||||
|
||||
while (*src) {
|
||||
sch = *src++;
|
||||
dch = mapvec[sch];
|
||||
while (dch != sch) {
|
||||
sch = dch;
|
||||
dch = mapvec[sch];
|
||||
}
|
||||
if (*dest = dch)
|
||||
dest++;
|
||||
}
|
||||
/*
|
||||
* restore all the changed characters
|
||||
*/
|
||||
while (*tmp) {
|
||||
mapvec[*tmp] = *tmp;
|
||||
tmp++;
|
||||
}
|
||||
}
|
||||
*dest = (char) 0;
|
||||
}
|
8
usr.bin/man/Makefile
Normal file
8
usr.bin/man/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= man
|
||||
SRCS= config.c man.c
|
||||
MAN1= man.0
|
||||
MAN5= man.conf.0
|
||||
|
||||
.include <bsd.prog.mk>
|
176
usr.bin/man/config.c
Normal file
176
usr.bin/man/config.c
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993, 1995
|
||||
* 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[] = "@(#)config.c 8.8 (Berkeley) 1/31/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
struct _head head;
|
||||
|
||||
/*
|
||||
* config --
|
||||
*
|
||||
* Read the configuration file and build a doubly linked
|
||||
* list that looks like:
|
||||
*
|
||||
* tag1 <-> record <-> record <-> record
|
||||
* |
|
||||
* tag2 <-> record <-> record <-> record
|
||||
*/
|
||||
void
|
||||
config(fname)
|
||||
char *fname;
|
||||
{
|
||||
TAG *tp;
|
||||
ENTRY *ep;
|
||||
FILE *cfp;
|
||||
size_t len;
|
||||
int lcnt;
|
||||
char *p, *t;
|
||||
|
||||
if (fname == NULL)
|
||||
fname = _PATH_MANCONF;
|
||||
if ((cfp = fopen(fname, "r")) == NULL)
|
||||
err(1, "%s", fname);
|
||||
TAILQ_INIT(&head);
|
||||
for (lcnt = 1; (p = fgetln(cfp, &len)) != NULL; ++lcnt) {
|
||||
if (len == 1) /* Skip empty lines. */
|
||||
continue;
|
||||
if (p[len - 1] != '\n') { /* Skip corrupted lines. */
|
||||
warnx("%s: line %d corrupted", fname, lcnt);
|
||||
continue;
|
||||
}
|
||||
p[len - 1] = '\0'; /* Terminate the line. */
|
||||
|
||||
/* Skip leading space. */
|
||||
for (; *p != '\0' && isspace(*p); ++p);
|
||||
/* Skip empty/comment lines. */
|
||||
if (*p == '\0' || *p == '#')
|
||||
continue;
|
||||
/* Find first token. */
|
||||
for (t = p; *t && !isspace(*t); ++t);
|
||||
if (*t == '\0') /* Need more than one token.*/
|
||||
continue;
|
||||
*t = '\0';
|
||||
|
||||
for (tp = head.tqh_first; /* Find any matching tag. */
|
||||
tp != NULL && strcmp(p, tp->s); tp = tp->q.tqe_next);
|
||||
|
||||
if (tp == NULL) /* Create a new tag. */
|
||||
tp = addlist(p);
|
||||
|
||||
/*
|
||||
* Attach new records. The keyword _build takes the rest of
|
||||
* the line as a single entity, everything else is white
|
||||
* space separated. The reason we're not just using strtok(3)
|
||||
* for all of the parsing is so we don't get caught if a line
|
||||
* has only a single token on it.
|
||||
*/
|
||||
if (!strcmp(p, "_build")) {
|
||||
while (*++t && isspace(*t));
|
||||
if ((ep = malloc(sizeof(ENTRY))) == NULL ||
|
||||
(ep->s = strdup(t)) == NULL)
|
||||
err(1, NULL);
|
||||
TAILQ_INSERT_TAIL(&tp->list, ep, q);
|
||||
} else for (++t; (p = strtok(t, " \t\n")) != NULL; t = NULL) {
|
||||
if ((ep = malloc(sizeof(ENTRY))) == NULL ||
|
||||
(ep->s = strdup(p)) == NULL)
|
||||
err(1, NULL);
|
||||
TAILQ_INSERT_TAIL(&tp->list, ep, q);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(cfp);
|
||||
}
|
||||
|
||||
/*
|
||||
* addlist --
|
||||
* Add a tag to the list.
|
||||
*/
|
||||
TAG *
|
||||
addlist(name)
|
||||
char *name;
|
||||
{
|
||||
TAG *tp;
|
||||
|
||||
if ((tp = calloc(1, sizeof(TAG))) == NULL ||
|
||||
(tp->s = strdup(name)) == NULL)
|
||||
err(1, NULL);
|
||||
TAILQ_INIT(&tp->list);
|
||||
TAILQ_INSERT_TAIL(&head, tp, q);
|
||||
return (tp);
|
||||
}
|
||||
|
||||
/*
|
||||
* getlist --
|
||||
* Return the linked list of entries for a tag if it exists.
|
||||
*/
|
||||
TAG *
|
||||
getlist(name)
|
||||
char *name;
|
||||
{
|
||||
TAG *tp;
|
||||
|
||||
for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next)
|
||||
if (!strcmp(name, tp->s))
|
||||
return (tp);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
debug(l)
|
||||
char *l;
|
||||
{
|
||||
TAG *tp;
|
||||
ENTRY *ep;
|
||||
|
||||
(void)printf("%s ===============\n", l);
|
||||
for (tp = head.tqh_first; tp != NULL; tp = tp->q.tqe_next) {
|
||||
printf("%s\n", tp->s);
|
||||
for (ep = tp->list.tqh_first; ep != NULL; ep = ep->q.tqe_next)
|
||||
printf("\t%s\n", ep->s);
|
||||
}
|
||||
}
|
57
usr.bin/man/config.h
Normal file
57
usr.bin/man/config.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*-
|
||||
* 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.
|
||||
*
|
||||
* @(#)config.h 8.4 (Berkeley) 12/18/93
|
||||
*/
|
||||
|
||||
typedef struct _tag {
|
||||
TAILQ_ENTRY(_tag) q; /* Queue of tags. */
|
||||
|
||||
TAILQ_HEAD(tqh, _entry) list; /* Queue of entries. */
|
||||
char *s; /* Associated string. */
|
||||
size_t len; /* Length of 's'. */
|
||||
} TAG;
|
||||
typedef struct _entry {
|
||||
TAILQ_ENTRY(_entry) q; /* Queue of entries. */
|
||||
|
||||
char *s; /* Associated string. */
|
||||
size_t len; /* Length of 's'. */
|
||||
} ENTRY;
|
||||
|
||||
TAILQ_HEAD(_head, _tag);
|
||||
extern struct _head head;
|
||||
|
||||
TAG *addlist __P((char *));
|
||||
void config __P((char *));
|
||||
void debug __P((char *));
|
||||
TAG *getlist __P((char *));
|
188
usr.bin/man/man.1
Normal file
188
usr.bin/man/man.1
Normal file
@ -0,0 +1,188 @@
|
||||
.\" Copyright (c) 1989, 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.
|
||||
.\"
|
||||
.\" @(#)man.1 8.2 (Berkeley) 1/2/94
|
||||
.\"
|
||||
.Dd January 2, 1994
|
||||
.Dt MAN 1
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm man
|
||||
.Nd display the on-line manual pages
|
||||
.Sh SYNOPSIS
|
||||
.Nm man
|
||||
.Op Fl achw
|
||||
.Op Fl C Ar file
|
||||
.Op Fl M Ar path
|
||||
.Op Fl m Ar path
|
||||
.Op Ar section
|
||||
.Ar name Ar ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm man
|
||||
utility
|
||||
displays the
|
||||
.Bx
|
||||
manual pages entitled
|
||||
.Ar name .
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl a
|
||||
Display all of the manual pages for a specified
|
||||
.Ar section
|
||||
and
|
||||
.Ar name
|
||||
combination.
|
||||
(Normally, only the first manual page found is displayed.)
|
||||
.It Fl C
|
||||
Use the specified
|
||||
.Ar file
|
||||
instead of the default configuration file.
|
||||
This permits users to configure their own manual environment.
|
||||
See
|
||||
.Xr man.conf 5
|
||||
for a description of the contents of this file.
|
||||
.It Fl c
|
||||
Copy the manual page to the standard output instead of using
|
||||
.Xr more 1
|
||||
to paginate it.
|
||||
This is done by default if the standard output is not a terminal device.
|
||||
.It Fl h
|
||||
Display only the
|
||||
.Dq Tn SYNOPSIS
|
||||
lines of the requested manual pages.
|
||||
.It Fl M
|
||||
Override the list of standard directories which
|
||||
.Nm man
|
||||
searches for manual pages.
|
||||
The supplied
|
||||
.Ar path
|
||||
must be a colon (``:'') separated list of directories.
|
||||
This search path may also be set using the environment variable
|
||||
.Ev MANPATH .
|
||||
The subdirectories to be searched, and their search order,
|
||||
is specified by the ``_subdir'' line in the
|
||||
.Nm man
|
||||
configuration file.
|
||||
.It Fl m
|
||||
Augment the list of standard directories which
|
||||
.Nm man
|
||||
searches for manual pages.
|
||||
The supplied
|
||||
.Ar path
|
||||
must be a colon (``:'') separated list of directories.
|
||||
These directories will be searched before the standard directories or
|
||||
the directories specified using the
|
||||
.Fl M
|
||||
option or the
|
||||
.Ev MANPATH
|
||||
environment variable.
|
||||
The subdirectories to be searched, and their search order,
|
||||
is specified by the ``_subdir'' line in the
|
||||
.Nm man
|
||||
configuration file.
|
||||
.It Fl w
|
||||
List the pathnames of the manual pages which
|
||||
.Nm man
|
||||
would display for the specified
|
||||
.Ar section
|
||||
and
|
||||
.Ar name
|
||||
combination.
|
||||
.El
|
||||
.Pp
|
||||
The optional
|
||||
.Ar section
|
||||
argument restricts the directories that
|
||||
.Nm man
|
||||
will search.
|
||||
The
|
||||
.Nm man
|
||||
configuration file (see
|
||||
.Xr man.conf 5 )
|
||||
specifies the possible
|
||||
.Ar section
|
||||
values that are currently available.
|
||||
If only a single argument is specified or if the first argument is
|
||||
not a valid section,
|
||||
.Nm man
|
||||
assumes that the argument is the name of a manual page to be displayed.
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width MANPATHX
|
||||
.It Ev MACHINE
|
||||
As some manual pages are intended only for specific architectures,
|
||||
.Nm man
|
||||
searches any subdirectories,
|
||||
with the same name as the current architecture,
|
||||
in every directory which it searches.
|
||||
Machine specific areas are checked before general areas.
|
||||
The current machine type may be overridden by setting the environment
|
||||
variable
|
||||
.Ev MACHINE
|
||||
to the name of a specific architecture.
|
||||
.It Ev MANPATH
|
||||
The standard search path used by
|
||||
.Nm man
|
||||
may be overridden by specifying a path in the
|
||||
.Ev MANPATH
|
||||
environment
|
||||
variable.
|
||||
The format of the path is a colon (``:'') separated list of directories.
|
||||
The subdirectories to be searched as well as their search order
|
||||
is specified by the ``_subdir'' line in the
|
||||
.Nm man
|
||||
configuration file.
|
||||
.It Ev PAGER
|
||||
Any value of the environment variable
|
||||
.Ev PAGER
|
||||
will be used instead of the standard pagination program,
|
||||
.Xr more 1 .
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /etc/man.conf -compact
|
||||
.It Pa /etc/man.conf
|
||||
default man configuration file.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr apropos 1 ,
|
||||
.Xr whatis 1 ,
|
||||
.Xr whereis 1 ,
|
||||
.Xr man.conf 5
|
||||
.Sh BUGS
|
||||
The on-line manual pages are, by necessity, forgiving toward stupid
|
||||
display devices, causing a few manual pages to not as nicely formatted
|
||||
as their typeset counterparts.
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
command appeared in
|
||||
.At v6 .
|
712
usr.bin/man/man.c
Normal file
712
usr.bin/man/man.c
Normal file
@ -0,0 +1,712 @@
|
||||
/*
|
||||
* Copyright (c) 1987, 1993, 1994, 1995
|
||||
* 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) 1987, 1993, 1994, 1995\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)man.c 8.17 (Berkeley) 1/31/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fnmatch.h>
|
||||
#include <glob.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
int f_all, f_where;
|
||||
|
||||
static void build_page __P((char *, char **));
|
||||
static void cat __P((char *));
|
||||
static char *check_pager __P((char *));
|
||||
static int cleanup __P((void));
|
||||
static void how __P((char *));
|
||||
static void jump __P((char **, char *, char *));
|
||||
static int manual __P((char *, TAG *, glob_t *));
|
||||
static void onsig __P((int));
|
||||
static void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
TAG *defp, *defnewp, *section, *sectnewp, *subp;
|
||||
ENTRY *e_defp, *e_sectp, *e_subp, *ep;
|
||||
glob_t pg;
|
||||
size_t len;
|
||||
int ch, f_cat, f_how, found;
|
||||
char **ap, *cmd, *machine, *p, *p_add, *p_path, *pager, *slashp;
|
||||
char *conffile, buf[MAXPATHLEN * 2];
|
||||
|
||||
f_cat = f_how = 0;
|
||||
conffile = p_add = p_path = NULL;
|
||||
while ((ch = getopt(argc, argv, "-aC:cfhkM:m:P:w")) != EOF)
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
f_all = 1;
|
||||
break;
|
||||
case 'C':
|
||||
conffile = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
case '-': /* Deprecated. */
|
||||
f_cat = 1;
|
||||
break;
|
||||
case 'h':
|
||||
f_how = 1;
|
||||
break;
|
||||
case 'm':
|
||||
p_add = optarg;
|
||||
break;
|
||||
case 'M':
|
||||
case 'P': /* Backward compatibility. */
|
||||
p_path = optarg;
|
||||
break;
|
||||
/*
|
||||
* The -f and -k options are backward compatible,
|
||||
* undocumented ways of calling whatis(1) and apropos(1).
|
||||
*/
|
||||
case 'f':
|
||||
jump(argv, "-f", "whatis");
|
||||
/* NOTREACHED */
|
||||
case 'k':
|
||||
jump(argv, "-k", "apropos");
|
||||
/* NOTREACHED */
|
||||
case 'w':
|
||||
f_all = f_where = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (!*argv)
|
||||
usage();
|
||||
|
||||
if (!f_cat && !f_how && !f_where)
|
||||
if (!isatty(1))
|
||||
f_cat = 1;
|
||||
else if ((pager = getenv("PAGER")) != NULL)
|
||||
pager = check_pager(pager);
|
||||
else
|
||||
pager = _PATH_PAGER;
|
||||
|
||||
/* Read the configuration file. */
|
||||
config(conffile);
|
||||
|
||||
/* Get the machine type. */
|
||||
if ((machine = getenv("MACHINE")) == NULL)
|
||||
machine = MACHINE;
|
||||
|
||||
/* If there's no _default list, create an empty one. */
|
||||
if ((defp = getlist("_default")) == NULL)
|
||||
defp = addlist("_default");
|
||||
|
||||
/*
|
||||
* 1: If the user specified a MANPATH variable, or set the -M
|
||||
* option, we replace the _default list with the user's list,
|
||||
* appending the entries in the _subdir list and the machine.
|
||||
*/
|
||||
if (p_path == NULL)
|
||||
p_path = getenv("MANPATH");
|
||||
if (p_path != NULL) {
|
||||
while ((e_defp = defp->list.tqh_first) != NULL) {
|
||||
free(e_defp->s);
|
||||
TAILQ_REMOVE(&defp->list, e_defp, q);
|
||||
}
|
||||
for (p = strtok(p_path, ":");
|
||||
p != NULL; p = strtok(NULL, ":")) {
|
||||
slashp = p[strlen(p) - 1] == '/' ? "" : "/";
|
||||
e_subp = (subp = getlist("_subdir")) == NULL ?
|
||||
NULL : subp->list.tqh_first;
|
||||
for (; e_subp != NULL; e_subp = e_subp->q.tqe_next) {
|
||||
(void)snprintf(buf, sizeof(buf), "%s%s%s{/%s,}",
|
||||
p, slashp, e_subp->s, machine);
|
||||
if ((ep = malloc(sizeof(ENTRY))) == NULL ||
|
||||
(ep->s = strdup(buf)) == NULL)
|
||||
err(1, NULL);
|
||||
TAILQ_INSERT_TAIL(&defp->list, ep, q);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 2: If the user did not specify MANPATH, -M or a section, rewrite
|
||||
* the _default list to include the _subdir list and the machine.
|
||||
*/
|
||||
if (argv[1] == NULL)
|
||||
section = NULL;
|
||||
else if ((section = getlist(*argv)) != NULL)
|
||||
++argv;
|
||||
if (p_path == NULL && section == NULL) {
|
||||
defnewp = addlist("_default_new");
|
||||
e_defp =
|
||||
defp->list.tqh_first == NULL ? NULL : defp->list.tqh_first;
|
||||
for (; e_defp != NULL; e_defp = e_defp->q.tqe_next) {
|
||||
slashp =
|
||||
e_defp->s[strlen(e_defp->s) - 1] == '/' ? "" : "/";
|
||||
e_subp = (subp = getlist("_subdir")) == NULL ?
|
||||
NULL : subp->list.tqh_first;
|
||||
for (; e_subp != NULL; e_subp = e_subp->q.tqe_next) {
|
||||
(void)snprintf(buf, sizeof(buf), "%s%s%s{/%s,}",
|
||||
e_defp->s, slashp, e_subp->s, machine);
|
||||
if ((ep = malloc(sizeof(ENTRY))) == NULL ||
|
||||
(ep->s = strdup(buf)) == NULL)
|
||||
err(1, NULL);
|
||||
TAILQ_INSERT_TAIL(&defnewp->list, ep, q);
|
||||
}
|
||||
}
|
||||
defp = getlist("_default");
|
||||
while ((e_defp = defp->list.tqh_first) != NULL) {
|
||||
free(e_defp->s);
|
||||
TAILQ_REMOVE(&defp->list, e_defp, q);
|
||||
}
|
||||
free(defp->s);
|
||||
TAILQ_REMOVE(&head, defp, q);
|
||||
defnewp = getlist("_default_new");
|
||||
free(defnewp->s);
|
||||
defnewp->s = "_default";
|
||||
defp = defnewp;
|
||||
}
|
||||
|
||||
/*
|
||||
* 3: If the user set the -m option, insert the user's list before
|
||||
* whatever list we have, again appending the _subdir list and
|
||||
* the machine.
|
||||
*/
|
||||
if (p_add != NULL)
|
||||
for (p = strtok(p_add, ":"); p != NULL; p = strtok(NULL, ":")) {
|
||||
slashp = p[strlen(p) - 1] == '/' ? "" : "/";
|
||||
e_subp = (subp = getlist("_subdir")) == NULL ?
|
||||
NULL : subp->list.tqh_first;
|
||||
for (; e_subp != NULL; e_subp = e_subp->q.tqe_next) {
|
||||
(void)snprintf(buf, sizeof(buf), "%s%s%s{/%s,}",
|
||||
p, slashp, e_subp->s, machine);
|
||||
if ((ep = malloc(sizeof(ENTRY))) == NULL ||
|
||||
(ep->s = strdup(buf)) == NULL)
|
||||
err(1, NULL);
|
||||
TAILQ_INSERT_HEAD(&defp->list, ep, q);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 4: If none of MANPATH, -M, or -m were specified, and a section was,
|
||||
* rewrite the section's paths (if they have a trailing slash) to
|
||||
* append the _subdir list and the machine. This then becomes the
|
||||
* _default list.
|
||||
*/
|
||||
if (p_path == NULL && p_add == NULL && section != NULL) {
|
||||
sectnewp = addlist("_section_new");
|
||||
for (e_sectp = section->list.tqh_first;
|
||||
e_sectp != NULL; e_sectp = e_sectp->q.tqe_next) {
|
||||
if (e_sectp->s[strlen(e_sectp->s) - 1] != '/') {
|
||||
(void)snprintf(buf, sizeof(buf),
|
||||
"%s{/%s,}", e_sectp->s, machine);
|
||||
if ((ep = malloc(sizeof(ENTRY))) == NULL ||
|
||||
(ep->s = strdup(buf)) == NULL)
|
||||
err(1, NULL);
|
||||
TAILQ_INSERT_TAIL(§newp->list, ep, q);
|
||||
continue;
|
||||
}
|
||||
e_subp = (subp = getlist("_subdir")) == NULL ?
|
||||
NULL : subp->list.tqh_first;
|
||||
for (; e_subp != NULL; e_subp = e_subp->q.tqe_next) {
|
||||
(void)snprintf(buf, sizeof(buf), "%s%s{/%s,}",
|
||||
e_sectp->s, e_subp->s, machine);
|
||||
if ((ep = malloc(sizeof(ENTRY))) == NULL ||
|
||||
(ep->s = strdup(buf)) == NULL)
|
||||
err(1, NULL);
|
||||
TAILQ_INSERT_TAIL(§newp->list, ep, q);
|
||||
}
|
||||
}
|
||||
sectnewp->s = section->s;
|
||||
defp = sectnewp;
|
||||
TAILQ_REMOVE(&head, section, q);
|
||||
}
|
||||
|
||||
/*
|
||||
* 5: Search for the files. Set up an interrupt handler, so the
|
||||
* temporary files go away.
|
||||
*/
|
||||
(void)signal(SIGINT, onsig);
|
||||
(void)signal(SIGHUP, onsig);
|
||||
|
||||
memset(&pg, 0, sizeof(pg));
|
||||
for (found = 0; *argv; ++argv)
|
||||
if (manual(*argv, defp, &pg))
|
||||
found = 1;
|
||||
|
||||
/* 6: If nothing found, we're done. */
|
||||
if (!found) {
|
||||
(void)cleanup();
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* 7: If it's simple, display it fast. */
|
||||
if (f_cat) {
|
||||
for (ap = pg.gl_pathv; *ap != NULL; ++ap) {
|
||||
if (**ap == '\0')
|
||||
continue;
|
||||
cat(*ap);
|
||||
}
|
||||
exit (cleanup());
|
||||
}
|
||||
if (f_how) {
|
||||
for (ap = pg.gl_pathv; *ap != NULL; ++ap) {
|
||||
if (**ap == '\0')
|
||||
continue;
|
||||
how(*ap);
|
||||
}
|
||||
exit(cleanup());
|
||||
}
|
||||
if (f_where) {
|
||||
for (ap = pg.gl_pathv; *ap != NULL; ++ap) {
|
||||
if (**ap == '\0')
|
||||
continue;
|
||||
(void)printf("%s\n", *ap);
|
||||
}
|
||||
exit(cleanup());
|
||||
}
|
||||
|
||||
/*
|
||||
* 8: We display things in a single command; build a list of things
|
||||
* to display.
|
||||
*/
|
||||
for (ap = pg.gl_pathv, len = strlen(pager) + 1; *ap != NULL; ++ap) {
|
||||
if (**ap == '\0')
|
||||
continue;
|
||||
len += strlen(*ap) + 1;
|
||||
}
|
||||
if ((cmd = malloc(len)) == NULL) {
|
||||
warn(NULL);
|
||||
(void)cleanup();
|
||||
exit(1);
|
||||
}
|
||||
p = cmd;
|
||||
len = strlen(pager);
|
||||
memmove(p, pager, len);
|
||||
p += len;
|
||||
*p++ = ' ';
|
||||
for (ap = pg.gl_pathv; *ap != NULL; ++ap) {
|
||||
if (**ap == '\0')
|
||||
continue;
|
||||
len = strlen(*ap);
|
||||
memmove(p, *ap, len);
|
||||
p += len;
|
||||
*p++ = ' ';
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
/* Use system(3) in case someone's pager is "pager arg1 arg2". */
|
||||
(void)system(cmd);
|
||||
|
||||
exit(cleanup());
|
||||
}
|
||||
|
||||
/*
|
||||
* manual --
|
||||
* Search the manuals for the pages.
|
||||
*/
|
||||
static int
|
||||
manual(page, tag, pg)
|
||||
char *page;
|
||||
TAG *tag;
|
||||
glob_t *pg;
|
||||
{
|
||||
ENTRY *ep, *e_sufp, *e_tag;
|
||||
TAG *missp, *sufp;
|
||||
int anyfound, cnt, found;
|
||||
char *p, buf[128];
|
||||
|
||||
anyfound = 0;
|
||||
buf[0] = '*';
|
||||
|
||||
/* For each element in the list... */
|
||||
e_tag = tag == NULL ? NULL : tag->list.tqh_first;
|
||||
for (; e_tag != NULL; e_tag = e_tag->q.tqe_next) {
|
||||
(void)snprintf(buf, sizeof(buf), "%s/%s.*", e_tag->s, page);
|
||||
if (glob(buf,
|
||||
GLOB_APPEND | GLOB_BRACE | GLOB_NOSORT | GLOB_QUOTE,
|
||||
NULL, pg)) {
|
||||
warn("globbing");
|
||||
(void)cleanup();
|
||||
exit(1);
|
||||
}
|
||||
if (pg->gl_matchc == 0)
|
||||
continue;
|
||||
|
||||
/* Find out if it's really a man page. */
|
||||
for (cnt = pg->gl_pathc - pg->gl_matchc;
|
||||
cnt < pg->gl_pathc; ++cnt) {
|
||||
|
||||
/*
|
||||
* Try the _suffix key words first.
|
||||
*
|
||||
* XXX
|
||||
* Older versions of man.conf didn't have the suffix
|
||||
* key words, it was assumed that everything was a .0.
|
||||
* We just test for .0 first, it's fast and probably
|
||||
* going to hit.
|
||||
*/
|
||||
(void)snprintf(buf, sizeof(buf), "*/%s.0", page);
|
||||
if (!fnmatch(buf, pg->gl_pathv[cnt], 0))
|
||||
goto next;
|
||||
|
||||
e_sufp = (sufp = getlist("_suffix")) == NULL ?
|
||||
NULL : sufp->list.tqh_first;
|
||||
for (found = 0;
|
||||
e_sufp != NULL; e_sufp = e_sufp->q.tqe_next) {
|
||||
(void)snprintf(buf,
|
||||
sizeof(buf), "*/%s%s", page, e_sufp->s);
|
||||
if (!fnmatch(buf, pg->gl_pathv[cnt], 0)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
goto next;
|
||||
|
||||
/* Try the _build key words next. */
|
||||
e_sufp = (sufp = getlist("_build")) == NULL ?
|
||||
NULL : sufp->list.tqh_first;
|
||||
for (found = 0;
|
||||
e_sufp != NULL; e_sufp = e_sufp->q.tqe_next) {
|
||||
for (p = e_sufp->s;
|
||||
*p != '\0' && !isspace(*p); ++p);
|
||||
if (*p == '\0')
|
||||
continue;
|
||||
*p = '\0';
|
||||
(void)snprintf(buf,
|
||||
sizeof(buf), "*/%s%s", page, e_sufp->s);
|
||||
if (!fnmatch(buf, pg->gl_pathv[cnt], 0)) {
|
||||
if (!f_where)
|
||||
build_page(p + 1,
|
||||
&pg->gl_pathv[cnt]);
|
||||
*p = ' ';
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
*p = ' ';
|
||||
}
|
||||
if (found) {
|
||||
next: anyfound = 1;
|
||||
if (!f_all) {
|
||||
/* Delete any other matches. */
|
||||
while (++cnt< pg->gl_pathc)
|
||||
pg->gl_pathv[cnt] = "";
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* It's not a man page, forget about it. */
|
||||
pg->gl_pathv[cnt] = "";
|
||||
}
|
||||
|
||||
if (anyfound && !f_all)
|
||||
break;
|
||||
}
|
||||
|
||||
/* If not found, enter onto the missing list. */
|
||||
if (!anyfound) {
|
||||
if ((missp = getlist("_missing")) == NULL)
|
||||
missp = addlist("_missing");
|
||||
if ((ep = malloc(sizeof(ENTRY))) == NULL ||
|
||||
(ep->s = strdup(page)) == NULL) {
|
||||
warn(NULL);
|
||||
(void)cleanup();
|
||||
exit(1);
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&missp->list, ep, q);
|
||||
}
|
||||
return (anyfound);
|
||||
}
|
||||
|
||||
/*
|
||||
* build_page --
|
||||
* Build a man page for display.
|
||||
*/
|
||||
static void
|
||||
build_page(fmt, pathp)
|
||||
char *fmt, **pathp;
|
||||
{
|
||||
static int warned;
|
||||
ENTRY *ep;
|
||||
TAG *intmpp;
|
||||
int fd;
|
||||
char buf[MAXPATHLEN], cmd[MAXPATHLEN], tpath[sizeof(_PATH_TMP)];
|
||||
|
||||
/* Let the user know this may take awhile. */
|
||||
if (!warned) {
|
||||
warned = 1;
|
||||
warnx("Formatting manual page...");
|
||||
}
|
||||
|
||||
/* Add a remove-when-done list. */
|
||||
if ((intmpp = getlist("_intmp")) == NULL)
|
||||
intmpp = addlist("_intmp");
|
||||
|
||||
/* Move to the printf(3) format string. */
|
||||
for (; *fmt && isspace(*fmt); ++fmt);
|
||||
|
||||
/*
|
||||
* Get a temporary file and build a version of the file
|
||||
* to display. Replace the old file name with the new one.
|
||||
*/
|
||||
(void)strcpy(tpath, _PATH_TMP);
|
||||
if ((fd = mkstemp(tpath)) == -1) {
|
||||
warn("%s", tpath);
|
||||
(void)cleanup();
|
||||
exit(1);
|
||||
}
|
||||
(void)snprintf(buf, sizeof(buf), "%s > %s", fmt, tpath);
|
||||
(void)snprintf(cmd, sizeof(cmd), buf, *pathp);
|
||||
(void)system(cmd);
|
||||
(void)close(fd);
|
||||
if ((*pathp = strdup(tpath)) == NULL) {
|
||||
warn(NULL);
|
||||
(void)cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Link the built file into the remove-when-done list. */
|
||||
if ((ep = malloc(sizeof(ENTRY))) == NULL) {
|
||||
warn(NULL);
|
||||
(void)cleanup();
|
||||
exit(1);
|
||||
}
|
||||
ep->s = *pathp;
|
||||
TAILQ_INSERT_TAIL(&intmpp->list, ep, q);
|
||||
}
|
||||
|
||||
/*
|
||||
* how --
|
||||
* display how information
|
||||
*/
|
||||
static void
|
||||
how(fname)
|
||||
char *fname;
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
int lcnt, print;
|
||||
char *p, buf[256];
|
||||
|
||||
if (!(fp = fopen(fname, "r"))) {
|
||||
warn("%s", fname);
|
||||
(void)cleanup();
|
||||
exit (1);
|
||||
}
|
||||
#define S1 "SYNOPSIS"
|
||||
#define S2 "S\bSY\bYN\bNO\bOP\bPS\bSI\bIS\bS"
|
||||
#define D1 "DESCRIPTION"
|
||||
#define D2 "D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN"
|
||||
for (lcnt = print = 0; fgets(buf, sizeof(buf), fp);) {
|
||||
if (!strncmp(buf, S1, sizeof(S1) - 1) ||
|
||||
!strncmp(buf, S2, sizeof(S2) - 1)) {
|
||||
print = 1;
|
||||
continue;
|
||||
} else if (!strncmp(buf, D1, sizeof(D1) - 1) ||
|
||||
!strncmp(buf, D2, sizeof(D2) - 1))
|
||||
return;
|
||||
if (!print)
|
||||
continue;
|
||||
if (*buf == '\n')
|
||||
++lcnt;
|
||||
else {
|
||||
for(; lcnt; --lcnt)
|
||||
(void)putchar('\n');
|
||||
for (p = buf; isspace(*p); ++p);
|
||||
(void)fputs(p, stdout);
|
||||
}
|
||||
}
|
||||
(void)fclose(fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* cat --
|
||||
* cat out the file
|
||||
*/
|
||||
static void
|
||||
cat(fname)
|
||||
char *fname;
|
||||
{
|
||||
int fd, n;
|
||||
char buf[2048];
|
||||
|
||||
if ((fd = open(fname, O_RDONLY, 0)) < 0) {
|
||||
warn("%s", fname);
|
||||
(void)cleanup();
|
||||
exit(1);
|
||||
}
|
||||
while ((n = read(fd, buf, sizeof(buf))) > 0)
|
||||
if (write(STDOUT_FILENO, buf, n) != n) {
|
||||
warn("write");
|
||||
(void)cleanup();
|
||||
exit (1);
|
||||
}
|
||||
if (n == -1) {
|
||||
warn("read");
|
||||
(void)cleanup();
|
||||
exit(1);
|
||||
}
|
||||
(void)close(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* check_pager --
|
||||
* check the user supplied page information
|
||||
*/
|
||||
static char *
|
||||
check_pager(name)
|
||||
char *name;
|
||||
{
|
||||
char *p, *save;
|
||||
|
||||
/*
|
||||
* if the user uses "more", we make it "more -s"; watch out for
|
||||
* PAGER = "mypager /usr/ucb/more"
|
||||
*/
|
||||
for (p = name; *p && !isspace(*p); ++p);
|
||||
for (; p > name && *p != '/'; --p);
|
||||
if (p != name)
|
||||
++p;
|
||||
|
||||
/* make sure it's "more", not "morex" */
|
||||
if (!strncmp(p, "more", 4) && (!p[4] || isspace(p[4]))){
|
||||
save = name;
|
||||
/* allocate space to add the "-s" */
|
||||
if (!(name =
|
||||
malloc((u_int)(strlen(save) + sizeof("-s") + 1))))
|
||||
err(1, NULL);
|
||||
(void)sprintf(name, "%s %s", save, "-s");
|
||||
}
|
||||
return(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* jump --
|
||||
* strip out flag argument and jump
|
||||
*/
|
||||
static void
|
||||
jump(argv, flag, name)
|
||||
char **argv, *flag, *name;
|
||||
{
|
||||
char **arg;
|
||||
|
||||
argv[0] = name;
|
||||
for (arg = argv + 1; *arg; ++arg)
|
||||
if (!strcmp(*arg, flag))
|
||||
break;
|
||||
for (; *arg; ++arg)
|
||||
arg[0] = arg[1];
|
||||
execvp(name, argv);
|
||||
(void)fprintf(stderr, "%s: Command not found.\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* onsig --
|
||||
* If signaled, delete the temporary files.
|
||||
*/
|
||||
static void
|
||||
onsig(signo)
|
||||
int signo;
|
||||
{
|
||||
(void)cleanup();
|
||||
|
||||
(void)signal(signo, SIG_DFL);
|
||||
(void)kill(getpid(), signo);
|
||||
|
||||
/* NOTREACHED */
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* cleanup --
|
||||
* Clean up temporary files, show any error messages.
|
||||
*/
|
||||
static int
|
||||
cleanup()
|
||||
{
|
||||
TAG *intmpp, *missp;
|
||||
ENTRY *ep;
|
||||
int rval;
|
||||
|
||||
rval = 0;
|
||||
ep = (missp = getlist("_missing")) == NULL ?
|
||||
NULL : missp->list.tqh_first;
|
||||
if (ep != NULL)
|
||||
for (; ep != NULL; ep = ep->q.tqe_next) {
|
||||
warnx("no entry for %s in the manual.", ep->s);
|
||||
rval = 1;
|
||||
}
|
||||
|
||||
ep = (intmpp = getlist("_intmp")) == NULL ?
|
||||
NULL : intmpp->list.tqh_first;
|
||||
for (; ep != NULL; ep = ep->q.tqe_next)
|
||||
(void)unlink(ep->s);
|
||||
return (rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* usage --
|
||||
* print usage message and die
|
||||
*/
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: man [-achw] [-C file] [-M path] [-m path] [section] title ...\n");
|
||||
exit(1);
|
||||
}
|
46
usr.bin/man/man.conf
Normal file
46
usr.bin/man/man.conf
Normal file
@ -0,0 +1,46 @@
|
||||
# Sheer, raging paranoia...
|
||||
_version BSD.2
|
||||
|
||||
# The whatis/apropos database.
|
||||
_whatdb /usr/share/man/whatis.db
|
||||
|
||||
# Subdirectories for paths ending in '/', IN SEARCH ORDER.
|
||||
_subdir cat{1,8,6,2,3,4,5,7,3f}
|
||||
|
||||
# Files typed by suffix and their commands.
|
||||
# Note the order, .Z must come after .[1-9].Z, or it will match first.
|
||||
_suffix .0
|
||||
_build .[1-9] /usr/bin/nroff -man %s
|
||||
_build .[1-9].Z /usr/bin/zcat %s | /usr/bin/nroff -man
|
||||
_build .Z /usr/bin/zcat %s
|
||||
_build .0.Z /usr/bin/zcat %s
|
||||
_build .gz /usr/contrib/bin/gunzip %s
|
||||
_build .z /usr/contrib/bin/gunzip %s
|
||||
_build .nr /usr/bin/nroff -man %s
|
||||
|
||||
# Sections and their directories.
|
||||
# All paths ending in '/' are the equivalent of entries specifying that
|
||||
# directory with all of the subdirectories listed for the keyword _subdir.
|
||||
|
||||
# default
|
||||
_default /usr/{share,X11,contrib,local}/{man,man/old}/
|
||||
|
||||
# Other sections that represent complete man subdirectories.
|
||||
X11 /usr/X11R4/man/
|
||||
X11R4 /usr/X11R4/man/
|
||||
contrib /usr/contrib/man/
|
||||
local /usr/local/man/
|
||||
new /usr/contrib/man/
|
||||
old /usr/share/man/old/
|
||||
|
||||
# Specific section/directory combinations.
|
||||
1 /usr/{share,X11R4,contrib,local}/{man/,man/old/}cat1
|
||||
2 /usr/{share,X11R4,contrib,local}/{man/,man/old/}cat2
|
||||
3 /usr/{share,X11R4,contrib,local}/{man/,man/old/}cat3
|
||||
3F /usr/share/man/cat3f
|
||||
3f /usr/share/man/cat3f
|
||||
4 /usr/{share,X11R4,contrib,local}/{man/,man/old/}cat4
|
||||
5 /usr/{share,X11R4,contrib,local}/{man/,man/old/}cat5
|
||||
6 /usr/{share,X11R4,contrib,local}/{man/,man/old/}cat6
|
||||
7 /usr/{share,X11R4,contrib,local}/{man/,man/old/}cat7
|
||||
8 /usr/{share,X11R4,contrib,local}/{man/,man/old/}cat8
|
195
usr.bin/man/man.conf.5
Normal file
195
usr.bin/man/man.conf.5
Normal file
@ -0,0 +1,195 @@
|
||||
.\" Copyright (c) 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.
|
||||
.\"
|
||||
.\" @(#)man.conf.5 8.5 (Berkeley) 1/2/94
|
||||
.\"
|
||||
.Dd January 2, 1994
|
||||
.Dt MAN.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm man.conf
|
||||
.Nd configuration file for
|
||||
.Xr man 1
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Xr man 1 ,
|
||||
.Xr apropos 1 ,
|
||||
and
|
||||
.Xr whatis 1
|
||||
commands
|
||||
search for manual pages or their database files as specified by the
|
||||
.Nm man.conf
|
||||
file.
|
||||
Manual pages are normally expected to be preformatted (see
|
||||
.Xr nroff 1 )
|
||||
and named with a trailing ``.0''.
|
||||
.Pp
|
||||
The
|
||||
.Nm man.conf
|
||||
file contains two types of lines.
|
||||
.Pp
|
||||
The first type of line is a ``section'' line, which contains a
|
||||
section name followed by one or more directory paths.
|
||||
The directory paths may contain the normal shell globbing characters,
|
||||
including curly braces (``{}''); to escape a shell globbing character,
|
||||
precede it with a backslash (``\e'').
|
||||
Lines in this format specify that manual pages for the section
|
||||
may be found in the following directories.
|
||||
.Pp
|
||||
Directories named with a trailing slash character (``/'') are expected
|
||||
to contain subdirectories of manual pages, (see the keyword ``_subdir''
|
||||
below) instead of manual pages.
|
||||
These subdirectories are searched instead of the directory.
|
||||
.Pp
|
||||
Before searching any directory for a manual page, the
|
||||
.Xr man 1
|
||||
command always searches the subdirectory with the same name
|
||||
as the current machine type, if it exists.
|
||||
No specification of these subdirectories is necessary in the
|
||||
.Nm man.conf
|
||||
file.
|
||||
.Pp
|
||||
Section names are unrestricted except for the reserved words specified
|
||||
below; in general, you should avoid anything with a leading underscore
|
||||
(``_'') to avoid future incompatibilities.
|
||||
.Pp
|
||||
The section named ``_default'' is the list of directories that will
|
||||
be searched if no section is specified by the user.
|
||||
.Pp
|
||||
The second type of line is preceded with a ``keyword''.
|
||||
The possible keywords and their meanings are as follows:
|
||||
.Pp
|
||||
.Bl -tag -width "_version"
|
||||
.It _build
|
||||
Man file names, regardless of their format, are expected to end in
|
||||
a ``.*'' pattern, i.e. a ``.'' followed by some suffix.
|
||||
The first field of a _build line lists a suffix which indicates
|
||||
files which need to be reformated or manipulated in some way before
|
||||
being displayed to the user.
|
||||
The suffix may contain the normal shell globbing characters (NOT
|
||||
including curly braces (``{}'')).
|
||||
The rest of the line must be a shell command line, the standard
|
||||
output of which is the manual page in a format which may be directly
|
||||
displayed to the user.
|
||||
Any occurrences of the string ``%s'' in the shell command line will
|
||||
be replaced by the name of the file which is being reformatted.
|
||||
.It _subdir
|
||||
The list (in search order) of subdirectories which will be searched in
|
||||
any directory named with a trailing slash (``/'') character.
|
||||
This list is also used when a path is specified to the
|
||||
.Xr man 1
|
||||
utility by the user, using the
|
||||
.Ev MANPATH
|
||||
environment variable or the
|
||||
.Fl M
|
||||
and
|
||||
.Fl m
|
||||
options.
|
||||
.It _suffix
|
||||
Man file names, regardless of their format are expected to end in
|
||||
a ``.*'' pattern, i.e. a ``.'' followed by some suffix.
|
||||
Each field of a _suffix line is a suffix which indicates
|
||||
files which do not need to be reformatted or manipulated
|
||||
in any way, but which may be directly displayed to the user.
|
||||
Each suffix may contain the normal shell globbing characters (NOT
|
||||
including curly braces (``{}'')).
|
||||
.It _version
|
||||
The version of the configuration file.
|
||||
.It _whatdb
|
||||
The full pathname (not just a directory path) for a database to be used
|
||||
by the
|
||||
.Xr apropos 1
|
||||
and
|
||||
.Xr whatis 1
|
||||
commands.
|
||||
.El
|
||||
.Pp
|
||||
Multiple specifications for all types of lines are cumulative and the
|
||||
entries are used in the order listed in the file; multiple entries may
|
||||
be listed per line, as well.
|
||||
.Pp
|
||||
Empty lines or lines whose first non-whitespace character is a hash
|
||||
mark (``#'') are ignored.
|
||||
.Sh EXAMPLES
|
||||
Given the following
|
||||
.Nm man.conf
|
||||
file:
|
||||
.Bd -literal -offset indent
|
||||
_version BSD.2
|
||||
_subdir cat[123]
|
||||
_suffix .0
|
||||
_build .[1-9] nroff -man %s
|
||||
_build .tbl tbl %s | nroff -man
|
||||
_default /usr/share/man/
|
||||
sect3 /usr/share/man/{old/,}cat3
|
||||
.Ed
|
||||
.Pp
|
||||
By default, the command
|
||||
.Dq Li man mktemp
|
||||
will search for
|
||||
``mktemp.<any_digit>'' and ``mktemp.tbl''
|
||||
in the directories
|
||||
.Dq Pa /usr/share/man/cat1 ,
|
||||
.Dq Pa /usr/share/man/cat2 ,
|
||||
and
|
||||
.Dq Pa /usr/share/man/cat3 .
|
||||
If on a machine of type ``vax'', the subdirectory ``vax'' in each
|
||||
directory would be searched as well, before the directory was
|
||||
searched.
|
||||
.Pp
|
||||
If ``mktemp.tbl'' was found first, the command
|
||||
.Dq Li tbl <manual page> | nroff -man
|
||||
would be run to build a man page for display to the user.
|
||||
.Pp
|
||||
The command
|
||||
.Dq Li man sect3 mktemp
|
||||
would search the directories
|
||||
.Dq Pa /usr/share/man/old/cat3
|
||||
and
|
||||
.Dq Pa /usr/share/man/cat3 ,
|
||||
in that order, for
|
||||
the mktemp manual page.
|
||||
If a subdirectory with the same name as the current machine type
|
||||
existed in any of them, it would be searched as well, before each
|
||||
of them were searched.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /etc/man.conf -compact
|
||||
.It Pa /etc/man.conf
|
||||
Standard manual directory search path.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr apropos 1 ,
|
||||
.Xr machine 1 ,
|
||||
.Xr man 1 ,
|
||||
.Xr whatis 1 ,
|
||||
.Xr whereis 1 ,
|
||||
.Xr fnmatch 3 ,
|
||||
.Xr glob 3
|
39
usr.bin/man/pathnames.h
Normal file
39
usr.bin/man/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.3 (Berkeley) 1/2/94
|
||||
*/
|
||||
|
||||
#define _PATH_MANCONF "/etc/man.conf"
|
||||
#define _PATH_PAGER "/usr/bin/more -s"
|
||||
#define _PATH_TMP "/tmp/man.XXXXXX"
|
||||
#define _PATH_WHATIS "whatis.db"
|
158
usr.bin/mklocale/Japanese
Normal file
158
usr.bin/mklocale/Japanese
Normal file
@ -0,0 +1,158 @@
|
||||
# @(#)Japanese 8.1 (Berkeley) 6/6/93
|
||||
|
||||
/*
|
||||
* Japanese LOCALE_CTYPE definitions using EUC of JIS character sets
|
||||
*/
|
||||
|
||||
ENCODING "EUC"
|
||||
|
||||
/* JIS JIS JIS */
|
||||
/* X201 X208 X201 */
|
||||
/* 00-7f 84-fe */
|
||||
|
||||
VARIABLE 1 0x0000 2 0x8080 2 0x0080 3 0x8000 0x8080
|
||||
|
||||
/*
|
||||
* Code Set 1
|
||||
*/
|
||||
ALPHA 'A' - 'Z' 'a' - 'z'
|
||||
CONTROL 0x00 - 0x1f 0x7f
|
||||
DIGIT '0' - '9'
|
||||
GRAPH 0x21 - 0x7e
|
||||
LOWER 'a' - 'z'
|
||||
PUNCT 0x21 - 0x2f 0x3a - 0x40 0x5b - 0x60 0x7b - 0x7e
|
||||
SPACE 0x09 - 0x0d 0x20
|
||||
UPPER 'A' - 'Z'
|
||||
XDIGIT 'a' - 'f' 'A' - 'F'
|
||||
BLANK ' ' '\t'
|
||||
PRINT 0x20 - 0x7e
|
||||
|
||||
MAPLOWER < 'A' - 'Z' : 'a' >
|
||||
MAPLOWER < 'a' - 'z' : 'a' >
|
||||
MAPUPPER < 'A' - 'Z' : 'A' >
|
||||
MAPUPPER < 'a' - 'z' : 'A' >
|
||||
TODIGIT < '0' - '9' : 0 >
|
||||
TODIGIT < 'A' - 'F' : 10 >
|
||||
TODIGIT < 'a' - 'f' : 10 >
|
||||
|
||||
/*
|
||||
* Code Set 2
|
||||
*/
|
||||
|
||||
SPACE 0xa1a1
|
||||
PHONOGRAM 0xa1bc
|
||||
SPECIAL 0xa1a2 - 0xa1fe
|
||||
PUNCT 0xa1a2 - 0xa1f8 /* A few too many in here... */
|
||||
|
||||
SPECIAL 0xa2a1 - 0xa2ae 0xa2ba - 0xa2c1 0xa2ca - 0xa2d0 0xa2dc - 0xa2ea
|
||||
SPECIAL 0xa2f2 - 0xa2f9 0xa2fe
|
||||
|
||||
DIGIT 0xa3b0 - 0xa3b9
|
||||
UPPER 0xa3c1 - 0xa3da /* Romaji */
|
||||
LOWER 0xa3e1 - 0xa3fa /* Romaji */
|
||||
MAPLOWER < 0xa3c1 - 0xa3da : 0xa3e1 > /* English */
|
||||
MAPLOWER < 0xa3e1 - 0xa3fa : 0xa3e1 > /* English */
|
||||
MAPUPPER < 0xa3c1 - 0xa3da : 0xa3c1 >
|
||||
MAPUPPER < 0xa3e1 - 0xa3fa : 0xa3c1 >
|
||||
|
||||
XDIGIT 0xa3c1 - 0xa3c6 0xa3e1 - 0xa3e6
|
||||
|
||||
TODIGIT < 0xa3b0 - 0xa3b9 : 0 >
|
||||
TODIGIT < 0xa3c1 - 0xa3c6 : 10 >
|
||||
TODIGIT < 0xa3e1 - 0xa3e6 : 10 >
|
||||
|
||||
PHONOGRAM 0xa4a1 - 0xa4f3
|
||||
PHONOGRAM 0xa5a1 - 0xa5f6
|
||||
|
||||
UPPER 0xa6a1 - 0xa6b8 /* Greek */
|
||||
LOWER 0xa6c1 - 0xa6d8 /* Greek */
|
||||
MAPLOWER < 0xa6a1 - 0xa6b8 : 0xa6c1 >
|
||||
MAPLOWER < 0xa6c1 - 0xa6d8 : 0xa6c1 >
|
||||
MAPUPPER < 0xa6a1 - 0xa6b8 : 0xa6a1 >
|
||||
MAPUPPER < 0xa6c1 - 0xa6d8 : 0xa6a1 >
|
||||
|
||||
UPPER 0xa7a1 - 0xa7c1 /* Cyrillic */
|
||||
LOWER 0xa7d1 - 0xa7f1 /* Cyrillic */
|
||||
MAPLOWER < 0xa7a1 - 0xa7c1 : 0xa7d1 >
|
||||
MAPLOWER < 0xa7d1 - 0xa7f1 : 0xa7d1 >
|
||||
MAPUPPER < 0xa7a1 - 0xa7c1 : 0xa7a1 >
|
||||
MAPUPPER < 0xa7d1 - 0xa7f1 : 0xa7a1 >
|
||||
|
||||
SPECIAL 0xa8a1 - 0xa8c0
|
||||
|
||||
IDEOGRAM 0xb0a1 - 0xb0fe
|
||||
IDEOGRAM 0xb1a1 - 0xb1fe
|
||||
IDEOGRAM 0xb2a1 - 0xb2fe
|
||||
IDEOGRAM 0xb3a1 - 0xb3fe
|
||||
IDEOGRAM 0xb4a1 - 0xb4fe
|
||||
IDEOGRAM 0xb5a1 - 0xb5fe
|
||||
IDEOGRAM 0xb6a1 - 0xb6fe
|
||||
IDEOGRAM 0xb7a1 - 0xb7fe
|
||||
IDEOGRAM 0xb8a1 - 0xb8fe
|
||||
IDEOGRAM 0xb9a1 - 0xb9fe
|
||||
IDEOGRAM 0xbaa1 - 0xbafe
|
||||
IDEOGRAM 0xbba1 - 0xbbfe
|
||||
IDEOGRAM 0xbca1 - 0xbcfe
|
||||
IDEOGRAM 0xbda1 - 0xbdfe
|
||||
IDEOGRAM 0xbea1 - 0xbefe
|
||||
IDEOGRAM 0xbfa1 - 0xbffe
|
||||
IDEOGRAM 0xc0a1 - 0xc0fe
|
||||
IDEOGRAM 0xc1a1 - 0xc1fe
|
||||
IDEOGRAM 0xc2a1 - 0xc2fe
|
||||
IDEOGRAM 0xc3a1 - 0xc3fe
|
||||
IDEOGRAM 0xc4a1 - 0xc4fe
|
||||
IDEOGRAM 0xc5a1 - 0xc5fe
|
||||
IDEOGRAM 0xc6a1 - 0xc6fe
|
||||
IDEOGRAM 0xc7a1 - 0xc7fe
|
||||
IDEOGRAM 0xc8a1 - 0xc8fe
|
||||
IDEOGRAM 0xc9a1 - 0xc9fe
|
||||
IDEOGRAM 0xcaa1 - 0xcafe
|
||||
IDEOGRAM 0xcba1 - 0xcbfe
|
||||
IDEOGRAM 0xcca1 - 0xccfe
|
||||
IDEOGRAM 0xcda1 - 0xcdfe
|
||||
IDEOGRAM 0xcea1 - 0xcefe
|
||||
IDEOGRAM 0xcfa1 - 0xcfd3
|
||||
IDEOGRAM 0xd0a1 - 0xd0fe
|
||||
IDEOGRAM 0xd1a1 - 0xd1fe
|
||||
IDEOGRAM 0xd2a1 - 0xd2fe
|
||||
IDEOGRAM 0xd3a1 - 0xd3fe
|
||||
IDEOGRAM 0xd4a1 - 0xd4fe
|
||||
IDEOGRAM 0xd5a1 - 0xd5fe
|
||||
IDEOGRAM 0xd6a1 - 0xd6fe
|
||||
IDEOGRAM 0xd7a1 - 0xd7fe
|
||||
IDEOGRAM 0xd8a1 - 0xd8fe
|
||||
IDEOGRAM 0xd9a1 - 0xd9fe
|
||||
IDEOGRAM 0xdaa1 - 0xdafe
|
||||
IDEOGRAM 0xdba1 - 0xdbfe
|
||||
IDEOGRAM 0xdca1 - 0xdcfe
|
||||
IDEOGRAM 0xdda1 - 0xddfe
|
||||
IDEOGRAM 0xdea1 - 0xdefe
|
||||
IDEOGRAM 0xdfa1 - 0xdffe
|
||||
IDEOGRAM 0xe0a1 - 0xe0fe
|
||||
IDEOGRAM 0xe1a1 - 0xe1fe
|
||||
IDEOGRAM 0xe2a1 - 0xe2fe
|
||||
IDEOGRAM 0xe3a1 - 0xe3fe
|
||||
IDEOGRAM 0xe4a1 - 0xe4fe
|
||||
IDEOGRAM 0xe5a1 - 0xe5fe
|
||||
IDEOGRAM 0xe6a1 - 0xe6fe
|
||||
IDEOGRAM 0xe7a1 - 0xe7fe
|
||||
IDEOGRAM 0xe8a1 - 0xe8fe
|
||||
IDEOGRAM 0xe9a1 - 0xe9fe
|
||||
IDEOGRAM 0xeaa1 - 0xeafe
|
||||
IDEOGRAM 0xeba1 - 0xebfe
|
||||
IDEOGRAM 0xeca1 - 0xecfe
|
||||
IDEOGRAM 0xeda1 - 0xedfe
|
||||
IDEOGRAM 0xeea1 - 0xeefe
|
||||
IDEOGRAM 0xefa1 - 0xeffe
|
||||
IDEOGRAM 0xf0a1 - 0xf0fe
|
||||
IDEOGRAM 0xf1a1 - 0xf1fe
|
||||
IDEOGRAM 0xf2a1 - 0xf2fe
|
||||
IDEOGRAM 0xf3a1 - 0xf3fe
|
||||
IDEOGRAM 0xf4a1 - 0xf4a4
|
||||
|
||||
/*
|
||||
* This is for Code Set 3, half-width kana
|
||||
*/
|
||||
SPECIAL 0xa1 - 0xdf
|
||||
PHONOGRAM 0xa1 - 0xdf
|
||||
CONTROL 0x84 - 0x97 0x9b - 0x9f 0xe0 - 0xfe
|
54
usr.bin/passwd/kpasswd_proto.h
Normal file
54
usr.bin/passwd/kpasswd_proto.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*-
|
||||
* 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.
|
||||
*
|
||||
* @(#)kpasswd_proto.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* kpasswd_proto
|
||||
*
|
||||
* definitions for the kpasswd "protocol"
|
||||
* (We hope this to be temporary until a real admin protocol is worked out.)
|
||||
*/
|
||||
|
||||
struct kpasswd_data {
|
||||
des_cblock random_key;
|
||||
char secure_msg[_PASSWORD_LEN];
|
||||
};
|
||||
|
||||
struct update_data {
|
||||
char pw[_PASSWORD_LEN];
|
||||
char secure_msg[_PASSWORD_LEN];
|
||||
};
|
||||
#define SERVICE "kpasswd"
|
||||
#define SECURE_STRING \
|
||||
"Kerberos password update program -- 12/9/88 UC Berkeley"
|
319
usr.bin/passwd/krb_passwd.c
Normal file
319
usr.bin/passwd/krb_passwd.c
Normal file
@ -0,0 +1,319 @@
|
||||
/*-
|
||||
* 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 sccsid[] = "@(#)krb_passwd.c 8.3 (Berkeley) 4/2/94";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifdef KERBEROS
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <netinet/in.h>
|
||||
#include <kerberosIV/des.h>
|
||||
#include <kerberosIV/krb.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "kpasswd_proto.h"
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
#define PROTO "tcp"
|
||||
|
||||
static void send_update __P((int, char *, char *));
|
||||
static void recv_ack __P((int));
|
||||
static void cleanup __P((void));
|
||||
static void finish __P((void));
|
||||
|
||||
static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0 };
|
||||
static struct kpasswd_data proto_data;
|
||||
static des_cblock okey;
|
||||
static Key_schedule osched;
|
||||
static KTEXT_ST ticket;
|
||||
static Key_schedule random_schedule;
|
||||
static long authopts;
|
||||
static char realm[REALM_SZ], krbhst[MAX_HSTNM];
|
||||
static int sock;
|
||||
|
||||
int
|
||||
krb_passwd()
|
||||
{
|
||||
struct servent *se;
|
||||
struct hostent *host;
|
||||
struct sockaddr_in sin;
|
||||
CREDENTIALS cred;
|
||||
fd_set readfds;
|
||||
int rval;
|
||||
char pass[_PASSWORD_LEN], password[_PASSWORD_LEN];
|
||||
static void finish();
|
||||
|
||||
static struct rlimit rl = { 0, 0 };
|
||||
|
||||
(void)signal(SIGHUP, SIG_IGN);
|
||||
(void)signal(SIGINT, SIG_IGN);
|
||||
(void)signal(SIGTSTP, SIG_IGN);
|
||||
|
||||
if (setrlimit(RLIMIT_CORE, &rl) < 0) {
|
||||
warn("setrlimit");
|
||||
return (1);
|
||||
}
|
||||
|
||||
if ((se = getservbyname(SERVICE, PROTO)) == NULL) {
|
||||
warnx("couldn't find entry for service %s/%s",
|
||||
SERVICE, PROTO);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if ((rval = krb_get_lrealm(realm,1)) != KSUCCESS) {
|
||||
warnx("couldn't get local Kerberos realm: %s",
|
||||
krb_err_txt[rval]);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if ((rval = krb_get_krbhst(krbhst, realm, 1)) != KSUCCESS) {
|
||||
warnx("couldn't get Kerberos host: %s",
|
||||
krb_err_txt[rval]);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if ((host = gethostbyname(krbhst)) == NULL) {
|
||||
warnx("couldn't get host entry for krb host %s",
|
||||
krbhst);
|
||||
return (1);
|
||||
}
|
||||
|
||||
sin.sin_family = host->h_addrtype;
|
||||
memmove((char *) &sin.sin_addr, host->h_addr, host->h_length);
|
||||
sin.sin_port = se->s_port;
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
|
||||
warn("socket");
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
|
||||
warn("connect");
|
||||
(void)close(sock);
|
||||
return (1);
|
||||
}
|
||||
|
||||
rval = krb_sendauth(
|
||||
authopts, /* NOT mutual */
|
||||
sock,
|
||||
&ticket, /* (filled in) */
|
||||
SERVICE,
|
||||
krbhst, /* instance (krbhst) */
|
||||
realm, /* dest realm */
|
||||
(u_long) getpid(), /* checksum */
|
||||
NULL, /* msg data */
|
||||
NULL, /* credentials */
|
||||
NULL, /* schedule */
|
||||
NULL, /* local addr */
|
||||
NULL, /* foreign addr */
|
||||
"KPWDV0.1"
|
||||
);
|
||||
|
||||
if (rval != KSUCCESS) {
|
||||
warnx("Kerberos sendauth error: %s", krb_err_txt[rval]);
|
||||
return (1);
|
||||
}
|
||||
|
||||
krb_get_cred("krbtgt", realm, realm, &cred);
|
||||
|
||||
(void)printf("Changing Kerberos password for %s.%s@%s.\n",
|
||||
cred.pname, cred.pinst, realm);
|
||||
|
||||
if (des_read_pw_string(pass,
|
||||
sizeof(pass)-1, "Old Kerberos password:", 0)) {
|
||||
warnx("error reading old Kerberos password");
|
||||
return (1);
|
||||
}
|
||||
|
||||
(void)des_string_to_key(pass, okey);
|
||||
(void)des_key_sched(okey, osched);
|
||||
(void)des_set_key(okey, osched);
|
||||
|
||||
/* wait on the verification string */
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(sock, &readfds);
|
||||
|
||||
rval =
|
||||
select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout);
|
||||
|
||||
if ((rval < 1) || !FD_ISSET(sock, &readfds)) {
|
||||
if(rval == 0) {
|
||||
warnx("timed out (aborted)");
|
||||
cleanup();
|
||||
return (1);
|
||||
}
|
||||
warnx("select failed (aborted)");
|
||||
cleanup();
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* read verification string */
|
||||
|
||||
if (des_read(sock, &proto_data, sizeof(proto_data)) !=
|
||||
sizeof(proto_data)) {
|
||||
warnx("couldn't read verification string (aborted)");
|
||||
cleanup();
|
||||
return (1);
|
||||
}
|
||||
|
||||
(void)signal(SIGHUP, finish);
|
||||
(void)signal(SIGINT, finish);
|
||||
|
||||
if (strcmp(SECURE_STRING, proto_data.secure_msg) != 0) {
|
||||
cleanup();
|
||||
/* don't complain loud if user just hit return */
|
||||
if (pass == NULL || (!*pass))
|
||||
return (0);
|
||||
(void)fprintf(stderr, "Sorry\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
(void)des_key_sched(proto_data.random_key, random_schedule);
|
||||
(void)des_set_key(proto_data.random_key, random_schedule);
|
||||
(void)memset(pass, 0, sizeof(pass));
|
||||
|
||||
if (des_read_pw_string(pass,
|
||||
sizeof(pass)-1, "New Kerberos password:", 0)) {
|
||||
warnx("error reading new Kerberos password (aborted)");
|
||||
cleanup();
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (des_read_pw_string(password,
|
||||
sizeof(password)-1, "Retype new Kerberos password:", 0)) {
|
||||
warnx("error reading new Kerberos password (aborted)");
|
||||
cleanup();
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (strcmp(password, pass) != 0) {
|
||||
warnx("password mismatch (aborted)");
|
||||
cleanup();
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (strlen(pass) == 0)
|
||||
(void)printf("using NULL password\n");
|
||||
|
||||
send_update(sock, password, SECURE_STRING);
|
||||
|
||||
/* wait for ACK */
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(sock, &readfds);
|
||||
|
||||
rval =
|
||||
select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout);
|
||||
if ((rval < 1) || !FD_ISSET(sock, &readfds)) {
|
||||
if(rval == 0) {
|
||||
warnx("timed out reading ACK (aborted)");
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
warnx("select failed (aborted)");
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
recv_ack(sock);
|
||||
cleanup();
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
send_update(dest, pwd, str)
|
||||
int dest;
|
||||
char *pwd, *str;
|
||||
{
|
||||
static struct update_data ud;
|
||||
|
||||
(void)strncpy(ud.secure_msg, str, _PASSWORD_LEN);
|
||||
(void)strncpy(ud.pw, pwd, sizeof(ud.pw));
|
||||
if (des_write(dest, &ud, sizeof(ud)) != sizeof(ud)) {
|
||||
warnx("couldn't write pw update (abort)");
|
||||
memset((char *)&ud, 0, sizeof(ud));
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
recv_ack(remote)
|
||||
int remote;
|
||||
{
|
||||
int cc;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
cc = des_read(remote, buf, sizeof(buf));
|
||||
if (cc <= 0) {
|
||||
warnx("error reading acknowledgement (aborted)");
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
(void)printf("%s", buf);
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup()
|
||||
{
|
||||
|
||||
(void)memset((char *)&proto_data, 0, sizeof(proto_data));
|
||||
(void)memset((char *)okey, 0, sizeof(okey));
|
||||
(void)memset((char *)osched, 0, sizeof(osched));
|
||||
(void)memset((char *)random_schedule, 0, sizeof(random_schedule));
|
||||
}
|
||||
|
||||
static void
|
||||
finish()
|
||||
{
|
||||
|
||||
(void)close(sock);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#endif /* KERBEROS */
|
15
usr.bin/patch/EXTERN.h
Normal file
15
usr.bin/patch/EXTERN.h
Normal file
@ -0,0 +1,15 @@
|
||||
/* $Header: EXTERN.h,v 2.0 86/09/17 15:35:37 lwall Exp $
|
||||
*
|
||||
* $Log: EXTERN.h,v $
|
||||
* Revision 2.0 86/09/17 15:35:37 lwall
|
||||
* Baseline for netwide release.
|
||||
*
|
||||
*/
|
||||
|
||||
#undef EXT
|
||||
#define EXT extern
|
||||
|
||||
#undef INIT
|
||||
#define INIT(x)
|
||||
|
||||
#undef DOINIT
|
15
usr.bin/patch/INTERN.h
Normal file
15
usr.bin/patch/INTERN.h
Normal file
@ -0,0 +1,15 @@
|
||||
/* $Header: INTERN.h,v 2.0 86/09/17 15:35:58 lwall Exp $
|
||||
*
|
||||
* $Log: INTERN.h,v $
|
||||
* Revision 2.0 86/09/17 15:35:58 lwall
|
||||
* Baseline for netwide release.
|
||||
*
|
||||
*/
|
||||
|
||||
#undef EXT
|
||||
#define EXT
|
||||
|
||||
#undef INIT
|
||||
#define INIT(x) = x
|
||||
|
||||
#define DOINIT
|
6
usr.bin/patch/Makefile
Normal file
6
usr.bin/patch/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= patch
|
||||
SRCS= patch.c pch.c inp.c version.c util.c
|
||||
|
||||
.include <bsd.prog.mk>
|
79
usr.bin/patch/README
Normal file
79
usr.bin/patch/README
Normal file
@ -0,0 +1,79 @@
|
||||
|
||||
The Makefile and config.h files in this directory work with the current
|
||||
BSD release. Don't run the Configure script, you'll get wrong results.
|
||||
|
||||
Keith Bostic 1/10/88
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
Patch Kit, Version 2.0
|
||||
|
||||
Copyright (c) 1986, Larry Wall
|
||||
|
||||
You may copy the patch kit in whole or in part as long as you don't try to
|
||||
make money off it, or pretend that you wrote it.
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
Please read all the directions below before you proceed any further, and
|
||||
then follow them carefully. Failure to do so may void your warranty. :-)
|
||||
|
||||
After you have unpacked your kit, you should have all the files listed
|
||||
in MANIFEST.
|
||||
|
||||
Installation
|
||||
|
||||
1) Run Configure. This will figure out various things about your system.
|
||||
Some things Configure will figure out for itself, other things it will
|
||||
ask you about. It will then proceed to make config.h, config.sh, and
|
||||
Makefile.
|
||||
|
||||
You might possibly have to trim # comments from the front of Configure
|
||||
if your sh doesn't handle them, but all other # comments will be taken
|
||||
care of.
|
||||
|
||||
If you don't have sh, you'll have to rip the prototype of config.h out
|
||||
of Configure and generate the defines by hand.
|
||||
|
||||
2) Glance through config.h to make sure system dependencies are correct.
|
||||
Most of them should have been taken care of by running the Configure script.
|
||||
|
||||
If you have any additional changes to make to the C definitions, they
|
||||
can be done in the Makefile, or in config.h. Bear in mind that they may
|
||||
get undone next time you run Configure.
|
||||
|
||||
3) make
|
||||
|
||||
This will attempt to make patch in the current directory.
|
||||
|
||||
4) make install
|
||||
|
||||
This will put patch into a public directory (normally /usr/local/bin).
|
||||
It will also try to put the man pages in a reasonable place. It will not
|
||||
nroff the man page, however.
|
||||
|
||||
5) Read the manual entry before running patch.
|
||||
|
||||
6) IMPORTANT! Help save the world! Communicate any problems and
|
||||
suggested patches to me, lwall@sdcrdcf.UUCP (Larry Wall), so we can
|
||||
keep the world in sync. If you have a problem, there's someone else
|
||||
out there who either has had or will have the same problem.
|
||||
|
||||
If possible, send in patches such that the patch program will apply them.
|
||||
Context diffs are the best, then normal diffs. Don't send ed scripts--
|
||||
I've probably changed my copy since the version you have.
|
||||
|
||||
Watch for patch patches in net.sources.bugs. Patches will generally be
|
||||
in a form usable by the patch program. If you are just now bringing up
|
||||
patch and aren't sure how many patches there are, write to me and I'll
|
||||
send any you don't have. Your current patch level is shown in patchlevel.h.
|
||||
|
||||
|
||||
NEW FEATURES IN THIS RELEASE
|
||||
|
||||
(Correct) support for 4.3bsd-style context diffs.
|
||||
Files can be created from scratch.
|
||||
You can specify a fuzz-factor for context matching.
|
||||
You can force patch to ask no questions.
|
||||
You can specify how much of the leading pathname to strip off filenames.
|
||||
Uses a Configure script for greater portability.
|
||||
You are now asked if you want to apply a reversed patch.
|
||||
No limit (apart from memory) on the size of hunks.
|
138
usr.bin/patch/common.h
Normal file
138
usr.bin/patch/common.h
Normal file
@ -0,0 +1,138 @@
|
||||
/* $Header: common.h,v 2.0 86/09/17 15:36:39 lwall Exp $
|
||||
*
|
||||
* $Log: common.h,v $
|
||||
* Revision 2.0 86/09/17 15:36:39 lwall
|
||||
* Baseline for netwide release.
|
||||
*
|
||||
*/
|
||||
|
||||
#define DEBUGGING
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* shut lint up about the following when return value ignored */
|
||||
|
||||
#define Signal (void)signal
|
||||
#define Unlink (void)unlink
|
||||
#define Lseek (void)lseek
|
||||
#define Fseek (void)fseek
|
||||
#define Fstat (void)fstat
|
||||
#define Pclose (void)pclose
|
||||
#define Close (void)close
|
||||
#define Fclose (void)fclose
|
||||
#define Fflush (void)fflush
|
||||
#define Sprintf (void)sprintf
|
||||
#define Mktemp (void)mktemp
|
||||
#define Strcpy (void)strcpy
|
||||
#define Strcat (void)strcat
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
|
||||
/* constants */
|
||||
|
||||
#define TRUE (1)
|
||||
#define FALSE (0)
|
||||
|
||||
#define MAXHUNKSIZE 100000 /* is this enough lines? */
|
||||
#define INITHUNKMAX 125 /* initial dynamic allocation size */
|
||||
#define MAXLINELEN 1024
|
||||
#define BUFFERSIZE 1024
|
||||
#define ORIGEXT ".orig"
|
||||
#define SCCSPREFIX "s."
|
||||
#define GET "get -e %s"
|
||||
#define RCSSUFFIX ",v"
|
||||
#define CHECKOUT "co -l %s"
|
||||
|
||||
/* handy definitions */
|
||||
|
||||
#define Null(t) ((t)0)
|
||||
#define Nullch Null(char *)
|
||||
#define Nullfp Null(FILE *)
|
||||
#define Nulline Null(LINENUM)
|
||||
|
||||
#define Ctl(ch) ((ch) & 037)
|
||||
|
||||
#define strNE(s1,s2) (strcmp(s1, s2))
|
||||
#define strEQ(s1,s2) (!strcmp(s1, s2))
|
||||
#define strnNE(s1,s2,l) (strncmp(s1, s2, l))
|
||||
#define strnEQ(s1,s2,l) (!strncmp(s1, s2, l))
|
||||
|
||||
/* typedefs */
|
||||
|
||||
typedef char bool;
|
||||
typedef long LINENUM; /* must be signed */
|
||||
typedef unsigned MEM; /* what to feed malloc */
|
||||
|
||||
/* globals */
|
||||
|
||||
EXT int Argc; /* guess */
|
||||
EXT char **Argv;
|
||||
EXT int Argc_last; /* for restarting plan_b */
|
||||
EXT char **Argv_last;
|
||||
|
||||
EXT struct stat filestat; /* file statistics area */
|
||||
EXT int filemode INIT(0644);
|
||||
|
||||
EXT char buf[MAXLINELEN]; /* general purpose buffer */
|
||||
EXT FILE *ofp INIT(Nullfp); /* output file pointer */
|
||||
EXT FILE *rejfp INIT(Nullfp); /* reject file pointer */
|
||||
|
||||
EXT bool using_plan_a INIT(TRUE); /* try to keep everything in memory */
|
||||
EXT bool out_of_mem INIT(FALSE); /* ran out of memory in plan a */
|
||||
|
||||
#define MAXFILEC 2
|
||||
EXT int filec INIT(0); /* how many file arguments? */
|
||||
EXT char *filearg[MAXFILEC];
|
||||
EXT bool ok_to_create_file INIT(FALSE);
|
||||
EXT char *bestguess INIT(Nullch); /* guess at correct filename */
|
||||
|
||||
EXT char *outname INIT(Nullch);
|
||||
EXT char rejname[128];
|
||||
|
||||
EXT char *origext INIT(Nullch);
|
||||
|
||||
EXT char TMPOUTNAME[] INIT("/tmp/patchoXXXXXX");
|
||||
EXT char TMPINNAME[] INIT("/tmp/patchiXXXXXX"); /* might want /usr/tmp here */
|
||||
EXT char TMPREJNAME[] INIT("/tmp/patchrXXXXXX");
|
||||
EXT char TMPPATNAME[] INIT("/tmp/patchpXXXXXX");
|
||||
EXT bool toutkeep INIT(FALSE);
|
||||
EXT bool trejkeep INIT(FALSE);
|
||||
|
||||
EXT LINENUM last_offset INIT(0);
|
||||
#ifdef DEBUGGING
|
||||
EXT int debug INIT(0);
|
||||
#endif
|
||||
EXT LINENUM maxfuzz INIT(2);
|
||||
EXT bool force INIT(FALSE);
|
||||
EXT bool verbose INIT(TRUE);
|
||||
EXT bool reverse INIT(FALSE);
|
||||
EXT bool noreverse INIT(FALSE);
|
||||
EXT bool skip_rest_of_patch INIT(FALSE);
|
||||
EXT int strippath INIT(957);
|
||||
EXT bool canonicalize INIT(FALSE);
|
||||
|
||||
#define CONTEXT_DIFF 1
|
||||
#define NORMAL_DIFF 2
|
||||
#define ED_DIFF 3
|
||||
#define NEW_CONTEXT_DIFF 4
|
||||
EXT int diff_type INIT(0);
|
||||
|
||||
EXT bool do_defines INIT(FALSE); /* patch using ifdef, ifndef, etc. */
|
||||
EXT char if_defined[128]; /* #ifdef xyzzy */
|
||||
EXT char not_defined[128]; /* #ifndef xyzzy */
|
||||
EXT char else_defined[] INIT("#else\n");/* #else */
|
||||
EXT char end_defined[128]; /* #endif xyzzy */
|
||||
|
||||
EXT char *revision INIT(Nullch); /* prerequisite revision, if any */
|
||||
|
||||
char *malloc();
|
||||
char *realloc();
|
||||
char *strcpy();
|
||||
char *strcat();
|
||||
long atol();
|
||||
char *mktemp();
|
16
usr.bin/patch/config.h
Normal file
16
usr.bin/patch/config.h
Normal file
@ -0,0 +1,16 @@
|
||||
#define Reg1 register /**/
|
||||
#define Reg2 register /**/
|
||||
#define Reg3 register /**/
|
||||
#define Reg4 register /**/
|
||||
#define Reg5 register /**/
|
||||
#define Reg6 register /**/
|
||||
#define Reg7 register /**/
|
||||
#define Reg8 register /**/
|
||||
#define Reg9 register /**/
|
||||
#define Reg10 register /**/
|
||||
#define Reg11 /**/
|
||||
#define Reg12 /**/
|
||||
#define Reg13 /**/
|
||||
#define Reg14 /**/
|
||||
#define Reg15 /**/
|
||||
#define Reg16 /**/
|
313
usr.bin/patch/inp.c
Normal file
313
usr.bin/patch/inp.c
Normal file
@ -0,0 +1,313 @@
|
||||
/* $Header: inp.c,v 2.0 86/09/17 15:37:02 lwall Exp $
|
||||
*
|
||||
* $Log: inp.c,v $
|
||||
* Revision 2.0 86/09/17 15:37:02 lwall
|
||||
* Baseline for netwide release.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EXTERN.h"
|
||||
#include "common.h"
|
||||
#include "util.h"
|
||||
#include "pch.h"
|
||||
#include "INTERN.h"
|
||||
#include "inp.h"
|
||||
|
||||
/* Input-file-with-indexable-lines abstract type */
|
||||
|
||||
static long i_size; /* size of the input file */
|
||||
static char *i_womp; /* plan a buffer for entire file */
|
||||
static char **i_ptr; /* pointers to lines in i_womp */
|
||||
|
||||
static int tifd = -1; /* plan b virtual string array */
|
||||
static char *tibuf[2]; /* plan b buffers */
|
||||
static LINENUM tiline[2] = {-1, -1}; /* 1st line in each buffer */
|
||||
static LINENUM lines_per_buf; /* how many lines per buffer */
|
||||
static int tireclen; /* length of records in tmp file */
|
||||
|
||||
/* New patch--prepare to edit another file. */
|
||||
|
||||
void
|
||||
re_input()
|
||||
{
|
||||
if (using_plan_a) {
|
||||
i_size = 0;
|
||||
#ifndef lint
|
||||
if (i_ptr != Null(char**))
|
||||
free((char *)i_ptr);
|
||||
#endif
|
||||
if (i_womp != Nullch)
|
||||
free(i_womp);
|
||||
i_womp = Nullch;
|
||||
i_ptr = Null(char **);
|
||||
}
|
||||
else {
|
||||
using_plan_a = TRUE; /* maybe the next one is smaller */
|
||||
Close(tifd);
|
||||
tifd = -1;
|
||||
free(tibuf[0]);
|
||||
free(tibuf[1]);
|
||||
tibuf[0] = tibuf[1] = Nullch;
|
||||
tiline[0] = tiline[1] = -1;
|
||||
tireclen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Constuct the line index, somehow or other. */
|
||||
|
||||
void
|
||||
scan_input(filename)
|
||||
char *filename;
|
||||
{
|
||||
if (!plan_a(filename))
|
||||
plan_b(filename);
|
||||
if (verbose) {
|
||||
say3("Patching file %s using Plan %s...\n", filename,
|
||||
(using_plan_a ? "A" : "B") );
|
||||
}
|
||||
}
|
||||
|
||||
/* Try keeping everything in memory. */
|
||||
|
||||
bool
|
||||
plan_a(filename)
|
||||
char *filename;
|
||||
{
|
||||
int ifd;
|
||||
Reg1 char *s;
|
||||
Reg2 LINENUM iline;
|
||||
|
||||
if (ok_to_create_file && stat(filename, &filestat) < 0) {
|
||||
if (verbose)
|
||||
say2("(Creating file %s...)\n",filename);
|
||||
makedirs(filename, TRUE);
|
||||
close(creat(filename, 0666));
|
||||
}
|
||||
if (stat(filename, &filestat) < 0) {
|
||||
Sprintf(buf, "RCS/%s%s", filename, RCSSUFFIX);
|
||||
if (stat(buf, &filestat) >= 0 || stat(buf+4, &filestat) >= 0) {
|
||||
Sprintf(buf, CHECKOUT, filename);
|
||||
if (verbose)
|
||||
say2("Can't find %s--attempting to check it out from RCS.\n",
|
||||
filename);
|
||||
if (system(buf) || stat(filename, &filestat))
|
||||
fatal2("Can't check out %s.\n", filename);
|
||||
}
|
||||
else {
|
||||
Sprintf(buf, "SCCS/%s%s", SCCSPREFIX, filename);
|
||||
if (stat(buf, &filestat) >= 0 || stat(buf+5, &filestat) >= 0) {
|
||||
Sprintf(buf, GET, filename);
|
||||
if (verbose)
|
||||
say2("Can't find %s--attempting to get it from SCCS.\n",
|
||||
filename);
|
||||
if (system(buf) || stat(filename, &filestat))
|
||||
fatal2("Can't get %s.\n", filename);
|
||||
}
|
||||
else
|
||||
fatal2("Can't find %s.\n", filename);
|
||||
}
|
||||
}
|
||||
filemode = filestat.st_mode;
|
||||
if ((filemode & S_IFMT) & ~S_IFREG)
|
||||
fatal2("%s is not a normal file--can't patch.\n", filename);
|
||||
i_size = filestat.st_size;
|
||||
if (out_of_mem) {
|
||||
set_hunkmax(); /* make sure dynamic arrays are allocated */
|
||||
out_of_mem = FALSE;
|
||||
return FALSE; /* force plan b because plan a bombed */
|
||||
}
|
||||
#ifdef lint
|
||||
i_womp = Nullch;
|
||||
#else
|
||||
i_womp = malloc((MEM)(i_size+2)); /* lint says this may alloc less than */
|
||||
/* i_size, but that's okay, I think. */
|
||||
#endif
|
||||
if (i_womp == Nullch)
|
||||
return FALSE;
|
||||
if ((ifd = open(filename, 0)) < 0)
|
||||
fatal2("Can't open file %s\n", filename);
|
||||
#ifndef lint
|
||||
if (read(ifd, i_womp, (int)i_size) != i_size) {
|
||||
Close(ifd); /* probably means i_size > 15 or 16 bits worth */
|
||||
free(i_womp); /* at this point it doesn't matter if i_womp was */
|
||||
return FALSE; /* undersized. */
|
||||
}
|
||||
#endif
|
||||
Close(ifd);
|
||||
if (i_size && i_womp[i_size-1] != '\n')
|
||||
i_womp[i_size++] = '\n';
|
||||
i_womp[i_size] = '\0';
|
||||
|
||||
/* count the lines in the buffer so we know how many pointers we need */
|
||||
|
||||
iline = 0;
|
||||
for (s=i_womp; *s; s++) {
|
||||
if (*s == '\n')
|
||||
iline++;
|
||||
}
|
||||
#ifdef lint
|
||||
i_ptr = Null(char**);
|
||||
#else
|
||||
i_ptr = (char **)malloc((MEM)((iline + 2) * sizeof(char *)));
|
||||
#endif
|
||||
if (i_ptr == Null(char **)) { /* shucks, it was a near thing */
|
||||
free((char *)i_womp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* now scan the buffer and build pointer array */
|
||||
|
||||
iline = 1;
|
||||
i_ptr[iline] = i_womp;
|
||||
for (s=i_womp; *s; s++) {
|
||||
if (*s == '\n')
|
||||
i_ptr[++iline] = s+1; /* these are NOT null terminated */
|
||||
}
|
||||
input_lines = iline - 1;
|
||||
|
||||
/* now check for revision, if any */
|
||||
|
||||
if (revision != Nullch) {
|
||||
if (!rev_in_string(i_womp)) {
|
||||
if (force) {
|
||||
if (verbose)
|
||||
say2("\
|
||||
Warning: this file doesn't appear to be the %s version--patching anyway.\n",
|
||||
revision);
|
||||
}
|
||||
else {
|
||||
ask2("\
|
||||
This file doesn't appear to be the %s version--patch anyway? [n] ",
|
||||
revision);
|
||||
if (*buf != 'y')
|
||||
fatal1("Aborted.\n");
|
||||
}
|
||||
}
|
||||
else if (verbose)
|
||||
say2("Good. This file appears to be the %s version.\n",
|
||||
revision);
|
||||
}
|
||||
return TRUE; /* plan a will work */
|
||||
}
|
||||
|
||||
/* Keep (virtually) nothing in memory. */
|
||||
|
||||
void
|
||||
plan_b(filename)
|
||||
char *filename;
|
||||
{
|
||||
Reg3 FILE *ifp;
|
||||
Reg1 int i = 0;
|
||||
Reg2 int maxlen = 1;
|
||||
Reg4 bool found_revision = (revision == Nullch);
|
||||
|
||||
using_plan_a = FALSE;
|
||||
if ((ifp = fopen(filename, "r")) == Nullfp)
|
||||
fatal2("Can't open file %s\n", filename);
|
||||
if ((tifd = creat(TMPINNAME, 0666)) < 0)
|
||||
fatal2("Can't open file %s\n", TMPINNAME);
|
||||
while (fgets(buf, sizeof buf, ifp) != Nullch) {
|
||||
if (revision != Nullch && !found_revision && rev_in_string(buf))
|
||||
found_revision = TRUE;
|
||||
if ((i = strlen(buf)) > maxlen)
|
||||
maxlen = i; /* find longest line */
|
||||
}
|
||||
if (revision != Nullch) {
|
||||
if (!found_revision) {
|
||||
if (force) {
|
||||
if (verbose)
|
||||
say2("\
|
||||
Warning: this file doesn't appear to be the %s version--patching anyway.\n",
|
||||
revision);
|
||||
}
|
||||
else {
|
||||
ask2("\
|
||||
This file doesn't appear to be the %s version--patch anyway? [n] ",
|
||||
revision);
|
||||
if (*buf != 'y')
|
||||
fatal1("Aborted.\n");
|
||||
}
|
||||
}
|
||||
else if (verbose)
|
||||
say2("Good. This file appears to be the %s version.\n",
|
||||
revision);
|
||||
}
|
||||
Fseek(ifp, 0L, 0); /* rewind file */
|
||||
lines_per_buf = BUFFERSIZE / maxlen;
|
||||
tireclen = maxlen;
|
||||
tibuf[0] = malloc((MEM)(BUFFERSIZE + 1));
|
||||
tibuf[1] = malloc((MEM)(BUFFERSIZE + 1));
|
||||
if (tibuf[1] == Nullch)
|
||||
fatal1("Can't seem to get enough memory.\n");
|
||||
for (i=1; ; i++) {
|
||||
if (! (i % lines_per_buf)) /* new block */
|
||||
if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
|
||||
fatal1("patch: can't write temp file.\n");
|
||||
if (fgets(tibuf[0] + maxlen * (i%lines_per_buf), maxlen + 1, ifp)
|
||||
== Nullch) {
|
||||
input_lines = i - 1;
|
||||
if (i % lines_per_buf)
|
||||
if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
|
||||
fatal1("patch: can't write temp file.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
Fclose(ifp);
|
||||
Close(tifd);
|
||||
if ((tifd = open(TMPINNAME, 0)) < 0) {
|
||||
fatal2("Can't reopen file %s\n", TMPINNAME);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fetch a line from the input file, \n terminated, not necessarily \0. */
|
||||
|
||||
char *
|
||||
ifetch(line,whichbuf)
|
||||
Reg1 LINENUM line;
|
||||
int whichbuf; /* ignored when file in memory */
|
||||
{
|
||||
if (line < 1 || line > input_lines)
|
||||
return "";
|
||||
if (using_plan_a)
|
||||
return i_ptr[line];
|
||||
else {
|
||||
LINENUM offline = line % lines_per_buf;
|
||||
LINENUM baseline = line - offline;
|
||||
|
||||
if (tiline[0] == baseline)
|
||||
whichbuf = 0;
|
||||
else if (tiline[1] == baseline)
|
||||
whichbuf = 1;
|
||||
else {
|
||||
tiline[whichbuf] = baseline;
|
||||
#ifndef lint /* complains of long accuracy */
|
||||
Lseek(tifd, (off_t)baseline / lines_per_buf * BUFFERSIZE, 0);
|
||||
#endif
|
||||
if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0)
|
||||
fatal2("Error reading tmp file %s.\n", TMPINNAME);
|
||||
}
|
||||
return tibuf[whichbuf] + (tireclen*offline);
|
||||
}
|
||||
}
|
||||
|
||||
/* True if the string argument contains the revision number we want. */
|
||||
|
||||
bool
|
||||
rev_in_string(string)
|
||||
char *string;
|
||||
{
|
||||
Reg1 char *s;
|
||||
Reg2 int patlen;
|
||||
|
||||
if (revision == Nullch)
|
||||
return TRUE;
|
||||
patlen = strlen(revision);
|
||||
for (s = string; *s; s++) {
|
||||
if (isspace(*s) && strnEQ(s+1, revision, patlen) &&
|
||||
isspace(s[patlen+1] )) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
18
usr.bin/patch/inp.h
Normal file
18
usr.bin/patch/inp.h
Normal file
@ -0,0 +1,18 @@
|
||||
/* $Header: inp.h,v 2.0 86/09/17 15:37:25 lwall Exp $
|
||||
*
|
||||
* $Log: inp.h,v $
|
||||
* Revision 2.0 86/09/17 15:37:25 lwall
|
||||
* Baseline for netwide release.
|
||||
*
|
||||
*/
|
||||
|
||||
EXT LINENUM input_lines INIT(0); /* how long is input file in lines */
|
||||
EXT LINENUM last_frozen_line INIT(0); /* how many input lines have been */
|
||||
/* irretractibly output */
|
||||
|
||||
bool rev_in_string();
|
||||
void scan_input();
|
||||
bool plan_a(); /* returns false if insufficient memory */
|
||||
void plan_b();
|
||||
char *ifetch();
|
||||
|
446
usr.bin/patch/patch.1
Normal file
446
usr.bin/patch/patch.1
Normal file
@ -0,0 +1,446 @@
|
||||
''' $Header: patch.man,v 2.0 86/09/17 15:39:09 lwall Exp $
|
||||
'''
|
||||
''' $Log: patch.man,v $
|
||||
''' Revision 2.0 86/09/17 15:39:09 lwall
|
||||
''' Baseline for netwide release.
|
||||
'''
|
||||
''' Revision 1.4 86/08/01 19:23:22 lwall
|
||||
''' Documented -v, -p, -F.
|
||||
''' Added notes to patch senders.
|
||||
'''
|
||||
''' Revision 1.3 85/03/26 15:11:06 lwall
|
||||
''' Frozen.
|
||||
'''
|
||||
''' Revision 1.2.1.4 85/03/12 16:14:27 lwall
|
||||
''' Documented -p.
|
||||
'''
|
||||
''' Revision 1.2.1.3 85/03/12 16:09:41 lwall
|
||||
''' Documented -D.
|
||||
'''
|
||||
''' Revision 1.2.1.2 84/12/05 11:06:55 lwall
|
||||
''' Added -l switch, and noted bistability bug.
|
||||
'''
|
||||
''' Revision 1.2.1.1 84/12/04 17:23:39 lwall
|
||||
''' Branch for sdcrdcf changes.
|
||||
'''
|
||||
''' Revision 1.2 84/12/04 17:22:02 lwall
|
||||
''' Baseline version.
|
||||
'''
|
||||
.de Sh
|
||||
.br
|
||||
.ne 5
|
||||
.PP
|
||||
\fB\\$1\fR
|
||||
.PP
|
||||
..
|
||||
.de Sp
|
||||
.if t .sp .5v
|
||||
.if n .sp
|
||||
..
|
||||
'''
|
||||
''' Set up \*(-- to give an unbreakable dash;
|
||||
''' string Tr holds user defined translation string.
|
||||
''' Bell System Logo is used as a dummy character.
|
||||
'''
|
||||
.ie n \{\
|
||||
.tr \(bs-\*(Tr
|
||||
.ds -- \(bs-
|
||||
.if (\n(.H=4u)&(1m=24u) .ds -- \(bs\h'-12u'\(bs\h'-12u'-\" diablo 10 pitch
|
||||
.if (\n(.H=4u)&(1m=20u) .ds -- \(bs\h'-12u'\(bs\h'-8u'-\" diablo 12 pitch
|
||||
.ds L" ""
|
||||
.ds R" ""
|
||||
.ds L' '
|
||||
.ds R' '
|
||||
'br\}
|
||||
.el\{\
|
||||
.ds -- \(em\|
|
||||
.tr \*(Tr
|
||||
.ds L" ``
|
||||
.ds R" ''
|
||||
.ds L' `
|
||||
.ds R' '
|
||||
'br\}
|
||||
.TH PATCH 1 "June 30, 1993"
|
||||
.SH NAME
|
||||
patch \- a program for applying a diff file to an original
|
||||
.SH SYNOPSIS
|
||||
.B patch
|
||||
[options] orig patchfile [+ [options] orig]
|
||||
.sp
|
||||
but usually just
|
||||
.sp
|
||||
.B patch
|
||||
<patchfile
|
||||
.SH DESCRIPTION
|
||||
.I Patch
|
||||
will take a patch file containing any of the three forms of difference
|
||||
listing produced by the
|
||||
.I diff
|
||||
program and apply those differences to an original file, producing a patched
|
||||
version.
|
||||
By default, the patched version is put in place of the original, with
|
||||
the original file backed up to the same name with the
|
||||
extension \*(L".orig\*(R", or as specified by the
|
||||
.B -b
|
||||
switch.
|
||||
You may also specify where you want the output to go with a
|
||||
.B -o
|
||||
switch.
|
||||
If
|
||||
.I patchfile
|
||||
is omitted, or is a hyphen, the patch will be read from standard input.
|
||||
.PP
|
||||
Upon startup, patch will attempt to determine the type of the diff listing,
|
||||
unless over-ruled by a
|
||||
.BR -c ,
|
||||
.BR -e ,
|
||||
or
|
||||
.B -n
|
||||
switch.
|
||||
Context diffs and normal diffs are applied by the
|
||||
.I patch
|
||||
program itself, while ed diffs are simply fed to the
|
||||
.I ed
|
||||
editor via a pipe.
|
||||
.PP
|
||||
.I Patch
|
||||
will try to skip any leading garbage, apply the diff,
|
||||
and then skip any trailing garbage.
|
||||
Thus you could feed an article or message containing a
|
||||
diff listing to
|
||||
.IR patch ,
|
||||
and it should work.
|
||||
If the entire diff is indented by a consistent amount,
|
||||
this will be taken into account.
|
||||
.PP
|
||||
With context diffs, and to a lesser extent with normal diffs,
|
||||
.I patch
|
||||
can detect when the line numbers mentioned in the patch are incorrect,
|
||||
and will attempt to find the correct place to apply each hunk of the patch.
|
||||
As a first guess, it takes the line number mentioned for the hunk, plus or
|
||||
minus any offset used in applying the previous hunk.
|
||||
If that is not the correct place,
|
||||
.I patch
|
||||
will scan both forwards and backwards for a set of lines matching the context
|
||||
given in the hunk.
|
||||
First
|
||||
.I patch
|
||||
looks for a place where all lines of the context match.
|
||||
If no such place is found, and it's a context diff, and the maximum fuzz factor
|
||||
is set to 1 or more, then another scan takes place ignoring the first and last
|
||||
line of context.
|
||||
If that fails, and the maximum fuzz factor is set to 2 or more,
|
||||
the first two and last two lines of context are ignored,
|
||||
and another scan is made.
|
||||
(The default maximum fuzz factor is 2.)
|
||||
If
|
||||
.I patch
|
||||
cannot find a place to install that hunk of the patch, it will put the
|
||||
hunk out to a reject file, which normally is the name of the output file
|
||||
plus \*(L".rej\*(R".
|
||||
(Note that the rejected hunk will come out in context diff form whether the
|
||||
input patch was a context diff or a normal diff.
|
||||
If the input was a normal diff, many of the contexts will simply be null.)
|
||||
The line numbers on the hunks in the reject file may be different than
|
||||
in the patch file: they reflect the approximate location patch thinks the
|
||||
failed hunks belong in the new file rather than the old one.
|
||||
.PP
|
||||
As each hunk is completed, you will be told whether the hunk succeeded or
|
||||
failed, and which line (in the new file)
|
||||
.I patch
|
||||
thought the hunk should go on.
|
||||
If this is different from the line number specified in the diff you will
|
||||
be told the offset.
|
||||
A single large offset MAY be an indication that a hunk was installed in the
|
||||
wrong place.
|
||||
You will also be told if a fuzz factor was used to make the match, in which
|
||||
case you should also be slightly suspicious.
|
||||
.PP
|
||||
If no original file is specified on the command line,
|
||||
.I patch
|
||||
will try to figure out from the leading garbage what the name of the file
|
||||
to edit is.
|
||||
In the header of a context diff, the filename is found from lines beginning
|
||||
with \*(L"***\*(R" or \*(L"---\*(R", with the shortest name of an existing
|
||||
file winning.
|
||||
Only context diffs have lines like that, but if there is an \*(L"Index:\*(R"
|
||||
line in the leading garbage,
|
||||
.I patch
|
||||
will try to use the filename from that line.
|
||||
The context diff header takes precedence over an Index line.
|
||||
If no filename can be intuited from the leading garbage, you will be asked
|
||||
for the name of the file to patch.
|
||||
.PP
|
||||
(If the original file cannot be found, but a suitable SCCS or RCS file is
|
||||
handy,
|
||||
.I patch
|
||||
will attempt to get or check out the file.)
|
||||
.PP
|
||||
Additionally, if the leading garbage contains a \*(L"Prereq: \*(R" line,
|
||||
.I patch
|
||||
will take the first word from the prerequisites line (normally a version
|
||||
number) and check the input file to see if that word can be found.
|
||||
If not,
|
||||
.I patch
|
||||
will ask for confirmation before proceeding.
|
||||
.PP
|
||||
The upshot of all this is that you should be able to say, while in a news
|
||||
interface, the following:
|
||||
.Sp
|
||||
| patch -d /usr/src/local/blurfl
|
||||
.Sp
|
||||
and patch a file in the blurfl directory directly from the article containing
|
||||
the patch.
|
||||
.PP
|
||||
If the patch file contains more than one patch,
|
||||
.I patch
|
||||
will try to apply each of them as if they came from separate patch files.
|
||||
This means, among other things, that it is assumed that the name of the file
|
||||
to patch must be determined for each diff listing,
|
||||
and that the garbage before each diff listing will
|
||||
be examined for interesting things such as filenames and revision level, as
|
||||
mentioned previously.
|
||||
You can give switches (and another original file name) for the second and
|
||||
subsequent patches by separating the corresponding argument lists
|
||||
by a \*(L'+\*(R'.
|
||||
(The argument list for a second or subsequent patch may not specify a new
|
||||
patch file, however.)
|
||||
.PP
|
||||
.I Patch
|
||||
recognizes the following switches:
|
||||
.TP 5
|
||||
.B \-b
|
||||
causes the next argument to be interpreted as the backup extension, to be
|
||||
used in place of \*(L".orig\*(R".
|
||||
.TP 5
|
||||
.B \-c
|
||||
forces
|
||||
.I patch
|
||||
to interpret the patch file as a context diff.
|
||||
.TP 5
|
||||
.B \-d
|
||||
causes
|
||||
.I patch
|
||||
to interpret the next argument as a directory, and cd to it before doing
|
||||
anything else.
|
||||
.TP 5
|
||||
.B \-D
|
||||
causes
|
||||
.I patch
|
||||
to use the "#ifdef...#endif" construct to mark changes.
|
||||
The argument following will be used as the differentiating symbol.
|
||||
Note that, unlike the C compiler, there must be a space between the
|
||||
.B \-D
|
||||
and the argument.
|
||||
.TP 5
|
||||
.B \-e
|
||||
forces
|
||||
.I patch
|
||||
to interpret the patch file as an ed script.
|
||||
.TP 5
|
||||
.B \-f
|
||||
forces
|
||||
.I patch
|
||||
to assume that the user knows exactly what he or she is doing, and to not
|
||||
ask any questions.
|
||||
It does not suppress commentary, however.
|
||||
Use
|
||||
.B \-s
|
||||
for that.
|
||||
.TP 5
|
||||
.B \-F<number>
|
||||
sets the maximum fuzz factor.
|
||||
This switch only applied to context diffs, and causes
|
||||
.I patch
|
||||
to ignore up to that many lines in looking for places to install a hunk.
|
||||
Note that a larger fuzz factor increases the odds of a faulty patch.
|
||||
The default fuzz factor is 2, and it may not be set to more than
|
||||
the number of lines of context in the context diff, ordinarily 3.
|
||||
.TP 5
|
||||
.B \-l
|
||||
causes the pattern matching to be done loosely, in case the tabs and
|
||||
spaces have been munged in your input file.
|
||||
Any sequence of whitespace in the pattern line will match any sequence
|
||||
in the input file.
|
||||
Normal characters must still match exactly.
|
||||
Each line of the context must still match a line in the input file.
|
||||
.TP 5
|
||||
.B \-n
|
||||
forces
|
||||
.I patch
|
||||
to interpret the patch file as a normal diff.
|
||||
.TP 5
|
||||
.B \-N
|
||||
causes
|
||||
.I patch
|
||||
to ignore patches that it thinks are reversed or already applied.
|
||||
See also
|
||||
.B \-R .
|
||||
.TP 5
|
||||
.B \-o
|
||||
causes the next argument to be interpreted as the output file name.
|
||||
.TP 5
|
||||
.B \-p<number>
|
||||
sets the pathname strip count,
|
||||
which controls how pathnames found in the patch file are treated, in case
|
||||
the you keep your files in a different directory than the person who sent
|
||||
out the patch.
|
||||
The strip count specifies how many backslashes are to be stripped from
|
||||
the front of the pathname.
|
||||
(Any intervening directory names also go away.)
|
||||
For example, supposing the filename in the patch file was
|
||||
.sp
|
||||
/u/howard/src/blurfl/blurfl.c
|
||||
.sp
|
||||
setting
|
||||
.B \-p
|
||||
or
|
||||
.B \-p0
|
||||
gives the entire pathname unmodified,
|
||||
.B \-p1
|
||||
gives
|
||||
.sp
|
||||
u/howard/src/blurfl/blurfl.c
|
||||
.sp
|
||||
without the leading slash,
|
||||
.B \-p4
|
||||
gives
|
||||
.sp
|
||||
blurfl/blurfl.c
|
||||
.sp
|
||||
and not specifying
|
||||
.B \-p
|
||||
at all just gives you "blurfl.c".
|
||||
Whatever you end up with is looked for either in the current directory,
|
||||
or the directory specified by the
|
||||
.B \-d
|
||||
switch.
|
||||
.TP 5
|
||||
.B \-r
|
||||
causes the next argument to be interpreted as the reject file name.
|
||||
.TP 5
|
||||
.B \-R
|
||||
tells
|
||||
.I patch
|
||||
that this patch was created with the old and new files swapped.
|
||||
(Yes, I'm afraid that does happen occasionally, human nature being what it
|
||||
is.)
|
||||
.I Patch
|
||||
will attempt to swap each hunk around before applying it.
|
||||
Rejects will come out in the swapped format.
|
||||
The
|
||||
.B \-R
|
||||
switch will not work with ed diff scripts because there is too little
|
||||
information to reconstruct the reverse operation.
|
||||
.Sp
|
||||
If the first hunk of a patch fails,
|
||||
.I patch
|
||||
will reverse the hunk to see if it can be applied that way.
|
||||
If it can, you will be asked if you want to have the
|
||||
.B \-R
|
||||
switch set.
|
||||
If it can't, the patch will continue to be applied normally.
|
||||
(Note: this method cannot detect a reversed patch if it is a normal diff
|
||||
and if the first command is an append (i.e. it should have been a delete)
|
||||
since appends always succeed, due to the fact that a null context will match
|
||||
anywhere.
|
||||
Luckily, most patches add or change lines rather than delete them, so most
|
||||
reversed normal diffs will begin with a delete, which will fail, triggering
|
||||
the heuristic.)
|
||||
.TP 5
|
||||
.B \-s
|
||||
makes
|
||||
.I patch
|
||||
do its work silently, unless an error occurs.
|
||||
.TP 5
|
||||
.B \-S
|
||||
causes
|
||||
.I patch
|
||||
to ignore this patch from the patch file, but continue on looking
|
||||
for the next patch in the file.
|
||||
Thus
|
||||
.sp
|
||||
patch -S + -S + <patchfile
|
||||
.sp
|
||||
will ignore the first and second of three patches.
|
||||
.TP 5
|
||||
.B \-v
|
||||
causes
|
||||
.I patch
|
||||
to print out it's revision header and patch level.
|
||||
.TP 5
|
||||
.B \-x<number>
|
||||
sets internal debugging flags, and is of interest only to
|
||||
.I patch
|
||||
patchers.
|
||||
.SH ENVIRONMENT
|
||||
No environment variables are used by
|
||||
.IR patch .
|
||||
.SH FILES
|
||||
/tmp/patch*
|
||||
.SH SEE ALSO
|
||||
diff(1)
|
||||
.SH NOTES FOR PATCH SENDERS
|
||||
There are several things you should bear in mind if you are going to
|
||||
be sending out patches.
|
||||
First, you can save people a lot of grief by keeping a patchlevel.h file
|
||||
which is patched to increment the patch level as the first diff in the
|
||||
patch file you send out.
|
||||
If you put a Prereq: line in with the patch, it won't let them apply
|
||||
patches out of order without some warning.
|
||||
Second, make sure you've specified the filenames right, either in a
|
||||
context diff header, or with an Index: line.
|
||||
If you are patching something in a subdirectory, be sure to tell the patch
|
||||
user to specify a
|
||||
.B \-p
|
||||
switch as needed.
|
||||
Third, you can create a file by sending out a diff that compares a
|
||||
null file to the file you want to create.
|
||||
This will only work if the file you want to create doesn't exist already in
|
||||
the target directory.
|
||||
Fourth, take care not to send out reversed patches, since it makes people wonder
|
||||
whether they already applied the patch.
|
||||
Fifth, while you may be able to get away with putting 582 diff listings into
|
||||
one file, it is probably wiser to group related patches into separate files in
|
||||
case something goes haywire.
|
||||
.SH DIAGNOSTICS
|
||||
Too many to list here, but generally indicative that
|
||||
.I patch
|
||||
couldn't parse your patch file.
|
||||
.PP
|
||||
The message \*(L"Hmm...\*(R" indicates that there is unprocessed text in
|
||||
the patch file and that
|
||||
.I patch
|
||||
is attempting to intuit whether there is a patch in that text and, if so,
|
||||
what kind of patch it is.
|
||||
.SH CAVEATS
|
||||
.I Patch
|
||||
cannot tell if the line numbers are off in an ed script, and can only detect
|
||||
bad line numbers in a normal diff when it finds a \*(L"change\*(R" or
|
||||
a \*(L"delete\*(R" command.
|
||||
A context diff using fuzz factor 3 may have the same problem.
|
||||
Until a suitable interactive interface is added, you should probably do
|
||||
a context diff in these cases to see if the changes made sense.
|
||||
Of course, compiling without errors is a pretty good indication that the patch
|
||||
worked, but not always.
|
||||
.PP
|
||||
.I Patch
|
||||
usually produces the correct results, even when it has to do a lot of
|
||||
guessing.
|
||||
However, the results are guaranteed to be correct only when the patch is
|
||||
applied to exactly the same version of the file that the patch was
|
||||
generated from.
|
||||
.SH BUGS
|
||||
Could be smarter about partial matches, excessively \&deviant offsets and
|
||||
swapped code, but that would take an extra pass.
|
||||
.PP
|
||||
If code has been duplicated (for instance with #ifdef OLDCODE ... #else ...
|
||||
#endif),
|
||||
.I patch
|
||||
is incapable of patching both versions, and, if it works at all, will likely
|
||||
patch the wrong one, and tell you that it succeeded to boot.
|
||||
.PP
|
||||
If you apply a patch you've already applied,
|
||||
.I patch
|
||||
will think it is a reversed patch, and offer to un-apply the patch.
|
||||
This could be construed as a feature.
|
800
usr.bin/patch/patch.c
Normal file
800
usr.bin/patch/patch.c
Normal file
@ -0,0 +1,800 @@
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)patch.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif not lint
|
||||
|
||||
char rcsid[] =
|
||||
"$Header: patch.c,v 2.0.1.4 87/02/16 14:00:04 lwall Exp $";
|
||||
|
||||
/* patch - a program to apply diffs to original files
|
||||
*
|
||||
* Copyright 1986, Larry Wall
|
||||
*
|
||||
* This program may be copied as long as you don't try to make any
|
||||
* money off of it, or pretend that you wrote it.
|
||||
*
|
||||
* $Log: patch.c,v $
|
||||
* Revision 2.0.1.4 87/02/16 14:00:04 lwall
|
||||
* Short replacement caused spurious "Out of sync" message.
|
||||
*
|
||||
* Revision 2.0.1.3 87/01/30 22:45:50 lwall
|
||||
* Improved diagnostic on sync error.
|
||||
* Moved do_ed_script() to pch.c.
|
||||
*
|
||||
* Revision 2.0.1.2 86/11/21 09:39:15 lwall
|
||||
* Fuzz factor caused offset of installed lines.
|
||||
*
|
||||
* Revision 2.0.1.1 86/10/29 13:10:22 lwall
|
||||
* Backwards search could terminate prematurely.
|
||||
*
|
||||
* Revision 2.0 86/09/17 15:37:32 lwall
|
||||
* Baseline for netwide release.
|
||||
*
|
||||
* Revision 1.5 86/08/01 20:53:24 lwall
|
||||
* Changed some %d's to %ld's.
|
||||
* Linted.
|
||||
*
|
||||
* Revision 1.4 86/08/01 19:17:29 lwall
|
||||
* Fixes for machines that can't vararg.
|
||||
* Added fuzz factor.
|
||||
* Generalized -p.
|
||||
* General cleanup.
|
||||
*
|
||||
* 85/08/15 van%ucbmonet@berkeley
|
||||
* Changes for 4.3bsd diff -c.
|
||||
*
|
||||
* Revision 1.3 85/03/26 15:07:43 lwall
|
||||
* Frozen.
|
||||
*
|
||||
* Revision 1.2.1.9 85/03/12 17:03:35 lwall
|
||||
* Changed pfp->_file to fileno(pfp).
|
||||
*
|
||||
* Revision 1.2.1.8 85/03/12 16:30:43 lwall
|
||||
* Check i_ptr and i_womp to make sure they aren't null before freeing.
|
||||
* Also allow ed output to be suppressed.
|
||||
*
|
||||
* Revision 1.2.1.7 85/03/12 15:56:13 lwall
|
||||
* Added -p option from jromine@uci-750a.
|
||||
*
|
||||
* Revision 1.2.1.6 85/03/12 12:12:51 lwall
|
||||
* Now checks for normalness of file to patch.
|
||||
*
|
||||
* Revision 1.2.1.5 85/03/12 11:52:12 lwall
|
||||
* Added -D (#ifdef) option from joe@fluke.
|
||||
*
|
||||
* Revision 1.2.1.4 84/12/06 11:14:15 lwall
|
||||
* Made smarter about SCCS subdirectories.
|
||||
*
|
||||
* Revision 1.2.1.3 84/12/05 11:18:43 lwall
|
||||
* Added -l switch to do loose string comparison.
|
||||
*
|
||||
* Revision 1.2.1.2 84/12/04 09:47:13 lwall
|
||||
* Failed hunk count not reset on multiple patch file.
|
||||
*
|
||||
* Revision 1.2.1.1 84/12/04 09:42:37 lwall
|
||||
* Branch for sdcrdcf changes.
|
||||
*
|
||||
* Revision 1.2 84/11/29 13:29:51 lwall
|
||||
* Linted. Identifiers uniqified. Fixed i_ptr malloc() bug. Fixed
|
||||
* multiple calls to mktemp(). Will now work on machines that can only
|
||||
* read 32767 chars. Added -R option for diffs with new and old swapped.
|
||||
* Various cosmetic changes.
|
||||
*
|
||||
* Revision 1.1 84/11/09 17:03:58 lwall
|
||||
* Initial revision
|
||||
*
|
||||
*/
|
||||
|
||||
#include "INTERN.h"
|
||||
#include "common.h"
|
||||
#include "EXTERN.h"
|
||||
#include "version.h"
|
||||
#include "util.h"
|
||||
#include "pch.h"
|
||||
#include "inp.h"
|
||||
|
||||
/* procedures */
|
||||
|
||||
void reinitialize_almost_everything();
|
||||
void get_some_switches();
|
||||
LINENUM locate_hunk();
|
||||
void abort_hunk();
|
||||
void apply_hunk();
|
||||
void init_output();
|
||||
void init_reject();
|
||||
void copy_till();
|
||||
void spew_output();
|
||||
void dump_line();
|
||||
bool patch_match();
|
||||
bool similar();
|
||||
void re_input();
|
||||
void my_exit();
|
||||
|
||||
/* Apply a set of diffs as appropriate. */
|
||||
|
||||
main(argc,argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
LINENUM where;
|
||||
LINENUM newwhere;
|
||||
LINENUM fuzz;
|
||||
LINENUM mymaxfuzz;
|
||||
int hunk = 0;
|
||||
int failed = 0;
|
||||
int i;
|
||||
|
||||
setbuf(stderr, serrbuf);
|
||||
for (i = 0; i<MAXFILEC; i++)
|
||||
filearg[i] = Nullch;
|
||||
Mktemp(TMPOUTNAME);
|
||||
Mktemp(TMPINNAME);
|
||||
Mktemp(TMPREJNAME);
|
||||
Mktemp(TMPPATNAME);
|
||||
|
||||
/* parse switches */
|
||||
Argc = argc;
|
||||
Argv = argv;
|
||||
get_some_switches();
|
||||
|
||||
/* make sure we clean up /tmp in case of disaster */
|
||||
set_signals();
|
||||
|
||||
for (
|
||||
open_patch_file(filearg[1]);
|
||||
there_is_another_patch();
|
||||
reinitialize_almost_everything()
|
||||
) { /* for each patch in patch file */
|
||||
|
||||
if (outname == Nullch)
|
||||
outname = savestr(filearg[0]);
|
||||
|
||||
/* initialize the patched file */
|
||||
if (!skip_rest_of_patch)
|
||||
init_output(TMPOUTNAME);
|
||||
|
||||
/* for ed script just up and do it and exit */
|
||||
if (diff_type == ED_DIFF) {
|
||||
do_ed_script();
|
||||
continue;
|
||||
}
|
||||
|
||||
/* initialize reject file */
|
||||
init_reject(TMPREJNAME);
|
||||
|
||||
/* find out where all the lines are */
|
||||
if (!skip_rest_of_patch)
|
||||
scan_input(filearg[0]);
|
||||
|
||||
/* from here on, open no standard i/o files, because malloc */
|
||||
/* might misfire and we can't catch it easily */
|
||||
|
||||
/* apply each hunk of patch */
|
||||
hunk = 0;
|
||||
failed = 0;
|
||||
out_of_mem = FALSE;
|
||||
while (another_hunk()) {
|
||||
hunk++;
|
||||
fuzz = Nulline;
|
||||
mymaxfuzz = pch_context();
|
||||
if (maxfuzz < mymaxfuzz)
|
||||
mymaxfuzz = maxfuzz;
|
||||
if (!skip_rest_of_patch) {
|
||||
do {
|
||||
where = locate_hunk(fuzz);
|
||||
if (hunk == 1 && where == Nulline && !force) {
|
||||
/* dwim for reversed patch? */
|
||||
if (!pch_swap()) {
|
||||
if (fuzz == Nulline)
|
||||
say1("\
|
||||
Not enough memory to try swapped hunk! Assuming unswapped.\n");
|
||||
continue;
|
||||
}
|
||||
reverse = !reverse;
|
||||
where = locate_hunk(fuzz); /* try again */
|
||||
if (where == Nulline) { /* didn't find it swapped */
|
||||
if (!pch_swap()) /* put it back to normal */
|
||||
fatal1("Lost hunk on alloc error!\n");
|
||||
reverse = !reverse;
|
||||
}
|
||||
else if (noreverse) {
|
||||
if (!pch_swap()) /* put it back to normal */
|
||||
fatal1("Lost hunk on alloc error!\n");
|
||||
reverse = !reverse;
|
||||
say1("\
|
||||
Ignoring previously applied (or reversed) patch.\n");
|
||||
skip_rest_of_patch = TRUE;
|
||||
}
|
||||
else {
|
||||
ask3("\
|
||||
%seversed (or previously applied) patch detected! %s -R? [y] ",
|
||||
reverse ? "R" : "Unr",
|
||||
reverse ? "Assume" : "Ignore");
|
||||
if (*buf == 'n') {
|
||||
ask1("Apply anyway? [n] ");
|
||||
if (*buf != 'y')
|
||||
skip_rest_of_patch = TRUE;
|
||||
where = Nulline;
|
||||
reverse = !reverse;
|
||||
if (!pch_swap()) /* put it back to normal */
|
||||
fatal1("Lost hunk on alloc error!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (!skip_rest_of_patch && where == Nulline &&
|
||||
++fuzz <= mymaxfuzz);
|
||||
|
||||
if (skip_rest_of_patch) { /* just got decided */
|
||||
Fclose(ofp);
|
||||
ofp = Nullfp;
|
||||
}
|
||||
}
|
||||
|
||||
newwhere = pch_newfirst() + last_offset;
|
||||
if (skip_rest_of_patch) {
|
||||
abort_hunk();
|
||||
failed++;
|
||||
if (verbose)
|
||||
say3("Hunk #%d ignored at %ld.\n", hunk, newwhere);
|
||||
}
|
||||
else if (where == Nulline) {
|
||||
abort_hunk();
|
||||
failed++;
|
||||
if (verbose)
|
||||
say3("Hunk #%d failed at %ld.\n", hunk, newwhere);
|
||||
}
|
||||
else {
|
||||
apply_hunk(where);
|
||||
if (verbose) {
|
||||
say3("Hunk #%d succeeded at %ld", hunk, newwhere);
|
||||
if (fuzz)
|
||||
say2(" with fuzz %ld", fuzz);
|
||||
if (last_offset)
|
||||
say3(" (offset %ld line%s)",
|
||||
last_offset, last_offset==1L?"":"s");
|
||||
say1(".\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (out_of_mem && using_plan_a) {
|
||||
Argc = Argc_last;
|
||||
Argv = Argv_last;
|
||||
say1("\n\nRan out of memory using Plan A--trying again...\n\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(hunk);
|
||||
|
||||
/* finish spewing out the new file */
|
||||
if (!skip_rest_of_patch)
|
||||
spew_output();
|
||||
|
||||
/* and put the output where desired */
|
||||
ignore_signals();
|
||||
if (!skip_rest_of_patch) {
|
||||
if (move_file(TMPOUTNAME, outname) < 0) {
|
||||
toutkeep = TRUE;
|
||||
chmod(TMPOUTNAME, filemode);
|
||||
}
|
||||
else
|
||||
chmod(outname, filemode);
|
||||
}
|
||||
Fclose(rejfp);
|
||||
rejfp = Nullfp;
|
||||
if (failed) {
|
||||
if (!*rejname) {
|
||||
Strcpy(rejname, outname);
|
||||
Strcat(rejname, ".rej");
|
||||
}
|
||||
if (skip_rest_of_patch) {
|
||||
say4("%d out of %d hunks ignored--saving rejects to %s\n",
|
||||
failed, hunk, rejname);
|
||||
}
|
||||
else {
|
||||
say4("%d out of %d hunks failed--saving rejects to %s\n",
|
||||
failed, hunk, rejname);
|
||||
}
|
||||
if (move_file(TMPREJNAME, rejname) < 0)
|
||||
trejkeep = TRUE;
|
||||
}
|
||||
set_signals();
|
||||
}
|
||||
my_exit(0);
|
||||
}
|
||||
|
||||
/* Prepare to find the next patch to do in the patch file. */
|
||||
|
||||
void
|
||||
reinitialize_almost_everything()
|
||||
{
|
||||
re_patch();
|
||||
re_input();
|
||||
|
||||
input_lines = 0;
|
||||
last_frozen_line = 0;
|
||||
|
||||
filec = 0;
|
||||
if (filearg[0] != Nullch && !out_of_mem) {
|
||||
free(filearg[0]);
|
||||
filearg[0] = Nullch;
|
||||
}
|
||||
|
||||
if (outname != Nullch) {
|
||||
free(outname);
|
||||
outname = Nullch;
|
||||
}
|
||||
|
||||
last_offset = 0;
|
||||
|
||||
diff_type = 0;
|
||||
|
||||
if (revision != Nullch) {
|
||||
free(revision);
|
||||
revision = Nullch;
|
||||
}
|
||||
|
||||
reverse = FALSE;
|
||||
skip_rest_of_patch = FALSE;
|
||||
|
||||
get_some_switches();
|
||||
|
||||
if (filec >= 2)
|
||||
fatal1("You may not change to a different patch file.\n");
|
||||
}
|
||||
|
||||
/* Process switches and filenames up to next '+' or end of list. */
|
||||
|
||||
void
|
||||
get_some_switches()
|
||||
{
|
||||
Reg1 char *s;
|
||||
|
||||
rejname[0] = '\0';
|
||||
Argc_last = Argc;
|
||||
Argv_last = Argv;
|
||||
if (!Argc)
|
||||
return;
|
||||
for (Argc--,Argv++; Argc; Argc--,Argv++) {
|
||||
s = Argv[0];
|
||||
if (strEQ(s, "+")) {
|
||||
return; /* + will be skipped by for loop */
|
||||
}
|
||||
if (*s != '-' || !s[1]) {
|
||||
if (filec == MAXFILEC)
|
||||
fatal1("Too many file arguments.\n");
|
||||
filearg[filec++] = savestr(s);
|
||||
}
|
||||
else {
|
||||
switch (*++s) {
|
||||
case 'b':
|
||||
origext = savestr(Argv[1]);
|
||||
Argc--,Argv++;
|
||||
break;
|
||||
case 'c':
|
||||
diff_type = CONTEXT_DIFF;
|
||||
break;
|
||||
case 'd':
|
||||
if (!*++s) {
|
||||
Argc--,Argv++;
|
||||
s = Argv[0];
|
||||
}
|
||||
if (chdir(s) < 0)
|
||||
fatal2("Can't cd to %s.\n", s);
|
||||
break;
|
||||
case 'D':
|
||||
do_defines = TRUE;
|
||||
if (!*++s) {
|
||||
Argc--,Argv++;
|
||||
s = Argv[0];
|
||||
}
|
||||
Sprintf(if_defined, "#ifdef %s\n", s);
|
||||
Sprintf(not_defined, "#ifndef %s\n", s);
|
||||
Sprintf(end_defined, "#endif /* %s */\n", s);
|
||||
break;
|
||||
case 'e':
|
||||
diff_type = ED_DIFF;
|
||||
break;
|
||||
case 'f':
|
||||
force = TRUE;
|
||||
break;
|
||||
case 'F':
|
||||
if (*++s == '=')
|
||||
s++;
|
||||
maxfuzz = atoi(s);
|
||||
break;
|
||||
case 'l':
|
||||
canonicalize = TRUE;
|
||||
break;
|
||||
case 'n':
|
||||
diff_type = NORMAL_DIFF;
|
||||
break;
|
||||
case 'N':
|
||||
noreverse = TRUE;
|
||||
break;
|
||||
case 'o':
|
||||
outname = savestr(Argv[1]);
|
||||
Argc--,Argv++;
|
||||
break;
|
||||
case 'p':
|
||||
if (*++s == '=')
|
||||
s++;
|
||||
strippath = atoi(s);
|
||||
break;
|
||||
case 'r':
|
||||
Strcpy(rejname, Argv[1]);
|
||||
Argc--,Argv++;
|
||||
break;
|
||||
case 'R':
|
||||
reverse = TRUE;
|
||||
break;
|
||||
case 's':
|
||||
verbose = FALSE;
|
||||
break;
|
||||
case 'S':
|
||||
skip_rest_of_patch = TRUE;
|
||||
break;
|
||||
case 'v':
|
||||
version();
|
||||
break;
|
||||
#ifdef DEBUGGING
|
||||
case 'x':
|
||||
debug = atoi(s+1);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fatal2("Unrecognized switch: %s\n", Argv[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Attempt to find the right place to apply this hunk of patch. */
|
||||
|
||||
LINENUM
|
||||
locate_hunk(fuzz)
|
||||
LINENUM fuzz;
|
||||
{
|
||||
Reg1 LINENUM first_guess = pch_first() + last_offset;
|
||||
Reg2 LINENUM offset;
|
||||
LINENUM pat_lines = pch_ptrn_lines();
|
||||
Reg3 LINENUM max_pos_offset = input_lines - first_guess
|
||||
- pat_lines + 1;
|
||||
Reg4 LINENUM max_neg_offset = first_guess - last_frozen_line - 1
|
||||
+ pch_context();
|
||||
|
||||
if (!pat_lines) /* null range matches always */
|
||||
return first_guess;
|
||||
if (max_neg_offset >= first_guess) /* do not try lines < 0 */
|
||||
max_neg_offset = first_guess - 1;
|
||||
if (first_guess <= input_lines && patch_match(first_guess, Nulline, fuzz))
|
||||
return first_guess;
|
||||
for (offset = 1; ; offset++) {
|
||||
Reg5 bool check_after = (offset <= max_pos_offset);
|
||||
Reg6 bool check_before = (offset <= max_neg_offset);
|
||||
|
||||
if (check_after && patch_match(first_guess, offset, fuzz)) {
|
||||
#ifdef DEBUGGING
|
||||
if (debug & 1)
|
||||
say3("Offset changing from %ld to %ld\n", last_offset, offset);
|
||||
#endif
|
||||
last_offset = offset;
|
||||
return first_guess+offset;
|
||||
}
|
||||
else if (check_before && patch_match(first_guess, -offset, fuzz)) {
|
||||
#ifdef DEBUGGING
|
||||
if (debug & 1)
|
||||
say3("Offset changing from %ld to %ld\n", last_offset, -offset);
|
||||
#endif
|
||||
last_offset = -offset;
|
||||
return first_guess-offset;
|
||||
}
|
||||
else if (!check_before && !check_after)
|
||||
return Nulline;
|
||||
}
|
||||
}
|
||||
|
||||
/* We did not find the pattern, dump out the hunk so they can handle it. */
|
||||
|
||||
void
|
||||
abort_hunk()
|
||||
{
|
||||
Reg1 LINENUM i;
|
||||
Reg2 LINENUM pat_end = pch_end();
|
||||
/* add in last_offset to guess the same as the previous successful hunk */
|
||||
LINENUM oldfirst = pch_first() + last_offset;
|
||||
LINENUM newfirst = pch_newfirst() + last_offset;
|
||||
LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1;
|
||||
LINENUM newlast = newfirst + pch_repl_lines() - 1;
|
||||
char *stars = (diff_type == NEW_CONTEXT_DIFF ? " ****" : "");
|
||||
char *minuses = (diff_type == NEW_CONTEXT_DIFF ? " ----" : " -----");
|
||||
|
||||
fprintf(rejfp, "***************\n");
|
||||
for (i=0; i<=pat_end; i++) {
|
||||
switch (pch_char(i)) {
|
||||
case '*':
|
||||
if (oldlast < oldfirst)
|
||||
fprintf(rejfp, "*** 0%s\n", stars);
|
||||
else if (oldlast == oldfirst)
|
||||
fprintf(rejfp, "*** %ld%s\n", oldfirst, stars);
|
||||
else
|
||||
fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst, oldlast, stars);
|
||||
break;
|
||||
case '=':
|
||||
if (newlast < newfirst)
|
||||
fprintf(rejfp, "--- 0%s\n", minuses);
|
||||
else if (newlast == newfirst)
|
||||
fprintf(rejfp, "--- %ld%s\n", newfirst, minuses);
|
||||
else
|
||||
fprintf(rejfp, "--- %ld,%ld%s\n", newfirst, newlast, minuses);
|
||||
break;
|
||||
case '\n':
|
||||
fprintf(rejfp, "%s", pfetch(i));
|
||||
break;
|
||||
case ' ': case '-': case '+': case '!':
|
||||
fprintf(rejfp, "%c %s", pch_char(i), pfetch(i));
|
||||
break;
|
||||
default:
|
||||
say1("Fatal internal error in abort_hunk().\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We found where to apply it (we hope), so do it. */
|
||||
|
||||
void
|
||||
apply_hunk(where)
|
||||
LINENUM where;
|
||||
{
|
||||
Reg1 LINENUM old = 1;
|
||||
Reg2 LINENUM lastline = pch_ptrn_lines();
|
||||
Reg3 LINENUM new = lastline+1;
|
||||
#define OUTSIDE 0
|
||||
#define IN_IFNDEF 1
|
||||
#define IN_IFDEF 2
|
||||
#define IN_ELSE 3
|
||||
Reg4 int def_state = OUTSIDE;
|
||||
Reg5 bool R_do_defines = do_defines;
|
||||
Reg6 LINENUM pat_end = pch_end();
|
||||
|
||||
where--;
|
||||
while (pch_char(new) == '=' || pch_char(new) == '\n')
|
||||
new++;
|
||||
|
||||
while (old <= lastline) {
|
||||
if (pch_char(old) == '-') {
|
||||
copy_till(where + old - 1);
|
||||
if (R_do_defines) {
|
||||
if (def_state == OUTSIDE) {
|
||||
fputs(not_defined, ofp);
|
||||
def_state = IN_IFNDEF;
|
||||
}
|
||||
else if (def_state == IN_IFDEF) {
|
||||
fputs(else_defined, ofp);
|
||||
def_state = IN_ELSE;
|
||||
}
|
||||
fputs(pfetch(old), ofp);
|
||||
}
|
||||
last_frozen_line++;
|
||||
old++;
|
||||
}
|
||||
else if (new > pat_end)
|
||||
break;
|
||||
else if (pch_char(new) == '+') {
|
||||
copy_till(where + old - 1);
|
||||
if (R_do_defines) {
|
||||
if (def_state == IN_IFNDEF) {
|
||||
fputs(else_defined, ofp);
|
||||
def_state = IN_ELSE;
|
||||
}
|
||||
else if (def_state == OUTSIDE) {
|
||||
fputs(if_defined, ofp);
|
||||
def_state = IN_IFDEF;
|
||||
}
|
||||
}
|
||||
fputs(pfetch(new), ofp);
|
||||
new++;
|
||||
}
|
||||
else {
|
||||
if (pch_char(new) != pch_char(old)) {
|
||||
say3("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n",
|
||||
pch_hunk_beg() + old,
|
||||
pch_hunk_beg() + new);
|
||||
#ifdef DEBUGGING
|
||||
say3("oldchar = '%c', newchar = '%c'\n",
|
||||
pch_char(old), pch_char(new));
|
||||
#endif
|
||||
my_exit(1);
|
||||
}
|
||||
if (pch_char(new) == '!') {
|
||||
copy_till(where + old - 1);
|
||||
if (R_do_defines) {
|
||||
fputs(not_defined, ofp);
|
||||
def_state = IN_IFNDEF;
|
||||
}
|
||||
while (pch_char(old) == '!') {
|
||||
if (R_do_defines) {
|
||||
fputs(pfetch(old), ofp);
|
||||
}
|
||||
last_frozen_line++;
|
||||
old++;
|
||||
}
|
||||
if (R_do_defines) {
|
||||
fputs(else_defined, ofp);
|
||||
def_state = IN_ELSE;
|
||||
}
|
||||
while (pch_char(new) == '!') {
|
||||
fputs(pfetch(new), ofp);
|
||||
new++;
|
||||
}
|
||||
if (R_do_defines) {
|
||||
fputs(end_defined, ofp);
|
||||
def_state = OUTSIDE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(pch_char(new) == ' ');
|
||||
old++;
|
||||
new++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (new <= pat_end && pch_char(new) == '+') {
|
||||
copy_till(where + old - 1);
|
||||
if (R_do_defines) {
|
||||
if (def_state == OUTSIDE) {
|
||||
fputs(if_defined, ofp);
|
||||
def_state = IN_IFDEF;
|
||||
}
|
||||
else if (def_state == IN_IFNDEF) {
|
||||
fputs(else_defined, ofp);
|
||||
def_state = IN_ELSE;
|
||||
}
|
||||
}
|
||||
while (new <= pat_end && pch_char(new) == '+') {
|
||||
fputs(pfetch(new), ofp);
|
||||
new++;
|
||||
}
|
||||
}
|
||||
if (R_do_defines && def_state != OUTSIDE) {
|
||||
fputs(end_defined, ofp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Open the new file. */
|
||||
|
||||
void
|
||||
init_output(name)
|
||||
char *name;
|
||||
{
|
||||
ofp = fopen(name, "w");
|
||||
if (ofp == Nullfp)
|
||||
fatal2("patch: can't create %s.\n", name);
|
||||
}
|
||||
|
||||
/* Open a file to put hunks we can't locate. */
|
||||
|
||||
void
|
||||
init_reject(name)
|
||||
char *name;
|
||||
{
|
||||
rejfp = fopen(name, "w");
|
||||
if (rejfp == Nullfp)
|
||||
fatal2("patch: can't create %s.\n", name);
|
||||
}
|
||||
|
||||
/* Copy input file to output, up to wherever hunk is to be applied. */
|
||||
|
||||
void
|
||||
copy_till(lastline)
|
||||
Reg1 LINENUM lastline;
|
||||
{
|
||||
Reg2 LINENUM R_last_frozen_line = last_frozen_line;
|
||||
|
||||
if (R_last_frozen_line > lastline)
|
||||
say1("patch: misordered hunks! output will be garbled.\n");
|
||||
while (R_last_frozen_line < lastline) {
|
||||
dump_line(++R_last_frozen_line);
|
||||
}
|
||||
last_frozen_line = R_last_frozen_line;
|
||||
}
|
||||
|
||||
/* Finish copying the input file to the output file. */
|
||||
|
||||
void
|
||||
spew_output()
|
||||
{
|
||||
#ifdef DEBUGGING
|
||||
if (debug & 256)
|
||||
say3("il=%ld lfl=%ld\n",input_lines,last_frozen_line);
|
||||
#endif
|
||||
if (input_lines)
|
||||
copy_till(input_lines); /* dump remainder of file */
|
||||
Fclose(ofp);
|
||||
ofp = Nullfp;
|
||||
}
|
||||
|
||||
/* Copy one line from input to output. */
|
||||
|
||||
void
|
||||
dump_line(line)
|
||||
LINENUM line;
|
||||
{
|
||||
Reg1 char *s;
|
||||
Reg2 char R_newline = '\n';
|
||||
|
||||
/* Note: string is not null terminated. */
|
||||
for (s=ifetch(line, 0); putc(*s, ofp) != R_newline; s++) ;
|
||||
}
|
||||
|
||||
/* Does the patch pattern match at line base+offset? */
|
||||
|
||||
bool
|
||||
patch_match(base, offset, fuzz)
|
||||
LINENUM base;
|
||||
LINENUM offset;
|
||||
LINENUM fuzz;
|
||||
{
|
||||
Reg1 LINENUM pline = 1 + fuzz;
|
||||
Reg2 LINENUM iline;
|
||||
Reg3 LINENUM pat_lines = pch_ptrn_lines() - fuzz;
|
||||
|
||||
for (iline=base+offset+fuzz; pline <= pat_lines; pline++,iline++) {
|
||||
if (canonicalize) {
|
||||
if (!similar(ifetch(iline, (offset >= 0)),
|
||||
pfetch(pline),
|
||||
pch_line_len(pline) ))
|
||||
return FALSE;
|
||||
}
|
||||
else if (strnNE(ifetch(iline, (offset >= 0)),
|
||||
pfetch(pline),
|
||||
pch_line_len(pline) ))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Do two lines match with canonicalized white space? */
|
||||
|
||||
bool
|
||||
similar(a,b,len)
|
||||
Reg1 char *a;
|
||||
Reg2 char *b;
|
||||
Reg3 int len;
|
||||
{
|
||||
while (len) {
|
||||
if (isspace(*b)) { /* whitespace (or \n) to match? */
|
||||
if (!isspace(*a)) /* no corresponding whitespace? */
|
||||
return FALSE;
|
||||
while (len && isspace(*b) && *b != '\n')
|
||||
b++,len--; /* skip pattern whitespace */
|
||||
while (isspace(*a) && *a != '\n')
|
||||
a++; /* skip target whitespace */
|
||||
if (*a == '\n' || *b == '\n')
|
||||
return (*a == *b); /* should end in sync */
|
||||
}
|
||||
else if (*a++ != *b++) /* match non-whitespace chars */
|
||||
return FALSE;
|
||||
else
|
||||
len--; /* probably not necessary */
|
||||
}
|
||||
return TRUE; /* actually, this is not reached */
|
||||
/* since there is always a \n */
|
||||
}
|
||||
|
||||
/* Exit with cleanup. */
|
||||
|
||||
void
|
||||
my_exit(status)
|
||||
int status;
|
||||
{
|
||||
Unlink(TMPINNAME);
|
||||
if (!toutkeep) {
|
||||
Unlink(TMPOUTNAME);
|
||||
}
|
||||
if (!trejkeep) {
|
||||
Unlink(TMPREJNAME);
|
||||
}
|
||||
Unlink(TMPPATNAME);
|
||||
exit(status);
|
||||
}
|
1
usr.bin/patch/patchlevel.h
Normal file
1
usr.bin/patch/patchlevel.h
Normal file
@ -0,0 +1 @@
|
||||
#define PATCHLEVEL 9
|
1108
usr.bin/patch/pch.c
Normal file
1108
usr.bin/patch/pch.c
Normal file
File diff suppressed because it is too large
Load Diff
36
usr.bin/patch/pch.h
Normal file
36
usr.bin/patch/pch.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* $Header: pch.h,v 2.0.1.1 87/01/30 22:47:16 lwall Exp $
|
||||
*
|
||||
* $Log: pch.h,v $
|
||||
* Revision 2.0.1.1 87/01/30 22:47:16 lwall
|
||||
* Added do_ed_script().
|
||||
*
|
||||
* Revision 2.0 86/09/17 15:39:57 lwall
|
||||
* Baseline for netwide release.
|
||||
*
|
||||
*/
|
||||
|
||||
EXT FILE *pfp INIT(Nullfp); /* patch file pointer */
|
||||
|
||||
void re_patch();
|
||||
void open_patch_file();
|
||||
void set_hunkmax();
|
||||
void grow_hunkmax();
|
||||
bool there_is_another_patch();
|
||||
int intuit_diff_type();
|
||||
void next_intuit_at();
|
||||
void skip_to();
|
||||
bool another_hunk();
|
||||
bool pch_swap();
|
||||
char *pfetch();
|
||||
short pch_line_len();
|
||||
LINENUM pch_first();
|
||||
LINENUM pch_ptrn_lines();
|
||||
LINENUM pch_newfirst();
|
||||
LINENUM pch_repl_lines();
|
||||
LINENUM pch_end();
|
||||
LINENUM pch_context();
|
||||
LINENUM pch_hunk_beg();
|
||||
char pch_char();
|
||||
char *pfetch();
|
||||
char *pgets();
|
||||
void do_ed_script();
|
339
usr.bin/patch/util.c
Normal file
339
usr.bin/patch/util.c
Normal file
@ -0,0 +1,339 @@
|
||||
#include "EXTERN.h"
|
||||
#include "common.h"
|
||||
#include "INTERN.h"
|
||||
#include "util.h"
|
||||
|
||||
/* Rename a file, copying it if necessary. */
|
||||
|
||||
int
|
||||
move_file(from,to)
|
||||
char *from, *to;
|
||||
{
|
||||
char bakname[512];
|
||||
Reg1 char *s;
|
||||
Reg2 int i;
|
||||
Reg3 int fromfd;
|
||||
|
||||
/* to stdout? */
|
||||
|
||||
if (strEQ(to, "-")) {
|
||||
#ifdef DEBUGGING
|
||||
if (debug & 4)
|
||||
say2("Moving %s to stdout.\n", from);
|
||||
#endif
|
||||
fromfd = open(from, 0);
|
||||
if (fromfd < 0)
|
||||
fatal2("patch: internal error, can't reopen %s\n", from);
|
||||
while ((i=read(fromfd, buf, sizeof buf)) > 0)
|
||||
if (write(1, buf, i) != 1)
|
||||
fatal1("patch: write failed\n");
|
||||
Close(fromfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Strcpy(bakname, to);
|
||||
Strcat(bakname, origext?origext:ORIGEXT);
|
||||
if (stat(to, &filestat) >= 0) { /* output file exists */
|
||||
dev_t to_device = filestat.st_dev;
|
||||
ino_t to_inode = filestat.st_ino;
|
||||
char *simplename = bakname;
|
||||
|
||||
for (s=bakname; *s; s++) {
|
||||
if (*s == '/')
|
||||
simplename = s+1;
|
||||
}
|
||||
/* find a backup name that is not the same file */
|
||||
while (stat(bakname, &filestat) >= 0 &&
|
||||
to_device == filestat.st_dev && to_inode == filestat.st_ino) {
|
||||
for (s=simplename; *s && !islower(*s); s++) ;
|
||||
if (*s)
|
||||
*s = toupper(*s);
|
||||
else
|
||||
Strcpy(simplename, simplename+1);
|
||||
}
|
||||
while (unlink(bakname) >= 0) ; /* while() is for benefit of Eunice */
|
||||
#ifdef DEBUGGING
|
||||
if (debug & 4)
|
||||
say3("Moving %s to %s.\n", to, bakname);
|
||||
#endif
|
||||
if (link(to, bakname) < 0) {
|
||||
say3("patch: can't backup %s, output is in %s\n",
|
||||
to, from);
|
||||
return -1;
|
||||
}
|
||||
while (unlink(to) >= 0) ;
|
||||
}
|
||||
#ifdef DEBUGGING
|
||||
if (debug & 4)
|
||||
say3("Moving %s to %s.\n", from, to);
|
||||
#endif
|
||||
if (link(from, to) < 0) { /* different file system? */
|
||||
Reg4 int tofd;
|
||||
|
||||
tofd = creat(to, 0666);
|
||||
if (tofd < 0) {
|
||||
say3("patch: can't create %s, output is in %s.\n",
|
||||
to, from);
|
||||
return -1;
|
||||
}
|
||||
fromfd = open(from, 0);
|
||||
if (fromfd < 0)
|
||||
fatal2("patch: internal error, can't reopen %s\n", from);
|
||||
while ((i=read(fromfd, buf, sizeof buf)) > 0)
|
||||
if (write(tofd, buf, i) != i)
|
||||
fatal1("patch: write failed\n");
|
||||
Close(fromfd);
|
||||
Close(tofd);
|
||||
}
|
||||
Unlink(from);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy a file. */
|
||||
|
||||
void
|
||||
copy_file(from,to)
|
||||
char *from, *to;
|
||||
{
|
||||
Reg3 int tofd;
|
||||
Reg2 int fromfd;
|
||||
Reg1 int i;
|
||||
|
||||
tofd = creat(to, 0666);
|
||||
if (tofd < 0)
|
||||
fatal2("patch: can't create %s.\n", to);
|
||||
fromfd = open(from, 0);
|
||||
if (fromfd < 0)
|
||||
fatal2("patch: internal error, can't reopen %s\n", from);
|
||||
while ((i=read(fromfd, buf, sizeof buf)) > 0)
|
||||
if (write(tofd, buf, i) != i)
|
||||
fatal2("patch: write (%s) failed\n", to);
|
||||
Close(fromfd);
|
||||
Close(tofd);
|
||||
}
|
||||
|
||||
/* Allocate a unique area for a string. */
|
||||
|
||||
char *
|
||||
savestr(s)
|
||||
Reg1 char *s;
|
||||
{
|
||||
Reg3 char *rv;
|
||||
Reg2 char *t;
|
||||
|
||||
if (!s)
|
||||
s = "Oops";
|
||||
t = s;
|
||||
while (*t++);
|
||||
rv = malloc((MEM) (t - s));
|
||||
if (rv == Nullch) {
|
||||
if (using_plan_a)
|
||||
out_of_mem = TRUE;
|
||||
else
|
||||
fatal1("patch: out of memory (savestr)\n");
|
||||
}
|
||||
else {
|
||||
t = rv;
|
||||
while (*t++ = *s++);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
#if defined(lint) && defined(CANVARARG)
|
||||
|
||||
/*VARARGS ARGSUSED*/
|
||||
say(pat) char *pat; { ; }
|
||||
/*VARARGS ARGSUSED*/
|
||||
fatal(pat) char *pat; { ; }
|
||||
/*VARARGS ARGSUSED*/
|
||||
ask(pat) char *pat; { ; }
|
||||
|
||||
#else
|
||||
|
||||
/* Vanilla terminal output (buffered). */
|
||||
|
||||
void
|
||||
say(pat,arg1,arg2,arg3)
|
||||
char *pat;
|
||||
int arg1,arg2,arg3;
|
||||
{
|
||||
fprintf(stderr, pat, arg1, arg2, arg3);
|
||||
Fflush(stderr);
|
||||
}
|
||||
|
||||
/* Terminal output, pun intended. */
|
||||
|
||||
void /* very void */
|
||||
fatal(pat,arg1,arg2,arg3)
|
||||
char *pat;
|
||||
int arg1,arg2,arg3;
|
||||
{
|
||||
void my_exit();
|
||||
|
||||
say(pat, arg1, arg2, arg3);
|
||||
my_exit(1);
|
||||
}
|
||||
|
||||
/* Get a response from the user, somehow or other. */
|
||||
|
||||
void
|
||||
ask(pat,arg1,arg2,arg3)
|
||||
char *pat;
|
||||
int arg1,arg2,arg3;
|
||||
{
|
||||
int ttyfd;
|
||||
int r;
|
||||
bool tty2 = isatty(2);
|
||||
|
||||
Sprintf(buf, pat, arg1, arg2, arg3);
|
||||
Fflush(stderr);
|
||||
write(2, buf, strlen(buf));
|
||||
if (tty2) { /* might be redirected to a file */
|
||||
r = read(2, buf, sizeof buf);
|
||||
}
|
||||
else if (isatty(1)) { /* this may be new file output */
|
||||
Fflush(stdout);
|
||||
write(1, buf, strlen(buf));
|
||||
r = read(1, buf, sizeof buf);
|
||||
}
|
||||
else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
|
||||
/* might be deleted or unwriteable */
|
||||
write(ttyfd, buf, strlen(buf));
|
||||
r = read(ttyfd, buf, sizeof buf);
|
||||
Close(ttyfd);
|
||||
}
|
||||
else if (isatty(0)) { /* this is probably patch input */
|
||||
Fflush(stdin);
|
||||
write(0, buf, strlen(buf));
|
||||
r = read(0, buf, sizeof buf);
|
||||
}
|
||||
else { /* no terminal at all--default it */
|
||||
buf[0] = '\n';
|
||||
r = 1;
|
||||
}
|
||||
if (r <= 0)
|
||||
buf[0] = 0;
|
||||
else
|
||||
buf[r] = '\0';
|
||||
if (!tty2)
|
||||
say1(buf);
|
||||
}
|
||||
#endif lint
|
||||
|
||||
/* How to handle certain events when not in a critical region. */
|
||||
|
||||
void
|
||||
set_signals()
|
||||
{
|
||||
void my_exit();
|
||||
|
||||
#ifndef lint
|
||||
if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
|
||||
Signal(SIGHUP, my_exit);
|
||||
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
|
||||
Signal(SIGINT, my_exit);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* How to handle certain events when in a critical region. */
|
||||
|
||||
void
|
||||
ignore_signals()
|
||||
{
|
||||
#ifndef lint
|
||||
Signal(SIGHUP, SIG_IGN);
|
||||
Signal(SIGINT, SIG_IGN);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Make sure we'll have the directories to create a file. */
|
||||
|
||||
void
|
||||
makedirs(filename,striplast)
|
||||
Reg1 char *filename;
|
||||
bool striplast;
|
||||
{
|
||||
char tmpbuf[256];
|
||||
Reg2 char *s = tmpbuf;
|
||||
char *dirv[20];
|
||||
Reg3 int i;
|
||||
Reg4 int dirvp = 0;
|
||||
|
||||
while (*filename) {
|
||||
if (*filename == '/') {
|
||||
filename++;
|
||||
dirv[dirvp++] = s;
|
||||
*s++ = '\0';
|
||||
}
|
||||
else {
|
||||
*s++ = *filename++;
|
||||
}
|
||||
}
|
||||
*s = '\0';
|
||||
dirv[dirvp] = s;
|
||||
if (striplast)
|
||||
dirvp--;
|
||||
if (dirvp < 0)
|
||||
return;
|
||||
strcpy(buf, "mkdir");
|
||||
s = buf;
|
||||
for (i=0; i<=dirvp; i++) {
|
||||
while (*s) s++;
|
||||
*s++ = ' ';
|
||||
strcpy(s, tmpbuf);
|
||||
*dirv[i] = '/';
|
||||
}
|
||||
system(buf);
|
||||
}
|
||||
|
||||
/* Make filenames more reasonable. */
|
||||
|
||||
char *
|
||||
fetchname(at,strip_leading,assume_exists)
|
||||
char *at;
|
||||
int strip_leading;
|
||||
int assume_exists;
|
||||
{
|
||||
char *s;
|
||||
char *name;
|
||||
Reg1 char *t;
|
||||
char tmpbuf[200];
|
||||
|
||||
if (!at)
|
||||
return Nullch;
|
||||
s = savestr(at);
|
||||
for (t=s; isspace(*t); t++) ;
|
||||
name = t;
|
||||
#ifdef DEBUGGING
|
||||
if (debug & 128)
|
||||
say4("fetchname %s %d %d\n",name,strip_leading,assume_exists);
|
||||
#endif
|
||||
if (strnEQ(name, "/dev/null", 9)) /* so files can be created by diffing */
|
||||
return Nullch; /* against /dev/null. */
|
||||
for (; *t && !isspace(*t); t++)
|
||||
if (*t == '/')
|
||||
if (--strip_leading >= 0)
|
||||
name = t+1;
|
||||
*t = '\0';
|
||||
if (name != s && *s != '/') {
|
||||
name[-1] = '\0';
|
||||
if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) {
|
||||
name[-1] = '/';
|
||||
name=s;
|
||||
}
|
||||
}
|
||||
name = savestr(name);
|
||||
Sprintf(tmpbuf, "RCS/%s", name);
|
||||
free(s);
|
||||
if (stat(name, &filestat) < 0 && !assume_exists) {
|
||||
Strcat(tmpbuf, RCSSUFFIX);
|
||||
if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) {
|
||||
Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name);
|
||||
if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) {
|
||||
free(name);
|
||||
name = Nullch;
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
74
usr.bin/patch/util.h
Normal file
74
usr.bin/patch/util.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* $Header: util.h,v 2.0 86/09/17 15:40:06 lwall Exp $
|
||||
*
|
||||
* $Log: util.h,v $
|
||||
* Revision 2.0 86/09/17 15:40:06 lwall
|
||||
* Baseline for netwide release.
|
||||
*
|
||||
*/
|
||||
|
||||
/* and for those machine that can't handle a variable argument list */
|
||||
|
||||
#ifdef CANVARARG
|
||||
|
||||
#define say1 say
|
||||
#define say2 say
|
||||
#define say3 say
|
||||
#define say4 say
|
||||
#define ask1 ask
|
||||
#define ask2 ask
|
||||
#define ask3 ask
|
||||
#define ask4 ask
|
||||
#define fatal1 fatal
|
||||
#define fatal2 fatal
|
||||
#define fatal3 fatal
|
||||
#define fatal4 fatal
|
||||
|
||||
#else /* hope they allow multi-line macro actual arguments */
|
||||
|
||||
#ifdef lint
|
||||
|
||||
#define say1(a) say(a, 0, 0, 0)
|
||||
#define say2(a,b) say(a, (b)==(b), 0, 0)
|
||||
#define say3(a,b,c) say(a, (b)==(b), (c)==(c), 0)
|
||||
#define say4(a,b,c,d) say(a, (b)==(b), (c)==(c), (d)==(d))
|
||||
#define ask1(a) ask(a, 0, 0, 0)
|
||||
#define ask2(a,b) ask(a, (b)==(b), 0, 0)
|
||||
#define ask3(a,b,c) ask(a, (b)==(b), (c)==(c), 0)
|
||||
#define ask4(a,b,c,d) ask(a, (b)==(b), (c)==(c), (d)==(d))
|
||||
#define fatal1(a) fatal(a, 0, 0, 0)
|
||||
#define fatal2(a,b) fatal(a, (b)==(b), 0, 0)
|
||||
#define fatal3(a,b,c) fatal(a, (b)==(b), (c)==(c), 0)
|
||||
#define fatal4(a,b,c,d) fatal(a, (b)==(b), (c)==(c), (d)==(d))
|
||||
|
||||
#else /* lint */
|
||||
/* if this doesn't work, try defining CANVARARG above */
|
||||
#define say1(a) say(a, Nullch, Nullch, Nullch)
|
||||
#define say2(a,b) say(a, b, Nullch, Nullch)
|
||||
#define say3(a,b,c) say(a, b, c, Nullch)
|
||||
#define say4 say
|
||||
#define ask1(a) ask(a, Nullch, Nullch, Nullch)
|
||||
#define ask2(a,b) ask(a, b, Nullch, Nullch)
|
||||
#define ask3(a,b,c) ask(a, b, c, Nullch)
|
||||
#define ask4 ask
|
||||
#define fatal1(a) fatal(a, Nullch, Nullch, Nullch)
|
||||
#define fatal2(a,b) fatal(a, b, Nullch, Nullch)
|
||||
#define fatal3(a,b,c) fatal(a, b, c, Nullch)
|
||||
#define fatal4 fatal
|
||||
|
||||
#endif /* lint */
|
||||
|
||||
/* if neither of the above work, join all multi-line macro calls. */
|
||||
#endif
|
||||
|
||||
EXT char serrbuf[BUFSIZ]; /* buffer for stderr */
|
||||
|
||||
char *fetchname();
|
||||
int move_file();
|
||||
void copy_file();
|
||||
void say();
|
||||
void fatal();
|
||||
void ask();
|
||||
char *savestr();
|
||||
void set_signals();
|
||||
void ignore_signals();
|
||||
void makedirs();
|
28
usr.bin/patch/version.c
Normal file
28
usr.bin/patch/version.c
Normal file
@ -0,0 +1,28 @@
|
||||
/* $Header: version.c,v 2.0 86/09/17 15:40:11 lwall Exp $
|
||||
*
|
||||
* $Log: version.c,v $
|
||||
* Revision 2.0 86/09/17 15:40:11 lwall
|
||||
* Baseline for netwide release.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "EXTERN.h"
|
||||
#include "common.h"
|
||||
#include "util.h"
|
||||
#include "INTERN.h"
|
||||
#include "patchlevel.h"
|
||||
#include "version.h"
|
||||
|
||||
/* Print out the version number and die. */
|
||||
|
||||
void
|
||||
version()
|
||||
{
|
||||
extern char rcsid[];
|
||||
|
||||
#ifdef lint
|
||||
rcsid[0] = rcsid[0];
|
||||
#else
|
||||
fatal3("%s\nPatch level: %d\n", rcsid, PATCHLEVEL);
|
||||
#endif
|
||||
}
|
9
usr.bin/patch/version.h
Normal file
9
usr.bin/patch/version.h
Normal file
@ -0,0 +1,9 @@
|
||||
/* $Header: version.h,v 2.0 86/09/17 15:40:14 lwall Exp $
|
||||
*
|
||||
* $Log: version.h,v $
|
||||
* Revision 2.0 86/09/17 15:40:14 lwall
|
||||
* Baseline for netwide release.
|
||||
*
|
||||
*/
|
||||
|
||||
void version();
|
70
usr.bin/ranlib/ranlib.5.5
Normal file
70
usr.bin/ranlib/ranlib.5.5
Normal file
@ -0,0 +1,70 @@
|
||||
.\" Copyright (c) 1990, 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.
|
||||
.\"
|
||||
.\" @(#)ranlib.5.5 8.1 (Berkeley) 6/6/93
|
||||
.\"
|
||||
.Dd June 6, 1993
|
||||
.Dt RANLIB 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ranlib
|
||||
.Nd archive (library) table-of-contents format
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <ranlib.h>
|
||||
.Sh DESCRIPTION
|
||||
The archive table-of-contents command
|
||||
.Nm ranlib
|
||||
creates a table of contents for archives, containing object files, to
|
||||
be used by the link-editor
|
||||
.Xr ld 1 .
|
||||
It operates on archives created with the utility
|
||||
.Xr ar 1 .
|
||||
.Pp
|
||||
The
|
||||
.Nm Ranlib
|
||||
function
|
||||
prepends a new file to the archive which has three separate parts.
|
||||
The first part is a standard archive header, which has a special name
|
||||
field, "__.SYMDEF".
|
||||
.Pp
|
||||
The second part is a ``long'' followed by a list of ranlib structures.
|
||||
The long is the size, in bytes, of the list of ranlib structures.
|
||||
Each of the ranlib structures consists of a zero based offset into the
|
||||
next section (a string table of symbols) and an offset from the beginning
|
||||
of the archive to the start of the archive file which defines the symbol.
|
||||
The actual number of ranlib structures is this number divided by the size
|
||||
of an individual ranlib structure.
|
||||
.Pp
|
||||
The third part is a ``long'' followed by a string table.
|
||||
The long is the size, in bytes of the string table.
|
||||
.Sh SEE ALSO
|
||||
.Xr ar 1 ,
|
||||
.Xr ranlib 1
|
203
usr.bin/rlogin/des_rw.c
Normal file
203
usr.bin/rlogin/des_rw.c
Normal file
@ -0,0 +1,203 @@
|
||||
/*-
|
||||
* 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[] = "@(#)des_rw.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifdef CRYPT
|
||||
#ifdef KERBEROS
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <kerberosIV/des.h>
|
||||
#include <kerberosIV/krb.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static unsigned char des_inbuf[10240], storage[10240], *store_ptr;
|
||||
static bit_64 *key;
|
||||
static u_char *key_schedule;
|
||||
|
||||
/* XXX these should be in a kerberos include file */
|
||||
int krb_net_read __P((int, char *, int));
|
||||
#ifdef notdef
|
||||
/* XXX too hard to make this work */
|
||||
int des_pcbc_encrypt __P((des_cblock *, des_cblock *, long,
|
||||
des_key_schedule, des_cblock *, int));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NB: These routines will not function properly if NBIO
|
||||
* is set
|
||||
*/
|
||||
|
||||
/*
|
||||
* des_set_key
|
||||
*
|
||||
* Set des encryption/decryption key for use by the des_read and
|
||||
* des_write routines
|
||||
*
|
||||
* The inkey parameter is actually the DES initial vector,
|
||||
* and the insched is the DES Key unwrapped for faster decryption
|
||||
*/
|
||||
|
||||
void
|
||||
des_set_key(inkey, insched)
|
||||
bit_64 *inkey;
|
||||
u_char *insched;
|
||||
{
|
||||
key = inkey;
|
||||
key_schedule = insched;
|
||||
}
|
||||
|
||||
void
|
||||
des_clear_key()
|
||||
{
|
||||
bzero((char *) key, sizeof(C_Block));
|
||||
bzero((char *) key_schedule, sizeof(Key_schedule));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
des_read(fd, buf, len)
|
||||
int fd;
|
||||
register char *buf;
|
||||
int len;
|
||||
{
|
||||
int nreturned = 0;
|
||||
long net_len, rd_len;
|
||||
int nstored = 0;
|
||||
|
||||
if (nstored >= len) {
|
||||
(void) bcopy(store_ptr, buf, len);
|
||||
store_ptr += len;
|
||||
nstored -= len;
|
||||
return(len);
|
||||
} else if (nstored) {
|
||||
(void) bcopy(store_ptr, buf, nstored);
|
||||
nreturned += nstored;
|
||||
buf += nstored;
|
||||
len -= nstored;
|
||||
nstored = 0;
|
||||
}
|
||||
|
||||
if (krb_net_read(fd, (char *)&net_len, sizeof(net_len)) !=
|
||||
sizeof(net_len)) {
|
||||
/* XXX can't read enough, pipe
|
||||
must have closed */
|
||||
return(0);
|
||||
}
|
||||
net_len = ntohl(net_len);
|
||||
if (net_len <= 0 || net_len > sizeof(des_inbuf)) {
|
||||
/* preposterous length; assume out-of-sync; only
|
||||
recourse is to close connection, so return 0 */
|
||||
return(0);
|
||||
}
|
||||
/* the writer tells us how much real data we are getting, but
|
||||
we need to read the pad bytes (8-byte boundary) */
|
||||
rd_len = roundup(net_len, 8);
|
||||
if (krb_net_read(fd, (char *)des_inbuf, rd_len) != rd_len) {
|
||||
/* pipe must have closed, return 0 */
|
||||
return(0);
|
||||
}
|
||||
(void) des_pcbc_encrypt(des_inbuf, /* inbuf */
|
||||
storage, /* outbuf */
|
||||
net_len, /* length */
|
||||
key_schedule, /* DES key */
|
||||
key, /* IV */
|
||||
DECRYPT); /* direction */
|
||||
|
||||
if(net_len < 8)
|
||||
store_ptr = storage + 8 - net_len;
|
||||
else
|
||||
store_ptr = storage;
|
||||
|
||||
nstored = net_len;
|
||||
if (nstored > len) {
|
||||
(void) bcopy(store_ptr, buf, len);
|
||||
nreturned += len;
|
||||
store_ptr += len;
|
||||
nstored -= len;
|
||||
} else {
|
||||
(void) bcopy(store_ptr, buf, nstored);
|
||||
nreturned += nstored;
|
||||
nstored = 0;
|
||||
}
|
||||
|
||||
return(nreturned);
|
||||
}
|
||||
|
||||
static unsigned char des_outbuf[10240]; /* > longest write */
|
||||
|
||||
int
|
||||
des_write(fd, buf, len)
|
||||
int fd;
|
||||
char *buf;
|
||||
int len;
|
||||
{
|
||||
static int seeded = 0;
|
||||
static char garbage_buf[8];
|
||||
long net_len, garbage;
|
||||
|
||||
if(len < 8) {
|
||||
if(!seeded) {
|
||||
seeded = 1;
|
||||
srandom((int) time((long *)0));
|
||||
}
|
||||
garbage = random();
|
||||
/* insert random garbage */
|
||||
(void) bcopy(&garbage, garbage_buf, MIN(sizeof(long),8));
|
||||
/* this "right-justifies" the data in the buffer */
|
||||
(void) bcopy(buf, garbage_buf + 8 - len, len);
|
||||
}
|
||||
/* pcbc_encrypt outputs in 8-byte (64 bit) increments */
|
||||
|
||||
(void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf,
|
||||
des_outbuf,
|
||||
(len < 8) ? 8 : len,
|
||||
key_schedule, /* DES key */
|
||||
key, /* IV */
|
||||
ENCRYPT);
|
||||
|
||||
/* tell the other end the real amount, but send an 8-byte padded
|
||||
packet */
|
||||
net_len = htonl(len);
|
||||
(void) write(fd, &net_len, sizeof(net_len));
|
||||
(void) write(fd, des_outbuf, roundup(len,8));
|
||||
return(len);
|
||||
}
|
||||
#endif /* KERBEROS */
|
||||
#endif /* CRYPT */
|
5
usr.bin/sccs/Makefile
Normal file
5
usr.bin/sccs/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= sccs
|
||||
|
||||
.include <bsd.prog.mk>
|
7
usr.bin/sccs/PSD.doc/Makefile
Normal file
7
usr.bin/sccs/PSD.doc/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
# @(#)Makefile 8.2 (Berkeley) 5/23/94
|
||||
|
||||
DIR= psd/14.sccs
|
||||
SRCS= sccs.me
|
||||
MACROS= -me
|
||||
|
||||
.include <bsd.doc.mk>
|
1609
usr.bin/sccs/PSD.doc/sccs.me
Normal file
1609
usr.bin/sccs/PSD.doc/sccs.me
Normal file
File diff suppressed because it is too large
Load Diff
77
usr.bin/sccs/PSD.doc/spell.ok
Normal file
77
usr.bin/sccs/PSD.doc/spell.ok
Normal file
@ -0,0 +1,77 @@
|
||||
AccessSid
|
||||
Admin
|
||||
Allman
|
||||
Berkeley.Edu
|
||||
Delget
|
||||
Ingres
|
||||
LDFLAGS
|
||||
LIB
|
||||
LIBS
|
||||
OBJS
|
||||
OpsysSid
|
||||
PS1:14
|
||||
PWB
|
||||
REL
|
||||
SCCS
|
||||
SID
|
||||
SRCS
|
||||
Sccs
|
||||
SccsId
|
||||
System''PS1:14
|
||||
TARG
|
||||
a.c
|
||||
a.o
|
||||
a.out
|
||||
access.h
|
||||
admin
|
||||
b.c
|
||||
b.o
|
||||
backslash
|
||||
bi
|
||||
c.c
|
||||
c.o
|
||||
c.y
|
||||
ch
|
||||
cm7
|
||||
cmd
|
||||
cs
|
||||
d.o
|
||||
d.s
|
||||
deledit
|
||||
delget
|
||||
eric
|
||||
example.c
|
||||
example.o
|
||||
fb
|
||||
fd1
|
||||
foreach
|
||||
g.c
|
||||
info
|
||||
inline
|
||||
john
|
||||
lib
|
||||
lib.a
|
||||
makefile
|
||||
makefiles
|
||||
mod
|
||||
mothballed
|
||||
newxyz
|
||||
ok
|
||||
opsys.h
|
||||
prog
|
||||
prog.c
|
||||
prog.h
|
||||
prog.o
|
||||
prt
|
||||
rvu
|
||||
sccs
|
||||
sccsdiff
|
||||
src
|
||||
syssccs
|
||||
t.c
|
||||
ujohn
|
||||
who.c
|
||||
x.h
|
||||
xyz
|
||||
y.h
|
||||
z.h
|
51
usr.bin/sccs/pathnames.h
Normal file
51
usr.bin/sccs/pathnames.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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/6/93
|
||||
*/
|
||||
|
||||
#include <paths.h>
|
||||
|
||||
#define _PATH_SCCSADMIN "/usr/local/bin/admin"
|
||||
#define _PATH_SCCSBDIFF "/usr/local/bin/bdiff"
|
||||
#define _PATH_SCCSCOMB "/usr/local/bin/comb"
|
||||
#define _PATH_SCCSDELTA "/usr/local/bin/delta"
|
||||
#define _PATH_SCCSDIFF "/usr/local/bin/sccsdiff"
|
||||
#define _PATH_SCCSGET "/usr/local/bin/get"
|
||||
#define _PATH_SCCSHELP "/usr/local/bin/help"
|
||||
#define _PATH_SCCSPRS "/usr/local/bin/prs"
|
||||
#define _PATH_SCCSPRT "/usr/local/bin/prt"
|
||||
#define _PATH_SCCSRMDEL "/usr/local/bin/rmdel"
|
||||
#define _PATH_SCCSVAL "/usr/local/bin/val"
|
||||
#define _PATH_SCCSWHAT "/usr/local/bin/what"
|
||||
#undef _PATH_TMP
|
||||
#define _PATH_TMP "/tmp/sccsXXXXX"
|
398
usr.bin/sccs/sccs.1
Normal file
398
usr.bin/sccs/sccs.1
Normal file
@ -0,0 +1,398 @@
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)sccs.1 8.1 (Berkeley) 6/6/93
|
||||
.\"
|
||||
.Dd June 6, 1993
|
||||
.Dt SCCS 1
|
||||
.Os BSD 4.2
|
||||
.Sh NAME
|
||||
.Nm sccs
|
||||
.Nd front end for the
|
||||
.Li SCCS
|
||||
subsystem
|
||||
.Sh SYNOPSIS
|
||||
.Nm sccs
|
||||
.Op Fl r
|
||||
.Op Fl d Ar path
|
||||
.Op Fl p Ar path
|
||||
.Ar command
|
||||
.Op flags
|
||||
.Op Ar
|
||||
.Sh DESCRIPTION
|
||||
.Nm Sccs
|
||||
is a front end to the
|
||||
.Li SCCS
|
||||
programs
|
||||
that
|
||||
helps them mesh more cleanly
|
||||
with
|
||||
the rest of UNIX.
|
||||
It
|
||||
also includes the capability to run
|
||||
.Dq set user id
|
||||
to another user
|
||||
to
|
||||
provide additional protection.
|
||||
.Pp
|
||||
Basically,
|
||||
.Nm sccs
|
||||
runs the command with the specified
|
||||
.Ar flags
|
||||
and
|
||||
.Ar args .
|
||||
Each argument is normally modified to be prepended with
|
||||
.Dq Li SCCS/s. .
|
||||
.Pp
|
||||
Flags to be interpreted by the
|
||||
.Nm sccs
|
||||
program must be before the
|
||||
.Ar command
|
||||
argument.
|
||||
Flags to be passed to the actual
|
||||
.Li SCCS
|
||||
program must come after the
|
||||
.Ar command
|
||||
argument.
|
||||
These flags are specific to the command and
|
||||
are discussed in the documentation for that command.
|
||||
.Pp
|
||||
Besides the usual
|
||||
.Li SCCS
|
||||
commands,
|
||||
several
|
||||
.Dq pseudo-commands
|
||||
can be issued.
|
||||
These are:
|
||||
.Bl -tag -width deledit
|
||||
.It Cm edit
|
||||
Equivalent
|
||||
to
|
||||
.Dq Li get \-e .
|
||||
.It Cm delget
|
||||
Perform a delta on the named files and
|
||||
then get new versions.
|
||||
The new versions will have id keywords expanded, and
|
||||
will not be editable.
|
||||
The
|
||||
.Fl m ,
|
||||
.Fl p ,
|
||||
.Fl r ,
|
||||
.Fl s ,
|
||||
and
|
||||
.Fl y
|
||||
flags will be passed to
|
||||
.Nm delta ,
|
||||
and the
|
||||
.Fl b,
|
||||
.Fl c ,
|
||||
.Fl e ,
|
||||
.Fl i ,
|
||||
.Fl k ,
|
||||
.Fl l ,
|
||||
.Fl s ,
|
||||
.\" anybody who has a bad xterm which is almost anyone
|
||||
and
|
||||
.Fl x
|
||||
flags will be passed to get.
|
||||
.It Cm deledit
|
||||
Equivalent
|
||||
to
|
||||
.Nm delget
|
||||
except that the
|
||||
.Nm get
|
||||
phase includes the
|
||||
.Fl e
|
||||
flag.
|
||||
This
|
||||
option is useful for making a
|
||||
.Em checkpoint
|
||||
of your current editing phase. The same flags will be passed to delta
|
||||
as described above, and
|
||||
all the flags listed for
|
||||
.om get
|
||||
above except
|
||||
.Fl e
|
||||
and
|
||||
.Fl k
|
||||
are
|
||||
passed to
|
||||
.Nm edit .
|
||||
.It Cm create
|
||||
Creates
|
||||
an
|
||||
.Li SCCS
|
||||
file ,
|
||||
taking
|
||||
the initial contents from the file of the same name.
|
||||
Any
|
||||
flags to
|
||||
.Nm admin
|
||||
are accepted. If the creation is successful,
|
||||
the files are renamed with a comma on the front.
|
||||
These should be removed when you are convinced that the
|
||||
.Li SCCS
|
||||
files
|
||||
have been created successfully.
|
||||
.It Cm fix
|
||||
Must
|
||||
be followed by a
|
||||
.Fl r
|
||||
flag.
|
||||
This command essentially removes the named delta, but
|
||||
leaves you with a copy of the delta
|
||||
with the changes that were in it. It
|
||||
is useful for fixing small compiler bugs, etc.
|
||||
Since it doesn't leave audit trails, it should be used carefully.
|
||||
.It Cm clean
|
||||
This routine removes everything from the current directory
|
||||
that can be recreated from SCCS files.
|
||||
It will not remove any files being edited.
|
||||
If the
|
||||
.Fl b
|
||||
flag is given, branches are ignored in the determination of
|
||||
whether they are being edited; this
|
||||
is dangerous if you are keeping the branches in the
|
||||
same directory.
|
||||
.It Cm unedit
|
||||
This
|
||||
is the opposite of an
|
||||
.Nm edit
|
||||
or
|
||||
a
|
||||
.Dq Li get \-e .
|
||||
It should be used with extreme caution, since
|
||||
any changes you made since the get will be irretrievably lost.
|
||||
.It Cm info
|
||||
Gives a listing of all files being edited.
|
||||
If the
|
||||
.Fl b
|
||||
flag
|
||||
is given, branches (i.e.,
|
||||
.Li SID Ns \&\'s
|
||||
with two or fewer components)
|
||||
are ignored. If the
|
||||
.Fl u
|
||||
flag is given (with an optional argument) then
|
||||
only files being edited by you (or the named user) are listed.
|
||||
.It Cm check
|
||||
Like
|
||||
.Nm info
|
||||
except that nothing is printed if nothing is being edited, and
|
||||
a non-zero exit status is returned if anything is being edited.
|
||||
The intent is to have this included in an
|
||||
.Em install
|
||||
entry in a makefile to insure that everything is included into the
|
||||
.Li SCCS
|
||||
file before a version is installed.
|
||||
.It Cm tell
|
||||
Gives a newline-separated list of the files being edited
|
||||
on the standard output. Takes the
|
||||
.Fl b
|
||||
and
|
||||
.Fl u
|
||||
flags like
|
||||
.Nm info
|
||||
and
|
||||
.Nm check .
|
||||
.It Cm diffs
|
||||
Gives a
|
||||
.Nm diff
|
||||
listing between the current version of the
|
||||
program(s) you have out for editing and the versions in
|
||||
.Li SCCS
|
||||
format.
|
||||
The
|
||||
.Fl r ,
|
||||
.Fl c ,
|
||||
.Fl i ,
|
||||
.Fl x ,
|
||||
and
|
||||
.Fl t
|
||||
flags are passed to
|
||||
.if n \{\
|
||||
. br
|
||||
.\}
|
||||
.Nm get ;
|
||||
the
|
||||
.Fl l ,
|
||||
.Fl s ,
|
||||
.Fl e ,
|
||||
.Fl f ,
|
||||
.Fl h ,
|
||||
and
|
||||
.Fl b
|
||||
options are passed to
|
||||
.if n \{\
|
||||
. br
|
||||
.\}
|
||||
.Nm diff .
|
||||
The
|
||||
.Fl C
|
||||
flag is passed to
|
||||
.Nm diff
|
||||
as
|
||||
.Fl c .
|
||||
.It Cm print
|
||||
This command prints out verbose information
|
||||
about the named files.
|
||||
.Pp
|
||||
.It Fl r
|
||||
Runs
|
||||
.Nm sccs
|
||||
as the real user rather than as whatever effective user
|
||||
.Nm sccs
|
||||
is
|
||||
.Dq Li set user id
|
||||
to.
|
||||
.It Fl d
|
||||
Specifies a root directory for the
|
||||
.Li SCCS
|
||||
files.
|
||||
The default is the current directory.
|
||||
If environment variable
|
||||
.Ev PROJECT
|
||||
is set,
|
||||
it will be used to determine the
|
||||
.Fl d
|
||||
flag.
|
||||
.It Fl p
|
||||
Defines the pathname of the directory in which the
|
||||
.Li SCCS
|
||||
files will be found;
|
||||
.Dq Li SCCS
|
||||
is the default.
|
||||
The
|
||||
.Fl p
|
||||
flag
|
||||
differs from the
|
||||
.Fl d
|
||||
flag
|
||||
in that the
|
||||
.Fl d
|
||||
argument is prepended to the entire pathname and the
|
||||
.Fl p
|
||||
argument is inserted before the final component of the pathname.
|
||||
For example,
|
||||
.Dq Li sccs \-d/x \-py get a/b
|
||||
will convert to
|
||||
.Dq Li get /x/a/y/s.b .
|
||||
The intent here is to create aliases such as
|
||||
.Dq Li alias syssccs sccs -d/usr/src
|
||||
which
|
||||
will be used as
|
||||
.Dq Li syssccs get cmd/who.c .
|
||||
.Pp
|
||||
Certain
|
||||
commands (such as
|
||||
.Nm admin )
|
||||
cannot be run
|
||||
.Dq Li set user id
|
||||
by all users, since this would allow anyone to change the authorizations.
|
||||
These commands are always run as the real user.
|
||||
.Sh EXAMPLES
|
||||
To get a file for editing,
|
||||
edit it,
|
||||
and produce a new delta:
|
||||
.Pp
|
||||
.Dl sccs get \-e file.c
|
||||
.Dl ex file.c
|
||||
.Dl sccs delta file.c
|
||||
.Pp
|
||||
To get a file from another directory:
|
||||
.Pp
|
||||
.Dl sccs \-p/usr/src/sccs/s. get cc.c
|
||||
.Pp
|
||||
or
|
||||
.Pp
|
||||
.Dl sccs get /usr/src/sccs/s.cc.c
|
||||
.Pp
|
||||
To make a delta of a large number of files
|
||||
in the current directory:
|
||||
.Pp
|
||||
.Dl sccs delta *.c
|
||||
.Pp
|
||||
To get a list of files being edited that are not on branches:
|
||||
.Pp
|
||||
.Dl sccs info \-b
|
||||
.Pp
|
||||
To delta everything being edited by you:
|
||||
.Pp
|
||||
.Dl sccs delta \`sccs tell \-u\`
|
||||
.Pp
|
||||
In a makefile, to get source files
|
||||
from an
|
||||
.Li SCCS
|
||||
file if it does not already exist:
|
||||
.Pp
|
||||
.Dl SRCS = <list of source files>
|
||||
.Dl $(SRCS):
|
||||
.Dl \&\tsccs get $(REL) $@
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width Ar
|
||||
.It Ev PROJECT
|
||||
The PROJECT environment variable is checked by the
|
||||
.Fl d
|
||||
flag. If
|
||||
it begins with a slash, it is taken directly; otherwise,
|
||||
the home directory of a user of that name is
|
||||
examined for a subdirectory
|
||||
.Dq Li src
|
||||
or
|
||||
.Dq Li source .
|
||||
If such a directory is found, it is used.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr what 1
|
||||
.Xr admin SCCS ,
|
||||
.Xr chghist SCCS ,
|
||||
.Xr comb SCCS ,
|
||||
.Xr delta SCCS ,
|
||||
.Xr get SCCS ,
|
||||
.Xr help SCCS ,
|
||||
.Xr prt SCCS ,
|
||||
.Xr rmdel SCCS ,
|
||||
.Xr sccsdiff SCCS ,
|
||||
.Rs
|
||||
.%A Eric Allman
|
||||
.%T "An Introduction to the Source Code Control System"
|
||||
.Re
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm sccs
|
||||
command
|
||||
appeared in
|
||||
.Bx 4.3 .
|
||||
.Sh BUGS
|
||||
It should be able to take directory arguments on pseudo-commands
|
||||
like the
|
||||
.Li SCCS
|
||||
commands do.
|
1621
usr.bin/sccs/sccs.c
Normal file
1621
usr.bin/sccs/sccs.c
Normal file
File diff suppressed because it is too large
Load Diff
310
usr.bin/sort/sort.1
Normal file
310
usr.bin/sort/sort.1
Normal file
@ -0,0 +1,310 @@
|
||||
.\" Copyright (c) 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" the Institute of Electrical and Electronics Engineers, Inc.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)sort.1 8.2 (Berkeley) 5/4/95
|
||||
.\"
|
||||
.Dd May 4, 1995
|
||||
.Dt SORT 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm sort
|
||||
.Nd sort or merge text files
|
||||
.Sh SYNOPSIS
|
||||
.Nm sort
|
||||
.Op Fl mubdfinrtx
|
||||
.Oo
|
||||
.Cm \(pl Ns Ar pos1
|
||||
.Op Fl Ns Ar pos2
|
||||
.Oc
|
||||
.Ar ...
|
||||
.Op Fl o Ar output
|
||||
.Op Fl T Ar directory
|
||||
.Op Ar file
|
||||
.Ar ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm sort
|
||||
utility
|
||||
sorts text files by lines.
|
||||
Comparisons are based on one or more sort keys (or fields) extracted
|
||||
from each line of input, and are performed
|
||||
lexicographically. By default, if keys are not given,
|
||||
.Nm sort
|
||||
regards each input line as a single field.
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl c
|
||||
Check that the single input file is sorted lexicographically.
|
||||
If the file is not sorted,
|
||||
.Nm sort
|
||||
sorts it and writes the sorted output to the standard output or the
|
||||
filename specified by the
|
||||
.Fl o
|
||||
option.
|
||||
.It Fl m
|
||||
Merge only; the input files are assumed to be pre-sorted.
|
||||
.It Fl o Ar output
|
||||
The argument given is the name of an
|
||||
.Ar output
|
||||
file to
|
||||
be used instead of the standard output.
|
||||
This file
|
||||
can be the same as one of the input files.
|
||||
.It Fl T Ar directory
|
||||
The argument
|
||||
.Ar directory
|
||||
is used for creating temporary files.
|
||||
.It Fl u
|
||||
Unique: suppress all but one in each set of lines
|
||||
having equal keys.
|
||||
If used with the
|
||||
.Fl c
|
||||
option,
|
||||
check that there are no lines with duplicate keys.
|
||||
.El
|
||||
.Pp
|
||||
The following options override the default ordering rules.
|
||||
When ordering options appear independent of key field
|
||||
specifications, the requested field ordering rules are
|
||||
applied globally to all sort keys.
|
||||
.\" When attached to a
|
||||
.\" specific key
|
||||
.\" (see
|
||||
.\" .Fl k ) ,
|
||||
.\" the specified ordering options override
|
||||
.\" all global ordering options for that key.
|
||||
.Bl -tag -width indent
|
||||
.It Fl d
|
||||
Only blank space and alphanumeric characters
|
||||
.\" according
|
||||
.\" to the current setting of LC_CTYPE
|
||||
are used
|
||||
in making comparisons.
|
||||
.It Fl f
|
||||
Considers all lowercase characters that have uppercase
|
||||
equivalents to be the same for purposes of
|
||||
comparison.
|
||||
.It Fl i
|
||||
Ignore all non-printable characters.
|
||||
.It Fl n
|
||||
An initial numeric string, consisting of optional
|
||||
blank space, optional minus sign, and zero or more
|
||||
digits (including decimal point)
|
||||
.\" with
|
||||
.\" optional radix character and thousands
|
||||
.\" separator
|
||||
.\" (as defined in the current locale),
|
||||
is sorted by arithmetic value.
|
||||
The
|
||||
.Fl n
|
||||
option implies
|
||||
the
|
||||
.Fl b
|
||||
option. (See below.)
|
||||
Note that the
|
||||
.Fl b
|
||||
option
|
||||
is only effective when key fields have been specified
|
||||
and that
|
||||
.Fl \&0
|
||||
is considered equal to zero.
|
||||
.It Fl r
|
||||
Reverse the sense of comparisons.
|
||||
.El
|
||||
.Pp
|
||||
The treatment of field separators can be altered using the
|
||||
options:
|
||||
.Bl -tag -width indent
|
||||
.It Fl b
|
||||
Leading blank spaces are ignored when determining the starting
|
||||
ending positions of a restricted sort key.
|
||||
If the
|
||||
.Fl b
|
||||
option is specified before the first
|
||||
.Cm \(pl Ns Ar pos1
|
||||
argument, it shall be applied to all
|
||||
.Cm \(pl Ns Ar pos1
|
||||
arguments.
|
||||
Otherwise, the
|
||||
.Fl b
|
||||
option can be
|
||||
attached independently to each
|
||||
.Cm \(pl Ns Ar pos1
|
||||
or
|
||||
.Fl Ar pos2
|
||||
argument (see below).
|
||||
.It Fl t Ar char
|
||||
.Ar Char
|
||||
is used as the field separator character;
|
||||
.Ar char
|
||||
is not considered to be part of a field (although it
|
||||
can be included in a sort key).
|
||||
Each occurrence of
|
||||
.Ar char
|
||||
is significant (for example,
|
||||
.Dq Ar charchar
|
||||
delimits an empty field).
|
||||
If
|
||||
.Fl t
|
||||
is not specified,
|
||||
blank space characters are used as default field
|
||||
separators.
|
||||
.It Cm \(pl Ns Ar pos1
|
||||
Designates the start position of a key field.
|
||||
.It Fl Ns Ar pos1
|
||||
Designates the end position of a key field.
|
||||
.El
|
||||
.Pp
|
||||
The following operands are available:
|
||||
.Bl -tag -width indent
|
||||
.Ar file
|
||||
The pathname of a file to be sorted, merged, or checked.
|
||||
If no file
|
||||
operands are specified, or if
|
||||
a file operand is
|
||||
.Fl ,
|
||||
the standard input is used.
|
||||
.Pp
|
||||
A field is
|
||||
defined as a minimal sequence of characters followed by a
|
||||
field separator or a newline character.
|
||||
By default, the first
|
||||
blank space of a sequence of blank spaces acts as the field separator.
|
||||
All blank spaces in a sequence of blank spaces are considered
|
||||
to be part of the next field; for example, all blank spaces at
|
||||
the beginning of a line are considered to be part of the
|
||||
first field.
|
||||
.Pp
|
||||
Fields are specified
|
||||
by the
|
||||
.Cm \(pl Ns Ar pos1
|
||||
and
|
||||
.Fl Ar pos2
|
||||
arguments. A missing
|
||||
.Cm \(pl Ns Ar pos1
|
||||
argument defaults to the beginning of a line.
|
||||
A missing
|
||||
.Fl Ar pos2
|
||||
argument defaults to the end of a line.
|
||||
.Pp
|
||||
The arguments
|
||||
.Cm \(pl Ns Ar pos1
|
||||
and
|
||||
.Fl Ar pos2
|
||||
have the form
|
||||
.Em m.n
|
||||
followed by one or more of the options
|
||||
.Fl b , d , f , i ,
|
||||
.Fl n , r .
|
||||
A
|
||||
.Cm \(pl Ns Ar pos1
|
||||
position specified by
|
||||
.Em m.n
|
||||
is interpreted to
|
||||
mean the
|
||||
.Em n Ns th
|
||||
character in the
|
||||
.Em m Ns \(pl1th
|
||||
field.
|
||||
A missing
|
||||
.Em \&.n
|
||||
means
|
||||
.Ql \&.0 ,
|
||||
indicating the first character of the
|
||||
.Em m Ns \(pl1th
|
||||
field.
|
||||
If the
|
||||
.Fl b
|
||||
option is in effect,
|
||||
.Em n
|
||||
is counted from the first
|
||||
non-blank character in the
|
||||
.Em m Ns \(pl1th
|
||||
field;
|
||||
.Em m Ns \&.0b
|
||||
refers to the first
|
||||
non-blank character in the
|
||||
.Em m Ns \(pl1th
|
||||
field.
|
||||
.Pp
|
||||
A
|
||||
.Fl Ar pos2
|
||||
position specified by
|
||||
.Em m.n
|
||||
is interpreted to mean
|
||||
the
|
||||
.Em n Ns th
|
||||
character (including separators) after the last
|
||||
character of the
|
||||
.Em m Ns th
|
||||
field.
|
||||
A missing
|
||||
.Em \&.n
|
||||
means
|
||||
.Ql \&.0 ,
|
||||
indicating
|
||||
the last character of the
|
||||
.Em m Ns th
|
||||
field.
|
||||
If the
|
||||
.Fl b
|
||||
option
|
||||
is in effect,
|
||||
.Em n
|
||||
is counted from the last leading blank character in
|
||||
the
|
||||
.Em m Ns \(pl1th
|
||||
field;
|
||||
.Em m Ns \&.1b
|
||||
refers to the first non-blank character in the
|
||||
.Em m Ns \(pl1th
|
||||
field.
|
||||
.Sh FILES
|
||||
.Bl -tag -width Pa -compact
|
||||
.It Pa /var/tmp/stm*, /tmp/*
|
||||
Default temporary directories (in order of search).
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr comm 1 ,
|
||||
.Xr uniq 1 ,
|
||||
.Xr join 1
|
||||
.Sh DIAGNOSTICS
|
||||
.Sh BUGS
|
||||
Lines which are longer than 4096 are discarded and processing continues.
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
command appeared in
|
||||
.At v6 .
|
196
usr.bin/tip/acu.c
Normal file
196
usr.bin/tip/acu.c
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
* 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[] = "@(#)acu.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "tip.h"
|
||||
|
||||
static acu_t *acu = NOACU;
|
||||
static int conflag;
|
||||
static void acuabort();
|
||||
static acu_t *acutype();
|
||||
static jmp_buf jmpbuf;
|
||||
/*
|
||||
* Establish connection for tip
|
||||
*
|
||||
* If DU is true, we should dial an ACU whose type is AT.
|
||||
* The phone numbers are in PN, and the call unit is in CU.
|
||||
*
|
||||
* If the PN is an '@', then we consult the PHONES file for
|
||||
* the phone numbers. This file is /etc/phones, unless overriden
|
||||
* by an exported shell variable.
|
||||
*
|
||||
* The data base files must be in the format:
|
||||
* host-name[ \t]*phone-number
|
||||
* with the possibility of multiple phone numbers
|
||||
* for a single host acting as a rotary (in the order
|
||||
* found in the file).
|
||||
*/
|
||||
char *
|
||||
connect()
|
||||
{
|
||||
register char *cp = PN;
|
||||
char *phnum, string[256];
|
||||
FILE *fd;
|
||||
int tried = 0;
|
||||
|
||||
if (!DU) { /* regular connect message */
|
||||
if (CM != NOSTR)
|
||||
pwrite(FD, CM, size(CM));
|
||||
logent(value(HOST), "", DV, "call completed");
|
||||
return (NOSTR);
|
||||
}
|
||||
/*
|
||||
* @ =>'s use data base in PHONES environment variable
|
||||
* otherwise, use /etc/phones
|
||||
*/
|
||||
signal(SIGINT, acuabort);
|
||||
signal(SIGQUIT, acuabort);
|
||||
if (setjmp(jmpbuf)) {
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
printf("\ncall aborted\n");
|
||||
logent(value(HOST), "", "", "call aborted");
|
||||
if (acu != NOACU) {
|
||||
boolean(value(VERBOSE)) = FALSE;
|
||||
if (conflag)
|
||||
disconnect(NOSTR);
|
||||
else
|
||||
(*acu->acu_abort)();
|
||||
}
|
||||
return ("interrupt");
|
||||
}
|
||||
if ((acu = acutype(AT)) == NOACU)
|
||||
return ("unknown ACU type");
|
||||
if (*cp != '@') {
|
||||
while (*cp) {
|
||||
for (phnum = cp; *cp && *cp != ','; cp++)
|
||||
;
|
||||
if (*cp)
|
||||
*cp++ = '\0';
|
||||
|
||||
if (conflag = (*acu->acu_dialer)(phnum, CU)) {
|
||||
if (CM != NOSTR)
|
||||
pwrite(FD, CM, size(CM));
|
||||
logent(value(HOST), phnum, acu->acu_name,
|
||||
"call completed");
|
||||
return (NOSTR);
|
||||
} else
|
||||
logent(value(HOST), phnum, acu->acu_name,
|
||||
"call failed");
|
||||
tried++;
|
||||
}
|
||||
} else {
|
||||
if ((fd = fopen(PH, "r")) == NOFILE) {
|
||||
printf("%s: ", PH);
|
||||
return ("can't open phone number file");
|
||||
}
|
||||
while (fgets(string, sizeof(string), fd) != NOSTR) {
|
||||
for (cp = string; !any(*cp, " \t\n"); cp++)
|
||||
;
|
||||
if (*cp == '\n') {
|
||||
fclose(fd);
|
||||
return ("unrecognizable host name");
|
||||
}
|
||||
*cp++ = '\0';
|
||||
if (strcmp(string, value(HOST)))
|
||||
continue;
|
||||
while (any(*cp, " \t"))
|
||||
cp++;
|
||||
if (*cp == '\n') {
|
||||
fclose(fd);
|
||||
return ("missing phone number");
|
||||
}
|
||||
for (phnum = cp; *cp && *cp != ',' && *cp != '\n'; cp++)
|
||||
;
|
||||
if (*cp)
|
||||
*cp++ = '\0';
|
||||
|
||||
if (conflag = (*acu->acu_dialer)(phnum, CU)) {
|
||||
fclose(fd);
|
||||
if (CM != NOSTR)
|
||||
pwrite(FD, CM, size(CM));
|
||||
logent(value(HOST), phnum, acu->acu_name,
|
||||
"call completed");
|
||||
return (NOSTR);
|
||||
} else
|
||||
logent(value(HOST), phnum, acu->acu_name,
|
||||
"call failed");
|
||||
tried++;
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
if (!tried)
|
||||
logent(value(HOST), "", acu->acu_name, "missing phone number");
|
||||
else
|
||||
(*acu->acu_abort)();
|
||||
return (tried ? "call failed" : "missing phone number");
|
||||
}
|
||||
|
||||
disconnect(reason)
|
||||
char *reason;
|
||||
{
|
||||
if (!conflag) {
|
||||
logent(value(HOST), "", DV, "call terminated");
|
||||
return;
|
||||
}
|
||||
if (reason == NOSTR) {
|
||||
logent(value(HOST), "", acu->acu_name, "call terminated");
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("\r\ndisconnecting...");
|
||||
} else
|
||||
logent(value(HOST), "", acu->acu_name, reason);
|
||||
(*acu->acu_disconnect)();
|
||||
}
|
||||
|
||||
static void
|
||||
acuabort(s)
|
||||
{
|
||||
signal(s, SIG_IGN);
|
||||
longjmp(jmpbuf, 1);
|
||||
}
|
||||
|
||||
static acu_t *
|
||||
acutype(s)
|
||||
register char *s;
|
||||
{
|
||||
register acu_t *p;
|
||||
extern acu_t acutable[];
|
||||
|
||||
for (p = acutable; p->acu_name != '\0'; p++)
|
||||
if (!strcmp(s, p->acu_name))
|
||||
return (p);
|
||||
return (NOACU);
|
||||
}
|
187
usr.bin/tip/aculib/biz22.c
Normal file
187
usr.bin/tip/aculib/biz22.c
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* 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[] = "@(#)biz22.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "tip.h"
|
||||
|
||||
#define DISCONNECT_CMD "\20\04" /* disconnection string */
|
||||
|
||||
static void sigALRM();
|
||||
static int timeout = 0;
|
||||
static jmp_buf timeoutbuf;
|
||||
|
||||
/*
|
||||
* Dial up on a BIZCOMP Model 1022 with either
|
||||
* tone dialing (mod = "V")
|
||||
* pulse dialing (mod = "W")
|
||||
*/
|
||||
static int
|
||||
biz_dialer(num, mod)
|
||||
char *num, *mod;
|
||||
{
|
||||
register int connected = 0;
|
||||
char cbuf[40];
|
||||
static int cmd(), detect();
|
||||
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("\nstarting call...");
|
||||
/*
|
||||
* Disable auto-answer and configure for tone/pulse
|
||||
* dialing
|
||||
*/
|
||||
if (cmd("\02K\r")) {
|
||||
printf("can't initialize bizcomp...");
|
||||
return (0);
|
||||
}
|
||||
strcpy(cbuf, "\02.\r");
|
||||
cbuf[1] = *mod;
|
||||
if (cmd(cbuf)) {
|
||||
printf("can't set dialing mode...");
|
||||
return (0);
|
||||
}
|
||||
strcpy(cbuf, "\02D");
|
||||
strcat(cbuf, num);
|
||||
strcat(cbuf, "\r");
|
||||
write(FD, cbuf, strlen(cbuf));
|
||||
if (!detect("7\r")) {
|
||||
printf("can't get dial tone...");
|
||||
return (0);
|
||||
}
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("ringing...");
|
||||
/*
|
||||
* The reply from the BIZCOMP should be:
|
||||
* 2 \r or 7 \r failure
|
||||
* 1 \r success
|
||||
*/
|
||||
connected = detect("1\r");
|
||||
#ifdef ACULOG
|
||||
if (timeout) {
|
||||
char line[80];
|
||||
|
||||
sprintf(line, "%d second dial timeout",
|
||||
number(value(DIALTIMEOUT)));
|
||||
logent(value(HOST), num, "biz1022", line);
|
||||
}
|
||||
#endif
|
||||
if (timeout)
|
||||
biz22_disconnect(); /* insurance */
|
||||
return (connected);
|
||||
}
|
||||
|
||||
biz22w_dialer(num, acu)
|
||||
char *num, *acu;
|
||||
{
|
||||
|
||||
return (biz_dialer(num, "W"));
|
||||
}
|
||||
|
||||
biz22f_dialer(num, acu)
|
||||
char *num, *acu;
|
||||
{
|
||||
|
||||
return (biz_dialer(num, "V"));
|
||||
}
|
||||
|
||||
biz22_disconnect()
|
||||
{
|
||||
int rw = 2;
|
||||
|
||||
write(FD, DISCONNECT_CMD, 4);
|
||||
sleep(2);
|
||||
ioctl(FD, TIOCFLUSH, &rw);
|
||||
}
|
||||
|
||||
biz22_abort()
|
||||
{
|
||||
|
||||
write(FD, "\02", 1);
|
||||
}
|
||||
|
||||
static void
|
||||
sigALRM()
|
||||
{
|
||||
|
||||
timeout = 1;
|
||||
longjmp(timeoutbuf, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
cmd(s)
|
||||
register char *s;
|
||||
{
|
||||
sig_t f;
|
||||
char c;
|
||||
|
||||
write(FD, s, strlen(s));
|
||||
f = signal(SIGALRM, sigALRM);
|
||||
if (setjmp(timeoutbuf)) {
|
||||
biz22_abort();
|
||||
signal(SIGALRM, f);
|
||||
return (1);
|
||||
}
|
||||
alarm(number(value(DIALTIMEOUT)));
|
||||
read(FD, &c, 1);
|
||||
alarm(0);
|
||||
signal(SIGALRM, f);
|
||||
c &= 0177;
|
||||
return (c != '\r');
|
||||
}
|
||||
|
||||
static int
|
||||
detect(s)
|
||||
register char *s;
|
||||
{
|
||||
sig_t f;
|
||||
char c;
|
||||
|
||||
f = signal(SIGALRM, sigALRM);
|
||||
timeout = 0;
|
||||
while (*s) {
|
||||
if (setjmp(timeoutbuf)) {
|
||||
biz22_abort();
|
||||
break;
|
||||
}
|
||||
alarm(number(value(DIALTIMEOUT)));
|
||||
read(FD, &c, 1);
|
||||
alarm(0);
|
||||
c &= 0177;
|
||||
if (c != *s++)
|
||||
return (0);
|
||||
}
|
||||
signal(SIGALRM, f);
|
||||
return (timeout == 0);
|
||||
}
|
248
usr.bin/tip/aculib/biz31.c
Normal file
248
usr.bin/tip/aculib/biz31.c
Normal file
@ -0,0 +1,248 @@
|
||||
/*
|
||||
* 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[] = "@(#)biz31.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "tip.h"
|
||||
|
||||
#define MAXRETRY 3 /* sync up retry count */
|
||||
#define DISCONNECT_CMD "\21\25\11\24" /* disconnection string */
|
||||
|
||||
static void sigALRM();
|
||||
static int timeout = 0;
|
||||
static jmp_buf timeoutbuf;
|
||||
|
||||
/*
|
||||
* Dial up on a BIZCOMP Model 1031 with either
|
||||
* tone dialing (mod = "f")
|
||||
* pulse dialing (mod = "w")
|
||||
*/
|
||||
static int
|
||||
biz_dialer(num, mod)
|
||||
char *num, *mod;
|
||||
{
|
||||
register int connected = 0;
|
||||
|
||||
if (!bizsync(FD)) {
|
||||
logent(value(HOST), "", "biz", "out of sync");
|
||||
printf("bizcomp out of sync\n");
|
||||
delock(uucplock);
|
||||
exit(0);
|
||||
}
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("\nstarting call...");
|
||||
echo("#\rk$\r$\n"); /* disable auto-answer */
|
||||
echo("$>$.$ #\r"); /* tone/pulse dialing */
|
||||
echo(mod);
|
||||
echo("$\r$\n");
|
||||
echo("$>$.$ #\re$ "); /* disconnection sequence */
|
||||
echo(DISCONNECT_CMD);
|
||||
echo("\r$\n$\r$\n");
|
||||
echo("$>$.$ #\rr$ "); /* repeat dial */
|
||||
echo(num);
|
||||
echo("\r$\n");
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("ringing...");
|
||||
/*
|
||||
* The reply from the BIZCOMP should be:
|
||||
* `^G NO CONNECTION\r\n^G\r\n' failure
|
||||
* ` CONNECTION\r\n^G' success
|
||||
*/
|
||||
connected = detect(" ");
|
||||
#ifdef ACULOG
|
||||
if (timeout) {
|
||||
char line[80];
|
||||
|
||||
sprintf(line, "%d second dial timeout",
|
||||
number(value(DIALTIMEOUT)));
|
||||
logent(value(HOST), num, "biz", line);
|
||||
}
|
||||
#endif
|
||||
if (!connected)
|
||||
flush(" NO CONNECTION\r\n\07\r\n");
|
||||
else
|
||||
flush("CONNECTION\r\n\07");
|
||||
if (timeout)
|
||||
biz31_disconnect(); /* insurance */
|
||||
return (connected);
|
||||
}
|
||||
|
||||
biz31w_dialer(num, acu)
|
||||
char *num, *acu;
|
||||
{
|
||||
|
||||
return (biz_dialer(num, "w"));
|
||||
}
|
||||
|
||||
biz31f_dialer(num, acu)
|
||||
char *num, *acu;
|
||||
{
|
||||
|
||||
return (biz_dialer(num, "f"));
|
||||
}
|
||||
|
||||
biz31_disconnect()
|
||||
{
|
||||
|
||||
write(FD, DISCONNECT_CMD, 4);
|
||||
sleep(2);
|
||||
ioctl(FD, TIOCFLUSH);
|
||||
}
|
||||
|
||||
biz31_abort()
|
||||
{
|
||||
|
||||
write(FD, "\33", 1);
|
||||
}
|
||||
|
||||
static int
|
||||
echo(s)
|
||||
register char *s;
|
||||
{
|
||||
char c;
|
||||
|
||||
while (c = *s++) switch (c) {
|
||||
|
||||
case '$':
|
||||
read(FD, &c, 1);
|
||||
s++;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
c = *s++;
|
||||
write(FD, &c, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
write(FD, &c, 1);
|
||||
read(FD, &c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sigALRM()
|
||||
{
|
||||
|
||||
timeout = 1;
|
||||
longjmp(timeoutbuf, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
detect(s)
|
||||
register char *s;
|
||||
{
|
||||
sig_t f;
|
||||
char c;
|
||||
|
||||
f = signal(SIGALRM, sigALRM);
|
||||
timeout = 0;
|
||||
while (*s) {
|
||||
if (setjmp(timeoutbuf)) {
|
||||
printf("\07timeout waiting for reply\n");
|
||||
biz31_abort();
|
||||
break;
|
||||
}
|
||||
alarm(number(value(DIALTIMEOUT)));
|
||||
read(FD, &c, 1);
|
||||
alarm(0);
|
||||
if (c != *s++)
|
||||
break;
|
||||
}
|
||||
signal(SIGALRM, f);
|
||||
return (timeout == 0);
|
||||
}
|
||||
|
||||
static int
|
||||
flush(s)
|
||||
register char *s;
|
||||
{
|
||||
sig_t f;
|
||||
char c;
|
||||
|
||||
f = signal(SIGALRM, sigALRM);
|
||||
while (*s++) {
|
||||
if (setjmp(timeoutbuf))
|
||||
break;
|
||||
alarm(10);
|
||||
read(FD, &c, 1);
|
||||
alarm(0);
|
||||
}
|
||||
signal(SIGALRM, f);
|
||||
timeout = 0; /* guard against disconnection */
|
||||
}
|
||||
|
||||
/*
|
||||
* This convoluted piece of code attempts to get
|
||||
* the bizcomp in sync. If you don't have the capacity or nread
|
||||
* call there are gory ways to simulate this.
|
||||
*/
|
||||
static int
|
||||
bizsync(fd)
|
||||
{
|
||||
#ifdef FIOCAPACITY
|
||||
struct capacity b;
|
||||
# define chars(b) ((b).cp_nbytes)
|
||||
# define IOCTL FIOCAPACITY
|
||||
#endif
|
||||
#ifdef FIONREAD
|
||||
long b;
|
||||
# define chars(b) (b)
|
||||
# define IOCTL FIONREAD
|
||||
#endif
|
||||
register int already = 0;
|
||||
char buf[10];
|
||||
|
||||
retry:
|
||||
if (ioctl(fd, IOCTL, (caddr_t)&b) >= 0 && chars(b) > 0)
|
||||
ioctl(fd, TIOCFLUSH);
|
||||
write(fd, "\rp>\r", 4);
|
||||
sleep(1);
|
||||
if (ioctl(fd, IOCTL, (caddr_t)&b) >= 0) {
|
||||
if (chars(b) != 10) {
|
||||
nono:
|
||||
if (already > MAXRETRY)
|
||||
return (0);
|
||||
write(fd, DISCONNECT_CMD, 4);
|
||||
sleep(2);
|
||||
already++;
|
||||
goto retry;
|
||||
} else {
|
||||
read(fd, buf, 10);
|
||||
if (strncmp(buf, "p >\r\n\r\n>", 8))
|
||||
goto nono;
|
||||
}
|
||||
}
|
||||
return (1);
|
||||
}
|
380
usr.bin/tip/aculib/courier.c
Normal file
380
usr.bin/tip/aculib/courier.c
Normal file
@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright (c) 1986, 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[] = "@(#)courier.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Routines for calling up on a Courier modem.
|
||||
* Derived from Hayes driver.
|
||||
*/
|
||||
#include "tip.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define MAXRETRY 5
|
||||
|
||||
static void sigALRM();
|
||||
static int timeout = 0;
|
||||
static int connected = 0;
|
||||
static jmp_buf timeoutbuf, intbuf;
|
||||
static int coursync();
|
||||
|
||||
cour_dialer(num, acu)
|
||||
register char *num;
|
||||
char *acu;
|
||||
{
|
||||
register char *cp;
|
||||
#ifdef ACULOG
|
||||
char line[80];
|
||||
#endif
|
||||
static int cour_connect(), cour_swallow();
|
||||
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("Using \"%s\"\n", acu);
|
||||
|
||||
ioctl(FD, TIOCHPCL, 0);
|
||||
/*
|
||||
* Get in synch.
|
||||
*/
|
||||
if (!coursync()) {
|
||||
badsynch:
|
||||
printf("can't synchronize with courier\n");
|
||||
#ifdef ACULOG
|
||||
logent(value(HOST), num, "courier", "can't synch up");
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
cour_write(FD, "AT E0\r", 6); /* turn off echoing */
|
||||
sleep(1);
|
||||
#ifdef DEBUG
|
||||
if (boolean(value(VERBOSE)))
|
||||
cour_verbose_read();
|
||||
#endif
|
||||
ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */
|
||||
cour_write(FD, "AT C1 E0 H0 Q0 X6 V1\r", 21);
|
||||
if (!cour_swallow("\r\nOK\r\n"))
|
||||
goto badsynch;
|
||||
fflush(stdout);
|
||||
cour_write(FD, "AT D", 4);
|
||||
for (cp = num; *cp; cp++)
|
||||
if (*cp == '=')
|
||||
*cp = ',';
|
||||
cour_write(FD, num, strlen(num));
|
||||
cour_write(FD, "\r", 1);
|
||||
connected = cour_connect();
|
||||
#ifdef ACULOG
|
||||
if (timeout) {
|
||||
sprintf(line, "%d second dial timeout",
|
||||
number(value(DIALTIMEOUT)));
|
||||
logent(value(HOST), num, "cour", line);
|
||||
}
|
||||
#endif
|
||||
if (timeout)
|
||||
cour_disconnect();
|
||||
return (connected);
|
||||
}
|
||||
|
||||
cour_disconnect()
|
||||
{
|
||||
/* first hang up the modem*/
|
||||
ioctl(FD, TIOCCDTR, 0);
|
||||
sleep(1);
|
||||
ioctl(FD, TIOCSDTR, 0);
|
||||
coursync(); /* reset */
|
||||
close(FD);
|
||||
}
|
||||
|
||||
cour_abort()
|
||||
{
|
||||
cour_write(FD, "\r", 1); /* send anything to abort the call */
|
||||
cour_disconnect();
|
||||
}
|
||||
|
||||
static void
|
||||
sigALRM()
|
||||
{
|
||||
printf("\07timeout waiting for reply\n");
|
||||
timeout = 1;
|
||||
longjmp(timeoutbuf, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
cour_swallow(match)
|
||||
register char *match;
|
||||
{
|
||||
sig_t f;
|
||||
char c;
|
||||
|
||||
f = signal(SIGALRM, sigALRM);
|
||||
timeout = 0;
|
||||
do {
|
||||
if (*match =='\0') {
|
||||
signal(SIGALRM, f);
|
||||
return (1);
|
||||
}
|
||||
if (setjmp(timeoutbuf)) {
|
||||
signal(SIGALRM, f);
|
||||
return (0);
|
||||
}
|
||||
alarm(number(value(DIALTIMEOUT)));
|
||||
read(FD, &c, 1);
|
||||
alarm(0);
|
||||
c &= 0177;
|
||||
#ifdef DEBUG
|
||||
if (boolean(value(VERBOSE)))
|
||||
putchar(c);
|
||||
#endif
|
||||
} while (c == *match++);
|
||||
#ifdef DEBUG
|
||||
if (boolean(value(VERBOSE)))
|
||||
fflush(stdout);
|
||||
#endif
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct baud_msg {
|
||||
char *msg;
|
||||
int baud;
|
||||
} baud_msg[] = {
|
||||
"", B300,
|
||||
" 1200", B1200,
|
||||
" 2400", B2400,
|
||||
" 9600", B9600,
|
||||
" 9600/ARQ", B9600,
|
||||
0, 0,
|
||||
};
|
||||
|
||||
static int
|
||||
cour_connect()
|
||||
{
|
||||
char c;
|
||||
int nc, nl, n;
|
||||
struct sgttyb sb;
|
||||
char dialer_buf[64];
|
||||
struct baud_msg *bm;
|
||||
sig_t f;
|
||||
|
||||
if (cour_swallow("\r\n") == 0)
|
||||
return (0);
|
||||
f = signal(SIGALRM, sigALRM);
|
||||
again:
|
||||
nc = 0; nl = sizeof(dialer_buf)-1;
|
||||
bzero(dialer_buf, sizeof(dialer_buf));
|
||||
timeout = 0;
|
||||
for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) {
|
||||
if (setjmp(timeoutbuf))
|
||||
break;
|
||||
alarm(number(value(DIALTIMEOUT)));
|
||||
n = read(FD, &c, 1);
|
||||
alarm(0);
|
||||
if (n <= 0)
|
||||
break;
|
||||
c &= 0x7f;
|
||||
if (c == '\r') {
|
||||
if (cour_swallow("\n") == 0)
|
||||
break;
|
||||
if (!dialer_buf[0])
|
||||
goto again;
|
||||
if (strcmp(dialer_buf, "RINGING") == 0 &&
|
||||
boolean(value(VERBOSE))) {
|
||||
#ifdef DEBUG
|
||||
printf("%s\r\n", dialer_buf);
|
||||
#endif
|
||||
goto again;
|
||||
}
|
||||
if (strncmp(dialer_buf, "CONNECT",
|
||||
sizeof("CONNECT")-1) != 0)
|
||||
break;
|
||||
for (bm = baud_msg ; bm->msg ; bm++)
|
||||
if (strcmp(bm->msg,
|
||||
dialer_buf+sizeof("CONNECT")-1) == 0) {
|
||||
if (ioctl(FD, TIOCGETP, &sb) < 0) {
|
||||
perror("TIOCGETP");
|
||||
goto error;
|
||||
}
|
||||
sb.sg_ispeed = sb.sg_ospeed = bm->baud;
|
||||
if (ioctl(FD, TIOCSETP, &sb) < 0) {
|
||||
perror("TIOCSETP");
|
||||
goto error;
|
||||
}
|
||||
signal(SIGALRM, f);
|
||||
#ifdef DEBUG
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("%s\r\n", dialer_buf);
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
dialer_buf[nc] = c;
|
||||
#ifdef notdef
|
||||
if (boolean(value(VERBOSE)))
|
||||
putchar(c);
|
||||
#endif
|
||||
}
|
||||
error1:
|
||||
printf("%s\r\n", dialer_buf);
|
||||
error:
|
||||
signal(SIGALRM, f);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This convoluted piece of code attempts to get
|
||||
* the courier in sync.
|
||||
*/
|
||||
static int
|
||||
coursync()
|
||||
{
|
||||
int already = 0;
|
||||
int len;
|
||||
char buf[40];
|
||||
|
||||
while (already++ < MAXRETRY) {
|
||||
ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */
|
||||
cour_write(FD, "\rAT Z\r", 6); /* reset modem */
|
||||
bzero(buf, sizeof(buf));
|
||||
sleep(1);
|
||||
ioctl(FD, FIONREAD, &len);
|
||||
if (len) {
|
||||
len = read(FD, buf, sizeof(buf));
|
||||
#ifdef DEBUG
|
||||
buf[len] = '\0';
|
||||
printf("coursync: (\"%s\")\n\r", buf);
|
||||
#endif
|
||||
if (index(buf, '0') ||
|
||||
(index(buf, 'O') && index(buf, 'K')))
|
||||
return(1);
|
||||
}
|
||||
/*
|
||||
* If not strapped for DTR control,
|
||||
* try to get command mode.
|
||||
*/
|
||||
sleep(1);
|
||||
cour_write(FD, "+++", 3);
|
||||
sleep(1);
|
||||
/*
|
||||
* Toggle DTR to force anyone off that might have left
|
||||
* the modem connected.
|
||||
*/
|
||||
ioctl(FD, TIOCCDTR, 0);
|
||||
sleep(1);
|
||||
ioctl(FD, TIOCSDTR, 0);
|
||||
}
|
||||
cour_write(FD, "\rAT Z\r", 6);
|
||||
return (0);
|
||||
}
|
||||
|
||||
cour_write(fd, cp, n)
|
||||
int fd;
|
||||
char *cp;
|
||||
int n;
|
||||
{
|
||||
struct sgttyb sb;
|
||||
#ifdef notdef
|
||||
if (boolean(value(VERBOSE)))
|
||||
write(1, cp, n);
|
||||
#endif
|
||||
ioctl(fd, TIOCGETP, &sb);
|
||||
ioctl(fd, TIOCSETP, &sb);
|
||||
cour_nap();
|
||||
for ( ; n-- ; cp++) {
|
||||
write(fd, cp, 1);
|
||||
ioctl(fd, TIOCGETP, &sb);
|
||||
ioctl(fd, TIOCSETP, &sb);
|
||||
cour_nap();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
cour_verbose_read()
|
||||
{
|
||||
int n = 0;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
if (ioctl(FD, FIONREAD, &n) < 0)
|
||||
return;
|
||||
if (n <= 0)
|
||||
return;
|
||||
if (read(FD, buf, n) != n)
|
||||
return;
|
||||
write(1, buf, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Code stolen from /usr/src/lib/libc/gen/sleep.c
|
||||
*/
|
||||
#define mask(s) (1<<((s)-1))
|
||||
#define setvec(vec, a) \
|
||||
vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
|
||||
|
||||
static napms = 50; /* Give the courier 50 milliseconds between characters */
|
||||
|
||||
static int ringring;
|
||||
|
||||
cour_nap()
|
||||
{
|
||||
|
||||
static void cour_napx();
|
||||
int omask;
|
||||
struct itimerval itv, oitv;
|
||||
register struct itimerval *itp = &itv;
|
||||
struct sigvec vec, ovec;
|
||||
|
||||
timerclear(&itp->it_interval);
|
||||
timerclear(&itp->it_value);
|
||||
if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
|
||||
return;
|
||||
setvec(ovec, SIG_DFL);
|
||||
omask = sigblock(mask(SIGALRM));
|
||||
itp->it_value.tv_sec = napms/1000;
|
||||
itp->it_value.tv_usec = ((napms%1000)*1000);
|
||||
setvec(vec, cour_napx);
|
||||
ringring = 0;
|
||||
(void) sigvec(SIGALRM, &vec, &ovec);
|
||||
(void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
|
||||
while (!ringring)
|
||||
sigpause(omask &~ mask(SIGALRM));
|
||||
(void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
|
||||
(void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
|
||||
(void) sigsetmask(omask);
|
||||
}
|
||||
|
||||
static void
|
||||
cour_napx()
|
||||
{
|
||||
ringring = 1;
|
||||
}
|
132
usr.bin/tip/aculib/df.c
Normal file
132
usr.bin/tip/aculib/df.c
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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[] = "@(#)df.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Dial the DF02-AC or DF03-AC
|
||||
*/
|
||||
|
||||
#include "tip.h"
|
||||
|
||||
static jmp_buf Sjbuf;
|
||||
static void timeout();
|
||||
|
||||
df02_dialer(num, acu)
|
||||
char *num, *acu;
|
||||
{
|
||||
|
||||
return (df_dialer(num, acu, 0));
|
||||
}
|
||||
|
||||
df03_dialer(num, acu)
|
||||
char *num, *acu;
|
||||
{
|
||||
|
||||
return (df_dialer(num, acu, 1));
|
||||
}
|
||||
|
||||
df_dialer(num, acu, df03)
|
||||
char *num, *acu;
|
||||
int df03;
|
||||
{
|
||||
register int f = FD;
|
||||
struct sgttyb buf;
|
||||
int speed = 0, rw = 2;
|
||||
char c = '\0';
|
||||
|
||||
ioctl(f, TIOCHPCL, 0); /* make sure it hangs up when done */
|
||||
if (setjmp(Sjbuf)) {
|
||||
printf("connection timed out\r\n");
|
||||
df_disconnect();
|
||||
return (0);
|
||||
}
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("\ndialing...");
|
||||
fflush(stdout);
|
||||
#ifdef TIOCMSET
|
||||
if (df03) {
|
||||
int st = TIOCM_ST; /* secondary Transmit flag */
|
||||
|
||||
ioctl(f, TIOCGETP, &buf);
|
||||
if (buf.sg_ospeed != B1200) { /* must dial at 1200 baud */
|
||||
speed = buf.sg_ospeed;
|
||||
buf.sg_ospeed = buf.sg_ispeed = B1200;
|
||||
ioctl(f, TIOCSETP, &buf);
|
||||
ioctl(f, TIOCMBIC, &st); /* clear ST for 300 baud */
|
||||
} else
|
||||
ioctl(f, TIOCMBIS, &st); /* set ST for 1200 baud */
|
||||
}
|
||||
#endif
|
||||
signal(SIGALRM, timeout);
|
||||
alarm(5 * strlen(num) + 10);
|
||||
ioctl(f, TIOCFLUSH, &rw);
|
||||
write(f, "\001", 1);
|
||||
sleep(1);
|
||||
write(f, "\002", 1);
|
||||
write(f, num, strlen(num));
|
||||
read(f, &c, 1);
|
||||
#ifdef TIOCMSET
|
||||
if (df03 && speed) {
|
||||
buf.sg_ispeed = buf.sg_ospeed = speed;
|
||||
ioctl(f, TIOCSETP, &buf);
|
||||
}
|
||||
#endif
|
||||
return (c == 'A');
|
||||
}
|
||||
|
||||
df_disconnect()
|
||||
{
|
||||
int rw = 2;
|
||||
|
||||
write(FD, "\001", 1);
|
||||
sleep(1);
|
||||
ioctl(FD, TIOCFLUSH, &rw);
|
||||
}
|
||||
|
||||
|
||||
df_abort()
|
||||
{
|
||||
|
||||
df_disconnect();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
timeout()
|
||||
{
|
||||
|
||||
longjmp(Sjbuf, 1);
|
||||
}
|
142
usr.bin/tip/aculib/dn11.c
Normal file
142
usr.bin/tip/aculib/dn11.c
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* 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[] = "@(#)dn11.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Routines for dialing up on DN-11
|
||||
*/
|
||||
#include "tip.h"
|
||||
|
||||
int dn_abort();
|
||||
void alarmtr();
|
||||
static jmp_buf jmpbuf;
|
||||
static int child = -1, dn;
|
||||
|
||||
dn_dialer(num, acu)
|
||||
char *num, *acu;
|
||||
{
|
||||
extern errno;
|
||||
char *p, *q, phone[40];
|
||||
int lt, nw, connected = 1;
|
||||
register int timelim;
|
||||
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("\nstarting call...");
|
||||
if ((dn = open(acu, 1)) < 0) {
|
||||
if (errno == EBUSY)
|
||||
printf("line busy...");
|
||||
else
|
||||
printf("acu open error...");
|
||||
return (0);
|
||||
}
|
||||
if (setjmp(jmpbuf)) {
|
||||
kill(child, SIGKILL);
|
||||
close(dn);
|
||||
return (0);
|
||||
}
|
||||
signal(SIGALRM, alarmtr);
|
||||
timelim = 5 * strlen(num);
|
||||
alarm(timelim < 30 ? 30 : timelim);
|
||||
if ((child = fork()) == 0) {
|
||||
/*
|
||||
* ignore this stuff for aborts
|
||||
*/
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
sleep(2);
|
||||
nw = write(dn, num, lt = strlen(num));
|
||||
exit(nw != lt);
|
||||
}
|
||||
/*
|
||||
* open line - will return on carrier
|
||||
*/
|
||||
if ((FD = open(DV, 2)) < 0) {
|
||||
if (errno == EIO)
|
||||
printf("lost carrier...");
|
||||
else
|
||||
printf("dialup line open failed...");
|
||||
alarm(0);
|
||||
kill(child, SIGKILL);
|
||||
close(dn);
|
||||
return (0);
|
||||
}
|
||||
alarm(0);
|
||||
ioctl(dn, TIOCHPCL, 0);
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
while ((nw = wait(<)) != child && nw != -1)
|
||||
;
|
||||
fflush(stdout);
|
||||
close(dn);
|
||||
if (lt != 0) {
|
||||
close(FD);
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
alarmtr()
|
||||
{
|
||||
alarm(0);
|
||||
longjmp(jmpbuf, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insurance, for some reason we don't seem to be
|
||||
* hanging up...
|
||||
*/
|
||||
dn_disconnect()
|
||||
{
|
||||
|
||||
sleep(2);
|
||||
if (FD > 0)
|
||||
ioctl(FD, TIOCCDTR, 0);
|
||||
close(FD);
|
||||
}
|
||||
|
||||
dn_abort()
|
||||
{
|
||||
|
||||
sleep(2);
|
||||
if (child > 0)
|
||||
kill(child, SIGKILL);
|
||||
if (dn > 0)
|
||||
close(dn);
|
||||
if (FD > 0)
|
||||
ioctl(FD, TIOCCDTR, 0);
|
||||
close(FD);
|
||||
}
|
305
usr.bin/tip/aculib/hayes.c
Normal file
305
usr.bin/tip/aculib/hayes.c
Normal file
@ -0,0 +1,305 @@
|
||||
/*
|
||||
* 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[] = "@(#)hayes.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Routines for calling up on a Hayes Modem
|
||||
* (based on the old VenTel driver).
|
||||
* The modem is expected to be strapped for "echo".
|
||||
* Also, the switches enabling the DTR and CD lines
|
||||
* must be set correctly.
|
||||
* NOTICE:
|
||||
* The easy way to hang up a modem is always simply to
|
||||
* clear the DTR signal. However, if the +++ sequence
|
||||
* (which switches the modem back to local mode) is sent
|
||||
* before modem is hung up, removal of the DTR signal
|
||||
* has no effect (except that it prevents the modem from
|
||||
* recognizing commands).
|
||||
* (by Helge Skrivervik, Calma Company, Sunnyvale, CA. 1984)
|
||||
*/
|
||||
/*
|
||||
* TODO:
|
||||
* It is probably not a good idea to switch the modem
|
||||
* state between 'verbose' and terse (status messages).
|
||||
* This should be kicked out and we should use verbose
|
||||
* mode only. This would make it consistent with normal
|
||||
* interactive use thru the command 'tip dialer'.
|
||||
*/
|
||||
#include "tip.h"
|
||||
|
||||
#define min(a,b) ((a < b) ? a : b)
|
||||
|
||||
static void sigALRM();
|
||||
static int timeout = 0;
|
||||
static jmp_buf timeoutbuf;
|
||||
static char gobble();
|
||||
#define DUMBUFLEN 40
|
||||
static char dumbuf[DUMBUFLEN];
|
||||
|
||||
#define DIALING 1
|
||||
#define IDLE 2
|
||||
#define CONNECTED 3
|
||||
#define FAILED 4
|
||||
static int state = IDLE;
|
||||
|
||||
hay_dialer(num, acu)
|
||||
register char *num;
|
||||
char *acu;
|
||||
{
|
||||
register char *cp;
|
||||
register int connected = 0;
|
||||
char dummy;
|
||||
#ifdef ACULOG
|
||||
char line[80];
|
||||
#endif
|
||||
if (hay_sync() == 0) /* make sure we can talk to the modem */
|
||||
return(0);
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("\ndialing...");
|
||||
fflush(stdout);
|
||||
ioctl(FD, TIOCHPCL, 0);
|
||||
ioctl(FD, TIOCFLUSH, 0); /* get rid of garbage */
|
||||
write(FD, "ATv0\r", 5); /* tell modem to use short status codes */
|
||||
gobble("\r");
|
||||
gobble("\r");
|
||||
write(FD, "ATTD", 4); /* send dial command */
|
||||
write(FD, num, strlen(num));
|
||||
state = DIALING;
|
||||
write(FD, "\r", 1);
|
||||
connected = 0;
|
||||
if (gobble("\r")) {
|
||||
if ((dummy = gobble("01234")) != '1')
|
||||
error_rep(dummy);
|
||||
else
|
||||
connected = 1;
|
||||
}
|
||||
if (connected)
|
||||
state = CONNECTED;
|
||||
else {
|
||||
state = FAILED;
|
||||
return (connected); /* lets get out of here.. */
|
||||
}
|
||||
ioctl(FD, TIOCFLUSH, 0);
|
||||
#ifdef ACULOG
|
||||
if (timeout) {
|
||||
sprintf(line, "%d second dial timeout",
|
||||
number(value(DIALTIMEOUT)));
|
||||
logent(value(HOST), num, "hayes", line);
|
||||
}
|
||||
#endif
|
||||
if (timeout)
|
||||
hay_disconnect(); /* insurance */
|
||||
return (connected);
|
||||
}
|
||||
|
||||
|
||||
hay_disconnect()
|
||||
{
|
||||
char c;
|
||||
int len, rlen;
|
||||
|
||||
/* first hang up the modem*/
|
||||
#ifdef DEBUG
|
||||
printf("\rdisconnecting modem....\n\r");
|
||||
#endif
|
||||
ioctl(FD, TIOCCDTR, 0);
|
||||
sleep(1);
|
||||
ioctl(FD, TIOCSDTR, 0);
|
||||
goodbye();
|
||||
}
|
||||
|
||||
hay_abort()
|
||||
{
|
||||
|
||||
char c;
|
||||
|
||||
write(FD, "\r", 1); /* send anything to abort the call */
|
||||
hay_disconnect();
|
||||
}
|
||||
|
||||
static void
|
||||
sigALRM()
|
||||
{
|
||||
|
||||
printf("\07timeout waiting for reply\n\r");
|
||||
timeout = 1;
|
||||
longjmp(timeoutbuf, 1);
|
||||
}
|
||||
|
||||
static char
|
||||
gobble(match)
|
||||
register char *match;
|
||||
{
|
||||
char c;
|
||||
sig_t f;
|
||||
int i, status = 0;
|
||||
|
||||
f = signal(SIGALRM, sigALRM);
|
||||
timeout = 0;
|
||||
#ifdef DEBUG
|
||||
printf("\ngobble: waiting for %s\n", match);
|
||||
#endif
|
||||
do {
|
||||
if (setjmp(timeoutbuf)) {
|
||||
signal(SIGALRM, f);
|
||||
return (0);
|
||||
}
|
||||
alarm(number(value(DIALTIMEOUT)));
|
||||
read(FD, &c, 1);
|
||||
alarm(0);
|
||||
c &= 0177;
|
||||
#ifdef DEBUG
|
||||
printf("%c 0x%x ", c, c);
|
||||
#endif
|
||||
for (i = 0; i < strlen(match); i++)
|
||||
if (c == match[i])
|
||||
status = c;
|
||||
} while (status == 0);
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
#ifdef DEBUG
|
||||
printf("\n");
|
||||
#endif
|
||||
return (status);
|
||||
}
|
||||
|
||||
error_rep(c)
|
||||
register char c;
|
||||
{
|
||||
printf("\n\r");
|
||||
switch (c) {
|
||||
|
||||
case '0':
|
||||
printf("OK");
|
||||
break;
|
||||
|
||||
case '1':
|
||||
printf("CONNECT");
|
||||
break;
|
||||
|
||||
case '2':
|
||||
printf("RING");
|
||||
break;
|
||||
|
||||
case '3':
|
||||
printf("NO CARRIER");
|
||||
break;
|
||||
|
||||
case '4':
|
||||
printf("ERROR in input");
|
||||
break;
|
||||
|
||||
case '5':
|
||||
printf("CONNECT 1200");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unknown Modem error: %c (0x%x)", c, c);
|
||||
}
|
||||
printf("\n\r");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* set modem back to normal verbose status codes.
|
||||
*/
|
||||
goodbye()
|
||||
{
|
||||
int len, rlen;
|
||||
char c;
|
||||
|
||||
ioctl(FD, TIOCFLUSH, &len); /* get rid of trash */
|
||||
if (hay_sync()) {
|
||||
sleep(1);
|
||||
#ifndef DEBUG
|
||||
ioctl(FD, TIOCFLUSH, 0);
|
||||
#endif
|
||||
write(FD, "ATH0\r", 5); /* insurance */
|
||||
#ifndef DEBUG
|
||||
c = gobble("03");
|
||||
if (c != '0' && c != '3') {
|
||||
printf("cannot hang up modem\n\r");
|
||||
printf("please use 'tip dialer' to make sure the line is hung up\n\r");
|
||||
}
|
||||
#endif
|
||||
sleep(1);
|
||||
ioctl(FD, FIONREAD, &len);
|
||||
#ifdef DEBUG
|
||||
printf("goodbye1: len=%d -- ", len);
|
||||
rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
|
||||
dumbuf[rlen] = '\0';
|
||||
printf("read (%d): %s\r\n", rlen, dumbuf);
|
||||
#endif
|
||||
write(FD, "ATv1\r", 5);
|
||||
sleep(1);
|
||||
#ifdef DEBUG
|
||||
ioctl(FD, FIONREAD, &len);
|
||||
printf("goodbye2: len=%d -- ", len);
|
||||
rlen = read(FD, dumbuf, min(len, DUMBUFLEN));
|
||||
dumbuf[rlen] = '\0';
|
||||
printf("read (%d): %s\r\n", rlen, dumbuf);
|
||||
#endif
|
||||
}
|
||||
ioctl(FD, TIOCFLUSH, 0); /* clear the input buffer */
|
||||
ioctl(FD, TIOCCDTR, 0); /* clear DTR (insurance) */
|
||||
close(FD);
|
||||
}
|
||||
|
||||
#define MAXRETRY 5
|
||||
|
||||
hay_sync()
|
||||
{
|
||||
int len, retry = 0;
|
||||
|
||||
while (retry++ <= MAXRETRY) {
|
||||
write(FD, "AT\r", 3);
|
||||
sleep(1);
|
||||
ioctl(FD, FIONREAD, &len);
|
||||
if (len) {
|
||||
len = read(FD, dumbuf, min(len, DUMBUFLEN));
|
||||
if (index(dumbuf, '0') ||
|
||||
(index(dumbuf, 'O') && index(dumbuf, 'K')))
|
||||
return(1);
|
||||
#ifdef DEBUG
|
||||
dumbuf[len] = '\0';
|
||||
printf("hay_sync: (\"%s\") %d\n\r", dumbuf, retry);
|
||||
#endif
|
||||
}
|
||||
ioctl(FD, TIOCCDTR, 0);
|
||||
ioctl(FD, TIOCSDTR, 0);
|
||||
}
|
||||
printf("Cannot synchronize with hayes...\n\r");
|
||||
return(0);
|
||||
}
|
408
usr.bin/tip/aculib/t3000.c
Normal file
408
usr.bin/tip/aculib/t3000.c
Normal file
@ -0,0 +1,408 @@
|
||||
/*
|
||||
* 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[] = "@(#)t3000.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Routines for calling up on a Telebit T3000 modem.
|
||||
* Derived from Courier driver.
|
||||
*/
|
||||
#include "tip.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define MAXRETRY 5
|
||||
|
||||
static void sigALRM();
|
||||
static int timeout = 0;
|
||||
static int connected = 0;
|
||||
static jmp_buf timeoutbuf, intbuf;
|
||||
static int t3000_sync();
|
||||
|
||||
t3000_dialer(num, acu)
|
||||
register char *num;
|
||||
char *acu;
|
||||
{
|
||||
register char *cp;
|
||||
#ifdef ACULOG
|
||||
char line[80];
|
||||
#endif
|
||||
static int t3000_connect(), t3000_swallow();
|
||||
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("Using \"%s\"\n", acu);
|
||||
|
||||
ioctl(FD, TIOCHPCL, 0);
|
||||
/*
|
||||
* Get in synch.
|
||||
*/
|
||||
if (!t3000_sync()) {
|
||||
badsynch:
|
||||
printf("can't synchronize with t3000\n");
|
||||
#ifdef ACULOG
|
||||
logent(value(HOST), num, "t3000", "can't synch up");
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
t3000_write(FD, "AT E0\r", 6); /* turn off echoing */
|
||||
sleep(1);
|
||||
#ifdef DEBUG
|
||||
if (boolean(value(VERBOSE)))
|
||||
t3000_verbose_read();
|
||||
#endif
|
||||
ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */
|
||||
t3000_write(FD, "AT E0 H0 Q0 X4 V1\r", 18);
|
||||
if (!t3000_swallow("\r\nOK\r\n"))
|
||||
goto badsynch;
|
||||
fflush(stdout);
|
||||
t3000_write(FD, "AT D", 4);
|
||||
for (cp = num; *cp; cp++)
|
||||
if (*cp == '=')
|
||||
*cp = ',';
|
||||
t3000_write(FD, num, strlen(num));
|
||||
t3000_write(FD, "\r", 1);
|
||||
connected = t3000_connect();
|
||||
#ifdef ACULOG
|
||||
if (timeout) {
|
||||
sprintf(line, "%d second dial timeout",
|
||||
number(value(DIALTIMEOUT)));
|
||||
logent(value(HOST), num, "t3000", line);
|
||||
}
|
||||
#endif
|
||||
if (timeout)
|
||||
t3000_disconnect();
|
||||
return (connected);
|
||||
}
|
||||
|
||||
t3000_disconnect()
|
||||
{
|
||||
/* first hang up the modem*/
|
||||
ioctl(FD, TIOCCDTR, 0);
|
||||
sleep(1);
|
||||
ioctl(FD, TIOCSDTR, 0);
|
||||
t3000_sync(); /* reset */
|
||||
close(FD);
|
||||
}
|
||||
|
||||
t3000_abort()
|
||||
{
|
||||
t3000_write(FD, "\r", 1); /* send anything to abort the call */
|
||||
t3000_disconnect();
|
||||
}
|
||||
|
||||
static void
|
||||
sigALRM()
|
||||
{
|
||||
printf("\07timeout waiting for reply\n");
|
||||
timeout = 1;
|
||||
longjmp(timeoutbuf, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
t3000_swallow(match)
|
||||
register char *match;
|
||||
{
|
||||
sig_t f;
|
||||
char c;
|
||||
|
||||
f = signal(SIGALRM, sigALRM);
|
||||
timeout = 0;
|
||||
do {
|
||||
if (*match =='\0') {
|
||||
signal(SIGALRM, f);
|
||||
return (1);
|
||||
}
|
||||
if (setjmp(timeoutbuf)) {
|
||||
signal(SIGALRM, f);
|
||||
return (0);
|
||||
}
|
||||
alarm(number(value(DIALTIMEOUT)));
|
||||
read(FD, &c, 1);
|
||||
alarm(0);
|
||||
c &= 0177;
|
||||
#ifdef DEBUG
|
||||
if (boolean(value(VERBOSE)))
|
||||
putchar(c);
|
||||
#endif
|
||||
} while (c == *match++);
|
||||
#ifdef DEBUG
|
||||
if (boolean(value(VERBOSE)))
|
||||
fflush(stdout);
|
||||
#endif
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifndef B19200 /* XXX */
|
||||
#define B19200 EXTA
|
||||
#define B38400 EXTB
|
||||
#endif
|
||||
|
||||
struct tbaud_msg {
|
||||
char *msg;
|
||||
int baud;
|
||||
int baud2;
|
||||
} tbaud_msg[] = {
|
||||
"", B300, 0,
|
||||
" 1200", B1200, 0,
|
||||
" 2400", B2400, 0,
|
||||
" 4800", B4800, 0,
|
||||
" 9600", B9600, 0,
|
||||
" 14400", B19200, B9600,
|
||||
" 19200", B19200, B9600,
|
||||
" 38400", B38400, B9600,
|
||||
" 57600", B38400, B9600,
|
||||
" 7512", B9600, 0,
|
||||
" 1275", B2400, 0,
|
||||
" 7200", B9600, 0,
|
||||
" 12000", B19200, B9600,
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
static int
|
||||
t3000_connect()
|
||||
{
|
||||
char c;
|
||||
int nc, nl, n;
|
||||
struct sgttyb sb;
|
||||
char dialer_buf[64];
|
||||
struct tbaud_msg *bm;
|
||||
sig_t f;
|
||||
|
||||
if (t3000_swallow("\r\n") == 0)
|
||||
return (0);
|
||||
f = signal(SIGALRM, sigALRM);
|
||||
again:
|
||||
nc = 0; nl = sizeof(dialer_buf)-1;
|
||||
bzero(dialer_buf, sizeof(dialer_buf));
|
||||
timeout = 0;
|
||||
for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) {
|
||||
if (setjmp(timeoutbuf))
|
||||
break;
|
||||
alarm(number(value(DIALTIMEOUT)));
|
||||
n = read(FD, &c, 1);
|
||||
alarm(0);
|
||||
if (n <= 0)
|
||||
break;
|
||||
c &= 0x7f;
|
||||
if (c == '\r') {
|
||||
if (t3000_swallow("\n") == 0)
|
||||
break;
|
||||
if (!dialer_buf[0])
|
||||
goto again;
|
||||
if (strcmp(dialer_buf, "RINGING") == 0 &&
|
||||
boolean(value(VERBOSE))) {
|
||||
#ifdef DEBUG
|
||||
printf("%s\r\n", dialer_buf);
|
||||
#endif
|
||||
goto again;
|
||||
}
|
||||
if (strncmp(dialer_buf, "CONNECT",
|
||||
sizeof("CONNECT")-1) != 0)
|
||||
break;
|
||||
for (bm = tbaud_msg ; bm->msg ; bm++)
|
||||
if (strcmp(bm->msg,
|
||||
dialer_buf+sizeof("CONNECT")-1) == 0) {
|
||||
if (ioctl(FD, TIOCGETP, &sb) < 0) {
|
||||
perror("TIOCGETP");
|
||||
goto error;
|
||||
}
|
||||
sb.sg_ispeed = sb.sg_ospeed = bm->baud;
|
||||
if (ioctl(FD, TIOCSETP, &sb) < 0) {
|
||||
if (bm->baud2) {
|
||||
sb.sg_ispeed =
|
||||
sb.sg_ospeed =
|
||||
bm->baud2;
|
||||
if (ioctl(FD,
|
||||
TIOCSETP,
|
||||
&sb) >= 0)
|
||||
goto isok;
|
||||
}
|
||||
perror("TIOCSETP");
|
||||
goto error;
|
||||
}
|
||||
isok:
|
||||
signal(SIGALRM, f);
|
||||
#ifdef DEBUG
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("%s\r\n", dialer_buf);
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
dialer_buf[nc] = c;
|
||||
#ifdef notdef
|
||||
if (boolean(value(VERBOSE)))
|
||||
putchar(c);
|
||||
#endif
|
||||
}
|
||||
error1:
|
||||
printf("%s\r\n", dialer_buf);
|
||||
error:
|
||||
signal(SIGALRM, f);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This convoluted piece of code attempts to get
|
||||
* the t3000 in sync.
|
||||
*/
|
||||
static int
|
||||
t3000_sync()
|
||||
{
|
||||
int already = 0;
|
||||
int len;
|
||||
char buf[40];
|
||||
|
||||
while (already++ < MAXRETRY) {
|
||||
ioctl(FD, TIOCFLUSH, 0); /* flush any clutter */
|
||||
t3000_write(FD, "\rAT Z\r", 6); /* reset modem */
|
||||
bzero(buf, sizeof(buf));
|
||||
sleep(2);
|
||||
ioctl(FD, FIONREAD, &len);
|
||||
#if 1
|
||||
if (len == 0) len = 1;
|
||||
#endif
|
||||
if (len) {
|
||||
len = read(FD, buf, sizeof(buf));
|
||||
#ifdef DEBUG
|
||||
buf[len] = '\0';
|
||||
printf("t3000_sync: (\"%s\")\n\r", buf);
|
||||
#endif
|
||||
if (index(buf, '0') ||
|
||||
(index(buf, 'O') && index(buf, 'K')))
|
||||
return(1);
|
||||
}
|
||||
/*
|
||||
* If not strapped for DTR control,
|
||||
* try to get command mode.
|
||||
*/
|
||||
sleep(1);
|
||||
t3000_write(FD, "+++", 3);
|
||||
sleep(1);
|
||||
/*
|
||||
* Toggle DTR to force anyone off that might have left
|
||||
* the modem connected.
|
||||
*/
|
||||
ioctl(FD, TIOCCDTR, 0);
|
||||
sleep(1);
|
||||
ioctl(FD, TIOCSDTR, 0);
|
||||
}
|
||||
t3000_write(FD, "\rAT Z\r", 6);
|
||||
return (0);
|
||||
}
|
||||
|
||||
t3000_write(fd, cp, n)
|
||||
int fd;
|
||||
char *cp;
|
||||
int n;
|
||||
{
|
||||
struct sgttyb sb;
|
||||
|
||||
#ifdef notdef
|
||||
if (boolean(value(VERBOSE)))
|
||||
write(1, cp, n);
|
||||
#endif
|
||||
ioctl(fd, TIOCGETP, &sb);
|
||||
ioctl(fd, TIOCSETP, &sb);
|
||||
t3000_nap();
|
||||
for ( ; n-- ; cp++) {
|
||||
write(fd, cp, 1);
|
||||
ioctl(fd, TIOCGETP, &sb);
|
||||
ioctl(fd, TIOCSETP, &sb);
|
||||
t3000_nap();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
t3000_verbose_read()
|
||||
{
|
||||
int n = 0;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
if (ioctl(FD, FIONREAD, &n) < 0)
|
||||
return;
|
||||
if (n <= 0)
|
||||
return;
|
||||
if (read(FD, buf, n) != n)
|
||||
return;
|
||||
write(1, buf, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Code stolen from /usr/src/lib/libc/gen/sleep.c
|
||||
*/
|
||||
#define mask(s) (1<<((s)-1))
|
||||
#define setvec(vec, a) \
|
||||
vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
|
||||
|
||||
static napms = 50; /* Give the t3000 50 milliseconds between characters */
|
||||
|
||||
static int ringring;
|
||||
|
||||
t3000_nap()
|
||||
{
|
||||
|
||||
static void t3000_napx();
|
||||
int omask;
|
||||
struct itimerval itv, oitv;
|
||||
register struct itimerval *itp = &itv;
|
||||
struct sigvec vec, ovec;
|
||||
|
||||
timerclear(&itp->it_interval);
|
||||
timerclear(&itp->it_value);
|
||||
if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
|
||||
return;
|
||||
setvec(ovec, SIG_DFL);
|
||||
omask = sigblock(mask(SIGALRM));
|
||||
itp->it_value.tv_sec = napms/1000;
|
||||
itp->it_value.tv_usec = ((napms%1000)*1000);
|
||||
setvec(vec, t3000_napx);
|
||||
ringring = 0;
|
||||
(void) sigvec(SIGALRM, &vec, &ovec);
|
||||
(void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
|
||||
while (!ringring)
|
||||
sigpause(omask &~ mask(SIGALRM));
|
||||
(void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
|
||||
(void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
|
||||
(void) sigsetmask(omask);
|
||||
}
|
||||
|
||||
static void
|
||||
t3000_napx()
|
||||
{
|
||||
ringring = 1;
|
||||
}
|
214
usr.bin/tip/aculib/v3451.c
Normal file
214
usr.bin/tip/aculib/v3451.c
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* 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[] = "@(#)v3451.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Routines for calling up on a Vadic 3451 Modem
|
||||
*/
|
||||
#include "tip.h"
|
||||
|
||||
static jmp_buf Sjbuf;
|
||||
|
||||
v3451_dialer(num, acu)
|
||||
register char *num;
|
||||
char *acu;
|
||||
{
|
||||
sig_t func;
|
||||
int ok;
|
||||
int slow = number(value(BAUDRATE)) < 1200, rw = 2;
|
||||
char phone[50];
|
||||
#ifdef ACULOG
|
||||
char line[80];
|
||||
#endif
|
||||
static int expect();
|
||||
static void vawrite();
|
||||
|
||||
/*
|
||||
* Get in synch
|
||||
*/
|
||||
vawrite("I\r", 1 + slow);
|
||||
vawrite("I\r", 1 + slow);
|
||||
vawrite("I\r", 1 + slow);
|
||||
vawrite("\005\r", 2 + slow);
|
||||
if (!expect("READY")) {
|
||||
printf("can't synchronize with vadic 3451\n");
|
||||
#ifdef ACULOG
|
||||
logent(value(HOST), num, "vadic", "can't synch up");
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
ioctl(FD, TIOCHPCL, 0);
|
||||
sleep(1);
|
||||
vawrite("D\r", 2 + slow);
|
||||
if (!expect("NUMBER?")) {
|
||||
printf("Vadic will not accept dial command\n");
|
||||
#ifdef ACULOG
|
||||
logent(value(HOST), num, "vadic", "will not accept dial");
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
strcpy(phone, num);
|
||||
strcat(phone, "\r");
|
||||
vawrite(phone, 1 + slow);
|
||||
if (!expect(phone)) {
|
||||
printf("Vadic will not accept phone number\n");
|
||||
#ifdef ACULOG
|
||||
logent(value(HOST), num, "vadic", "will not accept number");
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
func = signal(SIGINT,SIG_IGN);
|
||||
/*
|
||||
* You cannot interrupt the Vadic when its dialing;
|
||||
* even dropping DTR does not work (definitely a
|
||||
* brain damaged design).
|
||||
*/
|
||||
vawrite("\r", 1 + slow);
|
||||
vawrite("\r", 1 + slow);
|
||||
if (!expect("DIALING:")) {
|
||||
printf("Vadic failed to dial\n");
|
||||
#ifdef ACULOG
|
||||
logent(value(HOST), num, "vadic", "failed to dial");
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("\ndialing...");
|
||||
ok = expect("ON LINE");
|
||||
signal(SIGINT, func);
|
||||
if (!ok) {
|
||||
printf("call failed\n");
|
||||
#ifdef ACULOG
|
||||
logent(value(HOST), num, "vadic", "call failed");
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
ioctl(FD, TIOCFLUSH, &rw);
|
||||
return (1);
|
||||
}
|
||||
|
||||
v3451_disconnect()
|
||||
{
|
||||
|
||||
close(FD);
|
||||
}
|
||||
|
||||
v3451_abort()
|
||||
{
|
||||
|
||||
close(FD);
|
||||
}
|
||||
|
||||
static void
|
||||
vawrite(cp, delay)
|
||||
register char *cp;
|
||||
int delay;
|
||||
{
|
||||
|
||||
for (; *cp; sleep(delay), cp++)
|
||||
write(FD, cp, 1);
|
||||
}
|
||||
|
||||
static
|
||||
expect(cp)
|
||||
register char *cp;
|
||||
{
|
||||
char buf[300];
|
||||
register char *rp = buf;
|
||||
int timeout = 30, online = 0;
|
||||
static int notin();
|
||||
static void alarmtr();
|
||||
|
||||
if (strcmp(cp, "\"\"") == 0)
|
||||
return (1);
|
||||
*rp = 0;
|
||||
/*
|
||||
* If we are waiting for the Vadic to complete
|
||||
* dialing and get a connection, allow more time
|
||||
* Unfortunately, the Vadic times out 24 seconds after
|
||||
* the last digit is dialed
|
||||
*/
|
||||
online = strcmp(cp, "ON LINE") == 0;
|
||||
if (online)
|
||||
timeout = number(value(DIALTIMEOUT));
|
||||
signal(SIGALRM, alarmtr);
|
||||
if (setjmp(Sjbuf))
|
||||
return (0);
|
||||
alarm(timeout);
|
||||
while (notin(cp, buf) && rp < buf + sizeof (buf) - 1) {
|
||||
if (online && notin("FAILED CALL", buf) == 0)
|
||||
return (0);
|
||||
if (read(FD, rp, 1) < 0) {
|
||||
alarm(0);
|
||||
return (0);
|
||||
}
|
||||
if (*rp &= 0177)
|
||||
rp++;
|
||||
*rp = '\0';
|
||||
}
|
||||
alarm(0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
alarmtr()
|
||||
{
|
||||
longjmp(Sjbuf, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
notin(sh, lg)
|
||||
char *sh, *lg;
|
||||
{
|
||||
static int prefix();
|
||||
|
||||
for (; *lg; lg++)
|
||||
if (prefix(sh, lg))
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static
|
||||
prefix(s1, s2)
|
||||
register char *s1, *s2;
|
||||
{
|
||||
register char c;
|
||||
|
||||
while ((c = *s1++) == *s2++)
|
||||
if (c == '\0')
|
||||
return (1);
|
||||
return (c == '\0');
|
||||
}
|
259
usr.bin/tip/aculib/v831.c
Normal file
259
usr.bin/tip/aculib/v831.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 sccsid[] = "@(#)v831.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Routines for dialing up on Vadic 831
|
||||
*/
|
||||
#include "tip.h"
|
||||
|
||||
int v831_abort();
|
||||
static void alarmtr();
|
||||
extern int errno;
|
||||
|
||||
static jmp_buf jmpbuf;
|
||||
static int child = -1;
|
||||
|
||||
v831_dialer(num, acu)
|
||||
char *num, *acu;
|
||||
{
|
||||
int status, pid, connected = 1;
|
||||
register int timelim;
|
||||
static int dialit();
|
||||
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("\nstarting call...");
|
||||
#ifdef DEBUG
|
||||
printf ("(acu=%s)\n", acu);
|
||||
#endif
|
||||
if ((AC = open(acu, O_RDWR)) < 0) {
|
||||
if (errno == EBUSY)
|
||||
printf("line busy...");
|
||||
else
|
||||
printf("acu open error...");
|
||||
return (0);
|
||||
}
|
||||
if (setjmp(jmpbuf)) {
|
||||
kill(child, SIGKILL);
|
||||
close(AC);
|
||||
return (0);
|
||||
}
|
||||
signal(SIGALRM, alarmtr);
|
||||
timelim = 5 * strlen(num);
|
||||
alarm(timelim < 30 ? 30 : timelim);
|
||||
if ((child = fork()) == 0) {
|
||||
/*
|
||||
* ignore this stuff for aborts
|
||||
*/
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
sleep(2);
|
||||
exit(dialit(num, acu) != 'A');
|
||||
}
|
||||
/*
|
||||
* open line - will return on carrier
|
||||
*/
|
||||
if ((FD = open(DV, O_RDWR)) < 0) {
|
||||
#ifdef DEBUG
|
||||
printf("(after open, errno=%d)\n", errno);
|
||||
#endif
|
||||
if (errno == EIO)
|
||||
printf("lost carrier...");
|
||||
else
|
||||
printf("dialup line open failed...");
|
||||
alarm(0);
|
||||
kill(child, SIGKILL);
|
||||
close(AC);
|
||||
return (0);
|
||||
}
|
||||
alarm(0);
|
||||
#ifdef notdef
|
||||
ioctl(AC, TIOCHPCL, 0);
|
||||
#endif
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
while ((pid = wait(&status)) != child && pid != -1)
|
||||
;
|
||||
if (status) {
|
||||
close(AC);
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
alarmtr()
|
||||
{
|
||||
alarm(0);
|
||||
longjmp(jmpbuf, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insurance, for some reason we don't seem to be
|
||||
* hanging up...
|
||||
*/
|
||||
v831_disconnect()
|
||||
{
|
||||
struct sgttyb cntrl;
|
||||
|
||||
sleep(2);
|
||||
#ifdef DEBUG
|
||||
printf("[disconnect: FD=%d]\n", FD);
|
||||
#endif
|
||||
if (FD > 0) {
|
||||
ioctl(FD, TIOCCDTR, 0);
|
||||
ioctl(FD, TIOCGETP, &cntrl);
|
||||
cntrl.sg_ispeed = cntrl.sg_ospeed = 0;
|
||||
ioctl(FD, TIOCSETP, &cntrl);
|
||||
ioctl(FD, TIOCNXCL, (struct sgttyb *)NULL);
|
||||
}
|
||||
close(FD);
|
||||
}
|
||||
|
||||
v831_abort()
|
||||
{
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[abort: AC=%d]\n", AC);
|
||||
#endif
|
||||
sleep(2);
|
||||
if (child > 0)
|
||||
kill(child, SIGKILL);
|
||||
if (AC > 0)
|
||||
ioctl(FD, TIOCNXCL, (struct sgttyb *)NULL);
|
||||
close(AC);
|
||||
if (FD > 0)
|
||||
ioctl(FD, TIOCCDTR, 0);
|
||||
close(FD);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sigh, this probably must be changed at each site.
|
||||
*/
|
||||
struct vaconfig {
|
||||
char *vc_name;
|
||||
char vc_rack;
|
||||
char vc_modem;
|
||||
} vaconfig[] = {
|
||||
{ "/dev/cua0",'4','0' },
|
||||
{ "/dev/cua1",'4','1' },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
#define pc(x) (c = x, write(AC,&c,1))
|
||||
#define ABORT 01
|
||||
#define SI 017
|
||||
#define STX 02
|
||||
#define ETX 03
|
||||
|
||||
static int
|
||||
dialit(phonenum, acu)
|
||||
register char *phonenum;
|
||||
char *acu;
|
||||
{
|
||||
register struct vaconfig *vp;
|
||||
struct sgttyb cntrl;
|
||||
char c;
|
||||
int i, two = 2;
|
||||
static char *sanitize();
|
||||
|
||||
phonenum = sanitize(phonenum);
|
||||
#ifdef DEBUG
|
||||
printf ("(dial phonenum=%s)\n", phonenum);
|
||||
#endif
|
||||
if (*phonenum == '<' && phonenum[1] == 0)
|
||||
return ('Z');
|
||||
for (vp = vaconfig; vp->vc_name; vp++)
|
||||
if (strcmp(vp->vc_name, acu) == 0)
|
||||
break;
|
||||
if (vp->vc_name == 0) {
|
||||
printf("Unable to locate dialer (%s)\n", acu);
|
||||
return ('K');
|
||||
}
|
||||
ioctl(AC, TIOCGETP, &cntrl);
|
||||
cntrl.sg_ispeed = cntrl.sg_ospeed = B2400;
|
||||
cntrl.sg_flags = RAW | EVENP | ODDP;
|
||||
ioctl(AC, TIOCSETP, &cntrl);
|
||||
ioctl(AC, TIOCFLUSH, &two);
|
||||
pc(STX);
|
||||
pc(vp->vc_rack);
|
||||
pc(vp->vc_modem);
|
||||
while (*phonenum && *phonenum != '<')
|
||||
pc(*phonenum++);
|
||||
pc(SI);
|
||||
pc(ETX);
|
||||
sleep(1);
|
||||
i = read(AC, &c, 1);
|
||||
#ifdef DEBUG
|
||||
printf("read %d chars, char=%c, errno %d\n", i, c, errno);
|
||||
#endif
|
||||
if (i != 1)
|
||||
c = 'M';
|
||||
if (c == 'B' || c == 'G') {
|
||||
char cc, oc = c;
|
||||
|
||||
pc(ABORT);
|
||||
read(AC, &cc, 1);
|
||||
#ifdef DEBUG
|
||||
printf("abort response=%c\n", cc);
|
||||
#endif
|
||||
c = oc;
|
||||
v831_disconnect();
|
||||
}
|
||||
close(AC);
|
||||
#ifdef DEBUG
|
||||
printf("dialit: returns %c\n", c);
|
||||
#endif
|
||||
return (c);
|
||||
}
|
||||
|
||||
static char *
|
||||
sanitize(s)
|
||||
register char *s;
|
||||
{
|
||||
static char buf[128];
|
||||
register char *cp;
|
||||
|
||||
for (cp = buf; *s; s++) {
|
||||
if (!isdigit(*s) && *s == '<' && *s != '_')
|
||||
continue;
|
||||
if (*s == '_')
|
||||
*s = '=';
|
||||
*cp++ = *s;
|
||||
}
|
||||
*cp++ = 0;
|
||||
return (buf);
|
||||
}
|
251
usr.bin/tip/aculib/ventel.c
Normal file
251
usr.bin/tip/aculib/ventel.c
Normal file
@ -0,0 +1,251 @@
|
||||
/*
|
||||
* 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[] = "@(#)ventel.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Routines for calling up on a Ventel Modem
|
||||
* The Ventel is expected to be strapped for local echo (just like uucp)
|
||||
*/
|
||||
#include "tip.h"
|
||||
|
||||
#define MAXRETRY 5
|
||||
|
||||
static void sigALRM();
|
||||
static int timeout = 0;
|
||||
static jmp_buf timeoutbuf;
|
||||
|
||||
/*
|
||||
* some sleep calls have been replaced by this macro
|
||||
* because some ventel modems require two <cr>s in less than
|
||||
* a second in order to 'wake up'... yes, it is dirty...
|
||||
*/
|
||||
#define delay(num,denom) busyloop(CPUSPEED*num/denom)
|
||||
#define CPUSPEED 1000000 /* VAX 780 is 1MIPS */
|
||||
#define DELAY(n) { register long N = (n); while (--N > 0); }
|
||||
busyloop(n) { DELAY(n); }
|
||||
|
||||
ven_dialer(num, acu)
|
||||
register char *num;
|
||||
char *acu;
|
||||
{
|
||||
register char *cp;
|
||||
register int connected = 0;
|
||||
char *msg, *index(), line[80];
|
||||
static int gobble(), vensync();
|
||||
static void echo();
|
||||
|
||||
/*
|
||||
* Get in synch with a couple of carriage returns
|
||||
*/
|
||||
if (!vensync(FD)) {
|
||||
printf("can't synchronize with ventel\n");
|
||||
#ifdef ACULOG
|
||||
logent(value(HOST), num, "ventel", "can't synch up");
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("\ndialing...");
|
||||
fflush(stdout);
|
||||
ioctl(FD, TIOCHPCL, 0);
|
||||
echo("#k$\r$\n$D$I$A$L$:$ ");
|
||||
for (cp = num; *cp; cp++) {
|
||||
delay(1, 10);
|
||||
write(FD, cp, 1);
|
||||
}
|
||||
delay(1, 10);
|
||||
write(FD, "\r", 1);
|
||||
gobble('\n', line);
|
||||
if (gobble('\n', line))
|
||||
connected = gobble('!', line);
|
||||
ioctl(FD, TIOCFLUSH);
|
||||
#ifdef ACULOG
|
||||
if (timeout) {
|
||||
sprintf(line, "%d second dial timeout",
|
||||
number(value(DIALTIMEOUT)));
|
||||
logent(value(HOST), num, "ventel", line);
|
||||
}
|
||||
#endif
|
||||
if (timeout)
|
||||
ven_disconnect(); /* insurance */
|
||||
if (connected || timeout || !boolean(value(VERBOSE)))
|
||||
return (connected);
|
||||
/* call failed, parse response for user */
|
||||
cp = index(line, '\r');
|
||||
if (cp)
|
||||
*cp = '\0';
|
||||
for (cp = line; cp = index(cp, ' '); cp++)
|
||||
if (cp[1] == ' ')
|
||||
break;
|
||||
if (cp) {
|
||||
while (*cp == ' ')
|
||||
cp++;
|
||||
msg = cp;
|
||||
while (*cp) {
|
||||
if (isupper(*cp))
|
||||
*cp = tolower(*cp);
|
||||
cp++;
|
||||
}
|
||||
printf("%s...", msg);
|
||||
}
|
||||
return (connected);
|
||||
}
|
||||
|
||||
ven_disconnect()
|
||||
{
|
||||
|
||||
close(FD);
|
||||
}
|
||||
|
||||
ven_abort()
|
||||
{
|
||||
|
||||
write(FD, "\03", 1);
|
||||
close(FD);
|
||||
}
|
||||
|
||||
static void
|
||||
echo(s)
|
||||
register char *s;
|
||||
{
|
||||
char c;
|
||||
|
||||
while (c = *s++) switch (c) {
|
||||
|
||||
case '$':
|
||||
read(FD, &c, 1);
|
||||
s++;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
c = *s++;
|
||||
write(FD, &c, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
write(FD, &c, 1);
|
||||
read(FD, &c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sigALRM()
|
||||
{
|
||||
printf("\07timeout waiting for reply\n");
|
||||
timeout = 1;
|
||||
longjmp(timeoutbuf, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
gobble(match, response)
|
||||
register char match;
|
||||
char response[];
|
||||
{
|
||||
register char *cp = response;
|
||||
sig_t f;
|
||||
char c;
|
||||
|
||||
f = signal(SIGALRM, sigALRM);
|
||||
timeout = 0;
|
||||
do {
|
||||
if (setjmp(timeoutbuf)) {
|
||||
signal(SIGALRM, f);
|
||||
*cp = '\0';
|
||||
return (0);
|
||||
}
|
||||
alarm(number(value(DIALTIMEOUT)));
|
||||
read(FD, cp, 1);
|
||||
alarm(0);
|
||||
c = (*cp++ &= 0177);
|
||||
#ifdef notdef
|
||||
if (boolean(value(VERBOSE)))
|
||||
putchar(c);
|
||||
#endif
|
||||
} while (c != '\n' && c != match);
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
*cp = '\0';
|
||||
return (c == match);
|
||||
}
|
||||
|
||||
#define min(a,b) ((a)>(b)?(b):(a))
|
||||
/*
|
||||
* This convoluted piece of code attempts to get
|
||||
* the ventel in sync. If you don't have FIONREAD
|
||||
* there are gory ways to simulate this.
|
||||
*/
|
||||
static int
|
||||
vensync(fd)
|
||||
{
|
||||
int already = 0, nread;
|
||||
char buf[60];
|
||||
|
||||
/*
|
||||
* Toggle DTR to force anyone off that might have left
|
||||
* the modem connected, and insure a consistent state
|
||||
* to start from.
|
||||
*
|
||||
* If you don't have the ioctl calls to diddle directly
|
||||
* with DTR, you can always try setting the baud rate to 0.
|
||||
*/
|
||||
ioctl(FD, TIOCCDTR, 0);
|
||||
sleep(1);
|
||||
ioctl(FD, TIOCSDTR, 0);
|
||||
while (already < MAXRETRY) {
|
||||
/*
|
||||
* After reseting the modem, send it two \r's to
|
||||
* autobaud on. Make sure to delay between them
|
||||
* so the modem can frame the incoming characters.
|
||||
*/
|
||||
write(fd, "\r", 1);
|
||||
delay(1,10);
|
||||
write(fd, "\r", 1);
|
||||
sleep(2);
|
||||
if (ioctl(fd, FIONREAD, (caddr_t)&nread) < 0) {
|
||||
perror("tip: ioctl");
|
||||
continue;
|
||||
}
|
||||
while (nread > 0) {
|
||||
read(fd, buf, min(nread, 60));
|
||||
if ((buf[nread - 1] & 0177) == '$')
|
||||
return (1);
|
||||
nread -= min(nread, 60);
|
||||
}
|
||||
sleep(1);
|
||||
already++;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
97
usr.bin/tip/acutab.c
Normal file
97
usr.bin/tip/acutab.c
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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[] = "@(#)acutab.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "tip.h"
|
||||
|
||||
extern int df02_dialer(), df03_dialer(), df_disconnect(), df_abort(),
|
||||
biz31f_dialer(), biz31_disconnect(), biz31_abort(),
|
||||
biz31w_dialer(),
|
||||
biz22f_dialer(), biz22_disconnect(), biz22_abort(),
|
||||
biz22w_dialer(),
|
||||
ven_dialer(), ven_disconnect(), ven_abort(),
|
||||
hay_dialer(), hay_disconnect(), hay_abort(),
|
||||
cour_dialer(), cour_disconnect(), cour_abort(),
|
||||
t3000_dialer(), t3000_disconnect(), t3000_abort(),
|
||||
v3451_dialer(), v3451_disconnect(), v3451_abort(),
|
||||
v831_dialer(), v831_disconnect(), v831_abort(),
|
||||
dn_dialer(), dn_disconnect(), dn_abort();
|
||||
|
||||
acu_t acutable[] = {
|
||||
#if BIZ1031
|
||||
"biz31f", biz31f_dialer, biz31_disconnect, biz31_abort,
|
||||
"biz31w", biz31w_dialer, biz31_disconnect, biz31_abort,
|
||||
#endif
|
||||
#if BIZ1022
|
||||
"biz22f", biz22f_dialer, biz22_disconnect, biz22_abort,
|
||||
"biz22w", biz22w_dialer, biz22_disconnect, biz22_abort,
|
||||
#endif
|
||||
#if DF02
|
||||
"df02", df02_dialer, df_disconnect, df_abort,
|
||||
#endif
|
||||
#if DF03
|
||||
"df03", df03_dialer, df_disconnect, df_abort,
|
||||
#endif
|
||||
#if DN11
|
||||
"dn11", dn_dialer, dn_disconnect, dn_abort,
|
||||
#endif
|
||||
#ifdef VENTEL
|
||||
"ventel",ven_dialer, ven_disconnect, ven_abort,
|
||||
#endif
|
||||
#ifdef HAYES
|
||||
"hayes",hay_dialer, hay_disconnect, hay_abort,
|
||||
#endif
|
||||
#ifdef COURIER
|
||||
"courier",cour_dialer, cour_disconnect, cour_abort,
|
||||
#endif
|
||||
#ifdef T3000
|
||||
"t3000",t3000_dialer, t3000_disconnect, t3000_abort,
|
||||
#endif
|
||||
#ifdef V3451
|
||||
#ifndef V831
|
||||
"vadic",v3451_dialer, v3451_disconnect, v3451_abort,
|
||||
#endif
|
||||
"v3451",v3451_dialer, v3451_disconnect, v3451_abort,
|
||||
#endif
|
||||
#ifdef V831
|
||||
#ifndef V3451
|
||||
"vadic",v831_dialer, v831_disconnect, v831_abort,
|
||||
#endif
|
||||
"v831",v831_dialer, v831_disconnect, v831_abort,
|
||||
#endif
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
888
usr.bin/tip/cmds.c
Normal file
888
usr.bin/tip/cmds.c
Normal file
@ -0,0 +1,888 @@
|
||||
/*
|
||||
* 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[] = "@(#)cmds.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "tip.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
/*
|
||||
* tip
|
||||
*
|
||||
* miscellaneous commands
|
||||
*/
|
||||
|
||||
int quant[] = { 60, 60, 24 };
|
||||
|
||||
char null = '\0';
|
||||
char *sep[] = { "second", "minute", "hour" };
|
||||
static char *argv[10]; /* argument vector for take and put */
|
||||
|
||||
void timeout(); /* timeout function called on alarm */
|
||||
void stopsnd(); /* SIGINT handler during file transfers */
|
||||
void intcopy(); /* interrupt routine for file transfers */
|
||||
|
||||
/*
|
||||
* FTP - remote ==> local
|
||||
* get a file from the remote host
|
||||
*/
|
||||
getfl(c)
|
||||
char c;
|
||||
{
|
||||
char buf[256], *cp, *expand();
|
||||
|
||||
putchar(c);
|
||||
/*
|
||||
* get the UNIX receiving file's name
|
||||
*/
|
||||
if (prompt("Local file name? ", copyname))
|
||||
return;
|
||||
cp = expand(copyname);
|
||||
if ((sfd = creat(cp, 0666)) < 0) {
|
||||
printf("\r\n%s: cannot creat\r\n", copyname);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* collect parameters
|
||||
*/
|
||||
if (prompt("List command for remote system? ", buf)) {
|
||||
unlink(copyname);
|
||||
return;
|
||||
}
|
||||
transfer(buf, sfd, value(EOFREAD));
|
||||
}
|
||||
|
||||
/*
|
||||
* Cu-like take command
|
||||
*/
|
||||
cu_take(cc)
|
||||
char cc;
|
||||
{
|
||||
int fd, argc;
|
||||
char line[BUFSIZ], *expand(), *cp;
|
||||
|
||||
if (prompt("[take] ", copyname))
|
||||
return;
|
||||
if ((argc = args(copyname, argv)) < 1 || argc > 2) {
|
||||
printf("usage: <take> from [to]\r\n");
|
||||
return;
|
||||
}
|
||||
if (argc == 1)
|
||||
argv[1] = argv[0];
|
||||
cp = expand(argv[1]);
|
||||
if ((fd = creat(cp, 0666)) < 0) {
|
||||
printf("\r\n%s: cannot create\r\n", argv[1]);
|
||||
return;
|
||||
}
|
||||
sprintf(line, "cat %s;echo \01", argv[0]);
|
||||
transfer(line, fd, "\01");
|
||||
}
|
||||
|
||||
static jmp_buf intbuf;
|
||||
/*
|
||||
* Bulk transfer routine --
|
||||
* used by getfl(), cu_take(), and pipefile()
|
||||
*/
|
||||
transfer(buf, fd, eofchars)
|
||||
char *buf, *eofchars;
|
||||
{
|
||||
register int ct;
|
||||
char c, buffer[BUFSIZ];
|
||||
register char *p = buffer;
|
||||
register int cnt, eof;
|
||||
time_t start;
|
||||
sig_t f;
|
||||
char r;
|
||||
|
||||
pwrite(FD, buf, size(buf));
|
||||
quit = 0;
|
||||
kill(pid, SIGIOT);
|
||||
read(repdes[0], (char *)&ccc, 1); /* Wait until read process stops */
|
||||
|
||||
/*
|
||||
* finish command
|
||||
*/
|
||||
r = '\r';
|
||||
pwrite(FD, &r, 1);
|
||||
do
|
||||
read(FD, &c, 1);
|
||||
while ((c&0177) != '\n');
|
||||
ioctl(0, TIOCSETC, &defchars);
|
||||
|
||||
(void) setjmp(intbuf);
|
||||
f = signal(SIGINT, intcopy);
|
||||
start = time(0);
|
||||
for (ct = 0; !quit;) {
|
||||
eof = read(FD, &c, 1) <= 0;
|
||||
c &= 0177;
|
||||
if (quit)
|
||||
continue;
|
||||
if (eof || any(c, eofchars))
|
||||
break;
|
||||
if (c == 0)
|
||||
continue; /* ignore nulls */
|
||||
if (c == '\r')
|
||||
continue;
|
||||
*p++ = c;
|
||||
|
||||
if (c == '\n' && boolean(value(VERBOSE)))
|
||||
printf("\r%d", ++ct);
|
||||
if ((cnt = (p-buffer)) == number(value(FRAMESIZE))) {
|
||||
if (write(fd, buffer, cnt) != cnt) {
|
||||
printf("\r\nwrite error\r\n");
|
||||
quit = 1;
|
||||
}
|
||||
p = buffer;
|
||||
}
|
||||
}
|
||||
if (cnt = (p-buffer))
|
||||
if (write(fd, buffer, cnt) != cnt)
|
||||
printf("\r\nwrite error\r\n");
|
||||
|
||||
if (boolean(value(VERBOSE)))
|
||||
prtime(" lines transferred in ", time(0)-start);
|
||||
ioctl(0, TIOCSETC, &tchars);
|
||||
write(fildes[1], (char *)&ccc, 1);
|
||||
signal(SIGINT, f);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* FTP - remote ==> local process
|
||||
* send remote input to local process via pipe
|
||||
*/
|
||||
pipefile()
|
||||
{
|
||||
int cpid, pdes[2];
|
||||
char buf[256];
|
||||
int status, p;
|
||||
extern int errno;
|
||||
|
||||
if (prompt("Local command? ", buf))
|
||||
return;
|
||||
|
||||
if (pipe(pdes)) {
|
||||
printf("can't establish pipe\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cpid = fork()) < 0) {
|
||||
printf("can't fork!\r\n");
|
||||
return;
|
||||
} else if (cpid) {
|
||||
if (prompt("List command for remote system? ", buf)) {
|
||||
close(pdes[0]), close(pdes[1]);
|
||||
kill (cpid, SIGKILL);
|
||||
} else {
|
||||
close(pdes[0]);
|
||||
signal(SIGPIPE, intcopy);
|
||||
transfer(buf, pdes[1], value(EOFREAD));
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
while ((p = wait(&status)) > 0 && p != cpid)
|
||||
;
|
||||
}
|
||||
} else {
|
||||
register int f;
|
||||
|
||||
dup2(pdes[0], 0);
|
||||
close(pdes[0]);
|
||||
for (f = 3; f < 20; f++)
|
||||
close(f);
|
||||
execute(buf);
|
||||
printf("can't execl!\r\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt service routine for FTP
|
||||
*/
|
||||
void
|
||||
stopsnd()
|
||||
{
|
||||
|
||||
stop = 1;
|
||||
signal(SIGINT, SIG_IGN);
|
||||
}
|
||||
|
||||
/*
|
||||
* FTP - local ==> remote
|
||||
* send local file to remote host
|
||||
* terminate transmission with pseudo EOF sequence
|
||||
*/
|
||||
sendfile(cc)
|
||||
char cc;
|
||||
{
|
||||
FILE *fd;
|
||||
char *fnamex;
|
||||
char *expand();
|
||||
|
||||
putchar(cc);
|
||||
/*
|
||||
* get file name
|
||||
*/
|
||||
if (prompt("Local file name? ", fname))
|
||||
return;
|
||||
|
||||
/*
|
||||
* look up file
|
||||
*/
|
||||
fnamex = expand(fname);
|
||||
if ((fd = fopen(fnamex, "r")) == NULL) {
|
||||
printf("%s: cannot open\r\n", fname);
|
||||
return;
|
||||
}
|
||||
transmit(fd, value(EOFWRITE), NULL);
|
||||
if (!boolean(value(ECHOCHECK))) {
|
||||
struct sgttyb buf;
|
||||
|
||||
ioctl(FD, TIOCGETP, &buf); /* this does a */
|
||||
ioctl(FD, TIOCSETP, &buf); /* wflushtty */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Bulk transfer routine to remote host --
|
||||
* used by sendfile() and cu_put()
|
||||
*/
|
||||
transmit(fd, eofchars, command)
|
||||
FILE *fd;
|
||||
char *eofchars, *command;
|
||||
{
|
||||
char *pc, lastc;
|
||||
int c, ccount, lcount;
|
||||
time_t start_t, stop_t;
|
||||
sig_t f;
|
||||
|
||||
kill(pid, SIGIOT); /* put TIPOUT into a wait state */
|
||||
stop = 0;
|
||||
f = signal(SIGINT, stopsnd);
|
||||
ioctl(0, TIOCSETC, &defchars);
|
||||
read(repdes[0], (char *)&ccc, 1);
|
||||
if (command != NULL) {
|
||||
for (pc = command; *pc; pc++)
|
||||
send(*pc);
|
||||
if (boolean(value(ECHOCHECK)))
|
||||
read(FD, (char *)&c, 1); /* trailing \n */
|
||||
else {
|
||||
struct sgttyb buf;
|
||||
|
||||
ioctl(FD, TIOCGETP, &buf); /* this does a */
|
||||
ioctl(FD, TIOCSETP, &buf); /* wflushtty */
|
||||
sleep(5); /* wait for remote stty to take effect */
|
||||
}
|
||||
}
|
||||
lcount = 0;
|
||||
lastc = '\0';
|
||||
start_t = time(0);
|
||||
while (1) {
|
||||
ccount = 0;
|
||||
do {
|
||||
c = getc(fd);
|
||||
if (stop)
|
||||
goto out;
|
||||
if (c == EOF)
|
||||
goto out;
|
||||
if (c == 0177 && !boolean(value(RAWFTP)))
|
||||
continue;
|
||||
lastc = c;
|
||||
if (c < 040) {
|
||||
if (c == '\n') {
|
||||
if (!boolean(value(RAWFTP)))
|
||||
c = '\r';
|
||||
}
|
||||
else if (c == '\t') {
|
||||
if (!boolean(value(RAWFTP))) {
|
||||
if (boolean(value(TABEXPAND))) {
|
||||
send(' ');
|
||||
while ((++ccount % 8) != 0)
|
||||
send(' ');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (!boolean(value(RAWFTP)))
|
||||
continue;
|
||||
}
|
||||
send(c);
|
||||
} while (c != '\r' && !boolean(value(RAWFTP)));
|
||||
if (boolean(value(VERBOSE)))
|
||||
printf("\r%d", ++lcount);
|
||||
if (boolean(value(ECHOCHECK))) {
|
||||
timedout = 0;
|
||||
alarm((int)value(ETIMEOUT));
|
||||
do { /* wait for prompt */
|
||||
read(FD, (char *)&c, 1);
|
||||
if (timedout || stop) {
|
||||
if (timedout)
|
||||
printf("\r\ntimed out at eol\r\n");
|
||||
alarm(0);
|
||||
goto out;
|
||||
}
|
||||
} while ((c&0177) != character(value(PROMPT)));
|
||||
alarm(0);
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (lastc != '\n' && !boolean(value(RAWFTP)))
|
||||
send('\r');
|
||||
for (pc = eofchars; *pc; pc++)
|
||||
send(*pc);
|
||||
stop_t = time(0);
|
||||
fclose(fd);
|
||||
signal(SIGINT, f);
|
||||
if (boolean(value(VERBOSE)))
|
||||
if (boolean(value(RAWFTP)))
|
||||
prtime(" chars transferred in ", stop_t-start_t);
|
||||
else
|
||||
prtime(" lines transferred in ", stop_t-start_t);
|
||||
write(fildes[1], (char *)&ccc, 1);
|
||||
ioctl(0, TIOCSETC, &tchars);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cu-like put command
|
||||
*/
|
||||
cu_put(cc)
|
||||
char cc;
|
||||
{
|
||||
FILE *fd;
|
||||
char line[BUFSIZ];
|
||||
int argc;
|
||||
char *expand();
|
||||
char *copynamex;
|
||||
|
||||
if (prompt("[put] ", copyname))
|
||||
return;
|
||||
if ((argc = args(copyname, argv)) < 1 || argc > 2) {
|
||||
printf("usage: <put> from [to]\r\n");
|
||||
return;
|
||||
}
|
||||
if (argc == 1)
|
||||
argv[1] = argv[0];
|
||||
copynamex = expand(argv[0]);
|
||||
if ((fd = fopen(copynamex, "r")) == NULL) {
|
||||
printf("%s: cannot open\r\n", copynamex);
|
||||
return;
|
||||
}
|
||||
if (boolean(value(ECHOCHECK)))
|
||||
sprintf(line, "cat>%s\r", argv[1]);
|
||||
else
|
||||
sprintf(line, "stty -echo;cat>%s;stty echo\r", argv[1]);
|
||||
transmit(fd, "\04", line);
|
||||
}
|
||||
|
||||
/*
|
||||
* FTP - send single character
|
||||
* wait for echo & handle timeout
|
||||
*/
|
||||
send(c)
|
||||
char c;
|
||||
{
|
||||
char cc;
|
||||
int retry = 0;
|
||||
|
||||
cc = c;
|
||||
pwrite(FD, &cc, 1);
|
||||
#ifdef notdef
|
||||
if (number(value(CDELAY)) > 0 && c != '\r')
|
||||
nap(number(value(CDELAY)));
|
||||
#endif
|
||||
if (!boolean(value(ECHOCHECK))) {
|
||||
#ifdef notdef
|
||||
if (number(value(LDELAY)) > 0 && c == '\r')
|
||||
nap(number(value(LDELAY)));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
tryagain:
|
||||
timedout = 0;
|
||||
alarm((int)value(ETIMEOUT));
|
||||
read(FD, &cc, 1);
|
||||
alarm(0);
|
||||
if (timedout) {
|
||||
printf("\r\ntimeout error (%s)\r\n", ctrl(c));
|
||||
if (retry++ > 3)
|
||||
return;
|
||||
pwrite(FD, &null, 1); /* poke it */
|
||||
goto tryagain;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
timeout()
|
||||
{
|
||||
signal(SIGALRM, timeout);
|
||||
timedout = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stolen from consh() -- puts a remote file on the output of a local command.
|
||||
* Identical to consh() except for where stdout goes.
|
||||
*/
|
||||
pipeout(c)
|
||||
{
|
||||
char buf[256];
|
||||
int cpid, status, p;
|
||||
time_t start;
|
||||
|
||||
putchar(c);
|
||||
if (prompt("Local command? ", buf))
|
||||
return;
|
||||
kill(pid, SIGIOT); /* put TIPOUT into a wait state */
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
ioctl(0, TIOCSETC, &defchars);
|
||||
read(repdes[0], (char *)&ccc, 1);
|
||||
/*
|
||||
* Set up file descriptors in the child and
|
||||
* let it go...
|
||||
*/
|
||||
if ((cpid = fork()) < 0)
|
||||
printf("can't fork!\r\n");
|
||||
else if (cpid) {
|
||||
start = time(0);
|
||||
while ((p = wait(&status)) > 0 && p != cpid)
|
||||
;
|
||||
} else {
|
||||
register int i;
|
||||
|
||||
dup2(FD, 1);
|
||||
for (i = 3; i < 20; i++)
|
||||
close(i);
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGQUIT, SIG_DFL);
|
||||
execute(buf);
|
||||
printf("can't find `%s'\r\n", buf);
|
||||
exit(0);
|
||||
}
|
||||
if (boolean(value(VERBOSE)))
|
||||
prtime("away for ", time(0)-start);
|
||||
write(fildes[1], (char *)&ccc, 1);
|
||||
ioctl(0, TIOCSETC, &tchars);
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGQUIT, SIG_DFL);
|
||||
}
|
||||
|
||||
#ifdef CONNECT
|
||||
/*
|
||||
* Fork a program with:
|
||||
* 0 <-> remote tty in
|
||||
* 1 <-> remote tty out
|
||||
* 2 <-> local tty out
|
||||
*/
|
||||
consh(c)
|
||||
{
|
||||
char buf[256];
|
||||
int cpid, status, p;
|
||||
time_t start;
|
||||
|
||||
putchar(c);
|
||||
if (prompt("Local command? ", buf))
|
||||
return;
|
||||
kill(pid, SIGIOT); /* put TIPOUT into a wait state */
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
ioctl(0, TIOCSETC, &defchars);
|
||||
read(repdes[0], (char *)&ccc, 1);
|
||||
/*
|
||||
* Set up file descriptors in the child and
|
||||
* let it go...
|
||||
*/
|
||||
if ((cpid = fork()) < 0)
|
||||
printf("can't fork!\r\n");
|
||||
else if (cpid) {
|
||||
start = time(0);
|
||||
while ((p = wait(&status)) > 0 && p != cpid)
|
||||
;
|
||||
} else {
|
||||
register int i;
|
||||
|
||||
dup2(FD, 0);
|
||||
dup2(3, 1);
|
||||
for (i = 3; i < 20; i++)
|
||||
close(i);
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGQUIT, SIG_DFL);
|
||||
execute(buf);
|
||||
printf("can't find `%s'\r\n", buf);
|
||||
exit(0);
|
||||
}
|
||||
if (boolean(value(VERBOSE)))
|
||||
prtime("away for ", time(0)-start);
|
||||
write(fildes[1], (char *)&ccc, 1);
|
||||
ioctl(0, TIOCSETC, &tchars);
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGQUIT, SIG_DFL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Escape to local shell
|
||||
*/
|
||||
shell()
|
||||
{
|
||||
int shpid, status;
|
||||
extern char **environ;
|
||||
char *cp;
|
||||
|
||||
printf("[sh]\r\n");
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
unraw();
|
||||
if (shpid = fork()) {
|
||||
while (shpid != wait(&status));
|
||||
raw();
|
||||
printf("\r\n!\r\n");
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGQUIT, SIG_DFL);
|
||||
return;
|
||||
} else {
|
||||
signal(SIGQUIT, SIG_DFL);
|
||||
signal(SIGINT, SIG_DFL);
|
||||
if ((cp = rindex(value(SHELL), '/')) == NULL)
|
||||
cp = value(SHELL);
|
||||
else
|
||||
cp++;
|
||||
shell_uid();
|
||||
execl(value(SHELL), cp, 0);
|
||||
printf("\r\ncan't execl!\r\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TIPIN portion of scripting
|
||||
* initiate the conversation with TIPOUT
|
||||
*/
|
||||
setscript()
|
||||
{
|
||||
char c;
|
||||
/*
|
||||
* enable TIPOUT side for dialogue
|
||||
*/
|
||||
kill(pid, SIGEMT);
|
||||
if (boolean(value(SCRIPT)))
|
||||
write(fildes[1], value(RECORD), size(value(RECORD)));
|
||||
write(fildes[1], "\n", 1);
|
||||
/*
|
||||
* wait for TIPOUT to finish
|
||||
*/
|
||||
read(repdes[0], &c, 1);
|
||||
if (c == 'n')
|
||||
printf("can't create %s\r\n", value(RECORD));
|
||||
}
|
||||
|
||||
/*
|
||||
* Change current working directory of
|
||||
* local portion of tip
|
||||
*/
|
||||
chdirectory()
|
||||
{
|
||||
char dirname[80];
|
||||
register char *cp = dirname;
|
||||
|
||||
if (prompt("[cd] ", dirname)) {
|
||||
if (stoprompt)
|
||||
return;
|
||||
cp = value(HOME);
|
||||
}
|
||||
if (chdir(cp) < 0)
|
||||
printf("%s: bad directory\r\n", cp);
|
||||
printf("!\r\n");
|
||||
}
|
||||
|
||||
tipabort(msg)
|
||||
char *msg;
|
||||
{
|
||||
|
||||
kill(pid, SIGTERM);
|
||||
disconnect(msg);
|
||||
if (msg != NOSTR)
|
||||
printf("\r\n%s", msg);
|
||||
printf("\r\n[EOT]\r\n");
|
||||
daemon_uid();
|
||||
(void)uu_unlock(uucplock);
|
||||
unraw();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
finish()
|
||||
{
|
||||
char *dismsg;
|
||||
|
||||
if ((dismsg = value(DISCONNECT)) != NOSTR) {
|
||||
write(FD, dismsg, strlen(dismsg));
|
||||
sleep(5);
|
||||
}
|
||||
tipabort(NOSTR);
|
||||
}
|
||||
|
||||
void
|
||||
intcopy()
|
||||
{
|
||||
raw();
|
||||
quit = 1;
|
||||
longjmp(intbuf, 1);
|
||||
}
|
||||
|
||||
execute(s)
|
||||
char *s;
|
||||
{
|
||||
register char *cp;
|
||||
|
||||
if ((cp = rindex(value(SHELL), '/')) == NULL)
|
||||
cp = value(SHELL);
|
||||
else
|
||||
cp++;
|
||||
shell_uid();
|
||||
execl(value(SHELL), cp, "-c", s, 0);
|
||||
}
|
||||
|
||||
args(buf, a)
|
||||
char *buf, *a[];
|
||||
{
|
||||
register char *p = buf, *start;
|
||||
register char **parg = a;
|
||||
register int n = 0;
|
||||
|
||||
do {
|
||||
while (*p && (*p == ' ' || *p == '\t'))
|
||||
p++;
|
||||
start = p;
|
||||
if (*p)
|
||||
*parg = p;
|
||||
while (*p && (*p != ' ' && *p != '\t'))
|
||||
p++;
|
||||
if (p != start)
|
||||
parg++, n++;
|
||||
if (*p)
|
||||
*p++ = '\0';
|
||||
} while (*p);
|
||||
|
||||
return(n);
|
||||
}
|
||||
|
||||
prtime(s, a)
|
||||
char *s;
|
||||
time_t a;
|
||||
{
|
||||
register i;
|
||||
int nums[3];
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
nums[i] = (int)(a % quant[i]);
|
||||
a /= quant[i];
|
||||
}
|
||||
printf("%s", s);
|
||||
while (--i >= 0)
|
||||
if (nums[i] || i == 0 && nums[1] == 0 && nums[2] == 0)
|
||||
printf("%d %s%c ", nums[i], sep[i],
|
||||
nums[i] == 1 ? '\0' : 's');
|
||||
printf("\r\n!\r\n");
|
||||
}
|
||||
|
||||
variable()
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
if (prompt("[set] ", buf))
|
||||
return;
|
||||
vlex(buf);
|
||||
if (vtable[BEAUTIFY].v_access&CHANGED) {
|
||||
vtable[BEAUTIFY].v_access &= ~CHANGED;
|
||||
kill(pid, SIGSYS);
|
||||
}
|
||||
if (vtable[SCRIPT].v_access&CHANGED) {
|
||||
vtable[SCRIPT].v_access &= ~CHANGED;
|
||||
setscript();
|
||||
/*
|
||||
* So that "set record=blah script" doesn't
|
||||
* cause two transactions to occur.
|
||||
*/
|
||||
if (vtable[RECORD].v_access&CHANGED)
|
||||
vtable[RECORD].v_access &= ~CHANGED;
|
||||
}
|
||||
if (vtable[RECORD].v_access&CHANGED) {
|
||||
vtable[RECORD].v_access &= ~CHANGED;
|
||||
if (boolean(value(SCRIPT)))
|
||||
setscript();
|
||||
}
|
||||
if (vtable[TAND].v_access&CHANGED) {
|
||||
vtable[TAND].v_access &= ~CHANGED;
|
||||
if (boolean(value(TAND)))
|
||||
tandem("on");
|
||||
else
|
||||
tandem("off");
|
||||
}
|
||||
if (vtable[LECHO].v_access&CHANGED) {
|
||||
vtable[LECHO].v_access &= ~CHANGED;
|
||||
HD = boolean(value(LECHO));
|
||||
}
|
||||
if (vtable[PARITY].v_access&CHANGED) {
|
||||
vtable[PARITY].v_access &= ~CHANGED;
|
||||
setparity();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn tandem mode on or off for remote tty.
|
||||
*/
|
||||
tandem(option)
|
||||
char *option;
|
||||
{
|
||||
struct sgttyb rmtty;
|
||||
|
||||
ioctl(FD, TIOCGETP, &rmtty);
|
||||
if (strcmp(option,"on") == 0) {
|
||||
rmtty.sg_flags |= TANDEM;
|
||||
arg.sg_flags |= TANDEM;
|
||||
} else {
|
||||
rmtty.sg_flags &= ~TANDEM;
|
||||
arg.sg_flags &= ~TANDEM;
|
||||
}
|
||||
ioctl(FD, TIOCSETP, &rmtty);
|
||||
ioctl(0, TIOCSETP, &arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a break.
|
||||
*/
|
||||
genbrk()
|
||||
{
|
||||
|
||||
ioctl(FD, TIOCSBRK, NULL);
|
||||
sleep(1);
|
||||
ioctl(FD, TIOCCBRK, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Suspend tip
|
||||
*/
|
||||
suspend(c)
|
||||
char c;
|
||||
{
|
||||
|
||||
unraw();
|
||||
kill(c == CTRL('y') ? getpid() : 0, SIGTSTP);
|
||||
raw();
|
||||
}
|
||||
|
||||
/*
|
||||
* expand a file name if it includes shell meta characters
|
||||
*/
|
||||
|
||||
char *
|
||||
expand(name)
|
||||
char name[];
|
||||
{
|
||||
static char xname[BUFSIZ];
|
||||
char cmdbuf[BUFSIZ];
|
||||
register int pid, l, rc;
|
||||
register char *cp, *Shell;
|
||||
int s, pivec[2], (*sigint)();
|
||||
|
||||
if (!anyof(name, "~{[*?$`'\"\\"))
|
||||
return(name);
|
||||
/* sigint = signal(SIGINT, SIG_IGN); */
|
||||
if (pipe(pivec) < 0) {
|
||||
perror("pipe");
|
||||
/* signal(SIGINT, sigint) */
|
||||
return(name);
|
||||
}
|
||||
sprintf(cmdbuf, "echo %s", name);
|
||||
if ((pid = vfork()) == 0) {
|
||||
Shell = value(SHELL);
|
||||
if (Shell == NOSTR)
|
||||
Shell = _PATH_BSHELL;
|
||||
close(pivec[0]);
|
||||
close(1);
|
||||
dup(pivec[1]);
|
||||
close(pivec[1]);
|
||||
close(2);
|
||||
shell_uid();
|
||||
execl(Shell, Shell, "-c", cmdbuf, 0);
|
||||
_exit(1);
|
||||
}
|
||||
if (pid == -1) {
|
||||
perror("fork");
|
||||
close(pivec[0]);
|
||||
close(pivec[1]);
|
||||
return(NOSTR);
|
||||
}
|
||||
close(pivec[1]);
|
||||
l = read(pivec[0], xname, BUFSIZ);
|
||||
close(pivec[0]);
|
||||
while (wait(&s) != pid);
|
||||
;
|
||||
s &= 0377;
|
||||
if (s != 0 && s != SIGPIPE) {
|
||||
fprintf(stderr, "\"Echo\" failed\n");
|
||||
return(NOSTR);
|
||||
}
|
||||
if (l < 0) {
|
||||
perror("read");
|
||||
return(NOSTR);
|
||||
}
|
||||
if (l == 0) {
|
||||
fprintf(stderr, "\"%s\": No match\n", name);
|
||||
return(NOSTR);
|
||||
}
|
||||
if (l == BUFSIZ) {
|
||||
fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
|
||||
return(NOSTR);
|
||||
}
|
||||
xname[l] = 0;
|
||||
for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
|
||||
;
|
||||
*++cp = '\0';
|
||||
return(xname);
|
||||
}
|
||||
|
||||
/*
|
||||
* Are any of the characters in the two strings the same?
|
||||
*/
|
||||
|
||||
anyof(s1, s2)
|
||||
register char *s1, *s2;
|
||||
{
|
||||
register int c;
|
||||
|
||||
while (c = *s1++)
|
||||
if (any(c, s2))
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
64
usr.bin/tip/cmdtab.c
Normal file
64
usr.bin/tip/cmdtab.c
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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[] = "@(#)cmdtab.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "tip.h"
|
||||
|
||||
extern int shell(), getfl(), sendfile(), chdirectory();
|
||||
extern int finish(), help(), pipefile(), pipeout(), consh(), variable();
|
||||
extern int cu_take(), cu_put(), dollar(), genbrk(), suspend();
|
||||
|
||||
esctable_t etable[] = {
|
||||
{ '!', NORM, "shell", shell },
|
||||
{ '<', NORM, "receive file from remote host", getfl },
|
||||
{ '>', NORM, "send file to remote host", sendfile },
|
||||
{ 't', NORM, "take file from remote UNIX", cu_take },
|
||||
{ 'p', NORM, "put file to remote UNIX", cu_put },
|
||||
{ '|', NORM, "pipe remote file", pipefile },
|
||||
{ '$', NORM, "pipe local command to remote host", pipeout },
|
||||
#ifdef CONNECT
|
||||
{ 'C', NORM, "connect program to remote host",consh },
|
||||
#endif
|
||||
{ 'c', NORM, "change directory", chdirectory },
|
||||
{ '.', NORM, "exit from tip", finish },
|
||||
{CTRL('d'),NORM,"exit from tip", finish },
|
||||
{CTRL('y'),NORM,"suspend tip (local+remote)", suspend },
|
||||
{CTRL('z'),NORM,"suspend tip (local only)", suspend },
|
||||
{ 's', NORM, "set variable", variable },
|
||||
{ '?', NORM, "get this summary", help },
|
||||
{ '#', NORM, "send break", genbrk },
|
||||
{ 0, 0, 0 }
|
||||
};
|
132
usr.bin/tip/cu.c
Normal file
132
usr.bin/tip/cu.c
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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[] = "@(#)cu.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "tip.h"
|
||||
|
||||
void cleanup();
|
||||
|
||||
/*
|
||||
* Botch the interface to look like cu's
|
||||
*/
|
||||
cumain(argc, argv)
|
||||
char *argv[];
|
||||
{
|
||||
register int i;
|
||||
static char sbuf[12];
|
||||
|
||||
if (argc < 2) {
|
||||
printf("usage: cu telno [-t] [-s speed] [-a acu] [-l line] [-#]\n");
|
||||
exit(8);
|
||||
}
|
||||
CU = DV = NOSTR;
|
||||
BR = DEFBR;
|
||||
for (; argc > 1; argv++, argc--) {
|
||||
if (argv[1][0] != '-')
|
||||
PN = argv[1];
|
||||
else switch (argv[1][1]) {
|
||||
|
||||
case 't':
|
||||
HW = 1, DU = -1;
|
||||
--argc;
|
||||
continue;
|
||||
|
||||
case 'a':
|
||||
CU = argv[2]; ++argv; --argc;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (argc < 3 || speed(atoi(argv[2])) == 0) {
|
||||
fprintf(stderr, "cu: unsupported speed %s\n",
|
||||
argv[2]);
|
||||
exit(3);
|
||||
}
|
||||
BR = atoi(argv[2]); ++argv; --argc;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
DV = argv[2]; ++argv; --argc;
|
||||
break;
|
||||
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
if (CU)
|
||||
CU[strlen(CU)-1] = argv[1][1];
|
||||
if (DV)
|
||||
DV[strlen(DV)-1] = argv[1][1];
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Bad flag %s", argv[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
signal(SIGINT, cleanup);
|
||||
signal(SIGQUIT, cleanup);
|
||||
signal(SIGHUP, cleanup);
|
||||
signal(SIGTERM, cleanup);
|
||||
|
||||
/*
|
||||
* The "cu" host name is used to define the
|
||||
* attributes of the generic dialer.
|
||||
*/
|
||||
(void)sprintf(sbuf, "cu%d", BR);
|
||||
if ((i = hunt(sbuf)) == 0) {
|
||||
printf("all ports busy\n");
|
||||
exit(3);
|
||||
}
|
||||
if (i == -1) {
|
||||
printf("link down\n");
|
||||
(void)uu_unlock(uucplock);
|
||||
exit(3);
|
||||
}
|
||||
setbuf(stdout, NULL);
|
||||
loginit();
|
||||
user_uid();
|
||||
vinit();
|
||||
setparity("none");
|
||||
boolean(value(VERBOSE)) = 0;
|
||||
if (HW)
|
||||
ttysetup(speed(BR));
|
||||
if (connect()) {
|
||||
printf("Connect failed\n");
|
||||
daemon_uid();
|
||||
(void)uu_unlock(uucplock);
|
||||
exit(1);
|
||||
}
|
||||
if (!HW)
|
||||
ttysetup(speed(BR));
|
||||
}
|
93
usr.bin/tip/hunt.c
Normal file
93
usr.bin/tip/hunt.c
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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[] = "@(#)hunt.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "tip.h"
|
||||
|
||||
extern char *getremote();
|
||||
extern char *rindex();
|
||||
|
||||
static jmp_buf deadline;
|
||||
static int deadfl;
|
||||
|
||||
void
|
||||
dead()
|
||||
{
|
||||
deadfl = 1;
|
||||
longjmp(deadline, 1);
|
||||
}
|
||||
|
||||
hunt(name)
|
||||
char *name;
|
||||
{
|
||||
register char *cp;
|
||||
sig_t f;
|
||||
|
||||
f = signal(SIGALRM, dead);
|
||||
while (cp = getremote(name)) {
|
||||
deadfl = 0;
|
||||
uucplock = rindex(cp, '/')+1;
|
||||
if (uu_lock(uucplock) < 0)
|
||||
continue;
|
||||
/*
|
||||
* Straight through call units, such as the BIZCOMP,
|
||||
* VADIC and the DF, must indicate they're hardwired in
|
||||
* order to get an open file descriptor placed in FD.
|
||||
* Otherwise, as for a DN-11, the open will have to
|
||||
* be done in the "open" routine.
|
||||
*/
|
||||
if (!HW)
|
||||
break;
|
||||
if (setjmp(deadline) == 0) {
|
||||
alarm(10);
|
||||
FD = open(cp, O_RDWR);
|
||||
}
|
||||
alarm(0);
|
||||
if (FD < 0) {
|
||||
perror(cp);
|
||||
deadfl = 1;
|
||||
}
|
||||
if (!deadfl) {
|
||||
ioctl(FD, TIOCEXCL, 0);
|
||||
ioctl(FD, TIOCHPCL, 0);
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
return ((int)cp);
|
||||
}
|
||||
(void)uu_unlock(uucplock);
|
||||
}
|
||||
signal(SIGALRM, f);
|
||||
return (deadfl ? -1 : (int)cp);
|
||||
}
|
86
usr.bin/tip/log.c
Normal file
86
usr.bin/tip/log.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[] = "@(#)log.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "tip.h"
|
||||
|
||||
#ifdef ACULOG
|
||||
static FILE *flog = NULL;
|
||||
|
||||
/*
|
||||
* Log file maintenance routines
|
||||
*/
|
||||
|
||||
logent(group, num, acu, message)
|
||||
char *group, *num, *acu, *message;
|
||||
{
|
||||
char *user, *timestamp;
|
||||
struct passwd *pwd;
|
||||
long t;
|
||||
|
||||
if (flog == NULL)
|
||||
return;
|
||||
if (flock(fileno(flog), LOCK_EX) < 0) {
|
||||
perror("tip: flock");
|
||||
return;
|
||||
}
|
||||
if ((user = getlogin()) == NOSTR)
|
||||
if ((pwd = getpwuid(getuid())) == NOPWD)
|
||||
user = "???";
|
||||
else
|
||||
user = pwd->pw_name;
|
||||
t = time(0);
|
||||
timestamp = ctime(&t);
|
||||
timestamp[24] = '\0';
|
||||
fprintf(flog, "%s (%s) <%s, %s, %s> %s\n",
|
||||
user, timestamp, group,
|
||||
#ifdef PRISTINE
|
||||
"",
|
||||
#else
|
||||
num,
|
||||
#endif
|
||||
acu, message);
|
||||
(void) fflush(flog);
|
||||
(void) flock(fileno(flog), LOCK_UN);
|
||||
}
|
||||
|
||||
loginit()
|
||||
{
|
||||
flog = fopen(value(LOG), "a");
|
||||
if (flog == NULL)
|
||||
fprintf(stderr, "can't open log file %s.\r\n", value(LOG));
|
||||
}
|
||||
#endif
|
58
usr.bin/tip/partab.c
Normal file
58
usr.bin/tip/partab.c
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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[] = "@(#)partab.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Even parity table for 0-0177
|
||||
*/
|
||||
char evenpartab[] = {
|
||||
0000,0201,0202,0003,0204,0005,0006,0207,
|
||||
0210,0011,0012,0213,0014,0215,0216,0017,
|
||||
0220,0021,0022,0223,0024,0225,0226,0027,
|
||||
0030,0231,0232,0033,0234,0035,0036,0237,
|
||||
0240,0041,0042,0243,0044,0245,0246,0047,
|
||||
0050,0251,0252,0053,0254,0055,0056,0257,
|
||||
0060,0261,0262,0063,0264,0065,0066,0267,
|
||||
0270,0071,0072,0273,0074,0275,0276,0077,
|
||||
0300,0101,0102,0303,0104,0305,0306,0107,
|
||||
0110,0311,0312,0113,0314,0115,0116,0317,
|
||||
0120,0321,0322,0123,0324,0125,0126,0327,
|
||||
0330,0131,0132,0333,0134,0335,0336,0137,
|
||||
0140,0341,0342,0143,0344,0145,0146,0347,
|
||||
0350,0151,0152,0353,0154,0355,0356,0157,
|
||||
0360,0161,0162,0363,0164,0365,0366,0167,
|
||||
0170,0371,0372,0173,0374,0175,0176,0377,
|
||||
};
|
426
usr.bin/tip/remcap.c
Normal file
426
usr.bin/tip/remcap.c
Normal file
@ -0,0 +1,426 @@
|
||||
/*
|
||||
* 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[] = "@(#)remcap.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* remcap - routines for dealing with the remote host data base
|
||||
*
|
||||
* derived from termcap
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include "pathnames.h"
|
||||
|
||||
#ifndef BUFSIZ
|
||||
#define BUFSIZ 1024
|
||||
#endif
|
||||
#define MAXHOP 32 /* max number of tc= indirections */
|
||||
|
||||
#define tgetent rgetent
|
||||
#define tnchktc rnchktc
|
||||
#define tnamatch rnamatch
|
||||
#define tgetnum rgetnum
|
||||
#define tgetflag rgetflag
|
||||
#define tgetstr rgetstr
|
||||
#define E_TERMCAP RM = _PATH_REMOTE
|
||||
#define V_TERMCAP "REMOTE"
|
||||
#define V_TERM "HOST"
|
||||
|
||||
char *RM;
|
||||
|
||||
/*
|
||||
* termcap - routines for dealing with the terminal capability data base
|
||||
*
|
||||
* BUG: Should use a "last" pointer in tbuf, so that searching
|
||||
* for capabilities alphabetically would not be a n**2/2
|
||||
* process when large numbers of capabilities are given.
|
||||
* Note: If we add a last pointer now we will screw up the
|
||||
* tc capability. We really should compile termcap.
|
||||
*
|
||||
* Essentially all the work here is scanning and decoding escapes
|
||||
* in string capabilities. We don't use stdio because the editor
|
||||
* doesn't, and because living w/o it is not hard.
|
||||
*/
|
||||
|
||||
static char *tbuf;
|
||||
static int hopcount; /* detect infinite loops in termcap, init 0 */
|
||||
static char *tskip();
|
||||
char *tgetstr();
|
||||
static char *tdecode();
|
||||
static char *remotefile;
|
||||
|
||||
/*
|
||||
* Get an entry for terminal name in buffer bp,
|
||||
* from the termcap file. Parse is very rudimentary;
|
||||
* we just notice escaped newlines.
|
||||
*/
|
||||
tgetent(bp, name)
|
||||
char *bp, *name;
|
||||
{
|
||||
char lbuf[BUFSIZ], *cp, *p;
|
||||
int rc1, rc2;
|
||||
|
||||
remotefile = cp = getenv(V_TERMCAP);
|
||||
if (cp == (char *)0 || strcmp(cp, _PATH_REMOTE) == 0) {
|
||||
remotefile = cp = _PATH_REMOTE;
|
||||
return (getent(bp, name, cp));
|
||||
} else {
|
||||
if ((rc1 = getent(bp, name, cp)) != 1)
|
||||
*bp = '\0';
|
||||
remotefile = cp = _PATH_REMOTE;
|
||||
rc2 = getent(lbuf, name, cp);
|
||||
if (rc1 != 1 && rc2 != 1)
|
||||
return (rc2);
|
||||
if (rc2 == 1) {
|
||||
p = lbuf;
|
||||
if (rc1 == 1)
|
||||
while (*p++ != ':')
|
||||
;
|
||||
if (strlen(bp) + strlen(p) > BUFSIZ) {
|
||||
write(2, "Remcap entry too long\n", 23);
|
||||
return (-1);
|
||||
}
|
||||
strcat(bp, p);
|
||||
}
|
||||
tbuf = bp;
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
getent(bp, name, cp)
|
||||
char *bp, *name, *cp;
|
||||
{
|
||||
register int c;
|
||||
register int i = 0, cnt = 0;
|
||||
char ibuf[BUFSIZ], *cp2;
|
||||
int tf;
|
||||
|
||||
tbuf = bp;
|
||||
tf = 0;
|
||||
/*
|
||||
* TERMCAP can have one of two things in it. It can be the
|
||||
* name of a file to use instead of /etc/termcap. In this
|
||||
* case it better start with a "/". Or it can be an entry to
|
||||
* use so we don't have to read the file. In this case it
|
||||
* has to already have the newlines crunched out.
|
||||
*/
|
||||
if (cp && *cp) {
|
||||
if (*cp!='/') {
|
||||
cp2 = getenv(V_TERM);
|
||||
if (cp2 == (char *)0 || strcmp(name,cp2) == 0) {
|
||||
strcpy(bp,cp);
|
||||
return (tnchktc());
|
||||
} else
|
||||
tf = open(E_TERMCAP, O_RDONLY);
|
||||
} else
|
||||
tf = open(RM = cp, O_RDONLY);
|
||||
}
|
||||
if (tf == 0)
|
||||
tf = open(E_TERMCAP, O_RDONLY);
|
||||
if (tf < 0)
|
||||
return (-1);
|
||||
for (;;) {
|
||||
cp = bp;
|
||||
for (;;) {
|
||||
if (i == cnt) {
|
||||
cnt = read(tf, ibuf, BUFSIZ);
|
||||
if (cnt <= 0) {
|
||||
close(tf);
|
||||
return (0);
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
c = ibuf[i++];
|
||||
if (c == '\n') {
|
||||
if (cp > bp && cp[-1] == '\\') {
|
||||
cp--;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (cp >= bp+BUFSIZ) {
|
||||
write(2,"Remcap entry too long\n", 23);
|
||||
break;
|
||||
} else
|
||||
*cp++ = c;
|
||||
}
|
||||
*cp = 0;
|
||||
|
||||
/*
|
||||
* The real work for the match.
|
||||
*/
|
||||
if (tnamatch(name)) {
|
||||
close(tf);
|
||||
return (tnchktc());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* tnchktc: check the last entry, see if it's tc=xxx. If so,
|
||||
* recursively find xxx and append that entry (minus the names)
|
||||
* to take the place of the tc=xxx entry. This allows termcap
|
||||
* entries to say "like an HP2621 but doesn't turn on the labels".
|
||||
* Note that this works because of the left to right scan.
|
||||
*/
|
||||
tnchktc()
|
||||
{
|
||||
register char *p, *q;
|
||||
char tcname[16]; /* name of similar terminal */
|
||||
char tcbuf[BUFSIZ];
|
||||
char *holdtbuf = tbuf;
|
||||
int l;
|
||||
char *cp;
|
||||
|
||||
p = tbuf + strlen(tbuf) - 2; /* before the last colon */
|
||||
while (*--p != ':')
|
||||
if (p<tbuf) {
|
||||
write(2, "Bad remcap entry\n", 18);
|
||||
return (0);
|
||||
}
|
||||
p++;
|
||||
/* p now points to beginning of last field */
|
||||
if (p[0] != 't' || p[1] != 'c')
|
||||
return (1);
|
||||
strcpy(tcname, p+3);
|
||||
q = tcname;
|
||||
while (*q && *q != ':')
|
||||
q++;
|
||||
*q = 0;
|
||||
if (++hopcount > MAXHOP) {
|
||||
write(2, "Infinite tc= loop\n", 18);
|
||||
return (0);
|
||||
}
|
||||
if (getent(tcbuf, tcname, remotefile) != 1) {
|
||||
if (strcmp(remotefile, _PATH_REMOTE) == 0)
|
||||
return (0);
|
||||
else if (getent(tcbuf, tcname, _PATH_REMOTE) != 1)
|
||||
return (0);
|
||||
}
|
||||
for (q = tcbuf; *q++ != ':'; )
|
||||
;
|
||||
l = p - holdtbuf + strlen(q);
|
||||
if (l > BUFSIZ) {
|
||||
write(2, "Remcap entry too long\n", 23);
|
||||
q[BUFSIZ - (p-holdtbuf)] = 0;
|
||||
}
|
||||
strcpy(p, q);
|
||||
tbuf = holdtbuf;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tnamatch deals with name matching. The first field of the termcap
|
||||
* entry is a sequence of names separated by |'s, so we compare
|
||||
* against each such name. The normal : terminator after the last
|
||||
* name (before the first field) stops us.
|
||||
*/
|
||||
tnamatch(np)
|
||||
char *np;
|
||||
{
|
||||
register char *Np, *Bp;
|
||||
|
||||
Bp = tbuf;
|
||||
if (*Bp == '#')
|
||||
return (0);
|
||||
for (;;) {
|
||||
for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
|
||||
continue;
|
||||
if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
|
||||
return (1);
|
||||
while (*Bp && *Bp != ':' && *Bp != '|')
|
||||
Bp++;
|
||||
if (*Bp == 0 || *Bp == ':')
|
||||
return (0);
|
||||
Bp++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip to the next field. Notice that this is very dumb, not
|
||||
* knowing about \: escapes or any such. If necessary, :'s can be put
|
||||
* into the termcap file in octal.
|
||||
*/
|
||||
static char *
|
||||
tskip(bp)
|
||||
register char *bp;
|
||||
{
|
||||
|
||||
while (*bp && *bp != ':')
|
||||
bp++;
|
||||
if (*bp == ':')
|
||||
bp++;
|
||||
return (bp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the (numeric) option id.
|
||||
* Numeric options look like
|
||||
* li#80
|
||||
* i.e. the option string is separated from the numeric value by
|
||||
* a # character. If the option is not found we return -1.
|
||||
* Note that we handle octal numbers beginning with 0.
|
||||
*/
|
||||
tgetnum(id)
|
||||
char *id;
|
||||
{
|
||||
register int i, base;
|
||||
register char *bp = tbuf;
|
||||
|
||||
for (;;) {
|
||||
bp = tskip(bp);
|
||||
if (*bp == 0)
|
||||
return (-1);
|
||||
if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
|
||||
continue;
|
||||
if (*bp == '@')
|
||||
return (-1);
|
||||
if (*bp != '#')
|
||||
continue;
|
||||
bp++;
|
||||
base = 10;
|
||||
if (*bp == '0')
|
||||
base = 8;
|
||||
i = 0;
|
||||
while (isdigit(*bp))
|
||||
i *= base, i += *bp++ - '0';
|
||||
return (i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a flag option.
|
||||
* Flag options are given "naked", i.e. followed by a : or the end
|
||||
* of the buffer. Return 1 if we find the option, or 0 if it is
|
||||
* not given.
|
||||
*/
|
||||
tgetflag(id)
|
||||
char *id;
|
||||
{
|
||||
register char *bp = tbuf;
|
||||
|
||||
for (;;) {
|
||||
bp = tskip(bp);
|
||||
if (!*bp)
|
||||
return (0);
|
||||
if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
|
||||
if (!*bp || *bp == ':')
|
||||
return (1);
|
||||
else if (*bp == '@')
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a string valued option.
|
||||
* These are given as
|
||||
* cl=^Z
|
||||
* Much decoding is done on the strings, and the strings are
|
||||
* placed in area, which is a ref parameter which is updated.
|
||||
* No checking on area overflow.
|
||||
*/
|
||||
char *
|
||||
tgetstr(id, area)
|
||||
char *id, **area;
|
||||
{
|
||||
register char *bp = tbuf;
|
||||
|
||||
for (;;) {
|
||||
bp = tskip(bp);
|
||||
if (!*bp)
|
||||
return (0);
|
||||
if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
|
||||
continue;
|
||||
if (*bp == '@')
|
||||
return (0);
|
||||
if (*bp != '=')
|
||||
continue;
|
||||
bp++;
|
||||
return (tdecode(bp, area));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Tdecode does the grung work to decode the
|
||||
* string capability escapes.
|
||||
*/
|
||||
static char *
|
||||
tdecode(str, area)
|
||||
register char *str;
|
||||
char **area;
|
||||
{
|
||||
register char *cp;
|
||||
register int c;
|
||||
register char *dp;
|
||||
int i;
|
||||
|
||||
cp = *area;
|
||||
while ((c = *str++) && c != ':') {
|
||||
switch (c) {
|
||||
|
||||
case '^':
|
||||
c = *str++ & 037;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
|
||||
c = *str++;
|
||||
nextc:
|
||||
if (*dp++ == c) {
|
||||
c = *dp++;
|
||||
break;
|
||||
}
|
||||
dp++;
|
||||
if (*dp)
|
||||
goto nextc;
|
||||
if (isdigit(c)) {
|
||||
c -= '0', i = 2;
|
||||
do
|
||||
c <<= 3, c |= *str++ - '0';
|
||||
while (--i && isdigit(*str));
|
||||
}
|
||||
break;
|
||||
}
|
||||
*cp++ = c;
|
||||
}
|
||||
*cp++ = 0;
|
||||
str = *area;
|
||||
*area = cp;
|
||||
return (str);
|
||||
}
|
226
usr.bin/tip/remote.c
Normal file
226
usr.bin/tip/remote.c
Normal file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
* 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[] = "@(#)remote.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
#include "tip.h"
|
||||
|
||||
/*
|
||||
* Attributes to be gleened from remote host description
|
||||
* data base.
|
||||
*/
|
||||
static char **caps[] = {
|
||||
&AT, &DV, &CM, &CU, &EL, &IE, &OE, &PN, &PR, &DI,
|
||||
&ES, &EX, &FO, &RC, &RE, &PA
|
||||
};
|
||||
|
||||
static char *capstrings[] = {
|
||||
"at", "dv", "cm", "cu", "el", "ie", "oe", "pn", "pr",
|
||||
"di", "es", "ex", "fo", "rc", "re", "pa", 0
|
||||
};
|
||||
|
||||
static char *db_array[3] = { _PATH_REMOTE, 0, 0 };
|
||||
|
||||
#define cgetflag(f) (cgetcap(bp, f, ':') != NULL)
|
||||
|
||||
static
|
||||
getremcap(host)
|
||||
register char *host;
|
||||
{
|
||||
register char **p, ***q;
|
||||
char *bp;
|
||||
char *rempath;
|
||||
int stat;
|
||||
|
||||
rempath = getenv("REMOTE");
|
||||
if (rempath != NULL)
|
||||
if (*rempath != '/')
|
||||
/* we have an entry */
|
||||
cgetset(rempath);
|
||||
else { /* we have a path */
|
||||
db_array[1] = rempath;
|
||||
db_array[2] = _PATH_REMOTE;
|
||||
}
|
||||
|
||||
if ((stat = cgetent(&bp, db_array, host)) < 0) {
|
||||
if (DV ||
|
||||
host[0] == '/' && access(DV = host, R_OK | W_OK) == 0) {
|
||||
CU = DV;
|
||||
HO = host;
|
||||
HW = 1;
|
||||
DU = 0;
|
||||
if (!BR)
|
||||
BR = DEFBR;
|
||||
FS = DEFFS;
|
||||
return;
|
||||
}
|
||||
switch(stat) {
|
||||
case -1:
|
||||
fprintf(stderr, "tip: unknown host %s\n", host);
|
||||
break;
|
||||
case -2:
|
||||
fprintf(stderr,
|
||||
"tip: can't open host description file\n");
|
||||
break;
|
||||
case -3:
|
||||
fprintf(stderr,
|
||||
"tip: possible reference loop in host description file\n");
|
||||
break;
|
||||
}
|
||||
exit(3);
|
||||
}
|
||||
|
||||
for (p = capstrings, q = caps; *p != NULL; p++, q++)
|
||||
if (**q == NULL)
|
||||
cgetstr(bp, *p, *q);
|
||||
if (!BR && (cgetnum(bp, "br", &BR) == -1))
|
||||
BR = DEFBR;
|
||||
if (cgetnum(bp, "fs", &FS) == -1)
|
||||
FS = DEFFS;
|
||||
if (DU < 0)
|
||||
DU = 0;
|
||||
else
|
||||
DU = cgetflag("du");
|
||||
if (DV == NOSTR) {
|
||||
fprintf(stderr, "%s: missing device spec\n", host);
|
||||
exit(3);
|
||||
}
|
||||
if (DU && CU == NOSTR)
|
||||
CU = DV;
|
||||
if (DU && PN == NOSTR) {
|
||||
fprintf(stderr, "%s: missing phone number\n", host);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
HD = cgetflag("hd");
|
||||
|
||||
/*
|
||||
* This effectively eliminates the "hw" attribute
|
||||
* from the description file
|
||||
*/
|
||||
if (!HW)
|
||||
HW = (CU == NOSTR) || (DU && equal(DV, CU));
|
||||
HO = host;
|
||||
/*
|
||||
* see if uppercase mode should be turned on initially
|
||||
*/
|
||||
if (cgetflag("ra"))
|
||||
boolean(value(RAISE)) = 1;
|
||||
if (cgetflag("ec"))
|
||||
boolean(value(ECHOCHECK)) = 1;
|
||||
if (cgetflag("be"))
|
||||
boolean(value(BEAUTIFY)) = 1;
|
||||
if (cgetflag("nb"))
|
||||
boolean(value(BEAUTIFY)) = 0;
|
||||
if (cgetflag("sc"))
|
||||
boolean(value(SCRIPT)) = 1;
|
||||
if (cgetflag("tb"))
|
||||
boolean(value(TABEXPAND)) = 1;
|
||||
if (cgetflag("vb"))
|
||||
boolean(value(VERBOSE)) = 1;
|
||||
if (cgetflag("nv"))
|
||||
boolean(value(VERBOSE)) = 0;
|
||||
if (cgetflag("ta"))
|
||||
boolean(value(TAND)) = 1;
|
||||
if (cgetflag("nt"))
|
||||
boolean(value(TAND)) = 0;
|
||||
if (cgetflag("rw"))
|
||||
boolean(value(RAWFTP)) = 1;
|
||||
if (cgetflag("hd"))
|
||||
boolean(value(HALFDUPLEX)) = 1;
|
||||
if (RE == NOSTR)
|
||||
RE = (char *)"tip.record";
|
||||
if (EX == NOSTR)
|
||||
EX = (char *)"\t\n\b\f";
|
||||
if (ES != NOSTR)
|
||||
vstring("es", ES);
|
||||
if (FO != NOSTR)
|
||||
vstring("fo", FO);
|
||||
if (PR != NOSTR)
|
||||
vstring("pr", PR);
|
||||
if (RC != NOSTR)
|
||||
vstring("rc", RC);
|
||||
if (cgetnum(bp, "dl", &DL) == -1)
|
||||
DL = 0;
|
||||
if (cgetnum(bp, "cl", &CL) == -1)
|
||||
CL = 0;
|
||||
if (cgetnum(bp, "et", &ET) == -1)
|
||||
ET = 10;
|
||||
}
|
||||
|
||||
char *
|
||||
getremote(host)
|
||||
char *host;
|
||||
{
|
||||
register char *cp;
|
||||
static char *next;
|
||||
static int lookedup = 0;
|
||||
|
||||
if (!lookedup) {
|
||||
if (host == NOSTR && (host = getenv("HOST")) == NOSTR) {
|
||||
fprintf(stderr, "tip: no host specified\n");
|
||||
exit(3);
|
||||
}
|
||||
getremcap(host);
|
||||
next = DV;
|
||||
lookedup++;
|
||||
}
|
||||
/*
|
||||
* We return a new device each time we're called (to allow
|
||||
* a rotary action to be simulated)
|
||||
*/
|
||||
if (next == NOSTR)
|
||||
return (NOSTR);
|
||||
if ((cp = index(next, ',')) == NULL) {
|
||||
DV = next;
|
||||
next = NOSTR;
|
||||
} else {
|
||||
*cp++ = '\0';
|
||||
DV = next;
|
||||
next = cp;
|
||||
}
|
||||
return (DV);
|
||||
}
|
451
usr.bin/tip/tip.1
Normal file
451
usr.bin/tip/tip.1
Normal file
@ -0,0 +1,451 @@
|
||||
.\" Copyright (c) 1980, 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.
|
||||
.\"
|
||||
.\" @(#)tip.1 8.4 (Berkeley) 4/18/94
|
||||
.\"
|
||||
.Dd April 18, 1994
|
||||
.Dt TIP 1
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm tip ,
|
||||
.Nm cu
|
||||
.Nd connect to a remote system
|
||||
.Sh SYNOPSIS
|
||||
.Nm tip
|
||||
.Op Fl v
|
||||
.Fl Ns Ns Ar speed
|
||||
.Ar system\-name
|
||||
.Nm tip
|
||||
.Op Fl v
|
||||
.Fl Ns Ns Ar speed
|
||||
.Ar phone\-number
|
||||
.Nm cu
|
||||
.Ar phone\-number
|
||||
.Op Fl t
|
||||
.Op Fl s Ar speed
|
||||
.Op Fl a Ar acu
|
||||
.Op Fl l Ar line
|
||||
.Op Fl #
|
||||
.Sh DESCRIPTION
|
||||
.Nm Tip
|
||||
and
|
||||
.Ar cu
|
||||
establish a full-duplex connection to another machine,
|
||||
giving the appearance of being logged in directly on the
|
||||
remote cpu. It goes without saying that you must have a login
|
||||
on the machine (or equivalent) to which you wish to connect.
|
||||
The preferred interface is
|
||||
.Nm tip .
|
||||
The
|
||||
.Ar cu
|
||||
interface is included for those people attached to the
|
||||
``call
|
||||
.Ux Ns ''
|
||||
command of version 7. This manual page
|
||||
describes only
|
||||
.Nm tip .
|
||||
.Pp
|
||||
Available Option:
|
||||
.Bl -tag -width indent
|
||||
.It Fl v
|
||||
Set verbose mode.
|
||||
.El
|
||||
.Pp
|
||||
Typed characters are normally transmitted directly to the remote
|
||||
machine (which does the echoing as well). A tilde (`~') appearing
|
||||
as the first character of a line is an escape signal; the following
|
||||
are recognized:
|
||||
.Bl -tag -width flag
|
||||
.It Ic \&~^D No or Ic \&~ .
|
||||
Drop the connection and exit
|
||||
(you may still be logged in on the
|
||||
remote machine).
|
||||
.It Ic \&~c Op Ar name
|
||||
Change directory to
|
||||
.Ar name
|
||||
(no argument
|
||||
implies change to your home directory).
|
||||
.It Ic \&~!
|
||||
Escape to a shell (exiting the shell will
|
||||
return you to tip).
|
||||
.It Ic \&~>
|
||||
Copy file from local to remote.
|
||||
.Nm Tip
|
||||
prompts for the name of a local file to transmit.
|
||||
.It Ic \&~<
|
||||
Copy file from remote to local.
|
||||
.Nm Tip
|
||||
prompts first for the name of the file to be sent, then for
|
||||
a command to be executed on the remote machine.
|
||||
.It Ic \&~p Ar from Op Ar to
|
||||
Send a file to a remote
|
||||
.Ux
|
||||
host. The put command causes the remote
|
||||
.Ux
|
||||
system to run the command string ``cat > 'to''', while
|
||||
.Nm tip
|
||||
sends it the ``from''
|
||||
file. If the ``to'' file isn't specified the ``from'' file name is used.
|
||||
This command is actually a
|
||||
.Ux
|
||||
specific version of the ``~>'' command.
|
||||
.It Ic \&~t Ar from Op Ar to
|
||||
Take a file from a remote
|
||||
.Ux
|
||||
host.
|
||||
As in the put command the ``to'' file
|
||||
defaults to the ``from'' file name if it isn't specified.
|
||||
The remote host
|
||||
executes the command string ``cat 'from';echo ^A'' to send the file to
|
||||
.Nm tip .
|
||||
.It Ic \&~|
|
||||
Pipe the output from a remote command to a local
|
||||
.Ux
|
||||
process.
|
||||
The command string sent to the local
|
||||
.Ux
|
||||
system is processed by the shell.
|
||||
.It Ic \&~$
|
||||
Pipe the output from a local
|
||||
.Ux
|
||||
process to the remote host.
|
||||
The command string sent to the local
|
||||
.Ux
|
||||
system is processed by the shell.
|
||||
.It Ic \&~C
|
||||
Fork a child process on the local system to perform special protocols
|
||||
such as \s-1XMODEM\s+1. The child program will be run with the following
|
||||
somewhat unusual arrangement of file descriptors:
|
||||
.nf
|
||||
.in +1i
|
||||
0 <-> local tty in
|
||||
1 <-> local tty out
|
||||
2 <-> local tty out
|
||||
3 <-> remote tty in
|
||||
4 <-> remote tty out
|
||||
.in -1i
|
||||
.fi
|
||||
.It Ic \&~#
|
||||
Send a
|
||||
.Dv BREAK
|
||||
to the remote system.
|
||||
For systems which don't support the
|
||||
necessary
|
||||
.Ar ioctl
|
||||
call the break is simulated by a sequence of line speed changes
|
||||
and
|
||||
.Dv DEL
|
||||
characters.
|
||||
.It Ic \&~s
|
||||
Set a variable (see the discussion below).
|
||||
.It Ic \&~^Z
|
||||
Stop
|
||||
.Nm tip
|
||||
(only available with job control).
|
||||
.It Ic \&~^Y
|
||||
Stop only the ``local side'' of
|
||||
.Nm tip
|
||||
(only available with job control);
|
||||
the ``remote side'' of
|
||||
.Nm tip ,
|
||||
the side that displays output from the remote host, is left running.
|
||||
.It Ic \&~?
|
||||
Get a summary of the tilde escapes
|
||||
.El
|
||||
.Pp
|
||||
.Nm Tip
|
||||
uses the file
|
||||
.Pa /etc/remote
|
||||
to find how to reach a particular
|
||||
system and to find out how it should operate while talking
|
||||
to the system;
|
||||
refer to
|
||||
.Xr remote 5
|
||||
for a full description.
|
||||
Each system has a default baud rate with which to
|
||||
establish a connection. If this value is not suitable, the baud rate
|
||||
to be used may be specified on the command line, e.g.
|
||||
.Ql "tip -300 mds" .
|
||||
.Pp
|
||||
When
|
||||
.Nm tip
|
||||
establishes a connection it sends out a
|
||||
connection message to the remote system; the default value, if any,
|
||||
is defined in
|
||||
.Pa /etc/remote
|
||||
(see
|
||||
.Xr remote 5 ) .
|
||||
.Pp
|
||||
When
|
||||
.Nm tip
|
||||
prompts for an argument (e.g. during setup of
|
||||
a file transfer) the line typed may be edited with the standard
|
||||
erase and kill characters. A null line in response to a prompt,
|
||||
or an interrupt, will abort the dialogue and return you to the
|
||||
remote machine.
|
||||
.Pp
|
||||
.Nm Tip
|
||||
guards against multiple users connecting to a remote system
|
||||
by opening modems and terminal lines with exclusive access,
|
||||
and by honoring the locking protocol used by
|
||||
.Xr uucico 8 .
|
||||
.Pp
|
||||
During file transfers
|
||||
.Nm tip
|
||||
provides a running count of the number of lines transferred.
|
||||
When using the ~> and ~< commands, the ``eofread'' and ``eofwrite''
|
||||
variables are used to recognize end-of-file when reading, and
|
||||
specify end-of-file when writing (see below). File transfers
|
||||
normally depend on tandem mode for flow control. If the remote
|
||||
system does not support tandem mode, ``echocheck'' may be set
|
||||
to indicate
|
||||
.Nm tip
|
||||
should synchronize with the remote system on the echo of each
|
||||
transmitted character.
|
||||
.Pp
|
||||
When
|
||||
.Nm tip
|
||||
must dial a phone number to connect to a system it will print
|
||||
various messages indicating its actions.
|
||||
.Nm Tip
|
||||
supports the
|
||||
.Tn DEC DN Ns-11
|
||||
and
|
||||
Racal-Vadic 831 auto-call-units;
|
||||
the
|
||||
.Tn DEC DF Ns \&02
|
||||
and
|
||||
.Tn DF Ns \&03 ,
|
||||
Ventel 212+, Racal-Vadic 3451, and
|
||||
Bizcomp 1031 and 1032 integral call unit/modems.
|
||||
.Ss VARIABLES
|
||||
.Nm Tip
|
||||
maintains a set of
|
||||
.Ar variables
|
||||
which control its operation.
|
||||
Some of these variables are read-only to normal users (root is allowed
|
||||
to change anything of interest). Variables may be displayed
|
||||
and set through the ``s'' escape. The syntax for variables is patterned
|
||||
after
|
||||
.Xr vi 1
|
||||
and
|
||||
.Xr Mail 1 .
|
||||
Supplying ``all''
|
||||
as an argument to the set command displays all variables readable by
|
||||
the user. Alternatively, the user may request display of a particular
|
||||
variable by attaching a `?' to the end. For example ``escape?''
|
||||
displays the current escape character.
|
||||
.Pp
|
||||
Variables are numeric, string, character, or boolean values. Boolean
|
||||
variables are set merely by specifying their name; they may be reset
|
||||
by prepending a `!' to the name. Other variable types are set by
|
||||
concatenating an `=' and the value. The entire assignment must not
|
||||
have any blanks in it. A single set command may be used to interrogate
|
||||
as well as set a number of variables.
|
||||
Variables may be initialized at run time by placing set commands
|
||||
(without the ``~s'' prefix in a file
|
||||
.Pa .tiprc
|
||||
in one's home directory). The
|
||||
.Fl v
|
||||
option causes
|
||||
.Nm tip
|
||||
to display the sets as they are made.
|
||||
Certain common variables have abbreviations.
|
||||
The following is a list of common variables,
|
||||
their abbreviations, and their default values.
|
||||
.Bl -tag -width Ar
|
||||
.It Ar beautify
|
||||
(bool) Discard unprintable characters when a session is being scripted;
|
||||
abbreviated
|
||||
.Ar be .
|
||||
.It Ar baudrate
|
||||
(num) The baud rate at which the connection was established;
|
||||
abbreviated
|
||||
.Ar ba .
|
||||
.It Ar dialtimeout
|
||||
(num) When dialing a phone number, the time (in seconds)
|
||||
to wait for a connection to be established; abbreviated
|
||||
.Ar dial .
|
||||
.It Ar echocheck
|
||||
(bool) Synchronize with the remote host during file transfer by
|
||||
waiting for the echo of the last character transmitted; default is
|
||||
.Ar off .
|
||||
.It Ar eofread
|
||||
(str) The set of characters which signify an end-of-transmission
|
||||
during a ~< file transfer command; abbreviated
|
||||
.Ar eofr .
|
||||
.It Ar eofwrite
|
||||
(str) The string sent to indicate end-of-transmission during
|
||||
a ~> file transfer command; abbreviated
|
||||
.Ar eofw .
|
||||
.It Ar eol
|
||||
(str) The set of characters which indicate an end-of-line.
|
||||
.Nm Tip
|
||||
will recognize escape characters only after an end-of-line.
|
||||
.It Ar escape
|
||||
(char) The command prefix (escape) character; abbreviated
|
||||
.Ar es ;
|
||||
default value is `~'.
|
||||
.It Ar exceptions
|
||||
(str) The set of characters which should not be discarded
|
||||
due to the beautification switch; abbreviated
|
||||
.Ar ex ;
|
||||
default value is ``\et\en\ef\eb''.
|
||||
.It Ar force
|
||||
(char) The character used to force literal data transmission;
|
||||
abbreviated
|
||||
.Ar fo ;
|
||||
default value is `^P'.
|
||||
.It Ar framesize
|
||||
(num) The amount of data (in bytes) to buffer between file system
|
||||
writes when receiving files; abbreviated
|
||||
.Ar fr .
|
||||
.It Ar host
|
||||
(str) The name of the host to which you are connected; abbreviated
|
||||
.Ar ho .
|
||||
.It Ar prompt
|
||||
(char) The character which indicates an end-of-line on the remote
|
||||
host; abbreviated
|
||||
.Ar pr ;
|
||||
default value is `\en'. This value is used to synchronize during
|
||||
data transfers. The count of lines transferred during a file transfer
|
||||
command is based on receipt of this character.
|
||||
.It Ar raise
|
||||
(bool) Upper case mapping mode; abbreviated
|
||||
.Ar ra ;
|
||||
default value is
|
||||
.Ar off .
|
||||
When this mode is enabled, all lower case letters will be mapped to
|
||||
upper case by
|
||||
.Nm tip
|
||||
for transmission to the remote machine.
|
||||
.It Ar raisechar
|
||||
(char) The input character used to toggle upper case mapping mode;
|
||||
abbreviated
|
||||
.Ar rc ;
|
||||
default value is `^A'.
|
||||
.It Ar record
|
||||
(str) The name of the file in which a session script is recorded;
|
||||
abbreviated
|
||||
.Ar rec ;
|
||||
default value is ``tip.record''.
|
||||
.It Ar script
|
||||
(bool) Session scripting mode; abbreviated
|
||||
.Ar sc ;
|
||||
default is
|
||||
.Ar off .
|
||||
When
|
||||
.Ar script
|
||||
is
|
||||
.Li true ,
|
||||
.Nm tip
|
||||
will record everything transmitted by the remote machine in
|
||||
the script record file specified in
|
||||
.Ar record .
|
||||
If the
|
||||
.Ar beautify
|
||||
switch is on, only printable
|
||||
.Tn ASCII
|
||||
characters will be included in
|
||||
the script file (those characters betwee 040 and 0177). The
|
||||
variable
|
||||
.Ar exceptions
|
||||
is used to indicate characters which are an exception to the normal
|
||||
beautification rules.
|
||||
.It Ar tabexpand
|
||||
(bool) Expand tabs to spaces during file transfers; abbreviated
|
||||
.Ar tab ;
|
||||
default value is
|
||||
.Ar false .
|
||||
Each tab is expanded to 8 spaces.
|
||||
.It Ar verbose
|
||||
(bool) Verbose mode; abbreviated
|
||||
.Ar verb ;
|
||||
default is
|
||||
.Ar true .
|
||||
When verbose mode is enabled,
|
||||
.Nm tip
|
||||
prints messages while dialing, shows the current number
|
||||
of lines transferred during a file transfer operations,
|
||||
and more.
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Nm Tip
|
||||
uses the following environment variables:
|
||||
.Bl -tag -width Fl
|
||||
.It Ev SHELL
|
||||
(str) The name of the shell to use for the ~! command; default
|
||||
value is ``/bin/sh'', or taken from the environment.
|
||||
.It Ev HOME
|
||||
(str) The home directory to use for the ~c command; default
|
||||
value is taken from the environment.
|
||||
.It Ev HOST
|
||||
Check for a default host if none specified.
|
||||
.El
|
||||
.Pp
|
||||
The variables
|
||||
.Ev ${REMOTE}
|
||||
and
|
||||
.Ev ${PHONES}
|
||||
are also exported.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /var/spool/uucp/LCK..* -compact
|
||||
.It Pa /etc/remote
|
||||
Global system descriptions.
|
||||
.It Pa /etc/phones
|
||||
Global phone number data base.
|
||||
.It ${REMOTE}
|
||||
Private system descriptions.
|
||||
.It ${PHONES}
|
||||
Private phone numbers.
|
||||
.It ~/.tiprc
|
||||
Initialization file.
|
||||
.It Pa tip.record
|
||||
Record file.
|
||||
.It /var/log/aculog
|
||||
Line access log.
|
||||
.It Pa /var/spool/uucp/LCK..*
|
||||
Lock file to avoid conflicts with
|
||||
.Xr uucp .
|
||||
.El
|
||||
.Sh DIAGNOSTICS
|
||||
Diagnostics are, hopefully, self explanatory.
|
||||
.Sh SEE ALSO
|
||||
.Xr remote 5 ,
|
||||
.Xr phones 5
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm tip
|
||||
appeared command in
|
||||
.Bx 4.2 .
|
||||
.Sh BUGS
|
||||
The full set of variables is undocumented and should, probably, be
|
||||
pared down.
|
353
usr.bin/tip/value.c
Normal file
353
usr.bin/tip/value.c
Normal file
@ -0,0 +1,353 @@
|
||||
/*
|
||||
* 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[] = "@(#)value.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "tip.h"
|
||||
|
||||
#define MIDDLE 35
|
||||
|
||||
static value_t *vlookup();
|
||||
static int col = 0;
|
||||
|
||||
/*
|
||||
* Variable manipulation
|
||||
*/
|
||||
vinit()
|
||||
{
|
||||
register value_t *p;
|
||||
register char *cp;
|
||||
FILE *f;
|
||||
char file[256];
|
||||
|
||||
for (p = vtable; p->v_name != NULL; p++) {
|
||||
if (p->v_type&ENVIRON)
|
||||
if (cp = getenv(p->v_name))
|
||||
p->v_value = cp;
|
||||
if (p->v_type&IREMOTE)
|
||||
number(p->v_value) = *address(p->v_value);
|
||||
}
|
||||
/*
|
||||
* Read the .tiprc file in the HOME directory
|
||||
* for sets
|
||||
*/
|
||||
strcpy(file, value(HOME));
|
||||
strcat(file, "/.tiprc");
|
||||
if ((f = fopen(file, "r")) != NULL) {
|
||||
register char *tp;
|
||||
|
||||
while (fgets(file, sizeof(file)-1, f) != NULL) {
|
||||
if (vflag)
|
||||
printf("set %s", file);
|
||||
if (tp = rindex(file, '\n'))
|
||||
*tp = '\0';
|
||||
vlex(file);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
/*
|
||||
* To allow definition of exception prior to fork
|
||||
*/
|
||||
vtable[EXCEPTIONS].v_access &= ~(WRITE<<PUBLIC);
|
||||
}
|
||||
|
||||
static int vaccess();
|
||||
|
||||
/*VARARGS1*/
|
||||
vassign(p, v)
|
||||
register value_t *p;
|
||||
char *v;
|
||||
{
|
||||
|
||||
if (!vaccess(p->v_access, WRITE)) {
|
||||
printf("access denied\r\n");
|
||||
return;
|
||||
}
|
||||
switch (p->v_type&TMASK) {
|
||||
|
||||
case STRING:
|
||||
if (p->v_value && equal(p->v_value, v))
|
||||
return;
|
||||
if (!(p->v_type&(ENVIRON|INIT)))
|
||||
free(p->v_value);
|
||||
if ((p->v_value = malloc(size(v)+1)) == NOSTR) {
|
||||
printf("out of core\r\n");
|
||||
return;
|
||||
}
|
||||
p->v_type &= ~(ENVIRON|INIT);
|
||||
strcpy(p->v_value, v);
|
||||
break;
|
||||
|
||||
case NUMBER:
|
||||
if (number(p->v_value) == number(v))
|
||||
return;
|
||||
number(p->v_value) = number(v);
|
||||
break;
|
||||
|
||||
case BOOL:
|
||||
if (boolean(p->v_value) == (*v != '!'))
|
||||
return;
|
||||
boolean(p->v_value) = (*v != '!');
|
||||
break;
|
||||
|
||||
case CHAR:
|
||||
if (character(p->v_value) == *v)
|
||||
return;
|
||||
character(p->v_value) = *v;
|
||||
}
|
||||
p->v_access |= CHANGED;
|
||||
}
|
||||
|
||||
static void vprint();
|
||||
|
||||
vlex(s)
|
||||
register char *s;
|
||||
{
|
||||
register value_t *p;
|
||||
static void vtoken();
|
||||
|
||||
if (equal(s, "all")) {
|
||||
for (p = vtable; p->v_name; p++)
|
||||
if (vaccess(p->v_access, READ))
|
||||
vprint(p);
|
||||
} else {
|
||||
register char *cp;
|
||||
|
||||
do {
|
||||
if (cp = vinterp(s, ' '))
|
||||
cp++;
|
||||
vtoken(s);
|
||||
s = cp;
|
||||
} while (s);
|
||||
}
|
||||
if (col > 0) {
|
||||
printf("\r\n");
|
||||
col = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vtoken(s)
|
||||
register char *s;
|
||||
{
|
||||
register value_t *p;
|
||||
register char *cp;
|
||||
char *expand();
|
||||
|
||||
if (cp = index(s, '=')) {
|
||||
*cp = '\0';
|
||||
if (p = vlookup(s)) {
|
||||
cp++;
|
||||
if (p->v_type&NUMBER)
|
||||
vassign(p, atoi(cp));
|
||||
else {
|
||||
if (strcmp(s, "record") == 0)
|
||||
cp = expand(cp);
|
||||
vassign(p, cp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (cp = index(s, '?')) {
|
||||
*cp = '\0';
|
||||
if ((p = vlookup(s)) && vaccess(p->v_access, READ)) {
|
||||
vprint(p);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (*s != '!')
|
||||
p = vlookup(s);
|
||||
else
|
||||
p = vlookup(s+1);
|
||||
if (p != NOVAL) {
|
||||
vassign(p, s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
printf("%s: unknown variable\r\n", s);
|
||||
}
|
||||
|
||||
static void
|
||||
vprint(p)
|
||||
register value_t *p;
|
||||
{
|
||||
register char *cp;
|
||||
extern char *interp(), *ctrl();
|
||||
|
||||
if (col > 0 && col < MIDDLE)
|
||||
while (col++ < MIDDLE)
|
||||
putchar(' ');
|
||||
col += size(p->v_name);
|
||||
switch (p->v_type&TMASK) {
|
||||
|
||||
case BOOL:
|
||||
if (boolean(p->v_value) == FALSE) {
|
||||
col++;
|
||||
putchar('!');
|
||||
}
|
||||
printf("%s", p->v_name);
|
||||
break;
|
||||
|
||||
case STRING:
|
||||
printf("%s=", p->v_name);
|
||||
col++;
|
||||
if (p->v_value) {
|
||||
cp = interp(p->v_value, NULL);
|
||||
col += size(cp);
|
||||
printf("%s", cp);
|
||||
}
|
||||
break;
|
||||
|
||||
case NUMBER:
|
||||
col += 6;
|
||||
printf("%s=%-5d", p->v_name, number(p->v_value));
|
||||
break;
|
||||
|
||||
case CHAR:
|
||||
printf("%s=", p->v_name);
|
||||
col++;
|
||||
if (p->v_value) {
|
||||
cp = ctrl(character(p->v_value));
|
||||
col += size(cp);
|
||||
printf("%s", cp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (col >= MIDDLE) {
|
||||
col = 0;
|
||||
printf("\r\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
vaccess(mode, rw)
|
||||
register unsigned mode, rw;
|
||||
{
|
||||
if (mode & (rw<<PUBLIC))
|
||||
return (1);
|
||||
if (mode & (rw<<PRIVATE))
|
||||
return (1);
|
||||
return ((mode & (rw<<ROOT)) && getuid() == 0);
|
||||
}
|
||||
|
||||
static value_t *
|
||||
vlookup(s)
|
||||
register char *s;
|
||||
{
|
||||
register value_t *p;
|
||||
|
||||
for (p = vtable; p->v_name; p++)
|
||||
if (equal(p->v_name, s) || (p->v_abrev && equal(p->v_abrev, s)))
|
||||
return (p);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
vinterp(s, stop)
|
||||
register char *s;
|
||||
char stop;
|
||||
{
|
||||
register char *p = s, c;
|
||||
int num;
|
||||
|
||||
while ((c = *s++) && c != stop)
|
||||
switch (c) {
|
||||
|
||||
case '^':
|
||||
if (*s)
|
||||
*p++ = *s++ - 0100;
|
||||
else
|
||||
*p++ = c;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
num = 0;
|
||||
c = *s++;
|
||||
if (c >= '0' && c <= '7')
|
||||
num = (num<<3)+(c-'0');
|
||||
else {
|
||||
register char *q = "n\nr\rt\tb\bf\f";
|
||||
|
||||
for (; *q; q++)
|
||||
if (c == *q++) {
|
||||
*p++ = *q;
|
||||
goto cont;
|
||||
}
|
||||
*p++ = c;
|
||||
cont:
|
||||
break;
|
||||
}
|
||||
if ((c = *s++) >= '0' && c <= '7') {
|
||||
num = (num<<3)+(c-'0');
|
||||
if ((c = *s++) >= '0' && c <= '7')
|
||||
num = (num<<3)+(c-'0');
|
||||
else
|
||||
s--;
|
||||
} else
|
||||
s--;
|
||||
*p++ = num;
|
||||
break;
|
||||
|
||||
default:
|
||||
*p++ = c;
|
||||
}
|
||||
*p = '\0';
|
||||
return (c == stop ? s-1 : NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* assign variable s with value v (for NUMBER or STRING or CHAR types)
|
||||
*/
|
||||
|
||||
vstring(s,v)
|
||||
register char *s;
|
||||
register char *v;
|
||||
{
|
||||
register value_t *p;
|
||||
char *expand();
|
||||
|
||||
p = vlookup(s);
|
||||
if (p == 0)
|
||||
return (1);
|
||||
if (p->v_type&NUMBER)
|
||||
vassign(p, atoi(v));
|
||||
else {
|
||||
if (strcmp(s, "record") == 0)
|
||||
v = expand(v);
|
||||
vassign(p, v);
|
||||
}
|
||||
return (0);
|
||||
}
|
112
usr.bin/tip/vars.c
Normal file
112
usr.bin/tip/vars.c
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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[] = "@(#)vars.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "tip.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
/*
|
||||
* Definition of variables
|
||||
*/
|
||||
value_t vtable[] = {
|
||||
{ "beautify", BOOL, (READ|WRITE)<<PUBLIC,
|
||||
"be", (char *)TRUE },
|
||||
{ "baudrate", NUMBER|IREMOTE|INIT, (READ<<PUBLIC)|(WRITE<<ROOT),
|
||||
"ba", (char *)&BR },
|
||||
{ "dialtimeout",NUMBER, (READ<<PUBLIC)|(WRITE<<ROOT),
|
||||
"dial", (char *)60 },
|
||||
{ "eofread", STRING|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
|
||||
"eofr", (char *)&IE },
|
||||
{ "eofwrite", STRING|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
|
||||
"eofw", (char *)&OE },
|
||||
{ "eol", STRING|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
|
||||
NOSTR, (char *)&EL },
|
||||
{ "escape", CHAR, (READ|WRITE)<<PUBLIC,
|
||||
"es", (char *)'~' },
|
||||
{ "exceptions", STRING|INIT|IREMOTE, (READ|WRITE)<<PUBLIC,
|
||||
"ex", (char *)&EX },
|
||||
{ "force", CHAR, (READ|WRITE)<<PUBLIC,
|
||||
"fo", (char *)CTRL('p') },
|
||||
{ "framesize", NUMBER|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
|
||||
"fr", (char *)&FS },
|
||||
{ "host", STRING|IREMOTE|INIT, READ<<PUBLIC,
|
||||
"ho", (char *)&HO },
|
||||
{ "log", STRING|INIT, (READ|WRITE)<<ROOT,
|
||||
NOSTR, _PATH_ACULOG },
|
||||
{ "phones", STRING|INIT|IREMOTE, READ<<PUBLIC,
|
||||
NOSTR, (char *)&PH },
|
||||
{ "prompt", CHAR, (READ|WRITE)<<PUBLIC,
|
||||
"pr", (char *)'\n' },
|
||||
{ "raise", BOOL, (READ|WRITE)<<PUBLIC,
|
||||
"ra", (char *)FALSE },
|
||||
{ "raisechar", CHAR, (READ|WRITE)<<PUBLIC,
|
||||
"rc", (char *)CTRL('a') },
|
||||
{ "record", STRING|INIT|IREMOTE, (READ|WRITE)<<PUBLIC,
|
||||
"rec", (char *)&RE },
|
||||
{ "remote", STRING|INIT|IREMOTE, READ<<PUBLIC,
|
||||
NOSTR, (char *)&RM },
|
||||
{ "script", BOOL, (READ|WRITE)<<PUBLIC,
|
||||
"sc", (char *)FALSE },
|
||||
{ "tabexpand", BOOL, (READ|WRITE)<<PUBLIC,
|
||||
"tab", (char *)FALSE },
|
||||
{ "verbose", BOOL, (READ|WRITE)<<PUBLIC,
|
||||
"verb", (char *)TRUE },
|
||||
{ "SHELL", STRING|ENVIRON|INIT, (READ|WRITE)<<PUBLIC,
|
||||
NULL, _PATH_BSHELL },
|
||||
{ "HOME", STRING|ENVIRON, (READ|WRITE)<<PUBLIC,
|
||||
NOSTR, NOSTR },
|
||||
{ "echocheck", BOOL, (READ|WRITE)<<PUBLIC,
|
||||
"ec", (char *)FALSE },
|
||||
{ "disconnect", STRING|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
|
||||
"di", (char *)&DI },
|
||||
{ "tandem", BOOL, (READ|WRITE)<<PUBLIC,
|
||||
"ta", (char *)TRUE },
|
||||
{ "linedelay", NUMBER|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
|
||||
"ldelay", (char *)&DL },
|
||||
{ "chardelay", NUMBER|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
|
||||
"cdelay", (char *)&CL },
|
||||
{ "etimeout", NUMBER|IREMOTE|INIT, (READ|WRITE)<<PUBLIC,
|
||||
"et", (char *)&ET },
|
||||
{ "rawftp", BOOL, (READ|WRITE)<<PUBLIC,
|
||||
"raw", (char *)FALSE },
|
||||
{ "halfduplex", BOOL, (READ|WRITE)<<PUBLIC,
|
||||
"hdx", (char *)FALSE },
|
||||
{ "localecho", BOOL, (READ|WRITE)<<PUBLIC,
|
||||
"le", (char *)FALSE },
|
||||
{ "parity", STRING|INIT|IREMOTE, (READ|WRITE)<<PUBLIC,
|
||||
"par", (char *)&PA },
|
||||
{ NOSTR, NULL, NULL, NOSTR, NOSTR }
|
||||
};
|
814
usr.bin/uucp/acucntrl/acucntrl.c
Normal file
814
usr.bin/uucp/acucntrl/acucntrl.c
Normal file
@ -0,0 +1,814 @@
|
||||
/*-
|
||||
* Copyright (c) 1985, 1986, 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) 1985, 1986, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)acucntrl.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/* acucntrl - turn around tty line between dialin and dialout
|
||||
*
|
||||
* Usage: acucntrl {enable,disable} /dev/ttydX
|
||||
*
|
||||
* History:
|
||||
* First written by Allan Wilkes (fisher!allan)
|
||||
*
|
||||
* Modified June 8,1983 by W.Sebok (astrovax!wls) to poke kernel rather
|
||||
* than use kernel hack to turn on/off modem control, using subroutine
|
||||
* stolen from program written by Tsutomu Shimomura
|
||||
* {astrovax,escher}!tsutomu
|
||||
*
|
||||
* Worked over many times by W.Sebok (i.e. hacked to death)
|
||||
*
|
||||
* Operation:
|
||||
* disable (i.e. setup for dialing out)
|
||||
* (1) check input arguments
|
||||
* (2) look in _PATH_UTMP to check that the line is not in use by another
|
||||
* (3) disable modem control on terminal
|
||||
* (4) check for carrier on device
|
||||
* (5) change owner of device to real id
|
||||
* (6) edit _PATH_TTYS, changing the first character of the appropriate
|
||||
* line to 0
|
||||
* (7) send a hangup to process 1 to poke init to disable getty
|
||||
* (8) post uid name in capitals in _PATH_UTMP to let world know device
|
||||
* has been grabbed
|
||||
* (9) make sure that DTR is on
|
||||
*
|
||||
* enable (i.e.) restore for dialin
|
||||
* (1) check input arguments
|
||||
* (2) look in _PATH_UTMP to check that the line is not in use by another
|
||||
* (3) make sure modem control on terminal is disabled
|
||||
* (4) turn off DTR to make sure line is hung up
|
||||
* (5) condition line: clear exclusive use and set hangup on close modes
|
||||
* (6) turn on modem control
|
||||
* (7) edit _PATH_TTYS, changing the first character of the appropriate
|
||||
* line to 1
|
||||
* (8) send a hangup to process 1 to poke init to enable getty
|
||||
* (9) clear uid name for _PATH_UTMP
|
||||
*/
|
||||
|
||||
/* #define SENSECARRIER */
|
||||
|
||||
#include "uucp.h"
|
||||
#ifdef DIALINOUT
|
||||
#include <sys/buf.h>
|
||||
#include <signal.h>
|
||||
#include <sys/conf.h>
|
||||
#ifdef vax
|
||||
#ifdef BSD4_2
|
||||
#include <vaxuba/ubavar.h>
|
||||
#else
|
||||
#include <sys/ubavar.h>
|
||||
#endif
|
||||
#endif /* vax */
|
||||
#include <sys/stat.h>
|
||||
#include <nlist.h>
|
||||
#include <sgtty.h>
|
||||
#include <utmp.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/file.h>
|
||||
#include "pathnames.h"
|
||||
|
||||
#define NDZLINE 8 /* lines/dz */
|
||||
#define NDHLINE 16 /* lines/dh */
|
||||
#define NDMFLINE 8 /* lines/dmf */
|
||||
|
||||
#define DZ11 1
|
||||
#define DH11 2
|
||||
#define DMF 3
|
||||
|
||||
#define NLVALUE(val) (nl[val].n_value)
|
||||
|
||||
struct nlist nl[] = {
|
||||
#define CDEVSW 0
|
||||
{ "_cdevsw" },
|
||||
|
||||
#define DZOPEN 1
|
||||
{ "_dzopen" },
|
||||
#define DZINFO 2
|
||||
{ "_dzinfo" },
|
||||
#define NDZ11 3
|
||||
{ "_dz_cnt" },
|
||||
#define DZSCAR 4
|
||||
{ "_dzsoftCAR" },
|
||||
|
||||
#define DHOPEN 5
|
||||
{ "_dhopen" },
|
||||
#define DHINFO 6
|
||||
{ "_dhinfo" },
|
||||
#define NDH11 7
|
||||
{ "_ndh11" },
|
||||
#define DHSCAR 8
|
||||
{ "_dhsoftCAR" },
|
||||
|
||||
#define DMFOPEN 9
|
||||
{ "_dmfopen" },
|
||||
#define DMFINFO 10
|
||||
{ "_dmfinfo" },
|
||||
#define NDMF 11
|
||||
{ "_ndmf" },
|
||||
#define DMFSCAR 12
|
||||
{ "_dmfsoftCAR" },
|
||||
|
||||
{ "\0" }
|
||||
};
|
||||
|
||||
#define ENABLE 1
|
||||
#define DISABLE 0
|
||||
|
||||
char Etcttys[] = _PATH_TTYS;
|
||||
#ifdef BSD4_3
|
||||
FILE *ttysfile, *nttysfile;
|
||||
char NEtcttys[] = _PATH_NEWTTYS;
|
||||
extern long ftell();
|
||||
#endif BSD4_3
|
||||
char Devhome[] = _PATH_DEV;
|
||||
|
||||
char usage[] = "Usage: acucntrl {dis|en}able ttydX\n";
|
||||
|
||||
struct utmp utmp;
|
||||
char resettty, resetmodem;
|
||||
int etcutmp;
|
||||
off_t utmploc;
|
||||
off_t ttyslnbeg;
|
||||
extern int errno;
|
||||
extern char *sys_errlist[];
|
||||
off_t lseek();
|
||||
|
||||
#define NAMSIZ sizeof(utmp.ut_name)
|
||||
#define LINSIZ sizeof(utmp.ut_line)
|
||||
|
||||
main(argc, argv)
|
||||
int argc; char *argv[];
|
||||
{
|
||||
register char *p;
|
||||
register int i;
|
||||
char uname[NAMSIZ], Uname[NAMSIZ];
|
||||
int enable ;
|
||||
char *device;
|
||||
int devfile;
|
||||
int uid, gid;
|
||||
struct passwd *getpwuid();
|
||||
char *rindex();
|
||||
|
||||
/* check input arguments */
|
||||
if (argc!=3 && argc != 4) {
|
||||
fprintf(stderr, usage);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* interpret command type */
|
||||
if (prefix(argv[1], "disable") || strcmp(argv[1], "dialout")==0)
|
||||
enable = 0;
|
||||
else if (prefix(argv[1], "enable") || strcmp(argv[1], "dialin")==0)
|
||||
enable = 1;
|
||||
else {
|
||||
fprintf(stderr, usage);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
device = rindex(argv[2], '/');
|
||||
device = (device == NULL) ? argv[2]: device+1;
|
||||
|
||||
opnttys(device);
|
||||
|
||||
#ifdef vax
|
||||
/* Get nlist info */
|
||||
nlist(_PATH_UNIX, nl);
|
||||
#endif vax
|
||||
|
||||
/* Chdir to /dev */
|
||||
if(chdir(Devhome) < 0) {
|
||||
fprintf(stderr, "Cannot chdir to %s: %s\r\n",
|
||||
Devhome, sys_errlist[errno]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Get uid information */
|
||||
uid = getuid();
|
||||
gid = getgid();
|
||||
|
||||
p = getpwuid(uid)->pw_name;
|
||||
if (p==NULL) {
|
||||
fprintf(stderr, "cannot get uid name\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strcmp(p, "uucp") == 0 && argc == 4)
|
||||
p = argv[3];
|
||||
|
||||
/* to upper case */
|
||||
i = 0;
|
||||
do {
|
||||
uname[i] = *p;
|
||||
Uname[i++] = (*p>='a' && *p<='z') ? (*p - ('a'-'A')) : *p;
|
||||
} while (*p++ && i<NAMSIZ);
|
||||
|
||||
/* check to see if line is being used */
|
||||
if( (etcutmp = open(_PATH_UTMP, 2)) < 0) {
|
||||
fprintf(stderr, "On open %s open: %s\n",
|
||||
_PATH_UTMP, sys_errlist[errno]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
(void)lseek(etcutmp, utmploc, 0);
|
||||
|
||||
i = read(etcutmp, (char *)&utmp, sizeof(struct utmp));
|
||||
|
||||
if(
|
||||
i == sizeof(struct utmp) &&
|
||||
utmp.ut_line[0] != '\0' &&
|
||||
utmp.ut_name[0] != '\0' &&
|
||||
(
|
||||
!upcase(utmp.ut_name, NAMSIZ) ||
|
||||
(
|
||||
uid != 0 &&
|
||||
strncmp(utmp.ut_name, Uname, NAMSIZ) != 0
|
||||
)
|
||||
)
|
||||
) {
|
||||
fprintf(stderr, "%s in use by %s\n", device, utmp.ut_name);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
#ifndef sequent
|
||||
/* Disable modem control */
|
||||
if (setmodem(device, DISABLE) < 0) {
|
||||
fprintf(stderr, "Unable to disable modem control\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif !sequent
|
||||
|
||||
if (enable) {
|
||||
#ifdef sequent
|
||||
if (setmodem(device, ENABLE) < 0) {
|
||||
fprintf(stderr, "Cannot Enable modem control\n");
|
||||
(void)setmodem(device, i);
|
||||
exit(1);
|
||||
}
|
||||
#endif sequent
|
||||
#ifndef sequent
|
||||
if((devfile = open(device, 1)) < 0) {
|
||||
fprintf(stderr, "On open of %s: %s\n",
|
||||
device, sys_errlist[errno]);
|
||||
(void)setmodem(device, resetmodem);
|
||||
exit(1);
|
||||
}
|
||||
/* Try one last time to hang up */
|
||||
if (ioctl(devfile, (int)TIOCCDTR, (char *)0) < 0)
|
||||
fprintf(stderr, "On TIOCCDTR ioctl: %s\n",
|
||||
sys_errlist[errno]);
|
||||
|
||||
if (ioctl(devfile, (int)TIOCNXCL, (char *)0) < 0)
|
||||
fprintf(stderr,
|
||||
"Cannot clear Exclusive Use on %s: %s\n",
|
||||
device, sys_errlist[errno]);
|
||||
|
||||
if (ioctl(devfile, (int)TIOCHPCL, (char *)0) < 0)
|
||||
fprintf(stderr,
|
||||
"Cannot set hangup on close on %s: %s\n",
|
||||
device, sys_errlist[errno]);
|
||||
|
||||
#endif !sequent
|
||||
i = resetmodem;
|
||||
|
||||
#ifndef sequent
|
||||
if (setmodem(device, ENABLE) < 0) {
|
||||
fprintf(stderr, "Cannot Enable modem control\n");
|
||||
(void)setmodem(device, i);
|
||||
exit(1);
|
||||
}
|
||||
#endif sequent
|
||||
resetmodem=i;
|
||||
|
||||
if (settys(ENABLE)) {
|
||||
fprintf(stderr, "%s already enabled\n", device);
|
||||
} else {
|
||||
pokeinit(device, Uname, enable);
|
||||
}
|
||||
post(device, "");
|
||||
|
||||
} else {
|
||||
#if defined(TIOCMGET) && defined(SENSECARRIER)
|
||||
if (uid!=0) {
|
||||
int linestat = 0;
|
||||
|
||||
/* check for presence of carrier */
|
||||
sleep(2); /* need time after modem control turnoff */
|
||||
|
||||
if((devfile = open(device, 1)) < 0) {
|
||||
fprintf(stderr, "On open of %s: %s\n",
|
||||
device, sys_errlist[errno]);
|
||||
(void)setmodem(device, resetmodem);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
(void)ioctl(devfile, TIOCMGET, &linestat);
|
||||
|
||||
if (linestat&TIOCM_CAR) {
|
||||
fprintf(stderr, "%s is in use (Carrier On)\n",
|
||||
device);
|
||||
(void)setmodem(device, resetmodem);
|
||||
exit(2);
|
||||
}
|
||||
(void)close(devfile);
|
||||
}
|
||||
#endif TIOCMGET
|
||||
/* chown device */
|
||||
if(chown(device, uid, gid) < 0)
|
||||
fprintf(stderr, "Cannot chown %s: %s\n",
|
||||
device, sys_errlist[errno]);
|
||||
|
||||
|
||||
/* poke init */
|
||||
if(settys(DISABLE)) {
|
||||
fprintf(stderr, "%s already disabled\n", device);
|
||||
} else {
|
||||
pokeinit(device, Uname, enable);
|
||||
}
|
||||
post(device, Uname);
|
||||
#ifdef sequent
|
||||
/* Disable modem control */
|
||||
if (setmodem(device, DISABLE) < 0) {
|
||||
fprintf(stderr, "Unable to disable modem control\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif sequent
|
||||
if((devfile = open(device, O_RDWR|O_NDELAY)) < 0) {
|
||||
fprintf(stderr, "On %s open: %s\n",
|
||||
device, sys_errlist[errno]);
|
||||
} else {
|
||||
if(ioctl(devfile, (int)TIOCSDTR, (char *)0) < 0)
|
||||
fprintf(stderr,
|
||||
"Cannot set DTR on %s: %s\n",
|
||||
device, sys_errlist[errno]);
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* return true if no lower case */
|
||||
upcase(str, len)
|
||||
register char *str;
|
||||
register int len;
|
||||
{
|
||||
for (; *str, --len >= 0 ; str++)
|
||||
if (*str>='a' && *str<='z')
|
||||
return(0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* Post name to public */
|
||||
post(device, name)
|
||||
char *device, *name;
|
||||
{
|
||||
(void)time((time_t *)&utmp.ut_time);
|
||||
strncpy(utmp.ut_line, device, LINSIZ);
|
||||
strncpy(utmp.ut_name, name, NAMSIZ);
|
||||
if (lseek(etcutmp, utmploc, 0) < 0)
|
||||
fprintf(stderr, "on lseek in %s: %s",
|
||||
_PATH_UTMP, sys_errlist[errno]);
|
||||
if (write(etcutmp, (char *)&utmp, sizeof(utmp)) < 0)
|
||||
fprintf(stderr, "on write in %s: %s",
|
||||
_PATH_UTMP, sys_errlist[errno]);
|
||||
}
|
||||
|
||||
/* poke process 1 and wait for it to do its thing */
|
||||
pokeinit(device, uname, enable)
|
||||
char *uname, *device; int enable;
|
||||
{
|
||||
struct utmp utmp;
|
||||
register int i;
|
||||
|
||||
post(device, uname);
|
||||
|
||||
/* poke init */
|
||||
if (kill(1, SIGHUP)) {
|
||||
fprintf(stderr,
|
||||
"Cannot send hangup to init process: %s\n",
|
||||
sys_errlist[errno]);
|
||||
(void)settys(resettty);
|
||||
(void)setmodem(device, resetmodem);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (enable)
|
||||
return;
|
||||
|
||||
/* wait till init has responded, clearing the utmp entry */
|
||||
i = 100;
|
||||
do {
|
||||
sleep(1);
|
||||
if (lseek(etcutmp, utmploc, 0) < 0)
|
||||
fprintf(stderr, "On lseek in %s: %s",
|
||||
_PATH_UTMP, sys_errlist[errno]);
|
||||
if (read(etcutmp, (char *)&utmp, sizeof utmp) < 0)
|
||||
fprintf(stderr, "On read from %s: %s",
|
||||
_PATH_UTMP, sys_errlist[errno]);
|
||||
} while (utmp.ut_name[0] != '\0' && --i > 0);
|
||||
}
|
||||
|
||||
#ifdef BSD4_3
|
||||
/* identify terminal line in ttys */
|
||||
opnttys(device)
|
||||
char *device;
|
||||
{
|
||||
register int ndevice;
|
||||
register char *p;
|
||||
char *index();
|
||||
char linebuf[BUFSIZ];
|
||||
|
||||
ttysfile = NULL;
|
||||
do {
|
||||
if (ttysfile != NULL) {
|
||||
fclose(ttysfile);
|
||||
sleep(5);
|
||||
}
|
||||
ttysfile = fopen(Etcttys, "r");
|
||||
if(ttysfile == NULL) {
|
||||
fprintf(stderr, "Cannot open %s: %s\n", Etcttys,
|
||||
sys_errlist[errno]);
|
||||
exit(1);
|
||||
}
|
||||
} while (flock(fileno(ttysfile), LOCK_NB|LOCK_EX) < 0);
|
||||
nttysfile = fopen(NEtcttys, "w");
|
||||
if(nttysfile == NULL) {
|
||||
fprintf(stderr, "Cannot open %s: %s\n", Etcttys,
|
||||
sys_errlist[errno]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ndevice = strlen(device);
|
||||
#ifndef BRL4_2
|
||||
utmploc = sizeof(utmp);
|
||||
#else BRL4_2
|
||||
utmploc = 0;
|
||||
#endif BRL4_2
|
||||
|
||||
while(fgets(linebuf, sizeof(linebuf) - 1, ttysfile) != NULL) {
|
||||
if(strncmp(device, linebuf, ndevice) == 0)
|
||||
return;
|
||||
ttyslnbeg += strlen(linebuf);
|
||||
if (linebuf[0] != '#' && linebuf[0] != '\0')
|
||||
utmploc += sizeof(utmp);
|
||||
if (fputs(linebuf, nttysfile) == NULL) {
|
||||
fprintf(stderr, "On %s write: %s\n",
|
||||
Etcttys, sys_errlist[errno]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
fprintf(stderr, "%s not found in %s\n", device, Etcttys);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* modify appropriate line in _PATH_TTYS to turn on/off the device */
|
||||
settys(enable)
|
||||
int enable;
|
||||
{
|
||||
register char *cp, *cp2;
|
||||
char lbuf[BUFSIZ];
|
||||
int i;
|
||||
char c1, c2;
|
||||
|
||||
(void) fseek(ttysfile, ttyslnbeg, 0);
|
||||
if(fgets(lbuf, BUFSIZ, ttysfile) == NULL) {
|
||||
fprintf(stderr, "On %s read: %s\n",
|
||||
Etcttys, sys_errlist[errno]);
|
||||
exit(1);
|
||||
}
|
||||
/* format is now */
|
||||
/* ttyd0 std.100 dialup on secure # comment */
|
||||
/* except, 2nd item may have embedded spaces inside quotes, Hubert */
|
||||
cp = lbuf;
|
||||
for (i=0;*cp && i<3;i++) {
|
||||
if (*cp == '"') {
|
||||
cp++;
|
||||
while (*cp && *cp != '"')
|
||||
cp++;
|
||||
if (*cp != '\0')
|
||||
cp++;
|
||||
}else {
|
||||
while (*cp && *cp != ' ' && *cp != '\t')
|
||||
cp++;
|
||||
}
|
||||
while (*cp && (*cp == ' ' || *cp == '\t'))
|
||||
cp++;
|
||||
}
|
||||
if (*cp == '\0') {
|
||||
fprintf(stderr,"Badly formatted line in %s:\n%s",
|
||||
_PATH_TTYS, lbuf);
|
||||
exit(1);
|
||||
}
|
||||
c1 = *--cp;
|
||||
*cp++ = '\0';
|
||||
cp2 = cp;
|
||||
while (*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
|
||||
cp++;
|
||||
if (*cp == '\0') {
|
||||
fprintf(stderr,"Badly formatted line in %s:\n%s",
|
||||
_PATH_TTYS, lbuf);
|
||||
exit(1);
|
||||
}
|
||||
c2 = *cp;
|
||||
*cp++ = '\0';
|
||||
while (*cp && (*cp == ' ' || *cp == '\t'))
|
||||
cp++;
|
||||
resettty = strcmp("on", cp2) != 0;
|
||||
fprintf(nttysfile,"%s%c%s%c%s", lbuf, c1, enable ? "on" : "off", c2, cp);
|
||||
if (ferror(nttysfile)) {
|
||||
fprintf(stderr, "On %s fprintf: %s\n",
|
||||
NEtcttys, sys_errlist[errno]);
|
||||
exit(1);
|
||||
}
|
||||
while(fgets(lbuf, sizeof(lbuf) - 1, ttysfile) != NULL) {
|
||||
if (fputs(lbuf, nttysfile) == NULL) {
|
||||
fprintf(stderr, "On %s write: %s\n",
|
||||
NEtcttys, sys_errlist[errno]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (enable^resettty)
|
||||
(void) unlink(NEtcttys);
|
||||
else {
|
||||
struct stat statb;
|
||||
if (stat(Etcttys, &statb) == 0) {
|
||||
fchmod(fileno(nttysfile) ,statb.st_mode);
|
||||
fchown(fileno(nttysfile), statb.st_uid, statb.st_gid);
|
||||
}
|
||||
(void) rename(NEtcttys, Etcttys);
|
||||
}
|
||||
(void) fclose(nttysfile);
|
||||
(void) fclose(ttysfile);
|
||||
return enable^resettty;
|
||||
}
|
||||
|
||||
#else !BSD4_3
|
||||
|
||||
/* identify terminal line in ttys */
|
||||
opnttys(device)
|
||||
char *device;
|
||||
{
|
||||
register FILE *ttysfile;
|
||||
register int ndevice, lnsiz;
|
||||
register char *p;
|
||||
char *index();
|
||||
char linebuf[BUFSIZ];
|
||||
|
||||
ttysfile = fopen(Etcttys, "r");
|
||||
if(ttysfile == NULL) {
|
||||
fprintf(stderr, "Cannot open %s: %s\n", Etcttys,
|
||||
sys_errlist[errno]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ndevice = strlen(device);
|
||||
ttyslnbeg = 0;
|
||||
utmploc = 0;
|
||||
|
||||
while(fgets(linebuf, sizeof(linebuf) - 1, ttysfile) != NULL) {
|
||||
lnsiz = strlen(linebuf);
|
||||
if ((p = index(linebuf, '\n')) != NULL)
|
||||
*p = '\0';
|
||||
if(strncmp(device, &linebuf[2], ndevice) == 0) {
|
||||
(void)fclose(ttysfile);
|
||||
#ifdef sequent
|
||||
/* Why is the sequent off by one? */
|
||||
utmploc += sizeof(utmp);
|
||||
#endif sequent
|
||||
return;
|
||||
}
|
||||
ttyslnbeg += lnsiz;
|
||||
utmploc += sizeof(utmp);
|
||||
}
|
||||
fprintf(stderr, "%s not found in %s\n", device, Etcttys);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* modify appropriate line in _PATH_TTYS to turn on/off the device */
|
||||
settys(enable)
|
||||
int enable;
|
||||
{
|
||||
int ittysfil;
|
||||
char out, in;
|
||||
|
||||
ittysfil = open(Etcttys, 2);
|
||||
if(ittysfil < 0) {
|
||||
fprintf(stderr, "Cannot open %s for output: %s\n",
|
||||
Etcttys, sys_errlist[errno]);
|
||||
exit(1);
|
||||
}
|
||||
(void)lseek(ittysfil, ttyslnbeg, 0);
|
||||
if(read(ittysfil, &in, 1)<0) {
|
||||
fprintf(stderr, "On %s write: %s\n",
|
||||
Etcttys, sys_errlist[errno]);
|
||||
exit(1);
|
||||
}
|
||||
resettty = (in == '1');
|
||||
out = enable ? '1' : '0';
|
||||
(void)lseek(ittysfil, ttyslnbeg, 0);
|
||||
if(write(ittysfil, &out, 1)<0) {
|
||||
fprintf(stderr, "On %s write: %s\n",
|
||||
Etcttys, sys_errlist[errno]);
|
||||
exit(1);
|
||||
}
|
||||
(void)close(ittysfil);
|
||||
return(in==out);
|
||||
}
|
||||
#endif !BSD4_3
|
||||
|
||||
#ifdef sequent
|
||||
setmodem(ttyline, enable)
|
||||
char *ttyline; int enable;
|
||||
{
|
||||
char *sysbuf[BUFSIZ];
|
||||
sprintf(sysbuf,"/etc/ttyconfig /dev/%s -special %s", ttyline,
|
||||
enable ? "-carrier" : "-nocarrier");
|
||||
system(sysbuf);
|
||||
}
|
||||
#endif /* sequent */
|
||||
#ifdef vax
|
||||
/*
|
||||
* Excerpted from (June 8, 1983 W.Sebok)
|
||||
* > ttymodem.c - enable/disable modem control for tty lines.
|
||||
* >
|
||||
* > Knows about DZ11s and DH11/DM11s.
|
||||
* > 23.3.83 - TS
|
||||
* > modified to know about DMF's (hasn't been tested) Nov 8, 1984 - WLS
|
||||
*/
|
||||
|
||||
|
||||
setmodem(ttyline, enable)
|
||||
char *ttyline; int enable;
|
||||
{
|
||||
dev_t dev;
|
||||
int kmem;
|
||||
int unit, line, nlines, addr, tflags;
|
||||
int devtype=0;
|
||||
char cflags; short sflags;
|
||||
#ifdef BSD4_2
|
||||
int flags;
|
||||
#else
|
||||
short flags;
|
||||
#endif
|
||||
struct uba_device *ubinfo;
|
||||
struct stat statb;
|
||||
struct cdevsw cdevsw;
|
||||
|
||||
if(nl[CDEVSW].n_type == 0) {
|
||||
fprintf(stderr, "No namelist.\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if((kmem = open(_PATH_KMEM, 2)) < 0) {
|
||||
fprintf(stderr, "%s open: %s\n", _PATH_KMEM,
|
||||
sys_errlist[errno]);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if(stat(ttyline, &statb) < 0) {
|
||||
fprintf(stderr, "%s stat: %s\n", ttyline, sys_errlist[errno]);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if((statb.st_mode&S_IFMT) != S_IFCHR) {
|
||||
fprintf(stderr, "%s is not a character device.\n",ttyline);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
dev = statb.st_rdev;
|
||||
(void)lseek(kmem,
|
||||
(off_t) &(((struct cdevsw *)NLVALUE(CDEVSW))[major(dev)]),0);
|
||||
(void)read(kmem, (char *) &cdevsw, sizeof cdevsw);
|
||||
|
||||
if((int)(cdevsw.d_open) == NLVALUE(DZOPEN)) {
|
||||
devtype = DZ11;
|
||||
unit = minor(dev) / NDZLINE;
|
||||
line = minor(dev) % NDZLINE;
|
||||
addr = (int) &(((int *)NLVALUE(DZINFO))[unit]);
|
||||
(void)lseek(kmem, (off_t) NLVALUE(NDZ11), 0);
|
||||
} else if((int)(cdevsw.d_open) == NLVALUE(DHOPEN)) {
|
||||
devtype = DH11;
|
||||
unit = minor(dev) / NDHLINE;
|
||||
line = minor(dev) % NDHLINE;
|
||||
addr = (int) &(((int *)NLVALUE(DHINFO))[unit]);
|
||||
(void)lseek(kmem, (off_t) NLVALUE(NDH11), 0);
|
||||
} else if((int)(cdevsw.d_open) == NLVALUE(DMFOPEN)) {
|
||||
devtype = DMF;
|
||||
unit = minor(dev) / NDMFLINE;
|
||||
line = minor(dev) % NDMFLINE;
|
||||
addr = (int) &(((int *)NLVALUE(DMFINFO))[unit]);
|
||||
(void)lseek(kmem, (off_t) NLVALUE(NDMF), 0);
|
||||
} else {
|
||||
fprintf(stderr, "Device %s (%d/%d) unknown.\n", ttyline,
|
||||
major(dev), minor(dev));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
(void)read(kmem, (char *) &nlines, sizeof nlines);
|
||||
if(minor(dev) >= nlines) {
|
||||
fprintf(stderr, "Sub-device %d does not exist (only %d).\n",
|
||||
minor(dev), nlines);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
(void)lseek(kmem, (off_t)addr, 0);
|
||||
(void)read(kmem, (char *) &ubinfo, sizeof ubinfo);
|
||||
(void)lseek(kmem, (off_t) &(ubinfo->ui_flags), 0);
|
||||
(void)read(kmem, (char *) &flags, sizeof flags);
|
||||
|
||||
tflags = 1<<line;
|
||||
resetmodem = ((flags&tflags) == 0);
|
||||
flags = enable ? (flags & ~tflags) : (flags | tflags);
|
||||
(void)lseek(kmem, (off_t) &(ubinfo->ui_flags), 0);
|
||||
(void)write(kmem, (char *) &flags, sizeof flags);
|
||||
switch(devtype) {
|
||||
case DZ11:
|
||||
if((addr = NLVALUE(DZSCAR)) == 0) {
|
||||
fprintf(stderr, "No dzsoftCAR.\n");
|
||||
return(-1);
|
||||
}
|
||||
cflags = flags;
|
||||
(void)lseek(kmem, (off_t) &(((char *)addr)[unit]), 0);
|
||||
(void)write(kmem, (char *) &cflags, sizeof cflags);
|
||||
break;
|
||||
case DH11:
|
||||
if((addr = NLVALUE(DHSCAR)) == 0) {
|
||||
fprintf(stderr, "No dhsoftCAR.\n");
|
||||
return(-1);
|
||||
}
|
||||
sflags = flags;
|
||||
(void)lseek(kmem, (off_t) &(((short *)addr)[unit]), 0);
|
||||
(void)write(kmem, (char *) &sflags, sizeof sflags);
|
||||
break;
|
||||
case DMF:
|
||||
if((addr = NLVALUE(DMFSCAR)) == 0) {
|
||||
fprintf(stderr, "No dmfsoftCAR.\n");
|
||||
return(-1);
|
||||
}
|
||||
cflags = flags;
|
||||
(void)lseek(kmem, (off_t) &(((char *)addr)[unit]), 0);
|
||||
(void)write(kmem, (char *) &cflags, sizeof cflags);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown device type\n");
|
||||
return(-1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
#endif /* vax */
|
||||
|
||||
prefix(s1, s2)
|
||||
register char *s1, *s2;
|
||||
{
|
||||
register char c;
|
||||
|
||||
while ((c = *s1++) == *s2++)
|
||||
if (c == '\0')
|
||||
return (1);
|
||||
return (c == '\0');
|
||||
}
|
||||
#else /* !DIALINOUT */
|
||||
main()
|
||||
{
|
||||
fprintf(stderr,"acucntrl is not supported on this system\n");
|
||||
}
|
||||
#endif /* !DIALINOUT */
|
111
usr.bin/uucp/uupoll/uupoll.8
Normal file
111
usr.bin/uucp/uupoll/uupoll.8
Normal file
@ -0,0 +1,111 @@
|
||||
.\" Copyright (c) 1986, 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.
|
||||
.\"
|
||||
.\" @(#)uupoll.8 8.1 (Berkeley) 6/6/93
|
||||
.\"
|
||||
.Dd June 6, 1993
|
||||
.Dt UUPOLL 8
|
||||
.Os BSD 4.3
|
||||
.Sh NAME
|
||||
.Nm uupoll
|
||||
.Nd poll a remote
|
||||
.Tn UUCP
|
||||
site
|
||||
.Sh SYNOPSIS
|
||||
.Nm uupoll
|
||||
.Op Fl g Ns Ar grade
|
||||
.Op Fl n
|
||||
.Ar system
|
||||
.Sh DESCRIPTION
|
||||
.Nm Uupoll
|
||||
is used to force a poll of a remote system. It queues a null job for the
|
||||
remote system and then invokes
|
||||
.Xr uucico 8 .
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width Fl
|
||||
.It Fl g Ns Ar grade
|
||||
Only send jobs of grade
|
||||
.Ar grade
|
||||
or higher on this call.
|
||||
.It Fl n
|
||||
Queue the null job, but do not invoke
|
||||
.Xr uucico .
|
||||
.El
|
||||
.Pp
|
||||
.Nm Uupoll
|
||||
is usually run by
|
||||
.Xr cron 5
|
||||
or by a user who wants to hurry a job along. A typical entry in
|
||||
.Em crontab
|
||||
could be:
|
||||
.Bd -literal
|
||||
0 0,8,16 * * * daemon /usr/bin/uupoll ihnp4
|
||||
0 4,12,20 * * * daemon /usr/bin/uupoll ucbvax
|
||||
.Ed
|
||||
.Pp
|
||||
This will poll
|
||||
.Em ihnp4
|
||||
at midnight, 0800, and 1600, and
|
||||
.Em ucbvax
|
||||
at 0400, noon, and 2000.
|
||||
.Pp
|
||||
If the local machine is already running
|
||||
.Xr uucico
|
||||
every
|
||||
hour and has a limited number of outgoing modems, a more elegant approach
|
||||
might be:
|
||||
.Bd -literal
|
||||
0 0,8,16 * * * daemon /usr/bin/uupoll -n ihnp4
|
||||
0 4,12,20 * * * daemon /usr/bin/uupoll -n ucbvax
|
||||
5 * * * * daemon /usr/lib/uucp/uucico -r1
|
||||
.Ed
|
||||
.Pp
|
||||
This will queue null jobs for the remote sites at the top of hour; they
|
||||
will be processed by
|
||||
.Xr uucico
|
||||
when it runs five minutes later.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /usr/lib/uucp/UUCP -compact
|
||||
.It Pa /usr/lib/uucp/UUCP
|
||||
internal files/utilities
|
||||
.It Pa /var/spool/uucp/
|
||||
Spool directory
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr uucp 1 ,
|
||||
.Xr uux 1 ,
|
||||
.Xr uucico 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.3 .
|
129
usr.bin/uucp/uupoll/uupoll.c
Normal file
129
usr.bin/uucp/uupoll/uupoll.c
Normal file
@ -0,0 +1,129 @@
|
||||
/*-
|
||||
* Copyright (c) 1986, 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 copyright[] =
|
||||
"@(#) Copyright (c) 1986, 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)uupoll.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Poll named system(s).
|
||||
*
|
||||
* The poll occurs even if recent attempts have failed,
|
||||
* but not if L.sys prohibits the call (e.g. wrong time of day).
|
||||
*
|
||||
* Original Author: Tom Truscott (rti!trt)
|
||||
*/
|
||||
|
||||
#include "uucp.h"
|
||||
|
||||
int TransferSucceeded = 1;
|
||||
struct timeb Now;
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char wrkpre[MAXFULLNAME];
|
||||
char file[MAXFULLNAME];
|
||||
char grade = 'A';
|
||||
int nocall = 0;
|
||||
int c;
|
||||
char *sysname;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "usage: uupoll [-gX] [-n] system ...\n");
|
||||
cleanup(1);
|
||||
}
|
||||
|
||||
if (chdir(Spool) < 0) {
|
||||
syslog(LOG_WARNING, "chdir(%s) failed: %m", Spool);
|
||||
cleanup(1);
|
||||
}
|
||||
strcpy(Progname, "uupoll");
|
||||
uucpname(Myname);
|
||||
|
||||
while ((c = getopt(argc, argv, "g:n")) != EOF)
|
||||
switch(c) {
|
||||
case 'g':
|
||||
grade = *optarg;
|
||||
break;
|
||||
case 'n':
|
||||
nocall++;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
fprintf(stderr, "unknown option %s\n",
|
||||
argv[optind-1]);
|
||||
}
|
||||
|
||||
while(optind < argc) {
|
||||
sysname = argv[optind++];
|
||||
if (strcmp(sysname, Myname) == SAME) {
|
||||
fprintf(stderr, "This *is* %s!\n", Myname);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (versys(&sysname)) {
|
||||
fprintf(stderr, "%s: unknown system.\n", sysname);
|
||||
continue;
|
||||
}
|
||||
/* Remove any STST file that might stop the poll */
|
||||
sprintf(wrkpre, "%s/LCK..%.*s", LOCKDIR, MAXBASENAME, sysname);
|
||||
if (access(wrkpre, 0) < 0)
|
||||
rmstat(sysname);
|
||||
sprintf(wrkpre, "%c.%.*s", CMDPRE, SYSNSIZE, sysname);
|
||||
if (!iswrk(file, "chk", Spool, wrkpre)) {
|
||||
sprintf(file, "%s/%c.%.*s%cPOLL", subdir(Spool, CMDPRE),
|
||||
CMDPRE, SYSNSIZE, sysname, grade);
|
||||
close(creat(file, 0666));
|
||||
}
|
||||
/* Attempt the call */
|
||||
if (!nocall)
|
||||
xuucico(sysname);
|
||||
}
|
||||
cleanup(0);
|
||||
}
|
||||
|
||||
cleanup(code)
|
||||
int code;
|
||||
{
|
||||
exit(code);
|
||||
}
|
9
usr.bin/uucp/uuq/Makefile
Normal file
9
usr.bin/uucp/uuq/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= uuq
|
||||
CFLAGS+=-I${.CURDIR}/../includes
|
||||
BINMODE=6555
|
||||
DPADD= ${LIBCOMPAT}
|
||||
LDADD= ${LIBUU} -lcompat
|
||||
|
||||
.include <bsd.prog.mk>
|
126
usr.bin/uucp/uuq/uuq.1
Normal file
126
usr.bin/uucp/uuq/uuq.1
Normal file
@ -0,0 +1,126 @@
|
||||
.\" Copyright (c) 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.
|
||||
.\"
|
||||
.\" @(#)uuq.1 8.1 (Berkeley) 6/6/93
|
||||
.\"
|
||||
.Dd June 6, 1993
|
||||
.Dt UUQ 1
|
||||
.Os BSD 4.3
|
||||
.Sh NAME
|
||||
.Nm uuq
|
||||
.Nd examine or manipulate the uucp queue
|
||||
.Sh SYNOPSIS
|
||||
.Nm uuq
|
||||
.Op Fl l
|
||||
.Op Fl h
|
||||
.Op Fl s Ns Ar system
|
||||
.Op Fl u Ns Ar user
|
||||
.Op Fl d Ns Ar jobno
|
||||
.Op Fl r Ns Ar sdir
|
||||
.Op Fl b Ns Ar baud
|
||||
.Sh DESCRIPTION
|
||||
.Nm Uuq
|
||||
is used to examine (and possibly delete) entries in the uucp queue.
|
||||
.Pp
|
||||
When listing jobs,
|
||||
.Nm uuq
|
||||
uses a format reminiscent of
|
||||
.Xr ls .
|
||||
For the long format,
|
||||
information for each job listed includes
|
||||
job number, number of files to transfer, user who
|
||||
spooled the job, number of bytes to send, type of command requested
|
||||
(S for sending files, R for receiving files, X for remote uucp),
|
||||
and file or command desired.
|
||||
.Pp
|
||||
Several options are available:
|
||||
.Bl -tag -width Ar
|
||||
.It Fl h
|
||||
Print only the summary lines for each system. Summary lines give system
|
||||
name, number of jobs for the system, and total number of bytes to send.
|
||||
.It Fl l
|
||||
Specifies a long format listing. The default is to list only the
|
||||
job numbers sorted across the page.
|
||||
.It Fl s Ns Ar system
|
||||
Limit output to jobs for systems whose system names begin with
|
||||
.Ar system .
|
||||
.It Fl u Ns Ar user
|
||||
Limit output to jobs for users whose login names begin with
|
||||
.Ar user .
|
||||
.It Fl d Ns Ar jobno
|
||||
Delete job number
|
||||
.Ar jobno
|
||||
(as obtained from a previous
|
||||
.Nm uuq
|
||||
command)
|
||||
from the uucp queue.
|
||||
Only the
|
||||
.Tn UUCP
|
||||
Administrator is permitted to delete jobs.
|
||||
.It Fl r Ns Ar sdir
|
||||
Look for files in the spooling directory
|
||||
.Ar sdir
|
||||
instead of the default
|
||||
directory.
|
||||
.It Fl b Ns Ar baud
|
||||
Use
|
||||
.Ar baud
|
||||
to compute the transfer time instead of the default
|
||||
1200 baud.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /usr/spool/uucp/Dhostname./D.x -compact
|
||||
.It Pa /usr/spool/uucp/
|
||||
Default spool directory
|
||||
.It Pa /usr/spool/uucp/C./C.*
|
||||
Control files
|
||||
.It Pa /usr/spool/uucp/D Ns Em hostname ./D.*
|
||||
Outgoing data files
|
||||
.It Pa /usr/spool/uucp/X./X.*
|
||||
Outgoing execution files
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr uucp 1 ,
|
||||
.Xr uux 1 ,
|
||||
.Xr uulog 1 ,
|
||||
.Xr uusnap 8
|
||||
.Sh BUGS
|
||||
No information is available on work requested by the remote machine.
|
||||
.Pp
|
||||
The user who requests a remote uucp command is unknown.
|
||||
.Pp
|
||||
.Dq Li uq \-l
|
||||
can be horrendously slow.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.3 .
|
435
usr.bin/uucp/uuq/uuq.c
Normal file
435
usr.bin/uucp/uuq/uuq.c
Normal file
@ -0,0 +1,435 @@
|
||||
/*-
|
||||
* 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 copyright[] =
|
||||
"@(#) Copyright (c) 1988, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)uuq.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* uuq - looks at uucp queues
|
||||
*
|
||||
* Lou Salkind
|
||||
* New York University
|
||||
*
|
||||
*/
|
||||
|
||||
#include "uucp.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef NDIR
|
||||
#include "libndir/ndir.h"
|
||||
#else !NDIR
|
||||
#include <sys/dir.h>
|
||||
#endif !NDIR
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define NOSYS (struct sys *)0
|
||||
|
||||
#define W_TYPE wrkvec[0]
|
||||
#define W_FILE1 wrkvec[1]
|
||||
#define W_FILE2 wrkvec[2]
|
||||
#define W_USER wrkvec[3]
|
||||
#define W_OPTNS wrkvec[4]
|
||||
#define W_DFILE wrkvec[5]
|
||||
#define W_MODE wrkvec[6]
|
||||
#define WSUFSIZE 5 /* work file name suffix size */
|
||||
|
||||
struct sys {
|
||||
char s_name[8];
|
||||
int s_njobs;
|
||||
off_t s_bytes;
|
||||
struct job *s_jobp;
|
||||
struct sys *s_sysp;
|
||||
};
|
||||
|
||||
struct job {
|
||||
int j_files;
|
||||
int j_flags;
|
||||
char j_jobno[WSUFSIZE];
|
||||
char j_user[22];
|
||||
char j_fname[128];
|
||||
char j_grade;
|
||||
off_t j_bytes;
|
||||
time_t j_date;
|
||||
struct job *j_jobp;
|
||||
};
|
||||
|
||||
struct sys *syshead;
|
||||
struct sys *getsys();
|
||||
int jcompare();
|
||||
char *sysname;
|
||||
char *user;
|
||||
char *rmjob;
|
||||
int hflag;
|
||||
int lflag;
|
||||
|
||||
char *malloc(), *calloc();
|
||||
double atof();
|
||||
float baudrate = 2400.;
|
||||
char Username[BUFSIZ];
|
||||
char Filename[BUFSIZ];
|
||||
int Maxulen = 0;
|
||||
struct timeb Now;
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
register int i;
|
||||
register struct sys *sp;
|
||||
register struct job *jp;
|
||||
struct job **sortjob;
|
||||
int nsys;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
strcpy(Progname, "uuq");
|
||||
uucpname(Myname);
|
||||
|
||||
while ((i = getopt(argc, argv, "r:S:s:u:d:b:hl")) != EOF)
|
||||
switch (i) {
|
||||
case 'r':
|
||||
case 'S':
|
||||
Spool = optarg;
|
||||
break;
|
||||
case 's':
|
||||
sysname = optarg;
|
||||
if (strlen(sysname) > SYSNSIZE)
|
||||
sysname[SYSNSIZE] = '\0';
|
||||
break;
|
||||
case 'u':
|
||||
user = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
rmjob = optarg;
|
||||
break;
|
||||
case 'b':
|
||||
baudrate = atof(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
hflag++;
|
||||
break;
|
||||
case 'l':
|
||||
lflag++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"usage: uuq [-l] [-h] [-ssystem] [-uuser] [-djobno] [-rspool] [-bbaudrate]\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
subchdir(Spool);
|
||||
baudrate *= 0.7; /* reduce speed because of protocol overhead */
|
||||
baudrate *= 7.5; /* convert to chars/minute (60/8) */
|
||||
gather();
|
||||
nsys = 0;
|
||||
for (sp = syshead; sp; sp = sp->s_sysp) {
|
||||
if (sp->s_njobs == 0)
|
||||
continue;
|
||||
if (!hflag && nsys++ > 0)
|
||||
putchar('\n');
|
||||
printf("%s: %d %s", sp->s_name,
|
||||
sp->s_njobs, sp->s_njobs > 1 ? "jobs" : "job");
|
||||
if (lflag) {
|
||||
float minutes;
|
||||
int hours;
|
||||
/* The 80 * njobs is because of the uucp handshaking */
|
||||
minutes = (float)(sp->s_bytes + 80 * sp->s_njobs)/baudrate;
|
||||
hours = minutes/60;
|
||||
printf(", %ld bytes, ", sp->s_bytes);
|
||||
if (minutes > 60){
|
||||
printf("%d hour%s, ",hours,
|
||||
hours > 1 ? "s": "");
|
||||
minutes -= 60 * hours;
|
||||
}
|
||||
printf("%3.1f minutes (@ effective baudrate of %d)",
|
||||
minutes,(int)(baudrate/6));
|
||||
}
|
||||
putchar('\n');
|
||||
if (hflag)
|
||||
continue;
|
||||
/* sort them babies! */
|
||||
sortjob = (struct job **)calloc(sp->s_njobs, sizeof (struct job *));
|
||||
for (i=0, jp=sp->s_jobp; i < sp->s_njobs; i++, jp=jp->j_jobp)
|
||||
sortjob[i] = jp;
|
||||
qsort(sortjob, sp->s_njobs, sizeof (struct job *), jcompare);
|
||||
for (i = 0; i < sp->s_njobs; i++) {
|
||||
jp = sortjob[i];
|
||||
if (lflag) {
|
||||
printf("%s %2d %-*s%7ld%5.1f %-12.12s %c %.*s\n",
|
||||
jp->j_jobno, jp->j_files, Maxulen, jp->j_user, jp->j_bytes, jp->j_bytes/baudrate,
|
||||
ctime(&jp->j_date) + 4, jp->j_flags, sizeof (jp->j_fname), jp->j_fname
|
||||
);
|
||||
} else {
|
||||
printf("%s", jp->j_jobno);
|
||||
putchar((i+1)%10 ? '\t' : '\n');
|
||||
}
|
||||
/* There's no need to keep the force poll if jobs > 1*/
|
||||
if (sp->s_njobs > 1 && strcmp("POLL", jp->j_jobno)==0) {
|
||||
char pbuf[BUFSIZ];
|
||||
sprintf(pbuf,"%s/%c.%s%cPOLL",
|
||||
subdir(Spool, CMDPRE), CMDPRE,
|
||||
sp->s_name, jp->j_grade);
|
||||
(void) unlink(pbuf);
|
||||
}
|
||||
}
|
||||
if (!lflag && (sp->s_njobs%10))
|
||||
putchar('\n');
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
jcompare(j1, j2)
|
||||
struct job **j1, **j2;
|
||||
{
|
||||
int delta;
|
||||
|
||||
delta = (*j1)->j_grade - (*j2)->j_grade;
|
||||
if (delta)
|
||||
return delta;
|
||||
return(strcmp((*j1)->j_jobno,(*j2)->j_jobno));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get all the command file names
|
||||
*/
|
||||
gather()
|
||||
{
|
||||
struct direct *d;
|
||||
DIR *df;
|
||||
|
||||
/*
|
||||
* Find all the spool files in the spooling directory
|
||||
*/
|
||||
if ((df = opendir(subdir(Spool, CMDPRE))) == NULL) {
|
||||
fprintf(stderr, "can't examine spooling area\n");
|
||||
exit(1);
|
||||
}
|
||||
for (;;) {
|
||||
if ((d = readdir(df)) == NULL)
|
||||
break;
|
||||
if (d->d_namlen <= 2 || d->d_name[0] != CMDPRE ||
|
||||
d->d_name[1] != '.')
|
||||
continue;
|
||||
if (analjob(d->d_name) < 0) {
|
||||
fprintf(stderr, "out of memory\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(df);
|
||||
}
|
||||
|
||||
/*
|
||||
* analjob does the grunge work of verifying jobs
|
||||
*/
|
||||
#include <pwd.h>
|
||||
analjob(filename)
|
||||
char *filename;
|
||||
{
|
||||
struct job *jp;
|
||||
struct sys *sp;
|
||||
char sbuf[MAXNAMLEN+1], str[256], nbuf[256];
|
||||
char *jptr, *wrkvec[20];
|
||||
char grade;
|
||||
FILE *fp, *df;
|
||||
struct stat statb;
|
||||
int files, gotname, i;
|
||||
off_t bytes;
|
||||
|
||||
strncpy(sbuf, filename, MAXNAMLEN);
|
||||
sbuf[MAXNAMLEN] = '\0';
|
||||
jptr = sbuf + strlen(sbuf) - WSUFSIZE;
|
||||
grade = *jptr;
|
||||
*jptr++ = 0;
|
||||
/*
|
||||
* sbuf+2 now points to sysname name (null terminated)
|
||||
* jptr now points to job number (null terminated)
|
||||
*/
|
||||
if (rmjob) {
|
||||
if (strcmp(rmjob, jptr))
|
||||
return(0);
|
||||
} else {
|
||||
if ((sp = getsys(sbuf+2)) == NOSYS)
|
||||
return(0);
|
||||
if (!lflag) {
|
||||
/* SHOULD USE A SMALLER STRUCTURE HERE */
|
||||
jp = (struct job *)malloc(sizeof(struct job));
|
||||
if (jp == (struct job *)0)
|
||||
return(-1);
|
||||
strcpy(jp->j_jobno, jptr);
|
||||
jp->j_jobp = sp->s_jobp;
|
||||
jp->j_grade = grade;
|
||||
sp->s_jobp = jp;
|
||||
sp->s_njobs++;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
if ((fp = fopen(subfile(filename), "r")) == NULL) {
|
||||
perror(subfile(filename));
|
||||
return(0);
|
||||
}
|
||||
files = 0;
|
||||
bytes = 0;
|
||||
gotname = 0;
|
||||
while (fgets(str, sizeof str, fp)) {
|
||||
if (getargs(str, wrkvec, 20) <= 0)
|
||||
continue;
|
||||
if (rmjob) {
|
||||
int myuid;
|
||||
struct passwd *pw;
|
||||
/*
|
||||
* Make sure person who is removing data files is
|
||||
* the person who created it or root.
|
||||
*/
|
||||
myuid = getuid();
|
||||
pw = getpwnam(W_USER);
|
||||
if (myuid && (pw == NULL || myuid != pw->pw_uid)) {
|
||||
fprintf(stderr, "Permission denied.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (W_TYPE[0] == 'S' && !index(W_OPTNS, 'c')) {
|
||||
unlink(subfile(W_DFILE));
|
||||
fprintf(stderr, "Removing data file %s\n", W_DFILE);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (user && (W_TYPE[0] == 'X' || !prefix(user, W_USER))) {
|
||||
fclose(fp);
|
||||
return(0);
|
||||
}
|
||||
files++;
|
||||
if (W_TYPE[0] == 'S') {
|
||||
if (strcmp(W_DFILE, "D.0") &&
|
||||
stat(subfile(W_DFILE), &statb) >= 0)
|
||||
bytes += statb.st_size;
|
||||
else if (stat(subfile(W_FILE1), &statb) >= 0)
|
||||
bytes += statb.st_size;
|
||||
}
|
||||
/* amusing heuristic */
|
||||
#define isXfile(s) (s[0]=='D' && s[strlen(s)-WSUFSIZE]=='X')
|
||||
if (gotname == 0 && isXfile(W_FILE1)) {
|
||||
if ((df = fopen(subfile(W_FILE1), "r")) == NULL)
|
||||
continue;
|
||||
while (fgets(nbuf, sizeof nbuf, df)) {
|
||||
nbuf[strlen(nbuf) - 1] = '\0';
|
||||
if (nbuf[0] == 'C' && nbuf[1] == ' ') {
|
||||
strcpy(Filename, nbuf+2);
|
||||
gotname++;
|
||||
} else if (nbuf[0] == 'R' && nbuf[1] == ' ') {
|
||||
register char *p, *q, *r;
|
||||
r = q = p = nbuf+2;
|
||||
do {
|
||||
if (*p == '!' || *p == '@'){
|
||||
r = q;
|
||||
q = p+1;
|
||||
}
|
||||
} while (*p++);
|
||||
|
||||
strcpy(Username, r);
|
||||
W_USER = Username;
|
||||
}
|
||||
}
|
||||
fclose(df);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
if (rmjob) {
|
||||
unlink(subfile(filename));
|
||||
fprintf(stderr, "Removing command file %s\n", filename);
|
||||
exit(0);
|
||||
}
|
||||
if (files == 0) {
|
||||
static char *wtype = "X";
|
||||
static char *wfile = "forced poll";
|
||||
if (strcmp("POLL", &filename[strlen(filename)-4])) {
|
||||
fprintf(stderr, "%.14s: empty command file\n", filename);
|
||||
return(0);
|
||||
}
|
||||
W_TYPE = wtype;
|
||||
W_FILE1 = wfile;
|
||||
}
|
||||
jp = (struct job *)malloc(sizeof(struct job));
|
||||
if (jp == (struct job *)0)
|
||||
return(-1);
|
||||
strcpy(jp->j_jobno, jptr);
|
||||
jp->j_files = files;
|
||||
jp->j_bytes = bytes;
|
||||
jp->j_grade = grade;
|
||||
jp->j_flags = W_TYPE[0];
|
||||
strncpy(jp->j_user, W_TYPE[0]=='X' ? "---" : W_USER, 20 );
|
||||
jp->j_user[20] = '\0';
|
||||
i = strlen(jp->j_user);
|
||||
if (i > Maxulen)
|
||||
Maxulen = i;
|
||||
/* SHOULD ADD ALL INFORMATION IN THE WHILE LOOP */
|
||||
if (gotname)
|
||||
strncpy(jp->j_fname, Filename, sizeof jp->j_fname);
|
||||
else
|
||||
strncpy(jp->j_fname, W_FILE1, sizeof jp->j_fname);
|
||||
stat(subfile(filename), &statb);
|
||||
jp->j_date = statb.st_mtime;
|
||||
jp->j_jobp = sp->s_jobp;
|
||||
sp->s_jobp = jp;
|
||||
sp->s_njobs++;
|
||||
sp->s_bytes += jp->j_bytes;
|
||||
return(1);
|
||||
}
|
||||
|
||||
struct sys *
|
||||
getsys(s)
|
||||
register char *s;
|
||||
{
|
||||
register struct sys *sp;
|
||||
|
||||
for (sp = syshead; sp; sp = sp->s_sysp)
|
||||
if (strcmp(s, sp->s_name) == 0)
|
||||
return(sp);
|
||||
if (sysname && !prefix(sysname, s))
|
||||
return(NOSYS);
|
||||
sp = (struct sys *)malloc(sizeof(struct sys));
|
||||
if (sp == NOSYS)
|
||||
return(NOSYS);
|
||||
strcpy(sp->s_name, s);
|
||||
sp->s_njobs = 0;
|
||||
sp->s_jobp = (struct job *)0;
|
||||
sp->s_sysp = syshead;
|
||||
sp->s_bytes = 0;
|
||||
syshead = sp;
|
||||
return(sp);
|
||||
}
|
6
usr.bin/uucp/uusend/Makefile
Normal file
6
usr.bin/uucp/uusend/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= uusend
|
||||
LINKS= ${BINDIR}/uusend ${BINDIR}/ruusend
|
||||
|
||||
.include <bsd.prog.mk>
|
96
usr.bin/uucp/uusend/uusend.1
Normal file
96
usr.bin/uucp/uusend/uusend.1
Normal file
@ -0,0 +1,96 @@
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)uusend.1 8.3 (Berkeley) 2/16/94
|
||||
.\"
|
||||
.Dd February 16, 1994
|
||||
.Dt UUSEND 1
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm uusend
|
||||
.Nd send a file to a remote host
|
||||
.Sh SYNOPSIS
|
||||
.Nm uusend
|
||||
.Op Fl m Ar mode
|
||||
.Ar sourcefile
|
||||
.Ar sys1!sys2!..!remotefile
|
||||
.Sh DESCRIPTION
|
||||
.Nm Uusend
|
||||
sends a file to a given location on a remote system.
|
||||
The system need not be directly connected to the local
|
||||
system, but a chain of
|
||||
.Xr uucp 1
|
||||
links must to connect the two systems.
|
||||
.Pp
|
||||
Available option:
|
||||
.Bl -tag -width Fl
|
||||
.It Fl m Ar mode
|
||||
The mode of the file on the remote
|
||||
end is taken from the octal number given.
|
||||
Otherwise, the mode of the input file will be used.
|
||||
.El
|
||||
.Pp
|
||||
The sourcefile
|
||||
can be
|
||||
.Ql Fl ,
|
||||
meaning to use the standard input.
|
||||
Both of these options are primarily intended for internal use of
|
||||
.Nm uusend .
|
||||
.Pp
|
||||
The remotefile can include the
|
||||
.Em ~userid
|
||||
syntax.
|
||||
.Sh DIAGNOSTICS
|
||||
If anything goes wrong any further away than the first system down
|
||||
the line, you will never hear about it.
|
||||
.Sh SEE ALSO
|
||||
.Xr uux 1 ,
|
||||
.Xr uucp 1 ,
|
||||
.Xr uuencode 1
|
||||
.Sh BUGS
|
||||
This command should not exist, since
|
||||
.Xr uucp
|
||||
should handle it.
|
||||
.Pp
|
||||
All systems along the line must have the
|
||||
.Nm uusend
|
||||
command available and allow remote execution of it.
|
||||
.Pp
|
||||
Some uucp systems have a bug where binary files cannot be the
|
||||
input to a
|
||||
.Xr uux 1
|
||||
command. If this bug exists in any system along the line,
|
||||
the file will show up severely munged.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.0 .
|
403
usr.bin/uucp/uusend/uusend.c
Normal file
403
usr.bin/uucp/uusend/uusend.c
Normal file
@ -0,0 +1,403 @@
|
||||
/*-
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1980, 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)uusend.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* uusend: primitive operation to allow uucp like copy of binary files
|
||||
* but handle indirection over systems.
|
||||
*
|
||||
* usage: uusend [-r] [-m ooo] localfile sysname1!sysname2!...!destfile
|
||||
* uusend [-r] [-m ooo] - sysname1!sysname2!...!destfile
|
||||
*
|
||||
* Author: Mark Horton, May 1980.
|
||||
*
|
||||
* "-r" switch added. Has same effect as "-r" in uux. 11/82 CCW
|
||||
*
|
||||
* Error recovery (a la uucp) added & ifdefs for ruusend (as in rmail).
|
||||
* Checks for illegal access to /usr/lib/uucp.
|
||||
* February 1983 Christopher Woodbury
|
||||
* Fixed mode set[ug]id loophole. 4/8/83 CCW
|
||||
*
|
||||
* Add '-f' to make uusend syntax more similar to UUCP. "destname"
|
||||
* can now be a directory. June 1983 CCW
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <pwd.h>
|
||||
|
||||
/*
|
||||
* define RECOVER to permit requests like 'uusend file sys1!sys2!~uucp'
|
||||
* (abbreviation for 'uusend file sys1!sys2!~uucp/file').
|
||||
* define DEBUG to keep log of uusend uusage.
|
||||
* define RUUSEND if neighboring sites permit 'ruusend',
|
||||
* which they certainly should to avoid security holes
|
||||
*/
|
||||
#define RECOVER
|
||||
/*#define DEBUG "/usr/spool/uucp/uusend.log"/**/
|
||||
|
||||
FILE *in, *out;
|
||||
FILE *dout;
|
||||
|
||||
extern FILE *popen();
|
||||
extern char *index(), *strcpy(), *strcat(), *ctime();
|
||||
|
||||
#ifdef RUUSEND
|
||||
int rsend;
|
||||
#endif RUUSEND
|
||||
int mode = -1; /* mode to chmod new file to */
|
||||
char *nextsys; /* next system in the chain */
|
||||
char dnbuf[200]; /* buffer for result of ~user/file */
|
||||
char cmdbuf[256]; /* buffer to build uux command in */
|
||||
char *rflg = ""; /* default value of rflg ccw -- 1 Nov '82 */
|
||||
|
||||
struct passwd *user; /* entry in /etc/passwd for ~user */
|
||||
struct passwd *getpwnam();
|
||||
struct stat stbuf;
|
||||
|
||||
char *excl; /* location of first ! in destname */
|
||||
char *sl; /* location of first / in destname */
|
||||
char *sourcename; /* argv[1] */
|
||||
char *destname; /* argv[2] */
|
||||
char *UULIB = "/usr/lib/uucp"; /* UUCP lib directory */
|
||||
|
||||
#ifdef RECOVER
|
||||
char *UUPUB = "/usr/spool/uucppublic/"; /* public UUCP directory */
|
||||
char *filename; /* file name from end of destname */
|
||||
char *getfname(); /* routine to get filename from destname */
|
||||
int fflg;
|
||||
char f[100]; /* name of default output file */
|
||||
#else !RECOVER
|
||||
char *f = ""; /* so we waste a little space */
|
||||
#endif !RECOVER
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
register int c;
|
||||
long count;
|
||||
extern char **environ;
|
||||
|
||||
#ifdef DEBUG
|
||||
long t;
|
||||
umask(022);
|
||||
dout = fopen(DEBUG, "a");
|
||||
if (dout == NULL) {
|
||||
printf("Cannot append to %s\n", DEBUG);
|
||||
exit(1);
|
||||
}
|
||||
freopen(DEBUG, "a", stdout);
|
||||
fprintf(dout, "\nuusend run: ");
|
||||
for (c=0; c<argc; c++)
|
||||
fprintf(dout, "%s ", argv[c]);
|
||||
time(&t);
|
||||
fprintf(dout, "%s", ctime(&t));
|
||||
#endif DEBUG
|
||||
|
||||
#ifdef RUUSEND
|
||||
if(argv[0][0] == 'r')
|
||||
rsend++;
|
||||
#endif RUUSEND
|
||||
while (argc > 1 && argv[1][0] == '-' && argv[1][1]) {
|
||||
switch(argv[1][1]) {
|
||||
case 'm':
|
||||
sscanf(argv[2], "%o", &mode);
|
||||
mode &= 0777; /* fix set[ug]id loophole */
|
||||
argc--; argv++;
|
||||
break;
|
||||
case 'r': /* -r flag for uux */
|
||||
rflg = "-r ";
|
||||
break;
|
||||
#ifdef RECOVER
|
||||
case 'f':
|
||||
fflg++;
|
||||
strcpy(f, argv[1]);
|
||||
break;
|
||||
#endif RECOVER
|
||||
default:
|
||||
fprintf(stderr, "Bad flag: %s\n", argv[1]);
|
||||
break;
|
||||
}
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: uusend [-m ooo] [-r] -/file sys!sys!..!rfile\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sourcename = argv[1];
|
||||
destname = argv[2];
|
||||
|
||||
if (sourcename[0] == '-')
|
||||
in = stdin;
|
||||
else {
|
||||
#ifdef RUUSEND
|
||||
if (rsend) {
|
||||
fprintf(stderr, "illegal input\n");
|
||||
exit(2);
|
||||
}
|
||||
#endif RUUSEND
|
||||
in = fopen(sourcename, "r");
|
||||
if (in == NULL) {
|
||||
perror(argv[1]);
|
||||
exit(2);
|
||||
}
|
||||
if (!fflg || f[2] == '\0') {
|
||||
strcpy(f, "-f");
|
||||
strcat(f, getfname(sourcename));
|
||||
fflg++;
|
||||
}
|
||||
}
|
||||
|
||||
excl = index(destname, '!');
|
||||
if (excl) {
|
||||
/*
|
||||
* destname is on a remote system.
|
||||
*/
|
||||
nextsys = destname;
|
||||
*excl++ = 0;
|
||||
destname = excl;
|
||||
if (mode < 0) {
|
||||
fstat(fileno(in), &stbuf);
|
||||
mode = stbuf.st_mode & 0777;
|
||||
}
|
||||
#ifdef RUUSEND
|
||||
sprintf(cmdbuf,"uux -gn -z %s- \"%s!ruusend %s -m %o - (%s)\"",
|
||||
#else !RUUSEND
|
||||
sprintf(cmdbuf, "uux -gn -z %s- \"%s!uusend %s -m %o - (%s)\"",
|
||||
#endif !RUUSEND
|
||||
rflg, nextsys, f, mode, destname);
|
||||
#ifdef DEBUG
|
||||
fprintf(dout, "remote: nextsys='%s', destname='%s', cmd='%s'\n", nextsys, destname, cmdbuf);
|
||||
#endif DEBUG
|
||||
out = popen(cmdbuf, "w");
|
||||
} else {
|
||||
/*
|
||||
* destname is local.
|
||||
*/
|
||||
if (destname[0] == '~') {
|
||||
#ifdef DEBUG
|
||||
fprintf(dout, "before ~: '%s'\n", destname);
|
||||
fflush(dout);
|
||||
#endif DEBUG
|
||||
sl = index(destname, '/');
|
||||
#ifdef RECOVER
|
||||
if (sl == NULL && !fflg) {
|
||||
fprintf(stderr, "Illegal ~user\n");
|
||||
exit(3);
|
||||
}
|
||||
for (sl = destname; *sl != '\0'; sl++)
|
||||
; /* boy, is this a hack! */
|
||||
#else !RECOVER
|
||||
if (sl == NULL) {
|
||||
fprintf(stderr, "Illegal ~user\n");
|
||||
exit(3);
|
||||
}
|
||||
*sl++ = 0;
|
||||
#endif !RECOVER
|
||||
user = getpwnam(destname+1);
|
||||
if (user == NULL) {
|
||||
fprintf(stderr, "No such user as %s\n",
|
||||
destname);
|
||||
#ifdef RECOVER
|
||||
if ((filename =getfname(sl)) == NULL &&
|
||||
!fflg)
|
||||
exit(4);
|
||||
strcpy(dnbuf, UUPUB);
|
||||
if (fflg)
|
||||
strcat(dnbuf, &f[2]);
|
||||
else
|
||||
strcat(dnbuf, filename);
|
||||
}
|
||||
else {
|
||||
strcpy(dnbuf, user->pw_dir);
|
||||
strcat(dnbuf, "/");
|
||||
strcat(dnbuf, sl);
|
||||
}
|
||||
#else !RECOVER
|
||||
exit(4);
|
||||
}
|
||||
strcpy(dnbuf, user->pw_dir);
|
||||
strcat(dnbuf, "/");
|
||||
strcat(dnbuf, sl);
|
||||
#endif !RECOVER
|
||||
destname = dnbuf;
|
||||
}
|
||||
#ifdef RECOVER
|
||||
else
|
||||
destname = strcpy(dnbuf, destname);
|
||||
#endif !RECOVER
|
||||
if(strncmp(UULIB, destname, strlen(UULIB)) == 0) {
|
||||
fprintf(stderr, "illegal file: %s", destname);
|
||||
exit(4);
|
||||
}
|
||||
#ifdef RECOVER
|
||||
if (stat(destname, &stbuf) == 0 &&
|
||||
(stbuf.st_mode & S_IFMT) == S_IFDIR &&
|
||||
fflg) {
|
||||
strcat(destname, "/");
|
||||
strcat(destname, &f[2]);
|
||||
}
|
||||
#endif RECOVER
|
||||
out = fopen(destname, "w");
|
||||
#ifdef DEBUG
|
||||
fprintf(dout, "local, file='%s'\n", destname);
|
||||
#endif DEBUG
|
||||
if (out == NULL) {
|
||||
perror(destname);
|
||||
#ifdef RECOVER
|
||||
if (strncmp(destname,UUPUB,strlen(UUPUB)) == 0)
|
||||
exit(5); /* forget it! */
|
||||
filename = getfname(destname);
|
||||
if (destname == dnbuf) /* cmdbuf is scratch */
|
||||
filename = strcpy(cmdbuf, filename);
|
||||
destname = strcpy(dnbuf, UUPUB);
|
||||
if (user != NULL) {
|
||||
strcat(destname, user->pw_name);
|
||||
if (stat(destname, &stbuf) == -1) {
|
||||
mkdir(destname, 0777);
|
||||
}
|
||||
strcat(destname, "/");
|
||||
}
|
||||
if (fflg)
|
||||
strcat(destname, &f[2]);
|
||||
else
|
||||
strcat(destname, filename);
|
||||
if ((out = fopen(destname, "w")) == NULL)
|
||||
exit(5); /* all for naught! */
|
||||
#else !RECOVER
|
||||
exit(5);
|
||||
#endif !RECOVER
|
||||
}
|
||||
if (mode > 0)
|
||||
chmod(destname, mode); /* don't bother to check it */
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, in any case, copy from in to out.
|
||||
*/
|
||||
|
||||
count = 0;
|
||||
while ((c=getc(in)) != EOF) {
|
||||
putc(c, out);
|
||||
count++;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(dout, "count %ld bytes\n", count);
|
||||
fclose(dout);
|
||||
#endif DEBUG
|
||||
|
||||
fclose(in);
|
||||
fclose(out); /* really should pclose in that case */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the ptr in sp at which the character c appears;
|
||||
* NULL if not found. Included so I don't have to fight the
|
||||
* index/strchr battle.
|
||||
*/
|
||||
|
||||
#define NULL 0
|
||||
|
||||
char *
|
||||
index(sp, c)
|
||||
register char *sp, c;
|
||||
{
|
||||
do {
|
||||
if (*sp == c)
|
||||
return(sp);
|
||||
} while (*sp++);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#ifdef RECOVER
|
||||
char *
|
||||
getfname(p)
|
||||
register char *p;
|
||||
{
|
||||
register char *s;
|
||||
s = p;
|
||||
while (*p != '\0')
|
||||
p++;
|
||||
if (p == s)
|
||||
return (NULL);
|
||||
for (;p != s; p--)
|
||||
if (*p == '/') {
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
|
||||
#ifndef BSD4_2
|
||||
makedir(dirname, mode)
|
||||
char *dirname;
|
||||
int mode;
|
||||
{
|
||||
register int pid;
|
||||
int retcode, status;
|
||||
switch ((pid = fork())) {
|
||||
case -1: /* error */
|
||||
return (-1);
|
||||
case 0: /* child */
|
||||
umask(0);
|
||||
execl("/bin/mkdir", "mkdir", dirname, (char *)0);
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
default: /* parent */
|
||||
while ((retcode=wait(&status)) != pid && retcode != -1)
|
||||
;
|
||||
if (retcode == -1)
|
||||
return -1;
|
||||
else {
|
||||
chmod(dirname, mode);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#endif !BSD4_2
|
||||
#endif RECOVER
|
80
usr.bin/uucp/uusnap/uusnap.8
Normal file
80
usr.bin/uucp/uusnap/uusnap.8
Normal file
@ -0,0 +1,80 @@
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)uusnap.8 8.1 (Berkeley) 6/6/93
|
||||
.\"
|
||||
.Dd June 6, 1993
|
||||
.Dt UUSNAP 8
|
||||
.Os BSD 4.2
|
||||
.Sh NAME
|
||||
.Nm uusnap
|
||||
.Nd show snapshot of the
|
||||
.Tn UUCP
|
||||
system
|
||||
.Sh SYNOPSIS
|
||||
.Nm uusnap
|
||||
.Sh DESCRIPTION
|
||||
.Nm Uusnap
|
||||
displays in tabular format a synopsis of the current
|
||||
.Tn UUCP
|
||||
situation. The format of each line is as follows:
|
||||
.Bd -literal -offset indent -compact
|
||||
|
||||
site N Cmds N Data N Xqts Message
|
||||
|
||||
.Ed
|
||||
Where "site" is the name of the site with work, "N" is a count of
|
||||
each of the three possible types of work (command, data, or remote execute),
|
||||
and "Message" is the current status message for that
|
||||
site as found in the
|
||||
.Tn STST
|
||||
file.
|
||||
.Pp
|
||||
Included in "Message" may be the time left before
|
||||
.Tn UUCP
|
||||
can re-try the
|
||||
call, and the count of the number of times that
|
||||
.Tn UUCP
|
||||
has tried
|
||||
(unsuccessfully) to reach the site.
|
||||
.Sh SEE ALSO
|
||||
.Xr uucp 1 ,
|
||||
.Xr uux 1 ,
|
||||
.Xr uuq 1 ,
|
||||
.Xr uucico 8
|
||||
.Rs
|
||||
.%T "UUCP Implementation Guide"
|
||||
.Re
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.2 .
|
348
usr.bin/uucp/uusnap/uusnap.c
Normal file
348
usr.bin/uucp/uusnap/uusnap.c
Normal file
@ -0,0 +1,348 @@
|
||||
/*-
|
||||
* Copyright (c) 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Rick Adams. Originally by RJKing WECo-MG6565 May 83.
|
||||
*
|
||||
* 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, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)uusnap.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "uucp.h"
|
||||
#include <sys/stat.h>
|
||||
#ifdef NDIR
|
||||
#include "ndir.h"
|
||||
#else
|
||||
#include <sys/dir.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
#define NSYSTEM 300 /* max # of systems queued */
|
||||
|
||||
#define CMDSLEN 5 /* Length of trailer */
|
||||
#define DATALEN 5 /* Length of trailer */
|
||||
#define XEQTLEN 5 /* Length of trailer */
|
||||
#define NUMCTRS 3 /* # file types to count */
|
||||
#define CMDTYPE 0 /* Index into scnt.cntr */
|
||||
#define DATTYPE 1 /* Index into scnt.cntr */
|
||||
#define XEQTYPE 2 /* Index into scnt.cntr */
|
||||
|
||||
struct scnt { /* System count structure */
|
||||
char name[MAXBASENAME+1]; /* Name of system */
|
||||
short cntr[NUMCTRS]; /* Count */
|
||||
char stst[32]; /* STST Message */
|
||||
time_t locked; /* If LCK..sys present */
|
||||
int st_type; /* STST Type */
|
||||
int st_count; /* STST Count */
|
||||
time_t st_lastime; /* STST Last time tried */
|
||||
time_t st_retry; /* STST Secs to retry */
|
||||
};
|
||||
|
||||
int sndx; /* Number of systems */
|
||||
struct scnt sys[NSYSTEM]; /* Systems queued */
|
||||
int xqtisrunning = 0;
|
||||
|
||||
main()
|
||||
{
|
||||
register int i, j, nlen = 0;
|
||||
time_t curtime, t;
|
||||
|
||||
dodir(CMDSDIR, "C.", CMDSLEN, '\0', CMDTYPE);
|
||||
dodir(DATADIR, "D.", DATALEN, '\0', DATTYPE);
|
||||
dodir(XEQTDIR, "X.", XEQTLEN, 'X', XEQTYPE);
|
||||
getstst(SPOOL);
|
||||
time(&curtime);
|
||||
for(i=0; i<sndx; ++i)
|
||||
if((j = strlen(sys[i].name)) > nlen)
|
||||
nlen = j;
|
||||
for(i=0; i<sndx; ++i) {
|
||||
t = (sys[i].st_lastime +sys[i].st_retry) - curtime;
|
||||
|
||||
/* decide if STST text is worth printing */
|
||||
if (-t < ONEDAY*2 && sys[i].st_type == SS_WRONGTIME) {
|
||||
sys[i].stst[0] = '\0';
|
||||
if (sys[i].cntr[0]+sys[i].cntr[1]+sys[i].cntr[2] == 0)
|
||||
continue; /* ignore entire line */
|
||||
}
|
||||
|
||||
printf("%-*.*s ", nlen, nlen, sys[i].name);
|
||||
if(sys[i].cntr[CMDTYPE])
|
||||
printf("%3.d Cmd%s ", sys[i].cntr[CMDTYPE],
|
||||
sys[i].cntr[CMDTYPE]>1?"s":" ");
|
||||
else
|
||||
printf(" --- ");
|
||||
if(sys[i].cntr[DATTYPE])
|
||||
printf("%3.d Data ", sys[i].cntr[DATTYPE]);
|
||||
else
|
||||
printf(" --- ");
|
||||
if(sys[i].cntr[XEQTYPE])
|
||||
printf("%3.d Xqt%s ", sys[i].cntr[XEQTYPE],
|
||||
sys[i].cntr[XEQTYPE]>1?"s":" ");
|
||||
else
|
||||
printf(" --- ");
|
||||
if(*sys[i].stst == '\0' || sys[i].locked > sys[i].st_lastime) {
|
||||
if(sys[i].locked)
|
||||
printf("LOCKED\n");
|
||||
else
|
||||
printf("\n");
|
||||
continue;
|
||||
}
|
||||
printf("%s ", sys[i].stst);
|
||||
/* decide if STST info is worth pursuing */
|
||||
if (-t < ONEDAY*2 && (sys[i].st_count == 0
|
||||
|| sys[i].st_type == SS_WRONGTIME
|
||||
|| (sys[i].st_type == SS_INPROGRESS && sys[i].locked))) {
|
||||
printf("\n");
|
||||
continue;
|
||||
}
|
||||
t = (sys[i].st_lastime +sys[i].st_retry) - curtime;
|
||||
if (-t < ONEDAY*2 && sys[i].st_type != SS_FAIL)
|
||||
t = 0;
|
||||
|
||||
if (sys[i].st_count > MAXRECALLS)
|
||||
printf("at MAX RECALLS");
|
||||
else if (-t >= ONEDAY*2)
|
||||
printf("%ld days ago", (long)-t/ONEDAY);
|
||||
else if (t <= 0)
|
||||
printf("Retry time reached");
|
||||
else if (t < 60)
|
||||
printf("Retry time %ld sec%s", (long)(t%60),
|
||||
(t%60)!=1? "s": "");
|
||||
else
|
||||
printf("Retry time %ld min%s", (long)(t/60),
|
||||
(t/60)!=1? "s": "");
|
||||
if(sys[i].st_count > 1)
|
||||
printf(" Count: %d\n", sys[i].st_count);
|
||||
else
|
||||
printf("\n");
|
||||
}
|
||||
if (xqtisrunning)
|
||||
printf("\nUuxqt is running\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
dodir(dnam, prfx, flen, fchr, type)
|
||||
char *dnam, *prfx;
|
||||
int flen;
|
||||
char fchr;
|
||||
int type;
|
||||
{
|
||||
register struct direct *dentp;
|
||||
register DIR *dirp;
|
||||
register int i, fnamlen, plen;
|
||||
char fnam[MAXNAMLEN+1];
|
||||
|
||||
plen = strlen(prfx);
|
||||
if(chdir(dnam) < 0) {
|
||||
perror(dnam);
|
||||
exit(1);
|
||||
}
|
||||
if ((dirp = opendir(".")) == NULL) {
|
||||
perror(dnam);
|
||||
exit(1);
|
||||
}
|
||||
while((dentp = readdir(dirp)) != NULL) {
|
||||
if(*dentp->d_name == '.')
|
||||
continue;
|
||||
if(strncmp(dentp->d_name, prfx, plen) != SAME) {
|
||||
fprintf(stderr, "strange file (%s) in %s\n",
|
||||
dentp->d_name, dnam);
|
||||
continue;
|
||||
}
|
||||
strcpy(fnam, &dentp->d_name[plen]);
|
||||
fnamlen = strlen(fnam);
|
||||
if(flen > 0) {
|
||||
fnamlen -= flen;
|
||||
fnam[fnamlen] = '\0';
|
||||
fnamlen = MAXBASENAME; /* yes, after = '\0'*/
|
||||
} else {
|
||||
for(; fnamlen>0; --fnamlen) {
|
||||
if(fnam[fnamlen] == fchr) {
|
||||
fnam[fnamlen] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
fnamlen = MAXBASENAME;
|
||||
}
|
||||
for(i=0; i<sndx; ++i) {
|
||||
if(strncmp(fnam, sys[i].name, fnamlen) == SAME) {
|
||||
++sys[i].cntr[type];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == sndx) {
|
||||
strcpy(sys[i].name, fnam);
|
||||
++sys[i].cntr[type];
|
||||
if(++sndx >= NSYSTEM) {
|
||||
sndx = NSYSTEM-1;
|
||||
fprintf(stderr,"Too many system names.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
}
|
||||
|
||||
getstst(sdir)
|
||||
char *sdir;
|
||||
{
|
||||
register int i, csys;
|
||||
register char *tp;
|
||||
char fnam[MAXNAMLEN+1], buff[128];
|
||||
register struct direct *dentp;
|
||||
register DIR *dirp;
|
||||
register FILE *st;
|
||||
struct stat stbuf;
|
||||
long atol();
|
||||
|
||||
if (chdir(sdir) < 0) {
|
||||
perror(sdir);
|
||||
exit(1);
|
||||
}
|
||||
if ((dirp = opendir(LOCKDIR)) == NULL) {
|
||||
perror(sdir);
|
||||
exit(1);
|
||||
}
|
||||
while ((dentp = readdir(dirp)) != NULL) {
|
||||
if (strcmp(&dentp->d_name[5], X_LOCK) == SAME) {
|
||||
xqtisrunning++;
|
||||
continue;
|
||||
}
|
||||
if(strncmp(dentp->d_name, "LCK..", 5) == SAME) {
|
||||
if(strncmp(&dentp->d_name[5], "tty", 3) == SAME ||
|
||||
strncmp(&dentp->d_name[5], "cul", 3) == SAME)
|
||||
continue;
|
||||
strcpy(fnam, dentp->d_name);
|
||||
for(csys=0; csys<sndx; ++csys) {
|
||||
if(strncmp(&fnam[5], sys[csys].name, SYSNSIZE)
|
||||
== SAME)
|
||||
break;
|
||||
}
|
||||
strcpy(sys[csys].name, &fnam[5]);
|
||||
if(csys == sndx) {
|
||||
++sndx;
|
||||
}
|
||||
if (stat(fnam, &stbuf) < 0)
|
||||
sys[csys].locked = 1;
|
||||
else
|
||||
sys[csys].locked = stbuf.st_mtime;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
if (chdir("STST") < 0) {
|
||||
perror("STST");
|
||||
exit(1);
|
||||
}
|
||||
if ((dirp = opendir(".")) == NULL) {
|
||||
perror("STST");
|
||||
exit(1);
|
||||
}
|
||||
while ((dentp = readdir(dirp)) != NULL) {
|
||||
if(*dentp->d_name == '.')
|
||||
continue;
|
||||
strcpy(fnam, dentp->d_name);
|
||||
for(csys=0; csys<sndx; ++csys) {
|
||||
if(strncmp(fnam, sys[csys].name, SYSNSIZE) == SAME)
|
||||
break;
|
||||
}
|
||||
strcpy(sys[csys].name, fnam);
|
||||
if(csys == sndx) {
|
||||
++sndx;
|
||||
}
|
||||
if((st = fopen(fnam, "r")) == NULL) {
|
||||
sys[csys].stst[0] = '\0';
|
||||
continue;
|
||||
}
|
||||
buff[0] = '\0';
|
||||
fgets(buff, sizeof(buff), st);
|
||||
fclose(st);
|
||||
if(tp = rindex(buff, ' '))
|
||||
*tp = '\0'; /* drop system name */
|
||||
else
|
||||
continue;
|
||||
for(i=0, tp=buff; i<4; ++i, ++tp)
|
||||
if((tp = index(tp, ' ')) == NULL)
|
||||
break;
|
||||
if(i != 4)
|
||||
continue;
|
||||
strncpy(sys[csys].stst, tp, sizeof(sys[csys].stst));
|
||||
tp = buff;
|
||||
sys[csys].st_type = atoi(tp);
|
||||
tp = index(tp+1, ' ');
|
||||
sys[csys].st_count = atoi(tp+1);
|
||||
tp = index(tp+1, ' ');
|
||||
sys[csys].st_lastime = atol(tp+1);
|
||||
tp = index(tp+1, ' ');
|
||||
sys[csys].st_retry = atol(tp+1);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Return the ptr in sp at which the character c appears;
|
||||
* NULL if not found
|
||||
*/
|
||||
|
||||
char *
|
||||
index(sp, c)
|
||||
register char *sp, c;
|
||||
{
|
||||
do {
|
||||
if (*sp == c)
|
||||
return sp;
|
||||
} while (*sp++);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the ptr in sp at which the character c last
|
||||
* appears; NULL if not found
|
||||
*/
|
||||
|
||||
char *
|
||||
rindex(sp, c)
|
||||
register char *sp, c;
|
||||
{
|
||||
register char *r;
|
||||
|
||||
r = NULL;
|
||||
do {
|
||||
if (*sp == c)
|
||||
r = sp;
|
||||
} while (*sp++);
|
||||
return r;
|
||||
}
|
7
usr.bin/whatis/Makefile
Normal file
7
usr.bin/whatis/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= whatis
|
||||
SRCS= whatis.c config.c
|
||||
.PATH: ${.CURDIR}/../man
|
||||
|
||||
.include <bsd.prog.mk>
|
105
usr.bin/whatis/whatis.1
Normal file
105
usr.bin/whatis/whatis.1
Normal file
@ -0,0 +1,105 @@
|
||||
.\" Copyright (c) 1989, 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.
|
||||
.\"
|
||||
.\" @(#)whatis.1 8.1 (Berkeley) 6/6/93
|
||||
.\"
|
||||
.Dd June 6, 1993
|
||||
.Dt WHATIS 1
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm whatis
|
||||
.Nd describe what a command is
|
||||
.Sh SYNOPSIS
|
||||
.Nm whatis
|
||||
.Op Fl M Ar path
|
||||
.Op Fl m Ar path
|
||||
.Ar command Ar ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm Whatis
|
||||
looks up a given command and gives the header line from the manual page.
|
||||
You can then use the
|
||||
.Xr man 1
|
||||
command to get more information.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Fl
|
||||
.It Fl M Ar path
|
||||
Override the list of standard directories
|
||||
.Nm whatis
|
||||
searches for its database named
|
||||
.Dq Pa whatis.db .
|
||||
The supplied
|
||||
.Ar path
|
||||
must be a colon
|
||||
.Dq \&:
|
||||
separated list of directories.
|
||||
This search path may also be set using the environment variable
|
||||
.Ev MANPATH .
|
||||
.It Fl m Ar path
|
||||
Augment the list of standard directories
|
||||
.Nm whatis
|
||||
searches for its database named
|
||||
.Dq Pa whatis.db .
|
||||
The supplied
|
||||
.Ar path
|
||||
must be a colon
|
||||
.Dq \&:
|
||||
separated list of directories.
|
||||
These directories will be searched before the standard directories
|
||||
or the directories supplied with the
|
||||
.Fl M
|
||||
option or the
|
||||
.Ev MANPATH
|
||||
environment variable are searched.
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width MANPATH
|
||||
.It Ev MANPATH
|
||||
The standard search path used by
|
||||
.Xr man 1
|
||||
may be overridden by specifying a path in the
|
||||
.Ev MANPATH
|
||||
environment variable.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width whatis.db
|
||||
.It Pa whatis.db
|
||||
name of the whatis database
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr apropos 1 ,
|
||||
.Xr man 1 ,
|
||||
.Xr whereis 1
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 3.0 .
|
218
usr.bin/whatis/whatis.c
Normal file
218
usr.bin/whatis/whatis.c
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 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) 1987, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)whatis.c 8.5 (Berkeley) 1/2/94";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../man/config.h"
|
||||
#include "../man/pathnames.h"
|
||||
|
||||
#define MAXLINELEN 256 /* max line handled */
|
||||
|
||||
static int *found, foundman;
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
ENTRY *ep;
|
||||
TAG *tp;
|
||||
int ch, rv;
|
||||
char *beg, *conffile, **p, *p_augment, *p_path;
|
||||
|
||||
conffile = NULL;
|
||||
p_augment = p_path = NULL;
|
||||
while ((ch = getopt(argc, argv, "C:M:m:P:")) != EOF)
|
||||
switch (ch) {
|
||||
case 'C':
|
||||
conffile = optarg;
|
||||
break;
|
||||
case 'M':
|
||||
case 'P': /* backward compatible */
|
||||
p_path = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
p_augment = optarg;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argv += optind;
|
||||
argc -= optind;
|
||||
|
||||
if (argc < 1)
|
||||
usage();
|
||||
|
||||
if ((found = malloc((u_int)argc * sizeof(int))) == NULL)
|
||||
err(1, NULL);
|
||||
memset(found, 0, argc * sizeof(int));
|
||||
|
||||
for (p = argv; *p; ++p) /* trim full paths */
|
||||
if (beg = rindex(*p, '/'))
|
||||
*p = beg + 1;
|
||||
|
||||
if (p_augment)
|
||||
whatis(argv, p_augment, 1);
|
||||
if (p_path || (p_path = getenv("MANPATH")))
|
||||
whatis(argv, p_path, 1);
|
||||
else {
|
||||
config(conffile);
|
||||
ep = (tp = getlist("_whatdb")) == NULL ?
|
||||
NULL : tp->list.tqh_first;
|
||||
for (; ep != NULL; ep = ep->q.tqe_next)
|
||||
whatis(argv, ep->s, 0);
|
||||
}
|
||||
|
||||
if (!foundman) {
|
||||
fprintf(stderr, "whatis: no %s file found.\n", _PATH_WHATIS);
|
||||
exit(1);
|
||||
}
|
||||
rv = 1;
|
||||
for (p = argv; *p; ++p)
|
||||
if (found[p - argv])
|
||||
rv = 0;
|
||||
else
|
||||
printf("%s: not found\n", *p);
|
||||
exit(rv);
|
||||
}
|
||||
|
||||
whatis(argv, path, buildpath)
|
||||
char **argv, *path;
|
||||
int buildpath;
|
||||
{
|
||||
register char *end, *name, **p;
|
||||
char buf[MAXLINELEN + 1], wbuf[MAXLINELEN + 1];
|
||||
|
||||
for (name = path; name; name = end) { /* through name list */
|
||||
if (end = index(name, ':'))
|
||||
*end++ = '\0';
|
||||
|
||||
if (buildpath) {
|
||||
char hold[MAXPATHLEN + 1];
|
||||
|
||||
(void)sprintf(hold, "%s/%s", name, _PATH_WHATIS);
|
||||
name = hold;
|
||||
}
|
||||
|
||||
if (!freopen(name, "r", stdin))
|
||||
continue;
|
||||
|
||||
foundman = 1;
|
||||
|
||||
/* for each file found */
|
||||
while (fgets(buf, sizeof(buf), stdin)) {
|
||||
dashtrunc(buf, wbuf);
|
||||
for (p = argv; *p; ++p)
|
||||
if (match(wbuf, *p)) {
|
||||
printf("%s", buf);
|
||||
found[p - argv] = 1;
|
||||
|
||||
/* only print line once */
|
||||
while (*++p)
|
||||
if (match(wbuf, *p))
|
||||
found[p - argv] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* match --
|
||||
* match a full word
|
||||
*/
|
||||
match(bp, str)
|
||||
register char *bp, *str;
|
||||
{
|
||||
register int len;
|
||||
register char *start;
|
||||
|
||||
if (!*str || !*bp)
|
||||
return(0);
|
||||
for (len = strlen(str);;) {
|
||||
for (; *bp && !isdigit(*bp) && !isalpha(*bp); ++bp);
|
||||
if (!*bp)
|
||||
break;
|
||||
for (start = bp++;
|
||||
*bp && (*bp == '_' || isdigit(*bp) || isalpha(*bp)); ++bp);
|
||||
if (bp - start == len && !strncasecmp(start, str, len))
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* dashtrunc --
|
||||
* truncate a string at " - "
|
||||
*/
|
||||
dashtrunc(from, to)
|
||||
register char *from, *to;
|
||||
{
|
||||
register int ch;
|
||||
|
||||
for (; (ch = *from) && ch != '\n' &&
|
||||
(ch != ' ' || from[1] != '-' || from[2] != ' '); ++from)
|
||||
*to++ = ch;
|
||||
*to = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* usage --
|
||||
* print usage message and die
|
||||
*/
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: whatis [-C file] [-M path] [-m path] command ...\n");
|
||||
exit(1);
|
||||
}
|
Loading…
Reference in New Issue
Block a user