shell_cmds-187

This commit is contained in:
Apple 2015-12-20 20:27:02 +01:00 committed by Lubos Dolezel
commit c68cae3f05
159 changed files with 37070 additions and 0 deletions

1
alias/alias.1 Normal file
View File

@ -0,0 +1 @@
.so man1/builtin.1

331
alias/builtin.1 Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1 @@
.so man1/basename.1

102
chroot/chroot.8 Normal file
View 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
View 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
View 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
View 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, &lt);
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, &lt);
(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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,2 @@
#include <stdlib.h>
int main () { exit(1); }

2
false/false.sh Normal file
View File

@ -0,0 +1,2 @@
#! /bin/sh
exit 1

124
find/extern.h Normal file
View 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

File diff suppressed because it is too large Load Diff

323
find/find.c Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

961
find/getdate.y Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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"

View File

@ -0,0 +1 @@
.so man8/locate.code.8

View 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
View 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
View 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);
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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