xref: /illumos-gate/usr/src/cmd/find/find.c (revision f3a525d9)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5d35170d6Srm  * Common Development and Distribution License (the "License").
6d35170d6Srm  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22ef497ae3SRich Burridge  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
2303f45afcSYuri Pankov  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
2405f32410SAndy Stormont  * Copyright (c) 2013 Andrew Stormont.  All rights reserved.
25*f3a525d9SJohn Levon  * Copyright 2020 Joyent, Inc.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
28da1a9cbeSjonb 
297c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
3027d3a169SToomas Soome /*	  All Rights Reserved	*/
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate /*	Parts of this product may be derived from		*/
347c478bd9Sstevel@tonic-gate /*	Mortice Kern Systems Inc. and Berkeley 4.3 BSD systems.	*/
3527d3a169SToomas Soome /*	licensed from  Mortice Kern Systems Inc. and		*/
367c478bd9Sstevel@tonic-gate /*	the University of California.				*/
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate  * Copyright 1985, 1990 by Mortice Kern Systems Inc.  All rights reserved.
407c478bd9Sstevel@tonic-gate  */
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #include <stdio.h>
437c478bd9Sstevel@tonic-gate #include <errno.h>
447c478bd9Sstevel@tonic-gate #include <pwd.h>
457c478bd9Sstevel@tonic-gate #include <grp.h>
467c478bd9Sstevel@tonic-gate #include <sys/types.h>
477c478bd9Sstevel@tonic-gate #include <sys/stat.h>
487c478bd9Sstevel@tonic-gate #include <sys/param.h>
497c478bd9Sstevel@tonic-gate #include <sys/acl.h>
507c478bd9Sstevel@tonic-gate #include <limits.h>
517c478bd9Sstevel@tonic-gate #include <unistd.h>
527c478bd9Sstevel@tonic-gate #include <stdlib.h>
537c478bd9Sstevel@tonic-gate #include <locale.h>
547c478bd9Sstevel@tonic-gate #include <string.h>
557c478bd9Sstevel@tonic-gate #include <strings.h>
567c478bd9Sstevel@tonic-gate #include <ctype.h>
577c478bd9Sstevel@tonic-gate #include <wait.h>
587c478bd9Sstevel@tonic-gate #include <fnmatch.h>
597c478bd9Sstevel@tonic-gate #include <langinfo.h>
607c478bd9Sstevel@tonic-gate #include <ftw.h>
619ab6dc39Schin #include <libgen.h>
62b34cd89aSYuri Pankov #include <err.h>
63b34cd89aSYuri Pankov #include <regex.h>
643d63ea05Sas #include "getresponse.h"
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate #define	A_DAY		(long)(60*60*24)	/* a day full of seconds */
67da1a9cbeSjonb #define	A_MIN		(long)(60)
687c478bd9Sstevel@tonic-gate #define	BLKSIZ		512
697c478bd9Sstevel@tonic-gate #define	round(x, s)	(((x)+(s)-1)&~((s)-1))
707c478bd9Sstevel@tonic-gate #ifndef FTW_SLN
717c478bd9Sstevel@tonic-gate #define	FTW_SLN		7
727c478bd9Sstevel@tonic-gate #endif
737c478bd9Sstevel@tonic-gate #define	LINEBUF_SIZE		LINE_MAX	/* input or output lines */
747c478bd9Sstevel@tonic-gate #define	REMOTE_FS		"/etc/dfs/fstypes"
757c478bd9Sstevel@tonic-gate #define	N_FSTYPES		20
76d35170d6Srm #define	SHELL_MAXARGS		253	/* see doexec() for description */
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate  * This is the list of operations
807c478bd9Sstevel@tonic-gate  * F_USER and F_GROUP are named to avoid conflict with USER and GROUP defined
817c478bd9Sstevel@tonic-gate  * in sys/acl.h
827c478bd9Sstevel@tonic-gate  */
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate enum Command
857c478bd9Sstevel@tonic-gate {
86b34cd89aSYuri Pankov 	PRINT,
87b34cd89aSYuri Pankov 	ACL, AMIN, AND, ATIME, CMIN, CPIO, CSIZE, CTIME, DEPTH, EXEC, F_GROUP,
8805f32410SAndy Stormont 	F_GROUPACL, F_USER, F_USERACL, FOLLOW, FSTYPE, INAME, INUM, IPATH,
8905f32410SAndy Stormont 	IREGEX,	LINKS, LOCAL, LPAREN, LS, MAXDEPTH, MINDEPTH, MMIN, MOUNT,
9005f32410SAndy Stormont 	MTIME, NAME, NCPIO, NEWER, NOGRP, NOT, NOUSER, OK, OR, PATH, PERM,
91ab823b7fSPrasad Joshi 	PRINT0, PRUNE, REGEX, RPAREN, SIZE, TYPE, VARARGS, XATTR, DELETE
927c478bd9Sstevel@tonic-gate };
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate enum Type
957c478bd9Sstevel@tonic-gate {
967c478bd9Sstevel@tonic-gate 	Unary, Id, Num, Str, Exec, Cpio, Op
977c478bd9Sstevel@tonic-gate };
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate struct Args
1007c478bd9Sstevel@tonic-gate {
1017c478bd9Sstevel@tonic-gate 	char		name[10];
1027c478bd9Sstevel@tonic-gate 	enum Command	action;
1037c478bd9Sstevel@tonic-gate 	enum Type	type;
1047c478bd9Sstevel@tonic-gate };
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate /*
1077c478bd9Sstevel@tonic-gate  * Except for pathnames, these are the only legal arguments
1087c478bd9Sstevel@tonic-gate  */
1097c478bd9Sstevel@tonic-gate static struct Args commands[] =
1107c478bd9Sstevel@tonic-gate {
111b34cd89aSYuri Pankov 	"!",		NOT,		Op,
112b34cd89aSYuri Pankov 	"(",		LPAREN,		Unary,
113b34cd89aSYuri Pankov 	")",		RPAREN,		Unary,
114b34cd89aSYuri Pankov 	"-a",		AND,		Op,
115b34cd89aSYuri Pankov 	"-acl",		ACL,		Unary,
116b34cd89aSYuri Pankov 	"-amin",	AMIN,		Num,
117b34cd89aSYuri Pankov 	"-and",		AND,		Op,
118b34cd89aSYuri Pankov 	"-atime",	ATIME,		Num,
119b34cd89aSYuri Pankov 	"-cmin",	CMIN,		Num,
120b34cd89aSYuri Pankov 	"-cpio",	CPIO,		Cpio,
121b34cd89aSYuri Pankov 	"-ctime",	CTIME,		Num,
122b34cd89aSYuri Pankov 	"-depth",	DEPTH,		Unary,
123ab823b7fSPrasad Joshi 	"-delete",	DELETE,		Unary,
124b34cd89aSYuri Pankov 	"-exec",	EXEC,		Exec,
125b34cd89aSYuri Pankov 	"-follow",	FOLLOW,		Unary,
126b34cd89aSYuri Pankov 	"-fstype",	FSTYPE,		Str,
1277c478bd9Sstevel@tonic-gate 	"-group",	F_GROUP,	Num,
128b34cd89aSYuri Pankov 	"-groupacl",	F_GROUPACL,	Num,
129b34cd89aSYuri Pankov 	"-iname",	INAME,		Str,
130b34cd89aSYuri Pankov 	"-inum",	INUM,		Num,
13105f32410SAndy Stormont 	"-ipath",	IPATH,		Str,
132b34cd89aSYuri Pankov 	"-iregex",	IREGEX,		Str,
13303f45afcSYuri Pankov 	"-links",	LINKS,		Num,
13403f45afcSYuri Pankov 	"-local",	LOCAL,		Unary,
135b34cd89aSYuri Pankov 	"-ls",		LS,		Unary,
136b34cd89aSYuri Pankov 	"-maxdepth",	MAXDEPTH,	Num,
137b34cd89aSYuri Pankov 	"-mindepth",	MINDEPTH,	Num,
138b34cd89aSYuri Pankov 	"-mmin",	MMIN,		Num,
139b34cd89aSYuri Pankov 	"-mount",	MOUNT,		Unary,
140b34cd89aSYuri Pankov 	"-mtime",	MTIME,		Num,
141b34cd89aSYuri Pankov 	"-name",	NAME,		Str,
142b34cd89aSYuri Pankov 	"-ncpio",	NCPIO,		Cpio,
143b34cd89aSYuri Pankov 	"-newer",	NEWER,		Str,
144b34cd89aSYuri Pankov 	"-nogroup",	NOGRP,		Unary,
145b34cd89aSYuri Pankov 	"-not",		NOT,		Op,
146b34cd89aSYuri Pankov 	"-nouser",	NOUSER,		Unary,
147b34cd89aSYuri Pankov 	"-o",		OR,		Op,
148b34cd89aSYuri Pankov 	"-ok",		OK,		Exec,
149b34cd89aSYuri Pankov 	"-or",		OR,		Op,
15005f32410SAndy Stormont 	"-path",	PATH,		Str,
151b34cd89aSYuri Pankov 	"-perm",	PERM,		Num,
152b34cd89aSYuri Pankov 	"-print",	PRINT,		Unary,
153b34cd89aSYuri Pankov 	"-print0",	PRINT0,		Unary,
154b34cd89aSYuri Pankov 	"-prune",	PRUNE,		Unary,
155b34cd89aSYuri Pankov 	"-regex",	REGEX,		Str,
156b34cd89aSYuri Pankov 	"-size",	SIZE,		Num,
157b34cd89aSYuri Pankov 	"-type",	TYPE,		Num,
158b34cd89aSYuri Pankov 	"-user",	F_USER,		Num,
159b34cd89aSYuri Pankov 	"-useracl",	F_USERACL,	Num,
160b34cd89aSYuri Pankov 	"-xattr",	XATTR,		Unary,
161b34cd89aSYuri Pankov 	"-xdev",	MOUNT,		Unary,
16227d3a169SToomas Soome 	0,		0,		0
1637c478bd9Sstevel@tonic-gate };
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate union Item
1667c478bd9Sstevel@tonic-gate {
1677c478bd9Sstevel@tonic-gate 	struct Node	*np;
1687c478bd9Sstevel@tonic-gate 	struct Arglist	*vp;
1697c478bd9Sstevel@tonic-gate 	time_t		t;
1707c478bd9Sstevel@tonic-gate 	char		*cp;
1717c478bd9Sstevel@tonic-gate 	char		**ap;
1727c478bd9Sstevel@tonic-gate 	long		l;
1737c478bd9Sstevel@tonic-gate 	int		i;
1747c478bd9Sstevel@tonic-gate 	long long	ll;
1757c478bd9Sstevel@tonic-gate };
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate struct Node
1787c478bd9Sstevel@tonic-gate {
1797c478bd9Sstevel@tonic-gate 	struct Node	*next;
1807c478bd9Sstevel@tonic-gate 	enum Command	action;
1817c478bd9Sstevel@tonic-gate 	enum Type	type;
1827c478bd9Sstevel@tonic-gate 	union Item	first;
1837c478bd9Sstevel@tonic-gate 	union Item	second;
1847c478bd9Sstevel@tonic-gate };
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate /* if no -print, -exec or -ok replace "expression" with "(expression) -print" */
1877c478bd9Sstevel@tonic-gate static	struct	Node PRINT_NODE = { 0, PRINT, 0, 0};
1887c478bd9Sstevel@tonic-gate static	struct	Node LPAREN_NODE = { 0, LPAREN, 0, 0};
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate /*
1927c478bd9Sstevel@tonic-gate  * Prototype variable size arglist buffer
1937c478bd9Sstevel@tonic-gate  */
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate struct Arglist
1967c478bd9Sstevel@tonic-gate {
1977c478bd9Sstevel@tonic-gate 	struct Arglist	*next;
1987c478bd9Sstevel@tonic-gate 	char		*end;
1997c478bd9Sstevel@tonic-gate 	char		*nextstr;
2007c478bd9Sstevel@tonic-gate 	char		**firstvar;
2017c478bd9Sstevel@tonic-gate 	char		**nextvar;
2027c478bd9Sstevel@tonic-gate 	char		*arglist[1];
2037c478bd9Sstevel@tonic-gate };
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 
20627d3a169SToomas Soome static int		compile(char **, struct Node *, int *);
20727d3a169SToomas Soome static int		execute(const char *, const struct stat *, int,
20827d3a169SToomas Soome     struct FTW *);
20927d3a169SToomas Soome static int		doexec(const char *, char **, int *);
21027d3a169SToomas Soome static int		dodelete(const char *, const struct stat *,
21127d3a169SToomas Soome     struct FTW *);
21227d3a169SToomas Soome static struct Args	*lookup(char *);
21327d3a169SToomas Soome static int		ok(const char *, char *[]);
2146c83d09fSrobbin static void		usage(void)	__NORETURN;
21527d3a169SToomas Soome static struct Arglist	*varargs(char **);
21627d3a169SToomas Soome static int		list(const char *, const struct stat *);
21727d3a169SToomas Soome static char		*getgroup(gid_t);
21827d3a169SToomas Soome static FILE		*cmdopen(char *, char **, char *, FILE *);
21927d3a169SToomas Soome static int		cmdclose(FILE *);
22027d3a169SToomas Soome static char		*getshell(void);
22127d3a169SToomas Soome static void		init_remote_fs(void);
22227d3a169SToomas Soome static char		*getname(uid_t);
22327d3a169SToomas Soome static int		readmode(const char *);
22427d3a169SToomas Soome static mode_t		getmode(mode_t);
22527d3a169SToomas Soome static const char	*gettail(const char *);
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 
22868a94df1Scf static int walkflags = FTW_CHDIR|FTW_PHYS|FTW_ANYERR|FTW_NOLOOP;
2297c478bd9Sstevel@tonic-gate static struct Node	*topnode;
2307c478bd9Sstevel@tonic-gate static struct Node	*freenode;	/* next free node we may use later */
2317c478bd9Sstevel@tonic-gate static char		*cpio[] = { "cpio", "-o", 0 };
2327c478bd9Sstevel@tonic-gate static char		*ncpio[] = { "cpio", "-oc", 0 };
2337c478bd9Sstevel@tonic-gate static char		*cpiol[] = { "cpio", "-oL", 0 };
2347c478bd9Sstevel@tonic-gate static char		*ncpiol[] = { "cpio", "-ocL", 0 };
2357c478bd9Sstevel@tonic-gate static time_t		now;
2367c478bd9Sstevel@tonic-gate static FILE		*output;
2377c478bd9Sstevel@tonic-gate static char		*dummyarg = (char *)-1;
2387c478bd9Sstevel@tonic-gate static int		lastval;
2397c478bd9Sstevel@tonic-gate static int		varsize;
2407c478bd9Sstevel@tonic-gate static struct Arglist	*lastlist;
2417c478bd9Sstevel@tonic-gate static char		*cmdname;
2427c478bd9Sstevel@tonic-gate static char		*remote_fstypes[N_FSTYPES+1];
2437c478bd9Sstevel@tonic-gate static int		fstype_index = 0;
2447c478bd9Sstevel@tonic-gate static int		action_expression = 0;	/* -print, -exec, or -ok */
2457c478bd9Sstevel@tonic-gate static int		error = 0;
2467c478bd9Sstevel@tonic-gate static int		paren_cnt = 0;	/* keeps track of parentheses */
247b34cd89aSYuri Pankov static int		Eflag = 0;
2487c478bd9Sstevel@tonic-gate static int		hflag = 0;
2497c478bd9Sstevel@tonic-gate static int		lflag = 0;
250d35170d6Srm /* set when doexec()-invoked utility returns non-zero */
251d35170d6Srm static int		exec_exitcode = 0;
252b34cd89aSYuri Pankov static regex_t		*preg = NULL;
253b34cd89aSYuri Pankov static int		npreg = 0;
254b34cd89aSYuri Pankov static int		mindepth = -1, maxdepth = -1;
2557c478bd9Sstevel@tonic-gate extern char		**environ;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)2587c478bd9Sstevel@tonic-gate main(int argc, char **argv)
2597c478bd9Sstevel@tonic-gate {
2607c478bd9Sstevel@tonic-gate 	char *cp;
2617c478bd9Sstevel@tonic-gate 	int c;
2627c478bd9Sstevel@tonic-gate 	int paths;
2637c478bd9Sstevel@tonic-gate 	char *cwdpath;
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
2667c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
2677c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
2687c478bd9Sstevel@tonic-gate #endif
2697c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	cmdname = argv[0];
2727c478bd9Sstevel@tonic-gate 	if (time(&now) == (time_t)(-1)) {
2737c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("%s: time() %s\n"),
2743d63ea05Sas 		    cmdname, strerror(errno));
2757c478bd9Sstevel@tonic-gate 		exit(1);
2767c478bd9Sstevel@tonic-gate 	}
277b34cd89aSYuri Pankov 	while ((c = getopt(argc, argv, "EHL")) != -1) {
2787c478bd9Sstevel@tonic-gate 		switch (c) {
279b34cd89aSYuri Pankov 		case 'E':
280b34cd89aSYuri Pankov 			Eflag = 1;
281b34cd89aSYuri Pankov 			break;
2827c478bd9Sstevel@tonic-gate 		case 'H':
2837c478bd9Sstevel@tonic-gate 			hflag = 1;
2847c478bd9Sstevel@tonic-gate 			lflag = 0;
2857c478bd9Sstevel@tonic-gate 			break;
2867c478bd9Sstevel@tonic-gate 		case 'L':
2877c478bd9Sstevel@tonic-gate 			hflag = 0;
2887c478bd9Sstevel@tonic-gate 			lflag = 1;
2897c478bd9Sstevel@tonic-gate 			break;
2907c478bd9Sstevel@tonic-gate 		case '?':
2917c478bd9Sstevel@tonic-gate 			usage();
2927c478bd9Sstevel@tonic-gate 			break;
2937c478bd9Sstevel@tonic-gate 		}
2947c478bd9Sstevel@tonic-gate 	}
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	argc -= optind;
2977c478bd9Sstevel@tonic-gate 	argv += optind;
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	if (argc < 1) {
3007c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
3017c478bd9Sstevel@tonic-gate 		    gettext("%s: insufficient number of arguments\n"), cmdname);
3027c478bd9Sstevel@tonic-gate 		usage();
3037c478bd9Sstevel@tonic-gate 	}
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	for (paths = 0; (cp = argv[paths]) != 0; ++paths) {
3067c478bd9Sstevel@tonic-gate 		if (*cp == '-')
3077c478bd9Sstevel@tonic-gate 			break;
3087c478bd9Sstevel@tonic-gate 		else if ((*cp == '!' || *cp == '(') && *(cp+1) == 0)
3097c478bd9Sstevel@tonic-gate 			break;
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	if (paths == 0) /* no path-list */
3137c478bd9Sstevel@tonic-gate 		usage();
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	output = stdout;
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	/* lflag is the same as -follow */
3187c478bd9Sstevel@tonic-gate 	if (lflag)
3197c478bd9Sstevel@tonic-gate 		walkflags &= ~FTW_PHYS;
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	/* allocate enough space for the compiler */
3227c478bd9Sstevel@tonic-gate 	topnode = malloc((argc + 1) * sizeof (struct Node));
3237c478bd9Sstevel@tonic-gate 	(void) memset(topnode, 0, (argc + 1) * sizeof (struct Node));
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 	if (compile(argv + paths, topnode, &action_expression) == 0) {
3267c478bd9Sstevel@tonic-gate 		/* no expression, default to -print */
3277c478bd9Sstevel@tonic-gate 		(void) memcpy(topnode, &PRINT_NODE, sizeof (struct Node));
3287c478bd9Sstevel@tonic-gate 	} else if (!action_expression) {
3297c478bd9Sstevel@tonic-gate 		/*
3307c478bd9Sstevel@tonic-gate 		 * if no action expression, insert an LPAREN node above topnode,
3317c478bd9Sstevel@tonic-gate 		 * with a PRINT node as its next node
3327c478bd9Sstevel@tonic-gate 		 */
3337c478bd9Sstevel@tonic-gate 		struct Node *savenode;
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 		if (freenode == NULL) {
3367c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("%s: can't append -print"
3373d63ea05Sas 			    " implicitly; try explicit -print option\n"),
3383d63ea05Sas 			    cmdname);
3397c478bd9Sstevel@tonic-gate 			exit(1);
3407c478bd9Sstevel@tonic-gate 		}
3417c478bd9Sstevel@tonic-gate 		savenode = topnode;
3427c478bd9Sstevel@tonic-gate 		topnode = freenode++;
3437c478bd9Sstevel@tonic-gate 		(void) memcpy(topnode, &LPAREN_NODE, sizeof (struct Node));
3447c478bd9Sstevel@tonic-gate 		topnode->next = freenode;
3457c478bd9Sstevel@tonic-gate 		topnode->first.np = savenode;
3467c478bd9Sstevel@tonic-gate 		(void) memcpy(topnode->next, &PRINT_NODE, sizeof (struct Node));
3477c478bd9Sstevel@tonic-gate 	}
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	while (paths--) {
3507c478bd9Sstevel@tonic-gate 		char *curpath;
3517c478bd9Sstevel@tonic-gate 		struct stat sb;
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 		curpath = *(argv++);
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 		/*
3567c478bd9Sstevel@tonic-gate 		 * If -H is specified, it means we walk the first
3577c478bd9Sstevel@tonic-gate 		 * level (pathname on command line) logically, following
3587c478bd9Sstevel@tonic-gate 		 * symlinks, but lower levels are walked physically.
3597c478bd9Sstevel@tonic-gate 		 * We use our own secret interface to nftw() to change
3607c478bd9Sstevel@tonic-gate 		 * the from stat to lstat after the top level is walked.
3617c478bd9Sstevel@tonic-gate 		 */
3627c478bd9Sstevel@tonic-gate 		if (hflag) {
3637c478bd9Sstevel@tonic-gate 			if (stat(curpath, &sb) < 0 && errno == ENOENT)
3647c478bd9Sstevel@tonic-gate 				walkflags &= ~FTW_HOPTION;
3657c478bd9Sstevel@tonic-gate 			else
3667c478bd9Sstevel@tonic-gate 				walkflags |= FTW_HOPTION;
3677c478bd9Sstevel@tonic-gate 		}
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 		/*
3707c478bd9Sstevel@tonic-gate 		 * We need this check as nftw needs a CWD and we have no
3717c478bd9Sstevel@tonic-gate 		 * way of returning back from that code with a meaningful
3727c478bd9Sstevel@tonic-gate 		 * error related to this
3737c478bd9Sstevel@tonic-gate 		 */
3747c478bd9Sstevel@tonic-gate 		if ((cwdpath = getcwd(NULL, PATH_MAX)) == NULL) {
3754b808d43SRich Burridge 			if ((errno == EACCES) && (walkflags & FTW_CHDIR)) {
3764b808d43SRich Burridge 				/*
3774b808d43SRich Burridge 				 * A directory above cwd is inaccessible,
3784b808d43SRich Burridge 				 * so don't do chdir(2)s. Slower, but at least
3794b808d43SRich Burridge 				 * it works.
3804b808d43SRich Burridge 				 */
3814b808d43SRich Burridge 				walkflags &= ~FTW_CHDIR;
3824b808d43SRich Burridge 				free(cwdpath);
3834b808d43SRich Burridge 			} else {
3844b808d43SRich Burridge 				(void) fprintf(stderr,
3854b808d43SRich Burridge 				    gettext("%s : cannot get the current "
3864b808d43SRich Burridge 				    "working directory\n"), cmdname);
3874b808d43SRich Burridge 				exit(1);
3884b808d43SRich Burridge 			}
3897c478bd9Sstevel@tonic-gate 		} else
3907c478bd9Sstevel@tonic-gate 			free(cwdpath);
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 		if (nftw(curpath, execute, 1000, walkflags)) {
3947c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
3957c478bd9Sstevel@tonic-gate 			    gettext("%s: cannot open %s: %s\n"),
3967c478bd9Sstevel@tonic-gate 			    cmdname, curpath, strerror(errno));
3977c478bd9Sstevel@tonic-gate 			error = 1;
3987c478bd9Sstevel@tonic-gate 		}
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	}
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	/* execute any remaining variable length lists */
4037c478bd9Sstevel@tonic-gate 	while (lastlist) {
4047c478bd9Sstevel@tonic-gate 		if (lastlist->end != lastlist->nextstr) {
4057c478bd9Sstevel@tonic-gate 			*lastlist->nextvar = 0;
40627d3a169SToomas Soome 			(void) doexec(NULL, lastlist->arglist,
407d35170d6Srm 			    &exec_exitcode);
4087c478bd9Sstevel@tonic-gate 		}
4097c478bd9Sstevel@tonic-gate 		lastlist = lastlist->next;
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate 	if (output != stdout)
4127c478bd9Sstevel@tonic-gate 		return (cmdclose(output));
413d35170d6Srm 	return ((exec_exitcode != 0) ? exec_exitcode : error);
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate /*
4177c478bd9Sstevel@tonic-gate  * compile the arguments
4187c478bd9Sstevel@tonic-gate  */
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate static int
compile(char ** argv,struct Node * np,int * actionp)42127d3a169SToomas Soome compile(char **argv, struct Node *np, int *actionp)
4227c478bd9Sstevel@tonic-gate {
4237c478bd9Sstevel@tonic-gate 	char *b;
4247c478bd9Sstevel@tonic-gate 	char **av;
4257c478bd9Sstevel@tonic-gate 	struct Node *oldnp = topnode;
4267c478bd9Sstevel@tonic-gate 	struct Args *argp;
4277c478bd9Sstevel@tonic-gate 	char **com;
4287c478bd9Sstevel@tonic-gate 	int i;
4297c478bd9Sstevel@tonic-gate 	enum Command wasop = PRINT;
4307c478bd9Sstevel@tonic-gate 
4313d63ea05Sas 	if (init_yes() < 0) {
4323d63ea05Sas 		(void) fprintf(stderr, gettext(ERR_MSG_INIT_YES),
4333d63ea05Sas 		    strerror(errno));
4343d63ea05Sas 		exit(1);
4353d63ea05Sas 	}
4363d63ea05Sas 
4377c478bd9Sstevel@tonic-gate 	for (av = argv; *av && (argp = lookup(*av)); av++) {
4387c478bd9Sstevel@tonic-gate 		np->next = 0;
4397c478bd9Sstevel@tonic-gate 		np->action = argp->action;
4407c478bd9Sstevel@tonic-gate 		np->type = argp->type;
4417c478bd9Sstevel@tonic-gate 		np->second.i = 0;
4427c478bd9Sstevel@tonic-gate 		if (argp->type == Op) {
4437c478bd9Sstevel@tonic-gate 			if (wasop == NOT || (wasop && np->action != NOT)) {
4447c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
44527d3a169SToomas Soome 				    gettext("%s: operand follows operand\n"),
44627d3a169SToomas Soome 				    cmdname);
4477c478bd9Sstevel@tonic-gate 				exit(1);
4487c478bd9Sstevel@tonic-gate 			}
4497c478bd9Sstevel@tonic-gate 			if (np->action != NOT && oldnp == 0)
4507c478bd9Sstevel@tonic-gate 				goto err;
4517c478bd9Sstevel@tonic-gate 			wasop = argp->action;
4527c478bd9Sstevel@tonic-gate 		} else {
4537c478bd9Sstevel@tonic-gate 			wasop = PRINT;
4547c478bd9Sstevel@tonic-gate 			if (argp->type != Unary) {
4557c478bd9Sstevel@tonic-gate 				if (!(b = *++av)) {
45627d3a169SToomas Soome 					(void) fprintf(stderr, gettext(
45727d3a169SToomas Soome 					    "%s: incomplete statement\n"),
45827d3a169SToomas Soome 					    cmdname);
4597c478bd9Sstevel@tonic-gate 					exit(1);
4607c478bd9Sstevel@tonic-gate 				}
4617c478bd9Sstevel@tonic-gate 				if (argp->type == Num) {
462b34cd89aSYuri Pankov 					if (((argp->action == MAXDEPTH) ||
463b34cd89aSYuri Pankov 					    (argp->action == MINDEPTH)) &&
464b34cd89aSYuri Pankov 					    ((int)strtol(b, (char **)NULL,
465b34cd89aSYuri Pankov 					    10) < 0))
46627d3a169SToomas Soome 						errx(1, gettext(
46727d3a169SToomas Soome 						    "%s: value must be "
46827d3a169SToomas Soome 						    "positive"),
469b34cd89aSYuri Pankov 						    (argp->action == MAXDEPTH) ?
470b34cd89aSYuri Pankov 						    "maxdepth" : "mindepth");
4717c478bd9Sstevel@tonic-gate 					if ((argp->action != PERM) ||
4727c478bd9Sstevel@tonic-gate 					    (*b != '+')) {
4737c478bd9Sstevel@tonic-gate 						if (*b == '+' || *b == '-') {
4747c478bd9Sstevel@tonic-gate 							np->second.i = *b;
4757c478bd9Sstevel@tonic-gate 							b++;
4767c478bd9Sstevel@tonic-gate 						}
4777c478bd9Sstevel@tonic-gate 					}
4787c478bd9Sstevel@tonic-gate 				}
4797c478bd9Sstevel@tonic-gate 			}
4807c478bd9Sstevel@tonic-gate 		}
4817c478bd9Sstevel@tonic-gate 		switch (argp->action) {
4827c478bd9Sstevel@tonic-gate 		case AND:
4837c478bd9Sstevel@tonic-gate 			break;
4847c478bd9Sstevel@tonic-gate 		case NOT:
4857c478bd9Sstevel@tonic-gate 			break;
4867c478bd9Sstevel@tonic-gate 		case OR:
4877c478bd9Sstevel@tonic-gate 			np->first.np = topnode;
4887c478bd9Sstevel@tonic-gate 			topnode = np;
4897c478bd9Sstevel@tonic-gate 			oldnp->next = 0;
4907c478bd9Sstevel@tonic-gate 			break;
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 		case LPAREN: {
4937c478bd9Sstevel@tonic-gate 			struct Node *save = topnode;
4947c478bd9Sstevel@tonic-gate 			topnode = np+1;
4957c478bd9Sstevel@tonic-gate 			paren_cnt++;
4967c478bd9Sstevel@tonic-gate 			i = compile(++av, topnode, actionp);
4977c478bd9Sstevel@tonic-gate 			np->first.np = topnode;
4987c478bd9Sstevel@tonic-gate 			topnode = save;
4997c478bd9Sstevel@tonic-gate 			av += i;
5007c478bd9Sstevel@tonic-gate 			oldnp = np;
5017c478bd9Sstevel@tonic-gate 			np += i + 1;
5027c478bd9Sstevel@tonic-gate 			oldnp->next = np;
5037c478bd9Sstevel@tonic-gate 			continue;
5047c478bd9Sstevel@tonic-gate 		}
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 		case RPAREN:
5077c478bd9Sstevel@tonic-gate 			if (paren_cnt <= 0) {
5087c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
5097c478bd9Sstevel@tonic-gate 				    gettext("%s: unmatched ')'\n"),
5107c478bd9Sstevel@tonic-gate 				    cmdname);
5117c478bd9Sstevel@tonic-gate 				exit(1);
5127c478bd9Sstevel@tonic-gate 			}
5137c478bd9Sstevel@tonic-gate 			paren_cnt--;
5147c478bd9Sstevel@tonic-gate 			if (oldnp == 0)
5157c478bd9Sstevel@tonic-gate 				goto err;
5167c478bd9Sstevel@tonic-gate 			if (oldnp->type == Op) {
5177c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
5187c478bd9Sstevel@tonic-gate 				    gettext("%s: cannot immediately"
5197c478bd9Sstevel@tonic-gate 				    " follow an operand with ')'\n"),
5207c478bd9Sstevel@tonic-gate 				    cmdname);
5217c478bd9Sstevel@tonic-gate 				exit(1);
5227c478bd9Sstevel@tonic-gate 			}
5237c478bd9Sstevel@tonic-gate 			oldnp->next = 0;
5247c478bd9Sstevel@tonic-gate 			return (av-argv);
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 		case FOLLOW:
5277c478bd9Sstevel@tonic-gate 			walkflags &= ~FTW_PHYS;
5287c478bd9Sstevel@tonic-gate 			break;
5297c478bd9Sstevel@tonic-gate 		case MOUNT:
5307c478bd9Sstevel@tonic-gate 			walkflags |= FTW_MOUNT;
5317c478bd9Sstevel@tonic-gate 			break;
5327c478bd9Sstevel@tonic-gate 		case DEPTH:
5337c478bd9Sstevel@tonic-gate 			walkflags |= FTW_DEPTH;
5347c478bd9Sstevel@tonic-gate 			break;
535ab823b7fSPrasad Joshi 		case DELETE:
536ab823b7fSPrasad Joshi 			walkflags |= (FTW_DEPTH | FTW_PHYS);
537ab823b7fSPrasad Joshi 			walkflags &= ~FTW_CHDIR;
538ab823b7fSPrasad Joshi 			(*actionp)++;
539ab823b7fSPrasad Joshi 			break;
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 		case LOCAL:
5427c478bd9Sstevel@tonic-gate 			np->first.l = 0L;
5437c478bd9Sstevel@tonic-gate 			np->first.ll = 0LL;
5447c478bd9Sstevel@tonic-gate 			np->second.i = '+';
5457c478bd9Sstevel@tonic-gate 			/*
5467c478bd9Sstevel@tonic-gate 			 * Make it compatible to df -l for
5477c478bd9Sstevel@tonic-gate 			 * future enhancement. So, anything
5487c478bd9Sstevel@tonic-gate 			 * that is not remote, then it is
5497c478bd9Sstevel@tonic-gate 			 * local.
5507c478bd9Sstevel@tonic-gate 			 */
5517c478bd9Sstevel@tonic-gate 			init_remote_fs();
5527c478bd9Sstevel@tonic-gate 			break;
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 		case SIZE:
5557c478bd9Sstevel@tonic-gate 			if (b[strlen(b)-1] == 'c')
5567c478bd9Sstevel@tonic-gate 				np->action = CSIZE;
5577c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
5587c478bd9Sstevel@tonic-gate 		case INUM:
5597c478bd9Sstevel@tonic-gate 			np->first.ll = atoll(b);
5607c478bd9Sstevel@tonic-gate 			break;
5617c478bd9Sstevel@tonic-gate 
562da1a9cbeSjonb 		case CMIN:
5637c478bd9Sstevel@tonic-gate 		case CTIME:
564da1a9cbeSjonb 		case MMIN:
5657c478bd9Sstevel@tonic-gate 		case MTIME:
566da1a9cbeSjonb 		case AMIN:
5677c478bd9Sstevel@tonic-gate 		case ATIME:
5687c478bd9Sstevel@tonic-gate 		case LINKS:
5697c478bd9Sstevel@tonic-gate 			np->first.l = atol(b);
5707c478bd9Sstevel@tonic-gate 			break;
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 		case F_USER:
573b34cd89aSYuri Pankov 		case F_GROUP:
574b34cd89aSYuri Pankov 		case F_USERACL:
575b34cd89aSYuri Pankov 		case F_GROUPACL: {
5767c478bd9Sstevel@tonic-gate 			struct	passwd	*pw;
5777c478bd9Sstevel@tonic-gate 			struct	group *gr;
578ef497ae3SRich Burridge 			long value;
579ef497ae3SRich Burridge 			char *q;
580ef497ae3SRich Burridge 
581ef497ae3SRich Burridge 			value = -1;
582b34cd89aSYuri Pankov 			if (argp->action == F_USER ||
583b34cd89aSYuri Pankov 			    argp->action == F_USERACL) {
5847c478bd9Sstevel@tonic-gate 				if ((pw = getpwnam(b)) != 0)
585ef497ae3SRich Burridge 					value = (long)pw->pw_uid;
5867c478bd9Sstevel@tonic-gate 			} else {
5877c478bd9Sstevel@tonic-gate 				if ((gr = getgrnam(b)) != 0)
588ef497ae3SRich Burridge 					value = (long)gr->gr_gid;
5897c478bd9Sstevel@tonic-gate 			}
590ef497ae3SRich Burridge 			if (value == -1) {
591ef497ae3SRich Burridge 				errno = 0;
592ef497ae3SRich Burridge 				value = strtol(b, &q, 10);
593ef497ae3SRich Burridge 				if (errno != 0 || q == b || *q != '\0') {
5947c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr, gettext(
5957c478bd9Sstevel@tonic-gate 					    "%s: cannot find %s name\n"),
59627d3a169SToomas Soome 					    cmdname, *av);
5977c478bd9Sstevel@tonic-gate 					exit(1);
5987c478bd9Sstevel@tonic-gate 				}
5997c478bd9Sstevel@tonic-gate 			}
600ef497ae3SRich Burridge 			np->first.l = value;
6017c478bd9Sstevel@tonic-gate 			break;
6027c478bd9Sstevel@tonic-gate 		}
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 		case EXEC:
6057c478bd9Sstevel@tonic-gate 		case OK:
6067c478bd9Sstevel@tonic-gate 			walkflags &= ~FTW_CHDIR;
6077c478bd9Sstevel@tonic-gate 			np->first.ap = av;
6087c478bd9Sstevel@tonic-gate 			(*actionp)++;
6097c478bd9Sstevel@tonic-gate 			for (;;) {
6107c478bd9Sstevel@tonic-gate 				if ((b = *av) == 0) {
61127d3a169SToomas Soome 					(void) fprintf(stderr, gettext(
61227d3a169SToomas Soome 					    "%s: incomplete statement\n"),
61327d3a169SToomas Soome 					    cmdname);
6147c478bd9Sstevel@tonic-gate 					exit(1);
6157c478bd9Sstevel@tonic-gate 				}
6167c478bd9Sstevel@tonic-gate 				if (strcmp(b, ";") == 0) {
6177c478bd9Sstevel@tonic-gate 					*av = 0;
6187c478bd9Sstevel@tonic-gate 					break;
6197c478bd9Sstevel@tonic-gate 				} else if (strcmp(b, "{}") == 0)
6207c478bd9Sstevel@tonic-gate 					*av = dummyarg;
6217c478bd9Sstevel@tonic-gate 				else if (strcmp(b, "+") == 0 &&
62227d3a169SToomas Soome 				    av[-1] == dummyarg && np->action == EXEC) {
6237c478bd9Sstevel@tonic-gate 					av[-1] = 0;
6247c478bd9Sstevel@tonic-gate 					np->first.vp = varargs(np->first.ap);
6257c478bd9Sstevel@tonic-gate 					np->action = VARARGS;
6267c478bd9Sstevel@tonic-gate 					break;
6277c478bd9Sstevel@tonic-gate 				}
6287c478bd9Sstevel@tonic-gate 				av++;
6297c478bd9Sstevel@tonic-gate 			}
6307c478bd9Sstevel@tonic-gate 			break;
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 		case NAME:
633b34cd89aSYuri Pankov 		case INAME:
63405f32410SAndy Stormont 		case PATH:
63505f32410SAndy Stormont 		case IPATH:
6367c478bd9Sstevel@tonic-gate 			np->first.cp = b;
6377c478bd9Sstevel@tonic-gate 			break;
638b34cd89aSYuri Pankov 		case REGEX:
639b34cd89aSYuri Pankov 		case IREGEX: {
640b34cd89aSYuri Pankov 			int error;
641b34cd89aSYuri Pankov 			size_t errlen;
642b34cd89aSYuri Pankov 			char *errmsg;
643b34cd89aSYuri Pankov 
644b34cd89aSYuri Pankov 			if ((preg = realloc(preg, (npreg + 1) *
645b34cd89aSYuri Pankov 			    sizeof (regex_t))) == NULL)
646b34cd89aSYuri Pankov 				err(1, "realloc");
647b34cd89aSYuri Pankov 			if ((error = regcomp(&preg[npreg], b,
648b34cd89aSYuri Pankov 			    ((np->action == IREGEX) ? REG_ICASE : 0) |
649b34cd89aSYuri Pankov 			    ((Eflag) ? REG_EXTENDED : 0))) != 0) {
650b34cd89aSYuri Pankov 				errlen = regerror(error, &preg[npreg], NULL, 0);
651b34cd89aSYuri Pankov 				if ((errmsg = malloc(errlen)) == NULL)
652b34cd89aSYuri Pankov 					err(1, "malloc");
653b34cd89aSYuri Pankov 				(void) regerror(error, &preg[npreg], errmsg,
654b34cd89aSYuri Pankov 				    errlen);
655b34cd89aSYuri Pankov 				errx(1, gettext("RE error: %s"), errmsg);
656b34cd89aSYuri Pankov 			}
657b34cd89aSYuri Pankov 			npreg++;
658b34cd89aSYuri Pankov 			break;
659b34cd89aSYuri Pankov 		}
6607c478bd9Sstevel@tonic-gate 		case PERM:
6617c478bd9Sstevel@tonic-gate 			if (*b == '-')
6627c478bd9Sstevel@tonic-gate 				++b;
6637c478bd9Sstevel@tonic-gate 
66427d3a169SToomas Soome 			if (readmode(b) != 0) {
6657c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
6667c478bd9Sstevel@tonic-gate 				    "find: -perm: Bad permission string\n"));
6677c478bd9Sstevel@tonic-gate 				usage();
6687c478bd9Sstevel@tonic-gate 			}
6697c478bd9Sstevel@tonic-gate 			np->first.l = (long)getmode((mode_t)0);
6707c478bd9Sstevel@tonic-gate 			break;
6717c478bd9Sstevel@tonic-gate 		case TYPE:
6727c478bd9Sstevel@tonic-gate 			i = *b;
6737c478bd9Sstevel@tonic-gate 			np->first.l =
6747c478bd9Sstevel@tonic-gate 			    i == 'd' ? S_IFDIR :
6757c478bd9Sstevel@tonic-gate 			    i == 'b' ? S_IFBLK :
6767c478bd9Sstevel@tonic-gate 			    i == 'c' ? S_IFCHR :
6777c478bd9Sstevel@tonic-gate #ifdef S_IFIFO
6787c478bd9Sstevel@tonic-gate 			    i == 'p' ? S_IFIFO :
6797c478bd9Sstevel@tonic-gate #endif
6807c478bd9Sstevel@tonic-gate 			    i == 'f' ? S_IFREG :
6817c478bd9Sstevel@tonic-gate #ifdef S_IFLNK
6827c478bd9Sstevel@tonic-gate 			    i == 'l' ? S_IFLNK :
6837c478bd9Sstevel@tonic-gate #endif
6847c478bd9Sstevel@tonic-gate #ifdef S_IFSOCK
6857c478bd9Sstevel@tonic-gate 			    i == 's' ? S_IFSOCK :
6867c478bd9Sstevel@tonic-gate #endif
6877c478bd9Sstevel@tonic-gate #ifdef S_IFDOOR
6887c478bd9Sstevel@tonic-gate 			    i == 'D' ? S_IFDOOR :
6897c478bd9Sstevel@tonic-gate #endif
6907c478bd9Sstevel@tonic-gate 			    0;
6917c478bd9Sstevel@tonic-gate 			break;
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate 		case CPIO:
6947c478bd9Sstevel@tonic-gate 			if (walkflags & FTW_PHYS)
6957c478bd9Sstevel@tonic-gate 				com = cpio;
6967c478bd9Sstevel@tonic-gate 			else
6977c478bd9Sstevel@tonic-gate 				com = cpiol;
6987c478bd9Sstevel@tonic-gate 			goto common;
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 		case NCPIO: {
7017c478bd9Sstevel@tonic-gate 			FILE *fd;
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 			if (walkflags & FTW_PHYS)
7047c478bd9Sstevel@tonic-gate 				com = ncpio;
7057c478bd9Sstevel@tonic-gate 			else
7067c478bd9Sstevel@tonic-gate 				com = ncpiol;
7077c478bd9Sstevel@tonic-gate 		common:
7087c478bd9Sstevel@tonic-gate 			/* set up cpio */
7097c478bd9Sstevel@tonic-gate 			if ((fd = fopen(b, "w")) == NULL) {
7107c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
71127d3a169SToomas Soome 				    gettext("%s: cannot create %s\n"),
71227d3a169SToomas Soome 				    cmdname, b);
7137c478bd9Sstevel@tonic-gate 				exit(1);
7147c478bd9Sstevel@tonic-gate 			}
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate 			np->first.l = (long)cmdopen("cpio", com, "w", fd);
7177c478bd9Sstevel@tonic-gate 			(void) fclose(fd);
7187c478bd9Sstevel@tonic-gate 			walkflags |= FTW_DEPTH;
7197c478bd9Sstevel@tonic-gate 			np->action = CPIO;
7207c478bd9Sstevel@tonic-gate 		}
7217c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
7227c478bd9Sstevel@tonic-gate 		case PRINT:
723b34cd89aSYuri Pankov 		case PRINT0:
7247c478bd9Sstevel@tonic-gate 			(*actionp)++;
7257c478bd9Sstevel@tonic-gate 			break;
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 		case NEWER: {
7287c478bd9Sstevel@tonic-gate 			struct stat statb;
7297c478bd9Sstevel@tonic-gate 			if (stat(b, &statb) < 0) {
7307c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
73127d3a169SToomas Soome 				    gettext("%s: cannot access %s\n"),
73227d3a169SToomas Soome 				    cmdname, b);
7337c478bd9Sstevel@tonic-gate 				exit(1);
7347c478bd9Sstevel@tonic-gate 			}
7357c478bd9Sstevel@tonic-gate 			np->first.l = statb.st_mtime;
7367c478bd9Sstevel@tonic-gate 			np->second.i = '+';
7377c478bd9Sstevel@tonic-gate 			break;
7387c478bd9Sstevel@tonic-gate 		}
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate 		case PRUNE:
7417c478bd9Sstevel@tonic-gate 		case NOUSER:
7427c478bd9Sstevel@tonic-gate 		case NOGRP:
7437c478bd9Sstevel@tonic-gate 			break;
7447c478bd9Sstevel@tonic-gate 		case FSTYPE:
7457c478bd9Sstevel@tonic-gate 			np->first.cp = b;
7467c478bd9Sstevel@tonic-gate 			break;
7477c478bd9Sstevel@tonic-gate 		case LS:
7487c478bd9Sstevel@tonic-gate 			(*actionp)++;
7497c478bd9Sstevel@tonic-gate 			break;
7507c478bd9Sstevel@tonic-gate 		case XATTR:
7517c478bd9Sstevel@tonic-gate 			break;
7527c478bd9Sstevel@tonic-gate 		case ACL:
7537c478bd9Sstevel@tonic-gate 			break;
754b34cd89aSYuri Pankov 		case MAXDEPTH:
75527d3a169SToomas Soome 			maxdepth = (int)strtol(b, NULL, 10);
756b34cd89aSYuri Pankov 			break;
757b34cd89aSYuri Pankov 		case MINDEPTH:
75827d3a169SToomas Soome 			mindepth = (int)strtol(b, NULL, 10);
759b34cd89aSYuri Pankov 			break;
7607c478bd9Sstevel@tonic-gate 		}
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate 		oldnp = np++;
7637c478bd9Sstevel@tonic-gate 		oldnp->next = np;
7647c478bd9Sstevel@tonic-gate 	}
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 	if ((*av) || (wasop))
7677c478bd9Sstevel@tonic-gate 		goto err;
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 	if (paren_cnt != 0) {
77027d3a169SToomas Soome 		(void) fprintf(stderr, gettext("%s: unmatched '('\n"), cmdname);
7717c478bd9Sstevel@tonic-gate 		exit(1);
7727c478bd9Sstevel@tonic-gate 	}
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 	/* just before returning, save next free node from the list */
7757c478bd9Sstevel@tonic-gate 	freenode = oldnp->next;
7767c478bd9Sstevel@tonic-gate 	oldnp->next = 0;
7777c478bd9Sstevel@tonic-gate 	return (av-argv);
7787c478bd9Sstevel@tonic-gate err:
7797c478bd9Sstevel@tonic-gate 	if (*av)
7807c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
7817c478bd9Sstevel@tonic-gate 		    gettext("%s: bad option %s\n"), cmdname, *av);
7827c478bd9Sstevel@tonic-gate 	else
7837c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("%s: bad option\n"), cmdname);
7847c478bd9Sstevel@tonic-gate 	usage();
7857c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
7867c478bd9Sstevel@tonic-gate }
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate /*
7897c478bd9Sstevel@tonic-gate  * print out a usage message
7907c478bd9Sstevel@tonic-gate  */
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate static void
usage(void)7936c83d09fSrobbin usage(void)
7947c478bd9Sstevel@tonic-gate {
7957c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
796b34cd89aSYuri Pankov 	    gettext("%s: [-E] [-H | -L] path-list predicate-list\n"), cmdname);
7977c478bd9Sstevel@tonic-gate 	exit(1);
7987c478bd9Sstevel@tonic-gate }
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate /*
8017c478bd9Sstevel@tonic-gate  * This is the function that gets executed at each node
8027c478bd9Sstevel@tonic-gate  */
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate static int
execute(const char * name,const struct stat * statb,int type,struct FTW * state)80527d3a169SToomas Soome execute(const char *name, const struct stat *statb, int type, struct FTW *state)
8067c478bd9Sstevel@tonic-gate {
8077c478bd9Sstevel@tonic-gate 	struct Node *np = topnode;
8087c478bd9Sstevel@tonic-gate 	int val;
8097c478bd9Sstevel@tonic-gate 	time_t t;
8107c478bd9Sstevel@tonic-gate 	long l;
8117c478bd9Sstevel@tonic-gate 	long long ll;
8127c478bd9Sstevel@tonic-gate 	int not = 1;
81327d3a169SToomas Soome 	const char *filename;
814b34cd89aSYuri Pankov 	int cnpreg = 0;
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 	if (type == FTW_NS) {
8177c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("%s: stat() error %s: %s\n"),
81827d3a169SToomas Soome 		    cmdname, name, strerror(errno));
8197c478bd9Sstevel@tonic-gate 		error = 1;
8207c478bd9Sstevel@tonic-gate 		return (0);
8217c478bd9Sstevel@tonic-gate 	} else if (type == FTW_DNR) {
8227c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("%s: cannot read dir %s: %s\n"),
82327d3a169SToomas Soome 		    cmdname, name, strerror(errno));
8247c478bd9Sstevel@tonic-gate 		error = 1;
8250729abfeSRich Burridge 	} else if (type == FTW_SLN && lflag == 1) {
8267c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
82727d3a169SToomas Soome 		    gettext("%s: cannot follow symbolic link %s: %s\n"),
82827d3a169SToomas Soome 		    cmdname, name, strerror(errno));
8297c478bd9Sstevel@tonic-gate 		error = 1;
83068a94df1Scf 	} else if (type == FTW_DL) {
83168a94df1Scf 		(void) fprintf(stderr, gettext("%s: cycle detected for %s\n"),
83227d3a169SToomas Soome 		    cmdname, name);
83368a94df1Scf 		error = 1;
83468a94df1Scf 		return (0);
8357c478bd9Sstevel@tonic-gate 	}
8367c478bd9Sstevel@tonic-gate 
837b34cd89aSYuri Pankov 	if ((maxdepth != -1 && state->level > maxdepth) ||
838b34cd89aSYuri Pankov 	    (mindepth != -1 && state->level < mindepth))
839b34cd89aSYuri Pankov 		return (0);
840b34cd89aSYuri Pankov 
8417c478bd9Sstevel@tonic-gate 	while (np) {
8427c478bd9Sstevel@tonic-gate 		switch (np->action) {
8437c478bd9Sstevel@tonic-gate 		case NOT:
8447c478bd9Sstevel@tonic-gate 			not = !not;
8457c478bd9Sstevel@tonic-gate 			np = np->next;
8467c478bd9Sstevel@tonic-gate 			continue;
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 		case AND:
8497c478bd9Sstevel@tonic-gate 			np = np->next;
8507c478bd9Sstevel@tonic-gate 			continue;
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate 		case OR:
8537c478bd9Sstevel@tonic-gate 			if (np->first.np == np) {
8547c478bd9Sstevel@tonic-gate 				/*
8557c478bd9Sstevel@tonic-gate 				 * handle naked OR (no term on left hand side)
8567c478bd9Sstevel@tonic-gate 				 */
8577c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
8587c478bd9Sstevel@tonic-gate 				    gettext("%s: invalid -o construction\n"),
8597c478bd9Sstevel@tonic-gate 				    cmdname);
8607c478bd9Sstevel@tonic-gate 				exit(2);
8617c478bd9Sstevel@tonic-gate 			}
8627c478bd9Sstevel@tonic-gate 			/* FALLTHROUGH */
8637c478bd9Sstevel@tonic-gate 		case LPAREN: {
8647c478bd9Sstevel@tonic-gate 			struct Node *save = topnode;
8657c478bd9Sstevel@tonic-gate 			topnode = np->first.np;
8667c478bd9Sstevel@tonic-gate 			(void) execute(name, statb, type, state);
8677c478bd9Sstevel@tonic-gate 			val = lastval;
8687c478bd9Sstevel@tonic-gate 			topnode = save;
8697c478bd9Sstevel@tonic-gate 			if (np->action == OR) {
8707c478bd9Sstevel@tonic-gate 				if (val)
8717c478bd9Sstevel@tonic-gate 					return (0);
8727c478bd9Sstevel@tonic-gate 				val = 1;
8737c478bd9Sstevel@tonic-gate 			}
8747c478bd9Sstevel@tonic-gate 			break;
8757c478bd9Sstevel@tonic-gate 		}
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 		case LOCAL: {
8787c478bd9Sstevel@tonic-gate 			int	nremfs;
8797c478bd9Sstevel@tonic-gate 			val = 1;
8807c478bd9Sstevel@tonic-gate 			/*
8817c478bd9Sstevel@tonic-gate 			 * If file system type matches the remote
8827c478bd9Sstevel@tonic-gate 			 * file system type, then it is not local.
8837c478bd9Sstevel@tonic-gate 			 */
8847c478bd9Sstevel@tonic-gate 			for (nremfs = 0; nremfs < fstype_index; nremfs++) {
8857c478bd9Sstevel@tonic-gate 				if (strcmp(remote_fstypes[nremfs],
88627d3a169SToomas Soome 				    statb->st_fstype) == 0) {
8877c478bd9Sstevel@tonic-gate 					val = 0;
8887c478bd9Sstevel@tonic-gate 					break;
8897c478bd9Sstevel@tonic-gate 				}
8907c478bd9Sstevel@tonic-gate 			}
8917c478bd9Sstevel@tonic-gate 			break;
8927c478bd9Sstevel@tonic-gate 		}
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate 		case TYPE:
8957c478bd9Sstevel@tonic-gate 			l = (long)statb->st_mode&S_IFMT;
8967c478bd9Sstevel@tonic-gate 			goto num;
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate 		case PERM:
8997c478bd9Sstevel@tonic-gate 			l = (long)statb->st_mode&07777;
9007c478bd9Sstevel@tonic-gate 			if (np->second.i == '-')
9017c478bd9Sstevel@tonic-gate 				val = ((l&np->first.l) == np->first.l);
9027c478bd9Sstevel@tonic-gate 			else
9037c478bd9Sstevel@tonic-gate 				val = (l == np->first.l);
9047c478bd9Sstevel@tonic-gate 			break;
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 		case INUM:
9077c478bd9Sstevel@tonic-gate 			ll = (long long)statb->st_ino;
9087c478bd9Sstevel@tonic-gate 			goto llnum;
9097c478bd9Sstevel@tonic-gate 		case NEWER:
9107c478bd9Sstevel@tonic-gate 			l = statb->st_mtime;
9117c478bd9Sstevel@tonic-gate 			goto num;
9127c478bd9Sstevel@tonic-gate 		case ATIME:
9137c478bd9Sstevel@tonic-gate 			t = statb->st_atime;
9147c478bd9Sstevel@tonic-gate 			goto days;
9157c478bd9Sstevel@tonic-gate 		case CTIME:
9167c478bd9Sstevel@tonic-gate 			t = statb->st_ctime;
9177c478bd9Sstevel@tonic-gate 			goto days;
9187c478bd9Sstevel@tonic-gate 		case MTIME:
9197c478bd9Sstevel@tonic-gate 			t = statb->st_mtime;
9207c478bd9Sstevel@tonic-gate 		days:
9217c478bd9Sstevel@tonic-gate 			l = (now-t)/A_DAY;
9227c478bd9Sstevel@tonic-gate 			goto num;
923da1a9cbeSjonb 		case MMIN:
924da1a9cbeSjonb 			t = statb->st_mtime;
925da1a9cbeSjonb 			goto mins;
926da1a9cbeSjonb 		case AMIN:
927da1a9cbeSjonb 			t = statb->st_atime;
928da1a9cbeSjonb 			goto mins;
929da1a9cbeSjonb 		case CMIN:
930da1a9cbeSjonb 			t = statb->st_ctime;
931da1a9cbeSjonb 			goto mins;
932da1a9cbeSjonb 		mins:
933da1a9cbeSjonb 			l = (now-t)/A_MIN;
934da1a9cbeSjonb 			goto num;
9357c478bd9Sstevel@tonic-gate 		case CSIZE:
9367c478bd9Sstevel@tonic-gate 			ll = (long long)statb->st_size;
9377c478bd9Sstevel@tonic-gate 			goto llnum;
9387c478bd9Sstevel@tonic-gate 		case SIZE:
9397c478bd9Sstevel@tonic-gate 			ll = (long long)round(statb->st_size, BLKSIZ)/BLKSIZ;
9407c478bd9Sstevel@tonic-gate 			goto llnum;
9417c478bd9Sstevel@tonic-gate 		case F_USER:
9427c478bd9Sstevel@tonic-gate 			l = (long)statb->st_uid;
9437c478bd9Sstevel@tonic-gate 			goto num;
9447c478bd9Sstevel@tonic-gate 		case F_GROUP:
9457c478bd9Sstevel@tonic-gate 			l = (long)statb->st_gid;
9467c478bd9Sstevel@tonic-gate 			goto num;
9477c478bd9Sstevel@tonic-gate 		case LINKS:
9487c478bd9Sstevel@tonic-gate 			l = (long)statb->st_nlink;
9497c478bd9Sstevel@tonic-gate 			goto num;
9507c478bd9Sstevel@tonic-gate 		llnum:
9517c478bd9Sstevel@tonic-gate 			if (np->second.i == '+')
9527c478bd9Sstevel@tonic-gate 				val = (ll > np->first.ll);
9537c478bd9Sstevel@tonic-gate 			else if (np->second.i == '-')
9547c478bd9Sstevel@tonic-gate 				val = (ll < np->first.ll);
9557c478bd9Sstevel@tonic-gate 			else
9567c478bd9Sstevel@tonic-gate 				val = (ll == np->first.ll);
9577c478bd9Sstevel@tonic-gate 			break;
9587c478bd9Sstevel@tonic-gate 		num:
9597c478bd9Sstevel@tonic-gate 			if (np->second.i == '+')
9607c478bd9Sstevel@tonic-gate 				val = (l > np->first.l);
9617c478bd9Sstevel@tonic-gate 			else if (np->second.i == '-')
9627c478bd9Sstevel@tonic-gate 				val = (l < np->first.l);
9637c478bd9Sstevel@tonic-gate 			else
9647c478bd9Sstevel@tonic-gate 				val = (l == np->first.l);
9657c478bd9Sstevel@tonic-gate 			break;
9667c478bd9Sstevel@tonic-gate 		case OK:
9677c478bd9Sstevel@tonic-gate 			val = ok(name, np->first.ap);
9687c478bd9Sstevel@tonic-gate 			break;
9697c478bd9Sstevel@tonic-gate 		case EXEC:
970d35170d6Srm 			val = doexec(name, np->first.ap, NULL);
9717c478bd9Sstevel@tonic-gate 			break;
972ab823b7fSPrasad Joshi 		case DELETE:
973ab823b7fSPrasad Joshi 			val = dodelete(name, statb, state);
974ab823b7fSPrasad Joshi 			break;
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 		case VARARGS: {
9777c478bd9Sstevel@tonic-gate 			struct Arglist *ap = np->first.vp;
9787c478bd9Sstevel@tonic-gate 			char *cp;
9797c478bd9Sstevel@tonic-gate 			cp = ap->nextstr - (strlen(name)+1);
9807c478bd9Sstevel@tonic-gate 			if (cp >= (char *)(ap->nextvar+3)) {
9817c478bd9Sstevel@tonic-gate 				/* there is room just copy the name */
9827c478bd9Sstevel@tonic-gate 				val = 1;
9837c478bd9Sstevel@tonic-gate 				(void) strcpy(cp, name);
9847c478bd9Sstevel@tonic-gate 				*ap->nextvar++ = cp;
9857c478bd9Sstevel@tonic-gate 				ap->nextstr = cp;
9867c478bd9Sstevel@tonic-gate 			} else {
9877c478bd9Sstevel@tonic-gate 				/* no more room, exec command */
98827d3a169SToomas Soome 				*ap->nextvar++ = (char *)name;
9897c478bd9Sstevel@tonic-gate 				*ap->nextvar = 0;
9907c478bd9Sstevel@tonic-gate 				val = 1;
99127d3a169SToomas Soome 				(void) doexec(NULL, ap->arglist,
992d35170d6Srm 				    &exec_exitcode);
9937c478bd9Sstevel@tonic-gate 				ap->nextstr = ap->end;
9947c478bd9Sstevel@tonic-gate 				ap->nextvar = ap->firstvar;
9957c478bd9Sstevel@tonic-gate 			}
9967c478bd9Sstevel@tonic-gate 			break;
9977c478bd9Sstevel@tonic-gate 		}
9987c478bd9Sstevel@tonic-gate 
9997c478bd9Sstevel@tonic-gate 		case DEPTH:
10007c478bd9Sstevel@tonic-gate 		case MOUNT:
10017c478bd9Sstevel@tonic-gate 		case FOLLOW:
10027c478bd9Sstevel@tonic-gate 			val = 1;
10037c478bd9Sstevel@tonic-gate 			break;
10047c478bd9Sstevel@tonic-gate 
1005b34cd89aSYuri Pankov 		case NAME:
100605f32410SAndy Stormont 		case INAME:
100705f32410SAndy Stormont 		case PATH:
100805f32410SAndy Stormont 		case IPATH: {
100905f32410SAndy Stormont 			char *path;
101005f32410SAndy Stormont 			int fnmflags = 0;
101105f32410SAndy Stormont 
101205f32410SAndy Stormont 			if (np->action == INAME || np->action == IPATH)
101305f32410SAndy Stormont 				fnmflags = FNM_IGNORECASE;
10149ab6dc39Schin 
10159ab6dc39Schin 			/*
10169ab6dc39Schin 			 * basename(3c) may modify name, so
10179ab6dc39Schin 			 * we need to pass another string
10189ab6dc39Schin 			 */
101905f32410SAndy Stormont 			if ((path = strdup(name)) == NULL) {
10209ab6dc39Schin 				(void) fprintf(stderr,
10219ab6dc39Schin 				    gettext("%s: cannot strdup() %s: %s\n"),
10226b238a5aSchin 				    cmdname, name, strerror(errno));
10239ab6dc39Schin 				exit(2);
10249ab6dc39Schin 			}
10257c478bd9Sstevel@tonic-gate 			/*
10267c478bd9Sstevel@tonic-gate 			 * XPG4 find should not treat a leading '.' in a
10277c478bd9Sstevel@tonic-gate 			 * filename specially for pattern matching.
10287c478bd9Sstevel@tonic-gate 			 * /usr/bin/find  will not pattern match a leading
10297c478bd9Sstevel@tonic-gate 			 * '.' in a filename, unless '.' is explicitly
10307c478bd9Sstevel@tonic-gate 			 * specified.
1031*f3a525d9SJohn Levon 			 *
1032*f3a525d9SJohn Levon 			 * The legacy behavior makes no sense for PATH.
10337c478bd9Sstevel@tonic-gate 			 */
1034b34cd89aSYuri Pankov #ifndef XPG4
1035*f3a525d9SJohn Levon 			if (np->action == NAME || np->action == INAME)
1036*f3a525d9SJohn Levon 				fnmflags |= FNM_PERIOD;
10377c478bd9Sstevel@tonic-gate #endif
103805f32410SAndy Stormont 
103905f32410SAndy Stormont 			val = !fnmatch(np->first.cp,
104027d3a169SToomas Soome 			    (np->action == NAME || np->action == INAME) ?
104127d3a169SToomas Soome 			    basename(path) : path, fnmflags);
104205f32410SAndy Stormont 			free(path);
10437c478bd9Sstevel@tonic-gate 			break;
10447c478bd9Sstevel@tonic-gate 		}
10457c478bd9Sstevel@tonic-gate 
10467c478bd9Sstevel@tonic-gate 		case PRUNE:
10477c478bd9Sstevel@tonic-gate 			if (type == FTW_D)
10487c478bd9Sstevel@tonic-gate 				state->quit = FTW_PRUNE;
10497c478bd9Sstevel@tonic-gate 			val = 1;
10507c478bd9Sstevel@tonic-gate 			break;
10517c478bd9Sstevel@tonic-gate 		case NOUSER:
10527c478bd9Sstevel@tonic-gate 			val = ((getpwuid(statb->st_uid)) == 0);
10537c478bd9Sstevel@tonic-gate 			break;
10547c478bd9Sstevel@tonic-gate 		case NOGRP:
10557c478bd9Sstevel@tonic-gate 			val = ((getgrgid(statb->st_gid)) == 0);
1056