mirror of
https://github.com/darlinghq/darling-shell_cmds.git
synced 2024-11-26 21:10:22 +00:00
shell_cmds-187
This commit is contained in:
commit
c68cae3f05
1
alias/alias.1
Normal file
1
alias/alias.1
Normal file
@ -0,0 +1 @@
|
||||
.so man1/builtin.1
|
331
alias/builtin.1
Normal file
331
alias/builtin.1
Normal file
@ -0,0 +1,331 @@
|
||||
.\"
|
||||
.\" Copyright (c) 1999 Sheldon Hearn
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD: /repoman/r/ncvs/src/share/man/man1/builtin.1,v 1.25 2005/09/09 17:02:08 garys Exp $
|
||||
.\"
|
||||
.Dd February 23, 2005
|
||||
.Dt BUILTIN 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm builtin ,
|
||||
.Nm \&! ,
|
||||
.Nm \&% ,
|
||||
.Nm \&. ,
|
||||
.Nm \&: ,
|
||||
.Nm \&@ ,
|
||||
.Nm \&{ ,
|
||||
.Nm \&} ,
|
||||
.Nm alias ,
|
||||
.Nm alloc ,
|
||||
.Nm bg ,
|
||||
.Nm bind ,
|
||||
.Nm bindkey ,
|
||||
.Nm break ,
|
||||
.Nm breaksw ,
|
||||
.Nm builtins ,
|
||||
.Nm case ,
|
||||
.Nm cd ,
|
||||
.Nm chdir ,
|
||||
.Nm command ,
|
||||
.Nm complete ,
|
||||
.Nm continue ,
|
||||
.Nm default ,
|
||||
.Nm dirs ,
|
||||
.Nm do ,
|
||||
.Nm done ,
|
||||
.Nm echo ,
|
||||
.Nm echotc ,
|
||||
.Nm elif ,
|
||||
.Nm else ,
|
||||
.Nm end ,
|
||||
.Nm endif ,
|
||||
.Nm endsw ,
|
||||
.Nm esac ,
|
||||
.Nm eval ,
|
||||
.Nm exec ,
|
||||
.Nm exit ,
|
||||
.Nm export ,
|
||||
.Nm false ,
|
||||
.Nm fc ,
|
||||
.Nm fg ,
|
||||
.Nm filetest ,
|
||||
.Nm fi ,
|
||||
.Nm for ,
|
||||
.Nm foreach ,
|
||||
.Nm getopts ,
|
||||
.Nm glob ,
|
||||
.Nm goto ,
|
||||
.Nm hash ,
|
||||
.Nm hashstat ,
|
||||
.Nm history ,
|
||||
.Nm hup ,
|
||||
.Nm if ,
|
||||
.Nm jobid ,
|
||||
.Nm jobs ,
|
||||
.Nm kill ,
|
||||
.Nm limit ,
|
||||
.Nm local ,
|
||||
.Nm log ,
|
||||
.Nm login ,
|
||||
.Nm logout ,
|
||||
.Nm ls-F ,
|
||||
.Nm nice ,
|
||||
.Nm nohup ,
|
||||
.Nm notify ,
|
||||
.Nm onintr ,
|
||||
.Nm popd ,
|
||||
.Nm printenv ,
|
||||
.Nm pushd ,
|
||||
.Nm pwd ,
|
||||
.Nm read ,
|
||||
.Nm readonly ,
|
||||
.Nm rehash ,
|
||||
.Nm repeat ,
|
||||
.Nm return ,
|
||||
.Nm sched ,
|
||||
.Nm set ,
|
||||
.Nm setenv ,
|
||||
.Nm settc ,
|
||||
.Nm setty ,
|
||||
.Nm setvar ,
|
||||
.Nm shift ,
|
||||
.Nm source ,
|
||||
.Nm stop ,
|
||||
.Nm suspend ,
|
||||
.Nm switch ,
|
||||
.Nm telltc ,
|
||||
.Nm test ,
|
||||
.Nm then ,
|
||||
.Nm time ,
|
||||
.Nm times ,
|
||||
.Nm trap ,
|
||||
.Nm true ,
|
||||
.Nm type ,
|
||||
.Nm ulimit ,
|
||||
.Nm umask ,
|
||||
.Nm unalias ,
|
||||
.Nm uncomplete ,
|
||||
.Nm unhash ,
|
||||
.Nm unlimit ,
|
||||
.Nm unset ,
|
||||
.Nm unsetenv ,
|
||||
.Nm until ,
|
||||
.Nm wait ,
|
||||
.Nm where ,
|
||||
.Nm which ,
|
||||
.Nm while
|
||||
.Nd shell built-in commands
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl options
|
||||
.Op Ar args ...
|
||||
.Sh DESCRIPTION
|
||||
Shell builtin commands are commands that can be executed within the
|
||||
running shell's process.
|
||||
Note that, in the case of
|
||||
.Xr csh 1
|
||||
builtin commands, the command is executed in a subshell if it occurs as
|
||||
any component of a pipeline except the last.
|
||||
.Pp
|
||||
If a command specified to the shell contains a slash
|
||||
.Dq \&/ ,
|
||||
the shell will not execute a builtin command, even if the last component
|
||||
of the specified command matches the name of a builtin command.
|
||||
Thus, while specifying
|
||||
.Dq Ic echo
|
||||
causes a builtin command to be executed under shells that support the
|
||||
.Nm echo
|
||||
builtin command,
|
||||
specifying
|
||||
.Dq Ic /bin/echo
|
||||
or
|
||||
.Dq Ic ./echo
|
||||
does not.
|
||||
.Pp
|
||||
While some builtin commands may exist in more than one shell, their
|
||||
operation may be different under each shell which supports them.
|
||||
Below is a table which lists shell builtin commands, the standard shells
|
||||
that support them and whether they exist as standalone utilities.
|
||||
.Pp
|
||||
Only builtin commands for the
|
||||
.Xr csh 1
|
||||
and
|
||||
.Xr sh 1
|
||||
shells are listed here.
|
||||
Consult a shell's manual page for
|
||||
details on the operation of its builtin commands.
|
||||
Beware that the
|
||||
.Xr sh 1
|
||||
manual page, at least, calls some of these commands
|
||||
.Dq built-in commands
|
||||
and some of them
|
||||
.Dq reserved words .
|
||||
Users of other shells may need to consult an
|
||||
.Xr info 1
|
||||
page or other sources of documentation.
|
||||
.Pp
|
||||
Commands marked
|
||||
.Dq Li No**
|
||||
under
|
||||
.Em External
|
||||
do exist externally,
|
||||
but are implemented as scripts using a builtin command of the same name.
|
||||
.Bl -column ".Ic uncomplete" ".Em External" ".Xr csh 1" ".Xr sh 1" -offset indent
|
||||
.It Xo
|
||||
.Em "Command External" Ta Xr csh 1 Ta Xr sh 1
|
||||
.Xc
|
||||
.It Ic ! Ta \&No Ta \&No Ta \&Yes
|
||||
.It Ic % Ta \&No Ta Yes Ta \&No
|
||||
.It Ic . Ta \&No Ta \&No Ta Yes
|
||||
.It Ic : Ta \&No Ta Yes Ta Yes
|
||||
.It Ic @ Ta \&No Ta Yes Ta Yes
|
||||
.It Ic { Ta \&No Ta \&No Ta \&Yes
|
||||
.It Ic } Ta \&No Ta \&No Ta \&Yes
|
||||
.It Ic alias Ta \&No** Ta Yes Ta Yes
|
||||
.It Ic alloc Ta \&No Ta Yes Ta \&No
|
||||
.It Ic bg Ta No** Ta Yes Ta Yes
|
||||
.It Ic bind Ta \&No Ta \&No Ta Yes
|
||||
.It Ic bindkey Ta \&No Ta Yes Ta \&No
|
||||
.It Ic break Ta \&No Ta Yes Ta \&Yes
|
||||
.It Ic breaksw Ta \&No Ta Yes Ta \&No
|
||||
.It Ic builtin Ta \&No Ta \&No Ta Yes
|
||||
.It Ic builtins Ta \&No Ta Yes Ta \&No
|
||||
.It Ic case Ta \&No Ta Yes Ta Yes
|
||||
.It Ic cd Ta \&No** Ta Yes Ta Yes
|
||||
.It Ic chdir Ta \&No Ta Yes Ta \&Yes
|
||||
.It Ic command Ta \&No** Ta \&No Ta Yes
|
||||
.It Ic complete Ta \&No Ta Yes Ta \&No
|
||||
.It Ic continue Ta \&No Ta Yes Ta \&Yes
|
||||
.It Ic default Ta \&No Ta Yes Ta \&No
|
||||
.It Ic dirs Ta \&No Ta Yes Ta \&No
|
||||
.It Ic do Ta \&No Ta \&No Ta Yes
|
||||
.It Ic done Ta \&No Ta \&No Ta Yes
|
||||
.It Ic echo Ta Yes Ta Yes Ta Yes
|
||||
.It Ic echotc Ta \&No Ta Yes Ta \&No
|
||||
.It Ic elif Ta \&No Ta \&No Ta Yes
|
||||
.It Ic else Ta \&No Ta Yes Ta \&Yes
|
||||
.It Ic end Ta \&No Ta Yes Ta \&No
|
||||
.It Ic endif Ta \&No Ta Yes Ta \&No
|
||||
.It Ic endsw Ta \&No Ta Yes Ta \&No
|
||||
.It Ic esac Ta \&No Ta \&No Ta Yes
|
||||
.It Ic eval Ta \&No Ta Yes Ta Yes
|
||||
.It Ic exec Ta \&No Ta Yes Ta Yes
|
||||
.It Ic exit Ta \&No Ta Yes Ta Yes
|
||||
.It Ic export Ta \&No Ta \&No Ta Yes
|
||||
.It Ic false Ta Yes Ta \&No Ta Yes
|
||||
.It Ic fc Ta \&No** Ta \&No Ta Yes
|
||||
.It Ic fg Ta \&No** Ta Yes Ta Yes
|
||||
.It Ic filetest Ta \&No Ta Yes Ta \&No
|
||||
.It Ic fi Ta \&No Ta \&No Ta Yes
|
||||
.It Ic for Ta \&No Ta \&No Ta Yes
|
||||
.It Ic foreach Ta \&No Ta Yes Ta \&No
|
||||
.It Ic getopts Ta \&No** Ta \&No Ta Yes
|
||||
.It Ic glob Ta \&No Ta Yes Ta \&No
|
||||
.It Ic goto Ta \&No Ta Yes Ta \&No
|
||||
.It Ic hash Ta \&No Ta \&No Ta Yes
|
||||
.It Ic hashstat Ta \&No Ta Yes Ta \&No
|
||||
.It Ic history Ta \&No Ta Yes Ta \&No
|
||||
.It Ic hup Ta \&No Ta Yes Ta \&No
|
||||
.It Ic if Ta \&No Ta Yes Ta \&Yes
|
||||
.It Ic jobid Ta \&No Ta \&No Ta Yes
|
||||
.It Ic jobs Ta \&No** Ta Yes Ta Yes
|
||||
.It Ic kill Ta Yes Ta Yes Ta \&No
|
||||
.It Ic limit Ta \&No Ta Yes Ta \&No
|
||||
.It Ic local Ta \&No Ta \&No Ta Yes
|
||||
.It Ic log Ta \&No Ta Yes Ta \&No
|
||||
.It Ic login Ta Yes Ta Yes Ta \&No
|
||||
.It Ic logout Ta \&No Ta Yes Ta \&No
|
||||
.It Ic ls-F Ta \&No Ta Yes Ta \&No
|
||||
.It Ic nice Ta Yes Ta Yes Ta \&No
|
||||
.It Ic nohup Ta Yes Ta Yes Ta \&No
|
||||
.It Ic notify Ta \&No Ta Yes Ta \&No
|
||||
.It Ic onintr Ta \&No Ta Yes Ta \&No
|
||||
.It Ic popd Ta \&No Ta Yes Ta \&No
|
||||
.It Ic printenv Ta Yes Ta Yes Ta \&No
|
||||
.It Ic pushd Ta \&No Ta Yes Ta \&No
|
||||
.It Ic pwd Ta Yes Ta \&No Ta Yes
|
||||
.It Ic read Ta \&No** Ta \&No Ta Yes
|
||||
.It Ic readonly Ta \&No Ta \&No Ta Yes
|
||||
.It Ic rehash Ta \&No Ta Yes Ta \&No
|
||||
.It Ic repeat Ta \&No Ta Yes Ta \&No
|
||||
.It Ic return Ta \&No Ta \&No Ta Yes
|
||||
.It Ic sched Ta \&No Ta Yes Ta \&No
|
||||
.It Ic set Ta \&No Ta Yes Ta \&Yes
|
||||
.It Ic setenv Ta \&No Ta Yes Ta \&No
|
||||
.It Ic settc Ta \&No Ta Yes Ta \&No
|
||||
.It Ic setty Ta \&No Ta Yes Ta \&No
|
||||
.It Ic setvar Ta \&No Ta \&No Ta Yes
|
||||
.It Ic shift Ta \&No Ta Yes Ta Yes
|
||||
.It Ic source Ta \&No Ta Yes Ta \&No
|
||||
.It Ic stop Ta \&No Ta Yes Ta \&No
|
||||
.It Ic suspend Ta \&No Ta Yes Ta \&No
|
||||
.It Ic switch Ta \&No Ta Yes Ta \&No
|
||||
.It Ic telltc Ta \&No Ta Yes Ta \&No
|
||||
.It Ic test Ta Yes Ta \&No Ta Yes
|
||||
.It Ic then Ta \&No Ta \&No Ta Yes
|
||||
.It Ic time Ta Yes Ta Yes Ta \&No
|
||||
.It Ic times Ta \&No Ta \&No Ta Yes
|
||||
.It Ic trap Ta \&No Ta \&No Ta Yes
|
||||
.It Ic true Ta Yes Ta \&No Ta Yes
|
||||
.It Ic type Ta \&No Ta \&No Ta Yes
|
||||
.It Ic ulimit Ta \&No Ta \&No Ta Yes
|
||||
.It Ic umask Ta \&No** Ta Yes Ta Yes
|
||||
.It Ic unalias Ta \&No** Ta Yes Ta Yes
|
||||
.It Ic uncomplete Ta \&No Ta Yes Ta \&No
|
||||
.It Ic unhash Ta \&No Ta Yes Ta \&No
|
||||
.It Ic unlimit Ta \&No Ta Yes Ta \&No
|
||||
.It Ic unset Ta \&No Ta Yes Ta Yes
|
||||
.It Ic unsetenv Ta \&No Ta Yes Ta \&No
|
||||
.It Ic until Ta \&No Ta \&No Ta Yes
|
||||
.It Ic wait Ta \&No** Ta Yes Ta Yes
|
||||
.It Ic where Ta \&No Ta Yes Ta \&No
|
||||
.It Ic which Ta Yes Ta Yes Ta \&No
|
||||
.It Ic while Ta \&No Ta Yes Ta \&Yes
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr csh 1 ,
|
||||
.Xr echo 1 ,
|
||||
.Xr false 1 ,
|
||||
.Xr info 1 ,
|
||||
.Xr kill 1 ,
|
||||
.Xr login 1 ,
|
||||
.Xr nice 1 ,
|
||||
.Xr nohup 1 ,
|
||||
.Xr printenv 1 ,
|
||||
.Xr pwd 1 ,
|
||||
.Xr sh 1 ,
|
||||
.Xr test 1 ,
|
||||
.Xr time 1 ,
|
||||
.Xr true 1 ,
|
||||
.Xr which 1
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
manual page first appeared in
|
||||
.Fx 3.4 .
|
||||
.Sh AUTHORS
|
||||
This manual page was written by
|
||||
.An Sheldon Hearn Aq sheldonh@FreeBSD.org .
|
4
alias/generic.sh
Normal file
4
alias/generic.sh
Normal file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
# $FreeBSD: src/usr.bin/alias/generic.sh,v 1.2 2005/10/24 22:32:19 cperciva Exp $
|
||||
# This file is in the public domain.
|
||||
builtin `echo ${0##*/} | tr \[:upper:] \[:lower:]` ${1+"$@"}
|
140
apply/apply.1
Normal file
140
apply/apply.1
Normal file
@ -0,0 +1,140 @@
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)apply.1 8.2 (Berkeley) 4/4/94
|
||||
.\" $FreeBSD: src/usr.bin/apply/apply.1,v 1.14 2002/04/19 23:16:06 charnier Exp $
|
||||
.\"
|
||||
.Dd April 4, 1994
|
||||
.Dt APPLY 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm apply
|
||||
.Nd apply a command to a set of arguments
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl a Ar c
|
||||
.Op Fl d
|
||||
.Op Fl #
|
||||
.Ar command argument ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility runs the named
|
||||
.Ar command
|
||||
on each
|
||||
argument
|
||||
.Ar argument
|
||||
in turn.
|
||||
.Pp
|
||||
Character sequences of the form
|
||||
.Dq Li \&%d
|
||||
in
|
||||
.Ar command ,
|
||||
where
|
||||
.Sq Li d
|
||||
is a digit from 1 to 9, are replaced by the
|
||||
.Li d Ns \'th
|
||||
following unused
|
||||
.Ar argument .
|
||||
In this case, the largest digit number of arguments are discarded for
|
||||
each execution of
|
||||
.Ar command .
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl #
|
||||
Normally arguments are taken singly; the optional number
|
||||
.Fl #
|
||||
specifies the number of arguments to be passed to
|
||||
.Ar command .
|
||||
If the number is zero,
|
||||
.Ar command
|
||||
is run, without arguments, once for each
|
||||
.Ar argument .
|
||||
.Pp
|
||||
If any sequences of
|
||||
.Dq Li \&%d
|
||||
occur in
|
||||
.Ar command ,
|
||||
the
|
||||
.Fl #
|
||||
option is ignored.
|
||||
.It Fl a Ar c
|
||||
The use of the character
|
||||
.Sq Li %
|
||||
as a magic character may be changed with the
|
||||
.Fl a
|
||||
option.
|
||||
.It Fl d
|
||||
Display the commands that would have been executed, but do not actually
|
||||
execute them.
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
The following environment variable affects the execution of
|
||||
.Nm :
|
||||
.Bl -tag -width SHELL
|
||||
.It Ev SHELL
|
||||
Pathname of shell to use.
|
||||
If this variable is not defined, the Bourne shell is used.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
.Bl -tag -width apply -compact
|
||||
.It Li "apply echo a*"
|
||||
is similar to
|
||||
.Xr ls 1 ;
|
||||
.It Li "apply \-2 cmp a1 b1 a2 b2 a3 b3"
|
||||
compares the `a' files to the `b' files;
|
||||
.It Li "apply \-0 who 1 2 3 4 5"
|
||||
runs
|
||||
.Xr who 1
|
||||
5 times; and
|
||||
.It Li "apply \'ln %1 /usr/joe\'" *
|
||||
links all files in the current directory to the directory
|
||||
.Pa /usr/joe .
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /bin/sh -compact
|
||||
.It Pa /bin/sh
|
||||
default shell
|
||||
.El
|
||||
.Sh AUTHORS
|
||||
.An Rob Pike
|
||||
.Sh BUGS
|
||||
Shell metacharacters in
|
||||
.Ar command
|
||||
may have bizarre effects; it is best to enclose complicated
|
||||
commands in single quotes
|
||||
.Pq '' .
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.2 .
|
267
apply/apply.c
Normal file
267
apply/apply.c
Normal file
@ -0,0 +1,267 @@
|
||||
/*-
|
||||
* Copyright (c) 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Jan-Simon Pendry.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)apply.c 8.4 (Berkeley) 4/4/94";
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$FreeBSD: src/usr.bin/apply/apply.c,v 1.22 2002/07/14 18:22:12 alfred Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <paths.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define EXEC "exec "
|
||||
|
||||
static int exec_shell(const char *, char *, char *);
|
||||
static void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
int ch, debug, i, magic, n, nargs, offset, rval;
|
||||
size_t clen, cmdsize, l;
|
||||
char *c, *cmd, *name, *p, *q, *shell, *slashp, *tmpshell;
|
||||
|
||||
debug = 0;
|
||||
magic = '%'; /* Default magic char is `%'. */
|
||||
nargs = -1;
|
||||
while ((ch = getopt(argc, argv, "a:d0123456789")) != -1)
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
if (optarg[1] != '\0')
|
||||
errx(1,
|
||||
"illegal magic character specification");
|
||||
magic = optarg[0];
|
||||
break;
|
||||
case 'd':
|
||||
debug = 1;
|
||||
break;
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
if (nargs != -1)
|
||||
errx(1,
|
||||
"only one -# argument may be specified");
|
||||
nargs = optopt - '0';
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 2)
|
||||
usage();
|
||||
|
||||
/*
|
||||
* The command to run is argv[0], and the args are argv[1..].
|
||||
* Look for %digit references in the command, remembering the
|
||||
* largest one.
|
||||
*/
|
||||
for (n = 0, p = argv[0]; *p != '\0'; ++p)
|
||||
if (p[0] == magic && isdigit(p[1]) && p[1] != '0') {
|
||||
++p;
|
||||
if (p[0] - '0' > n)
|
||||
n = p[0] - '0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out the shell and name arguments to pass to execl()
|
||||
* in exec_shell(). Always malloc() shell and just set name
|
||||
* to point at the last part of shell if there are any backslashes,
|
||||
* otherwise just set it to point at the space malloc()'d. If
|
||||
* SHELL environment variable exists, replace contents of
|
||||
* shell with it.
|
||||
*/
|
||||
shell = name = NULL;
|
||||
tmpshell = getenv("SHELL");
|
||||
shell = (tmpshell != NULL) ? strdup(tmpshell) : strdup(_PATH_BSHELL);
|
||||
if (shell == NULL)
|
||||
err(1, "strdup() failed");
|
||||
slashp = strrchr(shell, '/');
|
||||
name = (slashp != NULL) ? slashp + 1 : shell;
|
||||
|
||||
/*
|
||||
* If there were any %digit references, then use those, otherwise
|
||||
* build a new command string with sufficient %digit references at
|
||||
* the end to consume (nargs) arguments each time round the loop.
|
||||
* Allocate enough space to hold the maximum command. Save the
|
||||
* size to pass to snprintf().
|
||||
*/
|
||||
cmdsize = sizeof(EXEC) - 1 + strlen(argv[0])
|
||||
+ 9 * (sizeof(" %1") - 1) + 1;
|
||||
if ((cmd = malloc(cmdsize)) == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
if (n == 0) {
|
||||
/* If nargs not set, default to a single argument. */
|
||||
if (nargs == -1)
|
||||
nargs = 1;
|
||||
|
||||
p = cmd;
|
||||
offset = snprintf(cmd, cmdsize, EXEC "%s", argv[0]);
|
||||
if ((size_t)offset >= cmdsize)
|
||||
err(1, "snprintf() failed");
|
||||
p += offset;
|
||||
cmdsize -= offset;
|
||||
for (i = 1; i <= nargs; i++) {
|
||||
offset = snprintf(p, cmdsize, " %c%d", magic, i);
|
||||
if ((size_t)offset >= cmdsize)
|
||||
err(1, "snprintf() failed");
|
||||
p += offset;
|
||||
cmdsize -= offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* If nargs set to the special value 0, eat a single
|
||||
* argument for each command execution.
|
||||
*/
|
||||
if (nargs == 0)
|
||||
nargs = 1;
|
||||
} else {
|
||||
offset = snprintf(cmd, cmdsize, EXEC "%s", argv[0]);
|
||||
if ((size_t)offset >= cmdsize)
|
||||
err(1, "snprintf() failed");
|
||||
nargs = n;
|
||||
}
|
||||
|
||||
/*
|
||||
* Grab some space in which to build the command. Allocate
|
||||
* as necessary later, but no reason to build it up slowly
|
||||
* for the normal case.
|
||||
*/
|
||||
if ((c = malloc(clen = 1024)) == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
/*
|
||||
* (argc) and (argv) are still offset by one to make it simpler to
|
||||
* expand %digit references. At the end of the loop check for (argc)
|
||||
* equals 1 means that all the (argv) has been consumed.
|
||||
*/
|
||||
for (rval = 0; argc > nargs; argc -= nargs, argv += nargs) {
|
||||
/*
|
||||
* Find a max value for the command length, and ensure
|
||||
* there's enough space to build it.
|
||||
*/
|
||||
for (l = strlen(cmd), i = 0; i < nargs; i++)
|
||||
l += strlen(argv[i+1]);
|
||||
if (l > clen && (c = realloc(c, clen = l)) == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
/* Expand command argv references. */
|
||||
for (p = cmd, q = c; *p != '\0'; ++p)
|
||||
if (p[0] == magic && isdigit(p[1]) && p[1] != '0') {
|
||||
offset = snprintf(q, l, "%s",
|
||||
argv[(++p)[0] - '0']);
|
||||
if ((size_t)offset >= l)
|
||||
err(1, "snprintf() failed");
|
||||
q += offset;
|
||||
l -= offset;
|
||||
} else
|
||||
*q++ = *p;
|
||||
|
||||
/* Terminate the command string. */
|
||||
*q = '\0';
|
||||
|
||||
/* Run the command. */
|
||||
if (debug)
|
||||
(void)printf("%s\n", c);
|
||||
else
|
||||
if (exec_shell(c, shell, name))
|
||||
rval = 1;
|
||||
}
|
||||
|
||||
if (argc != 1)
|
||||
errx(1, "expecting additional argument%s after \"%s\"",
|
||||
(nargs - argc) ? "s" : "", argv[argc - 1]);
|
||||
free(cmd);
|
||||
free(c);
|
||||
free(shell);
|
||||
exit(rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* exec_shell --
|
||||
* Execute a shell command using passed use_shell and use_name
|
||||
* arguments.
|
||||
*/
|
||||
static int
|
||||
exec_shell(const char *command, char *use_shell, char *use_name)
|
||||
{
|
||||
pid_t pid;
|
||||
int omask, pstat;
|
||||
sig_t intsave, quitsave;
|
||||
|
||||
if (!command) /* just checking... */
|
||||
return(1);
|
||||
|
||||
omask = sigblock(sigmask(SIGCHLD));
|
||||
switch(pid = vfork()) {
|
||||
case -1: /* error */
|
||||
err(1, "vfork");
|
||||
case 0: /* child */
|
||||
(void)sigsetmask(omask);
|
||||
execl(use_shell, use_name, "-c", command, (char *)NULL);
|
||||
warn("%s", use_shell);
|
||||
_exit(1);
|
||||
}
|
||||
intsave = signal(SIGINT, SIG_IGN);
|
||||
quitsave = signal(SIGQUIT, SIG_IGN);
|
||||
pid = waitpid(pid, &pstat, 0);
|
||||
(void)sigsetmask(omask);
|
||||
(void)signal(SIGINT, intsave);
|
||||
(void)signal(SIGQUIT, quitsave);
|
||||
return(pid == -1 ? -1 : pstat);
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
(void)fprintf(stderr,
|
||||
"usage: apply [-a magic] [-d] [-0123456789] command arguments ...\n");
|
||||
exit(1);
|
||||
}
|
114
basename/basename.1
Normal file
114
basename/basename.1
Normal file
@ -0,0 +1,114 @@
|
||||
.\" Copyright (c) 1990, 1993, 1994
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)basename.1 8.2 (Berkeley) 4/18/94
|
||||
.\" $FreeBSD: src/usr.bin/basename/basename.1,v 1.13 2002/06/30 13:40:35 jmallett Exp $
|
||||
.\"
|
||||
.Dd April 18, 1994
|
||||
.Dt BASENAME 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm basename , dirname
|
||||
.Nd return filename or directory portion of pathname
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Ar string
|
||||
.Op Ar suffix
|
||||
.Nm
|
||||
.Op Fl a
|
||||
.Op Fl s Ar suffix
|
||||
.Ar string
|
||||
.Op Ar ...
|
||||
.Nm dirname
|
||||
.Ar string
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility deletes any prefix ending with the last slash
|
||||
.Ql \&/
|
||||
character present in
|
||||
.Ar string
|
||||
(after first stripping trailing slashes),
|
||||
and a
|
||||
.Ar suffix ,
|
||||
if given.
|
||||
The
|
||||
.Ar suffix
|
||||
is not stripped if it is identical to the remaining characters in
|
||||
.Ar string .
|
||||
The resulting filename is written to the standard output.
|
||||
A non-existent suffix is ignored.
|
||||
If
|
||||
.Fl a
|
||||
is specified, then every argument is treated as a
|
||||
.Ar string
|
||||
as if
|
||||
.Nm
|
||||
were invoked with just one argument.
|
||||
If
|
||||
.Fl s
|
||||
is specified, then the
|
||||
.Ar suffix
|
||||
is taken as its argument, and all other arguments are treated as a
|
||||
.Ar string .
|
||||
.Pp
|
||||
The
|
||||
.Nm dirname
|
||||
utility deletes the filename portion, beginning
|
||||
with the last slash
|
||||
.Ql \&/
|
||||
character to the end of
|
||||
.Ar string
|
||||
(after first stripping trailing slashes),
|
||||
and writes the result to the standard output.
|
||||
.Sh EXAMPLES
|
||||
The following line sets the shell variable
|
||||
.Ev FOO
|
||||
to
|
||||
.Pa /usr/bin .
|
||||
.Pp
|
||||
.Dl FOO=`dirname /usr/bin/trail`
|
||||
.Sh DIAGNOSTICS
|
||||
.Ex -std basename dirname
|
||||
.Sh SEE ALSO
|
||||
.Xr csh 1 ,
|
||||
.Xr sh 1
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
and
|
||||
.Nm dirname
|
||||
utilities are expected to be
|
||||
.St -p1003.2
|
||||
compatible.
|
119
basename/basename.c
Normal file
119
basename/basename.c
Normal file
@ -0,0 +1,119 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 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 const char copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)basename.c 8.4 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$FreeBSD: src/usr.bin/basename/basename.c,v 1.14 2002/09/04 23:28:52 dwmalone Exp $");
|
||||
|
||||
#include <err.h>
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *p, *q, *suffix;
|
||||
size_t suffixlen;
|
||||
int aflag, ch;
|
||||
|
||||
aflag = 0;
|
||||
suffix = NULL;
|
||||
suffixlen = 0;
|
||||
|
||||
while ((ch = getopt(argc, argv, "as:")) != -1)
|
||||
switch(ch) {
|
||||
case 'a':
|
||||
aflag = 1;
|
||||
break;
|
||||
case 's':
|
||||
suffix = optarg;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1)
|
||||
usage();
|
||||
|
||||
if (!*argv[0]) {
|
||||
printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
if ((p = basename(argv[0])) == NULL)
|
||||
err(1, "%s", argv[0]);
|
||||
if ((suffix == NULL && !aflag) && argc == 2) {
|
||||
suffix = argv[1];
|
||||
argc--;
|
||||
}
|
||||
if (suffix != NULL)
|
||||
suffixlen = strlen(suffix);
|
||||
while (argc--) {
|
||||
if ((p = basename(*argv)) == NULL)
|
||||
err(1, "%s", argv[0]);
|
||||
if (suffixlen && (q = strchr(p, '\0') - suffixlen) > p &&
|
||||
strcmp(suffix, q) == 0)
|
||||
*q = '\0';
|
||||
argv++;
|
||||
(void)printf("%s\n", p);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
(void)fprintf(stderr,
|
||||
"usage: basename string [suffix]\n"
|
||||
" basename [-a] [-s suffix] string [...]\n");
|
||||
exit(1);
|
||||
}
|
1
basename/dirname.1
Normal file
1
basename/dirname.1
Normal file
@ -0,0 +1 @@
|
||||
.so man1/basename.1
|
102
chroot/chroot.8
Normal file
102
chroot/chroot.8
Normal file
@ -0,0 +1,102 @@
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" from: @(#)chroot.8 8.1 (Berkeley) 6/9/93
|
||||
.\" $NetBSD: chroot.8,v 1.7 1998/10/06 03:47:50 mrg Exp $
|
||||
.\"
|
||||
.Dd October 6, 1998
|
||||
.Dt CHROOT 8
|
||||
.Os BSD 4.3
|
||||
.Sh NAME
|
||||
.Nm chroot
|
||||
.Nd change root directory
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl u user
|
||||
.Op Fl g group
|
||||
.Op Fl G group,group,...
|
||||
.Ar newroot
|
||||
.Op Ar command
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command changes its root directory to the supplied directory
|
||||
.Ar newroot
|
||||
and exec's
|
||||
.Ar command ,
|
||||
if supplied, or an interactive copy of your shell.
|
||||
.Pp
|
||||
If the
|
||||
.Fl u ,
|
||||
.Fl g
|
||||
or
|
||||
.Fl G
|
||||
options are given, the user, group and group list of the process are
|
||||
set to these values after the chroot has taken place. See
|
||||
.Xr setgid 2 ,
|
||||
.Xr setgroups 2 ,
|
||||
.Xr setuid 2 ,
|
||||
.Xr getgrnam 3
|
||||
and
|
||||
.Xr getpwnam 3 .
|
||||
.Pp
|
||||
Note,
|
||||
.Ar command
|
||||
or the shell are run as your real-user-id.
|
||||
.Sh ENVIRONMENT
|
||||
The following environment variable is referenced by
|
||||
.Nm :
|
||||
.Bl -tag -width SHELL
|
||||
.It Ev SHELL
|
||||
If set,
|
||||
the string specified by
|
||||
.Ev SHELL
|
||||
is interpreted as the name of
|
||||
the shell to exec.
|
||||
If the variable
|
||||
.Ev SHELL
|
||||
is not set,
|
||||
.Pa /bin/sh
|
||||
is used.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr chdir 2 ,
|
||||
.Xr chroot 2 ,
|
||||
.Xr environ 7
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in
|
||||
.Bx 4.4 .
|
||||
.Sh SECURITY CONSIDERATIONS
|
||||
.Nm
|
||||
should never be installed setuid root, as it would then be possible
|
||||
to exploit the program to gain root privileges.
|
178
chroot/chroot.c
Normal file
178
chroot/chroot.c
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1988, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)chroot.c 8.1 (Berkeley) 6/9/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: chroot.c,v 1.7 1998/10/06 03:47:51 mrg Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
#include <paths.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main __P((int, char **));
|
||||
void usage __P((void)) __attribute__((__noreturn__));
|
||||
|
||||
char *user; /* user to switch to before running program */
|
||||
char *group; /* group to switch to ... */
|
||||
char *grouplist; /* group list to switch to ... */
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
struct group *gp;
|
||||
struct passwd *pw;
|
||||
char *shell, *endp, *comma;
|
||||
gid_t gid = 0, gidlist[NGROUPS_MAX];
|
||||
uid_t uid = 0;
|
||||
int ch, gids;
|
||||
|
||||
while ((ch = getopt(argc, argv, "G:g:u:")) != -1)
|
||||
switch(ch) {
|
||||
case 'u':
|
||||
user = optarg;
|
||||
break;
|
||||
case 'g':
|
||||
group = optarg;
|
||||
break;
|
||||
case 'G':
|
||||
grouplist = optarg;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1)
|
||||
usage();
|
||||
|
||||
if (group) {
|
||||
if (isdigit(*group)) {
|
||||
gid = (gid_t)strtol(group, &endp, 0);
|
||||
if (endp == group)
|
||||
goto getgroup;
|
||||
} else {
|
||||
getgroup:
|
||||
if ((gp = getgrnam(group)))
|
||||
gid = gp->gr_gid;
|
||||
else
|
||||
errx(1, "no such group %s", group);
|
||||
}
|
||||
}
|
||||
|
||||
for (gids = 0; grouplist; ) {
|
||||
comma = strchr(grouplist, ',');
|
||||
|
||||
if (comma)
|
||||
*comma++ = '\0';
|
||||
|
||||
if (isdigit(*grouplist)) {
|
||||
gidlist[gids] = (gid_t)strtol(grouplist, &endp, 0);
|
||||
if (endp == grouplist)
|
||||
goto getglist;
|
||||
} else {
|
||||
getglist:
|
||||
if ((gp = getgrnam(grouplist)))
|
||||
gidlist[gids] = gp->gr_gid;
|
||||
else
|
||||
errx(1, "no such group %s", group);
|
||||
}
|
||||
gids++;
|
||||
grouplist = comma;
|
||||
}
|
||||
|
||||
if (user) {
|
||||
if (isdigit(*user)) {
|
||||
uid = (uid_t)strtol(user, &endp, 0);
|
||||
if (endp == user)
|
||||
goto getuser;
|
||||
} else {
|
||||
getuser:
|
||||
if ((pw = getpwnam(user)))
|
||||
uid = pw->pw_uid;
|
||||
else
|
||||
errx(1, "no such user %s", user);
|
||||
}
|
||||
}
|
||||
|
||||
if (chdir(argv[0]) || chroot("."))
|
||||
err(1, "%s", argv[0]);
|
||||
|
||||
if (gids && setgroups(gids, gidlist) < 0)
|
||||
err(1, "setgroups");
|
||||
if (group && setgid(gid) < 0)
|
||||
err(1, "setgid");
|
||||
if (user && setuid(uid) < 0)
|
||||
err(1, "setuid");
|
||||
|
||||
if (argv[1]) {
|
||||
execvp(argv[1], &argv[1]);
|
||||
err(1, "%s", argv[1]);
|
||||
}
|
||||
|
||||
if (!(shell = getenv("SHELL")))
|
||||
shell = _PATH_BSHELL;
|
||||
execlp(shell, shell, "-i", NULL);
|
||||
err(1, "%s", shell);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: chroot [-g group] [-G group,group,...] "
|
||||
"[-u user] newroot [command]\n");
|
||||
exit(1);
|
||||
}
|
445
date/date.1
Normal file
445
date/date.1
Normal file
@ -0,0 +1,445 @@
|
||||
.\"-
|
||||
.\" Copyright (c) 1980, 1990, 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.
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)date.1 8.3 (Berkeley) 4/28/95
|
||||
.\" $FreeBSD: src/bin/date/date.1,v 1.72 2005/02/13 22:25:09 ru Exp $
|
||||
.\"
|
||||
.Dd August 16, 2007
|
||||
.Dt DATE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm date
|
||||
.Nd display or set date and time
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl ju
|
||||
.Op Fl r Ar seconds
|
||||
.Oo
|
||||
.Fl v
|
||||
.Sm off
|
||||
.Op Cm + | -
|
||||
.Ar val Op Ar ymwdHMS
|
||||
.Sm on
|
||||
.Oc
|
||||
.Ar ...
|
||||
.Op Cm + Ns Ar output_fmt
|
||||
.Nm
|
||||
.Op Fl jnu
|
||||
.Sm off
|
||||
.Op Oo Oo Ar mm Oc Ar dd Oc Ar HH
|
||||
.Ar MM Oo Oo Ar cc Oc Ar yy Oc Op Ar .ss
|
||||
.Sm on
|
||||
.Nm
|
||||
.Op Fl jnu
|
||||
.Fl f Ar input_fmt new_date
|
||||
.Op Cm + Ns Ar output_fmt
|
||||
.Nm
|
||||
.Op Fl d Ar dst
|
||||
.Op Fl t Ar minutes_west
|
||||
.Sh DESCRIPTION
|
||||
When invoked without arguments, the
|
||||
.Nm
|
||||
utility displays the current date and time.
|
||||
Otherwise, depending on the options specified,
|
||||
.Nm
|
||||
will set the date and time or print it in a user-defined way.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility displays the date and time read from the kernel clock.
|
||||
When used to set the date and time,
|
||||
both the kernel clock and the hardware clock are updated.
|
||||
.Pp
|
||||
Only the superuser may set the date,
|
||||
and if the system securelevel (see
|
||||
.Xr securelevel 8 )
|
||||
is greater than 1,
|
||||
the time may not be changed by more than 1 second.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl d Ar dst
|
||||
Set the kernel's value for daylight saving time.
|
||||
If
|
||||
.Ar dst
|
||||
is non-zero, future calls
|
||||
to
|
||||
.Xr gettimeofday 2
|
||||
will return a non-zero for
|
||||
.Fa tz_dsttime .
|
||||
.It Fl f
|
||||
Use
|
||||
.Ar input_fmt
|
||||
as the format string to parse the
|
||||
.Ar new_date
|
||||
provided rather than using the default
|
||||
.Sm off
|
||||
.Oo Oo Oo
|
||||
.Ar mm Oc
|
||||
.Ar dd Oc
|
||||
.Ar HH Oc
|
||||
.Ar MM
|
||||
.Oo Oo
|
||||
.Ar cc Oc
|
||||
.Ar yy Oc Oo
|
||||
.Ar .ss Oc
|
||||
.Sm on
|
||||
format.
|
||||
Parsing is done using
|
||||
.Xr strptime 3 .
|
||||
.It Fl j
|
||||
Do not try to set the date.
|
||||
This allows you to use the
|
||||
.Fl f
|
||||
flag in addition to the
|
||||
.Cm +
|
||||
option to convert one date format to another.
|
||||
.It Fl n
|
||||
By default, if the
|
||||
.Xr timed 8
|
||||
daemon is running,
|
||||
.Nm
|
||||
sets the time on all of the machines in the local group.
|
||||
The
|
||||
.Fl n
|
||||
option suppresses this behavior and causes the time to be set only on the
|
||||
current machine.
|
||||
.It Fl r Ar seconds
|
||||
Print the date and time represented by
|
||||
.Ar seconds ,
|
||||
where
|
||||
.Ar seconds
|
||||
is the number of seconds since the Epoch
|
||||
(00:00:00 UTC, January 1, 1970;
|
||||
see
|
||||
.Xr time 3 ) ,
|
||||
and can be specified in decimal, octal, or hex.
|
||||
.It Fl t Ar minutes_west
|
||||
Set the system's value for minutes west of
|
||||
.Tn GMT .
|
||||
.Ar minutes_west
|
||||
specifies the number of minutes returned in
|
||||
.Fa tz_minuteswest
|
||||
by future calls to
|
||||
.Xr gettimeofday 2 .
|
||||
.It Fl u
|
||||
Display or set the date in
|
||||
.Tn UTC
|
||||
(Coordinated Universal) time.
|
||||
.It Fl v
|
||||
Adjust (i.e., take the current date and display the result of the
|
||||
adjustment; not actually set the date) the second, minute, hour, month
|
||||
day, week day, month or year according to
|
||||
.Ar val .
|
||||
If
|
||||
.Ar val
|
||||
is preceded with a plus or minus sign,
|
||||
the date is adjusted forwards or backwards according to the remaining string,
|
||||
otherwise the relevant part of the date is set.
|
||||
The date can be adjusted as many times as required using these flags.
|
||||
Flags are processed in the order given.
|
||||
.Pp
|
||||
When setting values
|
||||
(rather than adjusting them),
|
||||
seconds are in the range 0-59, minutes are in the range 0-59, hours are
|
||||
in the range 0-23, month days are in the range 1-31, week days are in the
|
||||
range 0-6 (Sun-Sat),
|
||||
months are in the range 1-12 (Jan-Dec)
|
||||
and years are in the range 80-38 or 1980-2038.
|
||||
.Pp
|
||||
If
|
||||
.Ar val
|
||||
is numeric, one of either
|
||||
.Ar y ,
|
||||
.Ar m ,
|
||||
.Ar w ,
|
||||
.Ar d ,
|
||||
.Ar H ,
|
||||
.Ar M
|
||||
or
|
||||
.Ar S
|
||||
must be used to specify which part of the date is to be adjusted.
|
||||
.Pp
|
||||
The week day or month may be specified using a name rather than a
|
||||
number.
|
||||
If a name is used with the plus
|
||||
(or minus)
|
||||
sign, the date will be put forwards
|
||||
(or backwards)
|
||||
to the next
|
||||
(previous)
|
||||
date that matches the given week day or month.
|
||||
This will not adjust the date,
|
||||
if the given week day or month is the same as the current one.
|
||||
.Pp
|
||||
When a date is adjusted to a specific value or in units greater than hours,
|
||||
daylight savings time considerations are ignored.
|
||||
Adjustments in units of hours or less honor daylight saving time.
|
||||
So, assuming the current date is March 26, 0:30 and that the DST adjustment
|
||||
means that the clock goes forward at 01:00 to 02:00, using
|
||||
.Fl v No +1H
|
||||
will adjust the date to March 26, 2:30.
|
||||
Likewise, if the date is October 29, 0:30 and the DST adjustment means that
|
||||
the clock goes back at 02:00 to 01:00, using
|
||||
.Fl v No +3H
|
||||
will be necessary to reach October 29, 2:30.
|
||||
.Pp
|
||||
When the date is adjusted to a specific value that does not actually exist
|
||||
(for example March 26, 1:30 BST 2000 in the Europe/London timezone),
|
||||
the date will be silently adjusted forwards in units of one hour until it
|
||||
reaches a valid time.
|
||||
When the date is adjusted to a specific value that occurs twice
|
||||
(for example October 29, 1:30 2000),
|
||||
the resulting timezone will be set so that the date matches the earlier of
|
||||
the two times.
|
||||
.Pp
|
||||
Adjusting the date by months is inherently ambiguous because
|
||||
a month is a unit of variable length depending on the current date.
|
||||
This kind of date adjustment is applied in the most intuitive way.
|
||||
First of all,
|
||||
.Nm
|
||||
tries to preserve the day of the month.
|
||||
If it is impossible because the target month is shorter than the present one,
|
||||
the last day of the target month will be the result.
|
||||
For example, using
|
||||
.Fl v No +1m
|
||||
on May 31 will adjust the date to June 30, while using the same option
|
||||
on January 30 will result in the date adjusted to the last day of February.
|
||||
This approach is also believed to make the most sense for shell scripting.
|
||||
Nevertheless, be aware that going forth and back by the same number of
|
||||
months may take you to a different date.
|
||||
.Pp
|
||||
Refer to the examples below for further details.
|
||||
.El
|
||||
.Pp
|
||||
An operand with a leading plus
|
||||
.Pq Sq +
|
||||
sign signals a user-defined format string
|
||||
which specifies the format in which to display the date and time.
|
||||
The format string may contain any of the conversion specifications
|
||||
described in the
|
||||
.Xr strftime 3
|
||||
manual page, as well as any arbitrary text.
|
||||
A newline
|
||||
.Pq Ql \en
|
||||
character is always output after the characters specified by
|
||||
the format string.
|
||||
The format string for the default display is
|
||||
.Dq +%+ .
|
||||
.Pp
|
||||
If an operand does not have a leading plus sign, it is interpreted as
|
||||
a value for setting the system's notion of the current date and time.
|
||||
The canonical representation for setting the date and time is:
|
||||
.Pp
|
||||
.Bl -tag -width Ds -compact -offset indent
|
||||
.It Ar cc
|
||||
Century
|
||||
(either 19 or 20)
|
||||
prepended to the abbreviated year.
|
||||
.It Ar yy
|
||||
Year in abbreviated form
|
||||
(e.g., 89 for 1989, 06 for 2006).
|
||||
.It Ar mm
|
||||
Numeric month, a number from 1 to 12.
|
||||
.It Ar dd
|
||||
Day, a number from 1 to 31.
|
||||
.It Ar HH
|
||||
Hour, a number from 0 to 23.
|
||||
.It Ar MM
|
||||
Minutes, a number from 0 to 59.
|
||||
.It Ar ss
|
||||
Seconds, a number from 0 to 61
|
||||
(59 plus a maximum of two leap seconds).
|
||||
.El
|
||||
.Pp
|
||||
Everything but the minutes is optional.
|
||||
.Pp
|
||||
Time changes for Daylight Saving Time, standard time, leap seconds,
|
||||
and leap years are handled automatically.
|
||||
.Sh ENVIRONMENT
|
||||
The following environment variables affect the execution of
|
||||
.Nm :
|
||||
.Bl -tag -width Ds
|
||||
.It Ev TZ
|
||||
The timezone to use when displaying dates.
|
||||
The normal format is a pathname relative to
|
||||
.Pa /usr/share/zoneinfo .
|
||||
For example, the command
|
||||
.Dq TZ=America/Los_Angeles date
|
||||
displays the current time in California.
|
||||
See
|
||||
.Xr environ 7
|
||||
for more information.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /var/log/messages -compact
|
||||
.It Pa /var/log/messages
|
||||
record of the user setting the time
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
utility exits 0 on success, 1 if unable to set the date, and 2
|
||||
if able to set the local date, but unable to set it globally.
|
||||
.Sh EXAMPLES
|
||||
The command:
|
||||
.Pp
|
||||
.Dl "date ""+DATE: %Y-%m-%d%nTIME: %H:%M:%S"""
|
||||
.Pp
|
||||
will display:
|
||||
.Bd -literal -offset indent
|
||||
DATE: 1987-11-21
|
||||
TIME: 13:36:16
|
||||
.Ed
|
||||
.Pp
|
||||
In the Europe/London timezone, the command:
|
||||
.Pp
|
||||
.Dl "date -v1m -v+1y"
|
||||
.Pp
|
||||
will display:
|
||||
.Pp
|
||||
.Dl "Sun Jan 4 04:15:24 GMT 1998"
|
||||
.Pp
|
||||
where it is currently
|
||||
.Li "Mon Aug 4 04:15:24 BST 1997" .
|
||||
.Pp
|
||||
The command:
|
||||
.Pp
|
||||
.Dl "date -v1d -v3m -v0y -v-1d"
|
||||
.Pp
|
||||
will display the last day of February in the year 2000:
|
||||
.Pp
|
||||
.Dl "Tue Feb 29 03:18:00 GMT 2000"
|
||||
.Pp
|
||||
So will do the command:
|
||||
.Pp
|
||||
.Dl "date -v30d -v3m -v0y -v-1m"
|
||||
.Pp
|
||||
because there is no such date as the 30th of February.
|
||||
.Pp
|
||||
The command:
|
||||
.Pp
|
||||
.Dl "date -v1d -v+1m -v-1d -v-fri"
|
||||
.Pp
|
||||
will display the last Friday of the month:
|
||||
.Pp
|
||||
.Dl "Fri Aug 29 04:31:11 BST 1997"
|
||||
.Pp
|
||||
where it is currently
|
||||
.Li "Mon Aug 4 04:31:11 BST 1997" .
|
||||
.Pp
|
||||
The command:
|
||||
.Pp
|
||||
.Dl "date 0613162785"
|
||||
.Pp
|
||||
sets the date to
|
||||
.Dq Li "June 13, 1985, 4:27 PM" .
|
||||
.Pp
|
||||
.Dl "date ""+%m%d%H%M%Y.%S"""
|
||||
.Pp
|
||||
may be used on one machine to print out the date
|
||||
suitable for setting on another.
|
||||
.Pp
|
||||
The command:
|
||||
.Pp
|
||||
.Dl "date 1432"
|
||||
.Pp
|
||||
sets the time to
|
||||
.Li "2:32 PM" ,
|
||||
without modifying the date.
|
||||
.Pp
|
||||
Finally the command:
|
||||
.Pp
|
||||
.Dl "date -j -f ""%a %b %d %T %Z %Y"" ""`date`"" ""+%s"""
|
||||
.Pp
|
||||
can be used to parse the output from
|
||||
.Nm
|
||||
and express it in Epoch time.
|
||||
.Sh DIAGNOSTICS
|
||||
Occasionally, when
|
||||
.Xr timed 8
|
||||
synchronizes the time on many hosts, the setting of a new time value may
|
||||
require more than a few seconds.
|
||||
On these occasions,
|
||||
.Nm
|
||||
prints:
|
||||
.Ql Network time being set .
|
||||
The message
|
||||
.Ql Communication error with timed
|
||||
occurs when the communication
|
||||
between
|
||||
.Nm
|
||||
and
|
||||
.Xr timed 8
|
||||
fails.
|
||||
.Sh LEGACY SYNOPSIS
|
||||
As above, except for the second line, which is:
|
||||
.Pp
|
||||
.Nm
|
||||
.Op Fl jnu
|
||||
.Sm off
|
||||
.Op Oo Oo Oo Oo Ar cc Oc Ar yy Oc Ar mm Oc Ar dd Oc Ar HH
|
||||
.Ar MM Op Ar .ss
|
||||
.Sm on
|
||||
.Sh LEGACY DIAGNOSTICS
|
||||
When invoked in legacy mode, the following exit values are returned:
|
||||
.Bl -tag -width X -compact
|
||||
.It 0
|
||||
The date was written successfully
|
||||
.It 1
|
||||
Unable to set the date
|
||||
.It 2
|
||||
Able to set the local date, but unable to set it globally
|
||||
.El
|
||||
.Pp
|
||||
For more information about legacy mode, see
|
||||
.Xr compat 5 .
|
||||
.Sh SEE ALSO
|
||||
.Xr gettimeofday 2 ,
|
||||
.Xr strftime 3 ,
|
||||
.Xr strptime 3 ,
|
||||
.Xr utmpx 5 ,
|
||||
.Xr timed 8
|
||||
.Rs
|
||||
.%T "TSP: The Time Synchronization Protocol for UNIX 4.3BSD"
|
||||
.%A R. Gusella
|
||||
.%A S. Zatti
|
||||
.Re
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility is expected to be compatible with
|
||||
.St -p1003.2 .
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
command appeared in
|
||||
.At v1 .
|
344
date/date.c
Normal file
344
date/date.c
Normal file
@ -0,0 +1,344 @@
|
||||
/*-
|
||||
* Copyright (c) 1985, 1987, 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.
|
||||
* 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 const copyright[] =
|
||||
"@(#) Copyright (c) 1985, 1987, 1988, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)date.c 8.2 (Berkeley) 4/28/95";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/date/date.c,v 1.47 2005/01/10 08:39:21 imp Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <locale.h>
|
||||
#ifndef __APPLE__
|
||||
#include <libutil.h>
|
||||
#endif /* !__APPLE__ */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <utmpx.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <get_compat.h>
|
||||
#include <util.h>
|
||||
#else
|
||||
#define COMPAT_MODE(a,b) (1)
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#include "extern.h"
|
||||
#include "vary.h"
|
||||
|
||||
#ifndef TM_YEAR_BASE
|
||||
#define TM_YEAR_BASE 1900
|
||||
#endif
|
||||
|
||||
static time_t tval;
|
||||
int retval;
|
||||
int unix2003_std = 0; /* to determine legacy vs std mode */
|
||||
|
||||
static void setthetime(const char *, const char *, int, int);
|
||||
static void badformat(void);
|
||||
static void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct timezone tz;
|
||||
int ch, rflag;
|
||||
int jflag, nflag;
|
||||
const char *format;
|
||||
char buf[1024];
|
||||
char *endptr, *fmt;
|
||||
char *tmp;
|
||||
int set_timezone;
|
||||
struct vary *v;
|
||||
const struct vary *badv;
|
||||
struct tm lt;
|
||||
|
||||
unix2003_std = COMPAT_MODE("bin/date", "unix2003"); /* Determine the STD */
|
||||
|
||||
v = NULL;
|
||||
fmt = NULL;
|
||||
(void) setlocale(LC_TIME, "");
|
||||
tz.tz_dsttime = tz.tz_minuteswest = 0;
|
||||
rflag = 0;
|
||||
jflag = nflag = 0;
|
||||
set_timezone = 0;
|
||||
while ((ch = getopt(argc, argv, "d:f:jnr:t:uv:")) != -1)
|
||||
switch((char)ch) {
|
||||
case 'd': /* daylight savings time */
|
||||
tz.tz_dsttime = strtol(optarg, &endptr, 10) ? 1 : 0;
|
||||
if (endptr == optarg || *endptr != '\0')
|
||||
usage();
|
||||
set_timezone = 1;
|
||||
break;
|
||||
case 'f':
|
||||
fmt = optarg;
|
||||
break;
|
||||
case 'j':
|
||||
jflag = 1; /* don't set time */
|
||||
break;
|
||||
case 'n': /* don't set network */
|
||||
nflag = 1;
|
||||
break;
|
||||
case 'r': /* user specified seconds */
|
||||
rflag = 1;
|
||||
tval = strtoq(optarg, &tmp, 0);
|
||||
if (*tmp != 0)
|
||||
usage();
|
||||
break;
|
||||
case 't': /* minutes west of UTC */
|
||||
/* error check; don't allow "PST" */
|
||||
tz.tz_minuteswest = strtol(optarg, &endptr, 10);
|
||||
if (endptr == optarg || *endptr != '\0')
|
||||
usage();
|
||||
set_timezone = 1;
|
||||
break;
|
||||
case 'u': /* do everything in UTC */
|
||||
(void)setenv("TZ", "UTC0", 1);
|
||||
break;
|
||||
case 'v':
|
||||
v = vary_append(v, optarg);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/*
|
||||
* If -d or -t, set the timezone or daylight savings time; this
|
||||
* doesn't belong here; the kernel should not know about either.
|
||||
*/
|
||||
if (set_timezone && settimeofday((struct timeval *)NULL, &tz))
|
||||
err(1, "settimeofday (timezone)");
|
||||
|
||||
if (!rflag && time(&tval) == -1)
|
||||
err(1, "time");
|
||||
|
||||
format = "%+";
|
||||
|
||||
/* allow the operands in any order */
|
||||
if (*argv && **argv == '+') {
|
||||
format = *argv + 1;
|
||||
++argv;
|
||||
}
|
||||
|
||||
if (*argv) {
|
||||
setthetime(fmt, *argv, jflag, nflag);
|
||||
++argv;
|
||||
} else if (fmt != NULL)
|
||||
usage();
|
||||
|
||||
if (*argv && **argv == '+')
|
||||
format = *argv + 1;
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* 7999711 */
|
||||
struct tm *ltp = localtime(&tval);
|
||||
if (ltp == NULL) {
|
||||
err(1, "localtime");
|
||||
}
|
||||
lt = *ltp;
|
||||
#else
|
||||
lt = *localtime(&tval);
|
||||
#endif
|
||||
badv = vary_apply(v, <);
|
||||
if (badv) {
|
||||
fprintf(stderr, "%s: Cannot apply date adjustment\n",
|
||||
badv->arg);
|
||||
vary_destroy(v);
|
||||
usage();
|
||||
}
|
||||
vary_destroy(v);
|
||||
(void)strftime(buf, sizeof(buf), format, <);
|
||||
(void)printf("%s\n", buf);
|
||||
if (fflush(stdout))
|
||||
err(1, "stdout");
|
||||
/*
|
||||
* If date/time could not be set/notified in the other hosts as
|
||||
* determined by netsetval(), a return value 2 is set, which is
|
||||
* only propagated back to shell in legacy mode.
|
||||
*/
|
||||
if (unix2003_std)
|
||||
exit(0);
|
||||
exit(retval);
|
||||
}
|
||||
|
||||
#define ATOI2(s) ((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0'))
|
||||
#define ATOI2_OFFSET(s, o) (((s)[o] - '0') * 10 + ((s)[o + 1] - '0'))
|
||||
|
||||
static void
|
||||
setthetime(const char *fmt, const char *p, int jflag, int nflag)
|
||||
{
|
||||
struct tm *lt;
|
||||
const char *dot, *t;
|
||||
int century;
|
||||
size_t length;
|
||||
|
||||
if (fmt != NULL) {
|
||||
lt = localtime(&tval);
|
||||
t = strptime(p, fmt, lt);
|
||||
if (t == NULL) {
|
||||
fprintf(stderr, "Failed conversion of ``%s''"
|
||||
" using format ``%s''\n", p, fmt);
|
||||
badformat();
|
||||
} else if (*t != '\0')
|
||||
fprintf(stderr, "Warning: Ignoring %ld extraneous"
|
||||
" characters in date string (%s)\n",
|
||||
(long) strlen(t), t);
|
||||
} else {
|
||||
for (t = p, dot = NULL; *t; ++t) {
|
||||
if (isdigit(*t))
|
||||
continue;
|
||||
if (*t == '.' && dot == NULL) {
|
||||
dot = t;
|
||||
continue;
|
||||
}
|
||||
badformat();
|
||||
}
|
||||
|
||||
lt = localtime(&tval);
|
||||
|
||||
if (dot != NULL) { /* .ss */
|
||||
dot++; /* *dot++ = '\0'; */
|
||||
if (strlen(dot) != 2)
|
||||
badformat();
|
||||
lt->tm_sec = ATOI2(dot);
|
||||
if (lt->tm_sec > 61)
|
||||
badformat();
|
||||
} else
|
||||
lt->tm_sec = 0;
|
||||
|
||||
century = 0;
|
||||
/* if p has a ".ss" field then let's pretend it's not there */
|
||||
switch (length = strlen(p) - ((dot != NULL) ? 3 : 0)) {
|
||||
case 12: /* cc */
|
||||
lt->tm_year = (unix2003_std ? ATOI2_OFFSET(p, length - 4) : ATOI2(p)) * 100 - TM_YEAR_BASE;
|
||||
century = 1;
|
||||
/* FALLTHROUGH */
|
||||
case 10: /* yy */
|
||||
if (century)
|
||||
lt->tm_year += (unix2003_std ? ATOI2_OFFSET(p, length - 2) : ATOI2(p));
|
||||
else {
|
||||
lt->tm_year = (unix2003_std ? ATOI2_OFFSET(p, length - 2) : ATOI2(p));
|
||||
if (lt->tm_year < 69) /* hack for 2000 ;-} */
|
||||
lt->tm_year += 2000 - TM_YEAR_BASE;
|
||||
else
|
||||
lt->tm_year += 1900 - TM_YEAR_BASE;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 8: /* mm */
|
||||
lt->tm_mon = ATOI2(p);
|
||||
if (lt->tm_mon > 12)
|
||||
badformat();
|
||||
--lt->tm_mon; /* time struct is 0 - 11 */
|
||||
/* FALLTHROUGH */
|
||||
case 6: /* dd */
|
||||
lt->tm_mday = ATOI2(p);
|
||||
if (lt->tm_mday > 31)
|
||||
badformat();
|
||||
/* FALLTHROUGH */
|
||||
case 4: /* HH */
|
||||
lt->tm_hour = ATOI2(p);
|
||||
if (lt->tm_hour > 23)
|
||||
badformat();
|
||||
/* FALLTHROUGH */
|
||||
case 2: /* MM */
|
||||
lt->tm_min = ATOI2(p);
|
||||
if (lt->tm_min > 59)
|
||||
badformat();
|
||||
break;
|
||||
default:
|
||||
badformat();
|
||||
}
|
||||
}
|
||||
|
||||
/* Let mktime() decide whether summer time is in effect. */
|
||||
lt->tm_isdst = -1;
|
||||
|
||||
/* convert broken-down time to GMT clock time */
|
||||
if ((tval = mktime(lt)) == -1)
|
||||
errx(1, "nonexistent time");
|
||||
|
||||
if (!jflag) {
|
||||
/* set the time */
|
||||
if (nflag || netsettime(tval)) {
|
||||
struct utmpx ut;
|
||||
bzero(&ut, sizeof(ut));
|
||||
ut.ut_type = OLD_TIME;
|
||||
(void)gettimeofday(&ut.ut_tv, NULL);
|
||||
pututxline(&ut);
|
||||
ut.ut_tv.tv_sec = tval;
|
||||
ut.ut_tv.tv_usec = 0;
|
||||
if (settimeofday(&ut.ut_tv, NULL))
|
||||
err(1, "settimeofday (timeval)");
|
||||
ut.ut_type = NEW_TIME;
|
||||
pututxline(&ut);
|
||||
}
|
||||
|
||||
if ((p = getlogin()) == NULL)
|
||||
p = "???";
|
||||
syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
badformat(void)
|
||||
{
|
||||
warnx("illegal time format");
|
||||
usage();
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr, "%s\n%s\n",
|
||||
"usage: date [-jnu] [-d dst] [-r seconds] [-t west] "
|
||||
"[-v[+|-]val[ymwdHMS]] ... ",
|
||||
unix2003_std ? " "
|
||||
"[-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]" :
|
||||
" "
|
||||
"[-f fmt date | [[[[[cc]yy]mm]dd]HH]MM[.ss]] [+format]");
|
||||
exit(1);
|
||||
}
|
33
date/extern.h
Normal file
33
date/extern.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*-
|
||||
* 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.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.1 (Berkeley) 5/31/93
|
||||
* $FreeBSD: src/bin/date/extern.h,v 1.7 2004/04/06 20:06:45 markm Exp $
|
||||
*/
|
||||
|
||||
int netsettime(time_t);
|
183
date/netdate.c
Normal file
183
date/netdate.c
Normal file
@ -0,0 +1,183 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)netdate.c 8.1 (Berkeley) 5/31/93";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/date/netdate.c,v 1.18 2004/04/06 20:06:45 markm Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#define TSPTYPES
|
||||
#include <protocols/timed.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
#define WAITACK 2 /* seconds */
|
||||
#define WAITDATEACK 5 /* seconds */
|
||||
|
||||
extern int retval;
|
||||
|
||||
/*
|
||||
* Set the date in the machines controlled by timedaemons by communicating the
|
||||
* new date to the local timedaemon. If the timedaemon is in the master state,
|
||||
* it performs the correction on all slaves. If it is in the slave state, it
|
||||
* notifies the master that a correction is needed.
|
||||
* Returns 0 on success. Returns > 0 on failure, setting retval to 2;
|
||||
*/
|
||||
int
|
||||
netsettime(time_t tval)
|
||||
{
|
||||
struct timeval tout;
|
||||
struct servent *sp;
|
||||
struct tsp msg;
|
||||
struct sockaddr_in lsin, dest, from;
|
||||
fd_set ready;
|
||||
long waittime;
|
||||
int s, port, timed_ack, found, lerr;
|
||||
socklen_t length;
|
||||
char hostname[MAXHOSTNAMELEN];
|
||||
|
||||
if ((sp = getservbyname("timed", "udp")) == NULL) {
|
||||
warnx("timed/udp: unknown service");
|
||||
return (retval = 2);
|
||||
}
|
||||
|
||||
dest.sin_port = sp->s_port;
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_addr.s_addr = htonl((u_long)INADDR_ANY);
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s < 0) {
|
||||
if (errno != EPROTONOSUPPORT)
|
||||
warn("timed");
|
||||
return (retval = 2);
|
||||
}
|
||||
|
||||
memset(&lsin, 0, sizeof(lsin));
|
||||
lsin.sin_family = AF_INET;
|
||||
for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
|
||||
lsin.sin_port = htons((u_short)port);
|
||||
if (bind(s, (struct sockaddr *)&lsin, sizeof(lsin)) >= 0)
|
||||
break;
|
||||
if (errno == EADDRINUSE)
|
||||
continue;
|
||||
if (errno != EADDRNOTAVAIL)
|
||||
warn("bind");
|
||||
goto bad;
|
||||
}
|
||||
if (port == IPPORT_RESERVED / 2) {
|
||||
warnx("all ports in use");
|
||||
goto bad;
|
||||
}
|
||||
msg.tsp_type = TSP_SETDATE;
|
||||
msg.tsp_vers = TSPVERSION;
|
||||
if (gethostname(hostname, sizeof(hostname))) {
|
||||
warn("gethostname");
|
||||
goto bad;
|
||||
}
|
||||
(void)strncpy(msg.tsp_name, hostname, sizeof(msg.tsp_name) - 1);
|
||||
msg.tsp_name[sizeof(msg.tsp_name) - 1] = '\0';
|
||||
msg.tsp_seq = htons((u_short)0);
|
||||
msg.tsp_time.tv_sec = htonl((u_long)tval);
|
||||
msg.tsp_time.tv_usec = htonl((u_long)0);
|
||||
length = sizeof(struct sockaddr_in);
|
||||
if (connect(s, (struct sockaddr *)&dest, length) < 0) {
|
||||
warn("connect");
|
||||
goto bad;
|
||||
}
|
||||
if (send(s, (char *)&msg, sizeof(struct tsp), 0) < 0) {
|
||||
if (errno != ECONNREFUSED)
|
||||
warn("send");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
timed_ack = -1;
|
||||
waittime = WAITACK;
|
||||
loop:
|
||||
tout.tv_sec = waittime;
|
||||
tout.tv_usec = 0;
|
||||
|
||||
FD_ZERO(&ready);
|
||||
FD_SET(s, &ready);
|
||||
found = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout);
|
||||
|
||||
length = sizeof(lerr);
|
||||
if (!getsockopt(s,
|
||||
SOL_SOCKET, SO_ERROR, (char *)&lerr, &length) && lerr) {
|
||||
if (lerr != ECONNREFUSED)
|
||||
warnc(lerr, "send (delayed error)");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (found > 0 && FD_ISSET(s, &ready)) {
|
||||
length = sizeof(struct sockaddr_in);
|
||||
if (recvfrom(s, &msg, sizeof(struct tsp), 0,
|
||||
(struct sockaddr *)&from, &length) < 0) {
|
||||
if (errno != ECONNREFUSED)
|
||||
warn("recvfrom");
|
||||
goto bad;
|
||||
}
|
||||
msg.tsp_seq = ntohs(msg.tsp_seq);
|
||||
msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec);
|
||||
msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec);
|
||||
switch (msg.tsp_type) {
|
||||
case TSP_ACK:
|
||||
timed_ack = TSP_ACK;
|
||||
waittime = WAITDATEACK;
|
||||
goto loop;
|
||||
case TSP_DATEACK:
|
||||
(void)close(s);
|
||||
return (0);
|
||||
default:
|
||||
warnx("wrong ack received from timed: %s",
|
||||
tsptype[msg.tsp_type]);
|
||||
timed_ack = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (timed_ack == -1)
|
||||
warnx("can't reach time daemon, time set locally");
|
||||
|
||||
bad:
|
||||
(void)close(s);
|
||||
return (retval = 2);
|
||||
}
|
506
date/vary.c
Normal file
506
date/vary.c
Normal file
@ -0,0 +1,506 @@
|
||||
/*-
|
||||
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/date/vary.c,v 1.16 2004/08/09 13:43:39 yar Exp $");
|
||||
|
||||
#include <err.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "vary.h"
|
||||
|
||||
struct trans {
|
||||
int val;
|
||||
const char *str;
|
||||
};
|
||||
|
||||
static struct trans trans_mon[] = {
|
||||
{ 1, "january" }, { 2, "february" }, { 3, "march" }, { 4, "april" },
|
||||
{ 5, "may"}, { 6, "june" }, { 7, "july" }, { 8, "august" },
|
||||
{ 9, "september" }, { 10, "october" }, { 11, "november" }, { 12, "december" },
|
||||
{ -1, NULL }
|
||||
};
|
||||
|
||||
static struct trans trans_wday[] = {
|
||||
{ 0, "sunday" }, { 1, "monday" }, { 2, "tuesday" }, { 3, "wednesday" },
|
||||
{ 4, "thursday" }, { 5, "friday" }, { 6, "saturday" },
|
||||
{ -1, NULL }
|
||||
};
|
||||
|
||||
static char digits[] = "0123456789";
|
||||
static int adjhour(struct tm *, char, int, int);
|
||||
|
||||
static int
|
||||
domktime(struct tm *t, char type)
|
||||
{
|
||||
time_t ret;
|
||||
|
||||
while ((ret = mktime(t)) == -1 && t->tm_year > 68 && t->tm_year < 138)
|
||||
/* While mktime() fails, adjust by an hour */
|
||||
adjhour(t, type == '-' ? type : '+', 1, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
trans(const struct trans t[], const char *arg)
|
||||
{
|
||||
int f;
|
||||
|
||||
for (f = 0; t[f].val != -1; f++)
|
||||
if (!strncasecmp(t[f].str, arg, 3) ||
|
||||
!strncasecmp(t[f].str, arg, strlen(t[f].str)))
|
||||
return t[f].val;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct vary *
|
||||
vary_append(struct vary *v, char *arg)
|
||||
{
|
||||
struct vary *result, **nextp;
|
||||
|
||||
if (v) {
|
||||
result = v;
|
||||
while (v->next)
|
||||
v = v->next;
|
||||
nextp = &v->next;
|
||||
} else
|
||||
nextp = &result;
|
||||
|
||||
if ((*nextp = (struct vary *)malloc(sizeof(struct vary))) == NULL)
|
||||
err(1, "malloc");
|
||||
(*nextp)->arg = arg;
|
||||
(*nextp)->next = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int mdays[12] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
static int
|
||||
daysinmonth(const struct tm *t)
|
||||
{
|
||||
int year;
|
||||
|
||||
year = t->tm_year + 1900;
|
||||
|
||||
if (t->tm_mon == 1)
|
||||
if (!(year % 400))
|
||||
return 29;
|
||||
else if (!(year % 100))
|
||||
return 28;
|
||||
else if (!(year % 4))
|
||||
return 29;
|
||||
else
|
||||
return 28;
|
||||
else if (t->tm_mon >= 0 && t->tm_mon < 12)
|
||||
return mdays[t->tm_mon];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
adjyear(struct tm *t, char type, int val, int mk)
|
||||
{
|
||||
switch (type) {
|
||||
case '+':
|
||||
t->tm_year += val;
|
||||
break;
|
||||
case '-':
|
||||
t->tm_year -= val;
|
||||
break;
|
||||
default:
|
||||
t->tm_year = val;
|
||||
if (t->tm_year < 69)
|
||||
t->tm_year += 100; /* as per date.c */
|
||||
else if (t->tm_year > 1900)
|
||||
t->tm_year -= 1900; /* struct tm holds years since 1900 */
|
||||
break;
|
||||
}
|
||||
return !mk || domktime(t, type) != -1;
|
||||
}
|
||||
|
||||
static int
|
||||
adjmon(struct tm *t, char type, int val, int istext, int mk)
|
||||
{
|
||||
int lmdays;
|
||||
|
||||
if (val < 0)
|
||||
return 0;
|
||||
|
||||
switch (type) {
|
||||
case '+':
|
||||
if (istext) {
|
||||
if (val <= t->tm_mon)
|
||||
val += 11 - t->tm_mon; /* early next year */
|
||||
else
|
||||
val -= t->tm_mon + 1; /* later this year */
|
||||
}
|
||||
if (val) {
|
||||
if (!adjyear(t, '+', (t->tm_mon + val) / 12, 0))
|
||||
return 0;
|
||||
val %= 12;
|
||||
t->tm_mon += val;
|
||||
if (t->tm_mon > 11)
|
||||
t->tm_mon -= 12;
|
||||
}
|
||||
break;
|
||||
|
||||
case '-':
|
||||
if (istext) {
|
||||
if (val-1 > t->tm_mon)
|
||||
val = 13 - val + t->tm_mon; /* later last year */
|
||||
else
|
||||
val = t->tm_mon - val + 1; /* early this year */
|
||||
}
|
||||
if (val) {
|
||||
if (!adjyear(t, '-', val / 12, 0))
|
||||
return 0;
|
||||
val %= 12;
|
||||
if (val > t->tm_mon) {
|
||||
if (!adjyear(t, '-', 1, 0))
|
||||
return 0;
|
||||
val -= 12;
|
||||
}
|
||||
t->tm_mon -= val;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (val > 12 || val < 1)
|
||||
return 0;
|
||||
t->tm_mon = --val;
|
||||
}
|
||||
|
||||
/* e.g., -v-1m on March, 31 is the last day of February in common sense */
|
||||
lmdays = daysinmonth(t);
|
||||
if (t->tm_mday > lmdays)
|
||||
t->tm_mday = lmdays;
|
||||
|
||||
return !mk || domktime(t, type) != -1;
|
||||
}
|
||||
|
||||
static int
|
||||
adjday(struct tm *t, char type, int val, int mk)
|
||||
{
|
||||
int lmdays;
|
||||
|
||||
switch (type) {
|
||||
case '+':
|
||||
while (val) {
|
||||
lmdays = daysinmonth(t);
|
||||
if (val > lmdays - t->tm_mday) {
|
||||
val -= lmdays - t->tm_mday + 1;
|
||||
t->tm_mday = 1;
|
||||
if (!adjmon(t, '+', 1, 0, 0))
|
||||
return 0;
|
||||
} else {
|
||||
t->tm_mday += val;
|
||||
val = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
while (val)
|
||||
if (val >= t->tm_mday) {
|
||||
val -= t->tm_mday;
|
||||
t->tm_mday = 1;
|
||||
if (!adjmon(t, '-', 1, 0, 0))
|
||||
return 0;
|
||||
t->tm_mday = daysinmonth(t);
|
||||
} else {
|
||||
t->tm_mday -= val;
|
||||
val = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (val > 0 && val <= daysinmonth(t))
|
||||
t->tm_mday = val;
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return !mk || domktime(t, type) != -1;
|
||||
}
|
||||
|
||||
static int
|
||||
adjwday(struct tm *t, char type, int val, int istext, int mk)
|
||||
{
|
||||
if (val < 0)
|
||||
return 0;
|
||||
|
||||
switch (type) {
|
||||
case '+':
|
||||
if (istext)
|
||||
if (val < t->tm_wday)
|
||||
val = 7 - t->tm_wday + val; /* early next week */
|
||||
else
|
||||
val -= t->tm_wday; /* later this week */
|
||||
else
|
||||
val *= 7; /* "-v+5w" == "5 weeks in the future" */
|
||||
return !val || adjday(t, '+', val, mk);
|
||||
case '-':
|
||||
if (istext) {
|
||||
if (val > t->tm_wday)
|
||||
val = 7 - val + t->tm_wday; /* later last week */
|
||||
else
|
||||
val = t->tm_wday - val; /* early this week */
|
||||
} else
|
||||
val *= 7; /* "-v-5w" == "5 weeks ago" */
|
||||
return !val || adjday(t, '-', val, mk);
|
||||
default:
|
||||
if (val < t->tm_wday)
|
||||
return adjday(t, '-', t->tm_wday - val, mk);
|
||||
else if (val > 6)
|
||||
return 0;
|
||||
else if (val > t->tm_wday)
|
||||
return adjday(t, '+', val - t->tm_wday, mk);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
adjhour(struct tm *t, char type, int val, int mk)
|
||||
{
|
||||
if (val < 0)
|
||||
return 0;
|
||||
|
||||
switch (type) {
|
||||
case '+':
|
||||
if (val) {
|
||||
int days;
|
||||
|
||||
days = (t->tm_hour + val) / 24;
|
||||
val %= 24;
|
||||
t->tm_hour += val;
|
||||
t->tm_hour %= 24;
|
||||
if (!adjday(t, '+', days, 0))
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case '-':
|
||||
if (val) {
|
||||
int days;
|
||||
|
||||
days = val / 24;
|
||||
val %= 24;
|
||||
if (val > t->tm_hour) {
|
||||
days++;
|
||||
val -= 24;
|
||||
}
|
||||
t->tm_hour -= val;
|
||||
if (!adjday(t, '-', days, 0))
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (val > 23)
|
||||
return 0;
|
||||
t->tm_hour = val;
|
||||
}
|
||||
|
||||
return !mk || domktime(t, type) != -1;
|
||||
}
|
||||
|
||||
static int
|
||||
adjmin(struct tm *t, char type, int val, int mk)
|
||||
{
|
||||
if (val < 0)
|
||||
return 0;
|
||||
|
||||
switch (type) {
|
||||
case '+':
|
||||
if (val) {
|
||||
if (!adjhour(t, '+', (t->tm_min + val) / 60, 0))
|
||||
return 0;
|
||||
val %= 60;
|
||||
t->tm_min += val;
|
||||
if (t->tm_min > 59)
|
||||
t->tm_min -= 60;
|
||||
}
|
||||
break;
|
||||
|
||||
case '-':
|
||||
if (val) {
|
||||
if (!adjhour(t, '-', val / 60, 0))
|
||||
return 0;
|
||||
val %= 60;
|
||||
if (val > t->tm_min) {
|
||||
if (!adjhour(t, '-', 1, 0))
|
||||
return 0;
|
||||
val -= 60;
|
||||
}
|
||||
t->tm_min -= val;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (val > 59)
|
||||
return 0;
|
||||
t->tm_min = val;
|
||||
}
|
||||
|
||||
return !mk || domktime(t, type) != -1;
|
||||
}
|
||||
|
||||
static int
|
||||
adjsec(struct tm *t, char type, int val, int mk)
|
||||
{
|
||||
if (val < 0)
|
||||
return 0;
|
||||
|
||||
switch (type) {
|
||||
case '+':
|
||||
if (val) {
|
||||
if (!adjmin(t, '+', (t->tm_sec + val) / 60, 0))
|
||||
return 0;
|
||||
val %= 60;
|
||||
t->tm_sec += val;
|
||||
if (t->tm_sec > 59)
|
||||
t->tm_sec -= 60;
|
||||
}
|
||||
break;
|
||||
|
||||
case '-':
|
||||
if (val) {
|
||||
if (!adjmin(t, '-', val / 60, 0))
|
||||
return 0;
|
||||
val %= 60;
|
||||
if (val > t->tm_sec) {
|
||||
if (!adjmin(t, '-', 1, 0))
|
||||
return 0;
|
||||
val -= 60;
|
||||
}
|
||||
t->tm_sec -= val;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (val > 59)
|
||||
return 0;
|
||||
t->tm_sec = val;
|
||||
}
|
||||
|
||||
return !mk || domktime(t, type) != -1;
|
||||
}
|
||||
|
||||
const struct vary *
|
||||
vary_apply(const struct vary *v, struct tm *t)
|
||||
{
|
||||
char type;
|
||||
char which;
|
||||
char *arg;
|
||||
size_t len;
|
||||
int val;
|
||||
|
||||
for (; v; v = v->next) {
|
||||
type = *v->arg;
|
||||
arg = v->arg;
|
||||
if (type == '+' || type == '-')
|
||||
arg++;
|
||||
else
|
||||
type = '\0';
|
||||
len = strlen(arg);
|
||||
if (len < 2)
|
||||
return v;
|
||||
|
||||
if (type == '\0')
|
||||
t->tm_isdst = -1;
|
||||
|
||||
if (strspn(arg, digits) != len-1) {
|
||||
val = trans(trans_wday, arg);
|
||||
if (val != -1) {
|
||||
if (!adjwday(t, type, val, 1, 1))
|
||||
return v;
|
||||
} else {
|
||||
val = trans(trans_mon, arg);
|
||||
if (val != -1) {
|
||||
if (!adjmon(t, type, val, 1, 1))
|
||||
return v;
|
||||
} else
|
||||
return v;
|
||||
}
|
||||
} else {
|
||||
val = atoi(arg);
|
||||
which = arg[len-1];
|
||||
|
||||
switch (which) {
|
||||
case 'S':
|
||||
if (!adjsec(t, type, val, 1))
|
||||
return v;
|
||||
break;
|
||||
case 'M':
|
||||
if (!adjmin(t, type, val, 1))
|
||||
return v;
|
||||
break;
|
||||
case 'H':
|
||||
if (!adjhour(t, type, val, 1))
|
||||
return v;
|
||||
break;
|
||||
case 'd':
|
||||
t->tm_isdst = -1;
|
||||
if (!adjday(t, type, val, 1))
|
||||
return v;
|
||||
break;
|
||||
case 'w':
|
||||
t->tm_isdst = -1;
|
||||
if (!adjwday(t, type, val, 0, 1))
|
||||
return v;
|
||||
break;
|
||||
case 'm':
|
||||
t->tm_isdst = -1;
|
||||
if (!adjmon(t, type, val, 0, 1))
|
||||
return v;
|
||||
break;
|
||||
case 'y':
|
||||
t->tm_isdst = -1;
|
||||
if (!adjyear(t, type, val, 1))
|
||||
return v;
|
||||
break;
|
||||
default:
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
vary_destroy(struct vary *v)
|
||||
{
|
||||
struct vary *n;
|
||||
|
||||
while (v) {
|
||||
n = v->next;
|
||||
free(v);
|
||||
v = n;
|
||||
}
|
||||
}
|
36
date/vary.h
Normal file
36
date/vary.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*-
|
||||
* Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*
|
||||
* $FreeBSD: src/bin/date/vary.h,v 1.4 1999/08/27 23:14:00 peter Exp $
|
||||
*/
|
||||
|
||||
struct vary {
|
||||
char *arg;
|
||||
struct vary *next;
|
||||
};
|
||||
|
||||
extern struct vary *vary_append(struct vary *v, char *arg);
|
||||
extern const struct vary *vary_apply(const struct vary *v, struct tm *t);
|
||||
extern void vary_destroy(struct vary *v);
|
84
dirname/dirname.c
Normal file
84
dirname/dirname.c
Normal file
@ -0,0 +1,84 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 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 const char copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static const char sccsid[] = "@(#)dirname.c 8.4 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$FreeBSD: src/usr.bin/dirname/dirname.c,v 1.11 2002/07/28 15:43:56 dwmalone Exp $");
|
||||
|
||||
#include <err.h>
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *p;
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != -1)
|
||||
switch(ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 1)
|
||||
usage();
|
||||
|
||||
if ((p = dirname(*argv)) == NULL)
|
||||
err(1, "%s", *argv);
|
||||
(void)printf("%s\n", p);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "usage: dirname path\n");
|
||||
exit(1);
|
||||
}
|
101
echo/echo.1
Normal file
101
echo/echo.1
Normal file
@ -0,0 +1,101 @@
|
||||
.\"-
|
||||
.\" Copyright (c) 1990, 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.
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)echo.1 8.1 (Berkeley) 7/22/93
|
||||
.\" $FreeBSD: src/bin/echo/echo.1,v 1.19 2005/01/16 16:41:56 ru Exp $
|
||||
.\"
|
||||
.Dd April 12, 2003
|
||||
.Dt ECHO 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm echo
|
||||
.Nd write arguments to the standard output
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl n
|
||||
.Op Ar string ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility writes any specified operands, separated by single blank
|
||||
.Pq Ql "\ "
|
||||
characters and followed by a newline
|
||||
.Pq Ql \en
|
||||
character, to the standard
|
||||
output.
|
||||
.Pp
|
||||
The following option is available:
|
||||
.Bl -tag -width flag
|
||||
.It Fl n
|
||||
Do not print the trailing newline character.
|
||||
This may also be achieved by appending
|
||||
.Ql \ec
|
||||
to the end of the string, as is done
|
||||
by iBCS2 compatible systems.
|
||||
Note that this option as well as the effect of
|
||||
.Ql \ec
|
||||
are implementation-defined in
|
||||
.St -p1003.1-2001
|
||||
as amended by Cor.\& 1-2002.
|
||||
Applications aiming for maximum
|
||||
portability are strongly encouraged to use
|
||||
.Xr printf 1
|
||||
to suppress the newline character.
|
||||
.El
|
||||
.Pp
|
||||
Some shells may provide a builtin
|
||||
.Nm
|
||||
command which is similar or identical to this utility.
|
||||
.\" 4874742
|
||||
Most notably, the builtin
|
||||
.Nm
|
||||
in
|
||||
.Xr sh 1
|
||||
does not accept the
|
||||
.Fl n
|
||||
option.
|
||||
.\" 4874742
|
||||
Consult the
|
||||
.Xr builtin 1
|
||||
manual page.
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh SEE ALSO
|
||||
.Xr builtin 1 ,
|
||||
.Xr csh 1 ,
|
||||
.Xr printf 1 ,
|
||||
.Xr sh 1
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility conforms to
|
||||
.St -p1003.1-2001
|
||||
as amended by Cor.\& 1-2002.
|
137
echo/echo.c
Normal file
137
echo/echo.c
Normal file
@ -0,0 +1,137 @@
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char const copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)echo.c 8.1 (Berkeley) 5/31/93";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/echo/echo.c,v 1.18 2005/01/10 08:39:22 imp Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* Report an error and exit.
|
||||
* Use it instead of err(3) to avoid linking-in stdio.
|
||||
*/
|
||||
static void
|
||||
errexit(const char *prog, const char *reason)
|
||||
{
|
||||
char *errstr = strerror(errno);
|
||||
write(STDERR_FILENO, prog, strlen(prog));
|
||||
write(STDERR_FILENO, ": ", 2);
|
||||
write(STDERR_FILENO, reason, strlen(reason));
|
||||
write(STDERR_FILENO, ": ", 2);
|
||||
write(STDERR_FILENO, errstr, strlen(errstr));
|
||||
write(STDERR_FILENO, "\n", 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int nflag; /* if not set, output a trailing newline. */
|
||||
int veclen; /* number of writev arguments. */
|
||||
struct iovec *iov, *vp; /* Elements to write, current element. */
|
||||
char space[] = " ";
|
||||
char newline[] = "\n";
|
||||
char *progname = argv[0];
|
||||
|
||||
/* This utility may NOT do getopt(3) option parsing. */
|
||||
if (*++argv && !strcmp(*argv, "-n")) {
|
||||
++argv;
|
||||
--argc;
|
||||
nflag = 1;
|
||||
} else
|
||||
nflag = 0;
|
||||
|
||||
veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0;
|
||||
|
||||
if ((vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL)
|
||||
errexit(progname, "malloc");
|
||||
|
||||
while (argv[0] != NULL) {
|
||||
size_t len;
|
||||
|
||||
len = strlen(argv[0]);
|
||||
|
||||
/*
|
||||
* If the next argument is NULL then this is this
|
||||
* the last argument, therefore we need to check
|
||||
* for a trailing \c.
|
||||
*/
|
||||
if (argv[1] == NULL) {
|
||||
/* is there room for a '\c' and is there one? */
|
||||
if (len >= 2 &&
|
||||
argv[0][len - 2] == '\\' &&
|
||||
argv[0][len - 1] == 'c') {
|
||||
/* chop it and set the no-newline flag. */
|
||||
len -= 2;
|
||||
nflag = 1;
|
||||
}
|
||||
}
|
||||
vp->iov_base = *argv;
|
||||
vp++->iov_len = len;
|
||||
if (*++argv) {
|
||||
vp->iov_base = space;
|
||||
vp++->iov_len = 1;
|
||||
}
|
||||
}
|
||||
if (!nflag) {
|
||||
veclen++;
|
||||
vp->iov_base = newline;
|
||||
vp++->iov_len = 1;
|
||||
}
|
||||
/* assert(veclen == (vp - iov)); */
|
||||
while (veclen) {
|
||||
int nwrite;
|
||||
|
||||
nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen;
|
||||
if (writev(STDOUT_FILENO, iov, nwrite) == -1)
|
||||
errexit(progname, "write");
|
||||
iov += nwrite;
|
||||
veclen -= nwrite;
|
||||
}
|
||||
return 0;
|
||||
}
|
482
env/env.1
vendored
Normal file
482
env/env.1
vendored
Normal file
@ -0,0 +1,482 @@
|
||||
.\" Copyright (c) 1980, 1990, 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.
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" From @(#)printenv.1 8.1 (Berkeley) 6/6/93
|
||||
.\" From FreeBSD: src/usr.bin/printenv/printenv.1,v 1.17 2002/11/26 17:33:35 ru Exp
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd April 17, 2008
|
||||
.Dt ENV 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm env
|
||||
.Nd set environment and execute command, or print environment
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl iv
|
||||
.Op Fl P Ar altpath
|
||||
.Op Fl S Ar string
|
||||
.Op Fl u Ar name
|
||||
.Op Ar name Ns = Ns Ar value ...
|
||||
.Op Ar utility Op Ar argument ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility executes another
|
||||
.Ar utility
|
||||
after modifying the environment as
|
||||
specified on the command line.
|
||||
Each
|
||||
.Ar name Ns = Ns Ar value
|
||||
option specifies the setting of an environment variable,
|
||||
.Ar name ,
|
||||
with a value of
|
||||
.Ar value .
|
||||
All such environment variables are set before the
|
||||
.Ar utility
|
||||
is executed.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl i
|
||||
Execute the
|
||||
.Ar utility
|
||||
with only those environment variables specified by
|
||||
.Ar name Ns = Ns Ar value
|
||||
options.
|
||||
The environment inherited
|
||||
by
|
||||
.Nm
|
||||
is ignored completely.
|
||||
.\" -P
|
||||
.It Fl P Ar altpath
|
||||
Search the set of directories as specified by
|
||||
.Ar altpath
|
||||
to locate the specified
|
||||
.Ar utility
|
||||
program, instead of using the value of the
|
||||
.Ev PATH
|
||||
environment variable.
|
||||
.\" -S
|
||||
.It Fl S Ar string
|
||||
Split apart the given
|
||||
.Ar string
|
||||
into multiple strings, and process each of the resulting strings
|
||||
as separate arguments to the
|
||||
.Nm
|
||||
utility.
|
||||
The
|
||||
.Fl S
|
||||
option recognizes some special character escape sequences and
|
||||
also supports environment-variable substitution, as described
|
||||
below.
|
||||
.\" -u
|
||||
.It Fl u Ar name
|
||||
If the environment variable
|
||||
.Ar name
|
||||
is in the environment, then remove it before processing the
|
||||
remaining options.
|
||||
This is similar to the
|
||||
.Ic unset
|
||||
command in
|
||||
.Xr sh 1 .
|
||||
The value for
|
||||
.Ar name
|
||||
must not include the
|
||||
.Ql =
|
||||
character.
|
||||
.\" -v
|
||||
.It Fl v
|
||||
Print verbose information for each step of processing done by the
|
||||
.Nm
|
||||
utility.
|
||||
Additional information will be printed if
|
||||
.Fl v
|
||||
is specified multiple times.
|
||||
.El
|
||||
.Pp
|
||||
The above options are only recognized when they are specified
|
||||
before any
|
||||
.Ar name Ns = Ns Ar value
|
||||
options.
|
||||
.Pp
|
||||
If no
|
||||
.Ar utility
|
||||
is specified,
|
||||
.Nm
|
||||
prints out the names and values
|
||||
of the variables in the environment, with one name/value pair per line.
|
||||
.\"
|
||||
.Ss Details of Fl S Ss (split-string) processing
|
||||
The processing of the
|
||||
.Fl S
|
||||
option will split the given
|
||||
.Ar string
|
||||
into separate arguments based on any space or <tab> characters found in the
|
||||
.Ar string .
|
||||
Each of those new arguments will then be treated as if it had been
|
||||
specified as a separate argument on the original
|
||||
.Nm
|
||||
command.
|
||||
.Pp
|
||||
Spaces and tabs may be embedded in one of those new arguments by using
|
||||
single
|
||||
.Pq Dq Li '
|
||||
or double
|
||||
.Pq Ql \&"
|
||||
quotes, or backslashes
|
||||
.Pq Ql \e .
|
||||
Single quotes will escape all non-single quote characters, up to
|
||||
the matching single quote.
|
||||
Double quotes will escape all non-double quote characters, up to
|
||||
the matching double quote.
|
||||
It is an error if the end of the
|
||||
.Ar string
|
||||
is reached before the matching quote character.
|
||||
.Pp
|
||||
If
|
||||
.Fl S
|
||||
would create a new argument that starts with the
|
||||
.Ql #
|
||||
character, then that argument and the remainder of the
|
||||
.Ar string
|
||||
will be ignored.
|
||||
The
|
||||
.Ql \e#
|
||||
sequence can be used when you want a new argument to start
|
||||
with a
|
||||
.Ql #
|
||||
character, without causing the remainder of the
|
||||
.Ar string
|
||||
to be skipped.
|
||||
.Pp
|
||||
While processing the
|
||||
.Ar string
|
||||
value,
|
||||
.Fl S
|
||||
processing will treat certain character combinations as escape
|
||||
sequences which represent some action to take.
|
||||
The character escape sequences are in backslash notation.
|
||||
The characters and their meanings are as follows:
|
||||
.Pp
|
||||
.Bl -tag -width indent -offset indent -compact
|
||||
.It Cm \ec
|
||||
Ignore the remaining characters in the
|
||||
.Ar string .
|
||||
This must not appear inside a double-quoted string.
|
||||
.It Cm \ef
|
||||
Replace with a <form-feed> character.
|
||||
.It Cm \en
|
||||
Replace with a <new-line> character.
|
||||
.It Cm \er
|
||||
Replace with a <carriage return> character.
|
||||
.It Cm \et
|
||||
Replace with a <tab> character.
|
||||
.It Cm \ev
|
||||
Replace with a <vertical tab> character.
|
||||
.It Cm \e#
|
||||
Replace with a
|
||||
.Ql #
|
||||
character.
|
||||
This would be useful when you need a
|
||||
.Ql #
|
||||
as the first character in one of the arguments created
|
||||
by splitting apart the given
|
||||
.Ar string .
|
||||
.It Cm \e$
|
||||
Replace with a
|
||||
.Ql $
|
||||
character.
|
||||
.It Cm \e_
|
||||
If this is found inside of a double-quoted string, then replace it
|
||||
with a single blank.
|
||||
If this is found outside of a quoted string, then treat this as the
|
||||
separator character between new arguments in the original
|
||||
.Ar string .
|
||||
.It Cm \e"
|
||||
Replace with a <double quote> character.
|
||||
.It Cm \e\'
|
||||
Replace with a <single quote> character.
|
||||
.It Cm \e\e
|
||||
Replace with a backslash character.
|
||||
.El
|
||||
.Pp
|
||||
The sequences for <single-quote> and backslash are the only sequences
|
||||
which are recognized inside of a single-quoted string.
|
||||
The other sequences have no special meaning inside a single-quoted
|
||||
string.
|
||||
All escape sequences are recognized inside of a double-quoted string.
|
||||
It is an error if a single
|
||||
.Ql \e
|
||||
character is followed by a character other than the ones listed above.
|
||||
.Pp
|
||||
The processing of
|
||||
.Fl S
|
||||
also supports substitution of values from environment variables.
|
||||
To do this, the name of the environment variable must be inside of
|
||||
.Ql ${} ,
|
||||
such as:
|
||||
.Li ${SOMEVAR} .
|
||||
The common shell syntax of
|
||||
.Li $SOMEVAR
|
||||
is not supported.
|
||||
All values substituted will be the values of the environment variables
|
||||
as they were when the
|
||||
.Nm
|
||||
utility was originally invoked.
|
||||
Those values will not be checked for any of the escape sequences as
|
||||
described above.
|
||||
And any settings of
|
||||
.Ar name Ns = Ns Ar value
|
||||
will not effect the values used for substitution in
|
||||
.Fl S
|
||||
processing.
|
||||
.Pp
|
||||
Also,
|
||||
.Fl S
|
||||
processing can not reference the value of the special parameters
|
||||
which are defined by most shells.
|
||||
For instance,
|
||||
.Fl S
|
||||
can not recognize special parameters such as:
|
||||
.Ql $* ,
|
||||
.Ql $@ ,
|
||||
.Ql $# ,
|
||||
.Ql $?
|
||||
or
|
||||
.Ql $$
|
||||
if they appear inside the given
|
||||
.Ar string .
|
||||
.\"
|
||||
.Ss Use in shell-scripts
|
||||
The
|
||||
.Nm
|
||||
utility is often used as the
|
||||
.Ar interpreter
|
||||
on the first line of interpreted scripts, as
|
||||
described in
|
||||
.Xr execve 2 .
|
||||
.Pp
|
||||
Note that the way the kernel parses the
|
||||
.Ql #!
|
||||
(first line) of an interpreted script has changed as of
|
||||
.Fx 6.0 .
|
||||
Prior to that, the
|
||||
.Fx
|
||||
kernel would split that first line into separate arguments based
|
||||
on any whitespace (space or <tab> characters) found in the line.
|
||||
So, if a script named
|
||||
.Pa /usr/local/bin/someport
|
||||
had a first line of:
|
||||
.Pp
|
||||
.Dl "#!/usr/local/bin/php -n -q -dsafe_mode=0"
|
||||
.Pp
|
||||
then the
|
||||
.Pa /usr/local/bin/php
|
||||
program would have been started with the arguments of:
|
||||
.Bd -literal -offset indent
|
||||
arg[0] = '/usr/local/bin/php'
|
||||
arg[1] = '-n'
|
||||
arg[2] = '-q'
|
||||
arg[3] = '-dsafe_mode=0'
|
||||
arg[4] = '/usr/local/bin/someport'
|
||||
.Ed
|
||||
.Pp
|
||||
plus any arguments the user specified when executing
|
||||
.Pa someport .
|
||||
However, this processing of multiple options on the
|
||||
.Ql #!
|
||||
line is not the way any other operating system parses the
|
||||
first line of an interpreted script.
|
||||
So after a change which was made for
|
||||
.Fx 6.0
|
||||
release, that script will result in
|
||||
.Pa /usr/local/bin/php
|
||||
being started with the arguments of:
|
||||
.Bd -literal -offset indent
|
||||
arg[0] = '/usr/local/bin/php'
|
||||
arg[1] = '-n -q -dsafe_mode=0'
|
||||
arg[2] = '/usr/local/bin/someport'
|
||||
.Ed
|
||||
.Pp
|
||||
plus any arguments the user specified.
|
||||
This caused a significant change in the behavior of a few scripts.
|
||||
In the case of above script, to have it behave the same way under
|
||||
.Fx 6.0
|
||||
as it did under earlier releases, the first line should be
|
||||
changed to:
|
||||
.Pp
|
||||
.Dl "#!/usr/bin/env -S /usr/local/bin/php -n -q -dsafe_mode=0"
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility will be started with the entire line as a single
|
||||
argument:
|
||||
.Pp
|
||||
.Dl "arg[1] = '-S /usr/local/bin/php -n -q -dsafe_mode=0'"
|
||||
.Pp
|
||||
and then
|
||||
.Fl S
|
||||
processing will split that line into separate arguments before
|
||||
executing
|
||||
.Pa /usr/local/bin/php .
|
||||
.\"
|
||||
.Sh ENVIRONMENT
|
||||
The
|
||||
.Nm
|
||||
utility uses the
|
||||
.Ev PATH
|
||||
environment variable to locate the requested
|
||||
.Ar utility
|
||||
if the name contains no
|
||||
.Ql /
|
||||
characters, unless the
|
||||
.Fl P
|
||||
option has been specified.
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
An exit status of 126 indicates that
|
||||
.Ar utility
|
||||
was found, but could not be executed.
|
||||
An exit status of 127 indicates that
|
||||
.Ar utility
|
||||
could not be found.
|
||||
.Sh EXAMPLES
|
||||
Since the
|
||||
.Nm
|
||||
utility is often used as part of the first line of an interpreted script,
|
||||
the following examples show a number of ways that the
|
||||
.Nm
|
||||
utility can be useful in scripts.
|
||||
.Pp
|
||||
The kernel processing of an interpreted script does not allow a script
|
||||
to directly reference some other script as its own interpreter.
|
||||
As a way around this, the main difference between
|
||||
.Pp
|
||||
.Dl #!/usr/local/bin/foo
|
||||
and
|
||||
.Dl "#!/usr/bin/env /usr/local/bin/foo"
|
||||
.Pp
|
||||
is that the latter works even if
|
||||
.Pa /usr/local/bin/foo
|
||||
is itself an interpreted script.
|
||||
.Pp
|
||||
Probably the most common use of
|
||||
.Nm
|
||||
is to find the correct interpreter for a script, when the interpreter
|
||||
may be in different directories on different systems.
|
||||
The following example will find the
|
||||
.Ql perl
|
||||
interpreter by searching through the directories specified by
|
||||
.Ev PATH .
|
||||
.Pp
|
||||
.Dl "#!/usr/bin/env perl"
|
||||
.Pp
|
||||
One limitation of that example is that it assumes the user's value
|
||||
for
|
||||
.Ev PATH
|
||||
is set to a value which will find the interpreter you want
|
||||
to execute.
|
||||
The
|
||||
.Fl P
|
||||
option can be used to make sure a specific list of directories is
|
||||
used in the search for
|
||||
.Ar utility .
|
||||
Note that the
|
||||
.Fl S
|
||||
option is also required for this example to work correctly.
|
||||
.Pp
|
||||
.Dl "#!/usr/bin/env -S -P/usr/local/bin:/usr/bin perl"
|
||||
.Pp
|
||||
The above finds
|
||||
.Ql perl
|
||||
only if it is in
|
||||
.Pa /usr/local/bin
|
||||
or
|
||||
.Pa /usr/bin .
|
||||
That could be combined with the present value of
|
||||
.Ev PATH ,
|
||||
to provide more flexibility.
|
||||
Note that spaces are not required between the
|
||||
.Fl S
|
||||
and
|
||||
.Fl P
|
||||
options:
|
||||
.Pp
|
||||
.Dl "#!/usr/bin/env -S-P/usr/local/bin:/usr/bin:${PATH} perl"
|
||||
.Sh COMPATIBILITY
|
||||
The
|
||||
.Nm
|
||||
utility accepts the
|
||||
.Fl
|
||||
option as a synonym for
|
||||
.Fl i .
|
||||
.Sh SEE ALSO
|
||||
.Xr printenv 1 ,
|
||||
.Xr sh 1 ,
|
||||
.Xr execvp 3 ,
|
||||
.Xr environ 7
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility conforms to
|
||||
.St -p1003.1-2001 .
|
||||
The
|
||||
.Fl P , S , u
|
||||
and
|
||||
.Fl v
|
||||
options are non-standard extensions supported by
|
||||
.Fx ,
|
||||
but which may not be available on other operating systems.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.4 .
|
||||
The
|
||||
.Fl P , S
|
||||
and
|
||||
.Fl v
|
||||
options were added in
|
||||
.Fx 6.0 .
|
||||
.Sh BUGS
|
||||
The
|
||||
.Nm
|
||||
utility does not handle values of
|
||||
.Ar utility
|
||||
which have an equals sign
|
||||
.Pq Ql =
|
||||
in their name, for obvious reasons.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility does not take multibyte characters into account when
|
||||
processing the
|
||||
.Fl S
|
||||
option, which may lead to incorrect results in some locales.
|
144
env/env.c
vendored
Normal file
144
env/env.c
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 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.
|
||||
* 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 const char copyright[] =
|
||||
"@(#) Copyright (c) 1988, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)env.c 8.3 (Berkeley) 4/2/94";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "envopts.h"
|
||||
|
||||
extern char **environ;
|
||||
|
||||
int env_verbosity;
|
||||
|
||||
static void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *altpath, **ep, *p, **parg;
|
||||
char *cleanenv[1];
|
||||
int ch, want_clear;
|
||||
int rtrn;
|
||||
|
||||
altpath = NULL;
|
||||
want_clear = 0;
|
||||
while ((ch = getopt(argc, argv, "-iP:S:u:v")) != -1)
|
||||
switch(ch) {
|
||||
case '-':
|
||||
case 'i':
|
||||
want_clear = 1;
|
||||
break;
|
||||
case 'P':
|
||||
altpath = strdup(optarg);
|
||||
break;
|
||||
case 'S':
|
||||
/*
|
||||
* The -S option, for "split string on spaces, with
|
||||
* support for some simple substitutions"...
|
||||
*/
|
||||
split_spaces(optarg, &optind, &argc, &argv);
|
||||
break;
|
||||
case 'u':
|
||||
if (env_verbosity)
|
||||
fprintf(stderr, "#env unset:\t%s\n", optarg);
|
||||
rtrn = unsetenv(optarg);
|
||||
if (rtrn == -1)
|
||||
err(EXIT_FAILURE, "unsetenv %s", optarg);
|
||||
break;
|
||||
case 'v':
|
||||
env_verbosity++;
|
||||
if (env_verbosity > 1)
|
||||
fprintf(stderr, "#env verbosity now at %d\n",
|
||||
env_verbosity);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
if (want_clear) {
|
||||
environ = cleanenv;
|
||||
cleanenv[0] = NULL;
|
||||
if (env_verbosity)
|
||||
fprintf(stderr, "#env clearing environ\n");
|
||||
}
|
||||
for (argv += optind; *argv && (p = strchr(*argv, '=')); ++argv) {
|
||||
if (env_verbosity)
|
||||
fprintf(stderr, "#env setenv:\t%s\n", *argv);
|
||||
*p = '\0';
|
||||
rtrn = setenv(*argv, p + 1, 1);
|
||||
*p = '=';
|
||||
if (rtrn == -1)
|
||||
err(EXIT_FAILURE, "setenv %s", *argv);
|
||||
}
|
||||
if (*argv) {
|
||||
if (altpath)
|
||||
search_paths(altpath, argv);
|
||||
if (env_verbosity) {
|
||||
fprintf(stderr, "#env executing:\t%s\n", *argv);
|
||||
for (parg = argv, argc = 0; *parg; parg++, argc++)
|
||||
fprintf(stderr, "#env arg[%d]=\t'%s'\n",
|
||||
argc, *parg);
|
||||
if (env_verbosity > 1)
|
||||
sleep(1);
|
||||
}
|
||||
execvp(*argv, argv);
|
||||
err(errno == ENOENT ? 127 : 126, "%s", *argv);
|
||||
}
|
||||
for (ep = environ; *ep; ep++)
|
||||
(void)printf("%s\n", *ep);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: env [-iv] [-P utilpath] [-S string] [-u name]\n"
|
||||
" [name=value ...] [utility [argument ...]]\n");
|
||||
exit(1);
|
||||
}
|
468
env/envopts.c
vendored
Normal file
468
env/envopts.c
vendored
Normal file
@ -0,0 +1,468 @@
|
||||
/*-
|
||||
* Copyright (c) 2005 - Garance Alistair Drosehn <gad@FreeBSD.org>.
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation
|
||||
* are those of the authors and should not be interpreted as representing
|
||||
* official policies, either expressed or implied, of the FreeBSD Project.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "envopts.h"
|
||||
|
||||
static const char *
|
||||
expand_vars(int in_thisarg, char **thisarg_p, char **dest_p,
|
||||
const char **src_p);
|
||||
static int is_there(char *candidate);
|
||||
|
||||
/*
|
||||
* The is*() routines take a parameter of 'int', but expect values in the range
|
||||
* of unsigned char. Define some wrappers which take a value of type 'char',
|
||||
* whether signed or unsigned, and ensure the value ends up in the right range.
|
||||
*/
|
||||
#define isalnumch(Anychar) isalnum((u_char)(Anychar))
|
||||
#define isalphach(Anychar) isalpha((u_char)(Anychar))
|
||||
#define isspacech(Anychar) isspace((u_char)(Anychar))
|
||||
|
||||
/*
|
||||
* Routine to determine if a given fully-qualified filename is executable.
|
||||
* This is copied almost verbatim from FreeBSD's usr.bin/which/which.c.
|
||||
*/
|
||||
static int
|
||||
is_there(char *candidate)
|
||||
{
|
||||
struct stat fin;
|
||||
|
||||
/* XXX work around access(2) false positives for superuser */
|
||||
if (access(candidate, X_OK) == 0 &&
|
||||
stat(candidate, &fin) == 0 &&
|
||||
S_ISREG(fin.st_mode) &&
|
||||
(getuid() != 0 ||
|
||||
(fin.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)) {
|
||||
if (env_verbosity > 1)
|
||||
fprintf(stderr, "#env matched:\t'%s'\n", candidate);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Routine to search through an alternate path-list, looking for a given
|
||||
* filename to execute. If the file is found, replace the original
|
||||
* unqualified name with a fully-qualified path. This allows `env' to
|
||||
* execute programs from a specific strict list of possible paths, without
|
||||
* changing the value of PATH seen by the program which will be executed.
|
||||
* E.G.:
|
||||
* #!/usr/bin/env -S-P/usr/local/bin:/usr/bin perl
|
||||
* will execute /usr/local/bin/perl or /usr/bin/perl (whichever is found
|
||||
* first), no matter what the current value of PATH is, and without
|
||||
* changing the value of PATH that the script will see when it runs.
|
||||
*
|
||||
* This is similar to the print_matches() routine in usr.bin/which/which.c.
|
||||
*/
|
||||
void
|
||||
search_paths(char *path, char **argv)
|
||||
{
|
||||
char candidate[PATH_MAX];
|
||||
const char *d;
|
||||
char *filename, *fqname;
|
||||
|
||||
/* If the file has a `/' in it, then no search is done */
|
||||
filename = *argv;
|
||||
if (strchr(filename, '/') != NULL)
|
||||
return;
|
||||
|
||||
if (env_verbosity > 1) {
|
||||
fprintf(stderr, "#env Searching:\t'%s'\n", path);
|
||||
fprintf(stderr, "#env for file:\t'%s'\n", filename);
|
||||
}
|
||||
|
||||
fqname = NULL;
|
||||
while ((d = strsep(&path, ":")) != NULL) {
|
||||
if (*d == '\0')
|
||||
d = ".";
|
||||
if (snprintf(candidate, sizeof(candidate), "%s/%s", d,
|
||||
filename) >= (int)sizeof(candidate))
|
||||
continue;
|
||||
if (is_there(candidate)) {
|
||||
fqname = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fqname == NULL) {
|
||||
errno = ENOENT;
|
||||
err(127, "%s", filename);
|
||||
}
|
||||
*argv = strdup(candidate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Routine to split a string into multiple parameters, while recognizing a
|
||||
* few special characters. It recognizes both single and double-quoted
|
||||
* strings. This processing is designed entirely for the benefit of the
|
||||
* parsing of "#!"-lines (aka "shebang" lines == the first line of an
|
||||
* executable script). Different operating systems parse that line in very
|
||||
* different ways, and this split-on-spaces processing is meant to provide
|
||||
* ways to specify arbitrary arguments on that line, no matter how the OS
|
||||
* parses it.
|
||||
*
|
||||
* Within a single-quoted string, the two characters "\'" are treated as
|
||||
* a literal "'" character to add to the string, and "\\" are treated as
|
||||
* a literal "\" character to add. Other than that, all characters are
|
||||
* copied until the processing gets to a terminating "'".
|
||||
*
|
||||
* Within a double-quoted string, many more "\"-style escape sequences
|
||||
* are recognized, mostly copied from what is recognized in the `printf'
|
||||
* command. Some OS's will not allow a literal blank character to be
|
||||
* included in the one argument that they recognize on a shebang-line,
|
||||
* so a few additional escape-sequences are defined to provide ways to
|
||||
* specify blanks.
|
||||
*
|
||||
* Within a double-quoted string "\_" is turned into a literal blank.
|
||||
* (Inside of a single-quoted string, the two characters are just copied)
|
||||
* Outside of a quoted string, "\_" is treated as both a blank, and the
|
||||
* end of the current argument. So with a shelbang-line of:
|
||||
* #!/usr/bin/env -SA=avalue\_perl
|
||||
* the -S value would be broken up into arguments "A=avalue" and "perl".
|
||||
*/
|
||||
void
|
||||
split_spaces(const char *str, int *origind, int *origc, char ***origv)
|
||||
{
|
||||
static const char *nullarg = "";
|
||||
const char *bq_src, *copystr, *src;
|
||||
char *dest, **newargv, *newstr, **nextarg, **oldarg;
|
||||
int addcount, bq_destlen, copychar, found_sep, in_arg, in_dq, in_sq;
|
||||
|
||||
/*
|
||||
* Ignore leading space on the string, and then malloc enough room
|
||||
* to build a copy of it. The copy might end up shorter than the
|
||||
* original, due to quoted strings and '\'-processing.
|
||||
*/
|
||||
while (isspacech(*str))
|
||||
str++;
|
||||
if (*str == '\0')
|
||||
return;
|
||||
newstr = malloc(strlen(str) + 1);
|
||||
|
||||
/*
|
||||
* Allocate plenty of space for the new array of arg-pointers,
|
||||
* and start that array off with the first element of the old
|
||||
* array.
|
||||
*/
|
||||
newargv = malloc((*origc + (strlen(str) / 2) + 2) * sizeof(char *));
|
||||
nextarg = newargv;
|
||||
*nextarg++ = **origv;
|
||||
|
||||
/* Come up with the new args by splitting up the given string. */
|
||||
addcount = 0;
|
||||
bq_destlen = in_arg = in_dq = in_sq = 0;
|
||||
bq_src = NULL;
|
||||
for (src = str, dest = newstr; *src != '\0'; src++) {
|
||||
/*
|
||||
* This switch will look at a character in *src, and decide
|
||||
* what should be copied to *dest. It only decides what
|
||||
* character(s) to copy, it should not modify *dest. In some
|
||||
* cases, it will look at multiple characters from *src.
|
||||
*/
|
||||
copychar = found_sep = 0;
|
||||
copystr = NULL;
|
||||
switch (*src) {
|
||||
case '"':
|
||||
if (in_sq)
|
||||
copychar = *src;
|
||||
else if (in_dq)
|
||||
in_dq = 0;
|
||||
else {
|
||||
/*
|
||||
* Referencing nullarg ensures that a new
|
||||
* argument is created, even if this quoted
|
||||
* string ends up with zero characters.
|
||||
*/
|
||||
copystr = nullarg;
|
||||
in_dq = 1;
|
||||
bq_destlen = dest - *(nextarg - 1);
|
||||
bq_src = src;
|
||||
}
|
||||
break;
|
||||
case '$':
|
||||
if (in_sq)
|
||||
copychar = *src;
|
||||
else {
|
||||
copystr = expand_vars(in_arg, (nextarg - 1),
|
||||
&dest, &src);
|
||||
}
|
||||
break;
|
||||
case '\'':
|
||||
if (in_dq)
|
||||
copychar = *src;
|
||||
else if (in_sq)
|
||||
in_sq = 0;
|
||||
else {
|
||||
/*
|
||||
* Referencing nullarg ensures that a new
|
||||
* argument is created, even if this quoted
|
||||
* string ends up with zero characters.
|
||||
*/
|
||||
copystr = nullarg;
|
||||
in_sq = 1;
|
||||
bq_destlen = dest - *(nextarg - 1);
|
||||
bq_src = src;
|
||||
}
|
||||
break;
|
||||
case '\\':
|
||||
if (in_sq) {
|
||||
/*
|
||||
* Inside single-quoted strings, only the
|
||||
* "\'" and "\\" are recognized as special
|
||||
* strings.
|
||||
*/
|
||||
copychar = *(src + 1);
|
||||
if (copychar == '\'' || copychar == '\\')
|
||||
src++;
|
||||
else
|
||||
copychar = *src;
|
||||
break;
|
||||
}
|
||||
src++;
|
||||
switch (*src) {
|
||||
case '"':
|
||||
case '#':
|
||||
case '$':
|
||||
case '\'':
|
||||
case '\\':
|
||||
copychar = *src;
|
||||
break;
|
||||
case '_':
|
||||
/*
|
||||
* Alternate way to get a blank, which allows
|
||||
* that blank be used to separate arguments
|
||||
* when it is not inside a quoted string.
|
||||
*/
|
||||
if (in_dq)
|
||||
copychar = ' ';
|
||||
else {
|
||||
found_sep = 1;
|
||||
src++;
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
/*
|
||||
* Ignore remaining characters in the -S string.
|
||||
* This would not make sense if found in the
|
||||
* middle of a quoted string.
|
||||
*/
|
||||
if (in_dq)
|
||||
errx(1, "Sequence '\\%c' is not allowed"
|
||||
" in quoted strings", *src);
|
||||
goto str_done;
|
||||
case 'f':
|
||||
copychar = '\f';
|
||||
break;
|
||||
case 'n':
|
||||
copychar = '\n';
|
||||
break;
|
||||
case 'r':
|
||||
copychar = '\r';
|
||||
break;
|
||||
case 't':
|
||||
copychar = '\t';
|
||||
break;
|
||||
case 'v':
|
||||
copychar = '\v';
|
||||
break;
|
||||
default:
|
||||
if (isspacech(*src))
|
||||
copychar = *src;
|
||||
else
|
||||
errx(1, "Invalid sequence '\\%c' in -S",
|
||||
*src);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if ((in_dq || in_sq) && in_arg)
|
||||
copychar = *src;
|
||||
else if (isspacech(*src))
|
||||
found_sep = 1;
|
||||
else {
|
||||
/*
|
||||
* If the first character of a new argument
|
||||
* is `#', then ignore the remaining chars.
|
||||
*/
|
||||
if (!in_arg && *src == '#')
|
||||
goto str_done;
|
||||
copychar = *src;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Now that the switch has determined what (if anything)
|
||||
* needs to be copied, copy whatever that is to *dest.
|
||||
*/
|
||||
if (copychar || copystr != NULL) {
|
||||
if (!in_arg) {
|
||||
/* This is the first byte of a new argument */
|
||||
*nextarg++ = dest;
|
||||
addcount++;
|
||||
in_arg = 1;
|
||||
}
|
||||
if (copychar)
|
||||
*dest++ = (char)copychar;
|
||||
else if (copystr != NULL)
|
||||
while (*copystr != '\0')
|
||||
*dest++ = *copystr++;
|
||||
} else if (found_sep) {
|
||||
*dest++ = '\0';
|
||||
while (isspacech(*src))
|
||||
src++;
|
||||
--src;
|
||||
in_arg = 0;
|
||||
}
|
||||
}
|
||||
str_done:
|
||||
*dest = '\0';
|
||||
*nextarg = NULL;
|
||||
if (in_dq || in_sq) {
|
||||
errx(1, "No terminating quote for string: %.*s%s",
|
||||
bq_destlen, *(nextarg - 1), bq_src);
|
||||
}
|
||||
if (env_verbosity > 1) {
|
||||
fprintf(stderr, "#env split -S:\t'%s'\n", str);
|
||||
oldarg = newargv + 1;
|
||||
fprintf(stderr, "#env into:\t'%s'\n", *oldarg);
|
||||
for (oldarg++; *oldarg; oldarg++)
|
||||
fprintf(stderr, "#env &\t'%s'\n", *oldarg);
|
||||
}
|
||||
|
||||
/* Copy the unprocessed arg-pointers from the original array */
|
||||
for (oldarg = *origv + *origind; *oldarg; oldarg++)
|
||||
*nextarg++ = *oldarg;
|
||||
*nextarg = NULL;
|
||||
|
||||
/* Update optind/argc/argv in the calling routine */
|
||||
*origind = 1;
|
||||
*origc += addcount;
|
||||
*origv = newargv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Routine to split expand any environment variables referenced in the string
|
||||
* that -S is processing. For now it only supports the form ${VARNAME}. It
|
||||
* explicitly does not support $VARNAME, and obviously can not handle special
|
||||
* shell-variables such as $?, $*, $1, etc. It is called with *src_p pointing
|
||||
* at the initial '$', and if successful it will update *src_p, *dest_p, and
|
||||
* possibly *thisarg_p in the calling routine.
|
||||
*/
|
||||
static const char *
|
||||
expand_vars(int in_thisarg, char **thisarg_p, char **dest_p, const char **src_p)
|
||||
{
|
||||
const char *vbegin, *vend, *vvalue;
|
||||
char *newstr, *vname;
|
||||
int bad_reference;
|
||||
size_t namelen, newlen;
|
||||
|
||||
bad_reference = 1;
|
||||
vbegin = vend = (*src_p) + 1;
|
||||
if (*vbegin++ == '{')
|
||||
if (*vbegin == '_' || isalphach(*vbegin)) {
|
||||
vend = vbegin + 1;
|
||||
while (*vend == '_' || isalnumch(*vend))
|
||||
vend++;
|
||||
if (*vend == '}')
|
||||
bad_reference = 0;
|
||||
}
|
||||
if (bad_reference)
|
||||
errx(1, "Only ${VARNAME} expansion is supported, error at: %s",
|
||||
*src_p);
|
||||
|
||||
/*
|
||||
* We now know we have a valid environment variable name, so update
|
||||
* the caller's source-pointer to the last character in that reference,
|
||||
* and then pick up the matching value. If the variable is not found,
|
||||
* or if it has a null value, then our work here is done.
|
||||
*/
|
||||
*src_p = vend;
|
||||
namelen = vend - vbegin + 1;
|
||||
vname = malloc(namelen);
|
||||
strlcpy(vname, vbegin, namelen);
|
||||
vvalue = getenv(vname);
|
||||
if (vvalue == NULL || *vvalue == '\0') {
|
||||
if (env_verbosity > 2)
|
||||
fprintf(stderr,
|
||||
"#env replacing ${%s} with null string\n",
|
||||
vname);
|
||||
free(vname);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (env_verbosity > 2)
|
||||
fprintf(stderr, "#env expanding ${%s} into '%s'\n", vname,
|
||||
vvalue);
|
||||
|
||||
/*
|
||||
* There is some value to copy to the destination. If the value is
|
||||
* shorter than the ${VARNAME} reference that it replaces, then our
|
||||
* caller can just copy the value to the existing destination.
|
||||
*/
|
||||
if (strlen(vname) + 3 >= strlen(vvalue)) {
|
||||
free(vname);
|
||||
return (vvalue);
|
||||
}
|
||||
|
||||
/*
|
||||
* The value is longer than the string it replaces, which means the
|
||||
* present destination area is too small to hold it. Create a new
|
||||
* destination area, and update the caller's 'dest' variable to match.
|
||||
* If the caller has already started copying some info for 'thisarg'
|
||||
* into the present destination, then the new destination area must
|
||||
* include a copy of that data, and the pointer to 'thisarg' must also
|
||||
* be updated. Note that it is still the caller which copies this
|
||||
* vvalue to the new *dest.
|
||||
*/
|
||||
newlen = strlen(vvalue) + strlen(*src_p) + 1;
|
||||
if (in_thisarg) {
|
||||
**dest_p = '\0'; /* Provide terminator for 'thisarg' */
|
||||
newlen += strlen(*thisarg_p);
|
||||
newstr = malloc(newlen);
|
||||
strcpy(newstr, *thisarg_p);
|
||||
*thisarg_p = newstr;
|
||||
} else {
|
||||
newstr = malloc(newlen);
|
||||
*newstr = '\0';
|
||||
}
|
||||
*dest_p = strchr(newstr, '\0');
|
||||
free(vname);
|
||||
return (vvalue);
|
||||
}
|
37
env/envopts.h
vendored
Normal file
37
env/envopts.h
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
/*-
|
||||
* Copyright (c) 2005 - Garance Alistair Drosehn <gad@FreeBSD.org>.
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation
|
||||
* are those of the authors and should not be interpreted as representing
|
||||
* official policies, either expressed or implied, of the FreeBSD Project.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
void search_paths(char *path, char **argv);
|
||||
void split_spaces(const char *str, int *origind, int *origc,
|
||||
char ***origv);
|
||||
|
||||
extern int env_verbosity;
|
235
expr/expr.1
Normal file
235
expr/expr.1
Normal file
@ -0,0 +1,235 @@
|
||||
.\" -*- nroff -*-
|
||||
.\"-
|
||||
.\" Copyright (c) 1993 Winning Strategies, Inc.
|
||||
.\" 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 Winning Strategies, Inc.
|
||||
.\" 4. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD: src/bin/expr/expr.1,v 1.31 2011/07/09 12:05:53 se Exp $
|
||||
.\"
|
||||
.Dd September 9, 2010
|
||||
.Dt EXPR 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm expr
|
||||
.Nd evaluate expression
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Ar expression
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility evaluates
|
||||
.Ar expression
|
||||
and writes the result on standard output.
|
||||
.Pp
|
||||
All operators and operands must be passed as separate arguments.
|
||||
Several of the operators have special meaning to command interpreters
|
||||
and must therefore be quoted appropriately.
|
||||
All integer operands are interpreted in base 10 and must consist of only
|
||||
an optional leading minus sign followed by one or more digits.
|
||||
.Pp
|
||||
Arithmetic operations are performed using signed integer math with a
|
||||
range according to the C
|
||||
.Vt intmax_t
|
||||
data type (the largest signed integral type available).
|
||||
All conversions and operations are checked for overflow.
|
||||
Overflow results in program termination with an error message on stdout
|
||||
and with an error status.
|
||||
.Pp
|
||||
Operators are listed below in order of increasing precedence; all
|
||||
are left-associative.
|
||||
Operators with equal precedence are grouped within symbols
|
||||
.Ql {
|
||||
and
|
||||
.Ql } .
|
||||
.Bl -tag -width indent
|
||||
.It Ar expr1 Li | Ar expr2
|
||||
Return the evaluation of
|
||||
.Ar expr1
|
||||
if it is neither an empty string nor zero;
|
||||
otherwise, returns the evaluation of
|
||||
.Ar expr2
|
||||
if it is not an empty string;
|
||||
otherwise, returns zero.
|
||||
.It Ar expr1 Li & Ar expr2
|
||||
Return the evaluation of
|
||||
.Ar expr1
|
||||
if neither expression evaluates to an empty string or zero;
|
||||
otherwise, returns zero.
|
||||
.It Ar expr1 Li "{=, >, >=, <, <=, !=}" Ar expr2
|
||||
Return the results of integer comparison if both arguments are integers;
|
||||
otherwise, returns the results of string comparison using the locale-specific
|
||||
collation sequence.
|
||||
The result of each comparison is 1 if the specified relation is true,
|
||||
or 0 if the relation is false.
|
||||
.It Ar expr1 Li "{+, -}" Ar expr2
|
||||
Return the results of addition or subtraction of integer-valued arguments.
|
||||
.It Ar expr1 Li "{*, /, %}" Ar expr2
|
||||
Return the results of multiplication, integer division, or remainder of integer-valued arguments.
|
||||
.It Ar expr1 Li : Ar expr2
|
||||
The
|
||||
.Dq Li \&:
|
||||
operator matches
|
||||
.Ar expr1
|
||||
against
|
||||
.Ar expr2 ,
|
||||
which must be a basic regular expression.
|
||||
The regular expression is anchored
|
||||
to the beginning of the string with an implicit
|
||||
.Dq Li ^ .
|
||||
.Pp
|
||||
If the match succeeds and the pattern contains at least one regular
|
||||
expression subexpression
|
||||
.Dq Li "\e(...\e)" ,
|
||||
the string corresponding to
|
||||
.Dq Li \e1
|
||||
is returned;
|
||||
otherwise the matching operator returns the number of characters matched.
|
||||
If the match fails and the pattern contains a regular expression subexpression
|
||||
the null string is returned;
|
||||
otherwise 0.
|
||||
.El
|
||||
.Pp
|
||||
Parentheses are used for grouping in the usual manner.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility makes no lexical distinction between arguments which may be
|
||||
operators and arguments which may be operands.
|
||||
An operand which is lexically identical to an operator will be considered a
|
||||
syntax error.
|
||||
See the examples below for a work-around.
|
||||
.Pp
|
||||
The syntax of the
|
||||
.Nm
|
||||
command in general is historic and inconvenient.
|
||||
New applications are advised to use shell arithmetic rather than
|
||||
.Nm .
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
utility exits with one of the following values:
|
||||
.Bl -tag -width indent -compact
|
||||
.It 0
|
||||
the expression is neither an empty string nor 0.
|
||||
.It 1
|
||||
the expression is an empty string or 0.
|
||||
.It 2
|
||||
the expression is invalid.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
.Bl -bullet
|
||||
.It
|
||||
The following example (in
|
||||
.Xr sh 1
|
||||
syntax) adds one to the variable
|
||||
.Va a :
|
||||
.Dl "a=$(expr $a + 1)"
|
||||
.It
|
||||
This will fail if the value of
|
||||
.Va a
|
||||
is a negative number.
|
||||
To protect negative values of
|
||||
.Va a
|
||||
from being interpreted as options to the
|
||||
.Nm
|
||||
command, one might rearrange the expression:
|
||||
.Dl "a=$(expr 1 + $a)"
|
||||
.It
|
||||
More generally, parenthesize possibly-negative values:
|
||||
.Dl "a=$(expr \e( $a \e) + 1)"
|
||||
.It
|
||||
With shell arithmetic, no escaping is required:
|
||||
.Dl "a=$((a + 1))"
|
||||
.It
|
||||
This example prints the filename portion of a pathname stored
|
||||
in variable
|
||||
.Va a .
|
||||
Since
|
||||
.Va a
|
||||
might represent the path
|
||||
.Pa / ,
|
||||
it is necessary to prevent it from being interpreted as the division operator.
|
||||
The
|
||||
.Li //
|
||||
characters resolve this ambiguity.
|
||||
.Dl "expr \*q//$a\*q \&: '.*/\e(.*\e)'"
|
||||
.It
|
||||
With modern
|
||||
.Xr sh 1
|
||||
syntax,
|
||||
.Dl "\*q${a##*/}\*q"
|
||||
expands to the same value.
|
||||
.El
|
||||
.Pp
|
||||
The following examples output the number of characters in variable
|
||||
.Va a .
|
||||
Again, if
|
||||
.Va a
|
||||
might begin with a hyphen, it is necessary to prevent it from being
|
||||
interpreted as an option to
|
||||
.Nm ,
|
||||
and
|
||||
.Va a
|
||||
might be interpreted as an operator.
|
||||
.Bl -bullet
|
||||
.It
|
||||
To deal with all of this, a complicated command
|
||||
is required:
|
||||
.Dl "expr \e( \*qX$a\*q \&: \*q.*\*q \e) - 1"
|
||||
.It
|
||||
With modern
|
||||
.Xr sh 1
|
||||
syntax, this can be done much more easily:
|
||||
.Dl "${#a}"
|
||||
expands to the required number.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr sh 1 ,
|
||||
.Xr test 1
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility conforms to
|
||||
.St -p1003.1-2008 .
|
||||
.Pp
|
||||
The extended arithmetic range and overflow checks do not conflict with
|
||||
POSIX's requirement that arithmetic be done using signed longs, since
|
||||
they only make a difference to the result in cases where using signed
|
||||
longs would give undefined behavior.
|
||||
.Pp
|
||||
According to the
|
||||
.Tn POSIX
|
||||
standard, the use of string arguments
|
||||
.Va length ,
|
||||
.Va substr ,
|
||||
.Va index ,
|
||||
or
|
||||
.Va match
|
||||
produces undefined results. In this version of
|
||||
.Nm ,
|
||||
these arguments are treated just as their respective string values.
|
571
expr/expr.y
Normal file
571
expr/expr.y
Normal file
@ -0,0 +1,571 @@
|
||||
%{
|
||||
/*-
|
||||
* Written by Pace Willisson (pace@blitz.com)
|
||||
* and placed in the public domain.
|
||||
*
|
||||
* Largely rewritten by J.T. Conklin (jtc@wimsey.com)
|
||||
*
|
||||
* $FreeBSD: src/bin/expr/expr.y,v 1.28 2011/07/09 12:20:15 se Exp $
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* POSIX specifies a specific error code for syntax errors. We exit
|
||||
* with this code for all errors.
|
||||
*/
|
||||
#define ERR_EXIT 2
|
||||
|
||||
enum valtype {
|
||||
integer, numeric_string, string
|
||||
} ;
|
||||
|
||||
struct val {
|
||||
enum valtype type;
|
||||
union {
|
||||
char *s;
|
||||
intmax_t i;
|
||||
} u;
|
||||
} ;
|
||||
|
||||
char **av;
|
||||
int nonposix;
|
||||
struct val *result;
|
||||
|
||||
void assert_to_integer(struct val *);
|
||||
void assert_div(intmax_t, intmax_t);
|
||||
void assert_minus(intmax_t, intmax_t, intmax_t);
|
||||
void assert_plus(intmax_t, intmax_t, intmax_t);
|
||||
void assert_times(intmax_t, intmax_t, intmax_t);
|
||||
int compare_vals(struct val *, struct val *);
|
||||
void free_value(struct val *);
|
||||
int is_integer(const char *);
|
||||
int is_string(struct val *);
|
||||
int is_zero_or_null(struct val *);
|
||||
struct val *make_integer(intmax_t);
|
||||
struct val *make_str(const char *);
|
||||
struct val *op_and(struct val *, struct val *);
|
||||
struct val *op_colon(struct val *, struct val *);
|
||||
struct val *op_div(struct val *, struct val *);
|
||||
struct val *op_eq(struct val *, struct val *);
|
||||
struct val *op_ge(struct val *, struct val *);
|
||||
struct val *op_gt(struct val *, struct val *);
|
||||
struct val *op_le(struct val *, struct val *);
|
||||
struct val *op_lt(struct val *, struct val *);
|
||||
struct val *op_minus(struct val *, struct val *);
|
||||
struct val *op_ne(struct val *, struct val *);
|
||||
struct val *op_or(struct val *, struct val *);
|
||||
struct val *op_plus(struct val *, struct val *);
|
||||
struct val *op_rem(struct val *, struct val *);
|
||||
struct val *op_times(struct val *, struct val *);
|
||||
int to_integer(struct val *);
|
||||
void to_string(struct val *);
|
||||
int yyerror(const char *);
|
||||
int yylex(void);
|
||||
int yyparse(void);
|
||||
|
||||
%}
|
||||
|
||||
%union
|
||||
{
|
||||
struct val *val;
|
||||
}
|
||||
|
||||
%left <val> '|'
|
||||
%left <val> '&'
|
||||
%left <val> '=' '>' '<' GE LE NE
|
||||
%left <val> '+' '-'
|
||||
%left <val> '*' '/' '%'
|
||||
%left <val> ':'
|
||||
|
||||
%token <val> TOKEN
|
||||
%type <val> start expr
|
||||
|
||||
%%
|
||||
|
||||
start: expr { result = $$; }
|
||||
|
||||
expr: TOKEN
|
||||
| '(' expr ')' { $$ = $2; }
|
||||
| expr '|' expr { $$ = op_or($1, $3); }
|
||||
| expr '&' expr { $$ = op_and($1, $3); }
|
||||
| expr '=' expr { $$ = op_eq($1, $3); }
|
||||
| expr '>' expr { $$ = op_gt($1, $3); }
|
||||
| expr '<' expr { $$ = op_lt($1, $3); }
|
||||
| expr GE expr { $$ = op_ge($1, $3); }
|
||||
| expr LE expr { $$ = op_le($1, $3); }
|
||||
| expr NE expr { $$ = op_ne($1, $3); }
|
||||
| expr '+' expr { $$ = op_plus($1, $3); }
|
||||
| expr '-' expr { $$ = op_minus($1, $3); }
|
||||
| expr '*' expr { $$ = op_times($1, $3); }
|
||||
| expr '/' expr { $$ = op_div($1, $3); }
|
||||
| expr '%' expr { $$ = op_rem($1, $3); }
|
||||
| expr ':' expr { $$ = op_colon($1, $3); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
struct val *
|
||||
make_integer(intmax_t i)
|
||||
{
|
||||
struct val *vp;
|
||||
|
||||
vp = (struct val *)malloc(sizeof(*vp));
|
||||
if (vp == NULL)
|
||||
errx(ERR_EXIT, "malloc() failed");
|
||||
|
||||
vp->type = integer;
|
||||
vp->u.i = i;
|
||||
return (vp);
|
||||
}
|
||||
|
||||
struct val *
|
||||
make_str(const char *s)
|
||||
{
|
||||
struct val *vp;
|
||||
|
||||
vp = (struct val *)malloc(sizeof(*vp));
|
||||
if (vp == NULL || ((vp->u.s = strdup(s)) == NULL))
|
||||
errx(ERR_EXIT, "malloc() failed");
|
||||
|
||||
if (is_integer(s))
|
||||
vp->type = numeric_string;
|
||||
else
|
||||
vp->type = string;
|
||||
|
||||
return (vp);
|
||||
}
|
||||
|
||||
void
|
||||
free_value(struct val *vp)
|
||||
{
|
||||
if (vp->type == string || vp->type == numeric_string)
|
||||
free(vp->u.s);
|
||||
}
|
||||
|
||||
int
|
||||
to_integer(struct val *vp)
|
||||
{
|
||||
intmax_t i;
|
||||
|
||||
/* we can only convert numeric_string to integer, here */
|
||||
if (vp->type == numeric_string) {
|
||||
errno = 0;
|
||||
i = strtoimax(vp->u.s, (char **)NULL, 10);
|
||||
/* just keep as numeric_string, if the conversion fails */
|
||||
if (errno != ERANGE) {
|
||||
free(vp->u.s);
|
||||
vp->u.i = i;
|
||||
vp->type = integer;
|
||||
}
|
||||
}
|
||||
return (vp->type == integer);
|
||||
}
|
||||
|
||||
void
|
||||
assert_to_integer(struct val *vp)
|
||||
{
|
||||
if (vp->type == string)
|
||||
errx(ERR_EXIT, "not a decimal number: '%s'", vp->u.s);
|
||||
if (!to_integer(vp))
|
||||
errx(ERR_EXIT, "operand too large: '%s'", vp->u.s);
|
||||
}
|
||||
|
||||
void
|
||||
to_string(struct val *vp)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
if (vp->type == string || vp->type == numeric_string)
|
||||
return;
|
||||
|
||||
/*
|
||||
* log_10(x) ~= 0.3 * log_2(x). Rounding up gives the number
|
||||
* of digits; add one each for the sign and terminating null
|
||||
* character, respectively.
|
||||
*/
|
||||
#define NDIGITS(x) (3 * (sizeof(x) * CHAR_BIT) / 10 + 1 + 1 + 1)
|
||||
tmp = malloc(NDIGITS(vp->u.i));
|
||||
if (tmp == NULL)
|
||||
errx(ERR_EXIT, "malloc() failed");
|
||||
|
||||
sprintf(tmp, "%jd", vp->u.i);
|
||||
vp->type = string;
|
||||
vp->u.s = tmp;
|
||||
}
|
||||
|
||||
int
|
||||
is_integer(const char *s)
|
||||
{
|
||||
if (nonposix) {
|
||||
if (*s == '\0')
|
||||
return (1);
|
||||
while (isspace((unsigned char)*s))
|
||||
s++;
|
||||
}
|
||||
if (*s == '-' || (nonposix && *s == '+'))
|
||||
s++;
|
||||
if (*s == '\0')
|
||||
return (0);
|
||||
while (isdigit((unsigned char)*s))
|
||||
s++;
|
||||
return (*s == '\0');
|
||||
}
|
||||
|
||||
int
|
||||
is_string(struct val *vp)
|
||||
{
|
||||
/* only TRUE if this string is not a valid integer */
|
||||
return (vp->type == string);
|
||||
}
|
||||
|
||||
int
|
||||
yylex(void)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (*av == NULL)
|
||||
return (0);
|
||||
|
||||
p = *av++;
|
||||
|
||||
if (strlen(p) == 1) {
|
||||
if (strchr("|&=<>+-*/%:()", *p))
|
||||
return (*p);
|
||||
} else if (strlen(p) == 2 && p[1] == '=') {
|
||||
switch (*p) {
|
||||
case '>': return (GE);
|
||||
case '<': return (LE);
|
||||
case '!': return (NE);
|
||||
}
|
||||
}
|
||||
|
||||
yylval.val = make_str(p);
|
||||
return (TOKEN);
|
||||
}
|
||||
|
||||
int
|
||||
is_zero_or_null(struct val *vp)
|
||||
{
|
||||
if (vp->type == integer)
|
||||
return (vp->u.i == 0);
|
||||
|
||||
return (*vp->u.s == 0 || (to_integer(vp) && vp->u.i == 0));
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
#ifndef __APPLE__
|
||||
int c;
|
||||
#endif
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
#ifdef __APPLE__
|
||||
av = argv + 1;
|
||||
if (*av && !strcmp(*av, "--"))
|
||||
av++;
|
||||
#else
|
||||
if (getenv("EXPR_COMPAT") != NULL
|
||||
|| check_utility_compat("expr")) {
|
||||
av = argv + 1;
|
||||
nonposix = 1;
|
||||
} else {
|
||||
while ((c = getopt(argc, argv, "e")) != -1) {
|
||||
switch (c) {
|
||||
case 'e':
|
||||
nonposix = 1;
|
||||
break;
|
||||
default:
|
||||
errx(ERR_EXIT,
|
||||
"usage: expr [-e] expression\n");
|
||||
}
|
||||
}
|
||||
av = argv + optind;
|
||||
}
|
||||
#endif
|
||||
|
||||
yyparse();
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (to_integer(result))
|
||||
#else
|
||||
if (result->type == integer)
|
||||
#endif
|
||||
printf("%jd\n", result->u.i);
|
||||
else
|
||||
printf("%s\n", result->u.s);
|
||||
|
||||
return (is_zero_or_null(result));
|
||||
}
|
||||
|
||||
int
|
||||
yyerror(const char *s __unused)
|
||||
{
|
||||
errx(ERR_EXIT, "syntax error");
|
||||
}
|
||||
|
||||
struct val *
|
||||
op_or(struct val *a, struct val *b)
|
||||
{
|
||||
if (!is_zero_or_null(a)) {
|
||||
free_value(b);
|
||||
return (a);
|
||||
}
|
||||
free_value(a);
|
||||
if (!is_zero_or_null(b))
|
||||
return (b);
|
||||
free_value(b);
|
||||
return (make_integer((intmax_t)0));
|
||||
}
|
||||
|
||||
struct val *
|
||||
op_and(struct val *a, struct val *b)
|
||||
{
|
||||
if (is_zero_or_null(a) || is_zero_or_null(b)) {
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return (make_integer((intmax_t)0));
|
||||
} else {
|
||||
free_value(b);
|
||||
return (a);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
compare_vals(struct val *a, struct val *b)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (is_string(a) || is_string(b)) {
|
||||
to_string(a);
|
||||
to_string(b);
|
||||
r = strcoll(a->u.s, b->u.s);
|
||||
} else {
|
||||
assert_to_integer(a);
|
||||
assert_to_integer(b);
|
||||
if (a->u.i > b->u.i)
|
||||
r = 1;
|
||||
else if (a->u.i < b->u.i)
|
||||
r = -1;
|
||||
else
|
||||
r = 0;
|
||||
}
|
||||
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return (r);
|
||||
}
|
||||
|
||||
struct val *
|
||||
op_eq(struct val *a, struct val *b)
|
||||
{
|
||||
return (make_integer((intmax_t)(compare_vals(a, b) == 0)));
|
||||
}
|
||||
|
||||
struct val *
|
||||
op_gt(struct val *a, struct val *b)
|
||||
{
|
||||
return (make_integer((intmax_t)(compare_vals(a, b) > 0)));
|
||||
}
|
||||
|
||||
struct val *
|
||||
op_lt(struct val *a, struct val *b)
|
||||
{
|
||||
return (make_integer((intmax_t)(compare_vals(a, b) < 0)));
|
||||
}
|
||||
|
||||
struct val *
|
||||
op_ge(struct val *a, struct val *b)
|
||||
{
|
||||
return (make_integer((intmax_t)(compare_vals(a, b) >= 0)));
|
||||
}
|
||||
|
||||
struct val *
|
||||
op_le(struct val *a, struct val *b)
|
||||
{
|
||||
return (make_integer((intmax_t)(compare_vals(a, b) <= 0)));
|
||||
}
|
||||
|
||||
struct val *
|
||||
op_ne(struct val *a, struct val *b)
|
||||
{
|
||||
return (make_integer((intmax_t)(compare_vals(a, b) != 0)));
|
||||
}
|
||||
|
||||
void
|
||||
assert_plus(intmax_t a, intmax_t b, intmax_t r)
|
||||
{
|
||||
/*
|
||||
* sum of two positive numbers must be positive,
|
||||
* sum of two negative numbers must be negative
|
||||
*/
|
||||
if ((a > 0 && b > 0 && r <= 0) ||
|
||||
(a < 0 && b < 0 && r >= 0))
|
||||
errx(ERR_EXIT, "overflow");
|
||||
}
|
||||
|
||||
struct val *
|
||||
op_plus(struct val *a, struct val *b)
|
||||
{
|
||||
struct val *r;
|
||||
|
||||
assert_to_integer(a);
|
||||
assert_to_integer(b);
|
||||
r = make_integer(a->u.i + b->u.i);
|
||||
assert_plus(a->u.i, b->u.i, r->u.i);
|
||||
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return (r);
|
||||
}
|
||||
|
||||
void
|
||||
assert_minus(intmax_t a, intmax_t b, intmax_t r)
|
||||
{
|
||||
/* special case subtraction of INTMAX_MIN */
|
||||
if (b == INTMAX_MIN && a < 0)
|
||||
errx(ERR_EXIT, "overflow");
|
||||
/* check addition of negative subtrahend */
|
||||
assert_plus(a, -b, r);
|
||||
}
|
||||
|
||||
struct val *
|
||||
op_minus(struct val *a, struct val *b)
|
||||
{
|
||||
struct val *r;
|
||||
|
||||
assert_to_integer(a);
|
||||
assert_to_integer(b);
|
||||
r = make_integer(a->u.i - b->u.i);
|
||||
assert_minus(a->u.i, b->u.i, r->u.i);
|
||||
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return (r);
|
||||
}
|
||||
|
||||
void
|
||||
assert_times(intmax_t a, intmax_t b, intmax_t r)
|
||||
{
|
||||
/*
|
||||
* if first operand is 0, no overflow is possible,
|
||||
* else result of division test must match second operand
|
||||
*/
|
||||
if (a != 0 && r / a != b)
|
||||
errx(ERR_EXIT, "overflow");
|
||||
}
|
||||
|
||||
struct val *
|
||||
op_times(struct val *a, struct val *b)
|
||||
{
|
||||
struct val *r;
|
||||
|
||||
assert_to_integer(a);
|
||||
assert_to_integer(b);
|
||||
r = make_integer(a->u.i * b->u.i);
|
||||
assert_times(a->u.i, b->u.i, r->u.i);
|
||||
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return (r);
|
||||
}
|
||||
|
||||
void
|
||||
assert_div(intmax_t a, intmax_t b)
|
||||
{
|
||||
if (b == 0)
|
||||
errx(ERR_EXIT, "division by zero");
|
||||
/* only INTMAX_MIN / -1 causes overflow */
|
||||
if (a == INTMAX_MIN && b == -1)
|
||||
errx(ERR_EXIT, "overflow");
|
||||
}
|
||||
|
||||
struct val *
|
||||
op_div(struct val *a, struct val *b)
|
||||
{
|
||||
struct val *r;
|
||||
|
||||
assert_to_integer(a);
|
||||
assert_to_integer(b);
|
||||
/* assert based on operands only, not on result */
|
||||
assert_div(a->u.i, b->u.i);
|
||||
r = make_integer(a->u.i / b->u.i);
|
||||
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return (r);
|
||||
}
|
||||
|
||||
struct val *
|
||||
op_rem(struct val *a, struct val *b)
|
||||
{
|
||||
struct val *r;
|
||||
|
||||
assert_to_integer(a);
|
||||
assert_to_integer(b);
|
||||
/* pass a=1 to only check for div by zero */
|
||||
assert_div(1, b->u.i);
|
||||
r = make_integer(a->u.i % b->u.i);
|
||||
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return (r);
|
||||
}
|
||||
|
||||
struct val *
|
||||
op_colon(struct val *a, struct val *b)
|
||||
{
|
||||
regex_t rp;
|
||||
regmatch_t rm[2];
|
||||
char errbuf[256];
|
||||
int eval;
|
||||
struct val *v;
|
||||
|
||||
/* coerce both arguments to strings */
|
||||
to_string(a);
|
||||
to_string(b);
|
||||
|
||||
/* compile regular expression */
|
||||
if ((eval = regcomp(&rp, b->u.s, 0)) != 0) {
|
||||
regerror(eval, &rp, errbuf, sizeof(errbuf));
|
||||
errx(ERR_EXIT, "%s", errbuf);
|
||||
}
|
||||
|
||||
/* compare string against pattern */
|
||||
/* remember that patterns are anchored to the beginning of the line */
|
||||
if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0)
|
||||
if (rm[1].rm_so >= 0) {
|
||||
*(a->u.s + rm[1].rm_eo) = '\0';
|
||||
v = make_str(a->u.s + rm[1].rm_so);
|
||||
#ifdef __APPLE__
|
||||
v->type = string; /* 8319378 */
|
||||
#endif
|
||||
|
||||
} else
|
||||
v = make_integer((intmax_t)(rm[0].rm_eo - rm[0].rm_so));
|
||||
else
|
||||
if (rp.re_nsub == 0)
|
||||
v = make_integer((intmax_t)0);
|
||||
else
|
||||
v = make_str("");
|
||||
|
||||
/* free arguments and pattern buffer */
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
regfree(&rp);
|
||||
|
||||
return (v);
|
||||
}
|
60
false/false.1
Normal file
60
false/false.1
Normal file
@ -0,0 +1,60 @@
|
||||
.\" $NetBSD: false.1,v 1.5 1997/10/18 14:46:54 lukem Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1983, 1990 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.
|
||||
.\"
|
||||
.\" from: @(#)false.1 6.6 (Berkeley) 7/24/91
|
||||
.\" $NetBSD: false.1,v 1.5 1997/10/18 14:46:54 lukem Exp $
|
||||
.\"
|
||||
.Dd July 24, 1991
|
||||
.Dt FALSE 1
|
||||
.Os BSD 4.2
|
||||
.Sh NAME
|
||||
.Nm false
|
||||
.Nd Return false value.
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility always exits with a nonzero exit code.
|
||||
.Sh SEE ALSO
|
||||
.Xr csh 1 ,
|
||||
.Xr sh 1 ,
|
||||
.Xr true 1
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility conforms to
|
||||
.St -p1003.2-92 .
|
2
false/false.c
Normal file
2
false/false.c
Normal file
@ -0,0 +1,2 @@
|
||||
#include <stdlib.h>
|
||||
int main () { exit(1); }
|
2
false/false.sh
Normal file
2
false/false.sh
Normal file
@ -0,0 +1,2 @@
|
||||
#! /bin/sh
|
||||
exit 1
|
124
find/extern.h
Normal file
124
find/extern.h
Normal file
@ -0,0 +1,124 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 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.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.3 (Berkeley) 4/16/94
|
||||
* $FreeBSD: src/usr.bin/find/extern.h,v 1.26 2010/12/11 08:32:16 joel Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
void brace_subst(char *, char **, char *, int);
|
||||
PLAN *find_create(char ***);
|
||||
int find_execute(PLAN *, char **);
|
||||
PLAN *find_formplan(char **);
|
||||
PLAN *not_squish(PLAN *);
|
||||
PLAN *or_squish(PLAN *);
|
||||
PLAN *paren_squish(PLAN *);
|
||||
time_t get_date(char *);
|
||||
struct stat;
|
||||
void printlong(char *, char *, struct stat *);
|
||||
int queryuser(char **);
|
||||
OPTION *lookup_option(const char *);
|
||||
void finish_execplus(void);
|
||||
|
||||
creat_f c_Xmin;
|
||||
creat_f c_Xtime;
|
||||
creat_f c_acl;
|
||||
creat_f c_and;
|
||||
creat_f c_delete;
|
||||
creat_f c_depth;
|
||||
creat_f c_empty;
|
||||
creat_f c_exec;
|
||||
creat_f c_flags;
|
||||
creat_f c_follow;
|
||||
creat_f c_fstype;
|
||||
creat_f c_group;
|
||||
creat_f c_inum;
|
||||
creat_f c_links;
|
||||
creat_f c_ls;
|
||||
creat_f c_mXXdepth;
|
||||
creat_f c_name;
|
||||
creat_f c_newer;
|
||||
creat_f c_nogroup;
|
||||
creat_f c_nouser;
|
||||
creat_f c_perm;
|
||||
creat_f c_print;
|
||||
creat_f c_regex;
|
||||
creat_f c_samefile;
|
||||
creat_f c_simple;
|
||||
creat_f c_size;
|
||||
creat_f c_type;
|
||||
creat_f c_user;
|
||||
creat_f c_xdev;
|
||||
|
||||
exec_f f_Xmin;
|
||||
exec_f f_Xtime;
|
||||
exec_f f_acl;
|
||||
exec_f f_always_true;
|
||||
exec_f f_closeparen;
|
||||
exec_f f_delete;
|
||||
exec_f f_depth;
|
||||
exec_f f_empty;
|
||||
exec_f f_exec;
|
||||
exec_f f_expr;
|
||||
exec_f f_false;
|
||||
exec_f f_flags;
|
||||
exec_f f_fstype;
|
||||
exec_f f_group;
|
||||
exec_f f_inum;
|
||||
exec_f f_links;
|
||||
exec_f f_ls;
|
||||
exec_f f_name;
|
||||
exec_f f_newer;
|
||||
exec_f f_nogroup;
|
||||
exec_f f_not;
|
||||
exec_f f_nouser;
|
||||
exec_f f_openparen;
|
||||
exec_f f_or;
|
||||
exec_f f_path;
|
||||
exec_f f_perm;
|
||||
exec_f f_print;
|
||||
exec_f f_print0;
|
||||
exec_f f_prune;
|
||||
exec_f f_quit;
|
||||
exec_f f_regex;
|
||||
exec_f f_size;
|
||||
exec_f f_type;
|
||||
exec_f f_user;
|
||||
#ifdef __APPLE__
|
||||
exec_f f_xattr;
|
||||
exec_f f_xattrname;
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
extern int ftsoptions, isdeprecated, isdepth, isoutput, issort, isxargs;
|
||||
extern int mindepth, maxdepth;
|
||||
extern int regexp_flags;
|
||||
extern time_t now;
|
||||
extern int dotfd;
|
||||
extern FTS *tree;
|
||||
extern int execplus_error;
|
1078
find/find.1
Normal file
1078
find/find.1
Normal file
File diff suppressed because it is too large
Load Diff
323
find/find.c
Normal file
323
find/find.c
Normal file
@ -0,0 +1,323 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Cimarron D. Taylor of the University of California, Berkeley.
|
||||
*
|
||||
* 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.
|
||||
* 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
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)find.c 8.5 (Berkeley) 8/5/94";
|
||||
#else
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/usr.bin/find/find.c,v 1.23 2010/12/11 08:32:16 joel Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fts.h>
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <get_compat.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#define COMPAT_MODE(func, mode) 1
|
||||
#endif
|
||||
|
||||
#include "find.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
static int find_compare(const FTSENT **s1, const FTSENT **s2);
|
||||
#else /* !__APPLE__ */
|
||||
static int find_compare(const FTSENT * const *s1, const FTSENT * const *s2);
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
/*
|
||||
* find_compare --
|
||||
* tell fts_open() how to order the traversal of the hierarchy.
|
||||
* This variant gives lexicographical order, i.e., alphabetical
|
||||
* order within each directory.
|
||||
*/
|
||||
static int
|
||||
#ifdef __APPLE__
|
||||
find_compare(const FTSENT **s1, const FTSENT **s2)
|
||||
#else /* !__APPLE__ */
|
||||
find_compare(const FTSENT * const *s1, const FTSENT * const *s2)
|
||||
#endif /* __APPLE__ */
|
||||
{
|
||||
|
||||
return (strcoll((*s1)->fts_name, (*s2)->fts_name));
|
||||
}
|
||||
|
||||
/*
|
||||
* find_formplan --
|
||||
* process the command line and create a "plan" corresponding to the
|
||||
* command arguments.
|
||||
*/
|
||||
PLAN *
|
||||
find_formplan(char *argv[])
|
||||
{
|
||||
PLAN *plan, *tail, *new;
|
||||
|
||||
/*
|
||||
* for each argument in the command line, determine what kind of node
|
||||
* it is, create the appropriate node type and add the new plan node
|
||||
* to the end of the existing plan. The resulting plan is a linked
|
||||
* list of plan nodes. For example, the string:
|
||||
*
|
||||
* % find . -name foo -newer bar -print
|
||||
*
|
||||
* results in the plan:
|
||||
*
|
||||
* [-name foo]--> [-newer bar]--> [-print]
|
||||
*
|
||||
* in this diagram, `[-name foo]' represents the plan node generated
|
||||
* by c_name() with an argument of foo and `-->' represents the
|
||||
* plan->next pointer.
|
||||
*/
|
||||
for (plan = tail = NULL; *argv;) {
|
||||
if (!(new = find_create(&argv)))
|
||||
continue;
|
||||
if (plan == NULL)
|
||||
tail = plan = new;
|
||||
else {
|
||||
tail->next = new;
|
||||
tail = new;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if the user didn't specify one of -print, -ok or -exec, then -print
|
||||
* is assumed so we bracket the current expression with parens, if
|
||||
* necessary, and add a -print node on the end.
|
||||
*/
|
||||
if (!isoutput) {
|
||||
OPTION *p;
|
||||
char **argv1 = 0;
|
||||
|
||||
if (plan == NULL) {
|
||||
p = lookup_option("-print");
|
||||
new = (p->create)(p, &argv1);
|
||||
tail = plan = new;
|
||||
} else {
|
||||
p = lookup_option("(");
|
||||
new = (p->create)(p, &argv1);
|
||||
new->next = plan;
|
||||
plan = new;
|
||||
p = lookup_option(")");
|
||||
new = (p->create)(p, &argv1);
|
||||
tail->next = new;
|
||||
tail = new;
|
||||
p = lookup_option("-print");
|
||||
new = (p->create)(p, &argv1);
|
||||
tail->next = new;
|
||||
tail = new;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* the command line has been completely processed into a search plan
|
||||
* except for the (, ), !, and -o operators. Rearrange the plan so
|
||||
* that the portions of the plan which are affected by the operators
|
||||
* are moved into operator nodes themselves. For example:
|
||||
*
|
||||
* [!]--> [-name foo]--> [-print]
|
||||
*
|
||||
* becomes
|
||||
*
|
||||
* [! [-name foo] ]--> [-print]
|
||||
*
|
||||
* and
|
||||
*
|
||||
* [(]--> [-depth]--> [-name foo]--> [)]--> [-print]
|
||||
*
|
||||
* becomes
|
||||
*
|
||||
* [expr [-depth]-->[-name foo] ]--> [-print]
|
||||
*
|
||||
* operators are handled in order of precedence.
|
||||
*/
|
||||
|
||||
plan = paren_squish(plan); /* ()'s */
|
||||
plan = not_squish(plan); /* !'s */
|
||||
plan = or_squish(plan); /* -o's */
|
||||
return (plan);
|
||||
}
|
||||
|
||||
/* addPath - helper function used to build a list of paths that were
|
||||
* specified on the command line that we are allowed to search.
|
||||
*/
|
||||
static char **addPath(char **array, char *newPath)
|
||||
{
|
||||
static int pathCounter = 0;
|
||||
|
||||
if (newPath == NULL) { /* initialize array */
|
||||
if ((array = malloc(sizeof(char *))) == NULL)
|
||||
err(2, "out of memory");
|
||||
array[0] = NULL;
|
||||
}
|
||||
else {
|
||||
array = realloc(array, (++pathCounter + 1) * sizeof(char *));
|
||||
if (array == NULL)
|
||||
err(2, "out of memory");
|
||||
else {
|
||||
array[pathCounter - 1] = newPath;
|
||||
array[pathCounter] = NULL; /* ensure array is null terminated */
|
||||
}
|
||||
}
|
||||
return (array);
|
||||
}
|
||||
|
||||
FTS *tree; /* pointer to top of FTS hierarchy */
|
||||
|
||||
/*
|
||||
* find_execute --
|
||||
* take a search plan and an array of search paths and executes the plan
|
||||
* over all FTSENT's returned for the given search paths.
|
||||
*/
|
||||
int
|
||||
find_execute(PLAN *plan, char *paths[])
|
||||
{
|
||||
FTSENT *entry;
|
||||
PLAN *p;
|
||||
int rval;
|
||||
char **myPaths;
|
||||
int nonSearchableDirFound = 0;
|
||||
int pathIndex;
|
||||
struct stat statInfo;
|
||||
|
||||
/* special-case directories specified on command line - explicitly examine
|
||||
* mode bits, to ensure failure if the directory cannot be searched
|
||||
* (whether or not it's empty). UNIX conformance... <sigh>
|
||||
*/
|
||||
|
||||
int strict_symlinks = (ftsoptions & (FTS_COMFOLLOW|FTS_LOGICAL))
|
||||
&& COMPAT_MODE("bin/find", "unix2003");
|
||||
|
||||
myPaths = addPath(NULL, NULL);
|
||||
for (pathIndex = 0; paths[pathIndex] != NULL; ++pathIndex) {
|
||||
int stat_ret = stat(paths[pathIndex], &statInfo);
|
||||
int stat_errno = errno;
|
||||
if (strict_symlinks && stat_ret < 0) {
|
||||
if (stat_errno == ELOOP) {
|
||||
errx(1, "Symlink loop resolving %s", paths[pathIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
/* retrieve mode bits, and examine "searchable" bit of
|
||||
directories, exempt root from POSIX conformance */
|
||||
if (COMPAT_MODE("bin/find", "unix2003") && getuid()
|
||||
&& stat_ret == 0
|
||||
&& ((statInfo.st_mode & S_IFMT) == S_IFDIR)) {
|
||||
if (access(paths[pathIndex], X_OK) == 0) {
|
||||
myPaths = addPath(myPaths, paths[pathIndex]);
|
||||
} else {
|
||||
if (stat_errno != ENAMETOOLONG) { /* if name is too long, just let existing logic handle it */
|
||||
warnx("%s: Permission denied", paths[pathIndex]);
|
||||
nonSearchableDirFound = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* not a directory, so add path to array */
|
||||
myPaths = addPath(myPaths, paths[pathIndex]);
|
||||
}
|
||||
}
|
||||
if (myPaths[0] == NULL) { /* were any directories searchable? */
|
||||
free(myPaths);
|
||||
return(nonSearchableDirFound); /* no... */
|
||||
}
|
||||
|
||||
tree = fts_open(myPaths, ftsoptions, (issort ? find_compare : NULL));
|
||||
if (tree == NULL)
|
||||
err(1, "ftsopen");
|
||||
|
||||
for (rval = nonSearchableDirFound; (entry = fts_read(tree)) != NULL;) {
|
||||
if (maxdepth != -1 && entry->fts_level >= maxdepth) {
|
||||
if (fts_set(tree, entry, FTS_SKIP))
|
||||
err(1, "%s", entry->fts_path);
|
||||
}
|
||||
|
||||
switch (entry->fts_info) {
|
||||
case FTS_D:
|
||||
if (isdepth)
|
||||
continue;
|
||||
break;
|
||||
case FTS_DP:
|
||||
if (!isdepth)
|
||||
continue;
|
||||
break;
|
||||
case FTS_DNR:
|
||||
case FTS_ERR:
|
||||
case FTS_NS:
|
||||
(void)fflush(stdout);
|
||||
warnx("%s: %s",
|
||||
entry->fts_path, strerror(entry->fts_errno));
|
||||
rval = 1;
|
||||
continue;
|
||||
#ifdef FTS_W
|
||||
case FTS_W:
|
||||
continue;
|
||||
#endif /* FTS_W */
|
||||
}
|
||||
#define BADCH " \t\n\\'\""
|
||||
if (isxargs && strpbrk(entry->fts_path, BADCH)) {
|
||||
(void)fflush(stdout);
|
||||
warnx("%s: illegal path", entry->fts_path);
|
||||
rval = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mindepth != -1 && entry->fts_level < mindepth)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Call all the functions in the execution plan until one is
|
||||
* false or all have been executed. This is where we do all
|
||||
* the work specified by the user on the command line.
|
||||
*/
|
||||
for (p = plan; p && (p->execute)(p, entry); p = p->next);
|
||||
}
|
||||
free (myPaths);
|
||||
finish_execplus();
|
||||
if (execplus_error) {
|
||||
exit(execplus_error);
|
||||
}
|
||||
if (errno)
|
||||
err(1, "fts_read");
|
||||
fts_close(tree);
|
||||
return (rval);
|
||||
}
|
145
find/find.h
Normal file
145
find/find.h
Normal file
@ -0,0 +1,145 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Cimarron D. Taylor of the University of California, Berkeley.
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @(#)find.h 8.1 (Berkeley) 6/6/93
|
||||
* $FreeBSD: src/usr.bin/find/find.h,v 1.21 2010/12/11 08:32:16 joel Exp $
|
||||
*/
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
/* forward declarations */
|
||||
struct _plandata;
|
||||
struct _option;
|
||||
|
||||
/* execute function */
|
||||
typedef int exec_f(struct _plandata *, FTSENT *);
|
||||
/* create function */
|
||||
typedef struct _plandata *creat_f(struct _option *, char ***);
|
||||
|
||||
/* function modifiers */
|
||||
#define F_NEEDOK 0x00000001 /* -ok vs. -exec */
|
||||
#define F_EXECDIR 0x00000002 /* -execdir vs. -exec */
|
||||
#define F_TIME_A 0x00000004 /* one of -atime, -anewer, -newera* */
|
||||
#define F_TIME_C 0x00000008 /* one of -ctime, -cnewer, -newerc* */
|
||||
#define F_TIME2_A 0x00000010 /* one of -newer?a */
|
||||
#define F_TIME2_C 0x00000020 /* one of -newer?c */
|
||||
#define F_TIME2_T 0x00000040 /* one of -newer?t */
|
||||
#define F_MAXDEPTH F_TIME_A /* maxdepth vs. mindepth */
|
||||
#define F_DEPTH F_TIME_A /* -depth n vs. -d */
|
||||
/* command line function modifiers */
|
||||
#define F_EQUAL 0x00000000 /* [acm]min [acm]time inum links size */
|
||||
#define F_LESSTHAN 0x00000100
|
||||
#define F_GREATER 0x00000200
|
||||
#define F_ELG_MASK 0x00000300
|
||||
#define F_ATLEAST 0x00000400 /* flags perm */
|
||||
#define F_ANY 0x00000800 /* perm */
|
||||
#define F_MTMASK 0x00003000
|
||||
#define F_MTFLAG 0x00000000 /* fstype */
|
||||
#define F_MTTYPE 0x00001000
|
||||
#define F_MTUNKNOWN 0x00002000
|
||||
#define F_IGNCASE 0x00010000 /* iname ipath iregex */
|
||||
#define F_EXACTTIME F_IGNCASE /* -[acm]time units syntax */
|
||||
#define F_EXECPLUS 0x00020000 /* -exec ... {} + */
|
||||
#define F_TIME_B 0x00040000 /* one of -Btime, -Bnewer, -newerB* */
|
||||
#define F_TIME2_B 0x00080000 /* one of -newer?B */
|
||||
#define F_LINK 0x00100000 /* lname or ilname */
|
||||
|
||||
/* node definition */
|
||||
typedef struct _plandata {
|
||||
struct _plandata *next; /* next node */
|
||||
exec_f *execute; /* node evaluation function */
|
||||
int flags; /* private flags */
|
||||
union {
|
||||
gid_t _g_data; /* gid */
|
||||
ino_t _i_data; /* inode */
|
||||
mode_t _m_data; /* mode mask */
|
||||
struct {
|
||||
u_long _f_flags;
|
||||
u_long _f_notflags;
|
||||
} fl;
|
||||
nlink_t _l_data; /* link count */
|
||||
short _d_data; /* level depth (-1 to N) */
|
||||
off_t _o_data; /* file size */
|
||||
time_t _t_data; /* time value */
|
||||
uid_t _u_data; /* uid */
|
||||
short _mt_data; /* mount flags */
|
||||
struct _plandata *_p_data[2]; /* PLAN trees */
|
||||
struct _ex {
|
||||
char **_e_argv; /* argv array */
|
||||
char **_e_orig; /* original strings */
|
||||
int *_e_len; /* allocated length */
|
||||
int _e_pbnum; /* base num. of args. used */
|
||||
int _e_ppos; /* number of arguments used */
|
||||
int _e_pnummax; /* max. number of arguments */
|
||||
int _e_psize; /* number of bytes of args. */
|
||||
int _e_pbsize; /* base num. of bytes of args */
|
||||
int _e_psizemax; /* max num. of bytes of args */
|
||||
struct _plandata *_e_next;/* next F_EXECPLUS in tree */
|
||||
} ex;
|
||||
char *_a_data[2]; /* array of char pointers */
|
||||
char *_c_data; /* char pointer */
|
||||
regex_t *_re_data; /* regex */
|
||||
} p_un;
|
||||
} PLAN;
|
||||
#define a_data p_un._a_data
|
||||
#define c_data p_un._c_data
|
||||
#define d_data p_un._d_data
|
||||
#define fl_flags p_un.fl._f_flags
|
||||
#define fl_notflags p_un.fl._f_notflags
|
||||
#define g_data p_un._g_data
|
||||
#define i_data p_un._i_data
|
||||
#define l_data p_un._l_data
|
||||
#define m_data p_un._m_data
|
||||
#define mt_data p_un._mt_data
|
||||
#define o_data p_un._o_data
|
||||
#define p_data p_un._p_data
|
||||
#define t_data p_un._t_data
|
||||
#define u_data p_un._u_data
|
||||
#define re_data p_un._re_data
|
||||
#define e_argv p_un.ex._e_argv
|
||||
#define e_orig p_un.ex._e_orig
|
||||
#define e_len p_un.ex._e_len
|
||||
#define e_pbnum p_un.ex._e_pbnum
|
||||
#define e_ppos p_un.ex._e_ppos
|
||||
#define e_pnummax p_un.ex._e_pnummax
|
||||
#define e_psize p_un.ex._e_psize
|
||||
#define e_pbsize p_un.ex._e_pbsize
|
||||
#define e_psizemax p_un.ex._e_psizemax
|
||||
#define e_next p_un.ex._e_next
|
||||
|
||||
typedef struct _option {
|
||||
const char *name; /* option name */
|
||||
creat_f *create; /* create function */
|
||||
exec_f *execute; /* execute function */
|
||||
int flags;
|
||||
} OPTION;
|
||||
|
||||
#include "extern.h"
|
30
find/find.plist.part
Normal file
30
find/find.plist.part
Normal file
@ -0,0 +1,30 @@
|
||||
<dict>
|
||||
<key>OpenSourceProject</key>
|
||||
<string>find</string>
|
||||
<key>OpenSourceVersion</key>
|
||||
<string>2011-12-10</string>
|
||||
<key>OpenSourceWebsiteURL</key>
|
||||
<string>http://svnweb.freebsd.org/base/head/usr.bin/find/</string>
|
||||
<key>OpenSourceSCM</key>
|
||||
<string>svn co http://svn.freebsd.org/base/head/usr.bin/find/</string>
|
||||
<key>OpenSourceImportDate</key>
|
||||
<string>2012-01-06</string>
|
||||
<key>OpenSourceModifications</key>
|
||||
<array>
|
||||
<string>Add -xattr and -xattrname options.</string>
|
||||
<string>execplus conformance fixes.</string>
|
||||
<string>Man page fix (4772561).</string>
|
||||
<string>Adjust FTS usage due to API differences.</string>
|
||||
<string>Avoid searching unsearchable directories (3849245).</string>
|
||||
<string>Add missing call to fts_close (4608460).</string>
|
||||
<string>Conformance fixes related to F_EXACTTIME.</string>
|
||||
<string>Apple-specific implementation of -acl primary.</string>
|
||||
<string>Conformance fix for f_name (6591280).</string>
|
||||
<string>setmode conformance fix (3936046).</string>
|
||||
<string>Use a saner MAXLOGNAME definition.</string>
|
||||
<string>Workaround for lack of rpmatch function.</string>
|
||||
<string>FreeBSD revisions 260336, 260355.</string>
|
||||
</array>
|
||||
<key>OpenSourceLicense</key>
|
||||
<string>bsd</string>
|
||||
</dict>
|
1772
find/function.c
Normal file
1772
find/function.c
Normal file
File diff suppressed because it is too large
Load Diff
961
find/getdate.y
Normal file
961
find/getdate.y
Normal file
@ -0,0 +1,961 @@
|
||||
%{
|
||||
/*
|
||||
** Originally written by Steven M. Bellovin <smb@research.att.com> while
|
||||
** at the University of North Carolina at Chapel Hill. Later tweaked by
|
||||
** a couple of people on Usenet. Completely overhauled by Rich $alz
|
||||
** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
|
||||
**
|
||||
** This grammar has 10 shift/reduce conflicts.
|
||||
**
|
||||
** This code is in the public domain and has no copyright.
|
||||
*/
|
||||
/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
|
||||
/* SUPPRESS 288 on yyerrlab *//* Label unused */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/usr.bin/find/getdate.y,v 1.7 2010/02/09 21:24:41 ed Exp $");
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* The code at the top of get_date which figures out the offset of the
|
||||
current time zone checks various CPP symbols to see if special
|
||||
tricks are need, but defaults to using the gettimeofday system call.
|
||||
Include <sys/time.h> if that will be used. */
|
||||
|
||||
#if defined(vms)
|
||||
# include <types.h>
|
||||
#else /* defined(vms) */
|
||||
# include <sys/types.h>
|
||||
# include <sys/time.h>
|
||||
#endif /* !defined(vms) */
|
||||
|
||||
#if defined (__STDC__) || defined (USG)
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/* Some old versions of bison generate parsers that use bcopy.
|
||||
That loses on systems that don't provide the function, so we have
|
||||
to redefine it here. */
|
||||
#if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
|
||||
#define bcopy(from, to, len) memcpy ((to), (from), (len))
|
||||
#endif
|
||||
|
||||
#if defined (__STDC__)
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/* NOTES on rebuilding getdate.c (particularly for inclusion in CVS
|
||||
releases):
|
||||
|
||||
We don't want to mess with all the portability hassles of alloca.
|
||||
In particular, most (all?) versions of bison will use alloca in
|
||||
their parser. If bison works on your system (e.g. it should work
|
||||
with gcc), then go ahead and use it, but the more general solution
|
||||
is to use byacc instead of bison, which should generate a portable
|
||||
parser. I played with adding "#define alloca dont_use_alloca", to
|
||||
give an error if the parser generator uses alloca (and thus detect
|
||||
unportable getdate.c's), but that seems to cause as many problems
|
||||
as it solves. */
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define yyparse getdate_yyparse
|
||||
#define yylex getdate_yylex
|
||||
#define yyerror getdate_yyerror
|
||||
|
||||
static int yyparse(void);
|
||||
static int yylex(void);
|
||||
static int yyerror(const char *);
|
||||
|
||||
time_t get_date(char *);
|
||||
|
||||
#define EPOCH 1970
|
||||
#define HOUR(x) ((time_t)(x) * 60)
|
||||
#define SECSPERDAY (24L * 60L * 60L)
|
||||
|
||||
|
||||
/*
|
||||
** An entry in the lexical lookup table.
|
||||
*/
|
||||
typedef struct _TABLE {
|
||||
const char *name;
|
||||
int type;
|
||||
time_t value;
|
||||
} TABLE;
|
||||
|
||||
|
||||
/*
|
||||
** Daylight-savings mode: on, off, or not yet known.
|
||||
*/
|
||||
typedef enum _DSTMODE {
|
||||
DSTon, DSToff, DSTmaybe
|
||||
} DSTMODE;
|
||||
|
||||
/*
|
||||
** Meridian: am, pm, or 24-hour style.
|
||||
*/
|
||||
typedef enum _MERIDIAN {
|
||||
MERam, MERpm, MER24
|
||||
} MERIDIAN;
|
||||
|
||||
|
||||
/*
|
||||
** Global variables. We could get rid of most of these by using a good
|
||||
** union as the yacc stack. (This routine was originally written before
|
||||
** yacc had the %union construct.) Maybe someday; right now we only use
|
||||
** the %union very rarely.
|
||||
*/
|
||||
static char *yyInput;
|
||||
static DSTMODE yyDSTmode;
|
||||
static time_t yyDayOrdinal;
|
||||
static time_t yyDayNumber;
|
||||
static int yyHaveDate;
|
||||
static int yyHaveDay;
|
||||
static int yyHaveRel;
|
||||
static int yyHaveTime;
|
||||
static int yyHaveZone;
|
||||
static time_t yyTimezone;
|
||||
static time_t yyDay;
|
||||
static time_t yyHour;
|
||||
static time_t yyMinutes;
|
||||
static time_t yyMonth;
|
||||
static time_t yySeconds;
|
||||
static time_t yyYear;
|
||||
static MERIDIAN yyMeridian;
|
||||
static time_t yyRelMonth;
|
||||
static time_t yyRelSeconds;
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
time_t Number;
|
||||
enum _MERIDIAN Meridian;
|
||||
}
|
||||
|
||||
%token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
|
||||
%token tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST
|
||||
|
||||
%type <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
|
||||
%type <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE
|
||||
%type <Meridian> tMERIDIAN o_merid
|
||||
|
||||
%%
|
||||
|
||||
spec : /* NULL */
|
||||
| spec item
|
||||
;
|
||||
|
||||
item : time {
|
||||
yyHaveTime++;
|
||||
}
|
||||
| zone {
|
||||
yyHaveZone++;
|
||||
}
|
||||
| date {
|
||||
yyHaveDate++;
|
||||
}
|
||||
| day {
|
||||
yyHaveDay++;
|
||||
}
|
||||
| rel {
|
||||
yyHaveRel++;
|
||||
}
|
||||
| number
|
||||
;
|
||||
|
||||
time : tUNUMBER tMERIDIAN {
|
||||
yyHour = $1;
|
||||
yyMinutes = 0;
|
||||
yySeconds = 0;
|
||||
yyMeridian = $2;
|
||||
}
|
||||
| tUNUMBER ':' tUNUMBER o_merid {
|
||||
yyHour = $1;
|
||||
yyMinutes = $3;
|
||||
yySeconds = 0;
|
||||
yyMeridian = $4;
|
||||
}
|
||||
| tUNUMBER ':' tUNUMBER tSNUMBER {
|
||||
yyHour = $1;
|
||||
yyMinutes = $3;
|
||||
yyMeridian = MER24;
|
||||
yyDSTmode = DSToff;
|
||||
yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
|
||||
}
|
||||
| tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
|
||||
yyHour = $1;
|
||||
yyMinutes = $3;
|
||||
yySeconds = $5;
|
||||
yyMeridian = $6;
|
||||
}
|
||||
| tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
|
||||
yyHour = $1;
|
||||
yyMinutes = $3;
|
||||
yySeconds = $5;
|
||||
yyMeridian = MER24;
|
||||
yyDSTmode = DSToff;
|
||||
yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
|
||||
}
|
||||
;
|
||||
|
||||
zone : tZONE {
|
||||
yyTimezone = $1;
|
||||
yyDSTmode = DSToff;
|
||||
}
|
||||
| tDAYZONE {
|
||||
yyTimezone = $1;
|
||||
yyDSTmode = DSTon;
|
||||
}
|
||||
|
|
||||
tZONE tDST {
|
||||
yyTimezone = $1;
|
||||
yyDSTmode = DSTon;
|
||||
}
|
||||
;
|
||||
|
||||
day : tDAY {
|
||||
yyDayOrdinal = 1;
|
||||
yyDayNumber = $1;
|
||||
}
|
||||
| tDAY ',' {
|
||||
yyDayOrdinal = 1;
|
||||
yyDayNumber = $1;
|
||||
}
|
||||
| tUNUMBER tDAY {
|
||||
yyDayOrdinal = $1;
|
||||
yyDayNumber = $2;
|
||||
}
|
||||
;
|
||||
|
||||
date : tUNUMBER '/' tUNUMBER {
|
||||
yyMonth = $1;
|
||||
yyDay = $3;
|
||||
}
|
||||
| tUNUMBER '/' tUNUMBER '/' tUNUMBER {
|
||||
if ($1 >= 100) {
|
||||
yyYear = $1;
|
||||
yyMonth = $3;
|
||||
yyDay = $5;
|
||||
} else {
|
||||
yyMonth = $1;
|
||||
yyDay = $3;
|
||||
yyYear = $5;
|
||||
}
|
||||
}
|
||||
| tUNUMBER tSNUMBER tSNUMBER {
|
||||
/* ISO 8601 format. yyyy-mm-dd. */
|
||||
yyYear = $1;
|
||||
yyMonth = -$2;
|
||||
yyDay = -$3;
|
||||
}
|
||||
| tUNUMBER tMONTH tSNUMBER {
|
||||
/* e.g. 17-JUN-1992. */
|
||||
yyDay = $1;
|
||||
yyMonth = $2;
|
||||
yyYear = -$3;
|
||||
}
|
||||
| tMONTH tUNUMBER {
|
||||
yyMonth = $1;
|
||||
yyDay = $2;
|
||||
}
|
||||
| tMONTH tUNUMBER ',' tUNUMBER {
|
||||
yyMonth = $1;
|
||||
yyDay = $2;
|
||||
yyYear = $4;
|
||||
}
|
||||
| tUNUMBER tMONTH {
|
||||
yyMonth = $2;
|
||||
yyDay = $1;
|
||||
}
|
||||
| tUNUMBER tMONTH tUNUMBER {
|
||||
yyMonth = $2;
|
||||
yyDay = $1;
|
||||
yyYear = $3;
|
||||
}
|
||||
;
|
||||
|
||||
rel : relunit tAGO {
|
||||
yyRelSeconds = -yyRelSeconds;
|
||||
yyRelMonth = -yyRelMonth;
|
||||
}
|
||||
| relunit
|
||||
;
|
||||
|
||||
relunit : tUNUMBER tMINUTE_UNIT {
|
||||
yyRelSeconds += $1 * $2 * 60L;
|
||||
}
|
||||
| tSNUMBER tMINUTE_UNIT {
|
||||
yyRelSeconds += $1 * $2 * 60L;
|
||||
}
|
||||
| tMINUTE_UNIT {
|
||||
yyRelSeconds += $1 * 60L;
|
||||
}
|
||||
| tSNUMBER tSEC_UNIT {
|
||||
yyRelSeconds += $1;
|
||||
}
|
||||
| tUNUMBER tSEC_UNIT {
|
||||
yyRelSeconds += $1;
|
||||
}
|
||||
| tSEC_UNIT {
|
||||
yyRelSeconds++;
|
||||
}
|
||||
| tSNUMBER tMONTH_UNIT {
|
||||
yyRelMonth += $1 * $2;
|
||||
}
|
||||
| tUNUMBER tMONTH_UNIT {
|
||||
yyRelMonth += $1 * $2;
|
||||
}
|
||||
| tMONTH_UNIT {
|
||||
yyRelMonth += $1;
|
||||
}
|
||||
;
|
||||
|
||||
number : tUNUMBER {
|
||||
if (yyHaveTime && yyHaveDate && !yyHaveRel)
|
||||
yyYear = $1;
|
||||
else {
|
||||
if($1>10000) {
|
||||
yyHaveDate++;
|
||||
yyDay= ($1)%100;
|
||||
yyMonth= ($1/100)%100;
|
||||
yyYear = $1/10000;
|
||||
}
|
||||
else {
|
||||
yyHaveTime++;
|
||||
if ($1 < 100) {
|
||||
yyHour = $1;
|
||||
yyMinutes = 0;
|
||||
}
|
||||
else {
|
||||
yyHour = $1 / 100;
|
||||
yyMinutes = $1 % 100;
|
||||
}
|
||||
yySeconds = 0;
|
||||
yyMeridian = MER24;
|
||||
}
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
o_merid : /* NULL */ {
|
||||
$$ = MER24;
|
||||
}
|
||||
| tMERIDIAN {
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
/* Month and day table. */
|
||||
static TABLE const MonthDayTable[] = {
|
||||
{ "january", tMONTH, 1 },
|
||||
{ "february", tMONTH, 2 },
|
||||
{ "march", tMONTH, 3 },
|
||||
{ "april", tMONTH, 4 },
|
||||
{ "may", tMONTH, 5 },
|
||||
{ "june", tMONTH, 6 },
|
||||
{ "july", tMONTH, 7 },
|
||||
{ "august", tMONTH, 8 },
|
||||
{ "september", tMONTH, 9 },
|
||||
{ "sept", tMONTH, 9 },
|
||||
{ "october", tMONTH, 10 },
|
||||
{ "november", tMONTH, 11 },
|
||||
{ "december", tMONTH, 12 },
|
||||
{ "sunday", tDAY, 0 },
|
||||
{ "monday", tDAY, 1 },
|
||||
{ "tuesday", tDAY, 2 },
|
||||
{ "tues", tDAY, 2 },
|
||||
{ "wednesday", tDAY, 3 },
|
||||
{ "wednes", tDAY, 3 },
|
||||
{ "thursday", tDAY, 4 },
|
||||
{ "thur", tDAY, 4 },
|
||||
{ "thurs", tDAY, 4 },
|
||||
{ "friday", tDAY, 5 },
|
||||
{ "saturday", tDAY, 6 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
/* Time units table. */
|
||||
static TABLE const UnitsTable[] = {
|
||||
{ "year", tMONTH_UNIT, 12 },
|
||||
{ "month", tMONTH_UNIT, 1 },
|
||||
{ "fortnight", tMINUTE_UNIT, 14 * 24 * 60 },
|
||||
{ "week", tMINUTE_UNIT, 7 * 24 * 60 },
|
||||
{ "day", tMINUTE_UNIT, 1 * 24 * 60 },
|
||||
{ "hour", tMINUTE_UNIT, 60 },
|
||||
{ "minute", tMINUTE_UNIT, 1 },
|
||||
{ "min", tMINUTE_UNIT, 1 },
|
||||
{ "second", tSEC_UNIT, 1 },
|
||||
{ "sec", tSEC_UNIT, 1 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
/* Assorted relative-time words. */
|
||||
static TABLE const OtherTable[] = {
|
||||
{ "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 },
|
||||
{ "yesterday", tMINUTE_UNIT, -1 * 24 * 60 },
|
||||
{ "today", tMINUTE_UNIT, 0 },
|
||||
{ "now", tMINUTE_UNIT, 0 },
|
||||
{ "last", tUNUMBER, -1 },
|
||||
{ "this", tMINUTE_UNIT, 0 },
|
||||
{ "next", tUNUMBER, 2 },
|
||||
{ "first", tUNUMBER, 1 },
|
||||
/* { "second", tUNUMBER, 2 }, */
|
||||
{ "third", tUNUMBER, 3 },
|
||||
{ "fourth", tUNUMBER, 4 },
|
||||
{ "fifth", tUNUMBER, 5 },
|
||||
{ "sixth", tUNUMBER, 6 },
|
||||
{ "seventh", tUNUMBER, 7 },
|
||||
{ "eighth", tUNUMBER, 8 },
|
||||
{ "ninth", tUNUMBER, 9 },
|
||||
{ "tenth", tUNUMBER, 10 },
|
||||
{ "eleventh", tUNUMBER, 11 },
|
||||
{ "twelfth", tUNUMBER, 12 },
|
||||
{ "ago", tAGO, 1 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
/* The timezone table. */
|
||||
/* Some of these are commented out because a time_t can't store a float. */
|
||||
static TABLE const TimezoneTable[] = {
|
||||
{ "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
|
||||
{ "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
|
||||
{ "utc", tZONE, HOUR( 0) },
|
||||
{ "wet", tZONE, HOUR( 0) }, /* Western European */
|
||||
{ "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
|
||||
{ "wat", tZONE, HOUR( 1) }, /* West Africa */
|
||||
{ "at", tZONE, HOUR( 2) }, /* Azores */
|
||||
#if 0
|
||||
/* For completeness. BST is also British Summer, and GST is
|
||||
* also Guam Standard. */
|
||||
{ "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
|
||||
{ "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
|
||||
#endif
|
||||
#if 0
|
||||
{ "nft", tZONE, HOUR(3.5) }, /* Newfoundland */
|
||||
{ "nst", tZONE, HOUR(3.5) }, /* Newfoundland Standard */
|
||||
{ "ndt", tDAYZONE, HOUR(3.5) }, /* Newfoundland Daylight */
|
||||
#endif
|
||||
{ "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
|
||||
{ "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
|
||||
{ "est", tZONE, HOUR( 5) }, /* Eastern Standard */
|
||||
{ "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
|
||||
{ "cst", tZONE, HOUR( 6) }, /* Central Standard */
|
||||
{ "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
|
||||
{ "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
|
||||
{ "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
|
||||
{ "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
|
||||
{ "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
|
||||
{ "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
|
||||
{ "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
|
||||
{ "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
|
||||
{ "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
|
||||
{ "cat", tZONE, HOUR(10) }, /* Central Alaska */
|
||||
{ "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
|
||||
{ "nt", tZONE, HOUR(11) }, /* Nome */
|
||||
{ "idlw", tZONE, HOUR(12) }, /* International Date Line West */
|
||||
{ "cet", tZONE, -HOUR(1) }, /* Central European */
|
||||
{ "met", tZONE, -HOUR(1) }, /* Middle European */
|
||||
{ "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
|
||||
{ "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
|
||||
{ "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
|
||||
{ "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
|
||||
{ "fwt", tZONE, -HOUR(1) }, /* French Winter */
|
||||
{ "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
|
||||
{ "eet", tZONE, -HOUR(2) }, /* Eastern Europe, USSR Zone 1 */
|
||||
{ "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */
|
||||
#if 0
|
||||
{ "it", tZONE, -HOUR(3.5) },/* Iran */
|
||||
#endif
|
||||
{ "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
|
||||
{ "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
|
||||
#if 0
|
||||
{ "ist", tZONE, -HOUR(5.5) },/* Indian Standard */
|
||||
#endif
|
||||
{ "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
|
||||
#if 0
|
||||
/* For completeness. NST is also Newfoundland Stanard, and SST is
|
||||
* also Swedish Summer. */
|
||||
{ "nst", tZONE, -HOUR(6.5) },/* North Sumatra */
|
||||
{ "sst", tZONE, -HOUR(7) }, /* South Sumatra, USSR Zone 6 */
|
||||
#endif /* 0 */
|
||||
{ "wast", tZONE, -HOUR(7) }, /* West Australian Standard */
|
||||
{ "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */
|
||||
#if 0
|
||||
{ "jt", tZONE, -HOUR(7.5) },/* Java (3pm in Cronusland!) */
|
||||
#endif
|
||||
{ "cct", tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */
|
||||
{ "jst", tZONE, -HOUR(9) }, /* Japan Standard, USSR Zone 8 */
|
||||
#if 0
|
||||
{ "cast", tZONE, -HOUR(9.5) },/* Central Australian Standard */
|
||||
{ "cadt", tDAYZONE, -HOUR(9.5) },/* Central Australian Daylight */
|
||||
#endif
|
||||
{ "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
|
||||
{ "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
|
||||
{ "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
|
||||
{ "nzt", tZONE, -HOUR(12) }, /* New Zealand */
|
||||
{ "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
|
||||
{ "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
|
||||
{ "idle", tZONE, -HOUR(12) }, /* International Date Line East */
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
/* Military timezone table. */
|
||||
static TABLE const MilitaryTable[] = {
|
||||
{ "a", tZONE, HOUR( 1) },
|
||||
{ "b", tZONE, HOUR( 2) },
|
||||
{ "c", tZONE, HOUR( 3) },
|
||||
{ "d", tZONE, HOUR( 4) },
|
||||
{ "e", tZONE, HOUR( 5) },
|
||||
{ "f", tZONE, HOUR( 6) },
|
||||
{ "g", tZONE, HOUR( 7) },
|
||||
{ "h", tZONE, HOUR( 8) },
|
||||
{ "i", tZONE, HOUR( 9) },
|
||||
{ "k", tZONE, HOUR( 10) },
|
||||
{ "l", tZONE, HOUR( 11) },
|
||||
{ "m", tZONE, HOUR( 12) },
|
||||
{ "n", tZONE, HOUR(- 1) },
|
||||
{ "o", tZONE, HOUR(- 2) },
|
||||
{ "p", tZONE, HOUR(- 3) },
|
||||
{ "q", tZONE, HOUR(- 4) },
|
||||
{ "r", tZONE, HOUR(- 5) },
|
||||
{ "s", tZONE, HOUR(- 6) },
|
||||
{ "t", tZONE, HOUR(- 7) },
|
||||
{ "u", tZONE, HOUR(- 8) },
|
||||
{ "v", tZONE, HOUR(- 9) },
|
||||
{ "w", tZONE, HOUR(-10) },
|
||||
{ "x", tZONE, HOUR(-11) },
|
||||
{ "y", tZONE, HOUR(-12) },
|
||||
{ "z", tZONE, HOUR( 0) },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
yyerror(const char *s __unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static time_t
|
||||
ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
|
||||
{
|
||||
if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
|
||||
return -1;
|
||||
switch (Meridian) {
|
||||
case MER24:
|
||||
if (Hours < 0 || Hours > 23)
|
||||
return -1;
|
||||
return (Hours * 60L + Minutes) * 60L + Seconds;
|
||||
case MERam:
|
||||
if (Hours < 1 || Hours > 12)
|
||||
return -1;
|
||||
if (Hours == 12)
|
||||
Hours = 0;
|
||||
return (Hours * 60L + Minutes) * 60L + Seconds;
|
||||
case MERpm:
|
||||
if (Hours < 1 || Hours > 12)
|
||||
return -1;
|
||||
if (Hours == 12)
|
||||
Hours = 0;
|
||||
return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
|
||||
/* Year is either
|
||||
* A negative number, which means to use its absolute value (why?)
|
||||
* A number from 0 to 99, which means a year from 1900 to 1999, or
|
||||
* The actual year (>=100). */
|
||||
static time_t
|
||||
Convert(time_t Month, time_t Day, time_t Year,
|
||||
time_t Hours, time_t Minutes, time_t Seconds,
|
||||
MERIDIAN Meridian, DSTMODE DSTmode)
|
||||
{
|
||||
static int DaysInMonth[12] = {
|
||||
31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||||
};
|
||||
time_t tod;
|
||||
time_t Julian;
|
||||
int i;
|
||||
|
||||
if (Year < 0)
|
||||
Year = -Year;
|
||||
if (Year < 69)
|
||||
Year += 2000;
|
||||
else if (Year < 100)
|
||||
Year += 1900;
|
||||
DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
|
||||
? 29 : 28;
|
||||
/* Checking for 2038 bogusly assumes that time_t is 32 bits. But
|
||||
I'm too lazy to try to check for time_t overflow in another way. */
|
||||
if (Year < EPOCH || Year > 2038
|
||||
|| Month < 1 || Month > 12
|
||||
/* Lint fluff: "conversion from long may lose accuracy" */
|
||||
|| Day < 1 || Day > DaysInMonth[(int)--Month])
|
||||
return -1;
|
||||
|
||||
for (Julian = Day - 1, i = 0; i < Month; i++)
|
||||
Julian += DaysInMonth[i];
|
||||
for (i = EPOCH; i < Year; i++)
|
||||
Julian += 365 + (i % 4 == 0);
|
||||
Julian *= SECSPERDAY;
|
||||
Julian += yyTimezone * 60L;
|
||||
if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
|
||||
return -1;
|
||||
Julian += tod;
|
||||
if (DSTmode == DSTon
|
||||
|| (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
|
||||
Julian -= 60 * 60;
|
||||
return Julian;
|
||||
}
|
||||
|
||||
|
||||
static time_t
|
||||
DSTcorrect(time_t Start, time_t Future)
|
||||
{
|
||||
time_t StartDay;
|
||||
time_t FutureDay;
|
||||
|
||||
StartDay = (localtime(&Start)->tm_hour + 1) % 24;
|
||||
FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
|
||||
return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
|
||||
}
|
||||
|
||||
|
||||
static time_t
|
||||
RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber)
|
||||
{
|
||||
struct tm *tm;
|
||||
time_t now;
|
||||
|
||||
now = Start;
|
||||
tm = localtime(&now);
|
||||
now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
|
||||
now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
|
||||
return DSTcorrect(Start, now);
|
||||
}
|
||||
|
||||
|
||||
static time_t
|
||||
RelativeMonth(time_t Start, time_t RelMonth)
|
||||
{
|
||||
struct tm *tm;
|
||||
time_t Month;
|
||||
time_t Year;
|
||||
|
||||
if (RelMonth == 0)
|
||||
return 0;
|
||||
tm = localtime(&Start);
|
||||
Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth;
|
||||
Year = Month / 12;
|
||||
Month = Month % 12 + 1;
|
||||
return DSTcorrect(Start,
|
||||
Convert(Month, (time_t)tm->tm_mday, Year,
|
||||
(time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
|
||||
MER24, DSTmaybe));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
LookupWord(char *buff)
|
||||
{
|
||||
char *p;
|
||||
char *q;
|
||||
const TABLE *tp;
|
||||
int i;
|
||||
int abbrev;
|
||||
|
||||
/* Make it lowercase. */
|
||||
for (p = buff; *p; p++)
|
||||
if (isupper(*p))
|
||||
*p = tolower(*p);
|
||||
|
||||
if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
|
||||
yylval.Meridian = MERam;
|
||||
return tMERIDIAN;
|
||||
}
|
||||
if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
|
||||
yylval.Meridian = MERpm;
|
||||
return tMERIDIAN;
|
||||
}
|
||||
|
||||
/* See if we have an abbreviation for a month. */
|
||||
if (strlen(buff) == 3)
|
||||
abbrev = 1;
|
||||
else if (strlen(buff) == 4 && buff[3] == '.') {
|
||||
abbrev = 1;
|
||||
buff[3] = '\0';
|
||||
}
|
||||
else
|
||||
abbrev = 0;
|
||||
|
||||
for (tp = MonthDayTable; tp->name; tp++) {
|
||||
if (abbrev) {
|
||||
if (strncmp(buff, tp->name, 3) == 0) {
|
||||
yylval.Number = tp->value;
|
||||
return tp->type;
|
||||
}
|
||||
}
|
||||
else if (strcmp(buff, tp->name) == 0) {
|
||||
yylval.Number = tp->value;
|
||||
return tp->type;
|
||||
}
|
||||
}
|
||||
|
||||
for (tp = TimezoneTable; tp->name; tp++)
|
||||
if (strcmp(buff, tp->name) == 0) {
|
||||
yylval.Number = tp->value;
|
||||
return tp->type;
|
||||
}
|
||||
|
||||
if (strcmp(buff, "dst") == 0)
|
||||
return tDST;
|
||||
|
||||
for (tp = UnitsTable; tp->name; tp++)
|
||||
if (strcmp(buff, tp->name) == 0) {
|
||||
yylval.Number = tp->value;
|
||||
return tp->type;
|
||||
}
|
||||
|
||||
/* Strip off any plural and try the units table again. */
|
||||
i = strlen(buff) - 1;
|
||||
if (buff[i] == 's') {
|
||||
buff[i] = '\0';
|
||||
for (tp = UnitsTable; tp->name; tp++)
|
||||
if (strcmp(buff, tp->name) == 0) {
|
||||
yylval.Number = tp->value;
|
||||
return tp->type;
|
||||
}
|
||||
buff[i] = 's'; /* Put back for "this" in OtherTable. */
|
||||
}
|
||||
|
||||
for (tp = OtherTable; tp->name; tp++)
|
||||
if (strcmp(buff, tp->name) == 0) {
|
||||
yylval.Number = tp->value;
|
||||
return tp->type;
|
||||
}
|
||||
|
||||
/* Military timezones. */
|
||||
if (buff[1] == '\0' && isalpha(*buff)) {
|
||||
for (tp = MilitaryTable; tp->name; tp++)
|
||||
if (strcmp(buff, tp->name) == 0) {
|
||||
yylval.Number = tp->value;
|
||||
return tp->type;
|
||||
}
|
||||
}
|
||||
|
||||
/* Drop out any periods and try the timezone table again. */
|
||||
for (i = 0, p = q = buff; *q; q++)
|
||||
if (*q != '.')
|
||||
*p++ = *q;
|
||||
else
|
||||
i++;
|
||||
*p = '\0';
|
||||
if (i)
|
||||
for (tp = TimezoneTable; tp->name; tp++)
|
||||
if (strcmp(buff, tp->name) == 0) {
|
||||
yylval.Number = tp->value;
|
||||
return tp->type;
|
||||
}
|
||||
|
||||
return tID;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
yylex(void)
|
||||
{
|
||||
char c;
|
||||
char *p;
|
||||
char buff[20];
|
||||
int Count;
|
||||
int sign;
|
||||
|
||||
for ( ; ; ) {
|
||||
while (isspace(*yyInput))
|
||||
yyInput++;
|
||||
|
||||
if (isdigit(c = *yyInput) || c == '-' || c == '+') {
|
||||
if (c == '-' || c == '+') {
|
||||
sign = c == '-' ? -1 : 1;
|
||||
if (!isdigit(*++yyInput))
|
||||
/* skip the '-' sign */
|
||||
continue;
|
||||
}
|
||||
else
|
||||
sign = 0;
|
||||
for (yylval.Number = 0; isdigit(c = *yyInput++); )
|
||||
yylval.Number = 10 * yylval.Number + c - '0';
|
||||
yyInput--;
|
||||
if (sign < 0)
|
||||
yylval.Number = -yylval.Number;
|
||||
return sign ? tSNUMBER : tUNUMBER;
|
||||
}
|
||||
if (isalpha(c)) {
|
||||
for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
|
||||
if (p < &buff[sizeof buff - 1])
|
||||
*p++ = c;
|
||||
*p = '\0';
|
||||
yyInput--;
|
||||
return LookupWord(buff);
|
||||
}
|
||||
if (c != '(')
|
||||
return *yyInput++;
|
||||
Count = 0;
|
||||
do {
|
||||
c = *yyInput++;
|
||||
if (c == '\0')
|
||||
return c;
|
||||
if (c == '(')
|
||||
Count++;
|
||||
else if (c == ')')
|
||||
Count--;
|
||||
} while (Count > 0);
|
||||
}
|
||||
}
|
||||
|
||||
#define TM_YEAR_ORIGIN 1900
|
||||
|
||||
/* Yield A - B, measured in seconds. */
|
||||
static long
|
||||
difftm (struct tm *a, struct tm *b)
|
||||
{
|
||||
int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
|
||||
int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
|
||||
int days = (
|
||||
/* difference in day of year */
|
||||
a->tm_yday - b->tm_yday
|
||||
/* + intervening leap days */
|
||||
+ ((ay >> 2) - (by >> 2))
|
||||
- (ay/100 - by/100)
|
||||
+ ((ay/100 >> 2) - (by/100 >> 2))
|
||||
/* + difference in years * 365 */
|
||||
+ (long)(ay-by) * 365
|
||||
);
|
||||
return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
|
||||
+ (a->tm_min - b->tm_min))
|
||||
+ (a->tm_sec - b->tm_sec));
|
||||
}
|
||||
|
||||
time_t
|
||||
get_date(char *p)
|
||||
{
|
||||
struct tm *tm, *gmt_ptr, gmt;
|
||||
int tzoff;
|
||||
time_t Start;
|
||||
time_t tod;
|
||||
time_t nowtime;
|
||||
|
||||
bzero (&gmt, sizeof(struct tm));
|
||||
yyInput = p;
|
||||
|
||||
(void)time (&nowtime);
|
||||
|
||||
gmt_ptr = gmtime (&nowtime);
|
||||
if (gmt_ptr != NULL)
|
||||
{
|
||||
/* Make a copy, in case localtime modifies *tm (I think
|
||||
that comment now applies to *gmt_ptr, but I am too
|
||||
lazy to dig into how gmtime and locatime allocate the
|
||||
structures they return pointers to). */
|
||||
gmt = *gmt_ptr;
|
||||
}
|
||||
|
||||
if (! (tm = localtime (&nowtime)))
|
||||
return -1;
|
||||
|
||||
if (gmt_ptr != NULL)
|
||||
tzoff = difftm (&gmt, tm) / 60;
|
||||
else
|
||||
/* We are on a system like VMS, where the system clock is
|
||||
in local time and the system has no concept of timezones.
|
||||
Hopefully we can fake this out (for the case in which the
|
||||
user specifies no timezone) by just saying the timezone
|
||||
is zero. */
|
||||
tzoff = 0;
|
||||
|
||||
if(tm->tm_isdst)
|
||||
tzoff += 60;
|
||||
|
||||
tm = localtime(&nowtime);
|
||||
yyYear = tm->tm_year + 1900;
|
||||
yyMonth = tm->tm_mon + 1;
|
||||
yyDay = tm->tm_mday;
|
||||
yyTimezone = tzoff;
|
||||
yyDSTmode = DSTmaybe;
|
||||
yyHour = 0;
|
||||
yyMinutes = 0;
|
||||
yySeconds = 0;
|
||||
yyMeridian = MER24;
|
||||
yyRelSeconds = 0;
|
||||
yyRelMonth = 0;
|
||||
yyHaveDate = 0;
|
||||
yyHaveDay = 0;
|
||||
yyHaveRel = 0;
|
||||
yyHaveTime = 0;
|
||||
yyHaveZone = 0;
|
||||
|
||||
if (yyparse()
|
||||
|| yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
|
||||
return -1;
|
||||
|
||||
if (yyHaveDate || yyHaveTime || yyHaveDay) {
|
||||
Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
|
||||
yyMeridian, yyDSTmode);
|
||||
if (Start < 0)
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
Start = nowtime;
|
||||
if (!yyHaveRel)
|
||||
Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
|
||||
}
|
||||
|
||||
Start += yyRelSeconds;
|
||||
Start += RelativeMonth(Start, yyRelMonth);
|
||||
|
||||
if (yyHaveDay && !yyHaveDate) {
|
||||
tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
|
||||
Start += tod;
|
||||
}
|
||||
|
||||
/* Have to do *something* with a legitimate -1 so it's distinguishable
|
||||
* from the error return value. (Alternately could set errno on error.) */
|
||||
return Start == -1 ? 0 : Start;
|
||||
}
|
||||
|
||||
|
||||
#if defined(TEST)
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
main(int ac, char *av[])
|
||||
{
|
||||
char buff[128];
|
||||
time_t d;
|
||||
|
||||
(void)printf("Enter date, or blank line to exit.\n\t> ");
|
||||
(void)fflush(stdout);
|
||||
while (gets(buff) && buff[0]) {
|
||||
d = get_date(buff);
|
||||
if (d == -1)
|
||||
(void)printf("Bad format - couldn't convert.\n");
|
||||
else
|
||||
(void)printf("%s", ctime(&d));
|
||||
(void)printf("\t> ");
|
||||
(void)fflush(stdout);
|
||||
}
|
||||
exit(0);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#endif /* defined(TEST) */
|
124
find/ls.c
Normal file
124
find/ls.c
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)ls.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/usr.bin/find/ls.c,v 1.23 2011/09/28 18:53:36 ed Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fts.h>
|
||||
#include <grp.h>
|
||||
#include <inttypes.h>
|
||||
#include <langinfo.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#undef MAXLOGNAME
|
||||
#define MAXLOGNAME 17
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#include "find.h"
|
||||
|
||||
/* Derived from the print routines in the ls(1) source code. */
|
||||
|
||||
static void printlink(char *);
|
||||
static void printtime(time_t);
|
||||
|
||||
void
|
||||
printlong(char *name, char *accpath, struct stat *sb)
|
||||
{
|
||||
char modep[15];
|
||||
|
||||
(void)printf("%6lu %8"PRId64" ", (u_long) sb->st_ino, sb->st_blocks);
|
||||
(void)strmode(sb->st_mode, modep);
|
||||
(void)printf("%s %3u %-*s %-*s ", modep, sb->st_nlink, MAXLOGNAME - 1,
|
||||
user_from_uid(sb->st_uid, 0), MAXLOGNAME - 1,
|
||||
group_from_gid(sb->st_gid, 0));
|
||||
|
||||
if (S_ISCHR(sb->st_mode) || S_ISBLK(sb->st_mode))
|
||||
(void)printf("%#8jx ", (uintmax_t)sb->st_rdev);
|
||||
else
|
||||
(void)printf("%8"PRId64" ", sb->st_size);
|
||||
printtime(sb->st_mtime);
|
||||
(void)printf("%s", name);
|
||||
if (S_ISLNK(sb->st_mode))
|
||||
printlink(accpath);
|
||||
(void)putchar('\n');
|
||||
}
|
||||
|
||||
static void
|
||||
printtime(time_t ftime)
|
||||
{
|
||||
char longstring[80];
|
||||
static time_t lnow;
|
||||
const char *format;
|
||||
static int d_first = -1;
|
||||
|
||||
if (d_first < 0)
|
||||
d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
|
||||
if (lnow == 0)
|
||||
lnow = time(NULL);
|
||||
|
||||
#define SIXMONTHS ((365 / 2) * 86400)
|
||||
if (ftime + SIXMONTHS > lnow && ftime < lnow + SIXMONTHS)
|
||||
/* mmm dd hh:mm || dd mmm hh:mm */
|
||||
format = d_first ? "%e %b %R " : "%b %e %R ";
|
||||
else
|
||||
/* mmm dd yyyy || dd mmm yyyy */
|
||||
format = d_first ? "%e %b %Y " : "%b %e %Y ";
|
||||
strftime(longstring, sizeof(longstring), format, localtime(&ftime));
|
||||
fputs(longstring, stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
printlink(char *name)
|
||||
{
|
||||
int lnklen;
|
||||
char path[MAXPATHLEN];
|
||||
|
||||
if ((lnklen = readlink(name, path, MAXPATHLEN - 1)) == -1) {
|
||||
warn("%s", name);
|
||||
return;
|
||||
}
|
||||
path[lnklen] = '\0';
|
||||
(void)printf(" -> %s", path);
|
||||
}
|
166
find/main.c
Normal file
166
find/main.c
Normal file
@ -0,0 +1,166 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Cimarron D. Taylor of the University of California, Berkeley.
|
||||
*
|
||||
* 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.
|
||||
* 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 const char copyright[] =
|
||||
"@(#) Copyright (c) 1990, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/usr.bin/find/main.c,v 1.23 2011/12/10 18:11:06 ed Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fts.h>
|
||||
#include <locale.h>
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "find.h"
|
||||
|
||||
time_t now; /* time find was run */
|
||||
int dotfd; /* starting directory */
|
||||
int ftsoptions; /* options for the ftsopen(3) call */
|
||||
int isdeprecated; /* using deprecated syntax */
|
||||
int isdepth; /* do directories on post-order visit */
|
||||
int isoutput; /* user specified output operator */
|
||||
int issort; /* do hierarchies in lexicographical order */
|
||||
int isxargs; /* don't permit xargs delimiting chars */
|
||||
int mindepth = -1, maxdepth = -1; /* minimum and maximum depth */
|
||||
int regexp_flags = REG_BASIC; /* use the "basic" regexp by default*/
|
||||
|
||||
static void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char **p, **start;
|
||||
int Hflag, Lflag, ch;
|
||||
|
||||
(void)setlocale(LC_ALL, "");
|
||||
|
||||
(void)time(&now); /* initialize the time-of-day */
|
||||
|
||||
p = start = argv;
|
||||
Hflag = Lflag = 0;
|
||||
ftsoptions = FTS_NOSTAT | FTS_PHYSICAL;
|
||||
while ((ch = getopt(argc, argv, "EHLPXdf:sx")) != -1)
|
||||
switch (ch) {
|
||||
case 'E':
|
||||
regexp_flags |= REG_EXTENDED;
|
||||
break;
|
||||
case 'H':
|
||||
Hflag = 1;
|
||||
Lflag = 0;
|
||||
break;
|
||||
case 'L':
|
||||
Lflag = 1;
|
||||
Hflag = 0;
|
||||
break;
|
||||
case 'P':
|
||||
Hflag = Lflag = 0;
|
||||
break;
|
||||
case 'X':
|
||||
isxargs = 1;
|
||||
break;
|
||||
case 'd':
|
||||
isdepth = 1;
|
||||
break;
|
||||
case 'f':
|
||||
*p++ = optarg;
|
||||
break;
|
||||
case 's':
|
||||
issort = 1;
|
||||
break;
|
||||
case 'x':
|
||||
ftsoptions |= FTS_XDEV;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (Hflag)
|
||||
ftsoptions |= FTS_COMFOLLOW;
|
||||
if (Lflag) {
|
||||
ftsoptions &= ~FTS_PHYSICAL;
|
||||
ftsoptions |= FTS_LOGICAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find first option to delimit the file list. The first argument
|
||||
* that starts with a -, or is a ! or a ( must be interpreted as a
|
||||
* part of the find expression, according to POSIX .2.
|
||||
*/
|
||||
for (; *argv != NULL; *p++ = *argv++) {
|
||||
if (argv[0][0] == '-')
|
||||
break;
|
||||
if ((argv[0][0] == '!' || argv[0][0] == '(') &&
|
||||
argv[0][1] == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
if (p == start)
|
||||
usage();
|
||||
*p = NULL;
|
||||
|
||||
if ((dotfd = open(".", O_RDONLY, 0)) < 0)
|
||||
err(1, ".");
|
||||
|
||||
exit(find_execute(find_formplan(argv), start));
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr, "%s\n%s\n",
|
||||
"usage: find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]",
|
||||
" find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]");
|
||||
exit(1);
|
||||
}
|
109
find/misc.c
Normal file
109
find/misc.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Cimarron D. Taylor of the University of California, Berkeley.
|
||||
*
|
||||
* 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.
|
||||
* 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
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)misc.c 8.2 (Berkeley) 4/1/94";
|
||||
#else
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/usr.bin/find/misc.c,v 1.13 2010/12/11 08:32:16 joel Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fts.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "find.h"
|
||||
|
||||
/*
|
||||
* brace_subst --
|
||||
* Replace occurrences of {} in s1 with s2 and return the result string.
|
||||
*/
|
||||
void
|
||||
brace_subst(char *orig, char **store, char *path, int len)
|
||||
{
|
||||
int plen;
|
||||
char ch, *p;
|
||||
|
||||
plen = strlen(path);
|
||||
for (p = *store; (ch = *orig) != '\0'; ++orig)
|
||||
if (ch == '{' && orig[1] == '}') {
|
||||
while ((p - *store) + plen > len)
|
||||
if (!(*store = realloc(*store, len *= 2)))
|
||||
err(1, NULL);
|
||||
memmove(p, path, plen);
|
||||
p += plen;
|
||||
++orig;
|
||||
} else
|
||||
*p++ = ch;
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* queryuser --
|
||||
* print a message to standard error and then read input from standard
|
||||
* input. If the input is an affirmative response (according to the
|
||||
* current locale) then 1 is returned.
|
||||
*/
|
||||
int
|
||||
queryuser(char *argv[])
|
||||
{
|
||||
char *p, resp[256];
|
||||
|
||||
(void)fprintf(stderr, "\"%s", *argv);
|
||||
while (*++argv)
|
||||
(void)fprintf(stderr, " %s", *argv);
|
||||
(void)fprintf(stderr, "\"? ");
|
||||
(void)fflush(stderr);
|
||||
|
||||
if (fgets(resp, sizeof(resp), stdin) == NULL)
|
||||
*resp = '\0';
|
||||
if ((p = strchr(resp, '\n')) != NULL)
|
||||
*p = '\0';
|
||||
else {
|
||||
(void)fprintf(stderr, "\n");
|
||||
(void)fflush(stderr);
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
return (resp[0] == 'y');
|
||||
#else
|
||||
return (rpmatch(resp) == 1);
|
||||
#endif
|
||||
}
|
273
find/operator.c
Normal file
273
find/operator.c
Normal file
@ -0,0 +1,273 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Cimarron D. Taylor of the University of California, Berkeley.
|
||||
*
|
||||
* 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.
|
||||
* 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
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)operator.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/usr.bin/find/operator.c,v 1.17 2010/12/11 08:32:16 joel Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <fts.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "find.h"
|
||||
|
||||
static PLAN *yanknode(PLAN **);
|
||||
static PLAN *yankexpr(PLAN **);
|
||||
|
||||
/*
|
||||
* yanknode --
|
||||
* destructively removes the top from the plan
|
||||
*/
|
||||
static PLAN *
|
||||
yanknode(PLAN **planp)
|
||||
{
|
||||
PLAN *node; /* top node removed from the plan */
|
||||
|
||||
if ((node = (*planp)) == NULL)
|
||||
return (NULL);
|
||||
(*planp) = (*planp)->next;
|
||||
node->next = NULL;
|
||||
return (node);
|
||||
}
|
||||
|
||||
/*
|
||||
* yankexpr --
|
||||
* Removes one expression from the plan. This is used mainly by
|
||||
* paren_squish. In comments below, an expression is either a
|
||||
* simple node or a f_expr node containing a list of simple nodes.
|
||||
*/
|
||||
static PLAN *
|
||||
yankexpr(PLAN **planp)
|
||||
{
|
||||
PLAN *next; /* temp node holding subexpression results */
|
||||
PLAN *node; /* pointer to returned node or expression */
|
||||
PLAN *tail; /* pointer to tail of subplan */
|
||||
PLAN *subplan; /* pointer to head of ( ) expression */
|
||||
|
||||
/* first pull the top node from the plan */
|
||||
if ((node = yanknode(planp)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* If the node is an '(' then we recursively slurp up expressions
|
||||
* until we find its associated ')'. If it's a closing paren we
|
||||
* just return it and unwind our recursion; all other nodes are
|
||||
* complete expressions, so just return them.
|
||||
*/
|
||||
if (node->execute == f_openparen)
|
||||
for (tail = subplan = NULL;;) {
|
||||
if ((next = yankexpr(planp)) == NULL)
|
||||
errx(1, "(: missing closing ')'");
|
||||
/*
|
||||
* If we find a closing ')' we store the collected
|
||||
* subplan in our '(' node and convert the node to
|
||||
* a f_expr. The ')' we found is ignored. Otherwise,
|
||||
* we just continue to add whatever we get to our
|
||||
* subplan.
|
||||
*/
|
||||
if (next->execute == f_closeparen) {
|
||||
if (subplan == NULL)
|
||||
errx(1, "(): empty inner expression");
|
||||
node->p_data[0] = subplan;
|
||||
node->execute = f_expr;
|
||||
break;
|
||||
} else {
|
||||
if (subplan == NULL)
|
||||
tail = subplan = next;
|
||||
else {
|
||||
tail->next = next;
|
||||
tail = next;
|
||||
}
|
||||
tail->next = NULL;
|
||||
}
|
||||
}
|
||||
return (node);
|
||||
}
|
||||
|
||||
/*
|
||||
* paren_squish --
|
||||
* replaces "parenthesized" plans in our search plan with "expr" nodes.
|
||||
*/
|
||||
PLAN *
|
||||
paren_squish(PLAN *plan)
|
||||
{
|
||||
PLAN *expr; /* pointer to next expression */
|
||||
PLAN *tail; /* pointer to tail of result plan */
|
||||
PLAN *result; /* pointer to head of result plan */
|
||||
|
||||
result = tail = NULL;
|
||||
|
||||
/*
|
||||
* the basic idea is to have yankexpr do all our work and just
|
||||
* collect its results together.
|
||||
*/
|
||||
while ((expr = yankexpr(&plan)) != NULL) {
|
||||
/*
|
||||
* if we find an unclaimed ')' it means there is a missing
|
||||
* '(' someplace.
|
||||
*/
|
||||
if (expr->execute == f_closeparen)
|
||||
errx(1, "): no beginning '('");
|
||||
|
||||
/* add the expression to our result plan */
|
||||
if (result == NULL)
|
||||
tail = result = expr;
|
||||
else {
|
||||
tail->next = expr;
|
||||
tail = expr;
|
||||
}
|
||||
tail->next = NULL;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* not_squish --
|
||||
* compresses "!" expressions in our search plan.
|
||||
*/
|
||||
PLAN *
|
||||
not_squish(PLAN *plan)
|
||||
{
|
||||
PLAN *next; /* next node being processed */
|
||||
PLAN *node; /* temporary node used in f_not processing */
|
||||
PLAN *tail; /* pointer to tail of result plan */
|
||||
PLAN *result; /* pointer to head of result plan */
|
||||
|
||||
tail = result = NULL;
|
||||
|
||||
while ((next = yanknode(&plan))) {
|
||||
/*
|
||||
* if we encounter a ( expression ) then look for nots in
|
||||
* the expr subplan.
|
||||
*/
|
||||
if (next->execute == f_expr)
|
||||
next->p_data[0] = not_squish(next->p_data[0]);
|
||||
|
||||
/*
|
||||
* if we encounter a not, then snag the next node and place
|
||||
* it in the not's subplan. As an optimization we compress
|
||||
* several not's to zero or one not.
|
||||
*/
|
||||
if (next->execute == f_not) {
|
||||
int notlevel = 1;
|
||||
|
||||
node = yanknode(&plan);
|
||||
while (node != NULL && node->execute == f_not) {
|
||||
++notlevel;
|
||||
node = yanknode(&plan);
|
||||
}
|
||||
if (node == NULL)
|
||||
errx(1, "!: no following expression");
|
||||
if (node->execute == f_or)
|
||||
errx(1, "!: nothing between ! and -o");
|
||||
/*
|
||||
* If we encounter ! ( expr ) then look for nots in
|
||||
* the expr subplan.
|
||||
*/
|
||||
if (node->execute == f_expr)
|
||||
node->p_data[0] = not_squish(node->p_data[0]);
|
||||
if (notlevel % 2 != 1)
|
||||
next = node;
|
||||
else
|
||||
next->p_data[0] = node;
|
||||
}
|
||||
|
||||
/* add the node to our result plan */
|
||||
if (result == NULL)
|
||||
tail = result = next;
|
||||
else {
|
||||
tail->next = next;
|
||||
tail = next;
|
||||
}
|
||||
tail->next = NULL;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* or_squish --
|
||||
* compresses -o expressions in our search plan.
|
||||
*/
|
||||
PLAN *
|
||||
or_squish(PLAN *plan)
|
||||
{
|
||||
PLAN *next; /* next node being processed */
|
||||
PLAN *tail; /* pointer to tail of result plan */
|
||||
PLAN *result; /* pointer to head of result plan */
|
||||
|
||||
tail = result = next = NULL;
|
||||
|
||||
while ((next = yanknode(&plan)) != NULL) {
|
||||
/*
|
||||
* if we encounter a ( expression ) then look for or's in
|
||||
* the expr subplan.
|
||||
*/
|
||||
if (next->execute == f_expr)
|
||||
next->p_data[0] = or_squish(next->p_data[0]);
|
||||
|
||||
/* if we encounter a not then look for or's in the subplan */
|
||||
if (next->execute == f_not)
|
||||
next->p_data[0] = or_squish(next->p_data[0]);
|
||||
|
||||
/*
|
||||
* if we encounter an or, then place our collected plan in the
|
||||
* or's first subplan and then recursively collect the
|
||||
* remaining stuff into the second subplan and return the or.
|
||||
*/
|
||||
if (next->execute == f_or) {
|
||||
if (result == NULL)
|
||||
errx(1, "-o: no expression before -o");
|
||||
next->p_data[0] = result;
|
||||
next->p_data[1] = or_squish(plan);
|
||||
if (next->p_data[1] == NULL)
|
||||
errx(1, "-o: no expression after -o");
|
||||
return (next);
|
||||
}
|
||||
|
||||
/* add the node to our result plan */
|
||||
if (result == NULL)
|
||||
tail = result = next;
|
||||
else {
|
||||
tail->next = next;
|
||||
tail = next;
|
||||
}
|
||||
tail->next = NULL;
|
||||
}
|
||||
return (result);
|
||||
}
|
201
find/option.c
Normal file
201
find/option.c
Normal file
@ -0,0 +1,201 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Cimarron D. Taylor of the University of California, Berkeley.
|
||||
*
|
||||
* 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.
|
||||
* 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[] = "@(#)option.c 8.2 (Berkeley) 4/16/94";
|
||||
*/
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/usr.bin/find/option.c,v 1.32 2011/05/27 22:14:49 jilles Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <fts.h>
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "find.h"
|
||||
|
||||
static int typecompare(const void *, const void *);
|
||||
|
||||
/* NB: the following table must be sorted lexically. */
|
||||
/* Options listed with C++ comments are in gnu find, but not our find */
|
||||
static OPTION const options[] = {
|
||||
{ "!", c_simple, f_not, 0 },
|
||||
{ "(", c_simple, f_openparen, 0 },
|
||||
{ ")", c_simple, f_closeparen, 0 },
|
||||
{ "-Bmin", c_Xmin, f_Xmin, F_TIME_B },
|
||||
{ "-Bnewer", c_newer, f_newer, F_TIME_B },
|
||||
{ "-Btime", c_Xtime, f_Xtime, F_TIME_B },
|
||||
{ "-a", c_and, NULL, 0 },
|
||||
{ "-acl", c_acl, f_acl, 0 },
|
||||
{ "-amin", c_Xmin, f_Xmin, F_TIME_A },
|
||||
{ "-and", c_and, NULL, 0 },
|
||||
{ "-anewer", c_newer, f_newer, F_TIME_A },
|
||||
{ "-atime", c_Xtime, f_Xtime, F_TIME_A },
|
||||
{ "-cmin", c_Xmin, f_Xmin, F_TIME_C },
|
||||
{ "-cnewer", c_newer, f_newer, F_TIME_C },
|
||||
{ "-ctime", c_Xtime, f_Xtime, F_TIME_C },
|
||||
{ "-d", c_depth, f_depth, 0 },
|
||||
// -daystart
|
||||
{ "-delete", c_delete, f_delete, 0 },
|
||||
{ "-depth", c_depth, f_depth, 0 },
|
||||
{ "-empty", c_empty, f_empty, 0 },
|
||||
{ "-exec", c_exec, f_exec, 0 },
|
||||
{ "-execdir", c_exec, f_exec, F_EXECDIR },
|
||||
{ "-false", c_simple, f_false, 0 },
|
||||
{ "-flags", c_flags, f_flags, 0 },
|
||||
// -fls
|
||||
{ "-follow", c_follow, f_always_true, 0 },
|
||||
// -fprint
|
||||
// -fprint0
|
||||
// -fprintf
|
||||
{ "-fstype", c_fstype, f_fstype, 0 },
|
||||
{ "-gid", c_group, f_group, 0 },
|
||||
{ "-group", c_group, f_group, 0 },
|
||||
{ "-ignore_readdir_race",c_simple, f_always_true,0 },
|
||||
{ "-ilname", c_name, f_name, F_LINK | F_IGNCASE },
|
||||
{ "-iname", c_name, f_name, F_IGNCASE },
|
||||
{ "-inum", c_inum, f_inum, 0 },
|
||||
{ "-ipath", c_name, f_path, F_IGNCASE },
|
||||
{ "-iregex", c_regex, f_regex, F_IGNCASE },
|
||||
{ "-iwholename",c_name, f_path, F_IGNCASE },
|
||||
{ "-links", c_links, f_links, 0 },
|
||||
{ "-lname", c_name, f_name, F_LINK },
|
||||
{ "-ls", c_ls, f_ls, 0 },
|
||||
{ "-maxdepth", c_mXXdepth, f_always_true, F_MAXDEPTH },
|
||||
{ "-mindepth", c_mXXdepth, f_always_true, 0 },
|
||||
{ "-mmin", c_Xmin, f_Xmin, 0 },
|
||||
{ "-mnewer", c_newer, f_newer, 0 },
|
||||
{ "-mount", c_xdev, f_always_true, 0 },
|
||||
{ "-mtime", c_Xtime, f_Xtime, 0 },
|
||||
{ "-name", c_name, f_name, 0 },
|
||||
{ "-newer", c_newer, f_newer, 0 },
|
||||
{ "-newerBB", c_newer, f_newer, F_TIME_B | F_TIME2_B },
|
||||
{ "-newerBa", c_newer, f_newer, F_TIME_B | F_TIME2_A },
|
||||
{ "-newerBc", c_newer, f_newer, F_TIME_B | F_TIME2_C },
|
||||
{ "-newerBm", c_newer, f_newer, F_TIME_B },
|
||||
{ "-newerBt", c_newer, f_newer, F_TIME_B | F_TIME2_T },
|
||||
{ "-neweraB", c_newer, f_newer, F_TIME_A | F_TIME2_B },
|
||||
{ "-neweraa", c_newer, f_newer, F_TIME_A | F_TIME2_A },
|
||||
{ "-newerac", c_newer, f_newer, F_TIME_A | F_TIME2_C },
|
||||
{ "-neweram", c_newer, f_newer, F_TIME_A },
|
||||
{ "-newerat", c_newer, f_newer, F_TIME_A | F_TIME2_T },
|
||||
{ "-newercB", c_newer, f_newer, F_TIME_C | F_TIME2_B },
|
||||
{ "-newerca", c_newer, f_newer, F_TIME_C | F_TIME2_A },
|
||||
{ "-newercc", c_newer, f_newer, F_TIME_C | F_TIME2_C },
|
||||
{ "-newercm", c_newer, f_newer, F_TIME_C },
|
||||
{ "-newerct", c_newer, f_newer, F_TIME_C | F_TIME2_T },
|
||||
{ "-newermB", c_newer, f_newer, F_TIME2_B },
|
||||
{ "-newerma", c_newer, f_newer, F_TIME2_A },
|
||||
{ "-newermc", c_newer, f_newer, F_TIME2_C },
|
||||
{ "-newermm", c_newer, f_newer, 0 },
|
||||
{ "-newermt", c_newer, f_newer, F_TIME2_T },
|
||||
{ "-nogroup", c_nogroup, f_nogroup, 0 },
|
||||
{ "-noignore_readdir_race",c_simple, f_always_true,0 },
|
||||
{ "-noleaf", c_simple, f_always_true, 0 },
|
||||
{ "-not", c_simple, f_not, 0 },
|
||||
{ "-nouser", c_nouser, f_nouser, 0 },
|
||||
{ "-o", c_simple, f_or, 0 },
|
||||
{ "-ok", c_exec, f_exec, F_NEEDOK },
|
||||
{ "-okdir", c_exec, f_exec, F_NEEDOK | F_EXECDIR },
|
||||
{ "-or", c_simple, f_or, 0 },
|
||||
{ "-path", c_name, f_path, 0 },
|
||||
{ "-perm", c_perm, f_perm, 0 },
|
||||
{ "-print", c_print, f_print, 0 },
|
||||
{ "-print0", c_print, f_print0, 0 },
|
||||
// -printf
|
||||
{ "-prune", c_simple, f_prune, 0 },
|
||||
{ "-quit", c_simple, f_quit, 0 },
|
||||
{ "-regex", c_regex, f_regex, 0 },
|
||||
{ "-samefile", c_samefile, f_inum, 0 },
|
||||
{ "-size", c_size, f_size, 0 },
|
||||
{ "-true", c_simple, f_always_true, 0 },
|
||||
{ "-type", c_type, f_type, 0 },
|
||||
{ "-uid", c_user, f_user, 0 },
|
||||
{ "-user", c_user, f_user, 0 },
|
||||
{ "-wholename", c_name, f_path, 0 },
|
||||
#ifdef __APPLE__
|
||||
{ "-xattr", c_simple, f_xattr, 0 },
|
||||
{ "-xattrname", c_name, f_xattrname, 0 },
|
||||
#endif /* __APPLE__ */
|
||||
{ "-xdev", c_xdev, f_always_true, 0 },
|
||||
// -xtype
|
||||
};
|
||||
|
||||
/*
|
||||
* find_create --
|
||||
* create a node corresponding to a command line argument.
|
||||
*
|
||||
* TODO:
|
||||
* add create/process function pointers to node, so we can skip
|
||||
* this switch stuff.
|
||||
*/
|
||||
PLAN *
|
||||
find_create(char ***argvp)
|
||||
{
|
||||
OPTION *p;
|
||||
PLAN *new;
|
||||
char **argv;
|
||||
|
||||
argv = *argvp;
|
||||
|
||||
if ((p = lookup_option(*argv)) == NULL)
|
||||
errx(1, "%s: unknown primary or operator", *argv);
|
||||
++argv;
|
||||
|
||||
new = (p->create)(p, &argv);
|
||||
*argvp = argv;
|
||||
return (new);
|
||||
}
|
||||
|
||||
OPTION *
|
||||
lookup_option(const char *name)
|
||||
{
|
||||
OPTION tmp;
|
||||
|
||||
tmp.name = name;
|
||||
return ((OPTION *)bsearch(&tmp, options,
|
||||
sizeof(options)/sizeof(OPTION), sizeof(OPTION), typecompare));
|
||||
}
|
||||
|
||||
static int
|
||||
typecompare(const void *a, const void *b)
|
||||
{
|
||||
return (strcmp(((const OPTION *)a)->name, ((const OPTION *)b)->name));
|
||||
}
|
134
getopt/getopt.1
Normal file
134
getopt/getopt.1
Normal file
@ -0,0 +1,134 @@
|
||||
.\" $FreeBSD: src/usr.bin/getopt/getopt.1,v 1.15 2002/04/19 23:43:02 charnier Exp $
|
||||
.\"
|
||||
.Dd April 3, 1999
|
||||
.Dt GETOPT 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm getopt
|
||||
.Nd parse command options
|
||||
.Sh SYNOPSIS
|
||||
.Nm args=\`getopt Ar optstring $*\`
|
||||
; errcode=$?; set \-\- $args
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility is used to break up options in command lines for easy parsing by
|
||||
shell procedures, and to check for legal options.
|
||||
.Ar Optstring
|
||||
is a string of recognized option letters (see
|
||||
.Xr getopt 3 ) ;
|
||||
if a letter is followed by a colon, the option
|
||||
is expected to have an argument which may or may not be
|
||||
separated from it by white space.
|
||||
The special option
|
||||
.Ql \-\-
|
||||
is used to delimit the end of the options.
|
||||
The
|
||||
.Nm
|
||||
utility will place
|
||||
.Ql \-\-
|
||||
in the arguments at the end of the options,
|
||||
or recognize it if used explicitly.
|
||||
The shell arguments
|
||||
(\fB$1 $2\fR ...) are reset so that each option is
|
||||
preceded by a
|
||||
.Ql \-
|
||||
and in its own shell argument;
|
||||
each option argument is also in its own shell argument.
|
||||
.Sh EXAMPLES
|
||||
The following code fragment shows how one might process the arguments
|
||||
for a command that can take the options
|
||||
.Fl a
|
||||
and
|
||||
.Fl b ,
|
||||
and the option
|
||||
.Fl o ,
|
||||
which requires an argument.
|
||||
.Pp
|
||||
.Bd -literal -offset indent
|
||||
args=\`getopt abo: $*\`
|
||||
# you should not use \`getopt abo: "$@"\` since that would parse
|
||||
# the arguments differently from what the set command below does.
|
||||
if [ $? != 0 ]
|
||||
then
|
||||
echo 'Usage: ...'
|
||||
exit 2
|
||||
fi
|
||||
set \-\- $args
|
||||
# You cannot use the set command with a backquoted getopt directly,
|
||||
# since the exit code from getopt would be shadowed by those of set,
|
||||
# which is zero by definition.
|
||||
for i
|
||||
do
|
||||
case "$i"
|
||||
in
|
||||
\-a|\-b)
|
||||
echo flag $i set; sflags="${i#-}$sflags";
|
||||
shift;;
|
||||
\-o)
|
||||
echo oarg is "'"$2"'"; oarg="$2"; shift;
|
||||
shift;;
|
||||
\-\-)
|
||||
shift; break;;
|
||||
esac
|
||||
done
|
||||
echo single-char flags: "'"$sflags"'"
|
||||
echo oarg is "'"$oarg"'"
|
||||
.Ed
|
||||
.Pp
|
||||
This code will accept any of the following as equivalent:
|
||||
.Pp
|
||||
.Bd -literal -offset indent
|
||||
cmd \-aoarg file file
|
||||
cmd \-a \-o arg file file
|
||||
cmd \-oarg -a file file
|
||||
cmd \-a \-oarg \-\- file file
|
||||
.Pp
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr sh 1 ,
|
||||
.Xr getopt 3
|
||||
.Sh DIAGNOSTICS
|
||||
The
|
||||
.Nm
|
||||
utility prints an error message on the standard error output and exits with
|
||||
status > 0 when it encounters an option letter not included in
|
||||
.Ar optstring .
|
||||
.Sh HISTORY
|
||||
Written by
|
||||
.An Henry Spencer ,
|
||||
working from a Bell Labs manual page.
|
||||
Behavior believed identical to the Bell version.
|
||||
Example changed in
|
||||
.Fx
|
||||
version 3.2 and 4.0.
|
||||
.Sh BUGS
|
||||
Whatever
|
||||
.Xr getopt 3
|
||||
has.
|
||||
.Pp
|
||||
Arguments containing white space or embedded shell metacharacters
|
||||
generally will not survive intact; this looks easy to fix but
|
||||
isn't. People trying to fix
|
||||
.Nm
|
||||
or the example in this manpage should check the history of this file
|
||||
in
|
||||
.Fx .
|
||||
.Pp
|
||||
The error message for an invalid option is identified as coming
|
||||
from
|
||||
.Nm
|
||||
rather than from the shell procedure containing the invocation
|
||||
of
|
||||
.Nm ;
|
||||
this again is hard to fix.
|
||||
.Pp
|
||||
The precise best way to use the
|
||||
.Nm set
|
||||
command to set the arguments without disrupting the value(s) of
|
||||
shell options varies from one shell version to another.
|
||||
.Pp
|
||||
Each shellscript has to carry complex code to parse arguments halfway
|
||||
correcty (like the example presented here). A better getopt-like tool
|
||||
would move much of the complexity into the tool and keep the client
|
||||
shell scripts simpler.
|
32
getopt/getopt.c
Normal file
32
getopt/getopt.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$FreeBSD: src/usr.bin/getopt/getopt.c,v 1.10 2002/09/04 23:29:01 dwmalone Exp $");
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
int status = 0;
|
||||
|
||||
optind = 2; /* Past the program name and the option letters. */
|
||||
while ((c = getopt(argc, argv, argv[1])) != -1)
|
||||
switch (c) {
|
||||
case '?':
|
||||
status = 1; /* getopt routine gave message */
|
||||
break;
|
||||
default:
|
||||
if (optarg != NULL)
|
||||
printf(" -%c %s", c, optarg);
|
||||
else
|
||||
printf(" -%c", c);
|
||||
break;
|
||||
}
|
||||
printf(" --");
|
||||
for (; optind < argc; optind++)
|
||||
printf(" %s", argv[optind]);
|
||||
printf("\n");
|
||||
return status;
|
||||
}
|
178
hexdump/conv.c
Normal file
178
hexdump/conv.c
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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 const char sccsid[] = "@(#)conv.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
#include "hexdump.h"
|
||||
|
||||
void
|
||||
conv_c(PR *pr, u_char *p, size_t bufsize)
|
||||
{
|
||||
char buf[10];
|
||||
char const *str;
|
||||
wchar_t wc;
|
||||
size_t clen, oclen;
|
||||
int converr, pad, width;
|
||||
u_char peekbuf[MB_LEN_MAX];
|
||||
|
||||
if (pr->mbleft > 0) {
|
||||
str = "**";
|
||||
pr->mbleft--;
|
||||
goto strpr;
|
||||
}
|
||||
|
||||
switch(*p) {
|
||||
case '\0':
|
||||
str = "\\0";
|
||||
goto strpr;
|
||||
/* case '\a': */
|
||||
case '\007':
|
||||
str = "\\a";
|
||||
goto strpr;
|
||||
case '\b':
|
||||
str = "\\b";
|
||||
goto strpr;
|
||||
case '\f':
|
||||
str = "\\f";
|
||||
goto strpr;
|
||||
case '\n':
|
||||
str = "\\n";
|
||||
goto strpr;
|
||||
case '\r':
|
||||
str = "\\r";
|
||||
goto strpr;
|
||||
case '\t':
|
||||
str = "\\t";
|
||||
goto strpr;
|
||||
case '\v':
|
||||
str = "\\v";
|
||||
goto strpr;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Multibyte characters are disabled for hexdump(1) for backwards
|
||||
* compatibility and consistency (none of its other output formats
|
||||
* recognize them correctly).
|
||||
*/
|
||||
converr = 0;
|
||||
if (odmode && MB_CUR_MAX > 1) {
|
||||
oclen = 0;
|
||||
retry:
|
||||
clen = mbrtowc(&wc, (const char *)p, bufsize, &pr->mbstate);
|
||||
if (clen == 0)
|
||||
clen = 1;
|
||||
else if (clen == (size_t)-1 || (clen == (size_t)-2 &&
|
||||
p == peekbuf)) {
|
||||
memset(&pr->mbstate, 0, sizeof(pr->mbstate));
|
||||
wc = *p;
|
||||
clen = 1;
|
||||
converr = 1;
|
||||
} else if (clen == (size_t)-2) {
|
||||
/*
|
||||
* Incomplete character; peek ahead and see if we
|
||||
* can complete it.
|
||||
*/
|
||||
oclen = bufsize;
|
||||
bufsize = peek(p = peekbuf, MB_CUR_MAX);
|
||||
goto retry;
|
||||
}
|
||||
clen += oclen;
|
||||
} else {
|
||||
wc = *p;
|
||||
clen = 1;
|
||||
}
|
||||
if (!converr && iswprint(wc)) {
|
||||
if (!odmode) {
|
||||
*pr->cchar = 'c';
|
||||
(void)printf(pr->fmt, (int)wc);
|
||||
} else {
|
||||
*pr->cchar = 'C';
|
||||
assert(strcmp(pr->fmt, "%3C") == 0);
|
||||
width = wcwidth(wc);
|
||||
assert(width >= 0);
|
||||
pad = 3 - width;
|
||||
if (pad < 0)
|
||||
pad = 0;
|
||||
(void)printf("%*s%C", pad, "", wc);
|
||||
pr->mbleft = clen - 1;
|
||||
}
|
||||
} else {
|
||||
(void)sprintf(buf, "%03o", (int)*p);
|
||||
str = buf;
|
||||
strpr: *pr->cchar = 's';
|
||||
(void)printf(pr->fmt, str);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
conv_u(PR *pr, u_char *p)
|
||||
{
|
||||
static char const * list[] = {
|
||||
"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
|
||||
"bs", "ht", "lf", "vt", "ff", "cr", "so", "si",
|
||||
"dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
|
||||
"can", "em", "sub", "esc", "fs", "gs", "rs", "us",
|
||||
};
|
||||
|
||||
/* od used nl, not lf */
|
||||
if (*p <= 0x1f) {
|
||||
*pr->cchar = 's';
|
||||
if (odmode && *p == 0x0a)
|
||||
(void)printf(pr->fmt, "nl");
|
||||
else
|
||||
(void)printf(pr->fmt, list[*p]);
|
||||
} else if (*p == 0x7f) {
|
||||
*pr->cchar = 's';
|
||||
(void)printf(pr->fmt, "del");
|
||||
} else if (odmode && *p == 0x20) { /* od replaced space with sp */
|
||||
*pr->cchar = 's';
|
||||
(void)printf(pr->fmt, " sp");
|
||||
} else if (isprint(*p)) {
|
||||
*pr->cchar = 'c';
|
||||
(void)printf(pr->fmt, *p);
|
||||
} else {
|
||||
*pr->cchar = 'x';
|
||||
(void)printf(pr->fmt, (int)*p);
|
||||
}
|
||||
}
|
417
hexdump/display.c
Normal file
417
hexdump/display.c
Normal file
@ -0,0 +1,417 @@
|
||||
/*
|
||||
* 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
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)display.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/usr.bin/hexdump/display.c,v 1.19 2004/07/11 01:11:12 tjr Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "hexdump.h"
|
||||
|
||||
enum _vflag vflag = FIRST;
|
||||
|
||||
static off_t address; /* address/offset in stream */
|
||||
static off_t eaddress; /* end address */
|
||||
|
||||
static __inline void print(PR *, u_char *);
|
||||
|
||||
void
|
||||
display(void)
|
||||
{
|
||||
FS *fs;
|
||||
FU *fu;
|
||||
PR *pr;
|
||||
int cnt;
|
||||
u_char *bp;
|
||||
off_t saveaddress;
|
||||
u_char savech=0, *savebp;
|
||||
|
||||
while ((bp = get()))
|
||||
for (fs = fshead, savebp = bp, saveaddress = address; fs;
|
||||
fs = fs->nextfs, bp = savebp, address = saveaddress)
|
||||
for (fu = fs->nextfu; fu; fu = fu->nextfu) {
|
||||
if (fu->flags&F_IGNORE)
|
||||
break;
|
||||
for (cnt = fu->reps; cnt; --cnt)
|
||||
for (pr = fu->nextpr; pr; address += pr->bcnt,
|
||||
bp += pr->bcnt, pr = pr->nextpr) {
|
||||
if (eaddress && address >= eaddress &&
|
||||
!(pr->flags & (F_TEXT|F_BPAD)))
|
||||
bpad(pr);
|
||||
if (cnt == 1 && pr->nospace) {
|
||||
savech = *pr->nospace;
|
||||
*pr->nospace = '\0';
|
||||
}
|
||||
print(pr, bp);
|
||||
if (cnt == 1 && pr->nospace)
|
||||
*pr->nospace = savech;
|
||||
}
|
||||
}
|
||||
if (endfu) {
|
||||
/*
|
||||
* If eaddress not set, error or file size was multiple of
|
||||
* blocksize, and no partial block ever found.
|
||||
*/
|
||||
if (!eaddress) {
|
||||
if (!address) {
|
||||
return;
|
||||
}
|
||||
eaddress = address;
|
||||
}
|
||||
for (pr = endfu->nextpr; pr; pr = pr->nextpr)
|
||||
switch(pr->flags) {
|
||||
case F_ADDRESS:
|
||||
(void)printf(pr->fmt, (quad_t)eaddress);
|
||||
break;
|
||||
case F_TEXT:
|
||||
(void)printf("%s", pr->fmt);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static __inline void
|
||||
print(PR *pr, u_char *bp)
|
||||
{
|
||||
long double ldbl;
|
||||
double f8;
|
||||
float f4;
|
||||
int16_t s2;
|
||||
int8_t s8;
|
||||
int32_t s4;
|
||||
u_int16_t u2;
|
||||
u_int32_t u4;
|
||||
u_int64_t u8;
|
||||
|
||||
switch(pr->flags) {
|
||||
case F_ADDRESS:
|
||||
(void)printf(pr->fmt, (quad_t)address);
|
||||
break;
|
||||
case F_BPAD:
|
||||
(void)printf(pr->fmt, "");
|
||||
break;
|
||||
case F_C:
|
||||
conv_c(pr, bp, eaddress ? eaddress - address :
|
||||
blocksize - address % blocksize);
|
||||
break;
|
||||
case F_CHAR:
|
||||
(void)printf(pr->fmt, *bp);
|
||||
break;
|
||||
case F_DBL:
|
||||
switch(pr->bcnt) {
|
||||
case 4:
|
||||
bcopy(bp, &f4, sizeof(f4));
|
||||
(void)printf(pr->fmt, f4);
|
||||
break;
|
||||
case 8:
|
||||
bcopy(bp, &f8, sizeof(f8));
|
||||
(void)printf(pr->fmt, f8);
|
||||
break;
|
||||
default:
|
||||
if (pr->bcnt == sizeof(long double)) {
|
||||
bcopy(bp, &ldbl, sizeof(ldbl));
|
||||
(void)printf(pr->fmt, ldbl);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case F_INT:
|
||||
switch(pr->bcnt) {
|
||||
case 1:
|
||||
(void)printf(pr->fmt, (quad_t)(signed char)*bp);
|
||||
break;
|
||||
case 2:
|
||||
bcopy(bp, &s2, sizeof(s2));
|
||||
(void)printf(pr->fmt, (quad_t)s2);
|
||||
break;
|
||||
case 4:
|
||||
bcopy(bp, &s4, sizeof(s4));
|
||||
(void)printf(pr->fmt, (quad_t)s4);
|
||||
break;
|
||||
case 8:
|
||||
bcopy(bp, &s8, sizeof(s8));
|
||||
(void)printf(pr->fmt, s8);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case F_P:
|
||||
(void)printf(pr->fmt, isprint(*bp) && isascii(*bp) ? *bp : '.');
|
||||
break;
|
||||
case F_STR:
|
||||
(void)printf(pr->fmt, (char *)bp);
|
||||
break;
|
||||
case F_TEXT:
|
||||
(void)printf("%s", pr->fmt);
|
||||
break;
|
||||
case F_U:
|
||||
conv_u(pr, bp);
|
||||
break;
|
||||
case F_UINT:
|
||||
switch(pr->bcnt) {
|
||||
case 1:
|
||||
(void)printf(pr->fmt, (u_quad_t)*bp);
|
||||
break;
|
||||
case 2:
|
||||
bcopy(bp, &u2, sizeof(u2));
|
||||
(void)printf(pr->fmt, (u_quad_t)u2);
|
||||
break;
|
||||
case 4:
|
||||
bcopy(bp, &u4, sizeof(u4));
|
||||
(void)printf(pr->fmt, (u_quad_t)u4);
|
||||
break;
|
||||
case 8:
|
||||
bcopy(bp, &u8, sizeof(u8));
|
||||
(void)printf(pr->fmt, u8);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bpad(PR *pr)
|
||||
{
|
||||
static char const *spec = " -0+#";
|
||||
char *p1, *p2;
|
||||
|
||||
/*
|
||||
* Remove all conversion flags; '-' is the only one valid
|
||||
* with %s, and it's not useful here.
|
||||
*/
|
||||
pr->flags = F_BPAD;
|
||||
pr->cchar[0] = 's';
|
||||
pr->cchar[1] = '\0';
|
||||
for (p1 = pr->fmt; *p1 != '%'; ++p1);
|
||||
for (p2 = ++p1; *p1 && index(spec, *p1); ++p1);
|
||||
while ((*p2++ = *p1++));
|
||||
}
|
||||
|
||||
static char **_argv;
|
||||
|
||||
u_char *
|
||||
get(void)
|
||||
{
|
||||
static int ateof = 1;
|
||||
static u_char *curp, *savp;
|
||||
int n;
|
||||
int need, nread;
|
||||
int valid_save = 0;
|
||||
u_char *tmpp;
|
||||
|
||||
if (!curp) {
|
||||
if ((curp = calloc(1, blocksize)) == NULL)
|
||||
err(1, NULL);
|
||||
if ((savp = calloc(1, blocksize)) == NULL)
|
||||
err(1, NULL);
|
||||
} else {
|
||||
tmpp = curp;
|
||||
curp = savp;
|
||||
savp = tmpp;
|
||||
address += blocksize;
|
||||
valid_save = 1;
|
||||
}
|
||||
for (need = blocksize, nread = 0;;) {
|
||||
/*
|
||||
* if read the right number of bytes, or at EOF for one file,
|
||||
* and no other files are available, zero-pad the rest of the
|
||||
* block and set the end flag.
|
||||
*/
|
||||
if (!length || (ateof && !next((char **)NULL))) {
|
||||
if (odmode && address < skip)
|
||||
errx(1, "cannot skip past end of input");
|
||||
if (need == blocksize)
|
||||
return((u_char *)NULL);
|
||||
/*
|
||||
* XXX bcmp() is not quite right in the presence
|
||||
* of multibyte characters.
|
||||
*/
|
||||
#ifdef __APPLE__
|
||||
/* 5650060 */
|
||||
if (!need && vflag != ALL &&
|
||||
#else
|
||||
if (vflag != ALL &&
|
||||
#endif
|
||||
valid_save &&
|
||||
bcmp(curp, savp, nread) == 0) {
|
||||
if (vflag != DUP)
|
||||
(void)printf("*\n");
|
||||
return((u_char *)NULL);
|
||||
}
|
||||
bzero((char *)curp + nread, need);
|
||||
eaddress = address + nread;
|
||||
if (length == 0)
|
||||
lseek(STDIN_FILENO, ftell(stdin), SEEK_SET); /* rewind stdin for next process */
|
||||
return(curp);
|
||||
}
|
||||
n = fread((char *)curp + nread, sizeof(u_char),
|
||||
length == -1 ? need : MIN(length, need), stdin);
|
||||
if (!n) {
|
||||
if (ferror(stdin))
|
||||
warn("%s", _argv[-1]);
|
||||
ateof = 1;
|
||||
continue;
|
||||
}
|
||||
ateof = 0;
|
||||
if (length != -1)
|
||||
length -= n;
|
||||
if (!(need -= n)) {
|
||||
/*
|
||||
* XXX bcmp() is not quite right in the presence
|
||||
* of multibyte characters.
|
||||
*/
|
||||
if (vflag == ALL || vflag == FIRST ||
|
||||
valid_save == 0 ||
|
||||
bcmp(curp, savp, blocksize) != 0) {
|
||||
if (vflag == DUP || vflag == FIRST)
|
||||
vflag = WAIT;
|
||||
return(curp);
|
||||
}
|
||||
if (vflag == WAIT)
|
||||
(void)printf("*\n");
|
||||
vflag = DUP;
|
||||
address += blocksize;
|
||||
need = blocksize;
|
||||
nread = 0;
|
||||
}
|
||||
else
|
||||
nread += n;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
peek(u_char *buf, size_t nbytes)
|
||||
{
|
||||
size_t n, nread;
|
||||
int c;
|
||||
|
||||
if (length != -1 && nbytes > length)
|
||||
nbytes = length;
|
||||
nread = 0;
|
||||
while (nread < nbytes && (c = getchar()) != EOF) {
|
||||
*buf++ = c;
|
||||
nread++;
|
||||
}
|
||||
n = nread;
|
||||
while (n-- > 0) {
|
||||
c = *--buf;
|
||||
ungetc(c, stdin);
|
||||
}
|
||||
return (nread);
|
||||
}
|
||||
|
||||
int
|
||||
next(char **argv)
|
||||
{
|
||||
static int done;
|
||||
int statok;
|
||||
|
||||
if (argv) {
|
||||
_argv = argv;
|
||||
return(1);
|
||||
}
|
||||
for (;;) {
|
||||
if (*_argv) {
|
||||
if (!(freopen(*_argv, "r", stdin))) {
|
||||
warn("%s", *_argv);
|
||||
exitval = 1;
|
||||
++_argv;
|
||||
continue;
|
||||
}
|
||||
statok = done = 1;
|
||||
} else {
|
||||
if (done++)
|
||||
return(0);
|
||||
statok = 0;
|
||||
}
|
||||
if (skip)
|
||||
doskip(statok ? *_argv : "stdin", statok);
|
||||
if (*_argv)
|
||||
++_argv;
|
||||
if (!skip)
|
||||
return(1);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
void
|
||||
doskip(const char *fname, int statok)
|
||||
{
|
||||
int cnt;
|
||||
struct stat sb;
|
||||
|
||||
if (statok) {
|
||||
if (fstat(fileno(stdin), &sb))
|
||||
err(1, "%s", fname);
|
||||
if (S_ISREG(sb.st_mode) && skip >= sb.st_size) {
|
||||
address += sb.st_size;
|
||||
skip -= sb.st_size;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
/* try to seek first; fall back on ESPIPE */
|
||||
if (fseeko(stdin, skip, SEEK_SET) == 0) {
|
||||
#else /* !__APPLE__ */
|
||||
if (S_ISREG(sb.st_mode)) {
|
||||
if (fseeko(stdin, skip, SEEK_SET))
|
||||
err(1, "%s", fname);
|
||||
#endif /* __APPLE__ */
|
||||
address += skip;
|
||||
skip = 0;
|
||||
} else {
|
||||
#ifdef __APPLE__
|
||||
if (errno != ESPIPE)
|
||||
err(1, "%s", fname);
|
||||
#endif /* __APPLE__ */
|
||||
for (cnt = 0; cnt < skip; ++cnt)
|
||||
if (getchar() == EOF)
|
||||
break;
|
||||
address += cnt;
|
||||
skip -= cnt;
|
||||
}
|
||||
}
|
342
hexdump/hexdump.1
Normal file
342
hexdump/hexdump.1
Normal file
@ -0,0 +1,342 @@
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)hexdump.1 8.2 (Berkeley) 4/18/94
|
||||
.\" $FreeBSD: src/usr.bin/hexdump/hexdump.1,v 1.21 2004/07/10 13:11:00 tjr Exp $
|
||||
.\"
|
||||
.Dd July 10, 2004
|
||||
.Dt HEXDUMP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm hexdump
|
||||
.Nd ASCII, decimal, hexadecimal, octal dump
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl bcCdovx
|
||||
.Op Fl e Ar format_string
|
||||
.Op Fl f Ar format_file
|
||||
.Op Fl n Ar length
|
||||
.Bk -words
|
||||
.Op Fl s Ar skip
|
||||
.Ek
|
||||
.Ar
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility is a filter which displays the specified files, or
|
||||
the standard input, if no files are specified, in a user specified
|
||||
format.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl b
|
||||
.Em One-byte octal display .
|
||||
Display the input offset in hexadecimal, followed by sixteen
|
||||
space-separated, three column, zero-filled, bytes of input data,
|
||||
in octal, per line.
|
||||
.It Fl C
|
||||
.Em Canonical hex+ASCII display .
|
||||
Display the input offset in hexadecimal, followed by sixteen
|
||||
space-separated, two column, hexadecimal bytes, followed by the
|
||||
same sixteen bytes in %_p format enclosed in ``|'' characters.
|
||||
.It Fl c
|
||||
.Em One-byte character display .
|
||||
Display the input offset in hexadecimal, followed by sixteen
|
||||
space-separated, three column, space-filled, characters of input
|
||||
data per line.
|
||||
.It Fl d
|
||||
.Em Two-byte decimal display .
|
||||
Display the input offset in hexadecimal, followed by eight
|
||||
space-separated, five column, zero-filled, two-byte units
|
||||
of input data, in unsigned decimal, per line.
|
||||
.It Fl e Ar format_string
|
||||
Specify a format string to be used for displaying data.
|
||||
.It Fl f Ar format_file
|
||||
Specify a file that contains one or more newline separated format strings.
|
||||
Empty lines and lines whose first non-blank character is a hash mark
|
||||
.Pf ( Cm \&# )
|
||||
are ignored.
|
||||
.It Fl n Ar length
|
||||
Interpret only
|
||||
.Ar length
|
||||
bytes of input.
|
||||
.It Fl o
|
||||
.Em Two-byte octal display .
|
||||
Display the input offset in hexadecimal, followed by eight
|
||||
space-separated, six column, zero-filled, two byte quantities of
|
||||
input data, in octal, per line.
|
||||
.It Fl s Ar offset
|
||||
Skip
|
||||
.Ar offset
|
||||
bytes from the beginning of the input.
|
||||
By default,
|
||||
.Ar offset
|
||||
is interpreted as a decimal number.
|
||||
With a leading
|
||||
.Cm 0x
|
||||
or
|
||||
.Cm 0X ,
|
||||
.Ar offset
|
||||
is interpreted as a hexadecimal number,
|
||||
otherwise, with a leading
|
||||
.Cm 0 ,
|
||||
.Ar offset
|
||||
is interpreted as an octal number.
|
||||
Appending the character
|
||||
.Cm b ,
|
||||
.Cm k ,
|
||||
.Cm m ,
|
||||
or
|
||||
.Cm g
|
||||
to
|
||||
.Ar offset
|
||||
causes it to be interpreted as a multiple of
|
||||
.Li 512 ,
|
||||
.Li 1024 ,
|
||||
.Li 1048576 ,
|
||||
or
|
||||
.Li 1073741824 ,
|
||||
respectively.
|
||||
.It Fl v
|
||||
Cause
|
||||
.Nm
|
||||
to display all input data.
|
||||
Without the
|
||||
.Fl v
|
||||
option, any number of groups of output lines, which would be
|
||||
identical to the immediately preceding group of output lines (except
|
||||
for the input offsets), are replaced with a line comprised of a
|
||||
single asterisk.
|
||||
.It Fl x
|
||||
.Em Two-byte hexadecimal display .
|
||||
Display the input offset in hexadecimal, followed by eight, space
|
||||
separated, four column, zero-filled, two-byte quantities of input
|
||||
data, in hexadecimal, per line.
|
||||
.El
|
||||
.Pp
|
||||
For each input file,
|
||||
.Nm
|
||||
sequentially copies the input to standard output, transforming the
|
||||
data according to the format strings specified by the
|
||||
.Fl e
|
||||
and
|
||||
.Fl f
|
||||
options, in the order that they were specified.
|
||||
.Ss Formats
|
||||
A format string contains any number of format units, separated by
|
||||
whitespace.
|
||||
A format unit contains up to three items: an iteration count, a byte
|
||||
count, and a format.
|
||||
.Pp
|
||||
The iteration count is an optional positive integer, which defaults to
|
||||
one.
|
||||
Each format is applied iteration count times.
|
||||
.Pp
|
||||
The byte count is an optional positive integer.
|
||||
If specified it defines the number of bytes to be interpreted by
|
||||
each iteration of the format.
|
||||
.Pp
|
||||
If an iteration count and/or a byte count is specified, a single slash
|
||||
must be placed after the iteration count and/or before the byte count
|
||||
to disambiguate them.
|
||||
Any whitespace before or after the slash is ignored.
|
||||
.Pp
|
||||
The format is required and must be surrounded by double quote
|
||||
(" ") marks.
|
||||
It is interpreted as a fprintf-style format string (see
|
||||
.Xr fprintf 3 ) ,
|
||||
with the
|
||||
following exceptions:
|
||||
.Bl -bullet -offset indent
|
||||
.It
|
||||
An asterisk (*) may not be used as a field width or precision.
|
||||
.It
|
||||
A byte count or field precision
|
||||
.Em is
|
||||
required for each ``s'' conversion
|
||||
character (unlike the
|
||||
.Xr fprintf 3
|
||||
default which prints the entire string if the precision is unspecified).
|
||||
.It
|
||||
The conversion characters ``h'', ``l'', ``n'', ``p'' and ``q'' are
|
||||
not supported.
|
||||
.It
|
||||
The single character escape sequences
|
||||
described in the C standard are supported:
|
||||
.Bd -ragged -offset indent -compact
|
||||
.Bl -column <alert_character>
|
||||
.It "NUL \e0
|
||||
.It "<alert character> \ea
|
||||
.It "<backspace> \eb
|
||||
.It "<form-feed> \ef
|
||||
.It "<newline> \en
|
||||
.It "<carriage return> \er
|
||||
.It "<tab> \et
|
||||
.It "<vertical tab> \ev
|
||||
.El
|
||||
.Ed
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility also supports the following additional conversion strings:
|
||||
.Bl -tag -width Fl
|
||||
.It Cm \&_a Ns Op Cm dox
|
||||
Display the input offset, cumulative across input files, of the
|
||||
next byte to be displayed.
|
||||
The appended characters
|
||||
.Cm d ,
|
||||
.Cm o ,
|
||||
and
|
||||
.Cm x
|
||||
specify the display base
|
||||
as decimal, octal or hexadecimal respectively.
|
||||
.It Cm \&_A Ns Op Cm dox
|
||||
Identical to the
|
||||
.Cm \&_a
|
||||
conversion string except that it is only performed
|
||||
once, when all of the input data has been processed.
|
||||
.It Cm \&_c
|
||||
Output characters in the default character set.
|
||||
Nonprinting characters are displayed in three character, zero-padded
|
||||
octal, except for those representable by standard escape notation
|
||||
(see above),
|
||||
which are displayed as two character strings.
|
||||
.It Cm _p
|
||||
Output characters in the ASCII character set.
|
||||
Non-ASCII characters are displayed as a single
|
||||
.Dq Cm \&. .
|
||||
.It Cm _u
|
||||
Output US
|
||||
.Tn ASCII
|
||||
characters, with the exception that control characters are
|
||||
displayed using the following, lower-case, names.
|
||||
Characters greater than 0xff, hexadecimal, are displayed as hexadecimal
|
||||
strings.
|
||||
.Bl -column \&000_nu \&001_so \&002_st \&003_et \&004_eo
|
||||
.It "\&000\ NUL\t001\ SOH\t002\ STX\t003\ ETX\t004\ EOT\t005\ ENQ
|
||||
.It "\&006\ ACK\t007\ BEL\t008\ BS\t009\ HT\t00A\ LF\t00B\ VT
|
||||
.It "\&00C\ FF\t00D\ CR\t00E\ SO\t00F\ SI\t010\ DLE\t011\ DC1
|
||||
.It "\&012\ DC2\t013\ DC3\t014\ DC4\t015\ NAK\t016\ SYN\t017\ ETB
|
||||
.It "\&018\ CAN\t019\ EM\t01A\ SUB\t01B\ ESC\t01C\ FS\t01D\ GS
|
||||
.It "\&01E\ RS\t01F\ US\t0FF\ DEL
|
||||
.El
|
||||
.El
|
||||
.Pp
|
||||
The default and supported byte counts for the conversion characters
|
||||
are as follows:
|
||||
.Bl -tag -width "Xc,_Xc,_Xc,_Xc,_Xc,_Xc" -offset indent
|
||||
.It Li \&%_c , \&%_p , \&%_u , \&%c
|
||||
One byte counts only.
|
||||
.It Xo
|
||||
.Li \&%d , \&%i , \&%o ,
|
||||
.Li \&%u , \&%X , \&%x
|
||||
.Xc
|
||||
Four byte default, one, two and four byte counts supported.
|
||||
.It Xo
|
||||
.Li \&%E , \&%e , \&%f ,
|
||||
.Li \&%G , \&%g
|
||||
.Xc
|
||||
Eight byte default, four and twelve byte counts supported.
|
||||
.El
|
||||
.Pp
|
||||
The amount of data interpreted by each format string is the sum of the
|
||||
data required by each format unit, which is the iteration count times the
|
||||
byte count, or the iteration count times the number of bytes required by
|
||||
the format if the byte count is not specified.
|
||||
.Pp
|
||||
The input is manipulated in ``blocks'', where a block is defined as the
|
||||
largest amount of data specified by any format string.
|
||||
Format strings interpreting less than an input block's worth of data,
|
||||
whose last format unit both interprets some number of bytes and does
|
||||
not have a specified iteration count, have the iteration count
|
||||
incremented until the entire input block has been processed or there
|
||||
is not enough data remaining in the block to satisfy the format string.
|
||||
.Pp
|
||||
If, either as a result of user specification or
|
||||
.Nm
|
||||
modifying
|
||||
the iteration count as described above, an iteration count is
|
||||
greater than one, no trailing whitespace characters are output
|
||||
during the last iteration.
|
||||
.Pp
|
||||
It is an error to specify a byte count as well as multiple conversion
|
||||
characters or strings unless all but one of the conversion characters
|
||||
or strings is
|
||||
.Cm \&_a
|
||||
or
|
||||
.Cm \&_A .
|
||||
.Pp
|
||||
If, as a result of the specification of the
|
||||
.Fl n
|
||||
option or end-of-file being reached, input data only partially
|
||||
satisfies a format string, the input block is zero-padded sufficiently
|
||||
to display all available data (i.e., any format units overlapping the
|
||||
end of data will display some number of the zero bytes).
|
||||
.Pp
|
||||
Further output by such format strings is replaced by an equivalent
|
||||
number of spaces.
|
||||
An equivalent number of spaces is defined as the number of spaces
|
||||
output by an
|
||||
.Cm s
|
||||
conversion character with the same field width
|
||||
and precision as the original conversion character or conversion
|
||||
string but with any
|
||||
.Dq Li \&+ ,
|
||||
.Dq \&\ \& ,
|
||||
.Dq Li \&#
|
||||
conversion flag characters
|
||||
removed, and referencing a NULL string.
|
||||
.Pp
|
||||
If no format strings are specified, the default display is a
|
||||
one-byte hexadecimal display.
|
||||
.Sh DIAGNOSTICS
|
||||
.Ex -std
|
||||
.Sh EXAMPLES
|
||||
Note that the following format strings, used with
|
||||
.Fl e ,
|
||||
must be enclosed in single quotes.
|
||||
.Pp
|
||||
Display the input in perusal format:
|
||||
.Bd -literal -offset indent
|
||||
"%06.6_ao " 12/1 "%3_u "
|
||||
"\et\et" "%_p "
|
||||
"\en"
|
||||
.Ed
|
||||
.Pp
|
||||
Implement the \-x option:
|
||||
.Bd -literal -offset indent
|
||||
"%07.7_Ax\en"
|
||||
"%07.7_ax " 8/2 "%04x " "\en"
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr gdb 1 ,
|
||||
.Xr od 1
|
86
hexdump/hexdump.c
Normal file
86
hexdump/hexdump.c
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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 const char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)hexdump.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/usr.bin/hexdump/hexdump.c,v 1.7 2002/09/04 23:29:01 dwmalone Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "hexdump.h"
|
||||
|
||||
FS *fshead; /* head of format strings */
|
||||
int blocksize; /* data block size */
|
||||
int exitval; /* final exit value */
|
||||
int length = -1; /* max bytes to read */
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
FS *tfs;
|
||||
char *p;
|
||||
|
||||
(void)setlocale(LC_ALL, "");
|
||||
|
||||
if (!(p = rindex(argv[0], 'o')) || strcmp(p, "od"))
|
||||
newsyntax(argc, &argv);
|
||||
else
|
||||
oldsyntax(argc, &argv);
|
||||
|
||||
/* figure out the data block size */
|
||||
for (blocksize = 0, tfs = fshead; tfs; tfs = tfs->nextfs) {
|
||||
tfs->bcnt = size(tfs);
|
||||
if (blocksize < tfs->bcnt)
|
||||
blocksize = tfs->bcnt;
|
||||
}
|
||||
/* rewrite the rules, do syntax checking */
|
||||
for (tfs = fshead; tfs; tfs = tfs->nextfs)
|
||||
rewrite(tfs);
|
||||
|
||||
(void)next(argv);
|
||||
display();
|
||||
exit(exitval);
|
||||
}
|
108
hexdump/hexdump.h
Normal file
108
hexdump/hexdump.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* @(#)hexdump.h 8.1 (Berkeley) 6/6/93
|
||||
* $FreeBSD: src/usr.bin/hexdump/hexdump.h,v 1.9 2004/07/11 01:11:12 tjr Exp $
|
||||
*/
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
typedef struct _pr {
|
||||
struct _pr *nextpr; /* next print unit */
|
||||
#define F_ADDRESS 0x001 /* print offset */
|
||||
#define F_BPAD 0x002 /* blank pad */
|
||||
#define F_C 0x004 /* %_c */
|
||||
#define F_CHAR 0x008 /* %c */
|
||||
#define F_DBL 0x010 /* %[EefGf] */
|
||||
#define F_INT 0x020 /* %[di] */
|
||||
#define F_P 0x040 /* %_p */
|
||||
#define F_STR 0x080 /* %s */
|
||||
#define F_U 0x100 /* %_u */
|
||||
#define F_UINT 0x200 /* %[ouXx] */
|
||||
#define F_TEXT 0x400 /* no conversions */
|
||||
u_int flags; /* flag values */
|
||||
int bcnt; /* byte count */
|
||||
char *cchar; /* conversion character */
|
||||
char *fmt; /* printf format */
|
||||
char *nospace; /* no whitespace version */
|
||||
int mbleft; /* bytes left of multibyte char. */
|
||||
mbstate_t mbstate; /* conversion state */
|
||||
} PR;
|
||||
|
||||
typedef struct _fu {
|
||||
struct _fu *nextfu; /* next format unit */
|
||||
struct _pr *nextpr; /* next print unit */
|
||||
#define F_IGNORE 0x01 /* %_A */
|
||||
#define F_SETREP 0x02 /* rep count set, not default */
|
||||
u_int flags; /* flag values */
|
||||
int reps; /* repetition count */
|
||||
int bcnt; /* byte count */
|
||||
char *fmt; /* format string */
|
||||
} FU;
|
||||
|
||||
typedef struct _fs { /* format strings */
|
||||
struct _fs *nextfs; /* linked list of format strings */
|
||||
struct _fu *nextfu; /* linked list of format units */
|
||||
int bcnt;
|
||||
} FS;
|
||||
|
||||
extern FS *fshead; /* head of format strings list */
|
||||
extern FU *endfu; /* format at end-of-data */
|
||||
extern int blocksize; /* data block size */
|
||||
extern int exitval; /* final exit value */
|
||||
extern int odmode; /* are we acting as od(1)? */
|
||||
extern int length; /* amount of data to read */
|
||||
extern off_t skip; /* amount of data to skip at start */
|
||||
enum _vflag { ALL, DUP, FIRST, WAIT }; /* -v values */
|
||||
extern enum _vflag vflag;
|
||||
|
||||
void add(const char *);
|
||||
void addfile(char *);
|
||||
void badcnt(char *);
|
||||
void badconv(char *);
|
||||
void badfmt(const char *);
|
||||
void badsfmt(void);
|
||||
void bpad(PR *);
|
||||
void conv_c(PR *, u_char *, size_t);
|
||||
void conv_u(PR *, u_char *);
|
||||
void display(void);
|
||||
void doskip(const char *, int);
|
||||
void escape(char *);
|
||||
u_char *get(void);
|
||||
void newsyntax(int, char ***);
|
||||
int next(char **);
|
||||
void nomem(void);
|
||||
void oldsyntax(int, char ***);
|
||||
size_t peek(u_char *, size_t);
|
||||
void rewrite(FS *);
|
||||
int size(FS *);
|
||||
void usage(void);
|
147
hexdump/hexsyntax.c
Normal file
147
hexdump/hexsyntax.c
Normal file
@ -0,0 +1,147 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)hexsyntax.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/usr.bin/hexdump/hexsyntax.c,v 1.12 2002/09/04 23:29:01 dwmalone Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "hexdump.h"
|
||||
|
||||
off_t skip; /* bytes to skip */
|
||||
|
||||
void
|
||||
newsyntax(int argc, char ***argvp)
|
||||
{
|
||||
int ch;
|
||||
char *p, **argv;
|
||||
|
||||
argv = *argvp;
|
||||
if ((p = rindex(argv[0], 'h')) != NULL &&
|
||||
strcmp(p, "hd") == 0) {
|
||||
/* "Canonical" format, implies -C. */
|
||||
add("\"%08.8_Ax\n\"");
|
||||
add("\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" ");
|
||||
add("\" |\" 16/1 \"%_p\" \"|\\n\"");
|
||||
}
|
||||
while ((ch = getopt(argc, argv, "bcCde:f:n:os:vx")) != -1)
|
||||
switch (ch) {
|
||||
case 'b':
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"");
|
||||
break;
|
||||
case 'c':
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"");
|
||||
break;
|
||||
case 'C':
|
||||
add("\"%08.8_Ax\n\"");
|
||||
add("\"%08.8_ax \" 8/1 \"%02x \" \" \" 8/1 \"%02x \" ");
|
||||
add("\" |\" 16/1 \"%_p\" \"|\\n\"");
|
||||
break;
|
||||
case 'd':
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 8/2 \" %05u \" \"\\n\"");
|
||||
break;
|
||||
case 'e':
|
||||
add(optarg);
|
||||
break;
|
||||
case 'f':
|
||||
addfile(optarg);
|
||||
break;
|
||||
case 'n':
|
||||
if ((length = atoi(optarg)) < 0)
|
||||
errx(1, "%s: bad length value", optarg);
|
||||
break;
|
||||
case 'o':
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"");
|
||||
break;
|
||||
case 's':
|
||||
if ((skip = strtoll(optarg, &p, 0)) < 0)
|
||||
errx(1, "%s: bad skip value", optarg);
|
||||
switch(*p) {
|
||||
case 'b':
|
||||
skip *= 512;
|
||||
break;
|
||||
case 'k':
|
||||
skip *= 1024;
|
||||
break;
|
||||
case 'm':
|
||||
skip *= 1048576;
|
||||
break;
|
||||
case 'g':
|
||||
skip *= 1073741824;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
vflag = ALL;
|
||||
break;
|
||||
case 'x':
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 8/2 \" %04x \" \"\\n\"");
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
}
|
||||
|
||||
if (!fshead) {
|
||||
add("\"%07.7_Ax\n\"");
|
||||
add("\"%07.7_ax \" 16/1 \"%02x \" \"\\n\"");
|
||||
}
|
||||
|
||||
*argvp += optind;
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
|
||||
"usage: hexdump [-bcCdovx] [-e fmt] [-f fmt_file] [-n length]",
|
||||
" [-s skip] [file ...]",
|
||||
" hd [-bcdovx] [-e fmt] [-f fmt_file] [-n length]",
|
||||
" [-s skip] [file ...]");
|
||||
exit(1);
|
||||
}
|
267
hexdump/od.1
Normal file
267
hexdump/od.1
Normal file
@ -0,0 +1,267 @@
|
||||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)od.1 8.1 (Berkeley) 6/6/93
|
||||
.\" $FreeBSD: src/usr.bin/hexdump/od.1,v 1.17 2004/07/11 01:11:12 tjr Exp $
|
||||
.\"
|
||||
.Dd July 11, 2004
|
||||
.Os
|
||||
.Dt OD 1
|
||||
.Sh NAME
|
||||
.Nm od
|
||||
.Nd octal, decimal, hex, ASCII dump
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl aBbcDdeFfHhIiLlOosvXx
|
||||
.Op Fl A Ar base
|
||||
.Op Fl j Ar skip
|
||||
.Op Fl N Ar length
|
||||
.Op Fl t Ar type
|
||||
.Sm off
|
||||
.Oo
|
||||
.Op Cm \&+
|
||||
.Li offset
|
||||
.Op Cm \&.
|
||||
.Op Cm Bb
|
||||
.Oc
|
||||
.Sm on
|
||||
.Op Ar
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility is a filter which displays the specified files, or standard
|
||||
input if no files are specified, in a user specified format.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width ".Fl I , L , l"
|
||||
.It Fl A Ar base
|
||||
Specify the input address base.
|
||||
.Ar base
|
||||
may be one of
|
||||
.Cm d ,
|
||||
.Cm o ,
|
||||
.Cm x
|
||||
or
|
||||
.Cm n ,
|
||||
which specify decimal, octal, hexadecimal
|
||||
addresses or no address, respectively.
|
||||
.It Fl a
|
||||
Output named characters.
|
||||
Equivalent to
|
||||
.Fl t Ar a .
|
||||
.It Fl B , o
|
||||
Output octal shorts.
|
||||
Equivalent to
|
||||
.Fl t Ar o2 .
|
||||
.It Fl b
|
||||
Output octal bytes.
|
||||
Equivalent to
|
||||
.Fl t Ar o1 .
|
||||
.It Fl c
|
||||
Output C-style escaped characters.
|
||||
Equivalent to
|
||||
.Fl t Ar c .
|
||||
.It Fl D
|
||||
Output unsigned decimal ints.
|
||||
Equivalent to
|
||||
.Fl t Ar u4 .
|
||||
.It Fl e , F
|
||||
Output double-precision floating point numbers.
|
||||
Equivalent to
|
||||
.Fl t Ar fD .
|
||||
.It Fl f
|
||||
Output single-precision floating point numbers.
|
||||
Equivalent to
|
||||
.Fl t Ar fF .
|
||||
.It Fl H , X
|
||||
Output hexadecimal ints.
|
||||
Equivalent to
|
||||
.Fl t Ar x4 .
|
||||
.It Fl h , x
|
||||
Output hexadecimal shorts.
|
||||
Equivalent to
|
||||
.Fl t Ar x2 .
|
||||
.It Fl I , L , l
|
||||
Output signed decimal longs.
|
||||
Equivalent to
|
||||
.Fl t Ar dL .
|
||||
.It Fl i
|
||||
Output signed decimal ints.
|
||||
Equivalent to
|
||||
.Fl t Ar dI .
|
||||
.It Fl j Ar skip
|
||||
Skip
|
||||
.Ar skip
|
||||
bytes of the combined input before dumping.
|
||||
The number may be followed by one
|
||||
of
|
||||
.Cm b , k
|
||||
or
|
||||
.Cm m
|
||||
which specify the units of the number as blocks (512 bytes), kilobytes and
|
||||
megabytes, respectively.
|
||||
.It Fl N Ar length
|
||||
Dump at most
|
||||
.Ar length
|
||||
bytes of input.
|
||||
.It Fl O
|
||||
Output octal ints.
|
||||
Equivalent to
|
||||
.Fl t Ar o4 .
|
||||
.It Fl s
|
||||
Output signed decimal shorts.
|
||||
Equivalent to
|
||||
.Fl t Ar d2 .
|
||||
.It Fl t Ar type
|
||||
Specify the output format.
|
||||
.Ar type
|
||||
is a string containing one or more of the following kinds of type specifiers:
|
||||
.Bl -tag -width indent
|
||||
.It Cm a
|
||||
Named characters
|
||||
.Pq Tn ASCII .
|
||||
Control characters are displayed using the following names:
|
||||
.Bl -column "000 NUL" "001 SOH" "002 STX" "003 ETX" "004 EOT" "005 ENQ"
|
||||
.It "000 NUL 001 SOH 002 STX 003 ETX 004 EOT 005 ENQ"
|
||||
.It "006 ACK 007 BEL 008 BS 009 HT 00a NL 00b VT"
|
||||
.It "00c FF 00d CR 00e SO 00f SI 010 DLE 011 DC1"
|
||||
.It "012 DC2 013 DC3 014 DC4 015 NAK 016 SYN 017 ETB"
|
||||
.It "018 CAN 019 EM 01a SUB 01b ESC 01c FS 01d GS"
|
||||
.It "01e RS 01f US 020 SP 0ff DEL"
|
||||
.El
|
||||
.It Cm c
|
||||
Characters in the default character set.
|
||||
Non-printing characters are
|
||||
represented as 3-digit octal character codes, except the following
|
||||
characters, which are represented as C escapes:
|
||||
.Pp
|
||||
.Bl -tag -width carriage-return -compact
|
||||
.It NUL
|
||||
\e0
|
||||
.It alert
|
||||
\ea
|
||||
.It backspace
|
||||
\eb
|
||||
.It newline
|
||||
\en
|
||||
.It carriage-return
|
||||
\er
|
||||
.It tab
|
||||
\et
|
||||
.It vertical tab
|
||||
\ev
|
||||
.El
|
||||
.Pp
|
||||
Multi-byte characters are displayed in the area corresponding to the first
|
||||
byte of the character. The remaining bytes are shown as
|
||||
.Ql ** .
|
||||
.It Xo
|
||||
.Sm off
|
||||
.Op Cm d | o | u | x
|
||||
.Op Cm C | S | I | L | Ar n
|
||||
.Sm on
|
||||
.Xc
|
||||
Signed decimal
|
||||
.Pq Cm d ,
|
||||
octal
|
||||
.Pq Cm o ,
|
||||
unsigned decimal
|
||||
.Pq Cm u
|
||||
or
|
||||
hexadecimal
|
||||
.Pq Cm x .
|
||||
Followed by an optional size specifier, which may be either
|
||||
.Cm C
|
||||
.Pq Vt char ,
|
||||
.Cm S
|
||||
.Pq Vt short ,
|
||||
.Cm I
|
||||
.Pq Vt int ,
|
||||
.Cm L
|
||||
.Pq Vt long ,
|
||||
or a byte count as a decimal integer.
|
||||
.It Xo
|
||||
.Sm off
|
||||
.Cm f
|
||||
.Op Cm F | D | L | Ar n
|
||||
.Sm on
|
||||
.Xc
|
||||
Floating-point number.
|
||||
Followed by an optional size specifier, which may be either
|
||||
.Cm F
|
||||
.Pq Vt float ,
|
||||
.Cm D
|
||||
.Pq Vt double
|
||||
or
|
||||
.Cm L
|
||||
.Pq Vt "long double" .
|
||||
.El
|
||||
.It Fl v
|
||||
Write all input data, instead of replacing lines of duplicate values with a
|
||||
.Ql * .
|
||||
.El
|
||||
.Pp
|
||||
Multiple options that specify output format may be used; the output will
|
||||
contain one line for each format.
|
||||
.Pp
|
||||
If no output format is specified,
|
||||
.Fl t Ar oS
|
||||
is assumed.
|
||||
.Sh ENVIRONMENT
|
||||
The
|
||||
.Ev LANG , LC_ALL
|
||||
and
|
||||
.Ev LC_CTYPE
|
||||
environment variables affect the execution of
|
||||
.Nm
|
||||
as described in
|
||||
.Xr environ 7 .
|
||||
.Sh DIAGNOSTICS
|
||||
.Ex -std
|
||||
.Sh COMPATIBILITY
|
||||
The traditional
|
||||
.Fl s
|
||||
option to extract string constants is not supported; consider using
|
||||
.Xr strings 1
|
||||
instead.
|
||||
.Sh SEE ALSO
|
||||
.Xr hexdump 1 ,
|
||||
.Xr strings 1
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility conforms to
|
||||
.St -p1003.1-2001 .
|
||||
.Sh HISTORY
|
||||
An
|
||||
.Nm
|
||||
command appeared in
|
||||
.At v1 .
|
447
hexdump/odsyntax.c
Normal file
447
hexdump/odsyntax.c
Normal file
@ -0,0 +1,447 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)odsyntax.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/usr.bin/hexdump/odsyntax.c,v 1.16 2002/09/04 23:29:01 dwmalone Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <float.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "hexdump.h"
|
||||
|
||||
#define PADDING " "
|
||||
|
||||
int odmode;
|
||||
|
||||
static void odadd(const char *);
|
||||
static void odformat(const char *);
|
||||
static const char *odformatfp(char, const char *);
|
||||
static const char *odformatint(char, const char *);
|
||||
static void odoffset(int, char ***);
|
||||
static void odusage(void);
|
||||
|
||||
void
|
||||
oldsyntax(int argc, char ***argvp)
|
||||
{
|
||||
static char _n[] = "%_n", padding[] = PADDING;
|
||||
int ch;
|
||||
char **argv, *end;
|
||||
|
||||
/* Add initial (default) address format. -A may change it later. */
|
||||
#define TYPE_OFFSET 7
|
||||
add("\"%07.7_Ao\n\"");
|
||||
add("\"%07.7_ao \"");
|
||||
|
||||
odmode = 1;
|
||||
argv = *argvp;
|
||||
while ((ch = getopt(argc, argv, "A:aBbcDdeFfHhIij:LlN:Oost:vXx")) != -1)
|
||||
switch (ch) {
|
||||
case 'A':
|
||||
switch (*optarg) {
|
||||
case 'd': case 'o': case 'x':
|
||||
fshead->nextfu->fmt[TYPE_OFFSET] = *optarg;
|
||||
fshead->nextfs->nextfu->fmt[TYPE_OFFSET] =
|
||||
*optarg;
|
||||
break;
|
||||
case 'n':
|
||||
fshead->nextfu->fmt = _n; /* mimic regular output */
|
||||
fshead->nextfs->nextfu->fmt = padding;
|
||||
break;
|
||||
default:
|
||||
errx(1, "%s: invalid address base", optarg);
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
odformat("a");
|
||||
break;
|
||||
case 'B':
|
||||
case 'o':
|
||||
odformat("o2");
|
||||
break;
|
||||
case 'b':
|
||||
odformat("o1");
|
||||
break;
|
||||
case 'c':
|
||||
odformat("c");
|
||||
break;
|
||||
case 'd':
|
||||
odformat("u2");
|
||||
break;
|
||||
case 'D':
|
||||
odformat("u4");
|
||||
break;
|
||||
case 'e': /* undocumented in od */
|
||||
case 'F':
|
||||
odformat("fD");
|
||||
break;
|
||||
case 'f':
|
||||
odformat("fF");
|
||||
break;
|
||||
case 'H':
|
||||
case 'X':
|
||||
odformat("x4");
|
||||
break;
|
||||
case 'h':
|
||||
case 'x':
|
||||
odformat("x2");
|
||||
break;
|
||||
case 'I':
|
||||
case 'L':
|
||||
case 'l':
|
||||
odformat("dL");
|
||||
break;
|
||||
case 'i':
|
||||
odformat("dI");
|
||||
break;
|
||||
case 'j':
|
||||
errno = 0;
|
||||
skip = strtoll(optarg, &end, 0);
|
||||
if (*end == 'b')
|
||||
skip *= 512;
|
||||
else if (*end == 'k')
|
||||
skip *= 1024;
|
||||
else if (*end == 'm')
|
||||
skip *= 1048576L;
|
||||
else if (*end == 'g')
|
||||
skip *= 1073741824;
|
||||
else if (*end != '\0')
|
||||
skip = -1;
|
||||
if (errno != 0 || skip < 0 || strlen(end) > 1)
|
||||
errx(1, "%s: invalid skip amount", optarg);
|
||||
break;
|
||||
case 'N':
|
||||
if ((length = atoi(optarg)) <= 0)
|
||||
errx(1, "%s: invalid length", optarg);
|
||||
break;
|
||||
case 'O':
|
||||
odformat("o4");
|
||||
break;
|
||||
case 's':
|
||||
odformat("d2");
|
||||
break;
|
||||
case 't':
|
||||
odformat(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
vflag = ALL;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
odusage();
|
||||
}
|
||||
|
||||
if (fshead->nextfs->nextfs == NULL)
|
||||
odformat("oS");
|
||||
|
||||
argc -= optind;
|
||||
*argvp += optind;
|
||||
|
||||
if (argc)
|
||||
odoffset(argc, argvp);
|
||||
}
|
||||
|
||||
static void
|
||||
odusage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr,
|
||||
"usage: od [-aBbcDdeFfHhIiLlOosvXx] [-A base] [-j skip] [-N length] [-t type]\n");
|
||||
fprintf(stderr,
|
||||
" [[+]offset[.][Bb]] [file ...]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
odoffset(int argc, char ***argvp)
|
||||
{
|
||||
unsigned char *p, *q, *num, *end;
|
||||
int base;
|
||||
|
||||
/*
|
||||
* The offset syntax of od(1) was genuinely bizarre. First, if
|
||||
* it started with a plus it had to be an offset. Otherwise, if
|
||||
* there were at least two arguments, a number or lower-case 'x'
|
||||
* followed by a number makes it an offset. By default it was
|
||||
* octal; if it started with 'x' or '0x' it was hex. If it ended
|
||||
* in a '.', it was decimal. If a 'b' or 'B' was appended, it
|
||||
* multiplied the number by 512 or 1024 byte units. There was
|
||||
* no way to assign a block count to a hex offset.
|
||||
*
|
||||
* We assume it's a file if the offset is bad.
|
||||
*/
|
||||
p = (unsigned char *)(argc == 1 ? (*argvp)[0] : (*argvp)[1]);
|
||||
|
||||
if (*p != '+' && (argc < 2 ||
|
||||
(!isdigit(p[0]) && (p[0] != 'x' || !isxdigit(p[1])))))
|
||||
return;
|
||||
|
||||
base = 0;
|
||||
/*
|
||||
* skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
|
||||
* set base.
|
||||
*/
|
||||
if (p[0] == '+')
|
||||
++p;
|
||||
if (p[0] == 'x' && isxdigit(p[1])) {
|
||||
++p;
|
||||
base = 16;
|
||||
} else if (p[0] == '0' && p[1] == 'x') {
|
||||
p += 2;
|
||||
base = 16;
|
||||
}
|
||||
|
||||
/* skip over the number */
|
||||
if (base == 16)
|
||||
for (num = p; isxdigit(*p); ++p);
|
||||
else
|
||||
for (num = p; isdigit(*p); ++p);
|
||||
|
||||
/* check for no number */
|
||||
if (num == p)
|
||||
return;
|
||||
q = p;
|
||||
/* if terminates with a '.', base is decimal */
|
||||
if (*q == '.') {
|
||||
if (base)
|
||||
return;
|
||||
base = 10;
|
||||
q++;
|
||||
}
|
||||
|
||||
skip = strtoll((const char *)num, (char **)&end, base ? base : 8);
|
||||
|
||||
/* if end isn't the same as p, we got a non-octal digit */
|
||||
if (end != p) {
|
||||
skip = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (*q) {
|
||||
if (*q == 'B') {
|
||||
skip *= 1024;
|
||||
++p;
|
||||
} else if (*q == 'b') {
|
||||
skip *= 512;
|
||||
++q;
|
||||
}
|
||||
}
|
||||
|
||||
if (*q) {
|
||||
skip = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the offset uses a non-octal base, the base of the offset
|
||||
* is changed as well. This isn't pretty, but it's easy.
|
||||
*/
|
||||
if (base == 16) {
|
||||
fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
|
||||
fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
|
||||
} else if (base == 10) {
|
||||
fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
|
||||
fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
|
||||
}
|
||||
|
||||
/* Terminate file list. */
|
||||
(*argvp)[1] = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
odformat(const char *fmt)
|
||||
{
|
||||
char fchar;
|
||||
|
||||
while (*fmt != '\0') {
|
||||
switch ((fchar = *fmt++)) {
|
||||
case 'a':
|
||||
odadd("16/1 \"%3_u \" \"\\n\"");
|
||||
break;
|
||||
case 'c':
|
||||
odadd("16/1 \"%3_c \" \"\\n\"");
|
||||
break;
|
||||
case 'o': case 'u': case 'd': case 'x':
|
||||
fmt = odformatint(fchar, fmt);
|
||||
break;
|
||||
case 'f':
|
||||
fmt = odformatfp(fchar, fmt);
|
||||
break;
|
||||
default:
|
||||
errx(1, "%c: unrecognised format character", fchar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
odformatfp(char fchar __unused, const char *fmt)
|
||||
{
|
||||
size_t isize;
|
||||
int digits;
|
||||
char *end, *hdfmt;
|
||||
|
||||
isize = sizeof(double);
|
||||
switch (*fmt) {
|
||||
case 'F':
|
||||
isize = sizeof(float);
|
||||
fmt++;
|
||||
break;
|
||||
case 'D':
|
||||
isize = sizeof(double);
|
||||
fmt++;
|
||||
break;
|
||||
case 'L':
|
||||
isize = sizeof(long double);
|
||||
fmt++;
|
||||
break;
|
||||
default:
|
||||
if (isdigit((unsigned char)*fmt)) {
|
||||
errno = 0;
|
||||
isize = (size_t)strtoul(fmt, &end, 10);
|
||||
if (errno != 0 || isize == 0)
|
||||
errx(1, "%s: invalid size", fmt);
|
||||
fmt = (const char *)end;
|
||||
}
|
||||
}
|
||||
switch (isize) {
|
||||
case sizeof(float):
|
||||
digits = FLT_DIG;
|
||||
break;
|
||||
case sizeof(double):
|
||||
digits = DBL_DIG;
|
||||
break;
|
||||
default:
|
||||
if (isize == sizeof(long double))
|
||||
digits = LDBL_DIG;
|
||||
else
|
||||
errx(1, "unsupported floating point size %lu",
|
||||
(u_long)isize);
|
||||
}
|
||||
|
||||
asprintf(&hdfmt, "%lu/%lu \" %%%d.%de \" \"\\n\"",
|
||||
16UL / (u_long)isize, (u_long)isize, digits + 8, digits);
|
||||
if (hdfmt == NULL)
|
||||
err(1, NULL);
|
||||
odadd(hdfmt);
|
||||
free(hdfmt);
|
||||
|
||||
return (fmt);
|
||||
}
|
||||
|
||||
static const char *
|
||||
odformatint(char fchar, const char *fmt)
|
||||
{
|
||||
unsigned long long n;
|
||||
size_t isize;
|
||||
int digits;
|
||||
char *end, *hdfmt;
|
||||
|
||||
isize = sizeof(int);
|
||||
switch (*fmt) {
|
||||
case 'C':
|
||||
isize = sizeof(char);
|
||||
fmt++;
|
||||
break;
|
||||
case 'I':
|
||||
isize = sizeof(int);
|
||||
fmt++;
|
||||
break;
|
||||
case 'L':
|
||||
isize = sizeof(long);
|
||||
fmt++;
|
||||
break;
|
||||
case 'S':
|
||||
isize = sizeof(short);
|
||||
fmt++;
|
||||
break;
|
||||
default:
|
||||
if (isdigit((unsigned char)*fmt)) {
|
||||
errno = 0;
|
||||
isize = (size_t)strtoul(fmt, &end, 10);
|
||||
if (errno != 0 || isize == 0)
|
||||
errx(1, "%s: invalid size", fmt);
|
||||
if (isize != sizeof(char) && isize != sizeof(short) &&
|
||||
isize != sizeof(int) && isize != sizeof(long))
|
||||
errx(1, "unsupported int size %lu",
|
||||
(u_long)isize);
|
||||
fmt = (const char *)end;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the maximum number of digits we need to
|
||||
* fit the number. Overestimate for decimal with log
|
||||
* base 8. We need one extra space for signed numbers
|
||||
* to store the sign.
|
||||
*/
|
||||
n = (1ULL << (8 * isize)) - 1;
|
||||
digits = 0;
|
||||
while (n != 0) {
|
||||
digits++;
|
||||
n >>= (fchar == 'x') ? 4 : 3;
|
||||
}
|
||||
if (fchar == 'd')
|
||||
digits++;
|
||||
asprintf(&hdfmt, "%lu/%lu \"%*s%%%s%d%c\" \"\\n\"",
|
||||
16UL / (u_long)isize, (u_long)isize, (int)(4 * isize - digits),
|
||||
"", (fchar == 'd' || fchar == 'u') ? "" : "0", digits, fchar);
|
||||
if (hdfmt == NULL)
|
||||
err(1, NULL);
|
||||
odadd(hdfmt);
|
||||
free(hdfmt);
|
||||
|
||||
return (fmt);
|
||||
}
|
||||
|
||||
static void
|
||||
odadd(const char *fmt)
|
||||
{
|
||||
static int needpad;
|
||||
|
||||
if (needpad)
|
||||
add("\""PADDING"\"");
|
||||
add(fmt);
|
||||
needpad = 1;
|
||||
}
|
523
hexdump/parse.c
Normal file
523
hexdump/parse.c
Normal file
@ -0,0 +1,523 @@
|
||||
/*
|
||||
* 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
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/usr.bin/hexdump/parse.c,v 1.12 2002/09/04 23:29:01 dwmalone Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "hexdump.h"
|
||||
|
||||
FU *endfu; /* format at end-of-data */
|
||||
|
||||
void
|
||||
addfile(char *name)
|
||||
{
|
||||
unsigned char *p;
|
||||
FILE *fp;
|
||||
int ch;
|
||||
char buf[2048 + 1];
|
||||
|
||||
if ((fp = fopen(name, "r")) == NULL)
|
||||
err(1, "%s", name);
|
||||
while (fgets(buf, sizeof(buf), fp)) {
|
||||
if (!(p = (unsigned char *)index(buf, '\n'))) {
|
||||
warnx("line too long");
|
||||
while ((ch = getchar()) != '\n' && ch != EOF);
|
||||
continue;
|
||||
}
|
||||
*p = '\0';
|
||||
for (p = (unsigned char *)buf; *p && isspace(*p); ++p);
|
||||
if (!*p || *p == '#')
|
||||
continue;
|
||||
add((const char *)p);
|
||||
}
|
||||
(void)fclose(fp);
|
||||
}
|
||||
|
||||
void
|
||||
add(const char *fmt)
|
||||
{
|
||||
unsigned const char *p, *savep;
|
||||
static FS **nextfs;
|
||||
FS *tfs;
|
||||
FU *tfu, **nextfu;
|
||||
|
||||
/* start new linked list of format units */
|
||||
if ((tfs = calloc(1, sizeof(FS))) == NULL)
|
||||
err(1, NULL);
|
||||
if (!fshead)
|
||||
fshead = tfs;
|
||||
else
|
||||
*nextfs = tfs;
|
||||
nextfs = &tfs->nextfs;
|
||||
nextfu = &tfs->nextfu;
|
||||
|
||||
/* take the format string and break it up into format units */
|
||||
for (p = (unsigned const char *)fmt;;) {
|
||||
/* skip leading white space */
|
||||
for (; isspace(*p); ++p);
|
||||
if (!*p)
|
||||
break;
|
||||
|
||||
/* allocate a new format unit and link it in */
|
||||
if ((tfu = calloc(1, sizeof(FU))) == NULL)
|
||||
err(1, NULL);
|
||||
*nextfu = tfu;
|
||||
nextfu = &tfu->nextfu;
|
||||
tfu->reps = 1;
|
||||
|
||||
/* if leading digit, repetition count */
|
||||
if (isdigit(*p)) {
|
||||
for (savep = p; isdigit(*p); ++p);
|
||||
if (!isspace(*p) && *p != '/')
|
||||
badfmt(fmt);
|
||||
/* may overwrite either white space or slash */
|
||||
tfu->reps = atoi((const char *)savep);
|
||||
tfu->flags = F_SETREP;
|
||||
/* skip trailing white space */
|
||||
for (++p; isspace(*p); ++p);
|
||||
}
|
||||
|
||||
/* skip slash and trailing white space */
|
||||
if (*p == '/')
|
||||
while (isspace(*++p));
|
||||
|
||||
/* byte count */
|
||||
if (isdigit(*p)) {
|
||||
for (savep = p; isdigit(*p); ++p);
|
||||
if (!isspace(*p))
|
||||
badfmt(fmt);
|
||||
tfu->bcnt = atoi((const char *)savep);
|
||||
/* skip trailing white space */
|
||||
for (++p; isspace(*p); ++p);
|
||||
}
|
||||
|
||||
/* format */
|
||||
if (*p != '"')
|
||||
badfmt(fmt);
|
||||
for (savep = ++p; *p != '"';)
|
||||
if (*p++ == 0)
|
||||
badfmt(fmt);
|
||||
if (!(tfu->fmt = malloc(p - savep + 1)))
|
||||
err(1, NULL);
|
||||
(void) strncpy(tfu->fmt, (const char *)savep, p - savep);
|
||||
tfu->fmt[p - savep] = '\0';
|
||||
escape(tfu->fmt);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *spec = ".#-+ 0123456789";
|
||||
|
||||
int
|
||||
size(FS *fs)
|
||||
{
|
||||
FU *fu;
|
||||
int bcnt, cursize;
|
||||
unsigned char *fmt;
|
||||
int prec;
|
||||
|
||||
/* figure out the data block size needed for each format unit */
|
||||
for (cursize = 0, fu = fs->nextfu; fu; fu = fu->nextfu) {
|
||||
if (fu->bcnt) {
|
||||
cursize += fu->bcnt * fu->reps;
|
||||
continue;
|
||||
}
|
||||
for (bcnt = prec = 0, fmt = (unsigned char *)fu->fmt; *fmt; ++fmt) {
|
||||
if (*fmt != '%')
|
||||
continue;
|
||||
/*
|
||||
* skip any special chars -- save precision in
|
||||
* case it's a %s format.
|
||||
*/
|
||||
while (index(spec + 1, *++fmt));
|
||||
if (*fmt == '.' && isdigit(*++fmt)) {
|
||||
prec = atoi((const char *)fmt);
|
||||
while (isdigit(*++fmt));
|
||||
}
|
||||
switch(*fmt) {
|
||||
case 'c':
|
||||
bcnt += 1;
|
||||
break;
|
||||
case 'd': case 'i': case 'o': case 'u':
|
||||
case 'x': case 'X':
|
||||
bcnt += 4;
|
||||
break;
|
||||
case 'e': case 'E': case 'f': case 'g': case 'G':
|
||||
bcnt += 8;
|
||||
break;
|
||||
case 's':
|
||||
bcnt += prec;
|
||||
break;
|
||||
case '_':
|
||||
switch(*++fmt) {
|
||||
case 'c': case 'p': case 'u':
|
||||
bcnt += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
cursize += bcnt * fu->reps;
|
||||
}
|
||||
return (cursize);
|
||||
}
|
||||
|
||||
void
|
||||
rewrite(FS *fs)
|
||||
{
|
||||
enum { NOTOKAY, USEBCNT, USEPREC } sokay;
|
||||
PR *pr, **nextpr = NULL;
|
||||
FU *fu;
|
||||
unsigned char *p1, *p2, *fmtp;
|
||||
char savech, cs[3];
|
||||
int nconv, prec = 0;
|
||||
|
||||
for (fu = fs->nextfu; fu; fu = fu->nextfu) {
|
||||
/*
|
||||
* Break each format unit into print units; each conversion
|
||||
* character gets its own.
|
||||
*/
|
||||
for (nconv = 0, fmtp = (unsigned char *)fu->fmt; *fmtp; nextpr = &pr->nextpr) {
|
||||
if ((pr = calloc(1, sizeof(PR))) == NULL)
|
||||
err(1, NULL);
|
||||
if (!fu->nextpr)
|
||||
fu->nextpr = pr;
|
||||
else
|
||||
*nextpr = pr;
|
||||
|
||||
/* Skip preceding text and up to the next % sign. */
|
||||
for (p1 = fmtp; *p1 && *p1 != '%'; ++p1);
|
||||
|
||||
/* Only text in the string. */
|
||||
if (!*p1) {
|
||||
pr->fmt = (char *)fmtp;
|
||||
pr->flags = F_TEXT;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get precision for %s -- if have a byte count, don't
|
||||
* need it.
|
||||
*/
|
||||
if (fu->bcnt) {
|
||||
sokay = USEBCNT;
|
||||
/* Skip to conversion character. */
|
||||
for (++p1; index(spec, *p1); ++p1);
|
||||
} else {
|
||||
/* Skip any special chars, field width. */
|
||||
while (index(spec + 1, *++p1));
|
||||
if (*p1 == '.' && isdigit(*++p1)) {
|
||||
sokay = USEPREC;
|
||||
prec = atoi((const char *)p1);
|
||||
while (isdigit(*++p1));
|
||||
} else
|
||||
sokay = NOTOKAY;
|
||||
}
|
||||
|
||||
p2 = p1 + 1; /* Set end pointer. */
|
||||
cs[0] = *p1; /* Set conversion string. */
|
||||
cs[1] = '\0';
|
||||
|
||||
/*
|
||||
* Figure out the byte count for each conversion;
|
||||
* rewrite the format as necessary, set up blank-
|
||||
* padding for end of data.
|
||||
*/
|
||||
switch(cs[0]) {
|
||||
case 'c':
|
||||
pr->flags = F_CHAR;
|
||||
switch(fu->bcnt) {
|
||||
case 0: case 1:
|
||||
pr->bcnt = 1;
|
||||
break;
|
||||
default:
|
||||
p1[1] = '\0';
|
||||
badcnt((char *)p1);
|
||||
}
|
||||
break;
|
||||
case 'd': case 'i':
|
||||
pr->flags = F_INT;
|
||||
goto isint;
|
||||
case 'o': case 'u': case 'x': case 'X':
|
||||
pr->flags = F_UINT;
|
||||
isint: cs[2] = '\0';
|
||||
cs[1] = cs[0];
|
||||
cs[0] = 'q';
|
||||
switch(fu->bcnt) {
|
||||
case 0: case 4:
|
||||
pr->bcnt = 4;
|
||||
break;
|
||||
case 1:
|
||||
pr->bcnt = 1;
|
||||
break;
|
||||
case 2:
|
||||
pr->bcnt = 2;
|
||||
break;
|
||||
#ifdef __APPLE__
|
||||
case 8:
|
||||
pr->bcnt = 8;
|
||||
break;
|
||||
#endif /* __APPLE__ */
|
||||
default:
|
||||
p1[1] = '\0';
|
||||
badcnt((char *)p1);
|
||||
}
|
||||
break;
|
||||
case 'e': case 'E': case 'f': case 'g': case 'G':
|
||||
pr->flags = F_DBL;
|
||||
switch(fu->bcnt) {
|
||||
case 0: case 8:
|
||||
pr->bcnt = 8;
|
||||
break;
|
||||
case 4:
|
||||
pr->bcnt = 4;
|
||||
break;
|
||||
default:
|
||||
if (fu->bcnt == sizeof(long double)) {
|
||||
cs[2] = '\0';
|
||||
cs[1] = cs[0];
|
||||
cs[0] = 'L';
|
||||
pr->bcnt = sizeof(long double);
|
||||
} else {
|
||||
p1[1] = '\0';
|
||||
badcnt((char *)p1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
pr->flags = F_STR;
|
||||
switch(sokay) {
|
||||
case NOTOKAY:
|
||||
badsfmt();
|
||||
case USEBCNT:
|
||||
pr->bcnt = fu->bcnt;
|
||||
break;
|
||||
case USEPREC:
|
||||
pr->bcnt = prec;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '_':
|
||||
++p2;
|
||||
switch(p1[1]) {
|
||||
case 'A':
|
||||
endfu = fu;
|
||||
fu->flags |= F_IGNORE;
|
||||
/* FALLTHROUGH */
|
||||
case 'a':
|
||||
pr->flags = F_ADDRESS;
|
||||
++p2;
|
||||
switch(p1[2]) {
|
||||
case 'd': case 'o': case'x':
|
||||
cs[0] = 'q';
|
||||
cs[1] = p1[2];
|
||||
cs[2] = '\0';
|
||||
break;
|
||||
default:
|
||||
p1[3] = '\0';
|
||||
badconv((char *)p1);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
pr->flags = F_C;
|
||||
/* cs[0] = 'c'; set in conv_c */
|
||||
goto isint2;
|
||||
case 'p':
|
||||
pr->flags = F_P;
|
||||
cs[0] = 'c';
|
||||
goto isint2;
|
||||
case 'u':
|
||||
pr->flags = F_U;
|
||||
/* cs[0] = 'c'; set in conv_u */
|
||||
isint2: switch(fu->bcnt) {
|
||||
case 0: case 1:
|
||||
pr->bcnt = 1;
|
||||
break;
|
||||
default:
|
||||
p1[2] = '\0';
|
||||
badcnt((char *)p1);
|
||||
}
|
||||
break;
|
||||
case 'n': /* Force -A n to dump extra blank line like default od behavior */
|
||||
endfu = fu;
|
||||
fu->flags = F_IGNORE;
|
||||
pr->flags = F_TEXT;
|
||||
fmtp = (unsigned char *)"\n";
|
||||
cs[0] = '\0';
|
||||
break;
|
||||
default:
|
||||
p1[2] = '\0';
|
||||
badconv((char *)p1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
p1[1] = '\0';
|
||||
badconv((char *)p1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy to PR format string, set conversion character
|
||||
* pointer, update original.
|
||||
*/
|
||||
savech = *p2;
|
||||
p1[0] = '\0';
|
||||
if ((pr->fmt = calloc(1, strlen((const char *)fmtp) + 2)) == NULL)
|
||||
err(1, NULL);
|
||||
(void)strcpy(pr->fmt, (const char *)fmtp);
|
||||
(void)strcat(pr->fmt, cs);
|
||||
*p2 = savech;
|
||||
pr->cchar = pr->fmt + (p1 - fmtp);
|
||||
fmtp = p2;
|
||||
|
||||
/* Only one conversion character if byte count. */
|
||||
if (!(pr->flags&F_ADDRESS) && fu->bcnt && nconv++)
|
||||
errx(1, "byte count with multiple conversion characters");
|
||||
}
|
||||
/*
|
||||
* If format unit byte count not specified, figure it out
|
||||
* so can adjust rep count later.
|
||||
*/
|
||||
if (!fu->bcnt)
|
||||
for (pr = fu->nextpr; pr; pr = pr->nextpr)
|
||||
fu->bcnt += pr->bcnt;
|
||||
}
|
||||
/*
|
||||
* If the format string interprets any data at all, and it's
|
||||
* not the same as the blocksize, and its last format unit
|
||||
* interprets any data at all, and has no iteration count,
|
||||
* repeat it as necessary.
|
||||
*
|
||||
* If, rep count is greater than 1, no trailing whitespace
|
||||
* gets output from the last iteration of the format unit.
|
||||
*/
|
||||
for (fu = fs->nextfu; fu; fu = fu->nextfu) {
|
||||
if (!fu->nextfu && fs->bcnt < blocksize &&
|
||||
!(fu->flags&F_SETREP) && fu->bcnt)
|
||||
fu->reps += (blocksize - fs->bcnt) / fu->bcnt;
|
||||
if (fu->reps > 1) {
|
||||
for (pr = fu->nextpr;; pr = pr->nextpr)
|
||||
if (!pr->nextpr)
|
||||
break;
|
||||
for (p1 = (unsigned char *)pr->fmt, p2 = NULL; *p1; ++p1)
|
||||
p2 = isspace(*p1) ? p1 : NULL;
|
||||
if (p2)
|
||||
pr->nospace = (char *)p2;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
for (fu = fs->nextfu; fu; fu = fu->nextfu) {
|
||||
(void)printf("fmt:");
|
||||
for (pr = fu->nextpr; pr; pr = pr->nextpr)
|
||||
(void)printf(" {%s}", pr->fmt);
|
||||
(void)printf("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
escape(char *p1)
|
||||
{
|
||||
char *p2;
|
||||
|
||||
/* alphabetic escape sequences have to be done in place */
|
||||
for (p2 = p1;; ++p1, ++p2) {
|
||||
if (!*p1) {
|
||||
*p2 = *p1;
|
||||
break;
|
||||
}
|
||||
if (*p1 == '\\')
|
||||
switch(*++p1) {
|
||||
case 'a':
|
||||
/* *p2 = '\a'; */
|
||||
*p2 = '\007';
|
||||
break;
|
||||
case 'b':
|
||||
*p2 = '\b';
|
||||
break;
|
||||
case 'f':
|
||||
*p2 = '\f';
|
||||
break;
|
||||
case 'n':
|
||||
*p2 = '\n';
|
||||
break;
|
||||
case 'r':
|
||||
*p2 = '\r';
|
||||
break;
|
||||
case 't':
|
||||
*p2 = '\t';
|
||||
break;
|
||||
case 'v':
|
||||
*p2 = '\v';
|
||||
break;
|
||||
default:
|
||||
*p2 = *p1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
badcnt(char *s)
|
||||
{
|
||||
errx(1, "%s: bad byte count", s);
|
||||
}
|
||||
|
||||
void
|
||||
badsfmt(void)
|
||||
{
|
||||
errx(1, "%%s: requires a precision or a byte count");
|
||||
}
|
||||
|
||||
void
|
||||
badfmt(const char *fmt)
|
||||
{
|
||||
errx(1, "\"%s\": bad format", fmt);
|
||||
}
|
||||
|
||||
void
|
||||
badconv(char *ch)
|
||||
{
|
||||
errx(1, "%%%s: bad conversion character", ch);
|
||||
}
|
67
hostname/hostname.1
Normal file
67
hostname/hostname.1
Normal file
@ -0,0 +1,67 @@
|
||||
.\"-
|
||||
.\" Copyright (c) 1983, 1988, 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.
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)hostname.1 8.2 (Berkeley) 4/28/95
|
||||
.\" $FreeBSD: src/bin/hostname/hostname.1,v 1.21 2006/12/08 07:47:08 kientzle Exp $
|
||||
.\"
|
||||
.Dd December 7, 2006
|
||||
.Dt HOSTNAME 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm hostname
|
||||
.Nd set or print name of current host system
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl fs
|
||||
.Op Ar name-of-host
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility prints the name of the current host.
|
||||
The super-user can
|
||||
set the hostname by supplying an argument.
|
||||
To keep the hostname between reboots, run
|
||||
.Sq scutil --set HostName Ar name-of-host .
|
||||
.Pp
|
||||
Options:
|
||||
.Bl -tag -width flag
|
||||
.It Fl f
|
||||
Include domain information in the printed name.
|
||||
This is the default behavior.
|
||||
.It Fl s
|
||||
Trim off any domain information from the printed
|
||||
name.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr gethostname 3 ,
|
||||
.Xr scutil 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.2 .
|
105
hostname/hostname.c
Normal file
105
hostname/hostname.c
Normal file
@ -0,0 +1,105 @@
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char const 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[] = "@(#)hostname.c 8.1 (Berkeley) 5/31/93";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/bin/hostname/hostname.c,v 1.19 2006/12/08 07:47:08 kientzle Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch, sflag;
|
||||
char *p, hostname[MAXHOSTNAMELEN];
|
||||
|
||||
sflag = 0;
|
||||
while ((ch = getopt(argc, argv, "fs")) != -1)
|
||||
switch (ch) {
|
||||
case 'f':
|
||||
/*
|
||||
* On Linux, "hostname -f" prints FQDN.
|
||||
* BSD "hostname" always prints FQDN by
|
||||
* default, so we accept but ignore -f.
|
||||
*/
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc > 1)
|
||||
usage();
|
||||
|
||||
if (*argv) {
|
||||
if (sethostname(*argv, (int)strlen(*argv)))
|
||||
err(1, "sethostname");
|
||||
} else {
|
||||
if (gethostname(hostname, (int)sizeof(hostname)))
|
||||
err(1, "gethostname");
|
||||
if (sflag) {
|
||||
p = strchr(hostname, '.');
|
||||
if (p != NULL)
|
||||
*p = '\0';
|
||||
}
|
||||
(void)printf("%s\n", hostname);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "usage: hostname [-fs] [name-of-host]\n");
|
||||
exit(1);
|
||||
}
|
63
id/groups.1
Normal file
63
id/groups.1
Normal file
@ -0,0 +1,63 @@
|
||||
.\" Copyright (c) 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)groups.1 8.1 (Berkeley) 6/6/93
|
||||
.\" $FreeBSD: src/usr.bin/id/groups.1,v 1.10 2006/12/23 17:14:01 ru Exp $
|
||||
.\"
|
||||
.Dd June 6, 1993
|
||||
.Dt GROUPS 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm groups
|
||||
.Nd show group memberships
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Ar user
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility has been obsoleted by the
|
||||
.Xr id 1
|
||||
utility, and is equivalent to
|
||||
.Dq Nm id Fl Gn Op Ar user .
|
||||
The command
|
||||
.Dq Nm id Fl p
|
||||
is suggested for normal interactive use.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility displays the groups to which you (or the optionally specified
|
||||
.Ar user )
|
||||
belong.
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh SEE ALSO
|
||||
.Xr id 1
|
167
id/id.1
Normal file
167
id/id.1
Normal file
@ -0,0 +1,167 @@
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)id.1 8.1 (Berkeley) 6/6/93
|
||||
.\" $FreeBSD: src/usr.bin/id/id.1,v 1.18 2006/09/26 22:28:12 ceri Exp $
|
||||
.\"
|
||||
.Dd September 26, 2006
|
||||
.Dt ID 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm id
|
||||
.Nd return user identity
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Ar user
|
||||
.Nm
|
||||
.Fl A
|
||||
.Nm
|
||||
.Fl F
|
||||
.Op Ar user
|
||||
.Nm
|
||||
.Fl G Op Fl n
|
||||
.Op Ar user
|
||||
.Nm
|
||||
.Fl M
|
||||
.Nm
|
||||
.Fl P
|
||||
.Op Ar user
|
||||
.Nm
|
||||
.Fl g Op Fl nr
|
||||
.Op Ar user
|
||||
.Nm
|
||||
.Fl p
|
||||
.Op Ar user
|
||||
.Nm
|
||||
.Fl u Op Fl nr
|
||||
.Op Ar user
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility displays the user and group names and numeric IDs, of the
|
||||
calling process, to the standard output.
|
||||
If the real and effective IDs are different, both are displayed,
|
||||
otherwise only the real ID is displayed.
|
||||
.Pp
|
||||
If a
|
||||
.Ar user
|
||||
(login name or user ID)
|
||||
is specified, the user and group IDs of that user are displayed.
|
||||
In this case, the real and effective IDs are assumed to be the same.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl A
|
||||
Display the process audit user ID and other process audit properties, which
|
||||
requires privilege.
|
||||
.It Fl F
|
||||
Display the full name of the user.
|
||||
.It Fl G
|
||||
Display the different group IDs (effective, real and supplementary)
|
||||
as white-space separated numbers, in no particular order.
|
||||
.It Fl M
|
||||
Display the MAC label of the current process.
|
||||
.It Fl P
|
||||
Display the id as a password file entry.
|
||||
.It Fl a
|
||||
Ignored for compatibility with other
|
||||
.Nm
|
||||
implementations.
|
||||
.It Fl g
|
||||
Display the effective group ID as a number.
|
||||
.It Fl n
|
||||
Display the name of the user or group ID for the
|
||||
.Fl G ,
|
||||
.Fl g
|
||||
and
|
||||
.Fl u
|
||||
options instead of the number.
|
||||
If any of the ID numbers cannot be mapped into names, the number will be
|
||||
displayed as usual.
|
||||
.It Fl p
|
||||
Make the output human-readable.
|
||||
If the user name returned by
|
||||
.Xr getlogin 2
|
||||
is different from the login name referenced by the user ID, the name
|
||||
returned by
|
||||
.Xr getlogin 2
|
||||
is displayed, preceded by the keyword
|
||||
.Dq login .
|
||||
The user ID as a name is displayed, preceded by the keyword
|
||||
.Dq uid .
|
||||
If the effective user ID is different from the real user ID, the real user
|
||||
ID is displayed as a name, preceded by the keyword
|
||||
.Dq euid .
|
||||
If the effective group ID is different from the real group ID, the real group
|
||||
ID is displayed as a name, preceded by the keyword
|
||||
.Dq rgid .
|
||||
The list of groups to which the user belongs is then displayed as names,
|
||||
preceded by the keyword
|
||||
.Dq groups .
|
||||
Each display is on a separate line.
|
||||
.It Fl r
|
||||
Display the real ID for the
|
||||
.Fl g
|
||||
and
|
||||
.Fl u
|
||||
options instead of the effective ID.
|
||||
.It Fl u
|
||||
Display the effective user ID as a number.
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh SEE ALSO
|
||||
.Xr who 1
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
function is expected to conform to
|
||||
.St -p1003.2 .
|
||||
.Sh HISTORY
|
||||
The
|
||||
historic
|
||||
.Xr groups 1
|
||||
command is equivalent to
|
||||
.Dq Nm id Fl Gn Op Ar user .
|
||||
.Pp
|
||||
The
|
||||
historic
|
||||
.Xr whoami 1
|
||||
command is equivalent to
|
||||
.Dq Nm id Fl un .
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.4 .
|
529
id/id.c
Normal file
529
id/id.c
Normal file
@ -0,0 +1,529 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)id.c 8.2 (Berkeley) 2/16/94";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/usr.bin/id/id.c,v 1.33 2006/12/29 12:28:34 stefanf Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#ifndef __APPLE__
|
||||
#include <sys/mac.h>
|
||||
#endif /* !__APPLE__ */
|
||||
|
||||
#ifdef USE_BSM_AUDIT
|
||||
#include <bsm/audit.h>
|
||||
#endif
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void id_print(struct passwd *, int, int, int);
|
||||
void pline(struct passwd *);
|
||||
void pretty(struct passwd *);
|
||||
void auditid(void);
|
||||
void fullname(struct passwd *);
|
||||
void group(struct passwd *, int);
|
||||
void maclabel(void);
|
||||
void usage(void);
|
||||
struct passwd *who(char *);
|
||||
|
||||
int isgroups, iswhoami;
|
||||
|
||||
#ifdef __APPLE__
|
||||
// SPI for 5235093
|
||||
int32_t getgrouplist_2(const char *, gid_t, gid_t **);
|
||||
#endif
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct group *gr;
|
||||
struct passwd *pw;
|
||||
int Gflag, Mflag, Pflag, ch, gflag, id, nflag, pflag, rflag, uflag;
|
||||
int Aflag;
|
||||
int Fflag;
|
||||
const char *myname;
|
||||
|
||||
Gflag = Mflag = Pflag = gflag = nflag = pflag = rflag = uflag = 0;
|
||||
Aflag = 0;
|
||||
Fflag = 0;
|
||||
|
||||
myname = strrchr(argv[0], '/');
|
||||
myname = (myname != NULL) ? myname + 1 : argv[0];
|
||||
if (strcmp(myname, "groups") == 0) {
|
||||
isgroups = 1;
|
||||
Gflag = nflag = 1;
|
||||
}
|
||||
else if (strcmp(myname, "whoami") == 0) {
|
||||
iswhoami = 1;
|
||||
uflag = nflag = 1;
|
||||
}
|
||||
|
||||
while ((ch = getopt(argc, argv,
|
||||
(isgroups || iswhoami) ? "" : "AFPGMagnpru")) != -1)
|
||||
switch(ch) {
|
||||
#ifdef USE_BSM_AUDIT
|
||||
case 'A':
|
||||
Aflag = 1;
|
||||
break;
|
||||
#endif
|
||||
case 'F':
|
||||
Fflag = 1;
|
||||
break;
|
||||
case 'G':
|
||||
Gflag = 1;
|
||||
break;
|
||||
case 'M':
|
||||
Mflag = 1;
|
||||
break;
|
||||
case 'P':
|
||||
Pflag = 1;
|
||||
break;
|
||||
case 'a':
|
||||
break;
|
||||
case 'g':
|
||||
gflag = 1;
|
||||
break;
|
||||
case 'n':
|
||||
nflag = 1;
|
||||
break;
|
||||
case 'p':
|
||||
pflag = 1;
|
||||
break;
|
||||
case 'r':
|
||||
rflag = 1;
|
||||
break;
|
||||
case 'u':
|
||||
uflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (iswhoami && argc > 0)
|
||||
usage();
|
||||
|
||||
switch(Aflag + Fflag + Gflag + Mflag + Pflag + gflag + pflag + uflag) {
|
||||
case 1:
|
||||
break;
|
||||
case 0:
|
||||
if (!nflag && !rflag)
|
||||
break;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
pw = *argv ? who(*argv) : NULL;
|
||||
|
||||
if (Mflag && pw != NULL)
|
||||
usage();
|
||||
|
||||
#ifdef USE_BSM_AUDIT
|
||||
if (Aflag) {
|
||||
auditid();
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (Fflag) {
|
||||
fullname(pw);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (gflag) {
|
||||
id = pw ? pw->pw_gid : rflag ? getgid() : getegid();
|
||||
if (nflag && (gr = getgrgid(id)))
|
||||
(void)printf("%s\n", gr->gr_name);
|
||||
else
|
||||
(void)printf("%u\n", id);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (uflag) {
|
||||
id = pw ? pw->pw_uid : rflag ? getuid() : geteuid();
|
||||
if (nflag && (pw = getpwuid(id)))
|
||||
(void)printf("%s\n", pw->pw_name);
|
||||
else
|
||||
(void)printf("%u\n", id);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (Gflag) {
|
||||
group(pw, nflag);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (Mflag) {
|
||||
maclabel();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (Pflag) {
|
||||
pline(pw);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (pflag) {
|
||||
pretty(pw);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (pw) {
|
||||
id_print(pw, 1, 0, 0);
|
||||
}
|
||||
else {
|
||||
id = getuid();
|
||||
pw = getpwuid(id);
|
||||
id_print(pw, 0, 1, 1);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
pretty(struct passwd *pw)
|
||||
{
|
||||
struct group *gr;
|
||||
u_int eid, rid;
|
||||
char *login;
|
||||
|
||||
if (pw) {
|
||||
(void)printf("uid\t%s\n", pw->pw_name);
|
||||
(void)printf("groups\t");
|
||||
group(pw, 1);
|
||||
} else {
|
||||
if ((login = getlogin()) == NULL)
|
||||
err(1, "getlogin");
|
||||
|
||||
pw = getpwuid(rid = getuid());
|
||||
if (pw == NULL || strcmp(login, pw->pw_name))
|
||||
(void)printf("login\t%s\n", login);
|
||||
if (pw)
|
||||
(void)printf("uid\t%s\n", pw->pw_name);
|
||||
else
|
||||
(void)printf("uid\t%u\n", rid);
|
||||
|
||||
if ((eid = geteuid()) != rid) {
|
||||
if ((pw = getpwuid(eid)))
|
||||
(void)printf("euid\t%s\n", pw->pw_name);
|
||||
else
|
||||
(void)printf("euid\t%u\n", eid);
|
||||
}
|
||||
if ((rid = getgid()) != (eid = getegid())) {
|
||||
if ((gr = getgrgid(rid)))
|
||||
(void)printf("rgid\t%s\n", gr->gr_name);
|
||||
else
|
||||
(void)printf("rgid\t%u\n", rid);
|
||||
}
|
||||
(void)printf("groups\t");
|
||||
group(NULL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
id_print(struct passwd *pw, int use_ggl, int p_euid, int p_egid)
|
||||
{
|
||||
struct group *gr;
|
||||
gid_t gid, egid, lastgid;
|
||||
uid_t uid, euid;
|
||||
int cnt, ngroups;
|
||||
#ifdef __APPLE__
|
||||
gid_t *groups = NULL;
|
||||
#else
|
||||
gid_t groups[NGROUPS + 1];
|
||||
#endif
|
||||
const char *fmt;
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (pw == NULL) {
|
||||
pw = getpwuid(getuid());
|
||||
}
|
||||
|
||||
use_ggl = 1;
|
||||
#endif
|
||||
|
||||
if (pw != NULL) {
|
||||
uid = pw->pw_uid;
|
||||
gid = pw->pw_gid;
|
||||
}
|
||||
else {
|
||||
uid = getuid();
|
||||
gid = getgid();
|
||||
}
|
||||
|
||||
if (use_ggl && pw != NULL) {
|
||||
#ifdef __APPLE__
|
||||
// 5235093
|
||||
ngroups = getgrouplist_2(pw->pw_name, gid, &groups);
|
||||
#else
|
||||
ngroups = NGROUPS + 1;
|
||||
getgrouplist(pw->pw_name, gid, groups, &ngroups);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#ifdef __APPLE__
|
||||
groups = malloc((NGROUPS + 1) * sizeof(gid_t));
|
||||
#endif
|
||||
ngroups = getgroups(NGROUPS + 1, groups);
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (ngroups < 0)
|
||||
warn("failed to retrieve group list");
|
||||
#endif
|
||||
|
||||
if (pw != NULL)
|
||||
printf("uid=%u(%s)", uid, pw->pw_name);
|
||||
else
|
||||
printf("uid=%u", getuid());
|
||||
printf(" gid=%u", gid);
|
||||
if ((gr = getgrgid(gid)))
|
||||
(void)printf("(%s)", gr->gr_name);
|
||||
if (p_euid && (euid = geteuid()) != uid) {
|
||||
(void)printf(" euid=%u", euid);
|
||||
if ((pw = getpwuid(euid)))
|
||||
(void)printf("(%s)", pw->pw_name);
|
||||
}
|
||||
if (p_egid && (egid = getegid()) != gid) {
|
||||
(void)printf(" egid=%u", egid);
|
||||
if ((gr = getgrgid(egid)))
|
||||
(void)printf("(%s)", gr->gr_name);
|
||||
}
|
||||
fmt = " groups=%u";
|
||||
for (lastgid = -1, cnt = 0; cnt < ngroups; ++cnt) {
|
||||
if (lastgid == (gid = groups[cnt]))
|
||||
continue;
|
||||
printf(fmt, gid);
|
||||
fmt = ",%u";
|
||||
if ((gr = getgrgid(gid)))
|
||||
printf("(%s)", gr->gr_name);
|
||||
lastgid = gid;
|
||||
}
|
||||
printf("\n");
|
||||
#ifdef __APPLE__
|
||||
free(groups);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_BSM_AUDIT
|
||||
void
|
||||
auditid(void)
|
||||
{
|
||||
auditinfo_addr_t auditinfo;
|
||||
|
||||
if (getaudit_addr(&auditinfo, sizeof(auditinfo)) < 0)
|
||||
err(1, "getaudit");
|
||||
printf("auid=%d\n", auditinfo.ai_auid);
|
||||
printf("mask.success=0x%08x\n", auditinfo.ai_mask.am_success);
|
||||
printf("mask.failure=0x%08x\n", auditinfo.ai_mask.am_failure);
|
||||
printf("termid.port=0x%08x\n", auditinfo.ai_termid.at_port);
|
||||
printf("asid=%d\n", auditinfo.ai_asid);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
fullname(struct passwd *pw)
|
||||
{
|
||||
|
||||
if (!pw) {
|
||||
if ((pw = getpwuid(getuid())) == NULL)
|
||||
err(1, "getpwuid");
|
||||
}
|
||||
|
||||
(void)printf("%s\n", pw->pw_gecos);
|
||||
}
|
||||
|
||||
void
|
||||
group(struct passwd *pw, int nflag)
|
||||
{
|
||||
struct group *gr;
|
||||
int cnt, id, lastid, ngroups;
|
||||
#ifdef __APPLE__
|
||||
gid_t *groups = NULL;
|
||||
#else
|
||||
gid_t groups[NGROUPS + 1];
|
||||
#endif
|
||||
const char *fmt;
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (pw == NULL) {
|
||||
pw = getpwuid(getuid());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pw) {
|
||||
#ifdef __APPLE__
|
||||
// 5235093
|
||||
ngroups = getgrouplist_2(pw->pw_name, pw->pw_gid, &groups);
|
||||
#else
|
||||
ngroups = NGROUPS + 1;
|
||||
(void) getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef __APPLE__
|
||||
groups = malloc((NGROUPS + 1) * sizeof(gid_t));
|
||||
#endif
|
||||
groups[0] = getgid();
|
||||
ngroups = getgroups(NGROUPS, groups + 1) + 1;
|
||||
}
|
||||
fmt = nflag ? "%s" : "%u";
|
||||
for (lastid = -1, cnt = 0; cnt < ngroups; ++cnt) {
|
||||
if (lastid == (id = groups[cnt]))
|
||||
continue;
|
||||
if (nflag) {
|
||||
if ((gr = getgrgid(id)))
|
||||
(void)printf(fmt, gr->gr_name);
|
||||
else
|
||||
(void)printf(*fmt == ' ' ? " %u" : "%u",
|
||||
id);
|
||||
fmt = " %s";
|
||||
} else {
|
||||
(void)printf(fmt, id);
|
||||
fmt = " %u";
|
||||
}
|
||||
lastid = id;
|
||||
}
|
||||
(void)printf("\n");
|
||||
#ifdef __APPLE__
|
||||
free(groups);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
maclabel(void)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
errx(1, "-M unsupported");
|
||||
#else /* !__APPLE__ */
|
||||
char *string;
|
||||
mac_t label;
|
||||
int error;
|
||||
|
||||
error = mac_prepare_process_label(&label);
|
||||
if (error == -1)
|
||||
errx(1, "mac_prepare_type: %s", strerror(errno));
|
||||
|
||||
error = mac_get_proc(label);
|
||||
if (error == -1)
|
||||
errx(1, "mac_get_proc: %s", strerror(errno));
|
||||
|
||||
error = mac_to_text(label, &string);
|
||||
if (error == -1)
|
||||
errx(1, "mac_to_text: %s", strerror(errno));
|
||||
|
||||
(void)printf("%s\n", string);
|
||||
mac_free(label);
|
||||
free(string);
|
||||
#endif /* __APPLE__ */
|
||||
}
|
||||
|
||||
struct passwd *
|
||||
who(char *u)
|
||||
{
|
||||
struct passwd *pw;
|
||||
long id;
|
||||
char *ep;
|
||||
|
||||
/*
|
||||
* Translate user argument into a pw pointer. First, try to
|
||||
* get it as specified. If that fails, try it as a number.
|
||||
*/
|
||||
if ((pw = getpwnam(u)))
|
||||
return(pw);
|
||||
id = strtol(u, &ep, 10);
|
||||
if (*u && !*ep && (pw = getpwuid(id)))
|
||||
return(pw);
|
||||
errx(1, "%s: no such user", u);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
void
|
||||
pline(struct passwd *pw)
|
||||
{
|
||||
|
||||
if (!pw) {
|
||||
if ((pw = getpwuid(getuid())) == NULL)
|
||||
err(1, "getpwuid");
|
||||
}
|
||||
|
||||
(void)printf("%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name,
|
||||
pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
|
||||
(long)pw->pw_change, (long)pw->pw_expire, pw->pw_gecos,
|
||||
pw->pw_dir, pw->pw_shell);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
if (isgroups)
|
||||
(void)fprintf(stderr, "usage: groups [user]\n");
|
||||
else if (iswhoami)
|
||||
(void)fprintf(stderr, "usage: whoami\n");
|
||||
else
|
||||
(void)fprintf(stderr, "%s\n%s%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
|
||||
"usage: id [user]",
|
||||
#ifdef USE_BSM_AUDIT
|
||||
" id -A\n",
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
" id -F [user]",
|
||||
" id -G [-n] [user]",
|
||||
" id -M",
|
||||
" id -P [user]",
|
||||
" id -g [-nr] [user]",
|
||||
" id -p [user]",
|
||||
" id -u [-nr] [user]");
|
||||
exit(1);
|
||||
}
|
229
id/open_directory.c
Normal file
229
id/open_directory.c
Normal file
@ -0,0 +1,229 @@
|
||||
#include <membership.h>
|
||||
|
||||
#include "open_directory.h"
|
||||
|
||||
ODNodeRef
|
||||
CreateNode(void)
|
||||
{
|
||||
CFErrorRef error = NULL;
|
||||
ODNodeRef node = NULL;
|
||||
|
||||
node = ODNodeCreateWithNodeType(NULL, kODSessionDefault, kODTypeAuthenticationSearchNode, &error);
|
||||
|
||||
if (node == NULL) {
|
||||
CFShow(error);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static ODRecordRef
|
||||
CopyRecordWithUUID(ODNodeRef node, CFStringRef type, uuid_t uuid)
|
||||
{
|
||||
CFErrorRef error = NULL;
|
||||
char uuidstr[37];
|
||||
CFStringRef uuidref;
|
||||
ODQueryRef query = NULL;
|
||||
CFTypeRef vals[] = { CFSTR(kDSAttributesStandardAll) };
|
||||
CFArrayRef attributes = CFArrayCreate(NULL, vals, 1, &kCFTypeArrayCallBacks);
|
||||
CFArrayRef results = NULL;
|
||||
ODRecordRef record = NULL;
|
||||
|
||||
uuid_unparse(uuid, uuidstr);
|
||||
uuidref = CFStringCreateWithCString(NULL, uuidstr, kCFStringEncodingUTF8);
|
||||
|
||||
if (uuidref) {
|
||||
query = ODQueryCreateWithNode(NULL, node, type, CFSTR(kDS1AttrGeneratedUID), kODMatchEqualTo, uuidref, attributes, 100, &error);
|
||||
|
||||
if (query) {
|
||||
results = ODQueryCopyResults(query, false, &error);
|
||||
|
||||
if (results) {
|
||||
if (CFArrayGetCount(results) == 1) {
|
||||
record = (ODRecordRef)CFArrayGetValueAtIndex(results, 0);
|
||||
CFRetain(record);
|
||||
}
|
||||
|
||||
CFRelease(results);
|
||||
}
|
||||
|
||||
CFRelease(query);
|
||||
}
|
||||
|
||||
CFRelease(uuidref);
|
||||
}
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
ODRecordRef
|
||||
CopyGroupRecordWithGID(ODNodeRef node, gid_t gid)
|
||||
{
|
||||
uuid_t uuid;
|
||||
|
||||
mbr_gid_to_uuid(gid, uuid);
|
||||
|
||||
return CopyRecordWithUUID(node, CFSTR(kDSStdRecordTypeGroups), uuid);
|
||||
}
|
||||
|
||||
ODRecordRef
|
||||
CopyUserRecordWithUID(ODNodeRef node, uid_t uid)
|
||||
{
|
||||
uuid_t uuid;
|
||||
|
||||
mbr_uid_to_uuid(uid, uuid);
|
||||
|
||||
return CopyRecordWithUUID(node, CFSTR(kDSStdRecordTypeUsers), uuid);
|
||||
}
|
||||
|
||||
ODRecordRef
|
||||
CopyUserRecordWithUsername(ODNodeRef node, char *name)
|
||||
{
|
||||
CFStringRef nameref;
|
||||
CFTypeRef vals[] = { CFSTR(kDSAttributesStandardAll) };
|
||||
CFArrayRef attributes = CFArrayCreate(NULL, vals, 1, &kCFTypeArrayCallBacks);
|
||||
CFErrorRef error;
|
||||
|
||||
nameref = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
|
||||
|
||||
if (nameref == NULL)
|
||||
return NULL;
|
||||
|
||||
return ODNodeCopyRecord(node, CFSTR(kDSStdRecordTypeUsers), nameref, attributes, &error);
|
||||
}
|
||||
|
||||
CFStringRef
|
||||
CopyAttrFromRecord(ODRecordRef record, CFStringRef attribute)
|
||||
{
|
||||
CFErrorRef error = NULL;
|
||||
CFArrayRef values = ODRecordCopyValues(record, attribute, &error);
|
||||
CFStringRef result = NULL;
|
||||
|
||||
if (values) {
|
||||
if (CFArrayGetCount(values) == 1) {
|
||||
result = CFArrayGetValueAtIndex(values, 0);
|
||||
CFRetain(result);
|
||||
}
|
||||
CFRelease(values);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
GetIntAttrFromRecord(ODRecordRef record, CFStringRef attribute, int *output)
|
||||
{
|
||||
int status = 1;
|
||||
CFStringRef str = CopyAttrFromRecord(record, attribute);
|
||||
|
||||
if (str) {
|
||||
*output = CFStringGetIntValue(str);
|
||||
status = 0;
|
||||
CFRelease(str);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uid_t
|
||||
GetUIDFromRecord(ODRecordRef record)
|
||||
{
|
||||
int uid = -1;
|
||||
|
||||
GetIntAttrFromRecord(record, CFSTR(kDS1AttrUniqueID), &uid);
|
||||
|
||||
return uid;
|
||||
}
|
||||
|
||||
gid_t
|
||||
GetGIDFromRecord(ODRecordRef record)
|
||||
{
|
||||
int gid = -1;
|
||||
|
||||
GetIntAttrFromRecord(record, CFSTR(kDS1AttrPrimaryGroupID), &gid);
|
||||
|
||||
return gid;
|
||||
}
|
||||
|
||||
CFArrayRef
|
||||
CopyGroupRecordsForUser(ODNodeRef node, ODRecordRef user, CFIndex limit)
|
||||
{
|
||||
CFMutableArrayRef groups;
|
||||
gid_t primary_gid;
|
||||
ODRecordRef primary_group;
|
||||
CFErrorRef error = NULL;
|
||||
ODQueryRef query;
|
||||
CFArrayRef results;
|
||||
int i;
|
||||
ODRecordRef gr;
|
||||
|
||||
query = ODQueryCreateWithNode(NULL, node, CFSTR(kDSStdRecordTypeGroups),
|
||||
CFSTR(kDSNAttrMember), kODMatchContains, ODRecordGetRecordName(user), NULL, limit, &error);
|
||||
results = ODQueryCopyResults(query, false, &error);
|
||||
CFRelease(query);
|
||||
|
||||
groups = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
|
||||
|
||||
primary_gid = GetGIDFromRecord(user);
|
||||
primary_group = CopyGroupRecordWithGID(node, primary_gid);
|
||||
CFArrayAppendValue(groups, primary_group);
|
||||
CFRelease(primary_group);
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(results); i++) {
|
||||
gr = (ODRecordRef)CFArrayGetValueAtIndex(results, i);
|
||||
if (GetGIDFromRecord(gr) != primary_gid) {
|
||||
CFArrayAppendValue(groups, gr);
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(results);
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
static int
|
||||
cvfprintf(FILE *file, const char *format, va_list args)
|
||||
{
|
||||
char* cstr;
|
||||
int result = 0;
|
||||
CFStringRef formatStr = CFStringCreateWithCStringNoCopy(NULL, format, kCFStringEncodingUTF8, kCFAllocatorNull);
|
||||
if (formatStr) {
|
||||
CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, formatStr, args);
|
||||
if (str) {
|
||||
size_t size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8) + 1;
|
||||
cstr = malloc(size);
|
||||
if (cstr && CFStringGetCString(str, cstr, size, kCFStringEncodingUTF8)) {
|
||||
result = fprintf(file, "%s", cstr);
|
||||
free(cstr);
|
||||
}
|
||||
CFRelease(str);
|
||||
}
|
||||
CFRelease(formatStr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
cfprintf(FILE *file, const char *format, ...)
|
||||
{
|
||||
int result;
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
result = cvfprintf(file, format, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
cprintf(const char *format, ...)
|
||||
{
|
||||
int result;
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
result = cvfprintf(stdout, format, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
18
id/open_directory.h
Normal file
18
id/open_directory.h
Normal file
@ -0,0 +1,18 @@
|
||||
#include <OpenDirectory/OpenDirectory.h>
|
||||
|
||||
ODNodeRef CreateNode(void);
|
||||
|
||||
ODRecordRef CopyGroupRecordWithGID(ODNodeRef, gid_t);
|
||||
|
||||
ODRecordRef CopyUserRecordWithUID(ODNodeRef, uid_t);
|
||||
ODRecordRef CopyUserRecordWithUsername(ODNodeRef, char *);
|
||||
|
||||
CFArrayRef CopyGroupRecordsForUser(ODNodeRef, ODRecordRef, CFIndex);
|
||||
|
||||
CFStringRef CopyAttrFromRecord(ODRecordRef record, CFStringRef attribute);
|
||||
int GetIntAttrFromRecord(ODRecordRef record, CFStringRef attribute, int *output);
|
||||
uid_t GetUIDFromRecord(ODRecordRef);
|
||||
gid_t GetGIDFromRecord(ODRecordRef);
|
||||
|
||||
int cfprintf(FILE *file, const char *format, ...);
|
||||
int cprintf(const char *format, ...);
|
60
id/whoami.1
Normal file
60
id/whoami.1
Normal file
@ -0,0 +1,60 @@
|
||||
.\" Copyright (c) 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)whoami.1 8.1 (Berkeley) 6/6/93
|
||||
.\" $FreeBSD: src/usr.bin/id/whoami.1,v 1.9 2005/01/17 07:44:19 ru Exp $
|
||||
.\"
|
||||
.Dd June 6, 1993
|
||||
.Dt WHOAMI 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm whoami
|
||||
.Nd display effective user id
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility has been obsoleted by the
|
||||
.Xr id 1
|
||||
utility, and is equivalent to
|
||||
.Dq Nm id Fl un .
|
||||
The command
|
||||
.Dq Nm id Fl p
|
||||
is suggested for normal interactive use.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility displays your effective user ID as a name.
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh SEE ALSO
|
||||
.Xr id 1
|
251
jot/jot.1
Normal file
251
jot/jot.1
Normal file
@ -0,0 +1,251 @@
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)jot.1 8.1 (Berkeley) 6/6/93
|
||||
.\" $FreeBSD: src/usr.bin/jot/jot.1,v 1.24 2010/02/20 00:16:44 delphij Exp $
|
||||
.\"
|
||||
.Dd February 19, 2010
|
||||
.Dt JOT 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm jot
|
||||
.Nd print sequential or random data
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl cnr
|
||||
.Op Fl b Ar word
|
||||
.Op Fl w Ar word
|
||||
.Op Fl s Ar string
|
||||
.Op Fl p Ar precision
|
||||
.Op Ar reps Op Ar begin Op Ar end Op Ar s
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility is used to print out increasing, decreasing, random,
|
||||
or redundant data, usually numbers, one per line.
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl r
|
||||
Generate random data instead of the default sequential data.
|
||||
.It Fl b Ar word
|
||||
Just print
|
||||
.Ar word
|
||||
repetitively.
|
||||
.It Fl w Ar word
|
||||
Print
|
||||
.Ar word
|
||||
with the generated data appended to it.
|
||||
Octal, hexadecimal, exponential,
|
||||
.Tn ASCII ,
|
||||
zero padded,
|
||||
and right-adjusted representations
|
||||
are possible by using the appropriate
|
||||
.Xr printf 3
|
||||
conversion specification inside
|
||||
.Ar word ,
|
||||
in which case the data are inserted rather than appended.
|
||||
.It Fl c
|
||||
This is an abbreviation for
|
||||
.Fl w Ar %c .
|
||||
.It Fl s Ar string
|
||||
Print data separated by
|
||||
.Ar string .
|
||||
Normally, newlines separate data.
|
||||
.It Fl n
|
||||
Do not print the final newline normally appended to the output.
|
||||
.It Fl p Ar precision
|
||||
Print only as many digits or characters of the data
|
||||
as indicated by the integer
|
||||
.Ar precision .
|
||||
In the absence of
|
||||
.Fl p ,
|
||||
the precision is the greater of the precisions of
|
||||
.Ar begin
|
||||
and
|
||||
.Ar end .
|
||||
The
|
||||
.Fl p
|
||||
option is overridden by whatever appears in a
|
||||
.Xr printf 3
|
||||
conversion following
|
||||
.Fl w .
|
||||
.El
|
||||
.Pp
|
||||
The last four arguments indicate, respectively,
|
||||
the number of data, the lower bound, the upper bound,
|
||||
and the step size or, for random data, the seed.
|
||||
While at least one of them must appear,
|
||||
any of the other three may be omitted, and
|
||||
will be considered as such if given as
|
||||
.Fl ""
|
||||
or as an empty string.
|
||||
Any three of these arguments determines the fourth.
|
||||
If four are specified and the given and computed values of
|
||||
.Ar reps
|
||||
conflict, the lower value is used.
|
||||
If fewer than three are specified, defaults are assigned
|
||||
left to right, except for
|
||||
.Ar s ,
|
||||
which assumes a default of 1 or -1 if both
|
||||
.Ar begin
|
||||
and
|
||||
.Ar end
|
||||
are given.
|
||||
.Pp
|
||||
Defaults for the four arguments are, respectively,
|
||||
100, 1, 100, and 1, except that when random data are requested,
|
||||
the seed,
|
||||
.Ar s ,
|
||||
is picked randomly.
|
||||
The
|
||||
.Ar reps
|
||||
argument is expected to be an unsigned integer,
|
||||
and if given as zero is taken to be infinite.
|
||||
The
|
||||
.Ar begin
|
||||
and
|
||||
.Ar end
|
||||
arguments may be given as real numbers or as characters
|
||||
representing the corresponding value in
|
||||
.Tn ASCII .
|
||||
The last argument must be a real number.
|
||||
.Pp
|
||||
Random numbers are obtained through
|
||||
.Xr arc4random 3
|
||||
when no seed is specified,
|
||||
and through
|
||||
.Xr random 3
|
||||
when a seed is given.
|
||||
When
|
||||
.Nm
|
||||
is asked to generate random integers or characters with begin
|
||||
and end values in the range of the random number generator function
|
||||
and no format is specified with one of the
|
||||
.Fl w ,
|
||||
.Fl b ,
|
||||
or
|
||||
.Fl p
|
||||
options,
|
||||
.Nm
|
||||
will arrange for all the values in the range to appear in the output
|
||||
with an equal probability.
|
||||
In all other cases be careful to ensure that the output format's
|
||||
rounding or truncation will not skew the distribution of output
|
||||
values in an unintended way.
|
||||
.Pp
|
||||
The name
|
||||
.Nm
|
||||
derives in part from
|
||||
.Nm iota ,
|
||||
a function in APL.
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh EXAMPLES
|
||||
The command
|
||||
.Dl jot - 1 10
|
||||
.Pp
|
||||
prints the integers from 1 to 10,
|
||||
while the command
|
||||
.Dl jot 21 -1 1.00
|
||||
.Pp
|
||||
prints 21 evenly spaced numbers increasing from -1 to 1.
|
||||
The
|
||||
.Tn ASCII
|
||||
character set is generated with
|
||||
.Dl jot -c 128 0
|
||||
.Pp
|
||||
and the strings xaa through xaz with
|
||||
.Dl jot -w xa%c 26 a
|
||||
.Pp
|
||||
while 20 random 8-letter strings are produced with
|
||||
.Dl "jot -r -c 160 a z | rs -g 0 8"
|
||||
.Pp
|
||||
Infinitely many
|
||||
.Em yes Ns 's
|
||||
may be obtained through
|
||||
.Dl jot -b yes 0
|
||||
.Pp
|
||||
and thirty
|
||||
.Xr ed 1
|
||||
substitution commands applying to lines 2, 7, 12, etc.\& is
|
||||
the result of
|
||||
.Dl jot -w %ds/old/new/ 30 2 - 5
|
||||
.Pp
|
||||
The stuttering sequence 9, 9, 8, 8, 7, etc.\& can be
|
||||
produced by suitable choice of step size,
|
||||
as in
|
||||
.Dl jot - 9 0 -.5
|
||||
.Pp
|
||||
and a file containing exactly 1024 bytes is created with
|
||||
.Dl jot -b x 512 > block
|
||||
.Pp
|
||||
Finally, to set tabs four spaces apart starting
|
||||
from column 10 and ending in column 132, use
|
||||
.Dl expand -`jot -s, - 10 132 4`
|
||||
.Pp
|
||||
and to print all lines 80 characters or longer,
|
||||
.Dl grep `jot -s \&"\&" -b \&. 80`
|
||||
.Sh DIAGNOSTICS
|
||||
The following diagnostic messages deserve special explanation:
|
||||
.Bl -diag
|
||||
.It "illegal or unsupported format '%s'"
|
||||
The requested conversion format specifier for
|
||||
.Xr printf 3
|
||||
was not of the form
|
||||
.Dl %[#][ ][{+,-}][0-9]*[.[0-9]*]?
|
||||
where
|
||||
.Dq ?\&
|
||||
must be one of
|
||||
.Dl [l]{d,i,o,u,x}
|
||||
or
|
||||
.Dl {c,e,f,g,D,E,G,O,U,X}
|
||||
.It "range error in conversion"
|
||||
A value to be printed fell outside the range of the data type
|
||||
associated with the requested output format.
|
||||
.It "too many conversions"
|
||||
More than one conversion format specifier has been supplied,
|
||||
but only one is allowed.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr ed 1 ,
|
||||
.Xr expand 1 ,
|
||||
.Xr rs 1 ,
|
||||
.Xr seq 1 ,
|
||||
.Xr yes 1 ,
|
||||
.Xr arc4random 3 ,
|
||||
.Xr printf 3 ,
|
||||
.Xr random 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in
|
||||
.Bx 4.2 .
|
490
jot/jot.c
Normal file
490
jot/jot.c
Normal file
@ -0,0 +1,490 @@
|
||||
/*-
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char copyright[] =
|
||||
"@(#) Copyright (c) 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)jot.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/usr.bin/jot/jot.c,v 1.40 2009/12/13 03:14:06 delphij Exp $");
|
||||
|
||||
/*
|
||||
* jot - print sequential or random data
|
||||
*
|
||||
* Author: John Kunze, Office of Comp. Affairs, UCB
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Defaults */
|
||||
#define REPS_DEF 100
|
||||
#define BEGIN_DEF 1
|
||||
#define ENDER_DEF 100
|
||||
#define STEP_DEF 1
|
||||
|
||||
/* Flags of options that have been set */
|
||||
#define HAVE_STEP 1
|
||||
#define HAVE_ENDER 2
|
||||
#define HAVE_BEGIN 4
|
||||
#define HAVE_REPS 8
|
||||
|
||||
#define is_default(s) (*(s) == 0 || strcmp((s), "-") == 0)
|
||||
|
||||
static bool boring;
|
||||
static int prec;
|
||||
static bool longdata;
|
||||
static bool intdata;
|
||||
static bool chardata;
|
||||
static bool nosign;
|
||||
static const char *sepstring = "\n";
|
||||
static char format[BUFSIZ];
|
||||
|
||||
static void getformat(void);
|
||||
static int getprec(const char *);
|
||||
static int putdata(double, bool);
|
||||
static void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
bool have_format = false;
|
||||
bool infinity = false;
|
||||
bool nofinalnl = false;
|
||||
bool randomize = false;
|
||||
bool use_random = false;
|
||||
int ch;
|
||||
int mask = 0;
|
||||
int n = 0;
|
||||
double begin = BEGIN_DEF;
|
||||
double divisor;
|
||||
double ender = ENDER_DEF;
|
||||
double s = STEP_DEF;
|
||||
double x, y;
|
||||
long i;
|
||||
long reps = REPS_DEF;
|
||||
|
||||
while ((ch = getopt(argc, argv, "b:cnp:rs:w:")) != -1)
|
||||
switch (ch) {
|
||||
case 'b':
|
||||
boring = true;
|
||||
/* FALLTHROUGH */
|
||||
case 'w':
|
||||
if (strlcpy(format, optarg, sizeof(format)) >=
|
||||
sizeof(format))
|
||||
errx(1, "-%c word too long", ch);
|
||||
have_format = true;
|
||||
break;
|
||||
case 'c':
|
||||
chardata = true;
|
||||
break;
|
||||
case 'n':
|
||||
nofinalnl = true;
|
||||
break;
|
||||
case 'p':
|
||||
prec = atoi(optarg);
|
||||
if (prec <= 0)
|
||||
errx(1, "bad precision value");
|
||||
have_format = true;
|
||||
break;
|
||||
case 'r':
|
||||
randomize = true;
|
||||
break;
|
||||
case 's':
|
||||
sepstring = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
switch (argc) { /* examine args right to left, falling thru cases */
|
||||
case 4:
|
||||
if (!is_default(argv[3])) {
|
||||
if (!sscanf(argv[3], "%lf", &s))
|
||||
errx(1, "bad s value: %s", argv[3]);
|
||||
mask |= HAVE_STEP;
|
||||
if (randomize)
|
||||
use_random = true;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 3:
|
||||
if (!is_default(argv[2])) {
|
||||
if (!sscanf(argv[2], "%lf", &ender))
|
||||
ender = argv[2][strlen(argv[2])-1];
|
||||
mask |= HAVE_ENDER;
|
||||
if (!prec)
|
||||
n = getprec(argv[2]);
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 2:
|
||||
if (!is_default(argv[1])) {
|
||||
if (!sscanf(argv[1], "%lf", &begin))
|
||||
begin = argv[1][strlen(argv[1])-1];
|
||||
mask |= HAVE_BEGIN;
|
||||
if (!prec)
|
||||
prec = getprec(argv[1]);
|
||||
if (n > prec) /* maximum precision */
|
||||
prec = n;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
if (!is_default(argv[0])) {
|
||||
if (!sscanf(argv[0], "%ld", &reps))
|
||||
errx(1, "bad reps value: %s", argv[0]);
|
||||
mask |= HAVE_REPS;
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
usage();
|
||||
default:
|
||||
errx(1, "too many arguments. What do you mean by %s?",
|
||||
argv[4]);
|
||||
}
|
||||
getformat();
|
||||
while (mask) /* 4 bit mask has 1's where last 4 args were given */
|
||||
switch (mask) { /* fill in the 0's by default or computation */
|
||||
case HAVE_STEP:
|
||||
case HAVE_ENDER:
|
||||
case HAVE_ENDER | HAVE_STEP:
|
||||
case HAVE_BEGIN:
|
||||
case HAVE_BEGIN | HAVE_STEP:
|
||||
reps = REPS_DEF;
|
||||
mask |= HAVE_REPS;
|
||||
break;
|
||||
case HAVE_BEGIN | HAVE_ENDER:
|
||||
s = ender > begin ? 1 : -1;
|
||||
mask |= HAVE_STEP;
|
||||
break;
|
||||
case HAVE_BEGIN | HAVE_ENDER | HAVE_STEP:
|
||||
if (randomize)
|
||||
reps = REPS_DEF;
|
||||
else if (s == 0.0)
|
||||
reps = 0;
|
||||
else
|
||||
reps = (ender - begin + s) / s;
|
||||
if (reps <= 0)
|
||||
errx(1, "impossible stepsize");
|
||||
mask = 0;
|
||||
break;
|
||||
case HAVE_REPS:
|
||||
case HAVE_REPS | HAVE_STEP:
|
||||
begin = BEGIN_DEF;
|
||||
mask |= HAVE_BEGIN;
|
||||
break;
|
||||
case HAVE_REPS | HAVE_ENDER:
|
||||
s = STEP_DEF;
|
||||
mask = HAVE_REPS | HAVE_ENDER | HAVE_STEP;
|
||||
break;
|
||||
case HAVE_REPS | HAVE_ENDER | HAVE_STEP:
|
||||
if (randomize)
|
||||
begin = BEGIN_DEF;
|
||||
else if (reps == 0)
|
||||
errx(1, "must specify begin if reps == 0");
|
||||
begin = ender - reps * s + s;
|
||||
mask = 0;
|
||||
break;
|
||||
case HAVE_REPS | HAVE_BEGIN:
|
||||
s = STEP_DEF;
|
||||
mask = HAVE_REPS | HAVE_BEGIN | HAVE_STEP;
|
||||
break;
|
||||
case HAVE_REPS | HAVE_BEGIN | HAVE_STEP:
|
||||
if (randomize)
|
||||
ender = ENDER_DEF;
|
||||
else
|
||||
ender = begin + reps * s - s;
|
||||
mask = 0;
|
||||
break;
|
||||
case HAVE_REPS | HAVE_BEGIN | HAVE_ENDER:
|
||||
if (reps == 0)
|
||||
errx(1, "infinite sequences cannot be bounded");
|
||||
else if (reps == 1)
|
||||
s = 0.0;
|
||||
else
|
||||
s = (ender - begin) / (reps - 1);
|
||||
mask = 0;
|
||||
break;
|
||||
case HAVE_REPS | HAVE_BEGIN | HAVE_ENDER | HAVE_STEP:
|
||||
/* if reps given and implied, */
|
||||
if (!randomize && s != 0.0) {
|
||||
long t = (ender - begin + s) / s;
|
||||
if (t <= 0)
|
||||
errx(1, "impossible stepsize");
|
||||
if (t < reps) /* take lesser */
|
||||
reps = t;
|
||||
}
|
||||
mask = 0;
|
||||
break;
|
||||
default:
|
||||
errx(1, "bad mask");
|
||||
}
|
||||
if (reps == 0)
|
||||
infinity = true;
|
||||
if (randomize) {
|
||||
if (use_random) {
|
||||
srandom((unsigned long)s);
|
||||
divisor = (double)INT32_MAX + 1;
|
||||
} else
|
||||
divisor = (double)UINT32_MAX + 1;
|
||||
|
||||
/*
|
||||
* Attempt to DWIM when the user has specified an
|
||||
* integer range within that of the random number
|
||||
* generator: distribute the numbers equally in
|
||||
* the range [begin .. ender]. Jot's default %.0f
|
||||
* format would make the appearance of the first and
|
||||
* last specified value half as likely as the rest.
|
||||
*/
|
||||
if (!have_format && prec == 0 &&
|
||||
begin >= 0 && begin < divisor &&
|
||||
ender >= 0 && ender < divisor) {
|
||||
ender += 1;
|
||||
nosign = true;
|
||||
intdata = true;
|
||||
(void)strlcpy(format,
|
||||
chardata ? "%c" : "%u", sizeof(format));
|
||||
}
|
||||
x = (ender - begin) * (ender > begin ? 1 : -1);
|
||||
for (i = 1; i <= reps || infinity; i++) {
|
||||
if (use_random)
|
||||
y = random() / divisor;
|
||||
else
|
||||
y = arc4random() / divisor;
|
||||
if (putdata(y * x + begin, !(reps - i)))
|
||||
errx(1, "range error in conversion");
|
||||
}
|
||||
} else
|
||||
for (i = 1, x = begin; i <= reps || infinity; i++, x += s)
|
||||
if (putdata(x, !(reps - i)))
|
||||
errx(1, "range error in conversion");
|
||||
if (!nofinalnl)
|
||||
putchar('\n');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send x to stdout using the specified format.
|
||||
* Last is true if this is the set's last value.
|
||||
* Return 0 if OK, or a positive number if the number passed was
|
||||
* outside the range specified by the various flags.
|
||||
*/
|
||||
static int
|
||||
putdata(double x, bool last)
|
||||
{
|
||||
|
||||
if (boring)
|
||||
printf("%s", format);
|
||||
else if (longdata && nosign) {
|
||||
if (x <= (double)ULONG_MAX && x >= (double)0)
|
||||
printf(format, (unsigned long)x);
|
||||
else
|
||||
return (1);
|
||||
} else if (longdata) {
|
||||
if (x <= (double)LONG_MAX && x >= (double)LONG_MIN)
|
||||
printf(format, (long)x);
|
||||
else
|
||||
return (1);
|
||||
} else if (chardata || (intdata && !nosign)) {
|
||||
if (x <= (double)INT_MAX && x >= (double)INT_MIN)
|
||||
printf(format, (int)x);
|
||||
else
|
||||
return (1);
|
||||
} else if (intdata) {
|
||||
if (x <= (double)UINT_MAX && x >= (double)0)
|
||||
printf(format, (unsigned int)x);
|
||||
else
|
||||
return (1);
|
||||
|
||||
} else
|
||||
printf(format, x);
|
||||
if (!last)
|
||||
fputs(sepstring, stdout);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "%s\n%s\n",
|
||||
"usage: jot [-cnr] [-b word] [-w word] [-s string] [-p precision]",
|
||||
" [reps [begin [end [s]]]]");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of digits following the number's decimal point.
|
||||
* Return 0 if no decimal point is found.
|
||||
*/
|
||||
static int
|
||||
getprec(const char *str)
|
||||
{
|
||||
const char *p;
|
||||
const char *q;
|
||||
|
||||
for (p = str; *p; p++)
|
||||
if (*p == '.')
|
||||
break;
|
||||
if (!*p)
|
||||
return (0);
|
||||
for (q = ++p; *p; p++)
|
||||
if (!isdigit((unsigned char)*p))
|
||||
break;
|
||||
return (p - q);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set format, intdata, chardata, longdata, and nosign
|
||||
* based on the command line arguments.
|
||||
*/
|
||||
static void
|
||||
getformat(void)
|
||||
{
|
||||
char *p, *p2;
|
||||
int dot, hash, space, sign, numbers = 0;
|
||||
size_t sz;
|
||||
|
||||
if (boring) /* no need to bother */
|
||||
return;
|
||||
for (p = format; *p; p++) /* look for '%' */
|
||||
if (*p == '%') {
|
||||
if (p[1] == '%')
|
||||
p++; /* leave %% alone */
|
||||
else
|
||||
break;
|
||||
}
|
||||
sz = sizeof(format) - strlen(format) - 1;
|
||||
if (!*p && !chardata) {
|
||||
if (snprintf(p, sz, "%%.%df", prec) >= (int)sz)
|
||||
errx(1, "-w word too long");
|
||||
} else if (!*p && chardata) {
|
||||
if (strlcpy(p, "%c", sz) >= sz)
|
||||
errx(1, "-w word too long");
|
||||
intdata = true;
|
||||
} else if (!*(p+1)) {
|
||||
if (sz <= 0)
|
||||
errx(1, "-w word too long");
|
||||
strcat(format, "%"); /* cannot end in single '%' */
|
||||
} else {
|
||||
/*
|
||||
* Allow conversion format specifiers of the form
|
||||
* %[#][ ][{+,-}][0-9]*[.[0-9]*]? where ? must be one of
|
||||
* [l]{d,i,o,u,x} or {f,e,g,E,G,d,o,x,D,O,U,X,c,u}
|
||||
*/
|
||||
p2 = p++;
|
||||
dot = hash = space = sign = numbers = 0;
|
||||
while (!isalpha((unsigned char)*p)) {
|
||||
if (isdigit((unsigned char)*p)) {
|
||||
numbers++;
|
||||
p++;
|
||||
} else if ((*p == '#' && !(numbers|dot|sign|space|
|
||||
hash++)) ||
|
||||
(*p == ' ' && !(numbers|dot|space++)) ||
|
||||
((*p == '+' || *p == '-') && !(numbers|dot|sign++))
|
||||
|| (*p == '.' && !(dot++)))
|
||||
p++;
|
||||
else
|
||||
goto fmt_broken;
|
||||
}
|
||||
if (*p == 'l') {
|
||||
longdata = true;
|
||||
if (*++p == 'l') {
|
||||
if (p[1] != '\0')
|
||||
p++;
|
||||
goto fmt_broken;
|
||||
}
|
||||
}
|
||||
switch (*p) {
|
||||
case 'o': case 'u': case 'x': case 'X':
|
||||
intdata = nosign = true;
|
||||
break;
|
||||
case 'd': case 'i':
|
||||
intdata = true;
|
||||
break;
|
||||
case 'D':
|
||||
if (!longdata) {
|
||||
intdata = true;
|
||||
break;
|
||||
}
|
||||
case 'O': case 'U':
|
||||
if (!longdata) {
|
||||
intdata = nosign = true;
|
||||
break;
|
||||
}
|
||||
case 'c':
|
||||
if (!(intdata | longdata)) {
|
||||
chardata = true;
|
||||
break;
|
||||
}
|
||||
case 'h': case 'n': case 'p': case 'q': case 's': case 'L':
|
||||
case '$': case '*':
|
||||
goto fmt_broken;
|
||||
case 'f': case 'e': case 'g': case 'E': case 'G':
|
||||
if (!longdata)
|
||||
break;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
fmt_broken:
|
||||
*++p = '\0';
|
||||
errx(1, "illegal or unsupported format '%s'", p2);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
while (*++p)
|
||||
if (*p == '%' && *(p+1) && *(p+1) != '%')
|
||||
errx(1, "too many conversions");
|
||||
else if (*p == '%' && *(p+1) == '%')
|
||||
p++;
|
||||
else if (*p == '%' && !*(p+1)) {
|
||||
if (strlcat(format, "%", sizeof(format)) >=
|
||||
sizeof(format))
|
||||
errx(1, "-w word too long");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
142
kill/kill.1
Normal file
142
kill/kill.1
Normal file
@ -0,0 +1,142 @@
|
||||
.\" Copyright (c) 1980, 1990, 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.
|
||||
.\"
|
||||
.\" @(#)kill.1 8.2 (Berkeley) 4/28/95
|
||||
.\" $FreeBSD: src/bin/kill/kill.1,v 1.11.2.1 2000/12/08 13:34:35 ru Exp $
|
||||
.\"
|
||||
.Dd April 28, 1995
|
||||
.Dt KILL 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm kill
|
||||
.Nd terminate or signal a process
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl s Ar signal_name
|
||||
.Ar pid
|
||||
\&...
|
||||
.Nm
|
||||
.Fl l
|
||||
.Op Ar exit_status
|
||||
.Nm
|
||||
.Fl signal_name
|
||||
.Ar pid
|
||||
\&...
|
||||
.Nm
|
||||
.Fl signal_number
|
||||
.Ar pid
|
||||
\&...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility sends a signal to the processes specified by the pid operand(s).
|
||||
.Pp
|
||||
Only the super-user may send signals to other users' processes.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Pp
|
||||
.Bl -tag -width Ds
|
||||
.It Fl s Ar signal_name
|
||||
A symbolic signal name specifying the signal to be sent instead of the
|
||||
default
|
||||
.Dv TERM .
|
||||
.It Fl l Op Ar exit_status
|
||||
If no operand is given, list the signal names; otherwise, write
|
||||
the signal name corresponding to
|
||||
.Ar exit_status .
|
||||
.It Fl signal_name
|
||||
A symbolic signal name specifying the signal to be sent instead of the
|
||||
default
|
||||
.Dv TERM .
|
||||
.It Fl signal_number
|
||||
A non-negative decimal integer, specifying the signal to be sent instead
|
||||
of the default
|
||||
.Dv TERM .
|
||||
.El
|
||||
.Pp
|
||||
The following pids have special meanings:
|
||||
.Bl -tag -width Ds -compact
|
||||
.It -1
|
||||
If superuser, broadcast the signal to all processes; otherwise broadcast
|
||||
to all processes belonging to the user.
|
||||
.El
|
||||
.Pp
|
||||
Some of the more commonly used signals:
|
||||
.Bl -tag -width Ds -compact
|
||||
.It 1
|
||||
HUP (hang up)
|
||||
.It 2
|
||||
INT (interrupt)
|
||||
.It 3
|
||||
QUIT (quit)
|
||||
.It 6
|
||||
ABRT (abort)
|
||||
.It 9
|
||||
KILL (non-catchable, non-ignorable kill)
|
||||
.It 14
|
||||
ALRM (alarm clock)
|
||||
.It 15
|
||||
TERM (software termination signal)
|
||||
.El
|
||||
.Pp
|
||||
Some shells may provide a builtin
|
||||
.Nm
|
||||
command which is similar or identical to this utility.
|
||||
Consult the
|
||||
.Xr builtin 1
|
||||
manual page.
|
||||
.Sh SEE ALSO
|
||||
.Xr builtin 1 ,
|
||||
.Xr csh 1 ,
|
||||
.Xr killall 1 ,
|
||||
.Xr ps 1 ,
|
||||
.Xr kill 2 ,
|
||||
.Xr sigaction 2
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
function is expected to be
|
||||
.St -p1003.2
|
||||
compatible.
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
command appeared in
|
||||
.At v6 .
|
||||
.Sh BUGS
|
||||
A replacement for the command
|
||||
.Dq Li kill 0
|
||||
for
|
||||
.Xr csh 1
|
||||
users should be provided.
|
192
kill/kill.c
Normal file
192
kill/kill.c
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (c) 1988, 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 const copyright[] =
|
||||
"@(#) Copyright (c) 1988, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)kill.c 8.4 (Berkeley) 4/28/95";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD: src/bin/kill/kill.c,v 1.11.2.1 2001/08/01 02:42:56 obrien Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int main __P((int, char *[]));
|
||||
void nosig __P((char *));
|
||||
void printsignals __P((FILE *));
|
||||
int signame_to_signum __P((char *));
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int errors, numsig, pid;
|
||||
char *ep;
|
||||
|
||||
if (argc < 2)
|
||||
usage();
|
||||
|
||||
numsig = SIGTERM;
|
||||
|
||||
argc--, argv++;
|
||||
if (!strcmp(*argv, "-l")) {
|
||||
argc--, argv++;
|
||||
if (argc > 1)
|
||||
usage();
|
||||
if (argc == 1) {
|
||||
if (!isdigit(**argv))
|
||||
usage();
|
||||
numsig = strtol(*argv, &ep, 10);
|
||||
if (!**argv || *ep)
|
||||
errx(1, "illegal signal number: %s", *argv);
|
||||
if (numsig >= 128)
|
||||
numsig -= 128;
|
||||
if (numsig <= 0 || numsig >= NSIG)
|
||||
nosig(*argv);
|
||||
printf("%s\n", sys_signame[numsig]);
|
||||
exit(0);
|
||||
}
|
||||
printsignals(stdout);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!strcmp(*argv, "-s")) {
|
||||
argc--, argv++;
|
||||
if (argc < 1) {
|
||||
warnx("option requires an argument -- s");
|
||||
usage();
|
||||
}
|
||||
if (strcmp(*argv, "0")) {
|
||||
if ((numsig = signame_to_signum(*argv)) < 0)
|
||||
nosig(*argv);
|
||||
} else
|
||||
numsig = 0;
|
||||
argc--, argv++;
|
||||
} else if (**argv == '-') {
|
||||
++*argv;
|
||||
if (isalpha(**argv)) {
|
||||
if ((numsig = signame_to_signum(*argv)) < 0)
|
||||
nosig(*argv);
|
||||
} else if (isdigit(**argv)) {
|
||||
numsig = strtol(*argv, &ep, 10);
|
||||
if (!**argv || *ep)
|
||||
errx(1, "illegal signal number: %s", *argv);
|
||||
if (numsig < 0 || numsig >= NSIG)
|
||||
nosig(*argv);
|
||||
} else
|
||||
nosig(*argv);
|
||||
argc--, argv++;
|
||||
}
|
||||
|
||||
if (argc == 0)
|
||||
usage();
|
||||
|
||||
for (errors = 0; argc; argc--, argv++) {
|
||||
pid = strtol(*argv, &ep, 10);
|
||||
if (!**argv || *ep) {
|
||||
warnx("illegal process id: %s", *argv);
|
||||
errors = 1;
|
||||
} else if (kill(pid, numsig) == -1) {
|
||||
warn("%s", *argv);
|
||||
errors = 1;
|
||||
}
|
||||
}
|
||||
|
||||
exit(errors);
|
||||
}
|
||||
|
||||
int
|
||||
signame_to_signum(sig)
|
||||
char *sig;
|
||||
{
|
||||
int n;
|
||||
|
||||
if (!strncasecmp(sig, "sig", (size_t)3))
|
||||
sig += 3;
|
||||
for (n = 1; n < NSIG; n++) {
|
||||
if (!strcasecmp(sys_signame[n], sig))
|
||||
return (n);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
void
|
||||
nosig(name)
|
||||
char *name;
|
||||
{
|
||||
|
||||
warnx("unknown signal %s; valid signals:", name);
|
||||
printsignals(stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
printsignals(fp)
|
||||
FILE *fp;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 1; n < NSIG; n++) {
|
||||
(void)fprintf(fp, "%s", sys_signame[n]);
|
||||
if (n == (NSIG / 2) || n == (NSIG - 1))
|
||||
(void)fprintf(fp, "\n");
|
||||
else
|
||||
(void)fprintf(fp, " ");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
|
||||
"usage: kill [-s signal_name] pid ...",
|
||||
" kill -l [exit_status]",
|
||||
" kill -signal_name pid ...",
|
||||
" kill -signal_number pid ...");
|
||||
exit(1);
|
||||
}
|
159
killall/killall.1
Normal file
159
killall/killall.1
Normal file
@ -0,0 +1,159 @@
|
||||
.\" Copyright (C) 1995 by Joerg Wunsch, Dresden
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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.
|
||||
.\"
|
||||
.\" $FreeBSD: src/usr.bin/killall/killall.1,v 1.34 2005/01/17 07:44:20 ru Exp $
|
||||
.\"
|
||||
.Dd January 26, 2004
|
||||
.Os
|
||||
.Dt KILLALL 1
|
||||
.Sh NAME
|
||||
.Nm killall
|
||||
.Nd kill processes by name
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl delmsvz
|
||||
.Op Fl help
|
||||
.Op Fl u Ar user
|
||||
.Op Fl t Ar tty
|
||||
.Op Fl c Ar procname
|
||||
.Op Fl SIGNAL
|
||||
.Op Ar procname ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility kills processes selected by name, as opposed to the selection by pid
|
||||
as done by
|
||||
.Xr kill 1 .
|
||||
By default, it will send a
|
||||
.Dv TERM
|
||||
signal to all processes with a real UID identical to the
|
||||
caller of
|
||||
.Nm
|
||||
that match the name
|
||||
.Ar procname .
|
||||
The super-user is allowed to kill any process.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width 10n -offset indent
|
||||
.It Fl v
|
||||
Be more verbose about what will be done.
|
||||
.It Fl e
|
||||
Use the effective user ID instead of the (default) real user ID for matching
|
||||
processes specified with the
|
||||
.Fl u
|
||||
option.
|
||||
.It Fl help
|
||||
Give a help on the command usage and exit.
|
||||
.It Fl l
|
||||
List the names of the available signals and exit, like in
|
||||
.Xr kill 1 .
|
||||
.It Fl m
|
||||
Match the argument
|
||||
.Ar procname
|
||||
as a (case sensitive) regular expression against the names
|
||||
of processes found.
|
||||
CAUTION!
|
||||
This is dangerous, a single dot will match any process
|
||||
running under the real UID of the caller.
|
||||
.It Fl s
|
||||
Show only what would be done, but do not send any signal.
|
||||
.It Fl d
|
||||
Print detailed information about the processes matched,
|
||||
but do not send any signal.
|
||||
.It Fl SIGNAL
|
||||
Send a different signal instead of the default
|
||||
.Dv TERM .
|
||||
The signal may be specified either as a name
|
||||
(with or without a leading
|
||||
.Dv SIG ) ,
|
||||
or numerically.
|
||||
.It Fl u Ar user
|
||||
Limit potentially matching processes to those belonging to
|
||||
the specified
|
||||
.Ar user .
|
||||
.It Fl t Ar tty
|
||||
Limit potentially matching processes to those running on
|
||||
the specified
|
||||
.Ar tty .
|
||||
.It Fl c Ar procname
|
||||
When used with the
|
||||
.Fl u
|
||||
or
|
||||
.Fl t
|
||||
flags, limit potentially matching processes to those matching
|
||||
the specified
|
||||
.Ar procname .
|
||||
.It Fl z
|
||||
Do not skip zombies.
|
||||
This should not have any effect except to print a few error messages
|
||||
if there are zombie processes that match the specified pattern.
|
||||
.El
|
||||
.Sh ALL PROCESSES
|
||||
Sending a signal to all processes with uid
|
||||
.Em XYZ
|
||||
is already supported by
|
||||
.Xr kill 1 .
|
||||
So use
|
||||
.Xr kill 1
|
||||
for this job (e.g.\& $ kill -TERM -1 or
|
||||
as root $ echo kill -TERM -1 | su -m <user>)
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
command will respond with a short usage message and exit with a status
|
||||
of 2 in case of a command error.
|
||||
A status of 1 will be returned if
|
||||
either no matching process has been found or not all processes have
|
||||
been signalled successfully.
|
||||
Otherwise, a status of 0 will be
|
||||
returned.
|
||||
.Sh DIAGNOSTICS
|
||||
Diagnostic messages will only be printed if requested by
|
||||
.Fl d
|
||||
options.
|
||||
.Sh SEE ALSO
|
||||
.Xr kill 1 ,
|
||||
.Xr sysctl 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Fx 2.1 .
|
||||
It has been modeled after the
|
||||
.Nm
|
||||
command as available on other platforms.
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The
|
||||
.Nm
|
||||
program was originally written in Perl and was contributed by
|
||||
.An Wolfram Schneider ,
|
||||
this manual page has been written by
|
||||
.An J\(:org Wunsch .
|
||||
The current version of
|
||||
.Nm
|
||||
was rewritten in C by
|
||||
.An Peter Wemm
|
||||
using
|
||||
.Xr sysctl 3 .
|
549
killall/killall.c
Normal file
549
killall/killall.c
Normal file
@ -0,0 +1,549 @@
|
||||
/*-
|
||||
* Copyright (c) 2000 Peter Wemm <peter@FreeBSD.org>
|
||||
* Copyright (c) 2000 Paul Saab <ps@FreeBSD.org>
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/usr.bin/killall/killall.c,v 1.31 2004/07/29 18:36:35 maxim Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#ifndef __APPLE__
|
||||
#include <sys/jail.h>
|
||||
#endif /* !__APPLE__ */
|
||||
#include <sys/stat.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <regex.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <locale.h>
|
||||
|
||||
#include <getopt.h>
|
||||
#define OPTIONS ("c:dej:lmst:u:vz")
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
static void __dead2
|
||||
usage(void)
|
||||
{
|
||||
|
||||
#ifdef __APPLE__
|
||||
fprintf(stderr, "usage: killall [-delmsvz] [-help]\n");
|
||||
#else /* !__APPLE__ */
|
||||
fprintf(stderr, "usage: killall [-delmsvz] [-help] [-j jid]\n");
|
||||
#endif /* __APPLE__ */
|
||||
fprintf(stderr,
|
||||
" [-u user] [-t tty] [-c cmd] [-SIGNAL] [cmd]...\n");
|
||||
fprintf(stderr, "At least one option or argument to specify processes must be given.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static char *
|
||||
upper(const char *str)
|
||||
{
|
||||
static char buf[80];
|
||||
char *s;
|
||||
|
||||
strncpy(buf, str, sizeof(buf));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
for (s = buf; *s; s++)
|
||||
*s = toupper((unsigned char)*s);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
printsig(FILE *fp)
|
||||
{
|
||||
const char *const * p;
|
||||
int cnt;
|
||||
int offset = 0;
|
||||
|
||||
for (cnt = NSIG, p = sys_signame + 1; --cnt; ++p) {
|
||||
offset += fprintf(fp, "%s ", upper(*p));
|
||||
if (offset >= 75 && cnt > 1) {
|
||||
offset = 0;
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
|
||||
static void
|
||||
nosig(char *name)
|
||||
{
|
||||
|
||||
warnx("unknown signal %s; valid signals:", name);
|
||||
printsig(stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* kludge_signal_args - remove any signal option (-SIGXXX, -##) from the argv array.
|
||||
*/
|
||||
void
|
||||
kludge_signal_args(int *argc, char **argv, int *sig)
|
||||
{
|
||||
int i;
|
||||
int shift = 0;
|
||||
int kludge = 1;
|
||||
char *ptr;
|
||||
const char *const *p;
|
||||
char *ep;
|
||||
|
||||
/* i = 1, skip program name */
|
||||
for (i = 1; i < *argc; i++) {
|
||||
/* Stop kludging if we encounter -- */
|
||||
if (strcmp(argv[i], "--") == 0)
|
||||
kludge = 0;
|
||||
ptr = argv[i] + 1;
|
||||
/* Only process arguments that start with - and do not look like an existing option. */
|
||||
if (kludge && *argv[i] == '-' && *ptr && strchr(OPTIONS, *ptr) == NULL) {
|
||||
if (isalpha(*ptr)) {
|
||||
if (strcmp(ptr, "help") == 0)
|
||||
usage();
|
||||
if (strncasecmp(ptr, "sig", 3) == 0)
|
||||
ptr += 3;
|
||||
for (*sig = NSIG, p = sys_signame + 1; --*sig; ++p)
|
||||
if (strcasecmp(*p, ptr) == 0) {
|
||||
*sig = p - sys_signame;
|
||||
break;
|
||||
}
|
||||
if (!*sig)
|
||||
nosig(ptr);
|
||||
} else if (isdigit(*ptr)) {
|
||||
*sig = strtol(ptr, &ep, 10);
|
||||
if (*ep)
|
||||
errx(1, "illegal signal number: %s", ptr);
|
||||
if (*sig < 0 || *sig >= NSIG)
|
||||
nosig(ptr);
|
||||
} else
|
||||
nosig(ptr);
|
||||
|
||||
shift++;
|
||||
continue;
|
||||
}
|
||||
|
||||
argv[i - shift] = argv[i];
|
||||
}
|
||||
|
||||
for (i = *argc - shift; i < *argc; i++) {
|
||||
argv[i] = NULL;
|
||||
}
|
||||
|
||||
*argc -= shift;
|
||||
}
|
||||
|
||||
int
|
||||
main(int ac, char **av)
|
||||
{
|
||||
struct kinfo_proc *procs = NULL, *newprocs;
|
||||
struct stat sb;
|
||||
struct passwd *pw;
|
||||
regex_t rgx;
|
||||
regmatch_t pmatch;
|
||||
int i, j;
|
||||
char buf[256];
|
||||
char *user = NULL;
|
||||
char *tty = NULL;
|
||||
char *cmd = NULL;
|
||||
int vflag = 0;
|
||||
int sflag = 0;
|
||||
int dflag = 0;
|
||||
int eflag = 0;
|
||||
#ifndef __APPLE__
|
||||
int jflag = 0;
|
||||
#endif /* !__APPLE__*/
|
||||
int mflag = 0;
|
||||
int zflag = 0;
|
||||
uid_t uid = 0;
|
||||
dev_t tdev = 0;
|
||||
pid_t mypid;
|
||||
#ifdef __APPLE__
|
||||
char *thiscmd;
|
||||
#else /* !__APPLE__ */
|
||||
char thiscmd[MAXCOMLEN + 1];
|
||||
#endif /* __APPLE__ */
|
||||
pid_t thispid;
|
||||
#ifndef __APPLE__
|
||||
uid_t thisuid;
|
||||
#endif /* !__APPLE__ */
|
||||
dev_t thistdev;
|
||||
int sig = SIGTERM;
|
||||
char *ep;
|
||||
int errors = 0;
|
||||
#ifndef __APPLE__
|
||||
int jid;
|
||||
#endif /* !__APPLE__ */
|
||||
int mib[4];
|
||||
size_t miblen;
|
||||
int st, nprocs;
|
||||
size_t size;
|
||||
int matched;
|
||||
int killed = 0;
|
||||
int ch;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
kludge_signal_args(&ac, av, &sig);
|
||||
|
||||
while ((ch = getopt(ac, av, OPTIONS)) != -1) {
|
||||
switch (ch) {
|
||||
case 'c':
|
||||
cmd = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
dflag++;
|
||||
break;
|
||||
case 'e':
|
||||
eflag++;
|
||||
break;
|
||||
#ifndef __APPLE__
|
||||
case 'j':
|
||||
jflag++;
|
||||
jid = strtol(optarg, &ep, 10);
|
||||
if (*ep)
|
||||
errx(1, "illegal jid: %s", optarg);
|
||||
if (jail_attach(jid) == -1)
|
||||
err(1, "jail_attach(): %d", jid);
|
||||
break;
|
||||
#endif /* __APPLE__ */
|
||||
case 'l':
|
||||
printsig(stdout);
|
||||
exit(0);
|
||||
case 'm':
|
||||
mflag++;
|
||||
break;
|
||||
case 's':
|
||||
sflag++;
|
||||
break;
|
||||
case 't':
|
||||
tty = optarg;
|
||||
break;
|
||||
case 'u':
|
||||
user = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
vflag++;
|
||||
break;
|
||||
case 'z':
|
||||
zflag++;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
ac -= optind;
|
||||
av += optind;
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (user == NULL && tty == NULL && cmd == NULL && ac == 0)
|
||||
#else /* !__APPLE__*/
|
||||
if (user == NULL && tty == NULL && cmd == NULL && !jflag && ac == 0)
|
||||
#endif /* __APPLE__ */
|
||||
usage();
|
||||
|
||||
if (tty) {
|
||||
if (strncmp(tty, "/dev/", 5) == 0)
|
||||
snprintf(buf, sizeof(buf), "%s", tty);
|
||||
else if (strncmp(tty, "tty", 3) == 0)
|
||||
snprintf(buf, sizeof(buf), "/dev/%s", tty);
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "/dev/tty%s", tty);
|
||||
if (stat(buf, &sb) < 0)
|
||||
err(1, "stat(%s)", buf);
|
||||
if (!S_ISCHR(sb.st_mode))
|
||||
errx(1, "%s: not a character device", buf);
|
||||
tdev = sb.st_rdev;
|
||||
if (dflag)
|
||||
printf("ttydev:0x%x\n", tdev);
|
||||
}
|
||||
if (user) {
|
||||
uid = strtol(user, &ep, 10);
|
||||
if (*user == '\0' || *ep != '\0') { /* was it a number? */
|
||||
pw = getpwnam(user);
|
||||
if (pw == NULL)
|
||||
errx(1, "user %s does not exist", user);
|
||||
uid = pw->pw_uid;
|
||||
if (dflag)
|
||||
printf("uid:%d\n", uid);
|
||||
}
|
||||
} else {
|
||||
uid = getuid();
|
||||
if (uid != 0) {
|
||||
pw = getpwuid(uid);
|
||||
if (pw)
|
||||
user = pw->pw_name;
|
||||
if (dflag)
|
||||
printf("uid:%d\n", uid);
|
||||
}
|
||||
}
|
||||
size = 0;
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
#ifdef __APPLE__
|
||||
mib[2] = KERN_PROC_ALL;
|
||||
#else /* !__APPLE__ */
|
||||
mib[2] = KERN_PROC_PROC;
|
||||
#endif /* __APPLE__ */
|
||||
mib[3] = 0;
|
||||
miblen = 3;
|
||||
|
||||
if (user) {
|
||||
mib[2] = eflag ? KERN_PROC_UID : KERN_PROC_RUID;
|
||||
mib[3] = uid;
|
||||
miblen = 4;
|
||||
} else if (tty) {
|
||||
mib[2] = KERN_PROC_TTY;
|
||||
mib[3] = tdev;
|
||||
miblen = 4;
|
||||
}
|
||||
|
||||
st = sysctl(mib, miblen, NULL, &size, NULL, 0);
|
||||
do {
|
||||
size += size / 10;
|
||||
newprocs = realloc(procs, size);
|
||||
if (newprocs == 0) {
|
||||
if (procs)
|
||||
free(procs);
|
||||
errx(1, "could not reallocate memory");
|
||||
}
|
||||
procs = newprocs;
|
||||
st = sysctl(mib, miblen, procs, &size, NULL, 0);
|
||||
} while (st == -1 && errno == ENOMEM);
|
||||
if (st == -1)
|
||||
err(1, "could not sysctl(KERN_PROC)");
|
||||
if (size % sizeof(struct kinfo_proc) != 0) {
|
||||
fprintf(stderr, "proc size mismatch (%zu total, %zu chunks)\n",
|
||||
size, sizeof(struct kinfo_proc));
|
||||
fprintf(stderr, "userland out of sync with kernel, recompile libkvm etc\n");
|
||||
exit(1);
|
||||
}
|
||||
nprocs = size / sizeof(struct kinfo_proc);
|
||||
if (dflag)
|
||||
printf("nprocs %d\n", nprocs);
|
||||
mypid = getpid();
|
||||
|
||||
for (i = 0; i < nprocs; i++) {
|
||||
#ifdef __APPLE__
|
||||
if (procs[i].kp_proc.p_stat == SZOMB && !zflag)
|
||||
continue;
|
||||
thispid = procs[i].kp_proc.p_pid;
|
||||
|
||||
int mib[3], argmax;
|
||||
size_t syssize;
|
||||
char *procargs, *cp;
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_ARGMAX;
|
||||
|
||||
syssize = sizeof(argmax);
|
||||
if (sysctl(mib, 2, &argmax, &syssize, NULL, 0) == -1)
|
||||
continue;
|
||||
|
||||
procargs = malloc(argmax);
|
||||
if (procargs == NULL)
|
||||
continue;
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
#if defined(__APPLE__) && TARGET_OS_EMBEDDED
|
||||
mib[1] = KERN_PROCARGS2;
|
||||
#else
|
||||
mib[1] = KERN_PROCARGS;
|
||||
#endif
|
||||
mib[2] = thispid;
|
||||
|
||||
syssize = (size_t)argmax;
|
||||
if (sysctl(mib, 3, procargs, &syssize, NULL, 0) == -1) {
|
||||
free(procargs);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (cp = procargs; cp < &procargs[syssize]; cp++) {
|
||||
if (*cp == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cp == &procargs[syssize]) {
|
||||
free(procargs);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (; cp < &procargs[syssize]; cp++) {
|
||||
if (*cp != '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cp == &procargs[syssize]) {
|
||||
free(procargs);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Strip off any path that was specified */
|
||||
for (thiscmd = cp; (cp < &procargs[syssize]) && (*cp != '\0'); cp++) {
|
||||
if (*cp == '/') {
|
||||
thiscmd = cp + 1;
|
||||
}
|
||||
}
|
||||
|
||||
thistdev = procs[i].kp_eproc.e_tdev;
|
||||
#else /* !__APPLE__ */
|
||||
if (procs[i].ki_stat == SZOMB && !zflag)
|
||||
continue;
|
||||
thispid = procs[i].ki_pid;
|
||||
strncpy(thiscmd, procs[i].ki_comm, MAXCOMLEN);
|
||||
thiscmd[MAXCOMLEN] = '\0';
|
||||
thistdev = procs[i].ki_tdev;
|
||||
#endif /* __APPLE__ */
|
||||
#ifndef __APPLE__
|
||||
if (eflag)
|
||||
thisuid = procs[i].ki_uid; /* effective uid */
|
||||
else
|
||||
thisuid = procs[i].ki_ruid; /* real uid */
|
||||
#endif /* !__APPLE__ */
|
||||
|
||||
if (thispid == mypid) {
|
||||
#ifdef __APPLE__
|
||||
free(procargs);
|
||||
#endif /* __APPLE__ */
|
||||
continue;
|
||||
}
|
||||
matched = 1;
|
||||
#ifndef __APPLE__
|
||||
if (user) {
|
||||
if (thisuid != uid)
|
||||
matched = 0;
|
||||
}
|
||||
#endif /* !__APPLE__ */
|
||||
if (tty) {
|
||||
if (thistdev != tdev)
|
||||
matched = 0;
|
||||
}
|
||||
if (cmd) {
|
||||
if (mflag) {
|
||||
if (regcomp(&rgx, cmd,
|
||||
REG_EXTENDED|REG_NOSUB) != 0) {
|
||||
mflag = 0;
|
||||
warnx("%s: illegal regexp", cmd);
|
||||
}
|
||||
}
|
||||
if (mflag) {
|
||||
pmatch.rm_so = 0;
|
||||
pmatch.rm_eo = strlen(thiscmd);
|
||||
if (regexec(&rgx, thiscmd, 0, &pmatch,
|
||||
REG_STARTEND) != 0)
|
||||
matched = 0;
|
||||
regfree(&rgx);
|
||||
} else {
|
||||
if (strncmp(thiscmd, cmd, MAXCOMLEN) != 0)
|
||||
matched = 0;
|
||||
}
|
||||
}
|
||||
#ifndef __APPLE__
|
||||
if (jflag && thispid == getpid())
|
||||
matched = 0;
|
||||
#endif /* !__APPLE__ */
|
||||
if (matched == 0) {
|
||||
#ifdef __APPLE__
|
||||
free(procargs);
|
||||
#endif /* !__APPLE__ */
|
||||
continue;
|
||||
}
|
||||
if (ac > 0)
|
||||
matched = 0;
|
||||
for (j = 0; j < ac; j++) {
|
||||
if (mflag) {
|
||||
if (regcomp(&rgx, av[j],
|
||||
REG_EXTENDED|REG_NOSUB) != 0) {
|
||||
mflag = 0;
|
||||
warnx("%s: illegal regexp", av[j]);
|
||||
}
|
||||
}
|
||||
if (mflag) {
|
||||
pmatch.rm_so = 0;
|
||||
pmatch.rm_eo = strlen(thiscmd);
|
||||
if (regexec(&rgx, thiscmd, 0, &pmatch,
|
||||
REG_STARTEND) == 0)
|
||||
matched = 1;
|
||||
regfree(&rgx);
|
||||
} else {
|
||||
if (strcmp(thiscmd, av[j]) == 0)
|
||||
matched = 1;
|
||||
}
|
||||
if (matched)
|
||||
break;
|
||||
}
|
||||
if (matched == 0) {
|
||||
#ifdef __APPLE__
|
||||
free(procargs);
|
||||
#endif /* __APPLE__ */
|
||||
continue;
|
||||
}
|
||||
if (dflag)
|
||||
#ifdef __APPLE__
|
||||
printf("sig:%d, cmd:%s, pid:%d, dev:0x%x\n", sig,
|
||||
thiscmd, thispid, thistdev);
|
||||
#else /* !__APPLE__ */
|
||||
printf("sig:%d, cmd:%s, pid:%d, dev:0x%x uid:%d\n", sig,
|
||||
thiscmd, thispid, thistdev, thisuid);
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
if (vflag || sflag)
|
||||
printf("kill -%s %d\n", upper(sys_signame[sig]),
|
||||
thispid);
|
||||
|
||||
killed++;
|
||||
if (!dflag && !sflag) {
|
||||
if (kill(thispid, sig) < 0 /* && errno != ESRCH */ ) {
|
||||
warn("warning: kill -%s %d",
|
||||
upper(sys_signame[sig]), thispid);
|
||||
errors = 1;
|
||||
}
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
free(procargs);
|
||||
#endif /* __APPLE__ */
|
||||
}
|
||||
if (killed == 0) {
|
||||
fprintf(stderr, "No matching processes %swere found\n",
|
||||
getuid() != 0 ? "belonging to you " : "");
|
||||
errors = 1;
|
||||
}
|
||||
exit(errors);
|
||||
}
|
132
lastcomm/lastcomm.1
Normal file
132
lastcomm/lastcomm.1
Normal file
@ -0,0 +1,132 @@
|
||||
.\" $NetBSD: lastcomm.1,v 1.11 2006/12/22 08:00:20 ad Exp $
|
||||
.\"
|
||||
.\" 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. 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.
|
||||
.\"
|
||||
.\" @(#)lastcomm.1 8.1 (Berkeley) 6/6/93
|
||||
.\"
|
||||
.Dd December 22, 2006
|
||||
.Dt LASTCOMM 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm lastcomm
|
||||
.Nd show last commands executed in reverse order
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl f Ar file
|
||||
.Op Ar command ...
|
||||
.Op Ar user ...
|
||||
.Op Ar terminal ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
gives information on previously executed commands.
|
||||
With no arguments,
|
||||
.Nm
|
||||
prints information about all the commands recorded
|
||||
during the current accounting file's lifetime.
|
||||
.Pp
|
||||
Option:
|
||||
.Pp
|
||||
.Bl -tag -width Fl
|
||||
.It Fl f Ar file
|
||||
Read from
|
||||
.Ar file
|
||||
rather than the default
|
||||
accounting file.
|
||||
.El
|
||||
.Pp
|
||||
If called with arguments, only accounting entries with a
|
||||
matching
|
||||
.Ar command
|
||||
name,
|
||||
.Ar user
|
||||
name,
|
||||
or
|
||||
.Ar terminal
|
||||
name
|
||||
are printed.
|
||||
So, for example:
|
||||
.Pp
|
||||
.Dl lastcomm a.out root ttyd0
|
||||
.Pp
|
||||
would produce a listing of all the
|
||||
executions of commands named
|
||||
.Pa a.out
|
||||
by user
|
||||
.Ar root
|
||||
on the terminal
|
||||
.Ar ttyd0 .
|
||||
.Pp
|
||||
For each process entry, the following are printed.
|
||||
.Pp
|
||||
.Bl -bullet -offset indent -compact
|
||||
.It
|
||||
The name of the user who ran the process.
|
||||
.It
|
||||
Flags, as accumulated by the accounting facilities in the system.
|
||||
.It
|
||||
The command name under which the process was called.
|
||||
.It
|
||||
The amount of cpu time used by the process (in seconds).
|
||||
.It
|
||||
The time the process started.
|
||||
.It
|
||||
The elapsed time of the process.
|
||||
.El
|
||||
.Pp
|
||||
The flags are encoded as follows:
|
||||
.Dq S
|
||||
indicates the command was
|
||||
executed by the super-user,
|
||||
.Dq F
|
||||
indicates the command ran after
|
||||
a fork, but without a following
|
||||
.Xr exec 3 ,
|
||||
.Dq C
|
||||
indicates the command was run in PDP-11 compatibility mode
|
||||
(VAX only),
|
||||
.Dq D
|
||||
indicates the command terminated with the generation of a
|
||||
.Pa core
|
||||
file, and
|
||||
.Dq X
|
||||
indicates the command was terminated with a signal.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /var/account/acct -compact
|
||||
.It Pa /var/account/acct
|
||||
Default accounting file.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr last 1 ,
|
||||
.Xr sigaction 2 ,
|
||||
.Xr acct 5 ,
|
||||
.Xr core 5
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 3.0 .
|
234
lastcomm/lastcomm.c
Normal file
234
lastcomm/lastcomm.c
Normal file
@ -0,0 +1,234 @@
|
||||
/* $NetBSD: lastcomm.c,v 1.21 2009/04/12 13:08:31 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1980, 1993\
|
||||
The Regents of the University of California. All rights reserved.");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)lastcomm.c 8.2 (Berkeley) 4/29/95";
|
||||
#endif
|
||||
__RCSID("$NetBSD: lastcomm.c,v 1.21 2009/04/12 13:08:31 lukem Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/acct.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <math.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <struct.h>
|
||||
#include <time.h>
|
||||
#include <tzfile.h>
|
||||
#include <unistd.h>
|
||||
/* definitions from utmp.h */
|
||||
#define UT_NAMESIZE 8
|
||||
#define UT_LINESIZE 8
|
||||
#include "pathnames.h"
|
||||
|
||||
static time_t expand(u_int);
|
||||
static char *flagbits(int);
|
||||
static const char *getdev(dev_t);
|
||||
static int requested(char *[], struct acct *);
|
||||
static void usage(void) __dead;
|
||||
|
||||
int main(int, char **);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char *p;
|
||||
struct acct ab;
|
||||
struct stat sb;
|
||||
FILE *fp;
|
||||
off_t size;
|
||||
time_t t;
|
||||
double delta;
|
||||
int ch;
|
||||
const char *acctfile = _PATH_ACCT;
|
||||
|
||||
setprogname(argv[0]);
|
||||
|
||||
while ((ch = getopt(argc, argv, "f:")) != -1)
|
||||
switch((char)ch) {
|
||||
case 'f':
|
||||
acctfile = optarg;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/* Open the file. */
|
||||
if ((fp = fopen(acctfile, "r")) == NULL || fstat(fileno(fp), &sb))
|
||||
err(1, "%s", acctfile);
|
||||
|
||||
/*
|
||||
* Round off to integral number of accounting records, probably
|
||||
* not necessary, but it doesn't hurt.
|
||||
*/
|
||||
size = sb.st_size - sb.st_size % sizeof(struct acct);
|
||||
|
||||
/* Check if any records to display. */
|
||||
if (size < (off_t)sizeof(struct acct))
|
||||
exit(0);
|
||||
|
||||
/*
|
||||
* Seek to before the last entry in the file; use lseek(2) in case
|
||||
* the file is bigger than a "long".
|
||||
*/
|
||||
size -= sizeof(struct acct);
|
||||
if (lseek(fileno(fp), size, SEEK_SET) == -1)
|
||||
err(1, "%s", acctfile);
|
||||
|
||||
for (;;) {
|
||||
if (fread(&ab, sizeof(struct acct), 1, fp) != 1)
|
||||
err(1, "%s", acctfile);
|
||||
|
||||
if (ab.ac_comm[0] == '\0') {
|
||||
ab.ac_comm[0] = '?';
|
||||
ab.ac_comm[1] = '\0';
|
||||
} else
|
||||
for (p = &ab.ac_comm[0];
|
||||
p < &ab.ac_comm[fldsiz(acct, ac_comm)] && *p; ++p)
|
||||
if (!isprint((unsigned char)*p))
|
||||
*p = '?';
|
||||
if (!*argv || requested(argv, &ab)) {
|
||||
|
||||
t = expand(ab.ac_utime) + expand(ab.ac_stime);
|
||||
(void)printf(
|
||||
"%-*.*s %-7s %-*.*s %-*.*s %6.2f secs %.16s",
|
||||
(int)fldsiz(acct, ac_comm),
|
||||
(int)fldsiz(acct, ac_comm),
|
||||
ab.ac_comm, flagbits(ab.ac_flag),
|
||||
UT_NAMESIZE, UT_NAMESIZE,
|
||||
user_from_uid(ab.ac_uid, 0), UT_LINESIZE,
|
||||
UT_LINESIZE, getdev(ab.ac_tty),
|
||||
t / (double)AHZ, ctime(&ab.ac_btime));
|
||||
delta = expand(ab.ac_etime) / (double)AHZ;
|
||||
printf(" (%1.0f:%02.0f:%05.2f)\n",
|
||||
floor(delta / SECSPERHOUR),
|
||||
floor(fmod(delta, SECSPERHOUR) / SECSPERMIN),
|
||||
fmod(delta, SECSPERMIN));
|
||||
}
|
||||
/* are we at the beginning of the file yet? */
|
||||
if (size == 0)
|
||||
break;
|
||||
/* seek backward over the one we read and the next to read */
|
||||
if (fseek(fp, 2 * -(long)sizeof(struct acct), SEEK_CUR) == -1)
|
||||
err(1, "%s", acctfile);
|
||||
/* and account for its size */
|
||||
size -= sizeof(struct acct);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static time_t
|
||||
expand(u_int t)
|
||||
{
|
||||
time_t nt;
|
||||
|
||||
nt = t & 017777;
|
||||
t >>= 13;
|
||||
while (t) {
|
||||
t--;
|
||||
nt <<= 3;
|
||||
}
|
||||
return (nt);
|
||||
}
|
||||
|
||||
static char *
|
||||
flagbits(int f)
|
||||
{
|
||||
static char flags[20] = "-";
|
||||
char *p;
|
||||
|
||||
#define BIT(flag, ch) if (f & flag) *p++ = ch
|
||||
|
||||
p = flags + 1;
|
||||
BIT(ASU, 'S');
|
||||
BIT(AFORK, 'F');
|
||||
BIT(ACOMPAT, 'C');
|
||||
BIT(ACORE, 'D');
|
||||
BIT(AXSIG, 'X');
|
||||
*p = '\0';
|
||||
return (flags);
|
||||
}
|
||||
|
||||
static int
|
||||
requested(char *argv[], struct acct *acp)
|
||||
{
|
||||
do {
|
||||
if (!strcmp(user_from_uid(acp->ac_uid, 0), *argv))
|
||||
return (1);
|
||||
if (!strcmp(getdev(acp->ac_tty), *argv))
|
||||
return (1);
|
||||
if (!strncmp(acp->ac_comm, *argv, fldsiz(acct, ac_comm)))
|
||||
return (1);
|
||||
} while (*++argv);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static const char *
|
||||
getdev(dev_t dev)
|
||||
{
|
||||
static dev_t lastdev = (dev_t)-1;
|
||||
static const char *lastname;
|
||||
|
||||
if (dev == NODEV) /* Special case. */
|
||||
return ("__");
|
||||
if (dev == lastdev) /* One-element cache. */
|
||||
return (lastname);
|
||||
lastdev = dev;
|
||||
if ((lastname = devname(dev, S_IFCHR)) == NULL)
|
||||
lastname = "??";
|
||||
return (lastname);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"Usage: %s [ -f file ] [command ...] [user ...] [tty ...]\n",
|
||||
getprogname());
|
||||
exit(1);
|
||||
}
|
36
lastcomm/pathnames.h
Normal file
36
lastcomm/pathnames.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* $NetBSD: pathnames.h,v 1.4 2003/08/07 11:14:18 agc Exp $ */
|
||||
|
||||
/*
|
||||
* 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. 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_ACCT "/var/account/acct"
|
1
locate/bigram/locate.bigram.8
Normal file
1
locate/bigram/locate.bigram.8
Normal file
@ -0,0 +1 @@
|
||||
.so man8/locate.code.8
|
110
locate/bigram/locate.bigram.c
Normal file
110
locate/bigram/locate.bigram.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* James A. Woods.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD: src/usr.bin/locate/bigram/locate.bigram.c,v 1.12 2005/02/09 09:13:36 stefanf Exp $
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)locate.bigram.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* bigram < sorted_file_names | sort -nr |
|
||||
* awk 'NR <= 128 { printf $2 }' > bigrams
|
||||
*
|
||||
* List bigrams for 'updatedb' script.
|
||||
* Use 'code' to encode a file using this output.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h> /* for MAXPATHLEN */
|
||||
#include "locate.h"
|
||||
|
||||
u_char buf1[MAXPATHLEN] = " ";
|
||||
u_char buf2[MAXPATHLEN];
|
||||
u_int bigram[UCHAR_MAX + 1][UCHAR_MAX + 1];
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
register u_char *cp;
|
||||
register u_char *oldpath = buf1, *path = buf2;
|
||||
register u_int i, j;
|
||||
|
||||
while (fgets(path, sizeof(buf2), stdin) != NULL) {
|
||||
|
||||
/*
|
||||
* We don't need remove newline character '\n'.
|
||||
* '\n' is less than ASCII_MIN and will be later
|
||||
* ignored at output.
|
||||
*/
|
||||
|
||||
|
||||
/* skip longest common prefix */
|
||||
for (cp = path; *cp == *oldpath; cp++, oldpath++)
|
||||
if (*cp == '\0')
|
||||
break;
|
||||
|
||||
while (*cp != '\0' && *(cp + 1) != '\0') {
|
||||
bigram[(u_char)*cp][(u_char)*(cp + 1)]++;
|
||||
cp += 2;
|
||||
}
|
||||
|
||||
/* swap pointers */
|
||||
if (path == buf1) {
|
||||
path = buf2;
|
||||
oldpath = buf1;
|
||||
} else {
|
||||
path = buf1;
|
||||
oldpath = buf2;
|
||||
}
|
||||
}
|
||||
|
||||
/* output, boundary check */
|
||||
for (i = ASCII_MIN; i <= ASCII_MAX; i++)
|
||||
for (j = ASCII_MIN; j <= ASCII_MAX; j++)
|
||||
if (bigram[i][j] != 0)
|
||||
(void)printf("%4u %c%c\n", bigram[i][j], i, j);
|
||||
|
||||
exit(0);
|
||||
}
|
23
locate/code/locate.code.8
Normal file
23
locate/code/locate.code.8
Normal file
@ -0,0 +1,23 @@
|
||||
.Dd October 15, 2004
|
||||
.Dt LOCATE.CODE 8
|
||||
.Os Darwin
|
||||
.Sh NAME
|
||||
.Nm locate.code, locate.bigram
|
||||
.Nd sorted list compressor
|
||||
.Sh SYNOPSIS
|
||||
.Nm locate.code
|
||||
.Nm locate.bigram
|
||||
.Sh DESCRIPTION
|
||||
.Nm locate.code
|
||||
and
|
||||
.Nm locate.bigram
|
||||
are programs used by
|
||||
.Xr locate 1
|
||||
during the indexing process.
|
||||
.Nm locate.code
|
||||
and
|
||||
.Nm locate.bigram
|
||||
should not be run manually.
|
||||
.Sh SEE ALSO
|
||||
.Xr locate 1 ,
|
||||
.Xr locate.updatedb 8
|
279
locate/code/locate.code.c
Normal file
279
locate/code/locate.code.c
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Copyright (c) 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* James A. Woods.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD: src/usr.bin/locate/code/locate.code.c,v 1.13 2002/03/22 01:22:47 imp Exp $
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)locate.code.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* PURPOSE: sorted list compressor (works with a modified 'find'
|
||||
* to encode/decode a filename database)
|
||||
*
|
||||
* USAGE: bigram < list > bigrams
|
||||
* process bigrams (see updatedb) > common_bigrams
|
||||
* code common_bigrams < list > squozen_list
|
||||
*
|
||||
* METHOD: Uses 'front compression' (see ";login:", Volume 8, Number 1
|
||||
* February/March 1983, p. 8). Output format is, per line, an
|
||||
* offset differential count byte followed by a partially bigram-
|
||||
* encoded ascii residue. A bigram is a two-character sequence,
|
||||
* the first 128 most common of which are encoded in one byte.
|
||||
*
|
||||
* EXAMPLE: For simple front compression with no bigram encoding,
|
||||
* if the input is... then the output is...
|
||||
*
|
||||
* /usr/src 0 /usr/src
|
||||
* /usr/src/cmd/aardvark.c 8 /cmd/aardvark.c
|
||||
* /usr/src/cmd/armadillo.c 14 armadillo.c
|
||||
* /usr/tmp/zoo 5 tmp/zoo
|
||||
*
|
||||
* The codes are:
|
||||
*
|
||||
* 0-28 likeliest differential counts + offset to make nonnegative
|
||||
* 30 switch code for out-of-range count to follow in next word
|
||||
* 31 an 8 bit char followed
|
||||
* 128-255 bigram codes (128 most common, as determined by 'updatedb')
|
||||
* 32-127 single character (printable) ascii residue (ie, literal)
|
||||
*
|
||||
* The locate database store any character except newline ('\n')
|
||||
* and NUL ('\0'). The 8-bit character support don't wast extra
|
||||
* space until you have characters in file names less than 32
|
||||
* or greather than 127.
|
||||
*
|
||||
*
|
||||
* SEE ALSO: updatedb.sh, ../bigram/locate.bigram.c
|
||||
*
|
||||
* AUTHOR: James A. Woods, Informatics General Corp.,
|
||||
* NASA Ames Research Center, 10/82
|
||||
* 8-bit file names characters:
|
||||
* Wolfram Schneider, Berlin September 1996
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "locate.h"
|
||||
|
||||
#define BGBUFSIZE (NBG * 2) /* size of bigram buffer */
|
||||
|
||||
u_char buf1[MAXPATHLEN] = " ";
|
||||
u_char buf2[MAXPATHLEN];
|
||||
u_char bigrams[BGBUFSIZE + 1] = { 0 };
|
||||
|
||||
#define LOOKUP 1 /* use a lookup array instead a function, 3x faster */
|
||||
|
||||
#ifdef LOOKUP
|
||||
#define BGINDEX(x) (big[(u_char)*x][(u_char)*(x + 1)])
|
||||
typedef short bg_t;
|
||||
bg_t big[UCHAR_MAX + 1][UCHAR_MAX + 1];
|
||||
#else
|
||||
#define BGINDEX(x) bgindex(x)
|
||||
typedef int bg_t;
|
||||
int bgindex(char *);
|
||||
#endif /* LOOKUP */
|
||||
|
||||
|
||||
void usage(void);
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register u_char *cp, *oldpath, *path;
|
||||
int ch, code, count, diffcount, oldcount;
|
||||
FILE *fp;
|
||||
register int i, j;
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != -1)
|
||||
switch(ch) {
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 1)
|
||||
usage();
|
||||
|
||||
if ((fp = fopen(argv[0], "r")) == NULL)
|
||||
err(1, "%s", argv[0]);
|
||||
|
||||
/* First copy bigram array to stdout. */
|
||||
(void)fgets(bigrams, BGBUFSIZE + 1, fp);
|
||||
|
||||
if (fwrite(bigrams, 1, BGBUFSIZE, stdout) != BGBUFSIZE)
|
||||
err(1, "stdout");
|
||||
(void)fclose(fp);
|
||||
|
||||
#ifdef LOOKUP
|
||||
/* init lookup table */
|
||||
for (i = 0; i < UCHAR_MAX + 1; i++)
|
||||
for (j = 0; j < UCHAR_MAX + 1; j++)
|
||||
big[i][j] = (bg_t)-1;
|
||||
|
||||
for (cp = bigrams, i = 0; *cp != '\0'; i += 2, cp += 2)
|
||||
big[(u_char)*cp][(u_char)*(cp + 1)] = (bg_t)i;
|
||||
|
||||
#endif /* LOOKUP */
|
||||
|
||||
oldpath = buf1;
|
||||
path = buf2;
|
||||
oldcount = 0;
|
||||
|
||||
while (fgets(path, sizeof(buf2), stdin) != NULL) {
|
||||
|
||||
/* skip empty lines */
|
||||
if (*path == '\n')
|
||||
continue;
|
||||
|
||||
/* remove newline */
|
||||
for (cp = path; *cp != '\0'; cp++) {
|
||||
#ifndef LOCATE_CHAR30
|
||||
/* old locate implementations core'd for char 30 */
|
||||
if (*cp == SWITCH)
|
||||
*cp = '?';
|
||||
else
|
||||
#endif /* !LOCATE_CHAR30 */
|
||||
|
||||
/* chop newline */
|
||||
if (*cp == '\n')
|
||||
*cp = '\0';
|
||||
}
|
||||
|
||||
/* Skip longest common prefix. */
|
||||
for (cp = path; *cp == *oldpath; cp++, oldpath++)
|
||||
if (*cp == '\0')
|
||||
break;
|
||||
|
||||
count = cp - path;
|
||||
diffcount = count - oldcount + OFFSET;
|
||||
oldcount = count;
|
||||
if (diffcount < 0 || diffcount > 2 * OFFSET) {
|
||||
if (putchar(SWITCH) == EOF ||
|
||||
putw(diffcount, stdout) == EOF)
|
||||
err(1, "stdout");
|
||||
} else
|
||||
if (putchar(diffcount) == EOF)
|
||||
err(1, "stdout");
|
||||
|
||||
while (*cp != '\0') {
|
||||
/* print *two* characters */
|
||||
|
||||
if ((code = BGINDEX(cp)) != (bg_t)-1) {
|
||||
/*
|
||||
* print *one* as bigram
|
||||
* Found, so mark byte with
|
||||
* parity bit.
|
||||
*/
|
||||
if (putchar((code / 2) | PARITY) == EOF)
|
||||
err(1, "stdout");
|
||||
cp += 2;
|
||||
}
|
||||
|
||||
else {
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (*cp == '\0')
|
||||
break;
|
||||
|
||||
/* print umlauts in file names */
|
||||
if (*cp < ASCII_MIN ||
|
||||
*cp > ASCII_MAX) {
|
||||
if (putchar(UMLAUT) == EOF ||
|
||||
putchar(*cp++) == EOF)
|
||||
err(1, "stdout");
|
||||
}
|
||||
|
||||
else {
|
||||
/* normal character */
|
||||
if(putchar(*cp++) == EOF)
|
||||
err(1, "stdout");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (path == buf1) { /* swap pointers */
|
||||
path = buf2;
|
||||
oldpath = buf1;
|
||||
} else {
|
||||
path = buf1;
|
||||
oldpath = buf2;
|
||||
}
|
||||
}
|
||||
/* Non-zero status if there were errors */
|
||||
if (fflush(stdout) != 0 || ferror(stdout))
|
||||
exit(1);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#ifndef LOOKUP
|
||||
int
|
||||
bgindex(bg) /* Return location of bg in bigrams or -1. */
|
||||
char *bg;
|
||||
{
|
||||
register char bg0, bg1, *p;
|
||||
|
||||
bg0 = bg[0];
|
||||
bg1 = bg[1];
|
||||
for (p = bigrams; *p != NULL; p++)
|
||||
if (*p++ == bg0 && *p == bg1)
|
||||
break;
|
||||
return (*p == NULL ? -1 : (--p - bigrams));
|
||||
}
|
||||
#endif /* !LOOKUP */
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: locate.code common_bigrams < list > squozen_list\n");
|
||||
exit(1);
|
||||
}
|
37
locate/locate/com.apple.locate.plist
Normal file
37
locate/locate/com.apple.locate.plist
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.apple.locate</string>
|
||||
<key>Disabled</key>
|
||||
<true/>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/usr/libexec/locate.updatedb</string>
|
||||
</array>
|
||||
<key>LowPriorityIO</key>
|
||||
<true/>
|
||||
<key>Nice</key>
|
||||
<integer>5</integer>
|
||||
<key>KeepAlive</key>
|
||||
<dict>
|
||||
<key>PathState</key>
|
||||
<dict>
|
||||
<key>/var/db/locate.database</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>StartCalendarInterval</key>
|
||||
<dict>
|
||||
<key>Hour</key>
|
||||
<integer>3</integer>
|
||||
<key>Minute</key>
|
||||
<integer>15</integer>
|
||||
<key>Weekday</key>
|
||||
<integer>6</integer>
|
||||
</dict>
|
||||
<key>AbandonProcessGroup</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
70
locate/locate/concatdb.sh
Normal file
70
locate/locate/concatdb.sh
Normal file
@ -0,0 +1,70 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) September 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
|
||||
# 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.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
#
|
||||
# concatdb - concatenate locate databases
|
||||
#
|
||||
# usage: concatdb database1 ... databaseN > newdb
|
||||
#
|
||||
# Sequence of databases is important.
|
||||
#
|
||||
# $FreeBSD: src/usr.bin/locate/locate/concatdb.sh,v 1.10 2000/01/12 08:01:00 kris Exp $
|
||||
|
||||
# The directory containing locate subprograms
|
||||
: ${LIBEXECDIR:=/usr/libexec}; export LIBEXECDIR
|
||||
|
||||
PATH=$LIBEXECDIR:/bin:/usr/bin:$PATH; export PATH
|
||||
|
||||
umask 077 # protect temp files
|
||||
|
||||
: ${TMPDIR:=/var/tmp}; export TMPDIR;
|
||||
test -d "$TMPDIR" || TMPDIR=/var/tmp
|
||||
|
||||
# utilities to built locate database
|
||||
: ${bigram:=locate.bigram}
|
||||
: ${code:=locate.code}
|
||||
: ${sort:=sort}
|
||||
: ${locate:=locate}
|
||||
|
||||
|
||||
case $# in
|
||||
[01]) echo 'usage: concatdb databases1 ... databaseN > newdb'
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
bigrams=`mktemp ${TMPDIR=/tmp}/_bigrams.XXXXXXXXXX` || exit 1
|
||||
trap 'rm -f $bigrams' 0 1 2 3 5 10 15
|
||||
|
||||
for db
|
||||
do
|
||||
$locate -d $db /
|
||||
done | $bigram | $sort -nr | awk 'NR <= 128 { printf $2 }' > $bigrams
|
||||
|
||||
for db
|
||||
do
|
||||
$locate -d $db /
|
||||
done | $code $bigrams
|
338
locate/locate/fastfind.c
Normal file
338
locate/locate/fastfind.c
Normal file
@ -0,0 +1,338 @@
|
||||
/*
|
||||
* Copyright (c) 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* James A. Woods.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD: src/usr.bin/locate/locate/fastfind.c,v 1.14 2005/12/07 12:22:46 des Exp $
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LOCATE_STATISTIC_
|
||||
#define _LOCATE_STATISTIC_
|
||||
|
||||
void
|
||||
statistic (fp, path_fcodes)
|
||||
FILE *fp; /* open database */
|
||||
char *path_fcodes; /* for error message */
|
||||
{
|
||||
register int lines, chars, size, big, zwerg;
|
||||
register u_char *p, *s;
|
||||
register int c;
|
||||
int count, umlaut;
|
||||
u_char bigram1[NBG], bigram2[NBG], path[MAXPATHLEN];
|
||||
|
||||
for (c = 0, p = bigram1, s = bigram2; c < NBG; c++) {
|
||||
p[c] = check_bigram_char(getc(fp));
|
||||
s[c] = check_bigram_char(getc(fp));
|
||||
}
|
||||
|
||||
lines = chars = big = zwerg = umlaut = 0;
|
||||
size = NBG + NBG;
|
||||
|
||||
for (c = getc(fp), count = 0; c != EOF; size++) {
|
||||
if (c == SWITCH) {
|
||||
count += getwf(fp) - OFFSET;
|
||||
size += sizeof(int);
|
||||
zwerg++;
|
||||
} else
|
||||
count += c - OFFSET;
|
||||
|
||||
for (p = path + count; (c = getc(fp)) > SWITCH; size++)
|
||||
if (c < PARITY) {
|
||||
if (c == UMLAUT) {
|
||||
c = getc(fp);
|
||||
size++;
|
||||
umlaut++;
|
||||
}
|
||||
p++;
|
||||
} else {
|
||||
/* bigram char */
|
||||
big++;
|
||||
p += 2;
|
||||
}
|
||||
|
||||
p++;
|
||||
lines++;
|
||||
chars += (p - path);
|
||||
}
|
||||
|
||||
(void)printf("\nDatabase: %s\n", path_fcodes);
|
||||
(void)printf("Compression: Front: %2.2f%%, ",
|
||||
(size + big - (2 * NBG)) / (chars / (float)100));
|
||||
(void)printf("Bigram: %2.2f%%, ", (size - big) / (size / (float)100));
|
||||
(void)printf("Total: %2.2f%%\n",
|
||||
(size - (2 * NBG)) / (chars / (float)100));
|
||||
(void)printf("Filenames: %d, ", lines);
|
||||
(void)printf("Characters: %d, ", chars);
|
||||
(void)printf("Database size: %d\n", size);
|
||||
(void)printf("Bigram characters: %d, ", big);
|
||||
(void)printf("Integers: %d, ", zwerg);
|
||||
(void)printf("8-Bit characters: %d\n", umlaut);
|
||||
|
||||
}
|
||||
#endif /* _LOCATE_STATISTIC_ */
|
||||
|
||||
extern char separator;
|
||||
|
||||
void
|
||||
#ifdef FF_MMAP
|
||||
|
||||
|
||||
#ifdef FF_ICASE
|
||||
fastfind_mmap_icase
|
||||
#else
|
||||
fastfind_mmap
|
||||
#endif /* FF_ICASE */
|
||||
(pathpart, paddr, len, database)
|
||||
char *pathpart; /* search string */
|
||||
caddr_t paddr; /* mmap pointer */
|
||||
int len; /* length of database */
|
||||
char *database; /* for error message */
|
||||
|
||||
|
||||
#else /* MMAP */
|
||||
|
||||
|
||||
#ifdef FF_ICASE
|
||||
fastfind_icase
|
||||
#else
|
||||
fastfind
|
||||
#endif /* FF_ICASE */
|
||||
|
||||
(fp, pathpart, database)
|
||||
FILE *fp; /* open database */
|
||||
char *pathpart; /* search string */
|
||||
char *database; /* for error message */
|
||||
|
||||
|
||||
#endif /* MMAP */
|
||||
|
||||
{
|
||||
register u_char *p, *s, *patend, *q, *foundchar;
|
||||
register int c, cc;
|
||||
int count, found, globflag;
|
||||
u_char *cutoff;
|
||||
u_char bigram1[NBG], bigram2[NBG], path[MAXPATHLEN];
|
||||
|
||||
#ifdef FF_ICASE
|
||||
/* use a lookup table for case insensitive search */
|
||||
u_char table[UCHAR_MAX + 1];
|
||||
|
||||
tolower_word(pathpart);
|
||||
#endif /* FF_ICASE*/
|
||||
|
||||
/* init bigram table */
|
||||
#ifdef FF_MMAP
|
||||
if (len < (2*NBG))
|
||||
errx(1, "database too small: %s", database);
|
||||
|
||||
for (c = 0, p = bigram1, s = bigram2; c < NBG; c++, len-= 2) {
|
||||
p[c] = check_bigram_char(*paddr++);
|
||||
s[c] = check_bigram_char(*paddr++);
|
||||
}
|
||||
#else
|
||||
for (c = 0, p = bigram1, s = bigram2; c < NBG; c++) {
|
||||
p[c] = check_bigram_char(getc(fp));
|
||||
s[c] = check_bigram_char(getc(fp));
|
||||
}
|
||||
#endif /* FF_MMAP */
|
||||
|
||||
/* find optimal (last) char for searching */
|
||||
for (p = pathpart; *p != '\0'; p++)
|
||||
if (index(LOCATE_REG, *p) != NULL)
|
||||
break;
|
||||
|
||||
if (*p == '\0')
|
||||
globflag = 0;
|
||||
else
|
||||
globflag = 1;
|
||||
|
||||
p = pathpart;
|
||||
patend = patprep(p);
|
||||
cc = *patend;
|
||||
|
||||
#ifdef FF_ICASE
|
||||
/* set patend char to true */
|
||||
for (c = 0; c < UCHAR_MAX + 1; c++)
|
||||
table[c] = 0;
|
||||
|
||||
table[TOLOWER(*patend)] = 1;
|
||||
table[toupper(*patend)] = 1;
|
||||
#endif /* FF_ICASE */
|
||||
|
||||
|
||||
/* main loop */
|
||||
found = count = 0;
|
||||
foundchar = 0;
|
||||
|
||||
#ifdef FF_MMAP
|
||||
c = (u_char)*paddr++; len--;
|
||||
for (; len > 0; ) {
|
||||
#else
|
||||
c = getc(fp);
|
||||
for (; c != EOF; ) {
|
||||
#endif /* FF_MMAP */
|
||||
|
||||
/* go forward or backward */
|
||||
if (c == SWITCH) { /* big step, an integer */
|
||||
#ifdef FF_MMAP
|
||||
count += getwm(paddr) - OFFSET;
|
||||
len -= INTSIZE; paddr += INTSIZE;
|
||||
#else
|
||||
count += getwf(fp) - OFFSET;
|
||||
#endif /* FF_MMAP */
|
||||
} else { /* slow step, =< 14 chars */
|
||||
count += c - OFFSET;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (count < 0) {
|
||||
errx(1, "Your locate database appears to be corrupt. "
|
||||
"Run 'sudo /usr/libexec/locate.updatedb' to "
|
||||
"regenerate the database.");
|
||||
}
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
/* overlay old path */
|
||||
p = path + count;
|
||||
foundchar = p - 1;
|
||||
|
||||
#ifdef FF_MMAP
|
||||
for (; len > 0;) {
|
||||
c = (u_char)*paddr++;
|
||||
len--;
|
||||
#else
|
||||
for (;;) {
|
||||
c = getc(fp);
|
||||
#endif /* FF_MMAP */
|
||||
/*
|
||||
* == UMLAUT: 8 bit char followed
|
||||
* <= SWITCH: offset
|
||||
* >= PARITY: bigram
|
||||
* rest: single ascii char
|
||||
*
|
||||
* offset < SWITCH < UMLAUT < ascii < PARITY < bigram
|
||||
*/
|
||||
if (c < PARITY) {
|
||||
if (c <= UMLAUT) {
|
||||
if (c == UMLAUT) {
|
||||
#ifdef FF_MMAP
|
||||
c = (u_char)*paddr++;
|
||||
len--;
|
||||
#else
|
||||
c = getc(fp);
|
||||
#endif /* FF_MMAP */
|
||||
|
||||
} else
|
||||
break; /* SWITCH */
|
||||
}
|
||||
#ifdef FF_ICASE
|
||||
if (table[c])
|
||||
#else
|
||||
if (c == cc)
|
||||
#endif /* FF_ICASE */
|
||||
foundchar = p;
|
||||
*p++ = c;
|
||||
}
|
||||
else {
|
||||
/* bigrams are parity-marked */
|
||||
TO7BIT(c);
|
||||
|
||||
#ifndef FF_ICASE
|
||||
if (bigram1[c] == cc ||
|
||||
bigram2[c] == cc)
|
||||
#else
|
||||
|
||||
if (table[bigram1[c]] ||
|
||||
table[bigram2[c]])
|
||||
#endif /* FF_ICASE */
|
||||
foundchar = p + 1;
|
||||
|
||||
*p++ = bigram1[c];
|
||||
*p++ = bigram2[c];
|
||||
}
|
||||
}
|
||||
|
||||
if (found) { /* previous line matched */
|
||||
cutoff = path;
|
||||
*p-- = '\0';
|
||||
foundchar = p;
|
||||
} else if (foundchar >= path + count) { /* a char matched */
|
||||
*p-- = '\0';
|
||||
cutoff = path + count;
|
||||
} else /* nothing to do */
|
||||
continue;
|
||||
|
||||
found = 0;
|
||||
for (s = foundchar; s >= cutoff; s--) {
|
||||
if (*s == cc
|
||||
#ifdef FF_ICASE
|
||||
|| TOLOWER(*s) == cc
|
||||
#endif /* FF_ICASE */
|
||||
) { /* fast first char check */
|
||||
for (p = patend - 1, q = s - 1; *p != '\0';
|
||||
p--, q--)
|
||||
if (*q != *p
|
||||
#ifdef FF_ICASE
|
||||
&& TOLOWER(*q) != *p
|
||||
#endif /* FF_ICASE */
|
||||
)
|
||||
break;
|
||||
if (*p == '\0') { /* fast match success */
|
||||
found = 1;
|
||||
if (!globflag ||
|
||||
#ifndef FF_ICASE
|
||||
!fnmatch(pathpart, path, 0))
|
||||
#else
|
||||
!fnmatch(pathpart, path,
|
||||
FNM_CASEFOLD))
|
||||
#endif /* !FF_ICASE */
|
||||
{
|
||||
if (f_silent)
|
||||
counter++;
|
||||
else if (f_limit) {
|
||||
counter++;
|
||||
if (f_limit >= counter)
|
||||
(void)printf("%s%c",path,separator);
|
||||
else
|
||||
errx(0, "[show only %d lines]", counter - 1);
|
||||
} else
|
||||
(void)printf("%s%c",path,separator);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
276
locate/locate/locate.1
Normal file
276
locate/locate/locate.1
Normal file
@ -0,0 +1,276 @@
|
||||
.\" Copyright (c) 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
|
||||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)locate.1 8.1 (Berkeley) 6/6/93
|
||||
.\" $FreeBSD: src/usr.bin/locate/locate/locate.1,v 1.34 2006/09/29 15:20:45 ru Exp $
|
||||
.\"
|
||||
.Dd August 17, 2006
|
||||
.Dt LOCATE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm locate
|
||||
.Nd find filenames quickly
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl 0Scims
|
||||
.Op Fl l Ar limit
|
||||
.Op Fl d Ar database
|
||||
.Ar pattern ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
program searches a database for all pathnames which match the specified
|
||||
.Ar pattern .
|
||||
The database is recomputed periodically (usually weekly or daily),
|
||||
and contains the pathnames
|
||||
of all files which are publicly accessible.
|
||||
.Pp
|
||||
Shell globbing and quoting characters
|
||||
.Dq ( * ,
|
||||
.Dq \&? ,
|
||||
.Dq \e ,
|
||||
.Dq \&[
|
||||
and
|
||||
.Dq \&] )
|
||||
may be used in
|
||||
.Ar pattern ,
|
||||
although they will have to be escaped from the shell.
|
||||
Preceding any character with a backslash
|
||||
.Pq Dq \e
|
||||
eliminates any special
|
||||
meaning which it may have.
|
||||
The matching differs in that no characters must be matched explicitly,
|
||||
including slashes
|
||||
.Pq Dq / .
|
||||
.Pp
|
||||
As a special case, a pattern containing no globbing characters
|
||||
.Pq Dq foo
|
||||
is matched as though it were
|
||||
.Dq *foo* .
|
||||
.Pp
|
||||
Historically, locate only stored characters between 32 and 127.
|
||||
The
|
||||
current implementation store any character except newline
|
||||
.Pq Sq \en
|
||||
and
|
||||
.Dv NUL
|
||||
.Pq Sq \e0 .
|
||||
The 8-bit character support does not waste extra space for
|
||||
plain ASCII file names.
|
||||
Characters less than 32 or greater than 127
|
||||
are stored in 2 bytes.
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width 10n
|
||||
.It Fl 0
|
||||
Print pathnames separated by an
|
||||
.Tn ASCII
|
||||
.Dv NUL
|
||||
character (character code 0) instead of default NL
|
||||
(newline, character code 10).
|
||||
.It Fl S
|
||||
Print some statistics about the database and exit.
|
||||
.It Fl c
|
||||
Suppress normal output; instead print a count of matching file names.
|
||||
.It Fl d Ar database
|
||||
Search in
|
||||
.Ar database
|
||||
instead of the default file name database.
|
||||
Multiple
|
||||
.Fl d
|
||||
options are allowed.
|
||||
Each additional
|
||||
.Fl d
|
||||
option adds the specified database to the list
|
||||
of databases to be searched.
|
||||
.Pp
|
||||
The option
|
||||
.Ar database
|
||||
may be a colon-separated list of databases.
|
||||
A single colon is a reference
|
||||
to the default database.
|
||||
.Bd -literal
|
||||
$ locate -d $HOME/lib/mydb: foo
|
||||
.Ed
|
||||
.Pp
|
||||
will first search string
|
||||
.Dq foo
|
||||
in
|
||||
.Pa $HOME/lib/mydb
|
||||
and then in
|
||||
.Pa /var/db/locate.database .
|
||||
.Bd -literal
|
||||
$ locate -d $HOME/lib/mydb::/cdrom/locate.database foo
|
||||
.Ed
|
||||
.Pp
|
||||
will first search string
|
||||
.Dq foo
|
||||
in
|
||||
.Pa $HOME/lib/mydb
|
||||
and then in
|
||||
.Pa /var/db/locate.database
|
||||
and then in
|
||||
.Pa /cdrom/locate.database .
|
||||
.Pp
|
||||
.Dl "$ locate -d db1 -d db2 -d db3 pattern"
|
||||
.Pp
|
||||
is the same as
|
||||
.Pp
|
||||
.Dl "$ locate -d db1:db2:db3 pattern"
|
||||
.Pp
|
||||
or
|
||||
.Pp
|
||||
.Dl "$ locate -d db1:db2 -d db3 pattern"
|
||||
.Pp
|
||||
If
|
||||
.Fl
|
||||
is given as the database name, standard input will be read instead.
|
||||
For example, you can compress your database
|
||||
and use:
|
||||
.Bd -literal
|
||||
$ zcat database.gz | locate -d - pattern
|
||||
.Ed
|
||||
.Pp
|
||||
This might be useful on machines with a fast CPU and little RAM and slow
|
||||
I/O.
|
||||
Note: you can only use
|
||||
.Em one
|
||||
pattern for stdin.
|
||||
.It Fl i
|
||||
Ignore case distinctions in both the pattern and the database.
|
||||
.It Fl l Ar number
|
||||
Limit output to
|
||||
.Ar number
|
||||
of file names and exit.
|
||||
.It Fl m
|
||||
Use
|
||||
.Xr mmap 2
|
||||
instead of the
|
||||
.Xr stdio 3
|
||||
library.
|
||||
This is the default behavior
|
||||
and is faster in most cases.
|
||||
.It Fl s
|
||||
Use the
|
||||
.Xr stdio 3
|
||||
library instead of
|
||||
.Xr mmap 2 .
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width LOCATE_PATH -compact
|
||||
.It Pa LOCATE_PATH
|
||||
path to the locate database if set and not empty, ignored if the
|
||||
.Fl d
|
||||
option was specified.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /System/Library/LaunchDaemons/com.apple.locate.plist -compact
|
||||
.It Pa /var/db/locate.database
|
||||
locate database
|
||||
.It Pa /usr/libexec/locate.updatedb
|
||||
Script to update the locate database
|
||||
.It Pa /System/Library/LaunchDaemons/com.apple.locate.plist
|
||||
Job that starts the database rebuild
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr find 1 ,
|
||||
.Xr whereis 1 ,
|
||||
.Xr which 1 ,
|
||||
.Xr fnmatch 3 ,
|
||||
.Xr locate.updatedb 8
|
||||
.Rs
|
||||
.%A Woods, James A.
|
||||
.%D 1983
|
||||
.%T "Finding Files Fast"
|
||||
.%J ";login"
|
||||
.%V 8:1
|
||||
.%P pp. 8-10
|
||||
.Re
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command first appeared in
|
||||
.Bx 4.4 .
|
||||
Many new features were
|
||||
added in
|
||||
.Fx 2.2 .
|
||||
.Sh BUGS
|
||||
The
|
||||
.Nm
|
||||
program may fail to list some files that are present, or may
|
||||
list files that have been removed from the system.
|
||||
This is because
|
||||
locate only reports files that are present in the database, which is
|
||||
typically only regenerated once a week by the
|
||||
.Pa /System/Library/LaunchDaemons/com.apple.locate.plist
|
||||
job.
|
||||
Use
|
||||
.Xr find 1
|
||||
to locate files that are of a more transitory nature.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
database is typically built by user
|
||||
.Dq nobody
|
||||
and the
|
||||
.Xr locate.updatedb 8
|
||||
utility skips directories
|
||||
which are not readable for user
|
||||
.Dq nobody ,
|
||||
group
|
||||
.Dq nobody ,
|
||||
or
|
||||
world.
|
||||
For example, if your HOME directory is not world-readable,
|
||||
.Em none
|
||||
of your files are
|
||||
in the database.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
database is not byte order independent.
|
||||
It is not possible
|
||||
to share the databases between machines with different byte order.
|
||||
The current
|
||||
.Nm
|
||||
implementation understands databases in host byte order or
|
||||
network byte order if both architectures use the same integer size.
|
||||
So on a
|
||||
.Fx Ns /i386
|
||||
machine
|
||||
(little endian), you can read
|
||||
a locate database which was built on SunOS/sparc machine
|
||||
(big endian, net).
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility does not recognize multibyte characters.
|
389
locate/locate/locate.c
Normal file
389
locate/locate/locate.c
Normal file
@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Copyright (c) 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* James A. Woods.
|
||||
*
|
||||
* 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 const char copyright[] =
|
||||
"@(#) Copyright (c) 1995-1996 Wolfram Schneider, Berlin.\n\
|
||||
@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)locate.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD: src/usr.bin/locate/locate/locate.c,v 1.17 2006/06/11 17:40:25 maxim Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Ref: Usenix ;login:, Vol 8, No 1, February/March, 1983, p. 8.
|
||||
*
|
||||
* Locate scans a file list for the full pathname of a file given only part
|
||||
* of the name. The list has been processed with with "front-compression"
|
||||
* and bigram coding. Front compression reduces space by a factor of 4-5,
|
||||
* bigram coding by a further 20-25%.
|
||||
*
|
||||
* The codes are:
|
||||
*
|
||||
* 0-28 likeliest differential counts + offset to make nonnegative
|
||||
* 30 switch code for out-of-range count to follow in next word
|
||||
* 31 an 8 bit char followed
|
||||
* 128-255 bigram codes (128 most common, as determined by 'updatedb')
|
||||
* 32-127 single character (printable) ascii residue (ie, literal)
|
||||
*
|
||||
* A novel two-tiered string search technique is employed:
|
||||
*
|
||||
* First, a metacharacter-free subpattern and partial pathname is matched
|
||||
* BACKWARDS to avoid full expansion of the pathname list. The time savings
|
||||
* is 40-50% over forward matching, which cannot efficiently handle
|
||||
* overlapped search patterns and compressed path residue.
|
||||
*
|
||||
* Then, the actual shell glob-style regular expression (if in this form) is
|
||||
* matched against the candidate pathnames using the slower routines provided
|
||||
* in the standard 'find'.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#ifdef __APPLE__
|
||||
#include <errno.h>
|
||||
#endif /* __APPLE__ */
|
||||
#include <fnmatch.h>
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef MMAP
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# include <sys/mman.h>
|
||||
# include <fcntl.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "locate.h"
|
||||
#include "pathnames.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
# include <sys/time.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
int f_mmap; /* use mmap */
|
||||
int f_icase; /* ignore case */
|
||||
int f_stdin; /* read database from stdin */
|
||||
int f_statistic; /* print statistic */
|
||||
int f_silent; /* suppress output, show only count of matches */
|
||||
int f_limit; /* limit number of output lines, 0 == infinite */
|
||||
u_int counter; /* counter for matches [-c] */
|
||||
char separator='\n'; /* line separator */
|
||||
#ifdef __APPLE__
|
||||
u_char myctype[UCHAR_MAX + 1];
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
|
||||
void usage(void);
|
||||
void statistic(FILE *, char *);
|
||||
void fastfind(FILE *, char *, char *);
|
||||
void fastfind_icase(FILE *, char *, char *);
|
||||
void fastfind_mmap(char *, caddr_t, int, char *);
|
||||
void fastfind_mmap_icase(char *, caddr_t, int, char *);
|
||||
void search_mmap(char *, char **);
|
||||
void search_fopen(char *, char **);
|
||||
unsigned long cputime(void);
|
||||
|
||||
extern char **colon(char **, char*, char*);
|
||||
extern void print_matches(u_int);
|
||||
extern int getwm(caddr_t);
|
||||
extern int getwf(FILE *);
|
||||
extern u_char *tolower_word(u_char *);
|
||||
extern int check_bigram_char(int);
|
||||
extern char *patprep(char *);
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
register int ch;
|
||||
char **dbv = NULL;
|
||||
char *path_fcodes; /* locate database */
|
||||
#ifdef MMAP
|
||||
f_mmap = 1; /* mmap is default */
|
||||
#endif
|
||||
(void) setlocale(LC_ALL, "");
|
||||
|
||||
while ((ch = getopt(argc, argv, "0Scd:il:ms")) != -1)
|
||||
switch(ch) {
|
||||
case '0': /* 'find -print0' style */
|
||||
separator = '\0';
|
||||
break;
|
||||
case 'S': /* statistic lines */
|
||||
f_statistic = 1;
|
||||
break;
|
||||
case 'l': /* limit number of output lines, 0 == infinite */
|
||||
f_limit = atoi(optarg);
|
||||
break;
|
||||
case 'd': /* database */
|
||||
dbv = colon(dbv, optarg, _PATH_FCODES);
|
||||
break;
|
||||
case 'i': /* ignore case */
|
||||
f_icase = 1;
|
||||
break;
|
||||
case 'm': /* mmap */
|
||||
#ifdef MMAP
|
||||
f_mmap = 1;
|
||||
#else
|
||||
warnx("mmap(2) not implemented");
|
||||
#endif
|
||||
break;
|
||||
case 's': /* stdio lib */
|
||||
f_mmap = 0;
|
||||
break;
|
||||
case 'c': /* suppress output, show only count of matches */
|
||||
f_silent = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argv += optind;
|
||||
argc -= optind;
|
||||
|
||||
/* to few arguments */
|
||||
if (argc < 1 && !(f_statistic))
|
||||
usage();
|
||||
|
||||
/* no (valid) database as argument */
|
||||
if (dbv == NULL || *dbv == NULL) {
|
||||
/* try to read database from enviroment */
|
||||
if ((path_fcodes = getenv("LOCATE_PATH")) == NULL ||
|
||||
*path_fcodes == '\0')
|
||||
/* use default database */
|
||||
dbv = colon(dbv, _PATH_FCODES, _PATH_FCODES);
|
||||
else /* $LOCATE_PATH */
|
||||
dbv = colon(dbv, path_fcodes, _PATH_FCODES);
|
||||
}
|
||||
|
||||
if (f_icase && UCHAR_MAX < 4096) /* init tolower lookup table */
|
||||
for (ch = 0; ch < UCHAR_MAX + 1; ch++)
|
||||
myctype[ch] = tolower(ch);
|
||||
|
||||
/* foreach database ... */
|
||||
while((path_fcodes = *dbv) != NULL) {
|
||||
dbv++;
|
||||
|
||||
if (!strcmp(path_fcodes, "-"))
|
||||
f_stdin = 1;
|
||||
else
|
||||
f_stdin = 0;
|
||||
|
||||
#ifndef MMAP
|
||||
f_mmap = 0; /* be paranoid */
|
||||
#endif
|
||||
if (!f_mmap || f_stdin || f_statistic)
|
||||
search_fopen(path_fcodes, argv);
|
||||
else
|
||||
search_mmap(path_fcodes, argv);
|
||||
}
|
||||
|
||||
if (f_silent)
|
||||
print_matches(counter);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
search_fopen(db, s)
|
||||
char *db; /* database */
|
||||
char **s; /* search strings */
|
||||
{
|
||||
FILE *fp;
|
||||
#ifdef DEBUG
|
||||
long t0;
|
||||
#endif
|
||||
|
||||
/* can only read stdin once */
|
||||
if (f_stdin) {
|
||||
fp = stdin;
|
||||
if (*(s+1) != NULL) {
|
||||
warnx("read database from stdin, use only `%s' as pattern", *s);
|
||||
*(s+1) = NULL;
|
||||
}
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
else if ((fp = fopen(db, "r")) == NULL) {
|
||||
if (errno == ENOENT && !strcmp(db, _PATH_FCODES)) {
|
||||
fprintf(stderr, "\n"
|
||||
"WARNING: The locate database (%s) does not exist.\n"
|
||||
"To create the database, run the following command:\n"
|
||||
"\n"
|
||||
" sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.locate.plist\n"
|
||||
"\n"
|
||||
"Please be aware that the database can take some time to generate; once\n"
|
||||
"the database has been created, this message will no longer appear.\n"
|
||||
"\n",
|
||||
db);
|
||||
exit(1);
|
||||
}
|
||||
err(1, "`%s'", db);
|
||||
}
|
||||
#else /* !__APPLE__ */
|
||||
else if ((fp = fopen(db, "r")) == NULL)
|
||||
err(1, "`%s'", db);
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
/* count only chars or lines */
|
||||
if (f_statistic) {
|
||||
statistic(fp, db);
|
||||
(void)fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* foreach search string ... */
|
||||
while(*s != NULL) {
|
||||
#ifdef DEBUG
|
||||
t0 = cputime();
|
||||
#endif
|
||||
if (!f_stdin &&
|
||||
fseek(fp, (long)0, SEEK_SET) == -1)
|
||||
err(1, "fseek to begin of ``%s''\n", db);
|
||||
|
||||
if (f_icase)
|
||||
fastfind_icase(fp, *s, db);
|
||||
else
|
||||
fastfind(fp, *s, db);
|
||||
#ifdef DEBUG
|
||||
warnx("fastfind %ld ms", cputime () - t0);
|
||||
#endif
|
||||
s++;
|
||||
}
|
||||
(void)fclose(fp);
|
||||
}
|
||||
|
||||
#ifdef MMAP
|
||||
void
|
||||
search_mmap(db, s)
|
||||
char *db; /* database */
|
||||
char **s; /* search strings */
|
||||
{
|
||||
struct stat sb;
|
||||
int fd;
|
||||
caddr_t p;
|
||||
off_t len;
|
||||
#ifdef DEBUG
|
||||
long t0;
|
||||
#endif
|
||||
if ((fd = open(db, O_RDONLY)) == -1 ||
|
||||
fstat(fd, &sb) == -1)
|
||||
err(1, "`%s'", db);
|
||||
len = sb.st_size;
|
||||
|
||||
if ((p = mmap((caddr_t)0, (size_t)len,
|
||||
PROT_READ, MAP_SHARED,
|
||||
fd, (off_t)0)) == MAP_FAILED)
|
||||
err(1, "mmap ``%s''", db);
|
||||
|
||||
/* foreach search string ... */
|
||||
while (*s != NULL) {
|
||||
#ifdef DEBUG
|
||||
t0 = cputime();
|
||||
#endif
|
||||
if (f_icase)
|
||||
fastfind_mmap_icase(*s, p, (int)len, db);
|
||||
else
|
||||
fastfind_mmap(*s, p, (int)len, db);
|
||||
#ifdef DEBUG
|
||||
warnx("fastfind %ld ms", cputime () - t0);
|
||||
#endif
|
||||
s++;
|
||||
}
|
||||
|
||||
if (munmap(p, (size_t)len) == -1)
|
||||
warn("munmap %s\n", db);
|
||||
|
||||
(void)close(fd);
|
||||
}
|
||||
#endif /* MMAP */
|
||||
|
||||
#ifdef DEBUG
|
||||
unsigned long
|
||||
cputime ()
|
||||
{
|
||||
struct rusage rus;
|
||||
|
||||
getrusage(0, &rus);
|
||||
return(rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000);
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
void
|
||||
usage ()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: locate [-0Scims] [-l limit] [-d database] pattern ...\n\n");
|
||||
(void)fprintf(stderr,
|
||||
"default database: `%s' or $LOCATE_PATH\n", _PATH_FCODES);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* load fastfind functions */
|
||||
|
||||
/* statistic */
|
||||
/* fastfind_mmap, fastfind_mmap_icase */
|
||||
#ifdef MMAP
|
||||
#undef FF_MMAP
|
||||
#undef FF_ICASE
|
||||
|
||||
#define FF_MMAP
|
||||
#include "fastfind.c"
|
||||
#define FF_ICASE
|
||||
#include "fastfind.c"
|
||||
#endif /* MMAP */
|
||||
|
||||
/* fopen */
|
||||
/* fastfind, fastfind_icase */
|
||||
#undef FF_MMAP
|
||||
#undef FF_ICASE
|
||||
#include "fastfind.c"
|
||||
#define FF_ICASE
|
||||
#include "fastfind.c"
|
76
locate/locate/locate.h
Normal file
76
locate/locate/locate.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
|
||||
* 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.
|
||||
*
|
||||
* @(#)locate.h 8.1 (Berkeley) 6/6/93
|
||||
* $FreeBSD: src/usr.bin/locate/locate/locate.h,v 1.7 1999/08/28 01:02:59 peter Exp $
|
||||
*/
|
||||
|
||||
/* Symbolic constants shared by locate.c and code.c */
|
||||
|
||||
#define NBG 128 /* number of bigrams considered */
|
||||
#define OFFSET 14 /* abs value of max likely diff */
|
||||
#define PARITY 0200 /* parity bit */
|
||||
#define SWITCH 30 /* switch code */
|
||||
#define UMLAUT 31 /* an 8 bit char followed */
|
||||
|
||||
/* 0-28 likeliest differential counts + offset to make nonnegative */
|
||||
#define LDC_MIN 0
|
||||
#define LDC_MAX 28
|
||||
|
||||
/* 128-255 bigram codes (128 most common, as determined by 'updatedb') */
|
||||
#define BIGRAM_MIN (UCHAR_MAX - CHAR_MAX)
|
||||
#define BIGRAM_MAX UCHAR_MAX
|
||||
|
||||
/* 32-127 single character (printable) ascii residue (ie, literal) */
|
||||
#define ASCII_MIN 32
|
||||
#define ASCII_MAX CHAR_MAX
|
||||
|
||||
/* #define TO7BIT(x) (x = ( ((u_char)x) & CHAR_MAX )) */
|
||||
#define TO7BIT(x) (x = x & CHAR_MAX )
|
||||
|
||||
|
||||
#if UCHAR_MAX >= 4096
|
||||
define TOLOWER(ch) tolower(ch)
|
||||
#else
|
||||
|
||||
#ifdef __APPLE__
|
||||
extern u_char myctype[UCHAR_MAX + 1];
|
||||
#else
|
||||
u_char myctype[UCHAR_MAX + 1];
|
||||
#endif
|
||||
#define TOLOWER(ch) (myctype[ch])
|
||||
#endif
|
||||
|
||||
#define INTSIZE (sizeof(int))
|
||||
|
||||
#define LOCATE_REG "*?[]\\" /* fnmatch(3) meta characters */
|
26
locate/locate/locate.rc
Normal file
26
locate/locate/locate.rc
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
# /etc/locate.rc - command script for updatedb(8)
|
||||
#
|
||||
# $FreeBSD: src/usr.bin/locate/locate/locate.rc,v 1.9 2005/08/22 08:22:48 cperciva Exp $
|
||||
|
||||
#
|
||||
# All commented values are the defaults
|
||||
#
|
||||
# temp directory
|
||||
#TMPDIR="/tmp"
|
||||
|
||||
# the actual database
|
||||
#FCODES="/var/db/locate.database"
|
||||
|
||||
# directories to be put in the database
|
||||
#SEARCHPATHS="/"
|
||||
|
||||
# directories unwanted in output
|
||||
#PRUNEPATHS="/tmp /var/tmp"
|
||||
|
||||
# filesystems allowed. Beware: a non-listed filesystem will be pruned
|
||||
# and if the SEARCHPATHS starts in such a filesystem locate will build
|
||||
# an empty database.
|
||||
#
|
||||
# be careful if you add 'nfs'
|
||||
#FILESYSTEMS="hfs ufs"
|
75
locate/locate/locate.updatedb.8
Executable file
75
locate/locate/locate.updatedb.8
Executable file
@ -0,0 +1,75 @@
|
||||
.\" Copyright (c) 1996
|
||||
.\" Mike Pritchard <mpp@FreeBSD.org>. 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 Mike Pritchard.
|
||||
.\" 4. Neither the name of the author 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 AUTHOR 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.
|
||||
.\"
|
||||
.\" $FreeBSD: src/usr.bin/locate/locate/locate.updatedb.8,v 1.12 2005/01/18 13:43:50 ru Exp $
|
||||
.\"
|
||||
.Dd February 11, 1996
|
||||
.Dt LOCATE.UPDATEDB 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm locate.updatedb
|
||||
.Nd update locate database
|
||||
.Sh SYNOPSIS
|
||||
.Nm /usr/libexec/locate.updatedb
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility updates the database used by
|
||||
.Xr locate 1 .
|
||||
It is typically run once a week by the
|
||||
.Pa /System/Library/LaunchDaemons/com.apple.locate.plist
|
||||
job.
|
||||
.Pp
|
||||
The contents of the newly built database can be controlled by the
|
||||
.Pa /etc/locate.rc
|
||||
file.
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width /var/db/locate.database -compact
|
||||
.It Pa LOCATE_CONFIG
|
||||
path to the configuration file
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /var/db/locate.database -compact
|
||||
.It Pa /var/db/locate.database
|
||||
the default database
|
||||
.It Pa /etc/locate.rc
|
||||
the configuration file
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr locate 1 ,
|
||||
.Xr launchd 8
|
||||
.Rs
|
||||
.%A Woods, James A.
|
||||
.%D 1983
|
||||
.%T "Finding Files Fast"
|
||||
.%J ";login"
|
||||
.%V 8:1
|
||||
.%P pp. 8-10
|
||||
.Re
|
92
locate/locate/mklocatedb.sh
Normal file
92
locate/locate/mklocatedb.sh
Normal file
@ -0,0 +1,92 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) September 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
|
||||
# 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.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
#
|
||||
# mklocatedb - build locate database
|
||||
#
|
||||
# usage: mklocatedb [-presort] < filelist > database
|
||||
#
|
||||
# $FreeBSD: src/usr.bin/locate/locate/mklocatedb.sh,v 1.13 2002/07/22 05:35:59 tjr Exp $
|
||||
|
||||
# The directory containing locate subprograms
|
||||
: ${LIBEXECDIR:=/usr/libexec}; export LIBEXECDIR
|
||||
|
||||
PATH=$LIBEXECDIR:/bin:/usr/bin:$PATH; export PATH
|
||||
|
||||
umask 077 # protect temp files
|
||||
|
||||
: ${TMPDIR:=/tmp}; export TMPDIR
|
||||
test -d "$TMPDIR" || TMPDIR=/tmp
|
||||
if ! TMPDIR=`mktemp -d $TMPDIR/mklocateXXXXXXXXXX`; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# utilities to built locate database
|
||||
: ${bigram:=locate.bigram}
|
||||
: ${code:=locate.code}
|
||||
: ${sort:=sort}
|
||||
|
||||
|
||||
sortopt="-u -T $TMPDIR"
|
||||
sortcmd=$sort
|
||||
|
||||
|
||||
bigrams=$TMPDIR/_mklocatedb$$.bigrams
|
||||
filelist=$TMPDIR/_mklocatedb$$.list
|
||||
|
||||
trap 'rm -f $bigrams $filelist; rmdir $TMPDIR' 0 1 2 3 5 10 15
|
||||
|
||||
|
||||
# Input already sorted
|
||||
if [ X"$1" = "X-presort" ]; then
|
||||
shift;
|
||||
|
||||
# create an empty file
|
||||
true > $bigrams
|
||||
|
||||
# Locate database bootstrapping
|
||||
# 1. first build a temp database without bigram compression
|
||||
# 2. create the bigram from the temp database
|
||||
# 3. create the real locate database with bigram compression.
|
||||
#
|
||||
# This scheme avoid large temporary files in /tmp
|
||||
|
||||
$code $bigrams > $filelist || exit 1
|
||||
locate -d $filelist / | $bigram | $sort -nr | head -128 |
|
||||
awk '{if (/^[ ]*[0-9]+[ ]+..$/) {printf("%s",$2)} else {exit 1}}' > $bigrams || exit 1
|
||||
locate -d $filelist / | $code $bigrams || exit 1
|
||||
exit
|
||||
|
||||
else
|
||||
if $sortcmd $sortopt > $filelist; then
|
||||
$bigram < $filelist | $sort -nr |
|
||||
awk '{if (/^[ ]*[0-9]+[ ]+..$/) {printf("%s",$2)} else {exit 1}}' > $bigrams || exit 1
|
||||
$code $bigrams < $filelist || exit 1
|
||||
else
|
||||
echo "`basename $0`: cannot build locate database" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
36
locate/locate/pathnames.h
Normal file
36
locate/locate/pathnames.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)pathnames.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
#define _PATH_FCODES "/var/db/locate.database"
|
101
locate/locate/updatedb.sh
Normal file
101
locate/locate/updatedb.sh
Normal file
@ -0,0 +1,101 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) September 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
|
||||
# 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.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
#
|
||||
# updatedb - update locate database for local mounted filesystems
|
||||
#
|
||||
# $FreeBSD: src/usr.bin/locate/locate/updatedb.sh,v 1.20 2005/11/12 12:45:08 grog Exp $
|
||||
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
rc=0
|
||||
export FCODES=`sudo -u nobody mktemp -t updatedb`
|
||||
chown nobody $FCODES
|
||||
tmpdb=`su -fm nobody -c "$0"` || rc=1
|
||||
if [ $rc = 0 ]; then
|
||||
install -m 0444 -o nobody -g wheel $FCODES /var/db/locate.database
|
||||
fi
|
||||
rm $FCODES
|
||||
exit $rc
|
||||
fi
|
||||
: ${LOCATE_CONFIG="/etc/locate.rc"}
|
||||
if [ -f "$LOCATE_CONFIG" -a -r "$LOCATE_CONFIG" ]; then
|
||||
. $LOCATE_CONFIG
|
||||
fi
|
||||
|
||||
# The directory containing locate subprograms
|
||||
: ${LIBEXECDIR:=/usr/libexec}; export LIBEXECDIR
|
||||
: ${TMPDIR:=/tmp}; export TMPDIR
|
||||
if ! TMPDIR=`mktemp -d $TMPDIR/locateXXXXXXXXXX`; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PATH=$LIBEXECDIR:/bin:/usr/bin:$PATH; export PATH
|
||||
|
||||
# 6497475
|
||||
set -o noglob
|
||||
|
||||
: ${mklocatedb:=locate.mklocatedb} # make locate database program
|
||||
: ${FCODES:=/var/db/locate.database} # the database
|
||||
: ${SEARCHPATHS:="/"} # directories to be put in the database
|
||||
: ${PRUNEPATHS:="/private/tmp /private/var/folders /private/var/tmp */Backups.backupdb"} # unwanted directories
|
||||
: ${FILESYSTEMS:="hfs ufs"} # allowed filesystems
|
||||
: ${find:=find}
|
||||
|
||||
case X"$SEARCHPATHS" in
|
||||
X) echo "$0: empty variable SEARCHPATHS"; exit 1;; esac
|
||||
case X"$FILESYSTEMS" in
|
||||
X) echo "$0: empty variable FILESYSTEMS"; exit 1;; esac
|
||||
|
||||
# Make a list a paths to exclude in the locate run
|
||||
excludes="! (" or=""
|
||||
for fstype in $FILESYSTEMS
|
||||
do
|
||||
excludes="$excludes $or -fstype $fstype"
|
||||
or="-or"
|
||||
done
|
||||
excludes="$excludes ) -prune"
|
||||
|
||||
case X"$PRUNEPATHS" in
|
||||
X) ;;
|
||||
*) for path in $PRUNEPATHS
|
||||
do
|
||||
excludes="$excludes -or -path $path -prune"
|
||||
done;;
|
||||
esac
|
||||
|
||||
tmp=$TMPDIR/_updatedb$$
|
||||
trap 'rm -f $tmp; rmdir $TMPDIR; exit' 0 1 2 3 5 10 15
|
||||
|
||||
# search locally
|
||||
# echo $find $SEARCHPATHS $excludes -or -print && exit
|
||||
if $find -s $SEARCHPATHS $excludes -or -print 2>/dev/null |
|
||||
$mklocatedb -presort > $tmp
|
||||
then
|
||||
case X"`$find $tmp -size -257c -print`" in
|
||||
X) cat $tmp > $FCODES;;
|
||||
*) echo "updatedb: locate database $tmp is empty"
|
||||
exit 1
|
||||
esac
|
||||
fi
|
278
locate/locate/util.c
Normal file
278
locate/locate/util.c
Normal file
@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (c) 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* James A. Woods.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD: src/usr.bin/locate/locate/util.c,v 1.10 2002/06/24 12:40:11 naddy Exp $
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
#include <sys/param.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "locate.h"
|
||||
|
||||
char **colon(char **, char*, char*);
|
||||
char *patprep(char *);
|
||||
void print_matches(u_int);
|
||||
u_char *tolower_word(u_char *);
|
||||
int getwm(caddr_t);
|
||||
int getwf(FILE *);
|
||||
int check_bigram_char(int);
|
||||
|
||||
/*
|
||||
* Validate bigram chars. If the test failed the database is corrupt
|
||||
* or the database is obviously not a locate database.
|
||||
*/
|
||||
int
|
||||
check_bigram_char(ch)
|
||||
int ch;
|
||||
{
|
||||
/* legal bigram: 0, ASCII_MIN ... ASCII_MAX */
|
||||
if (ch == 0 ||
|
||||
(ch >= ASCII_MIN && ch <= ASCII_MAX))
|
||||
return(ch);
|
||||
|
||||
errx(1,
|
||||
"locate database header corrupt, bigram char outside 0, %d-%d: %d",
|
||||
ASCII_MIN, ASCII_MAX, ch);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* split a colon separated string into a char vector
|
||||
*
|
||||
* "bla:foo" -> {"foo", "bla"}
|
||||
* "bla:" -> {"foo", dot}
|
||||
* "bla" -> {"bla"}
|
||||
* "" -> do nothing
|
||||
*
|
||||
*/
|
||||
char **
|
||||
colon(dbv, path, dot)
|
||||
char **dbv;
|
||||
char *path;
|
||||
char *dot; /* default for single ':' */
|
||||
{
|
||||
int vlen, slen;
|
||||
char *c, *ch, *p;
|
||||
char **pv;
|
||||
|
||||
if (dbv == NULL) {
|
||||
if ((dbv = malloc(sizeof(char **))) == NULL)
|
||||
err(1, "malloc");
|
||||
*dbv = NULL;
|
||||
}
|
||||
|
||||
/* empty string */
|
||||
if (*path == '\0') {
|
||||
warnx("empty database name, ignored");
|
||||
return(dbv);
|
||||
}
|
||||
|
||||
/* length of string vector */
|
||||
for(vlen = 0, pv = dbv; *pv != NULL; pv++, vlen++);
|
||||
|
||||
for (ch = c = path; ; ch++) {
|
||||
if (*ch == ':' ||
|
||||
(!*ch && !(*(ch - 1) == ':' && ch == 1+ path))) {
|
||||
/* single colon -> dot */
|
||||
if (ch == c)
|
||||
p = dot;
|
||||
else {
|
||||
/* a string */
|
||||
slen = ch - c;
|
||||
if ((p = malloc(sizeof(char) * (slen + 1)))
|
||||
== NULL)
|
||||
err(1, "malloc");
|
||||
bcopy(c, p, slen);
|
||||
*(p + slen) = '\0';
|
||||
}
|
||||
/* increase dbv with element p */
|
||||
if ((dbv = realloc(dbv, sizeof(char **) * (vlen + 2)))
|
||||
== NULL)
|
||||
err(1, "realloc");
|
||||
*(dbv + vlen) = p;
|
||||
*(dbv + ++vlen) = NULL;
|
||||
c = ch + 1;
|
||||
}
|
||||
if (*ch == '\0')
|
||||
break;
|
||||
}
|
||||
return (dbv);
|
||||
}
|
||||
|
||||
void
|
||||
print_matches(counter)
|
||||
u_int counter;
|
||||
{
|
||||
(void)printf("%d\n", counter);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* extract last glob-free subpattern in name for fast pre-match; prepend
|
||||
* '\0' for backwards match; return end of new pattern
|
||||
*/
|
||||
static char globfree[100];
|
||||
|
||||
char *
|
||||
patprep(name)
|
||||
char *name;
|
||||
{
|
||||
register char *endmark, *p, *subp;
|
||||
|
||||
subp = globfree;
|
||||
*subp++ = '\0'; /* set first element to '\0' */
|
||||
p = name + strlen(name) - 1;
|
||||
|
||||
/* skip trailing metacharacters */
|
||||
for (; p >= name; p--)
|
||||
if (index(LOCATE_REG, *p) == NULL)
|
||||
break;
|
||||
|
||||
/*
|
||||
* check if maybe we are in a character class
|
||||
*
|
||||
* 'foo.[ch]'
|
||||
* |----< p
|
||||
*/
|
||||
if (p >= name &&
|
||||
(index(p, '[') != NULL || index(p, ']') != NULL)) {
|
||||
for (p = name; *p != '\0'; p++)
|
||||
if (*p == ']' || *p == '[')
|
||||
break;
|
||||
p--;
|
||||
|
||||
/*
|
||||
* cannot find a non-meta character, give up
|
||||
* '*\*[a-z]'
|
||||
* |-------< p
|
||||
*/
|
||||
if (p >= name && index(LOCATE_REG, *p) != NULL)
|
||||
p = name - 1;
|
||||
}
|
||||
|
||||
if (p < name)
|
||||
/* only meta chars: "???", force '/' search */
|
||||
*subp++ = '/';
|
||||
|
||||
else {
|
||||
for (endmark = p; p >= name; p--)
|
||||
if (index(LOCATE_REG, *p) != NULL)
|
||||
break;
|
||||
for (++p;
|
||||
(p <= endmark) && subp < (globfree + sizeof(globfree));)
|
||||
*subp++ = *p++;
|
||||
}
|
||||
*subp = '\0';
|
||||
return(--subp);
|
||||
}
|
||||
|
||||
/* tolower word */
|
||||
u_char *
|
||||
tolower_word(word)
|
||||
u_char *word;
|
||||
{
|
||||
register u_char *p;
|
||||
|
||||
for(p = word; *p != '\0'; p++)
|
||||
*p = TOLOWER(*p);
|
||||
|
||||
return(word);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read integer from mmap pointer.
|
||||
* Essential a simple ``return *(int *)p'' but avoid sigbus
|
||||
* for integer alignment (SunOS 4.x, 5.x).
|
||||
*
|
||||
* Convert network byte order to host byte order if neccessary.
|
||||
* So we can read on FreeBSD/i386 (little endian) a locate database
|
||||
* which was built on SunOS/sparc (big endian).
|
||||
*/
|
||||
|
||||
int
|
||||
getwm(p)
|
||||
caddr_t p;
|
||||
{
|
||||
union {
|
||||
char buf[INTSIZE];
|
||||
int i;
|
||||
} u;
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < INTSIZE; i++)
|
||||
u.buf[i] = *p++;
|
||||
|
||||
i = u.i;
|
||||
|
||||
if (i > MAXPATHLEN || i < -(MAXPATHLEN)) {
|
||||
i = ntohl(i);
|
||||
if (i > MAXPATHLEN || i < -(MAXPATHLEN))
|
||||
errx(1, "integer out of +-MAXPATHLEN (%d): %d",
|
||||
MAXPATHLEN, abs(i) < abs(htonl(i)) ? i : htonl(i));
|
||||
}
|
||||
return(i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read integer from stream.
|
||||
*
|
||||
* Convert network byte order to host byte order if neccessary.
|
||||
* So we can read on FreeBSD/i386 (little endian) a locate database
|
||||
* which was built on SunOS/sparc (big endian).
|
||||
*/
|
||||
|
||||
int
|
||||
getwf(fp)
|
||||
FILE *fp;
|
||||
{
|
||||
register int word;
|
||||
|
||||
word = getw(fp);
|
||||
|
||||
if (word > MAXPATHLEN || word < -(MAXPATHLEN)) {
|
||||
word = ntohl(word);
|
||||
if (word > MAXPATHLEN || word < -(MAXPATHLEN))
|
||||
errx(1, "integer out of +-MAXPATHLEN (%d): %d",
|
||||
MAXPATHLEN, abs(word) < abs(htonl(word)) ? word :
|
||||
htonl(word));
|
||||
}
|
||||
return(word);
|
||||
}
|
78
logname/logname.1
Normal file
78
logname/logname.1
Normal file
@ -0,0 +1,78 @@
|
||||
.\" $NetBSD: logname.1,v 1.8 1997/10/19 04:20:06 lukem Exp $
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)logname.1 8.1 (Berkeley) 6/9/93
|
||||
.\"
|
||||
.Dd June 9, 1993
|
||||
.Dt LOGNAME 1
|
||||
.Os BSD 4.4
|
||||
.Sh NAME
|
||||
.Nm logname
|
||||
.Nd display user's login name
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility writes the user's login name to standard output followed by
|
||||
a newline.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility explicitly ignores the
|
||||
.Ev LOGNAME
|
||||
and
|
||||
.Ev USER
|
||||
environment variables
|
||||
because the environment cannot be trusted.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility exits 0 on success, and >0 if an error occurs.
|
||||
.Sh SEE ALSO
|
||||
.Xr who 1 ,
|
||||
.Xr whoami 1 ,
|
||||
.Xr getlogin 2
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility conforms to
|
||||
.St -p1003.2-92 .
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.4 .
|
92
logname/logname.c
Normal file
92
logname/logname.c
Normal file
@ -0,0 +1,92 @@
|
||||
/* $NetBSD: logname.c,v 1.7 1997/10/19 04:20:06 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1991, 1993, 1994\n\
|
||||
The Regents of the University of California. All rights reserved.\n");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)logname.c 8.2 (Berkeley) 4/3/94";
|
||||
#endif
|
||||
__RCSID("$NetBSD: logname.c,v 1.7 1997/10/19 04:20:06 lukem Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
|
||||
int main __P((int, char **));
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int ch;
|
||||
char *p;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != -1)
|
||||
switch (ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
if (argc != optind) {
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
if ((p = getlogin()) == NULL)
|
||||
err(1, "getlogin");
|
||||
(void)printf("%s\n", p);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: logname\n");
|
||||
exit(1);
|
||||
}
|
212
mktemp/mktemp.1
Normal file
212
mktemp/mktemp.1
Normal file
@ -0,0 +1,212 @@
|
||||
.\" 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.
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" From: $OpenBSD: mktemp.1,v 1.8 1998/03/19 06:13:37 millert Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 30, 2005
|
||||
.Dt MKTEMP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mktemp
|
||||
.Nd make temporary file name (unique)
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl d
|
||||
.Op Fl q
|
||||
.Op Fl t Ar prefix
|
||||
.Op Fl u
|
||||
.Ar template ...
|
||||
.Nm
|
||||
.Op Fl d
|
||||
.Op Fl q
|
||||
.Op Fl u
|
||||
.Fl t Ar prefix
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility takes each of the given file name templates and overwrites a
|
||||
portion of it to create a file name.
|
||||
This file name is unique
|
||||
and suitable for use by the application.
|
||||
The template may be
|
||||
any file name with some number of
|
||||
.Ql X Ns s
|
||||
appended
|
||||
to it, for example
|
||||
.Pa /tmp/temp.XXXX .
|
||||
The trailing
|
||||
.Ql X Ns s
|
||||
are replaced with the current process number and/or a
|
||||
unique letter combination.
|
||||
The number of unique file names
|
||||
.Nm
|
||||
can return depends on the number of
|
||||
.Ql X Ns s
|
||||
provided; six
|
||||
.Ql X Ns s
|
||||
will
|
||||
result in
|
||||
.Nm
|
||||
selecting 1 of 56800235584 (62 ** 6) possible file names.
|
||||
On case-insensitive file systems, the effective number of unique
|
||||
names is significantly less; given six
|
||||
.Ql X Ns s ,
|
||||
.Nm
|
||||
will instead select 1 of 2176782336 (36 ** 6) possible unique file names.
|
||||
.Pp
|
||||
If
|
||||
.Nm
|
||||
can successfully generate a unique file name, the file
|
||||
is created with mode 0600 (unless the
|
||||
.Fl u
|
||||
flag is given) and the filename is printed
|
||||
to standard output.
|
||||
.Pp
|
||||
If the
|
||||
.Fl t Ar prefix
|
||||
option is given,
|
||||
.Nm
|
||||
will generate a template string based on the
|
||||
.Ar prefix
|
||||
and the
|
||||
.Ev TMPDIR
|
||||
environment variable if set.
|
||||
The default location if
|
||||
.Ev TMPDIR
|
||||
is not set is
|
||||
.Pa /tmp .
|
||||
Care should
|
||||
be taken to ensure that it is appropriate to use an environment variable
|
||||
potentially supplied by the user.
|
||||
.Pp
|
||||
If no arguments are passed or if only the
|
||||
.Fl d
|
||||
flag is passed
|
||||
.Nm
|
||||
behaves as if
|
||||
.Fl t Li tmp
|
||||
was supplied.
|
||||
.Pp
|
||||
Any number of temporary files may be created in a single invocation,
|
||||
including one based on the internal template resulting from the
|
||||
.Fl t
|
||||
flag.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility is provided to allow shell scripts to safely use temporary files.
|
||||
Traditionally, many shell scripts take the name of the program with
|
||||
the pid as a suffix and use that as a temporary file name.
|
||||
This
|
||||
kind of naming scheme is predictable and the race condition it creates
|
||||
is easy for an attacker to win.
|
||||
A safer, though still inferior, approach
|
||||
is to make a temporary directory using the same naming scheme.
|
||||
While
|
||||
this does allow one to guarantee that a temporary file will not be
|
||||
subverted, it still allows a simple denial of service attack.
|
||||
For these
|
||||
reasons it is suggested that
|
||||
.Nm
|
||||
be used instead.
|
||||
.Sh OPTIONS
|
||||
The available options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl d
|
||||
Make a directory instead of a file.
|
||||
.It Fl q
|
||||
Fail silently if an error occurs.
|
||||
This is useful if
|
||||
a script does not want error output to go to standard error.
|
||||
.It Fl t Ar prefix
|
||||
Generate a template (using the supplied
|
||||
.Ar prefix
|
||||
and
|
||||
.Ev TMPDIR
|
||||
if set) to create a filename template.
|
||||
.It Fl u
|
||||
Operate in
|
||||
.Dq unsafe
|
||||
mode.
|
||||
The temp file will be unlinked before
|
||||
.Nm
|
||||
exits.
|
||||
This is slightly better than
|
||||
.Xr mktemp 3
|
||||
but still introduces a race condition.
|
||||
Use of this
|
||||
option is not encouraged.
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh EXAMPLES
|
||||
The following
|
||||
.Xr sh 1
|
||||
fragment illustrates a simple use of
|
||||
.Nm
|
||||
where the script should quit if it cannot get a safe
|
||||
temporary file.
|
||||
.Bd -literal -offset indent
|
||||
tempfoo=`basename $0`
|
||||
TMPFILE=`mktemp /tmp/${tempfoo}.XXXXXX` || exit 1
|
||||
echo "program output" >> $TMPFILE
|
||||
.Ed
|
||||
.Pp
|
||||
To allow the use of $TMPDIR:
|
||||
.Bd -literal -offset indent
|
||||
tempfoo=`basename $0`
|
||||
TMPFILE=`mktemp -t ${tempfoo}` || exit 1
|
||||
echo "program output" >> $TMPFILE
|
||||
.Ed
|
||||
.Pp
|
||||
In this case, we want the script to catch the error itself.
|
||||
.Bd -literal -offset indent
|
||||
tempfoo=`basename $0`
|
||||
TMPFILE=`mktemp -q /tmp/${tempfoo}.XXXXXX`
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "$0: Can't create temp file, exiting..."
|
||||
exit 1
|
||||
fi
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr mkdtemp 3 ,
|
||||
.Xr mkstemp 3 ,
|
||||
.Xr mktemp 3 ,
|
||||
.Xr environ 7
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
utility appeared in
|
||||
.Ox 2.1 .
|
||||
This implementation was written independently based on the
|
||||
.Ox
|
||||
man page, and
|
||||
first appeared in
|
||||
.Fx 2.2.7 .
|
||||
This man page is taken from
|
||||
.Ox .
|
182
mktemp/mktemp.c
Normal file
182
mktemp/mktemp.c
Normal file
@ -0,0 +1,182 @@
|
||||
/*-
|
||||
* Copyright (c) 1994, 1995, 1996, 1998 Peter Wemm <peter@netplex.com.au>
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program was originally written long ago, originally for a non
|
||||
* BSD-like OS without mkstemp(). It's been modified over the years
|
||||
* to use mkstemp() rather than the original O_CREAT|O_EXCL/fstat/lstat
|
||||
* etc style hacks.
|
||||
* A cleanup, misc options and mkdtemp() calls were added to try and work
|
||||
* more like the OpenBSD version - which was first to publish the interface.
|
||||
*/
|
||||
|
||||
#include <err.h>
|
||||
#ifdef __APPLE__
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#include <paths.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif /* not lint */
|
||||
|
||||
static void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int c, fd, ret;
|
||||
char *tmpdir;
|
||||
const char *prefix;
|
||||
char *name;
|
||||
int dflag, qflag, tflag, uflag;
|
||||
#ifdef __APPLE__
|
||||
char tmpbuf[PATH_MAX];
|
||||
size_t len;
|
||||
#endif
|
||||
|
||||
ret = dflag = qflag = tflag = uflag = 0;
|
||||
prefix = "mktemp";
|
||||
name = NULL;
|
||||
|
||||
while ((c = getopt(argc, argv, "dqt:u")) != -1)
|
||||
switch (c) {
|
||||
case 'd':
|
||||
dflag++;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
qflag++;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
prefix = optarg;
|
||||
tflag++;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
uflag++;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (!tflag && argc < 1) {
|
||||
tflag = 1;
|
||||
prefix = "tmp";
|
||||
}
|
||||
|
||||
if (tflag) {
|
||||
#ifdef __APPLE__
|
||||
if (confstr(_CS_DARWIN_USER_TEMP_DIR, tmpbuf, sizeof(tmpbuf)) > 0) {
|
||||
tmpdir = tmpbuf;
|
||||
} else {
|
||||
tmpdir = getenv("TMPDIR");
|
||||
}
|
||||
|
||||
if (tmpdir == NULL) {
|
||||
tmpdir = _PATH_TMP;
|
||||
}
|
||||
|
||||
len = strlen(tmpdir);
|
||||
if (len > 0 && tmpdir[len - 1] == '/') {
|
||||
asprintf(&name, "%s%s.XXXXXXXX", tmpdir, prefix);
|
||||
} else {
|
||||
asprintf(&name, "%s/%s.XXXXXXXX", tmpdir, prefix);
|
||||
}
|
||||
#else
|
||||
tmpdir = getenv("TMPDIR");
|
||||
if (tmpdir == NULL)
|
||||
asprintf(&name, "%s%s.XXXXXXXX", _PATH_TMP, prefix);
|
||||
else
|
||||
asprintf(&name, "%s/%s.XXXXXXXX", tmpdir, prefix);
|
||||
#endif
|
||||
/* if this fails, the program is in big trouble already */
|
||||
if (name == NULL) {
|
||||
if (qflag)
|
||||
return (1);
|
||||
else
|
||||
errx(1, "cannot generate template");
|
||||
}
|
||||
}
|
||||
|
||||
/* generate all requested files */
|
||||
while (name != NULL || argc > 0) {
|
||||
if (name == NULL) {
|
||||
name = strdup(argv[0]);
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
if (dflag) {
|
||||
if (mkdtemp(name) == NULL) {
|
||||
ret = 1;
|
||||
if (!qflag)
|
||||
warn("mkdtemp failed on %s", name);
|
||||
} else {
|
||||
printf("%s\n", name);
|
||||
if (uflag)
|
||||
rmdir(name);
|
||||
}
|
||||
} else {
|
||||
fd = mkstemp(name);
|
||||
if (fd < 0) {
|
||||
ret = 1;
|
||||
if (!qflag)
|
||||
warn("mkstemp failed on %s", name);
|
||||
} else {
|
||||
close(fd);
|
||||
if (uflag)
|
||||
unlink(name);
|
||||
printf("%s\n", name);
|
||||
}
|
||||
}
|
||||
if (name)
|
||||
free(name);
|
||||
name = NULL;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: mktemp [-d] [-q] [-t prefix] [-u] template ...\n");
|
||||
fprintf(stderr,
|
||||
" mktemp [-d] [-q] [-u] -t prefix \n");
|
||||
exit (1);
|
||||
}
|
20
mktemp/mktemp.plist.part
Normal file
20
mktemp/mktemp.plist.part
Normal file
@ -0,0 +1,20 @@
|
||||
<dict>
|
||||
<key>OpenSourceProject</key>
|
||||
<string>mktemp</string>
|
||||
<key>OpenSourceVersion</key>
|
||||
<string>2012-11-18</string>
|
||||
<key>OpenSourceWebsiteURL</key>
|
||||
<string>http://svnweb.freebsd.org/base/head/usr.bin/mktemp/</string>
|
||||
<key>OpenSourceSCM</key>
|
||||
<string>svn co http://svn.freebsd.org/base/head/usr.bin/mktemp/</string>
|
||||
<key>OpenSourceImportDate</key>
|
||||
<string>2014-08-11</string>
|
||||
<key>OpenSourceModifications</key>
|
||||
<array>
|
||||
<string>Avoid double-slash in output. (5334050)</string>
|
||||
<string>Document case-insensitive file system behavior. (14280248)</string>
|
||||
<string>Prefer _CS_DARWIN_USER_TEMP_DIR over TMPDIR and _PATH_TMP. (14338140)</string>
|
||||
</array>
|
||||
<key>OpenSourceLicense</key>
|
||||
<string>bsd</string>
|
||||
</dict>
|
120
nice/nice.1
Normal file
120
nice/nice.1
Normal file
@ -0,0 +1,120 @@
|
||||
.\" $NetBSD: nice.1,v 1.8 1997/10/19 06:28:02 lukem Exp $
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)nice.1 8.1 (Berkeley) 6/6/93
|
||||
.\"
|
||||
.Dd June 6, 1993
|
||||
.Dt NICE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm nice
|
||||
.Nd execute a utility with an altered scheduling priority
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl n Ar increment
|
||||
.Ar utility
|
||||
.Op Ar argument ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
runs
|
||||
.Ar utility
|
||||
at an altered scheduling priority.
|
||||
If an
|
||||
.Ar increment
|
||||
is given, it is used; otherwise
|
||||
an increment of 10 is assumed.
|
||||
The super-user can run utilities with priorities higher than normal by using
|
||||
a negative
|
||||
.Ar increment .
|
||||
The priority can be adjusted over a
|
||||
range of -20 (the highest) to 20 (the lowest).
|
||||
.Pp
|
||||
Available options:
|
||||
.Bl -tag -width indent
|
||||
.It Fl n Ar increment
|
||||
A positive or negative decimal integer used to modify the system scheduling
|
||||
priority of
|
||||
.Ar utility.
|
||||
.El
|
||||
.Sh DIAGNOSTICS
|
||||
The
|
||||
.Nm
|
||||
utility shall exit with one of the following values:
|
||||
.Bl -tag -width indent
|
||||
.It 1-125
|
||||
An error occurred in the
|
||||
.Nm
|
||||
utility.
|
||||
.It 126
|
||||
The
|
||||
.Ar utility
|
||||
was found but could not be invoked.
|
||||
.It 127
|
||||
The
|
||||
.Ar utility
|
||||
could not be found.
|
||||
.El
|
||||
.Pp
|
||||
Otherwise, the exit status of
|
||||
.Nm
|
||||
shall be that of
|
||||
.Ar utility .
|
||||
.Sh COMPATIBILITY
|
||||
The historic
|
||||
.Fl Ns Ar increment
|
||||
option has been deprecated but is still supported in this implementation.
|
||||
.Sh SEE ALSO
|
||||
.Xr csh 1 ,
|
||||
.Xr getpriority 2 ,
|
||||
.Xr setpriority 2 ,
|
||||
.Xr renice 8
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility conforms to
|
||||
.St -p1003.2-92 .
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v6 .
|
||||
.Sh BUGS
|
||||
.Nm
|
||||
is built into
|
||||
.Xr csh 1
|
||||
with a slightly different syntax than described here. The form
|
||||
.Ql nice +10
|
||||
nices to positive nice, and
|
||||
.Ql nice \-10
|
||||
can be used
|
||||
by the super-user to give a process more of the processor.
|
122
nice/nice.c
Normal file
122
nice/nice.c
Normal file
@ -0,0 +1,122 @@
|
||||
/* $NetBSD: nice.c,v 1.10 1997/10/19 06:28:04 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT(
|
||||
"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
|
||||
All rights reserved.\n");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)nice.c 5.4 (Berkeley) 6/1/90";
|
||||
#endif
|
||||
__RCSID("$NetBSD: nice.c,v 1.10 1997/10/19 06:28:04 lukem Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define DEFNICE 10
|
||||
|
||||
int main __P((int, char **));
|
||||
static void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int niceness = DEFNICE;
|
||||
int c;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
/* handle obsolete -number syntax */
|
||||
if (argc > 1 && argv[1][0] == '-' && isdigit(argv[1][1])) {
|
||||
niceness = atoi (argv[1] + 1);
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
while ((c = getopt (argc, argv, "n:")) != -1) {
|
||||
switch (c) {
|
||||
case 'n':
|
||||
niceness = atoi (optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind; argv += optind;
|
||||
|
||||
if (argc == 0)
|
||||
usage();
|
||||
|
||||
errno = 0;
|
||||
niceness += getpriority(PRIO_PROCESS, 0);
|
||||
if (errno) {
|
||||
err (1, "getpriority");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
if (setpriority(PRIO_PROCESS, 0, niceness)) {
|
||||
warn ("setpriority");
|
||||
}
|
||||
|
||||
execvp(argv[0], &argv[0]);
|
||||
err ((errno == ENOENT) ? 127 : 126, "%s", argv[0]);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: nice [ -n increment ] utility [ argument ...]\n");
|
||||
|
||||
exit(1);
|
||||
}
|
124
nohup/nohup.1
Normal file
124
nohup/nohup.1
Normal file
@ -0,0 +1,124 @@
|
||||
.\" Copyright (c) 1989, 1990, 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.
|
||||
.\"
|
||||
.\" @(#)nohup.1 8.1 (Berkeley) 6/6/93
|
||||
.\" $FreeBSD: src/usr.bin/nohup/nohup.1,v 1.13 2005/01/17 07:44:27 ru Exp $
|
||||
.\"
|
||||
.Dd July 19, 2001
|
||||
.Dt NOHUP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm nohup
|
||||
.Nd invoke a utility immune to hangups
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl Fl
|
||||
.Ar utility
|
||||
.Op Ar arguments
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility invokes
|
||||
.Ar utility
|
||||
with its
|
||||
.Ar arguments
|
||||
and at this time sets the signal
|
||||
.Dv SIGHUP
|
||||
to be ignored.
|
||||
If the standard output is a terminal, the standard output is
|
||||
appended to the file
|
||||
.Pa nohup.out
|
||||
in the current directory.
|
||||
If standard error is a terminal, it is directed to the same place
|
||||
as the standard output.
|
||||
.Pp
|
||||
Some shells may provide a builtin
|
||||
.Nm
|
||||
command which is similar or identical to this utility.
|
||||
Consult the
|
||||
.Xr builtin 1
|
||||
manual page.
|
||||
.Sh ENVIRONMENT
|
||||
The following variables are utilized by
|
||||
.Nm :
|
||||
.Bl -tag -width flag
|
||||
.It Ev HOME
|
||||
If the output file
|
||||
.Pa nohup.out
|
||||
cannot be created in the current directory, the
|
||||
.Nm
|
||||
utility uses the directory named by
|
||||
.Ev HOME
|
||||
to create the file.
|
||||
.It Ev PATH
|
||||
Used to locate the requested
|
||||
.Ar utility
|
||||
if the name contains no
|
||||
.Ql /
|
||||
characters.
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
utility exits with one of the following values:
|
||||
.Bl -tag -width Ds
|
||||
.It 126
|
||||
The
|
||||
.Ar utility
|
||||
was found, but could not be invoked.
|
||||
.It 127
|
||||
The
|
||||
.Ar utility
|
||||
could not be found or an error occurred in
|
||||
.Nm .
|
||||
.El
|
||||
.Pp
|
||||
Otherwise, the exit status of
|
||||
.Nm
|
||||
will be that of
|
||||
.Ar utility .
|
||||
.Sh SEE ALSO
|
||||
.Xr builtin 1 ,
|
||||
.Xr csh 1 ,
|
||||
.Xr signal 3
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility is expected to be
|
||||
.St -p1003.2
|
||||
compatible.
|
||||
.Sh BUGS
|
||||
Two or more instances of
|
||||
.Nm
|
||||
can append to the same file, which makes for a confusing output.
|
149
nohup/nohup.c
Normal file
149
nohup/nohup.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Portions copyright (c) 2007 Apple Inc. 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. 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.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static const char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)nohup.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef __APPLE__
|
||||
__FBSDID("$FreeBSD: src/usr.bin/nohup/nohup.c,v 1.10 2003/05/03 19:44:46 obrien Exp $");
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
#include <vproc.h>
|
||||
#include <vproc_priv.h>
|
||||
#endif
|
||||
|
||||
static void dofile(void);
|
||||
static void usage(void);
|
||||
|
||||
#define FILENAME "nohup.out"
|
||||
/*
|
||||
* POSIX mandates that we exit with:
|
||||
* 126 - If the utility was found, but failed to execute.
|
||||
* 127 - If any other error occurred.
|
||||
*/
|
||||
#define EXIT_NOEXEC 126
|
||||
#define EXIT_NOTFOUND 127
|
||||
#define EXIT_MISC 127
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int exit_status;
|
||||
|
||||
while (getopt(argc, argv, "") != -1)
|
||||
usage();
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (argc < 1)
|
||||
usage();
|
||||
|
||||
if (isatty(STDOUT_FILENO))
|
||||
dofile();
|
||||
if (isatty(STDERR_FILENO) && dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
|
||||
/* may have just closed stderr */
|
||||
err(EXIT_MISC, "%s", argv[0]);
|
||||
|
||||
(void)signal(SIGHUP, SIG_IGN);
|
||||
|
||||
#if defined(__APPLE__) && !TARGET_OS_EMBEDDED
|
||||
if (_vprocmgr_detach_from_console(0) != NULL)
|
||||
err(EXIT_MISC, "can't detach from console");
|
||||
#endif
|
||||
execvp(*argv, argv);
|
||||
exit_status = (errno == ENOENT) ? EXIT_NOTFOUND : EXIT_NOEXEC;
|
||||
err(exit_status, "%s", argv[0]);
|
||||
}
|
||||
|
||||
static void
|
||||
dofile(void)
|
||||
{
|
||||
int fd;
|
||||
char path[MAXPATHLEN];
|
||||
const char *p;
|
||||
|
||||
/*
|
||||
* POSIX mandates if the standard output is a terminal, the standard
|
||||
* output is appended to nohup.out in the working directory. Failing
|
||||
* that, it will be appended to nohup.out in the directory obtained
|
||||
* from the HOME environment variable. If file creation is required,
|
||||
* the mode_t is set to S_IRUSR | S_IWUSR.
|
||||
*/
|
||||
p = FILENAME;
|
||||
fd = open(p, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
|
||||
if (fd != -1)
|
||||
goto dupit;
|
||||
if ((p = getenv("HOME")) != NULL && *p != '\0' &&
|
||||
(size_t)snprintf(path, sizeof(path), "%s/%s", p, FILENAME) <
|
||||
sizeof(path)) {
|
||||
fd = open(p = path, O_RDWR | O_CREAT | O_APPEND,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (fd != -1)
|
||||
goto dupit;
|
||||
}
|
||||
errx(EXIT_MISC, "can't open a nohup.out file");
|
||||
|
||||
dupit:
|
||||
#ifdef __APPLE__
|
||||
(void)lseek(fd, 0L, SEEK_END);
|
||||
#endif
|
||||
if (dup2(fd, STDOUT_FILENO) == -1)
|
||||
err(EXIT_MISC, NULL);
|
||||
(void)fprintf(stderr, "appending output to %s\n", p);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr, "usage: nohup [--] utility [arguments]\n");
|
||||
exit(EXIT_MISC);
|
||||
}
|
76
path_helper/path_helper.8
Normal file
76
path_helper/path_helper.8
Normal file
@ -0,0 +1,76 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2007 Apple Inc. All rights reserved.
|
||||
.\"
|
||||
.\" @APPLE_LICENSE_HEADER_START@
|
||||
.\"
|
||||
.\" This file contains Original Code and/or Modifications of Original Code
|
||||
.\" as defined in and that are subject to the Apple Public Source License
|
||||
.\" Version 2.0 (the 'License'). You may not use this file except in
|
||||
.\" compliance with the License. Please obtain a copy of the License at
|
||||
.\" http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
.\" file.
|
||||
.\"
|
||||
.\" The Original Code and all software distributed under the License are
|
||||
.\" distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
.\" FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
.\" Please see the License for the specific language governing rights and
|
||||
.\" limitations under the License.
|
||||
.\"
|
||||
.\" @APPLE_LICENSE_HEADER_END@
|
||||
.\"
|
||||
.Dd March 15, 2007
|
||||
.Dt path_helper 8
|
||||
.Os "Mac OS X"
|
||||
.Sh NAME
|
||||
.Nm path_helper
|
||||
.Nd helper for constructing PATH environment variable
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl c | Fl s
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility reads the contents of the files in the directories
|
||||
.Pa /etc/paths.d
|
||||
and
|
||||
.Pa /etc/manpaths.d
|
||||
and appends their contents to the
|
||||
.Ev PATH
|
||||
and
|
||||
.Ev MANPATH
|
||||
environment variables respectively.
|
||||
(The
|
||||
.Ev MANPATH
|
||||
environment variable will not be modified unless it is already set
|
||||
in the environment.)
|
||||
.Pp
|
||||
Files in these directories should contain one path element per line.
|
||||
.Pp
|
||||
Prior to reading these directories, default
|
||||
.Ev PATH
|
||||
and
|
||||
.Ev MANPATH
|
||||
values are obtained from the files
|
||||
.Pa /etc/paths
|
||||
and
|
||||
.Pa /etc/manpaths
|
||||
respectively.
|
||||
.Pp
|
||||
Options:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl c
|
||||
Generate C-shell commands on stdout. This is the default if
|
||||
.Ev SHELL
|
||||
ends with "csh".
|
||||
.It Fl s
|
||||
Generate Bourne shell commands on stdout. This is the default if
|
||||
.Ev SHELL
|
||||
does not end with "csh".
|
||||
.El
|
||||
.Sh NOTE
|
||||
The
|
||||
.Nm
|
||||
utility should not be invoked directly.
|
||||
It is intended only for use by the shell profile.
|
201
path_helper/path_helper.c
Normal file
201
path_helper/path_helper.c
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
#include <fts.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
static void usage() {
|
||||
fprintf(stderr, "usage: path_helper [-c | -s]");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Append path segment if it does not exist. Reallocate
|
||||
// the path buffer as necessary.
|
||||
|
||||
int append_path_segment(char** path, const char* segment) {
|
||||
if (*path == NULL || segment == NULL) return -1;
|
||||
|
||||
size_t pathlen = strlen(*path);
|
||||
size_t seglen = strlen(segment);
|
||||
|
||||
if (seglen == 0) return 0;
|
||||
|
||||
// Does the segment already exist in the path?
|
||||
// (^|:)segment(:|$)
|
||||
char* match = strstr(*path, segment);
|
||||
while (match) {
|
||||
if ((match == *path || match[-1] == ':') &&
|
||||
(match[seglen] == ':' || match[seglen] == 0)) {
|
||||
return 0;
|
||||
}
|
||||
match = strstr(match+1, segment);
|
||||
}
|
||||
|
||||
// size = pathlen + ':' + segment + '\0'
|
||||
size_t size = pathlen + seglen + 2;
|
||||
*path = reallocf(*path, size);
|
||||
if (*path == NULL) return -1;
|
||||
|
||||
if (pathlen > 0) strlcat(*path, ":", size);
|
||||
strlcat(*path, segment, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Convert fgetln output into a sanitized segment
|
||||
// escape quotes, dollars, etc.
|
||||
char* read_segment(const char* line, size_t len) {
|
||||
int escapes = 0;
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
char c = line[i];
|
||||
if (c == '\"' || c == '\'' || c == '$') {
|
||||
++escapes;
|
||||
}
|
||||
}
|
||||
|
||||
size_t size = len + escapes + 1;
|
||||
|
||||
char* segment = calloc(1, size);
|
||||
if (segment == NULL) return NULL;
|
||||
|
||||
for (i = 0, j = 0; i < len; ++i, ++j) {
|
||||
char c = line[i];
|
||||
if (c == '\"' || c == '\'' || c == '$') {
|
||||
segment[j++] = '\\';
|
||||
segment[j] = c;
|
||||
} else if (c == '\n') {
|
||||
segment[j] = 0;
|
||||
break;
|
||||
} else {
|
||||
segment[j] = line[i];
|
||||
}
|
||||
}
|
||||
|
||||
return segment;
|
||||
}
|
||||
|
||||
// Construct a path variable, starting with the contents
|
||||
// of the given environment variable, adding the contents
|
||||
// of the default file and files in the path directory.
|
||||
|
||||
char* construct_path(char* env_var, char* defaults_path, char* dir_path) {
|
||||
FTS* fts;
|
||||
FTSENT* ent;
|
||||
|
||||
char* result = calloc(sizeof(char), 1);
|
||||
|
||||
char* dirpathv[] = { defaults_path, dir_path, NULL };
|
||||
fts = fts_open(dirpathv, FTS_PHYSICAL | FTS_XDEV, NULL);
|
||||
if (!fts) {
|
||||
perror(dir_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((ent = fts_read(fts)) != NULL) {
|
||||
// only interested in regular files, one level deep
|
||||
if (ent->fts_info != FTS_F) {
|
||||
if (ent->fts_level >= 1) fts_set(fts, ent, FTS_SKIP);
|
||||
continue;
|
||||
}
|
||||
|
||||
FILE* f = fopen(ent->fts_accpath, "r");
|
||||
if (f == NULL) {
|
||||
perror(ent->fts_accpath);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
size_t len;
|
||||
char* line = fgetln(f, &len);
|
||||
if (line == NULL) break;
|
||||
char* segment = read_segment(line, len);
|
||||
|
||||
append_path_segment(&result, segment);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
fts_close(fts);
|
||||
|
||||
// merge in any existing custom PATH elemenets
|
||||
char* str = getenv(env_var);
|
||||
if (str) str = strdup(str);
|
||||
while (str) {
|
||||
char* sep = strchr(str, ':');
|
||||
if (sep) *sep = 0;
|
||||
|
||||
append_path_segment(&result, str);
|
||||
if (sep) {
|
||||
str = sep + 1;
|
||||
} else {
|
||||
str = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
enum {
|
||||
STYLE_CSH,
|
||||
STYLE_SH
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int style = STYLE_SH;
|
||||
|
||||
if (argc > 2) usage();
|
||||
|
||||
// default to csh style, if $SHELL ends with "csh".
|
||||
char* shell = getenv("SHELL");
|
||||
if (shell) {
|
||||
char* str = strstr(shell, "csh");
|
||||
if (str) style = STYLE_CSH;
|
||||
}
|
||||
|
||||
if (argc == 2 && strcmp(argv[1], "-c") == 0) style = STYLE_CSH;
|
||||
if (argc == 2 && strcmp(argv[1], "-s") == 0) style = STYLE_SH;
|
||||
|
||||
char* path = construct_path("PATH", "/etc/paths", "/etc/paths.d");
|
||||
char* manpath = NULL;
|
||||
|
||||
// only adjust manpath if already set
|
||||
int do_manpath = (getenv("MANPATH") != NULL);
|
||||
if (do_manpath) {
|
||||
manpath = construct_path("MANPATH", "/etc/manpaths", "/etc/manpaths.d");
|
||||
}
|
||||
|
||||
if (style == STYLE_CSH) {
|
||||
printf("setenv PATH \"%s\";\n", path);
|
||||
if (do_manpath) printf("setenv MANPATH \"%s\";\n", manpath);
|
||||
} else {
|
||||
printf("PATH=\"%s\"; export PATH;\n", path);
|
||||
if (do_manpath) printf("MANPATH=\"%s\"; export MANPATH;\n", manpath);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
84
printenv/printenv.1
Normal file
84
printenv/printenv.1
Normal file
@ -0,0 +1,84 @@
|
||||
.\" Copyright (c) 1980, 1990, 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.
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)printenv.1 8.1 (Berkeley) 6/6/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 12, 2003
|
||||
.Dt PRINTENV 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm printenv
|
||||
.Nd print out the environment
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Ar name
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility prints out the names and values of the variables in the environment,
|
||||
with one name/value pair per line.
|
||||
If
|
||||
.Ar name
|
||||
is specified, only
|
||||
its value is printed.
|
||||
.Pp
|
||||
Some shells may provide a builtin
|
||||
.Nm
|
||||
command which is similar or identical to this utility.
|
||||
Consult the
|
||||
.Xr builtin 1
|
||||
manual page.
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh SEE ALSO
|
||||
.Xr csh 1 ,
|
||||
.Xr env 1 ,
|
||||
.Xr sh 1 ,
|
||||
.Xr environ 7
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility is provided for compatibility with earlier
|
||||
.Bx
|
||||
and
|
||||
.Fx
|
||||
releases and is not specified by any standards.
|
||||
The functionality of
|
||||
.Nm
|
||||
can be duplicated with the
|
||||
.Xr echo 1
|
||||
and
|
||||
.Xr env 1
|
||||
utilities.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 3.0 .
|
99
printenv/printenv.c
Normal file
99
printenv/printenv.c
Normal file
@ -0,0 +1,99 @@
|
||||
/*-
|
||||
* 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.
|
||||
* 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 const char copyright[] =
|
||||
"@(#) Copyright (c) 1987, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)printenv.c 8.2 (Berkeley) 5/4/95";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void usage(void);
|
||||
extern char **environ;
|
||||
|
||||
/*
|
||||
* printenv
|
||||
*
|
||||
* Bill Joy, UCB
|
||||
* February, 1979
|
||||
*/
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char *cp, **ep;
|
||||
size_t len;
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != -1)
|
||||
switch(ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0) {
|
||||
for (ep = environ; *ep; ep++)
|
||||
(void)printf("%s\n", *ep);
|
||||
exit(0);
|
||||
}
|
||||
len = strlen(*argv);
|
||||
for (ep = environ; *ep; ep++)
|
||||
if (!memcmp(*ep, *argv, len)) {
|
||||
cp = *ep + len;
|
||||
if (!*cp || *cp == '=') {
|
||||
(void)printf("%s\n", *cp ? cp + 1 : cp);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr, "usage: printenv [name]\n");
|
||||
exit(1);
|
||||
}
|
356
printf/printf.1
Normal file
356
printf/printf.1
Normal file
@ -0,0 +1,356 @@
|
||||
.\" Copyright (c) 1989, 1990, 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.
|
||||
.\"
|
||||
.\" @(#)printf.1 8.1 (Berkeley) 6/6/93
|
||||
.\" $FreeBSD: src/usr.bin/printf/printf.1,v 1.34 2005/06/14 11:50:52 ru Exp $
|
||||
.\"
|
||||
.Dd April 14, 2005
|
||||
.Dt PRINTF 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm printf
|
||||
.Nd formatted output
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Ar format Op Ar arguments ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility formats and prints its arguments, after the first, under control
|
||||
of the
|
||||
.Ar format .
|
||||
The
|
||||
.Ar format
|
||||
is a character string which contains three types of objects: plain characters,
|
||||
which are simply copied to standard output, character escape sequences which
|
||||
are converted and copied to the standard output, and format specifications,
|
||||
each of which causes printing of the next successive
|
||||
.Ar argument .
|
||||
.Pp
|
||||
The
|
||||
.Ar arguments
|
||||
after the first are treated as strings if the corresponding format is
|
||||
either
|
||||
.Cm c , b
|
||||
or
|
||||
.Cm s ;
|
||||
otherwise it is evaluated as a C constant, with the following extensions:
|
||||
.Pp
|
||||
.Bl -bullet -offset indent -compact
|
||||
.It
|
||||
A leading plus or minus sign is allowed.
|
||||
.It
|
||||
If the leading character is a single or double quote, the value is the
|
||||
.Tn ASCII
|
||||
code of the next character.
|
||||
.El
|
||||
.Pp
|
||||
The format string is reused as often as necessary to satisfy the
|
||||
.Ar arguments .
|
||||
Any extra format specifications are evaluated with zero or the null
|
||||
string.
|
||||
.Pp
|
||||
Character escape sequences are in backslash notation as defined in the
|
||||
.St -ansiC ,
|
||||
with extensions.
|
||||
The characters and their meanings
|
||||
are as follows:
|
||||
.Pp
|
||||
.Bl -tag -width Ds -offset indent -compact
|
||||
.It Cm \ea
|
||||
Write a <bell> character.
|
||||
.It Cm \eb
|
||||
Write a <backspace> character.
|
||||
.It Cm \ec
|
||||
Ignore remaining characters in this string.
|
||||
.It Cm \ef
|
||||
Write a <form-feed> character.
|
||||
.It Cm \en
|
||||
Write a <new-line> character.
|
||||
.It Cm \er
|
||||
Write a <carriage return> character.
|
||||
.It Cm \et
|
||||
Write a <tab> character.
|
||||
.It Cm \ev
|
||||
Write a <vertical tab> character.
|
||||
.It Cm \e\'
|
||||
Write a <single quote> character.
|
||||
.It Cm \e\e
|
||||
Write a backslash character.
|
||||
.It Cm \e Ns Ar num
|
||||
.It Cm \e0 Ns Ar num
|
||||
Write an 8-bit character whose
|
||||
.Tn ASCII
|
||||
value is the 1-, 2-, or 3-digit
|
||||
octal number
|
||||
.Ar num .
|
||||
.El
|
||||
.Pp
|
||||
Each format specification is introduced by the percent character
|
||||
(``%'').
|
||||
The remainder of the format specification includes,
|
||||
in the following order:
|
||||
.Bl -tag -width Ds
|
||||
.It "Zero or more of the following flags:"
|
||||
.Bl -tag -width Ds
|
||||
.It Cm #
|
||||
A `#' character
|
||||
specifying that the value should be printed in an ``alternate form''.
|
||||
For
|
||||
.Cm c , d ,
|
||||
and
|
||||
.Cm s ,
|
||||
formats, this option has no effect.
|
||||
For the
|
||||
.Cm o
|
||||
formats the precision of the number is increased to force the first
|
||||
character of the output string to a zero.
|
||||
For the
|
||||
.Cm x
|
||||
.Pq Cm X
|
||||
format, a non-zero result has the string
|
||||
.Li 0x
|
||||
.Pq Li 0X
|
||||
prepended to it.
|
||||
For
|
||||
.Cm e , E , f , g ,
|
||||
and
|
||||
.Cm G ,
|
||||
formats, the result will always contain a decimal point, even if no
|
||||
digits follow the point (normally, a decimal point only appears in the
|
||||
results of those formats if a digit follows the decimal point).
|
||||
For
|
||||
.Cm g
|
||||
and
|
||||
.Cm G
|
||||
formats, trailing zeros are not removed from the result as they
|
||||
would otherwise be;
|
||||
.It Cm \&\-
|
||||
A minus sign `\-' which specifies
|
||||
.Em left adjustment
|
||||
of the output in the indicated field;
|
||||
.It Cm \&+
|
||||
A `+' character specifying that there should always be
|
||||
a sign placed before the number when using signed formats.
|
||||
.It Sq \&\ \&
|
||||
A space specifying that a blank should be left before a positive number
|
||||
for a signed format.
|
||||
A `+' overrides a space if both are used;
|
||||
.It Cm \&0
|
||||
A zero `0' character indicating that zero-padding should be used
|
||||
rather than blank-padding.
|
||||
A `\-' overrides a `0' if both are used;
|
||||
.El
|
||||
.It "Field Width:"
|
||||
An optional digit string specifying a
|
||||
.Em field width ;
|
||||
if the output string has fewer characters than the field width it will
|
||||
be blank-padded on the left (or right, if the left-adjustment indicator
|
||||
has been given) to make up the field width (note that a leading zero
|
||||
is a flag, but an embedded zero is part of a field width);
|
||||
.It Precision:
|
||||
An optional period,
|
||||
.Sq Cm \&.\& ,
|
||||
followed by an optional digit string giving a
|
||||
.Em precision
|
||||
which specifies the number of digits to appear after the decimal point,
|
||||
for
|
||||
.Cm e
|
||||
and
|
||||
.Cm f
|
||||
formats, or the maximum number of characters to be printed
|
||||
from a string; if the digit string is missing, the precision is treated
|
||||
as zero;
|
||||
.It Format:
|
||||
A character which indicates the type of format to use (one of
|
||||
.Cm diouxXfFeEgGaAcsb ) .
|
||||
The uppercase formats differ from their lowercase counterparts only in
|
||||
that the output of the former is entirely in uppercase.
|
||||
The floating-point format specifiers
|
||||
.Pq Cm fFeEgGaA
|
||||
may be prefixed by an
|
||||
.Cm L
|
||||
to request that additional precision be used, if available.
|
||||
.El
|
||||
.Pp
|
||||
A field width or precision may be
|
||||
.Sq Cm \&*
|
||||
instead of a digit string.
|
||||
In this case an
|
||||
.Ar argument
|
||||
supplies the field width or precision.
|
||||
.Pp
|
||||
The format characters and their meanings are:
|
||||
.Bl -tag -width Fl
|
||||
.It Cm diouXx
|
||||
The
|
||||
.Ar argument
|
||||
is printed as a signed decimal (d or i), unsigned octal, unsigned decimal,
|
||||
or unsigned hexadecimal (X or x), respectively.
|
||||
.It Cm fF
|
||||
The
|
||||
.Ar argument
|
||||
is printed in the style `[\-]ddd.ddd' where the number of d's
|
||||
after the decimal point is equal to the precision specification for
|
||||
the argument.
|
||||
If the precision is missing, 6 digits are given; if the precision
|
||||
is explicitly 0, no digits and no decimal point are printed.
|
||||
The values \*[If] and \*[Na] are printed as
|
||||
.Ql inf
|
||||
and
|
||||
.Ql nan ,
|
||||
respectively.
|
||||
.It Cm eE
|
||||
The
|
||||
.Ar argument
|
||||
is printed in the style
|
||||
.Cm e
|
||||
.Sm off
|
||||
.Sq Op - Ar d.ddd No \(+- Ar dd
|
||||
.Sm on
|
||||
where there
|
||||
is one digit before the decimal point and the number after is equal to
|
||||
the precision specification for the argument; when the precision is
|
||||
missing, 6 digits are produced.
|
||||
The values \*[If] and \*[Na] are printed as
|
||||
.Ql inf
|
||||
and
|
||||
.Ql nan ,
|
||||
respectively.
|
||||
.It Cm gG
|
||||
The
|
||||
.Ar argument
|
||||
is printed in style
|
||||
.Cm f
|
||||
.Pq Cm F
|
||||
or in style
|
||||
.Cm e
|
||||
.Pq Cm E
|
||||
whichever gives full precision in minimum space.
|
||||
.It Cm aA
|
||||
The
|
||||
.Ar argument
|
||||
is printed in style
|
||||
.Sm off
|
||||
.Sq Op - Ar h.hhh No \(+- Li p Ar d
|
||||
.Sm on
|
||||
where there is one digit before the hexadecimal point and the number
|
||||
after is equal to the precision specification for the argument;
|
||||
when the precision is missing, enough digits are produced to convey
|
||||
the argument's exact double-precision floating-point representation.
|
||||
The values \*[If] and \*[Na] are printed as
|
||||
.Ql inf
|
||||
and
|
||||
.Ql nan ,
|
||||
respectively.
|
||||
.It Cm c
|
||||
The first character of
|
||||
.Ar argument
|
||||
is printed.
|
||||
.It Cm s
|
||||
Characters from the string
|
||||
.Ar argument
|
||||
are printed until the end is reached or until the number of characters
|
||||
indicated by the precision specification is reached; however if the
|
||||
precision is 0 or missing, all characters in the string are printed.
|
||||
.It Cm b
|
||||
As for
|
||||
.Cm s ,
|
||||
but interpret character escapes in backslash notation in the string
|
||||
.Ar argument .
|
||||
.It Cm \&%
|
||||
Print a `%'; no argument is used.
|
||||
.El
|
||||
.Pp
|
||||
The decimal point
|
||||
character is defined in the program's locale (category
|
||||
.Dv LC_NUMERIC ) .
|
||||
.Pp
|
||||
In no case does a non-existent or small field width cause truncation of
|
||||
a field; padding takes place only if the specified field width exceeds
|
||||
the actual width.
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh COMPATIBILITY
|
||||
The traditional
|
||||
.Bx
|
||||
behavior of converting arguments of numeric formats not beginning
|
||||
with a digit to the
|
||||
.Tn ASCII
|
||||
code of the first character is not supported.
|
||||
.Sh SEE ALSO
|
||||
.Xr echo 1 ,
|
||||
.Xr printf 3
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
command is expected to be mostly compatible with the
|
||||
.St -p1003.2
|
||||
specification.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.3 Reno .
|
||||
It is modeled
|
||||
after the standard library function,
|
||||
.Xr printf 3 .
|
||||
.Sh BUGS
|
||||
Since the floating point numbers are translated from
|
||||
.Tn ASCII
|
||||
to floating-point and
|
||||
then back again, floating-point precision may be lost.
|
||||
(By default, the number is translated to an IEEE-754 double-precision
|
||||
value before being printed.
|
||||
The
|
||||
.Cm L
|
||||
modifier may produce additional precision, depending on the hardware platform.)
|
||||
.Pp
|
||||
.Tn ANSI
|
||||
hexadecimal character constants were deliberately not provided.
|
||||
.Pp
|
||||
The escape sequence \e000 is the string terminator.
|
||||
When present in the argument for the
|
||||
.Cm b
|
||||
format, the argument will be truncated at the \e000 character.
|
||||
.Pp
|
||||
Multibyte characters are not recognized in format strings (this is only
|
||||
a problem if
|
||||
.Ql %
|
||||
can appear inside a multibyte character).
|
||||
.Pp
|
||||
Parsing of - arguments is also somewhat different from
|
||||
.Xr printf 3 ,
|
||||
where unknown arguments are simply printed instead of being
|
||||
flagged as errors.
|
557
printf/printf.c
Normal file
557
printf/printf.c
Normal file
@ -0,0 +1,557 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(BUILTIN) && !defined(SHELL)
|
||||
#ifndef lint
|
||||
static char const copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char const sccsid[] = "@(#)printf.c 8.1 (Berkeley) 7/20/93";
|
||||
#endif
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD: src/usr.bin/printf/printf.c,v 1.37 2005/08/05 08:18:00 stefanf Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef SHELL
|
||||
#define main printfcmd
|
||||
#include "bltin/bltin.h"
|
||||
#include "memalloc.h"
|
||||
#else
|
||||
#define warnx1(a, b, c) warnx(a)
|
||||
#define warnx2(a, b, c) warnx(a, b)
|
||||
#define warnx3(a, b, c) warnx(a, b, c)
|
||||
#endif
|
||||
|
||||
#ifndef BUILTIN
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
#define PF(f, func) do { \
|
||||
char *b = NULL; \
|
||||
if (havewidth) \
|
||||
if (haveprec) \
|
||||
(void)asprintf(&b, f, fieldwidth, precision, func); \
|
||||
else \
|
||||
(void)asprintf(&b, f, fieldwidth, func); \
|
||||
else if (haveprec) \
|
||||
(void)asprintf(&b, f, precision, func); \
|
||||
else \
|
||||
(void)asprintf(&b, f, func); \
|
||||
if (b) { \
|
||||
(void)fputs(b, stdout); \
|
||||
free(b); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int asciicode(void);
|
||||
static char *doformat(char *, int *);
|
||||
static int escape(char *, int, size_t *);
|
||||
static int getchr(void);
|
||||
static int getfloating(long double *, int);
|
||||
static int getint(int *);
|
||||
static int getnum(intmax_t *, uintmax_t *, int);
|
||||
static const char
|
||||
*getstr(void);
|
||||
static char *mknum(char *, int);
|
||||
static void usage(void);
|
||||
|
||||
static char **gargv;
|
||||
|
||||
int
|
||||
#ifdef BUILTIN
|
||||
progprintf(int argc, char *argv[])
|
||||
#else
|
||||
main(int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
size_t len;
|
||||
int ch, chopped, end, rval;
|
||||
char *format, *fmt, *start;
|
||||
|
||||
#ifndef BUILTIN
|
||||
(void) setlocale(LC_NUMERIC, "");
|
||||
#endif
|
||||
while ((ch = getopt(argc, argv, "")) != -1)
|
||||
switch (ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1) {
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic algorithm is to scan the format string for conversion
|
||||
* specifications -- once one is found, find out if the field
|
||||
* width or precision is a '*'; if it is, gather up value. Note,
|
||||
* format strings are reused as necessary to use up the provided
|
||||
* arguments, arguments of zero/null string are provided to use
|
||||
* up the format string.
|
||||
*/
|
||||
fmt = format = *argv;
|
||||
chopped = escape(fmt, 1, &len); /* backslash interpretation */
|
||||
rval = end = 0;
|
||||
gargv = ++argv;
|
||||
for (;;) {
|
||||
start = fmt;
|
||||
while (fmt < format + len) {
|
||||
if (fmt[0] == '%') {
|
||||
fwrite(start, 1, fmt - start, stdout);
|
||||
if (fmt[1] == '%') {
|
||||
/* %% prints a % */
|
||||
putchar('%');
|
||||
fmt += 2;
|
||||
} else {
|
||||
fmt = doformat(fmt, &rval);
|
||||
if (fmt == NULL)
|
||||
return (1);
|
||||
end = 0;
|
||||
}
|
||||
start = fmt;
|
||||
} else
|
||||
fmt++;
|
||||
}
|
||||
|
||||
if (end == 1) {
|
||||
warnx1("missing format character", NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
fwrite(start, 1, fmt - start, stdout);
|
||||
if (chopped || !*gargv)
|
||||
return (rval);
|
||||
/* Restart at the beginning of the format string. */
|
||||
fmt = format;
|
||||
end = 1;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
doformat(char *start, int *rval)
|
||||
{
|
||||
static const char skip1[] = "#'-+ 0";
|
||||
static const char skip2[] = "0123456789";
|
||||
char *fmt;
|
||||
int fieldwidth, haveprec, havewidth, mod_ldbl, precision;
|
||||
char convch, nextch;
|
||||
|
||||
fmt = start + 1;
|
||||
/* skip to field width */
|
||||
fmt += strspn(fmt, skip1);
|
||||
if (*fmt == '*') {
|
||||
if (getint(&fieldwidth))
|
||||
return (NULL);
|
||||
havewidth = 1;
|
||||
++fmt;
|
||||
} else {
|
||||
havewidth = 0;
|
||||
|
||||
/* skip to possible '.', get following precision */
|
||||
fmt += strspn(fmt, skip2);
|
||||
}
|
||||
if (*fmt == '.') {
|
||||
/* precision present? */
|
||||
++fmt;
|
||||
if (*fmt == '*') {
|
||||
if (getint(&precision))
|
||||
return (NULL);
|
||||
haveprec = 1;
|
||||
++fmt;
|
||||
} else {
|
||||
haveprec = 0;
|
||||
|
||||
/* skip to conversion char */
|
||||
fmt += strspn(fmt, skip2);
|
||||
}
|
||||
} else
|
||||
haveprec = 0;
|
||||
if (!*fmt) {
|
||||
warnx1("missing format character", NULL, NULL);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for a length modifier. POSIX doesn't have these, so
|
||||
* we only support them for floating-point conversions, which
|
||||
* are extensions. This is useful because the L modifier can
|
||||
* be used to gain extra range and precision, while omitting
|
||||
* it is more likely to produce consistent results on different
|
||||
* architectures. This is not so important for integers
|
||||
* because overflow is the only bad thing that can happen to
|
||||
* them, but consider the command printf %a 1.1
|
||||
*/
|
||||
if (*fmt == 'L') {
|
||||
mod_ldbl = 1;
|
||||
fmt++;
|
||||
if (!strchr("aAeEfFgG", *fmt)) {
|
||||
warnx2("bad modifier L for %%%c", *fmt, NULL);
|
||||
return (NULL);
|
||||
}
|
||||
} else {
|
||||
mod_ldbl = 0;
|
||||
}
|
||||
|
||||
convch = *fmt;
|
||||
nextch = *++fmt;
|
||||
*fmt = '\0';
|
||||
switch (convch) {
|
||||
case 'b': {
|
||||
size_t len;
|
||||
char *p;
|
||||
int getout;
|
||||
|
||||
#ifdef SHELL
|
||||
p = savestr(getstr());
|
||||
#else
|
||||
p = strdup(getstr());
|
||||
#endif
|
||||
if (p == NULL) {
|
||||
warnx2("%s", strerror(ENOMEM), NULL);
|
||||
return (NULL);
|
||||
}
|
||||
getout = escape(p, 0, &len);
|
||||
*(fmt - 1) = 's';
|
||||
PF(start, p);
|
||||
*(fmt - 1) = 'b';
|
||||
#ifdef SHELL
|
||||
ckfree(p);
|
||||
#else
|
||||
free(p);
|
||||
#endif
|
||||
if (getout)
|
||||
return (fmt);
|
||||
break;
|
||||
}
|
||||
case 'c': {
|
||||
char p;
|
||||
|
||||
p = getchr();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
const char *p;
|
||||
|
||||
p = getstr();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': {
|
||||
char *f;
|
||||
intmax_t val;
|
||||
uintmax_t uval;
|
||||
int signedconv;
|
||||
|
||||
signedconv = (convch == 'd' || convch == 'i');
|
||||
if ((f = mknum(start, convch)) == NULL)
|
||||
return (NULL);
|
||||
if (getnum(&val, &uval, signedconv))
|
||||
*rval = 1;
|
||||
if (signedconv)
|
||||
PF(f, val);
|
||||
else
|
||||
PF(f, uval);
|
||||
break;
|
||||
}
|
||||
case 'e': case 'E':
|
||||
case 'f': case 'F':
|
||||
case 'g': case 'G':
|
||||
case 'a': case 'A': {
|
||||
long double p;
|
||||
|
||||
if (getfloating(&p, mod_ldbl))
|
||||
*rval = 1;
|
||||
if (mod_ldbl)
|
||||
PF(start, p);
|
||||
else
|
||||
PF(start, (double)p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
warnx2("illegal format character %c", convch, NULL);
|
||||
return (NULL);
|
||||
}
|
||||
*fmt = nextch;
|
||||
return (fmt);
|
||||
}
|
||||
|
||||
static char *
|
||||
mknum(char *str, int ch)
|
||||
{
|
||||
static char *copy;
|
||||
static size_t copy_size;
|
||||
char *newcopy;
|
||||
size_t len, newlen;
|
||||
|
||||
len = strlen(str) + 2;
|
||||
if (len > copy_size) {
|
||||
newlen = ((len + 1023) >> 10) << 10;
|
||||
#ifdef SHELL
|
||||
if ((newcopy = ckrealloc(copy, newlen)) == NULL)
|
||||
#else
|
||||
if ((newcopy = realloc(copy, newlen)) == NULL)
|
||||
#endif
|
||||
{
|
||||
warnx2("%s", strerror(ENOMEM), NULL);
|
||||
return (NULL);
|
||||
}
|
||||
copy = newcopy;
|
||||
copy_size = newlen;
|
||||
}
|
||||
|
||||
memmove(copy, str, len - 3);
|
||||
copy[len - 3] = 'j';
|
||||
copy[len - 2] = ch;
|
||||
copy[len - 1] = '\0';
|
||||
return (copy);
|
||||
}
|
||||
|
||||
static int
|
||||
escape(char *fmt, int percent, size_t *len)
|
||||
{
|
||||
char *save, *store;
|
||||
int value, c;
|
||||
|
||||
for (save = store = fmt; (c = *fmt); ++fmt, ++store) {
|
||||
if (c != '\\') {
|
||||
*store = c;
|
||||
continue;
|
||||
}
|
||||
switch (*++fmt) {
|
||||
case '\0': /* EOS, user error */
|
||||
*store = '\\';
|
||||
*++store = '\0';
|
||||
*len = store - save;
|
||||
return (0);
|
||||
case '\\': /* backslash */
|
||||
case '\'': /* single quote */
|
||||
*store = *fmt;
|
||||
break;
|
||||
case 'a': /* bell/alert */
|
||||
*store = '\a';
|
||||
break;
|
||||
case 'b': /* backspace */
|
||||
*store = '\b';
|
||||
break;
|
||||
case 'c':
|
||||
*store = '\0';
|
||||
*len = store - save;
|
||||
return (1);
|
||||
case 'f': /* form-feed */
|
||||
*store = '\f';
|
||||
break;
|
||||
case 'n': /* newline */
|
||||
*store = '\n';
|
||||
break;
|
||||
case 'r': /* carriage-return */
|
||||
*store = '\r';
|
||||
break;
|
||||
case 't': /* horizontal tab */
|
||||
*store = '\t';
|
||||
break;
|
||||
case 'v': /* vertical tab */
|
||||
*store = '\v';
|
||||
break;
|
||||
/* octal constant */
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
for (c = *fmt == '0' ? 4 : 3, value = 0;
|
||||
c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) {
|
||||
value <<= 3;
|
||||
value += *fmt - '0';
|
||||
}
|
||||
--fmt;
|
||||
if (percent && value == '%') {
|
||||
*store++ = '%';
|
||||
*store = '%';
|
||||
} else
|
||||
*store = value;
|
||||
break;
|
||||
default:
|
||||
*store = *fmt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*store = '\0';
|
||||
*len = store - save;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
getchr(void)
|
||||
{
|
||||
if (!*gargv)
|
||||
return ('\0');
|
||||
return ((int)**gargv++);
|
||||
}
|
||||
|
||||
static const char *
|
||||
getstr(void)
|
||||
{
|
||||
if (!*gargv)
|
||||
return ("");
|
||||
return (*gargv++);
|
||||
}
|
||||
|
||||
static int
|
||||
getint(int *ip)
|
||||
{
|
||||
intmax_t val;
|
||||
uintmax_t uval;
|
||||
int rval;
|
||||
|
||||
if (getnum(&val, &uval, 1))
|
||||
return (1);
|
||||
rval = 0;
|
||||
if (val < INT_MIN || val > INT_MAX) {
|
||||
warnx3("%s: %s", *gargv, strerror(ERANGE));
|
||||
rval = 1;
|
||||
}
|
||||
*ip = (int)val;
|
||||
return (rval);
|
||||
}
|
||||
|
||||
static int
|
||||
getnum(intmax_t *ip, uintmax_t *uip, int signedconv)
|
||||
{
|
||||
char *ep;
|
||||
int rval;
|
||||
|
||||
if (!*gargv) {
|
||||
*ip = 0;
|
||||
return (0);
|
||||
}
|
||||
if (**gargv == '"' || **gargv == '\'') {
|
||||
if (signedconv)
|
||||
*ip = asciicode();
|
||||
else
|
||||
*uip = asciicode();
|
||||
return (0);
|
||||
}
|
||||
rval = 0;
|
||||
errno = 0;
|
||||
if (signedconv)
|
||||
*ip = strtoimax(*gargv, &ep, 0);
|
||||
else
|
||||
*uip = strtoumax(*gargv, &ep, 0);
|
||||
if (ep == *gargv) {
|
||||
warnx2("%s: expected numeric value", *gargv, NULL);
|
||||
rval = 1;
|
||||
}
|
||||
else if (*ep != '\0') {
|
||||
warnx2("%s: not completely converted", *gargv, NULL);
|
||||
rval = 1;
|
||||
}
|
||||
if (errno == ERANGE) {
|
||||
warnx3("%s: %s", *gargv, strerror(ERANGE));
|
||||
rval = 1;
|
||||
}
|
||||
++gargv;
|
||||
return (rval);
|
||||
}
|
||||
|
||||
static int
|
||||
getfloating(long double *dp, int mod_ldbl)
|
||||
{
|
||||
char *ep;
|
||||
int rval;
|
||||
|
||||
if (!*gargv) {
|
||||
*dp = 0.0;
|
||||
return (0);
|
||||
}
|
||||
if (**gargv == '"' || **gargv == '\'') {
|
||||
*dp = asciicode();
|
||||
return (0);
|
||||
}
|
||||
rval = 0;
|
||||
errno = 0;
|
||||
if (mod_ldbl)
|
||||
*dp = strtold(*gargv, &ep);
|
||||
else
|
||||
*dp = strtod(*gargv, &ep);
|
||||
if (ep == *gargv) {
|
||||
warnx2("%s: expected numeric value", *gargv, NULL);
|
||||
rval = 1;
|
||||
} else if (*ep != '\0') {
|
||||
warnx2("%s: not completely converted", *gargv, NULL);
|
||||
rval = 1;
|
||||
}
|
||||
if (errno == ERANGE) {
|
||||
warnx3("%s: %s", *gargv, strerror(ERANGE));
|
||||
rval = 1;
|
||||
}
|
||||
++gargv;
|
||||
return (rval);
|
||||
}
|
||||
|
||||
static int
|
||||
asciicode(void)
|
||||
{
|
||||
int ch;
|
||||
|
||||
ch = **gargv;
|
||||
if (ch == '\'' || ch == '"')
|
||||
ch = (*gargv)[1];
|
||||
++gargv;
|
||||
return (ch);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr, "usage: printf format [arguments ...]\n");
|
||||
}
|
103
pwd/pwd.1
Normal file
103
pwd/pwd.1
Normal file
@ -0,0 +1,103 @@
|
||||
.\"-
|
||||
.\" Copyright (c) 1990, 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.
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)pwd.1 8.2 (Berkeley) 4/28/95
|
||||
.\" $FreeBSD: src/bin/pwd/pwd.1,v 1.26 2005/01/16 16:41:58 ru Exp $
|
||||
.\"
|
||||
.Dd April 12, 2003
|
||||
.Dt PWD 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm pwd
|
||||
.Nd return working directory name
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl L | P
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility writes the absolute pathname of the current working directory to
|
||||
the standard output.
|
||||
.Pp
|
||||
Some shells may provide a builtin
|
||||
.Nm
|
||||
command which is similar or identical to this utility.
|
||||
Consult the
|
||||
.Xr builtin 1
|
||||
manual page.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl L
|
||||
Display the logical current working directory.
|
||||
.It Fl P
|
||||
Display the physical current working directory (all symbolic links resolved).
|
||||
.El
|
||||
.Pp
|
||||
If no options are specified, the
|
||||
.\" 4207130
|
||||
.Fl L
|
||||
option is assumed.
|
||||
.Sh ENVIRONMENT
|
||||
Environment variables used by
|
||||
.Nm :
|
||||
.Bl -tag -width ".Ev PWD"
|
||||
.It Ev PWD
|
||||
Logical current working directory.
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh SEE ALSO
|
||||
.Xr builtin 1 ,
|
||||
.Xr cd 1 ,
|
||||
.Xr csh 1 ,
|
||||
.Xr sh 1 ,
|
||||
.Xr getcwd 3
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility conforms to
|
||||
.St -p1003.1-2001 .
|
||||
.Sh BUGS
|
||||
In
|
||||
.Xr csh 1
|
||||
the command
|
||||
.Ic dirs
|
||||
is always faster because it is built into that shell.
|
||||
However, it can give a different answer in the rare case
|
||||
that the current directory or a containing directory was moved after
|
||||
the shell descended into it.
|
||||
.Pp
|
||||
The
|
||||
.Fl L
|
||||
option does not work unless the
|
||||
.Ev PWD
|
||||
environment variable is exported by the shell.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user