commands/find: original netbsd find
This commit is contained in:
parent
13d50be356
commit
fcd2a802a8
13
commands/find/Makefile
Normal file
13
commands/find/Makefile
Normal file
|
@ -0,0 +1,13 @@
|
|||
# $NetBSD: Makefile,v 1.12 2006/12/14 20:55:56 he Exp $
|
||||
# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= find
|
||||
SRCS= find.c function.c ls.c main.c misc.c operator.c option.c
|
||||
WARNS= 4
|
||||
|
||||
LDADD+=-lutil
|
||||
DPADD+=${LIBUTIL}
|
||||
|
||||
.include <bsd.prog.mk>
|
99
commands/find/extern.h
Normal file
99
commands/find/extern.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
/* $NetBSD: extern.h,v 1.28 2007/07/19 07:49:30 daniel 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. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (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: @(#)extern.h 8.3 (Berkeley) 4/16/94
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
void brace_subst(char *, char **, char *, int *);
|
||||
PLAN *find_create(char ***);
|
||||
int find_execute(PLAN *, char **);
|
||||
PLAN *find_formplan(char **);
|
||||
int find_traverse(PLAN *, int (*)(PLAN *, void *), void *);
|
||||
int f_expr(PLAN *, FTSENT *);
|
||||
PLAN *not_squish(PLAN *);
|
||||
PLAN *or_squish(PLAN *);
|
||||
PLAN *paren_squish(PLAN *);
|
||||
int plan_cleanup(PLAN *, void *);
|
||||
void printlong(char *, char *, struct stat *);
|
||||
int queryuser(char **);
|
||||
void show_path(int);
|
||||
|
||||
PLAN *c_amin(char ***, int);
|
||||
PLAN *c_anewer(char ***, int);
|
||||
PLAN *c_atime(char ***, int);
|
||||
PLAN *c_cmin(char ***, int);
|
||||
PLAN *c_cnewer(char ***, int);
|
||||
PLAN *c_ctime(char ***, int);
|
||||
PLAN *c_delete(char ***, int);
|
||||
PLAN *c_depth(char ***, int);
|
||||
PLAN *c_empty(char ***, int);
|
||||
PLAN *c_exec(char ***, int);
|
||||
PLAN *c_execdir(char ***, int);
|
||||
PLAN *c_exit(char ***, int);
|
||||
PLAN *c_false(char ***, int);
|
||||
PLAN *c_flags(char ***, int);
|
||||
PLAN *c_follow(char ***, int);
|
||||
PLAN *c_fprint(char ***, int);
|
||||
PLAN *c_fstype(char ***, int);
|
||||
PLAN *c_group(char ***, int);
|
||||
PLAN *c_iname(char ***, int);
|
||||
PLAN *c_inum(char ***, int);
|
||||
PLAN *c_iregex(char ***, int);
|
||||
PLAN *c_links(char ***, int);
|
||||
PLAN *c_ls(char ***, int);
|
||||
PLAN *c_maxdepth(char ***, int);
|
||||
PLAN *c_mindepth(char ***, int);
|
||||
PLAN *c_mmin(char ***, int);
|
||||
PLAN *c_mtime(char ***, int);
|
||||
PLAN *c_name(char ***, int);
|
||||
PLAN *c_newer(char ***, int);
|
||||
PLAN *c_nogroup(char ***, int);
|
||||
PLAN *c_nouser(char ***, int);
|
||||
PLAN *c_path(char ***, int);
|
||||
PLAN *c_perm(char ***, int);
|
||||
PLAN *c_print(char ***, int);
|
||||
PLAN *c_print0(char ***, int);
|
||||
PLAN *c_printx(char ***, int);
|
||||
PLAN *c_prune(char ***, int);
|
||||
PLAN *c_regex(char ***, int);
|
||||
PLAN *c_size(char ***, int);
|
||||
PLAN *c_type(char ***, int);
|
||||
PLAN *c_user(char ***, int);
|
||||
PLAN *c_xdev(char ***, int);
|
||||
PLAN *c_openparen(char ***, int);
|
||||
PLAN *c_closeparen(char ***, int);
|
||||
PLAN *c_not(char ***, int);
|
||||
PLAN *c_or(char ***, int);
|
||||
PLAN *c_null(char ***, int);
|
||||
|
||||
extern int ftsoptions, isdeprecated, isdepth, isoutput, issort, isxargs,
|
||||
regcomp_flags;
|
839
commands/find/find.1
Normal file
839
commands/find/find.1
Normal file
|
@ -0,0 +1,839 @@
|
|||
.\" $NetBSD: find.1,v 1.66 2007/07/19 07:49:30 daniel Exp $
|
||||
.\"
|
||||
.\" 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.
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" from: @(#)find.1 8.7 (Berkeley) 5/9/95
|
||||
.\"
|
||||
.Dd July 19, 2007
|
||||
.Dt FIND 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm find
|
||||
.Nd walk a file hierarchy
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl H | Fl L | Fl P
|
||||
.Op Fl dEhsXx
|
||||
.Ar file
|
||||
.Op Ar file ...
|
||||
.Op Ar expression
|
||||
.Nm
|
||||
.Op Fl H | Fl L | Fl P
|
||||
.Op Fl dEhsXx
|
||||
.Fl f Ar file
|
||||
.Op Ar file ...
|
||||
.Op Ar expression
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
recursively descends the directory tree for each
|
||||
.Ar file
|
||||
listed, evaluating an
|
||||
.Ar expression
|
||||
(composed of the
|
||||
.Dq primaries
|
||||
and
|
||||
.Dq operands
|
||||
listed below) in terms
|
||||
of each file in the tree.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Pp
|
||||
.Bl -tag -width Ds
|
||||
.It Fl H
|
||||
The
|
||||
.Fl H
|
||||
option causes the file information and file type (see
|
||||
.Xr stat 2 ) ,
|
||||
returned for each symbolic link encountered on the command line to be
|
||||
those of the file referenced by the link, not the link itself.
|
||||
If the referenced file does not exist, the file information and type will
|
||||
be for the link itself.
|
||||
File information of all symbolic links not on the command line is that
|
||||
of the link itself.
|
||||
.It Fl L
|
||||
The
|
||||
.Fl L
|
||||
option causes the file information and file type (see
|
||||
.Xr stat 2 )
|
||||
returned for each symbolic link to be those of the file referenced by the
|
||||
link, not the link itself.
|
||||
If the referenced file does not exist, the file information and type will
|
||||
be for the link itself.
|
||||
.It Fl P
|
||||
The
|
||||
.Fl P
|
||||
option causes the file information and file type (see
|
||||
.Xr stat 2 )
|
||||
returned for each symbolic link to be those of the link itself.
|
||||
.It Fl d
|
||||
The
|
||||
.Fl d
|
||||
option causes
|
||||
.Nm
|
||||
to perform a depth-first traversal, i.e., directories
|
||||
are visited in post-order and all entries in a directory will be acted
|
||||
on before the directory itself.
|
||||
By default,
|
||||
.Nm
|
||||
visits directories in pre-order, i.e., before their contents.
|
||||
Note, the default is
|
||||
.Ar not
|
||||
a breadth-first traversal.
|
||||
.It Fl E
|
||||
The
|
||||
.Fl E
|
||||
option causes
|
||||
.Ar regexp
|
||||
arguments to primaries to be interpreted as extended regular
|
||||
expressions (see
|
||||
.Xr re_format 7 ) .
|
||||
.It Fl f
|
||||
The
|
||||
.Fl f
|
||||
option specifies a file hierarchy for
|
||||
.Nm
|
||||
to traverse.
|
||||
File hierarchies may also be specified as the operands immediately
|
||||
following the options.
|
||||
.It Fl h
|
||||
The
|
||||
.Fl h
|
||||
option causes the file information and file type (see
|
||||
.Xr stat 2 ) ,
|
||||
returned for each symbolic link to be those of the file referenced by the
|
||||
link, not the link itself.
|
||||
If the referenced file does not exist, the file information and type will
|
||||
be for the link itself.
|
||||
.It Fl s
|
||||
The
|
||||
.Fl s
|
||||
option causes the entries of each directory to be sorted in
|
||||
lexicographical order.
|
||||
Note that the sorting is done only inside of each directory;
|
||||
files in different directories are not sorted.
|
||||
Therefore,
|
||||
.Sq Li a/b
|
||||
appears before
|
||||
.Sq Li a.b ,
|
||||
which is different from
|
||||
.Dq Li "find ... \&| sort"
|
||||
order.
|
||||
.It Fl X
|
||||
The
|
||||
.Fl X
|
||||
option is a modification to permit
|
||||
.Nm
|
||||
to be safely used in conjunction with
|
||||
.Xr xargs 1 .
|
||||
If a file name contains any of the delimiting characters used by
|
||||
.Nm xargs ,
|
||||
a diagnostic message is displayed on standard error, and the file
|
||||
is skipped.
|
||||
The delimiting characters include single
|
||||
.Pq Dq \&'
|
||||
and double
|
||||
.Pq Dq \&"
|
||||
quotes, backslash
|
||||
.Pq Dq \e ,
|
||||
space, tab and newline characters.
|
||||
Alternatively, the
|
||||
.Ic -print0
|
||||
or
|
||||
.Ic -printx
|
||||
primaries can be used to format the output in a way that
|
||||
.Nm xargs
|
||||
can accept.
|
||||
.It Fl x
|
||||
The
|
||||
.Fl x
|
||||
option restricts the search to the file system containing the
|
||||
directory specified.
|
||||
Does not list mount points to other file systems.
|
||||
.El
|
||||
.Sh PRIMARIES
|
||||
.Bl -tag -width Ds
|
||||
.It Ic -amin Ar n
|
||||
True if the difference between the file last access time and the time
|
||||
.Nm
|
||||
was started, rounded up to the next full minute, is
|
||||
.Ar n
|
||||
minutes.
|
||||
.It Ic -anewer Ar file
|
||||
True if the current file has a more recent last access time than
|
||||
.Ar file .
|
||||
.It Ic -atime Ar n
|
||||
True if the difference between the file last access time and the time
|
||||
.Nm
|
||||
was started, rounded up to the next full 24-hour period, is
|
||||
.Ar n
|
||||
24-hour periods.
|
||||
.It Ic -cmin Ar n
|
||||
True if the difference between the time of last change of file status
|
||||
information and the time
|
||||
.Nm
|
||||
was started, rounded up to the next full minute, is
|
||||
.Ar n
|
||||
minutes.
|
||||
.It Ic -cnewer Ar file
|
||||
True if the current file has a more recent last change time than
|
||||
.Ar file .
|
||||
.It Ic -ctime Ar n
|
||||
True if the difference between the time of last change of file status
|
||||
information and the time
|
||||
.Nm
|
||||
was started, rounded up to the next full 24-hour period, is
|
||||
.Ar n
|
||||
24-hour periods.
|
||||
.It Ic -delete
|
||||
Delete found files and/or directories.
|
||||
Always returns True.
|
||||
This executes from the current working directory as
|
||||
.Nm
|
||||
recurses down the tree.
|
||||
It will not attempt to delete a filename with a
|
||||
.Dq \/
|
||||
character in its pathname relative to
|
||||
.Dq \.
|
||||
for security reasons.
|
||||
Depth-first traversal processing is implied by this option.
|
||||
This can also be invoked as
|
||||
.Ic -rm .
|
||||
.It Ic -empty
|
||||
True if the current file or directory is empty.
|
||||
.\" The ".sp" below is probably not the right way to get the desired effect.
|
||||
.It Ic -exec Ar utility Oo argument ... Oc No ;
|
||||
.sp -1l
|
||||
.It Ic -exec Ar utility Oo argument ... Oc No {} +
|
||||
Execute the specified
|
||||
.Ar utility
|
||||
with the specified arguments.
|
||||
The list of arguments is terminated by
|
||||
.Dq Li \&;
|
||||
or
|
||||
.Dq Li \&+ .
|
||||
.Ar utility
|
||||
will be executed from the directory from which
|
||||
.Nm
|
||||
was executed.
|
||||
.Pp
|
||||
If terminated by a semicolon
|
||||
.Pq Dq \&; ,
|
||||
the
|
||||
.Ar utility
|
||||
is invoked once per path.
|
||||
If the string
|
||||
.Dq {}
|
||||
appears anywhere in the utility name or the arguments,
|
||||
it is replaced by the pathname of the current file.
|
||||
.Pp
|
||||
If terminated by a plus sign
|
||||
.Pq Dq \&+ ,
|
||||
the pathnames for which the
|
||||
primary is evaluated are aggregated into sets, and
|
||||
.Ar utility
|
||||
will be invoked once per set, similar to
|
||||
.Xr xargs 1 .
|
||||
If any invocation exits with non-zero exit status, then
|
||||
.Nm
|
||||
will eventually do so as well, but this does not cause
|
||||
.Nm
|
||||
to exit early.
|
||||
The string
|
||||
.Dq {}
|
||||
must appear, and must appear last.
|
||||
Each set is limitted to no more than 5,000 pathnames,
|
||||
and is also limitted such that the invokation of
|
||||
.Ar utility
|
||||
does not exceed
|
||||
.Dv ARG_MAX .
|
||||
.It Ic -execdir Ar utility Oo argument ... Oc No ;
|
||||
The
|
||||
.Ic -execdir
|
||||
primary is similar to the semicolon-terminated
|
||||
.Pq Dq \&;
|
||||
variant of the
|
||||
.Ic -exec
|
||||
primary, with the exception that
|
||||
.Ar utility
|
||||
will be executed from the directory that holds
|
||||
the current file.
|
||||
The filename substituted for the string
|
||||
.Dq {}
|
||||
is not qualified.
|
||||
Set aggregation
|
||||
.Pq Do \&+ Dc termination
|
||||
is not supported.
|
||||
.It Ic -exit Op Ar n
|
||||
This primary causes
|
||||
.Nm
|
||||
to stop traversing the filesystem and exit immediately if a
|
||||
previous condition was met.
|
||||
If no value is specified, the exit value will be 0, else
|
||||
.Ar n .
|
||||
Note that other primaries will be evaluated and acted upon before exiting.
|
||||
.It Ic -false
|
||||
This primary always evaluates to false.
|
||||
This can be used following a primary that caused the
|
||||
expression to be true to make the expression to be false.
|
||||
This can be useful after using a
|
||||
.Ic -fprint
|
||||
primary so it can continue to the next expression (using an
|
||||
.Cm -or
|
||||
operator, for example).
|
||||
.It Ic -flags Oo Fl Oc Ns Ar flags
|
||||
If
|
||||
.Ar flags
|
||||
are preceded by a dash
|
||||
.Pq Dq - ,
|
||||
this primary evaluates to true
|
||||
if at least all of the bits in
|
||||
.Ar flags
|
||||
are set in the file's flags bits.
|
||||
If
|
||||
.Ar flags
|
||||
are not preceded by a dash, this primary evaluates to true if
|
||||
the bits in
|
||||
.Ar flags
|
||||
exactly match the file's flags bits.
|
||||
If
|
||||
.Ar flags
|
||||
is
|
||||
.Dq none ,
|
||||
files with no flags bits set are matched.
|
||||
(See
|
||||
.Xr chflags 1
|
||||
for more information about file flags.)
|
||||
.It Ic -follow
|
||||
Follow symbolic links.
|
||||
.It Ic -fprint Ar filename
|
||||
This primary always evaluates to true.
|
||||
This creates
|
||||
.Ar filename
|
||||
or overwrites the file if it already exists.
|
||||
The file is created at startup.
|
||||
It writes the pathname of the current file to this file, followed
|
||||
by a newline character.
|
||||
The file will be empty if no files are matched.
|
||||
.It Ic -fstype Ar type
|
||||
True if the file is contained in a file system of type
|
||||
.Ar type .
|
||||
The
|
||||
.Xr sysctl 8
|
||||
command can be used to find out the types of filesystems
|
||||
that are available on the system:
|
||||
.Bd -literal -offset indent
|
||||
sysctl vfs.generic.fstypes
|
||||
.Ed
|
||||
.Pp
|
||||
In addition, there are two pseudo-types,
|
||||
.Dq local
|
||||
and
|
||||
.Dq rdonly .
|
||||
The former matches any file system physically mounted on the system where
|
||||
the
|
||||
.Nm
|
||||
is being executed, and the latter matches any file system which is
|
||||
mounted read-only.
|
||||
.It Ic -group Ar gname
|
||||
True if the file belongs to the group
|
||||
.Ar gname .
|
||||
If
|
||||
.Ar gname
|
||||
is numeric and there is no such group name, then
|
||||
.Ar gname
|
||||
is treated as a group id.
|
||||
.It Ic -iname Ar pattern
|
||||
True if the last component of the pathname being examined
|
||||
matches
|
||||
.Ar pattern .
|
||||
Case insensitive.
|
||||
.It Ic -inum Ar n
|
||||
True if the file has inode number
|
||||
.Ar n .
|
||||
.It Ic -iregex Ar regexp
|
||||
True if the path name of the current file matches the case-insensitive
|
||||
basic regular expression
|
||||
.Pq see Xr re_format 7
|
||||
.Ar regexp .
|
||||
This is a match on the whole path, not a search for the regular expression
|
||||
within the path.
|
||||
.It Ic -links Ar n
|
||||
True if the file has
|
||||
.Ar n
|
||||
links.
|
||||
.It Ic -rm
|
||||
This is an alias for
|
||||
.Ic -delete .
|
||||
.It Ic -ls
|
||||
This primary always evaluates to true.
|
||||
The following information for the current file is written to standard output:
|
||||
its inode number, size in 512-byte blocks, file permissions, number of hard
|
||||
links, owner, group, size in bytes, last modification time, and pathname.
|
||||
If the file is a block or character special file, the major and minor numbers
|
||||
will be displayed instead of the size in bytes.
|
||||
If the file is a symbolic link, the pathname of the linked-to file will be
|
||||
displayed preceded by
|
||||
.Dq -\*[Gt] .
|
||||
The format is identical to that produced by
|
||||
.Dq ls -dgils .
|
||||
.It Ic -maxdepth Ar n
|
||||
True if the current search depth is less than or equal to what is specified in
|
||||
.Ar n .
|
||||
.It Ic -mindepth Ar n
|
||||
True if the current search depth is at least what is specified in
|
||||
.Ar n .
|
||||
.It Ic -mmin Ar n
|
||||
True if the difference between the file last modification time and the time
|
||||
.Nm
|
||||
was started, rounded up to the next full minute, is
|
||||
.Ar n
|
||||
minutes.
|
||||
.It Ic -mtime Ar n
|
||||
True if the difference between the file last modification time and the time
|
||||
.Nm
|
||||
was started, rounded up to the next full 24-hour period, is
|
||||
.Ar n
|
||||
24-hour periods.
|
||||
.It Ic -ok Ar utility Oo argument ... Oc No ;
|
||||
The
|
||||
.Ic -ok
|
||||
primary is similar to the semicolon-terminated
|
||||
.Pq Dq \&;
|
||||
variant of the
|
||||
.Ic -exec
|
||||
primary, with the exception that
|
||||
.Nm
|
||||
requests user affirmation for the execution of the utility by printing
|
||||
a message to the terminal and reading a response.
|
||||
If the response is other than
|
||||
.Dq y ,
|
||||
the command is not executed and the
|
||||
.Ar -ok
|
||||
primary evaluates to false.
|
||||
Set aggregation
|
||||
.Pq Do \&+ Dc termination
|
||||
is not supported.
|
||||
.It Ic -name Ar pattern
|
||||
True if the last component of the pathname being examined matches
|
||||
.Ar pattern .
|
||||
Special shell pattern matching characters
|
||||
.Po
|
||||
.Dq \&[ ,
|
||||
.Dq \&] ,
|
||||
.Dq \&* ,
|
||||
.Dq \&?
|
||||
.Pc
|
||||
may be used as part of
|
||||
.Ar pattern .
|
||||
These characters may be matched explicitly by escaping them with a
|
||||
backslash
|
||||
.Pq Dq \e .
|
||||
.It Ic -newer Ar file
|
||||
True if the current file has a more recent last modification time than
|
||||
.Ar file .
|
||||
.It Ic -nouser
|
||||
True if the file belongs to an unknown user.
|
||||
.It Ic -nogroup
|
||||
True if the file belongs to an unknown group.
|
||||
.It Ic -path Ar pattern
|
||||
True if the pathname being examined matches
|
||||
.Ar pattern .
|
||||
Special shell pattern matching characters
|
||||
.Po
|
||||
.Dq \&[ ,
|
||||
.Dq \&] ,
|
||||
.Dq \&* ,
|
||||
and
|
||||
.Dq \&?
|
||||
.Pc
|
||||
may be used as part of
|
||||
.Ar pattern .
|
||||
These characters may be matched explicitly by escaping them with a
|
||||
backslash
|
||||
.Pq Dq \e .
|
||||
Slashes
|
||||
.Pq Dq /
|
||||
are treated as normal characters and do not have to be
|
||||
matched explicitly.
|
||||
.It Ic -perm Oo Fl Oc Ns Ar mode
|
||||
The
|
||||
.Ar mode
|
||||
may be either symbolic (see
|
||||
.Xr chmod 1 )
|
||||
or an octal number.
|
||||
If the mode is symbolic, a starting value of zero is assumed and the
|
||||
mode sets or clears permissions without regard to the process' file mode
|
||||
creation mask.
|
||||
If the mode is octal, only bits 07777
|
||||
.Pf ( Dv S_ISUID
|
||||
|
|
||||
.Dv S_ISGID
|
||||
|
|
||||
.Dv S_ISTXT
|
||||
|
|
||||
.Dv S_IRWXU
|
||||
|
|
||||
.Dv S_IRWXG
|
||||
|
|
||||
.Dv S_IRWXO )
|
||||
of the file's mode bits participate
|
||||
in the comparison.
|
||||
If the mode is preceded by a dash
|
||||
.Pq Dq - ,
|
||||
this primary evaluates to true
|
||||
if at least all of the bits in the mode are set in the file's mode bits.
|
||||
If the mode is not preceded by a dash, this primary evaluates to true if
|
||||
the bits in the mode exactly match the file's mode bits.
|
||||
Note, the first character of a symbolic mode may not be a dash
|
||||
.Pq Dq - .
|
||||
.It Ic -print
|
||||
This primary always evaluates to true.
|
||||
It prints the pathname of the current file to standard output, followed
|
||||
by a newline character.
|
||||
If none of
|
||||
.Ic -exec ,
|
||||
.Ic -exit ,
|
||||
.Ic -fprint ,
|
||||
.Ic -ls ,
|
||||
.Ic -ok ,
|
||||
.Ic -print0 ,
|
||||
nor
|
||||
.Ic -printx
|
||||
is specified, the given expression shall be effectively replaced by
|
||||
.Cm \&( Ns Ar given\& expression Ns Cm \&)
|
||||
.Ic -print .
|
||||
.It Ic -print0
|
||||
This primary always evaluates to true.
|
||||
It prints the pathname of the current file to standard output, followed
|
||||
by a null character.
|
||||
.It Ic -printx
|
||||
This primary always evaluates to true.
|
||||
It prints the pathname of the current file to standard output,
|
||||
with each space, tab, newline, backslash, dollar sign, and single,
|
||||
double, or back quotation mark prefixed by a backslash, so the output of
|
||||
.Nm find
|
||||
can safely be used as input to
|
||||
.Nm xargs .
|
||||
.It Ic -prune
|
||||
This primary always evaluates to true.
|
||||
It causes
|
||||
.Nm
|
||||
to not descend into the current file.
|
||||
Note, the
|
||||
.Ic -prune
|
||||
primary has no effect if the
|
||||
.Fl d
|
||||
option was specified.
|
||||
.It Ic -regex Ar regexp
|
||||
True if the path name of the current file matches the case-sensitive
|
||||
basic regular expression
|
||||
.Pq see Xr re_format 7
|
||||
.Ar regexp .
|
||||
This is a match on the whole path, not a search for the regular expression
|
||||
within the path.
|
||||
.It Ic -size Ar n Ns Op Cm c
|
||||
True if the file's size, rounded up, in 512-byte blocks is
|
||||
.Ar n .
|
||||
If
|
||||
.Ar n
|
||||
is followed by a
|
||||
.Dq c ,
|
||||
then the primary is true if the file's size is
|
||||
.Ar n
|
||||
bytes.
|
||||
.It Ic -type Ar t
|
||||
True if the file is of the specified type.
|
||||
Possible file types are as follows:
|
||||
.Pp
|
||||
.Bl -tag -width flag -offset indent -compact
|
||||
.It Cm b
|
||||
block special
|
||||
.It Cm c
|
||||
character special
|
||||
.It Cm d
|
||||
directory
|
||||
.It Cm f
|
||||
regular file
|
||||
.It Cm l
|
||||
symbolic link
|
||||
.It Cm p
|
||||
FIFO
|
||||
.It Cm s
|
||||
socket
|
||||
.It Cm W
|
||||
whiteout
|
||||
.It Cm w
|
||||
whiteout
|
||||
.El
|
||||
.Pp
|
||||
.It Ic -user Ar uname
|
||||
True if the file belongs to the user
|
||||
.Ar uname .
|
||||
If
|
||||
.Ar uname
|
||||
is numeric and there is no such user name, then
|
||||
.Ar uname
|
||||
is treated as a user id (and considered a numeric argument).
|
||||
.It Ic -xdev
|
||||
This primary always evaluates to true.
|
||||
It causes find not to descend past directories that have a different
|
||||
device ID (st_dev, see
|
||||
.Xr stat 2
|
||||
S5.6.2 [POSIX.1]).
|
||||
.El
|
||||
.Pp
|
||||
All primaries which take a numeric argument allow the number to be
|
||||
preceded by a plus sign
|
||||
.Pq Dq +
|
||||
or a minus sign
|
||||
.Pq Dq \- .
|
||||
A preceding plus sign means
|
||||
.Dq more than n ,
|
||||
a preceding minus sign means
|
||||
.Dq less than n ,
|
||||
and neither means
|
||||
.Dq exactly n .
|
||||
.Sh OPERATORS
|
||||
The primaries may be combined using the following operators.
|
||||
The operators are listed in order of decreasing precedence.
|
||||
.Bl -tag -width (expression)
|
||||
.It Cm \&( Ar expression Cm \&)
|
||||
This evaluates to true if the parenthesized expression evaluates to
|
||||
true.
|
||||
.Pp
|
||||
.It Cm \&! Ar expression
|
||||
This is the unary
|
||||
.Tn NOT
|
||||
operator.
|
||||
It evaluates to true if the expression is false.
|
||||
.Pp
|
||||
.It Ar expression Cm -and Ar expression
|
||||
.It Ar expression expression
|
||||
The
|
||||
.Cm -and
|
||||
operator is the logical
|
||||
.Tn AND
|
||||
operator.
|
||||
As it is implied by the juxtaposition of two expressions it does not
|
||||
have to be specified.
|
||||
The expression evaluates to true if both expressions are true.
|
||||
The second expression is not evaluated if the first expression is false.
|
||||
.Pp
|
||||
.It Ar expression Cm -or Ar expression
|
||||
The
|
||||
.Cm -or
|
||||
operator is the logical
|
||||
.Tn OR
|
||||
operator.
|
||||
The expression evaluates to true if either the first or the second expression
|
||||
is true.
|
||||
The second expression is not evaluated if the first expression is true.
|
||||
.El
|
||||
.Pp
|
||||
All operands and primaries must be separate arguments to
|
||||
.Nm .
|
||||
Primaries which themselves take arguments expect each argument
|
||||
to be a separate argument to
|
||||
.Nm .
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
utility normally exits 0 on success, and exits with 1 under certain
|
||||
internal error conditions.
|
||||
If any invokations of
|
||||
.Dq Ic -exec Ar ... No +
|
||||
primaries return non-zero exit-status, then
|
||||
.Nm
|
||||
will do so as well.
|
||||
.Sh EXAMPLES
|
||||
The following examples are shown as given to the shell:
|
||||
.Bl -tag -width findx
|
||||
.It Li "find / \e! -name \*q*.c\*q -print"
|
||||
Print out a list of all the files whose names do not end in
|
||||
.Dq \&.c .
|
||||
.It Li "find / -newer ttt -user wnj -print"
|
||||
Print out a list of all the files owned by user
|
||||
.Dq wnj
|
||||
that are newer than the file
|
||||
.Dq ttt .
|
||||
.It Li "find / \e! \e( -newer ttt -user wnj \e) -print"
|
||||
Print out a list of all the files which are not both newer than
|
||||
.Dq ttt
|
||||
and owned by
|
||||
.Dq wnj .
|
||||
.It Li "find / \e( -newer ttt -or -user wnj \e) -print"
|
||||
Print out a list of all the files that are either owned by
|
||||
.Dq wnj
|
||||
or that are newer than
|
||||
.Dq ttt .
|
||||
.It Li "find / \e( -newer ttt -or -user wnj \e) -exit 1"
|
||||
Return immediately with a value of 1 if any files are found that are either
|
||||
owned by
|
||||
.Dq wnj
|
||||
or that are newer than
|
||||
.Dq ttt ,
|
||||
but do not print them.
|
||||
.It Li "find / \e( -newer ttt -or -user wnj \e) -ls -exit 1"
|
||||
Same as above, but list the first file matching the criteria before exiting
|
||||
with a value of 1.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr chflags 1 ,
|
||||
.Xr chmod 1 ,
|
||||
.Xr locate 1 ,
|
||||
.Xr xargs 1 ,
|
||||
.Xr stat 2 ,
|
||||
.Xr fts 3 ,
|
||||
.Xr getgrent 3 ,
|
||||
.Xr getpwent 3 ,
|
||||
.Xr strmode 3 ,
|
||||
.Xr symlink 7 ,
|
||||
.Xr sysctl 8
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility syntax is a superset of the syntax specified by the
|
||||
.St -p1003.2
|
||||
standard.
|
||||
.Pp
|
||||
The options and the
|
||||
.Ic -amin ,
|
||||
.Ic -anewer ,
|
||||
.Ic -cmin ,
|
||||
.Ic -cnewer ,
|
||||
.Ic -delete ,
|
||||
.Ic -empty ,
|
||||
.Ic -execdir ,
|
||||
.Ic -follow ,
|
||||
.Ic -fstype ,
|
||||
.Ic -iname ,
|
||||
.Ic -inum ,
|
||||
.Ic -iregex ,
|
||||
.Ic -links ,
|
||||
.Ic -ls ,
|
||||
.Ic -maxdepth ,
|
||||
.Ic -mindepth ,
|
||||
.Ic -mmin ,
|
||||
.Ic -path ,
|
||||
.Ic -print0 ,
|
||||
.Ic -printx ,
|
||||
.Ic -regex ,
|
||||
and
|
||||
.Ic -rm
|
||||
primaries are extensions to
|
||||
.St -p1003.2 .
|
||||
.Pp
|
||||
Historically, the
|
||||
.Fl d ,
|
||||
.Fl h ,
|
||||
and
|
||||
.Fl x
|
||||
options were implemented using the primaries
|
||||
.Dq -depth ,
|
||||
.Dq -follow ,
|
||||
and
|
||||
.Dq -xdev .
|
||||
These primaries always evaluated to true.
|
||||
As they were really global variables that took effect before the traversal
|
||||
began, some legal expressions could have unexpected results.
|
||||
An example is the expression
|
||||
.Dq -print -o -depth .
|
||||
As -print always evaluates to true, the standard order of evaluation
|
||||
implies that -depth would never be evaluated.
|
||||
This is not the case.
|
||||
.Pp
|
||||
The operator
|
||||
.Dq -or
|
||||
was implemented as
|
||||
.Dq -o ,
|
||||
and the operator
|
||||
.Dq -and
|
||||
was implemented as
|
||||
.Dq -a .
|
||||
.Pp
|
||||
Historic implementations of the
|
||||
.Ic -exec
|
||||
and
|
||||
.Ic -ok
|
||||
primaries did not replace the string
|
||||
.Dq {}
|
||||
in the utility name or the
|
||||
utility arguments if it had preceding or following non-whitespace characters.
|
||||
This version replaces it no matter where in the utility name or arguments
|
||||
it appears.
|
||||
.Pp
|
||||
Support for
|
||||
.Dq Ic -exec Ar ... No +
|
||||
is consistent with
|
||||
.Em IEEE PASC Interpretation 1003.2 #210 ,
|
||||
though the feature originated in
|
||||
.Tn SVR4 .
|
||||
.Pp
|
||||
The
|
||||
.Ic -delete
|
||||
primary does not interact well with other options that cause the filesystem
|
||||
tree traversal options to be changed.
|
||||
.Sh HISTORY
|
||||
A much simpler
|
||||
.Nm find
|
||||
command appeared in First Edition AT\*[Am]T Unix.
|
||||
The syntax had become similar to the present version by
|
||||
the time of the Fifth Edition.
|
||||
.Sh BUGS
|
||||
The special characters used by
|
||||
.Nm
|
||||
are also special characters to many shell programs.
|
||||
In particular, the characters
|
||||
.Dq \&* ,
|
||||
.Dq \&[ ,
|
||||
.Dq \&] ,
|
||||
.Dq \&? ,
|
||||
.Dq \&( ,
|
||||
.Dq \&) ,
|
||||
.Dq \&! ,
|
||||
.Dq \e ,
|
||||
and
|
||||
.Dq \&;
|
||||
may have to be escaped from the shell.
|
||||
.Pp
|
||||
As there is no delimiter separating options and file names or file
|
||||
names and the
|
||||
.Ar expression ,
|
||||
it is difficult to specify files named
|
||||
.Dq -xdev
|
||||
or
|
||||
.Dq \&! .
|
||||
These problems are handled by the
|
||||
.Fl f
|
||||
option and the
|
||||
.Xr getopt 3
|
||||
.Dq --
|
||||
construct.
|
284
commands/find/find.c
Normal file
284
commands/find/find.c
Normal file
|
@ -0,0 +1,284 @@
|
|||
/* $NetBSD: find.c,v 1.25 2007/09/25 04:10:12 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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.
|
||||
* 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
|
||||
#if 0
|
||||
static char sccsid[] = "from: @(#)find.c 8.5 (Berkeley) 8/5/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: find.c,v 1.25 2007/09/25 04:10:12 lukem Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fts.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "find.h"
|
||||
|
||||
static int ftscompare(const FTSENT **, const FTSENT **);
|
||||
|
||||
static void sig_lock(sigset_t *);
|
||||
static void sig_unlock(const sigset_t *);
|
||||
|
||||
/*
|
||||
* 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, -fprint, -exec, or
|
||||
* -exit, then -print is assumed so we bracket the current expression
|
||||
* with parens, if necessary, and add a -print node on the end.
|
||||
*/
|
||||
if (!isoutput) {
|
||||
if (plan == NULL) {
|
||||
new = c_print(NULL, 0);
|
||||
tail = plan = new;
|
||||
} else {
|
||||
new = c_openparen(NULL, 0);
|
||||
new->next = plan;
|
||||
plan = new;
|
||||
new = c_closeparen(NULL, 0);
|
||||
tail->next = new;
|
||||
tail = new;
|
||||
new = c_print(NULL, 0);
|
||||
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);
|
||||
}
|
||||
|
||||
static int
|
||||
ftscompare(const FTSENT **e1, const FTSENT **e2)
|
||||
{
|
||||
|
||||
return (strcoll((*e1)->fts_name, (*e2)->fts_name));
|
||||
}
|
||||
|
||||
static void
|
||||
sig_lock(sigset_t *s)
|
||||
{
|
||||
sigset_t new;
|
||||
|
||||
sigemptyset(&new);
|
||||
sigaddset(&new, SIGINFO); /* block SIGINFO */
|
||||
sigprocmask(SIG_BLOCK, &new, s);
|
||||
}
|
||||
|
||||
static void
|
||||
sig_unlock(const sigset_t *s)
|
||||
{
|
||||
|
||||
sigprocmask(SIG_SETMASK, s, NULL);
|
||||
}
|
||||
|
||||
FTS *tree; /* pointer to top of FTS hierarchy */
|
||||
FTSENT *g_entry; /* shared with SIGINFO handler */
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
PLAN *p;
|
||||
int r, rval, cval;
|
||||
sigset_t s;
|
||||
|
||||
cval = 1;
|
||||
|
||||
if (!(tree = fts_open(paths, ftsoptions, issort ? ftscompare : NULL)))
|
||||
err(1, "ftsopen");
|
||||
|
||||
sig_lock(&s);
|
||||
for (rval = 0; cval && (g_entry = fts_read(tree)) != NULL; sig_lock(&s)) {
|
||||
sig_unlock(&s);
|
||||
switch (g_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",
|
||||
g_entry->fts_path, strerror(g_entry->fts_errno));
|
||||
rval = 1;
|
||||
continue;
|
||||
}
|
||||
#define BADCH " \t\n\\'\""
|
||||
if (isxargs && strpbrk(g_entry->fts_path, BADCH)) {
|
||||
(void)fflush(stdout);
|
||||
warnx("%s: illegal path", g_entry->fts_path);
|
||||
rval = 1;
|
||||
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->eval)(p, g_entry); p = p->next)
|
||||
if (p->type == N_EXIT) {
|
||||
rval = p->exit_val;
|
||||
cval = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sig_unlock(&s);
|
||||
if (errno)
|
||||
err(1, "fts_read");
|
||||
(void)fts_close(tree);
|
||||
|
||||
/*
|
||||
* Cleanup any plans with leftover state.
|
||||
* Keep the last non-zero return value.
|
||||
*/
|
||||
if ((r = find_traverse(plan, plan_cleanup, NULL)) != 0)
|
||||
rval = r;
|
||||
|
||||
return (rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* find_traverse --
|
||||
* traverse the plan tree and execute func() on all plans. This
|
||||
* does not evaluate each plan's eval() function; it is intended
|
||||
* for operations that must run on all plans, such as state
|
||||
* cleanup.
|
||||
*
|
||||
* If any func() returns non-zero, then so will find_traverse().
|
||||
*/
|
||||
int
|
||||
find_traverse(plan, func, arg)
|
||||
PLAN *plan;
|
||||
int (*func)(PLAN *, void *);
|
||||
void *arg;
|
||||
{
|
||||
PLAN *p;
|
||||
int r, rval;
|
||||
|
||||
rval = 0;
|
||||
for (p = plan; p; p = p->next) {
|
||||
if ((r = func(p, arg)) != 0)
|
||||
rval = r;
|
||||
if (p->type == N_EXPR || p->type == N_OR) {
|
||||
if (p->p_data[0])
|
||||
if ((r = find_traverse(p->p_data[0],
|
||||
func, arg)) != 0)
|
||||
rval = r;
|
||||
if (p->p_data[1])
|
||||
if ((r = find_traverse(p->p_data[1],
|
||||
func, arg)) != 0)
|
||||
rval = r;
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
135
commands/find/find.h
Normal file
135
commands/find/find.h
Normal file
|
@ -0,0 +1,135 @@
|
|||
/* $NetBSD: find.h,v 1.24 2007/02/06 13:25:01 elad Exp $ */
|
||||
|
||||
/*-
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* from: @(#)find.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
/* node type */
|
||||
enum ntype {
|
||||
N_AND = 1, /* must start > 0 */
|
||||
N_AMIN, N_ANEWER, N_ATIME, N_CLOSEPAREN, N_CMIN, N_CNEWER, N_CTIME,
|
||||
N_DEPTH, N_EMPTY, N_EXEC, N_EXECDIR, N_EXIT, N_EXPR, N_FALSE, N_FLAGS,
|
||||
N_FOLLOW, N_FPRINT, N_FSTYPE, N_GROUP,
|
||||
N_INAME, N_INUM, N_IREGEX, N_LINKS, N_LS, N_MINDEPTH, N_MAXDEPTH,
|
||||
N_MMIN, N_MTIME, N_NAME, N_NEWER, N_NOGROUP, N_NOT, N_NOUSER, N_OK,
|
||||
N_OPENPAREN, N_OR, N_PATH, N_PERM, N_PRINT, N_PRINT0, N_PRINTX,
|
||||
N_PRUNE, N_REGEX, N_SIZE, N_TYPE, N_USER, N_XDEV, N_DELETE
|
||||
};
|
||||
|
||||
/* node definition */
|
||||
typedef struct _plandata {
|
||||
struct _plandata *next; /* next node */
|
||||
int (*eval)(struct _plandata *, FTSENT *);
|
||||
/* node evaluation function */
|
||||
#define F_EQUAL 1 /* [acm]time inum links size */
|
||||
#define F_LESSTHAN 2
|
||||
#define F_GREATER 3
|
||||
#define F_NEEDOK 1 /* exec ok */
|
||||
#define F_PLUSSET 2 /* -exec ... {} + */
|
||||
#define F_MTFLAG 1 /* fstype */
|
||||
#define F_MTTYPE 2
|
||||
#define F_ATLEAST 1 /* perm */
|
||||
int flags; /* private flags */
|
||||
enum ntype type; /* plan node type */
|
||||
union {
|
||||
u_int32_t _f_data; /* flags */
|
||||
gid_t _g_data; /* gid */
|
||||
ino_t _i_data; /* inode */
|
||||
mode_t _m_data; /* mode mask */
|
||||
nlink_t _l_data; /* link count */
|
||||
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 */
|
||||
char **_ep_bxp; /* ptr to 1st addt'l arg */
|
||||
char *_ep_p; /* current buffer pointer */
|
||||
char *_ep_bbp; /* begin buffer pointer */
|
||||
char *_ep_ebp; /* end buffer pointer */
|
||||
int _ep_maxargs; /* max #args */
|
||||
int _ep_narg; /* # addt'l args */
|
||||
int _ep_rval; /* return value */
|
||||
} ex;
|
||||
char *_a_data[2]; /* array of char pointers */
|
||||
char *_c_data; /* char pointer */
|
||||
int _exit_val; /* exit value */
|
||||
int _max_data; /* tree depth */
|
||||
int _min_data; /* tree depth */
|
||||
regex_t _regexp_data; /* compiled regexp */
|
||||
FILE *_fprint_file; /* file stream for -fprint */
|
||||
} p_un;
|
||||
} PLAN;
|
||||
#define a_data p_un._a_data
|
||||
#define c_data p_un._c_data
|
||||
#define i_data p_un._i_data
|
||||
#define f_data p_un._f_data
|
||||
#define g_data p_un._g_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 e_argv p_un.ex._e_argv
|
||||
#define e_orig p_un.ex._e_orig
|
||||
#define e_len p_un.ex._e_len
|
||||
#define ep_p p_un.ex._ep_p
|
||||
#define ep_bbp p_un.ex._ep_bbp
|
||||
#define ep_ebp p_un.ex._ep_ebp
|
||||
#define ep_bxp p_un.ex._ep_bxp
|
||||
#define ep_cnt p_un.ex._ep_cnt
|
||||
#define ep_maxargs p_un.ex._ep_maxargs
|
||||
#define ep_nline p_un.ex._ep_nline
|
||||
#define ep_narg p_un.ex._ep_narg
|
||||
#define ep_rval p_un.ex._ep_rval
|
||||
#define exit_val p_un._exit_val
|
||||
#define max_data p_un._max_data
|
||||
#define min_data p_un._min_data
|
||||
#define regexp_data p_un._regexp_data
|
||||
#define fprint_file p_un._fprint_file
|
||||
|
||||
typedef struct _option {
|
||||
const char *name; /* option name */
|
||||
enum ntype token; /* token type */
|
||||
PLAN *(*create)(char ***, int); /* create function */
|
||||
int arg; /* function needs arg */
|
||||
} OPTION;
|
||||
|
||||
#include "extern.h"
|
1896
commands/find/function.c
Normal file
1896
commands/find/function.c
Normal file
File diff suppressed because it is too large
Load diff
123
commands/find/ls.c
Normal file
123
commands/find/ls.c
Normal file
|
@ -0,0 +1,123 @@
|
|||
/* $NetBSD: ls.c,v 1.19 2006/10/11 19:51:10 apb 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "from: @(#)ls.c 8.1 (Berkeley) 6/6/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: ls.c,v 1.19 2006/10/11 19:51:10 apb Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fts.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <tzfile.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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, /* filename to print */
|
||||
char *accpath, /* current valid path to filename */
|
||||
struct stat *sb) /* stat buffer */
|
||||
{
|
||||
char modep[15];
|
||||
|
||||
(void)printf("%7lu %6lld ", (u_long)sb->st_ino,
|
||||
(long long)sb->st_blocks);
|
||||
(void)strmode(sb->st_mode, modep);
|
||||
(void)printf("%s %3lu %-*s %-*s ", modep, (unsigned long)sb->st_nlink,
|
||||
LOGIN_NAME_MAX, user_from_uid(sb->st_uid, 0), LOGIN_NAME_MAX,
|
||||
group_from_gid(sb->st_gid, 0));
|
||||
|
||||
if (S_ISCHR(sb->st_mode) || S_ISBLK(sb->st_mode))
|
||||
(void)printf("%3d,%5d ", major(sb->st_rdev),
|
||||
minor(sb->st_rdev));
|
||||
else
|
||||
(void)printf("%9lld ", (long long)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)
|
||||
{
|
||||
int i;
|
||||
char *longstring;
|
||||
|
||||
longstring = ctime(&ftime);
|
||||
for (i = 4; i < 11; ++i)
|
||||
(void)putchar(longstring[i]);
|
||||
|
||||
#define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
|
||||
if (ftime + SIXMONTHS > time((time_t *)NULL))
|
||||
for (i = 11; i < 16; ++i)
|
||||
(void)putchar(longstring[i]);
|
||||
else {
|
||||
(void)putchar(' ');
|
||||
for (i = 20; i < 24; ++i)
|
||||
(void)putchar(longstring[i]);
|
||||
}
|
||||
(void)putchar(' ');
|
||||
}
|
||||
|
||||
static void
|
||||
printlink(char *name)
|
||||
{
|
||||
int lnklen;
|
||||
char path[MAXPATHLEN + 1];
|
||||
|
||||
if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) {
|
||||
warn("%s", name);
|
||||
return;
|
||||
}
|
||||
path[lnklen] = '\0';
|
||||
(void)printf(" -> %s", path);
|
||||
}
|
173
commands/find/main.c
Normal file
173
commands/find/main.c
Normal file
|
@ -0,0 +1,173 @@
|
|||
/* $NetBSD: main.c,v 1.28 2008/07/21 14:19:22 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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.
|
||||
* 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
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 5/4/95";
|
||||
#else
|
||||
__COPYRIGHT("@(#) Copyright (c) 1990, 1993, 1994\
|
||||
The Regents of the University of California. All rights reserved.");
|
||||
__RCSID("$NetBSD: main.c,v 1.28 2008/07/21 14:19:22 lukem Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fts.h>
|
||||
#include <signal.h>
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.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; /* sort directory entries */
|
||||
int isxargs; /* don't permit xargs delimiting chars */
|
||||
int regcomp_flags = REG_BASIC; /* regex compilation flags */
|
||||
|
||||
int main(int, char **);
|
||||
static void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct sigaction sa;
|
||||
char **p, **start;
|
||||
int ch;
|
||||
|
||||
(void)time(&now); /* initialize the time-of-day */
|
||||
(void)setlocale(LC_ALL, "");
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_flags = SA_RESTART;
|
||||
sa.sa_handler = show_path;
|
||||
sigaction(SIGINFO, &sa, NULL);
|
||||
|
||||
/* array to hold dir list. at most (argc - 1) elements. */
|
||||
p = start = malloc(argc * sizeof (char *));
|
||||
if (p == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
ftsoptions = FTS_NOSTAT | FTS_PHYSICAL;
|
||||
while ((ch = getopt(argc, argv, "HLPdEf:hsXx")) != -1)
|
||||
switch (ch) {
|
||||
case 'H':
|
||||
ftsoptions &= ~FTS_LOGICAL;
|
||||
ftsoptions |= FTS_PHYSICAL|FTS_COMFOLLOW;
|
||||
break;
|
||||
case 'L':
|
||||
ftsoptions &= ~(FTS_COMFOLLOW|FTS_PHYSICAL);
|
||||
ftsoptions |= FTS_LOGICAL;
|
||||
break;
|
||||
case 'P':
|
||||
ftsoptions &= ~(FTS_COMFOLLOW|FTS_LOGICAL);
|
||||
ftsoptions |= FTS_PHYSICAL;
|
||||
break;
|
||||
case 'd':
|
||||
isdepth = 1;
|
||||
break;
|
||||
case 'E':
|
||||
regcomp_flags = REG_EXTENDED;
|
||||
break;
|
||||
case 'f':
|
||||
*p++ = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
ftsoptions &= ~FTS_PHYSICAL;
|
||||
ftsoptions |= FTS_LOGICAL;
|
||||
break;
|
||||
case 's':
|
||||
issort = 1;
|
||||
break;
|
||||
case 'X':
|
||||
isxargs = 1;
|
||||
break;
|
||||
case 'x':
|
||||
ftsoptions |= FTS_XDEV;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/*
|
||||
* 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)) == -1 ||
|
||||
fcntl(dotfd, F_SETFD, FD_CLOEXEC) == -1)
|
||||
err(1, ".");
|
||||
|
||||
exit(find_execute(find_formplan(argv), start));
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
(void)fprintf(stderr,
|
||||
"usage: find [-H | -L | -P] [-dEhsXx] [-f file] file [file ...] [expression]\n");
|
||||
exit(1);
|
||||
}
|
151
commands/find/misc.c
Normal file
151
commands/find/misc.c
Normal file
|
@ -0,0 +1,151 @@
|
|||
/* $NetBSD: misc.c,v 1.14 2006/10/11 19:51:10 apb Exp $ */
|
||||
|
||||
/*-
|
||||
* 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.
|
||||
* 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
|
||||
#if 0
|
||||
static char sccsid[] = "from: @(#)misc.c 8.2 (Berkeley) 4/1/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: misc.c,v 1.14 2006/10/11 19:51:10 apb Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#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 <unistd.h>
|
||||
|
||||
#include "find.h"
|
||||
|
||||
/*
|
||||
* brace_subst --
|
||||
* Replace occurrences of {} in orig with path, and place it in a malloced
|
||||
* area of memory set in store.
|
||||
*/
|
||||
void
|
||||
brace_subst(char *orig, char **store, char *path, int *len)
|
||||
{
|
||||
int nlen, plen, rest;
|
||||
char ch, *p, *ostore;
|
||||
|
||||
plen = strlen(path);
|
||||
for (p = *store; (ch = *orig) != '\0'; ++orig)
|
||||
if (ch == '{' && orig[1] == '}') {
|
||||
/* Length of string after the {}. */
|
||||
rest = strlen(&orig[2]);
|
||||
|
||||
nlen = *len;
|
||||
while ((p - *store) + plen + rest + 1 > nlen)
|
||||
nlen *= 2;
|
||||
|
||||
if (nlen > *len) {
|
||||
ostore = *store;
|
||||
if ((*store = realloc(ostore, nlen)) == NULL)
|
||||
err(1, "realloc");
|
||||
*len = nlen;
|
||||
p += *store - ostore; /* Relocate. */
|
||||
}
|
||||
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 'y' then 1 is returned.
|
||||
*/
|
||||
int
|
||||
queryuser(char **argv)
|
||||
{
|
||||
int ch, first, nl;
|
||||
|
||||
(void)fprintf(stderr, "\"%s", *argv);
|
||||
while (*++argv)
|
||||
(void)fprintf(stderr, " %s", *argv);
|
||||
(void)fprintf(stderr, "\"? ");
|
||||
(void)fflush(stderr);
|
||||
|
||||
first = ch = getchar();
|
||||
for (nl = 0;;) {
|
||||
if (ch == '\n') {
|
||||
nl = 1;
|
||||
break;
|
||||
}
|
||||
if (ch == EOF)
|
||||
break;
|
||||
ch = getchar();
|
||||
}
|
||||
|
||||
if (!nl) {
|
||||
(void)fprintf(stderr, "\n");
|
||||
(void)fflush(stderr);
|
||||
}
|
||||
return (first == 'y');
|
||||
}
|
||||
|
||||
/*
|
||||
* show_path --
|
||||
* called on SIGINFO
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
void
|
||||
show_path(int sig)
|
||||
{
|
||||
extern FTSENT *g_entry;
|
||||
int errno_bak;
|
||||
|
||||
if (g_entry == NULL) {
|
||||
/*
|
||||
* not initialized yet.
|
||||
* assumption: pointer assignment is atomic.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
errno_bak = errno;
|
||||
write(STDERR_FILENO, "find path: ", 11);
|
||||
write(STDERR_FILENO, g_entry->fts_path, g_entry->fts_pathlen);
|
||||
write(STDERR_FILENO, "\n", 1);
|
||||
errno = errno_bak;
|
||||
}
|
272
commands/find/operator.c
Normal file
272
commands/find/operator.c
Normal file
|
@ -0,0 +1,272 @@
|
|||
/* $NetBSD: operator.c,v 1.9 2006/10/11 19:51:10 apb Exp $ */
|
||||
|
||||
/*-
|
||||
* 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.
|
||||
* 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
|
||||
#if 0
|
||||
static char sccsid[] = "from: @(#)operator.c 8.1 (Berkeley) 6/6/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: operator.c,v 1.9 2006/10/11 19:51:10 apb Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#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) /* pointer to top of plan (modified) */
|
||||
{
|
||||
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 N_EXPR node containing a list of simple nodes.
|
||||
*/
|
||||
static PLAN *
|
||||
yankexpr(PLAN **planp) /* pointer to top of plan (modified) */
|
||||
{
|
||||
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->type == N_OPENPAREN)
|
||||
for (tail = subplan = NULL;;) {
|
||||
if ((next = yankexpr(planp)) == NULL)
|
||||
err(1, "(: missing closing ')'");
|
||||
/*
|
||||
* If we find a closing ')' we store the collected
|
||||
* subplan in our '(' node and convert the node to
|
||||
* a N_EXPR. The ')' we found is ignored. Otherwise,
|
||||
* we just continue to add whatever we get to our
|
||||
* subplan.
|
||||
*/
|
||||
if (next->type == N_CLOSEPAREN) {
|
||||
if (subplan == NULL)
|
||||
errx(1, "(): empty inner expression");
|
||||
node->p_data[0] = subplan;
|
||||
node->type = N_EXPR;
|
||||
node->eval = f_expr;
|
||||
break;
|
||||
} else {
|
||||
if (subplan == NULL)
|
||||
tail = subplan = next;
|
||||
else {
|
||||
tail->next = next;
|
||||
tail = next;
|
||||
}
|
||||
tail->next = NULL;
|
||||
}
|
||||
}
|
||||
return (node);
|
||||
}
|
||||
|
||||
/*
|
||||
* paren_squish --
|
||||
* replaces "parentheisized" plans in our search plan with "expr" nodes.
|
||||
*/
|
||||
PLAN *
|
||||
paren_squish(PLAN *plan) /* plan with ( ) nodes */
|
||||
{
|
||||
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 it's results together.
|
||||
*/
|
||||
while ((expr = yankexpr(&plan)) != NULL) {
|
||||
/*
|
||||
* if we find an unclaimed ')' it means there is a missing
|
||||
* '(' someplace.
|
||||
*/
|
||||
if (expr->type == N_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 to process */
|
||||
{
|
||||
PLAN *next; /* next node being processed */
|
||||
PLAN *node; /* temporary node used in N_NOT processing */
|
||||
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 nots in
|
||||
* the expr subplan.
|
||||
*/
|
||||
if (next->type == N_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->type == N_NOT) {
|
||||
int notlevel = 1;
|
||||
|
||||
node = yanknode(&plan);
|
||||
while (node != NULL && node->type == N_NOT) {
|
||||
++notlevel;
|
||||
node = yanknode(&plan);
|
||||
}
|
||||
if (node == NULL)
|
||||
errx(1, "!: no following expression");
|
||||
if (node->type == N_OR)
|
||||
errx(1, "!: nothing between ! and -o");
|
||||
if (node->type == N_EXPR)
|
||||
node = not_squish(node);
|
||||
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 with ors to be squished */
|
||||
{
|
||||
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->type == N_EXPR)
|
||||
next->p_data[0] = or_squish(next->p_data[0]);
|
||||
|
||||
/* if we encounter a not then look for not's in the subplan */
|
||||
if (next->type == N_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->type == N_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);
|
||||
}
|
157
commands/find/option.c
Normal file
157
commands/find/option.c
Normal file
|
@ -0,0 +1,157 @@
|
|||
/* $NetBSD: option.c,v 1.26 2007/02/06 15:33:22 perry Exp $ */
|
||||
|
||||
/*-
|
||||
* 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.
|
||||
* 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
|
||||
#if 0
|
||||
static char sccsid[] = "from: @(#)option.c 8.2 (Berkeley) 4/16/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: option.c,v 1.26 2007/02/06 15:33:22 perry Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <fts.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "find.h"
|
||||
|
||||
int typecompare(const void *, const void *);
|
||||
static OPTION *option(char *);
|
||||
|
||||
/* NB: the following table must be sorted lexically. */
|
||||
static OPTION const options[] = {
|
||||
{ "!", N_NOT, c_not, 0 },
|
||||
{ "(", N_OPENPAREN, c_openparen, 0 },
|
||||
{ ")", N_CLOSEPAREN, c_closeparen, 0 },
|
||||
{ "-a", N_AND, c_null, 0 },
|
||||
{ "-amin", N_AMIN, c_amin, 1 },
|
||||
{ "-and", N_AND, c_null, 0 },
|
||||
{ "-anewer", N_ANEWER, c_anewer, 1 },
|
||||
{ "-atime", N_ATIME, c_atime, 1 },
|
||||
{ "-cmin", N_CMIN, c_cmin, 1 },
|
||||
{ "-cnewer", N_CNEWER, c_cnewer, 1 },
|
||||
{ "-ctime", N_CTIME, c_ctime, 1 },
|
||||
{ "-delete", N_DELETE, c_delete, 0 },
|
||||
{ "-depth", N_DEPTH, c_depth, 0 },
|
||||
{ "-empty", N_EMPTY, c_empty, 0 },
|
||||
{ "-exec", N_EXEC, c_exec, 1 },
|
||||
{ "-execdir", N_EXECDIR, c_execdir, 1 },
|
||||
{ "-exit", N_EXIT, c_exit, 0 },
|
||||
{ "-false", N_FALSE, c_false, 0 },
|
||||
{ "-flags", N_FLAGS, c_flags, 1 },
|
||||
{ "-follow", N_FOLLOW, c_follow, 0 },
|
||||
{ "-fprint", N_FPRINT, c_fprint, 1 },
|
||||
{ "-fstype", N_FSTYPE, c_fstype, 1 },
|
||||
{ "-group", N_GROUP, c_group, 1 },
|
||||
{ "-iname", N_INAME, c_iname, 1 },
|
||||
{ "-inum", N_INUM, c_inum, 1 },
|
||||
{ "-iregex", N_IREGEX, c_iregex, 1 },
|
||||
{ "-links", N_LINKS, c_links, 1 },
|
||||
{ "-ls", N_LS, c_ls, 0 },
|
||||
{ "-maxdepth", N_MAXDEPTH, c_maxdepth, 1 },
|
||||
{ "-mindepth", N_MINDEPTH, c_mindepth, 1 },
|
||||
{ "-mmin", N_MMIN, c_mmin, 1 },
|
||||
{ "-mtime", N_MTIME, c_mtime, 1 },
|
||||
{ "-name", N_NAME, c_name, 1 },
|
||||
{ "-newer", N_NEWER, c_newer, 1 },
|
||||
{ "-nogroup", N_NOGROUP, c_nogroup, 0 },
|
||||
{ "-nouser", N_NOUSER, c_nouser, 0 },
|
||||
{ "-o", N_OR, c_or, 0 },
|
||||
{ "-ok", N_OK, c_exec, 1 },
|
||||
{ "-or", N_OR, c_or, 0 },
|
||||
{ "-path", N_PATH, c_path, 1 },
|
||||
{ "-perm", N_PERM, c_perm, 1 },
|
||||
{ "-print", N_PRINT, c_print, 0 },
|
||||
{ "-print0", N_PRINT0, c_print0, 0 },
|
||||
{ "-printx", N_PRINTX, c_printx, 0 },
|
||||
{ "-prune", N_PRUNE, c_prune, 0 },
|
||||
{ "-regex", N_REGEX, c_regex, 1 },
|
||||
{ "-rm", N_DELETE, c_delete, 0 },
|
||||
{ "-size", N_SIZE, c_size, 1 },
|
||||
{ "-type", N_TYPE, c_type, 1 },
|
||||
{ "-user", N_USER, c_user, 1 },
|
||||
{ "-xdev", N_XDEV, c_xdev, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* 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 = option(*argv)) == NULL)
|
||||
errx(1, "%s: unknown option", *argv);
|
||||
++argv;
|
||||
if (p->arg && !*argv)
|
||||
errx(1, "%s: requires additional arguments", *--argv);
|
||||
|
||||
new = (p->create)(&argv, p->token == N_OK);
|
||||
|
||||
*argvp = argv;
|
||||
return (new);
|
||||
}
|
||||
|
||||
static OPTION *
|
||||
option(char *name)
|
||||
{
|
||||
OPTION tmp;
|
||||
|
||||
tmp.name = name;
|
||||
return ((OPTION *)bsearch(&tmp, options,
|
||||
sizeof(options)/sizeof(OPTION), sizeof(OPTION), typecompare));
|
||||
}
|
||||
|
||||
int
|
||||
typecompare(const void *a, const void *b)
|
||||
{
|
||||
|
||||
return (strcmp(((const OPTION *)a)->name, ((const OPTION *)b)->name));
|
||||
}
|
Loading…
Reference in a new issue