1/*-
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Cimarron D. Taylor of the University of California, Berkeley.
7 *
8 * Redistribution and use in source and binary forms, with or without
--- 26 unchanged lines hidden (view full) ---
35 */
36
37#ifndef lint
38#if 0
39static const char sccsid[] = "@(#)function.c 8.10 (Berkeley) 5/4/95";
40#endif
41#endif /* not lint */
42#include <sys/cdefs.h>
43__FBSDID("$FreeBSD: head/usr.bin/find/function.c 97736 2002-06-02 12:57:41Z tjr $");
44
45#include <sys/param.h>
46#include <sys/ucred.h>
47#include <sys/stat.h>
48#include <sys/wait.h>
49#include <sys/mount.h>
50#include <sys/timeb.h>
51
52#include <dirent.h>
53#include <err.h>
54#include <errno.h>
55#include <fnmatch.h>
56#include <fts.h>
57#include <grp.h>
58#include <limits.h>
59#include <pwd.h>
60#include <regex.h>
61#include <stdio.h>
62#include <stdlib.h>
63#include <string.h>
64#include <unistd.h>
65
66#include "find.h"
--- 457 unchanged lines hidden (view full) ---
524 FTSENT *entry;
525{
526 extern int dotfd;
527 int cnt;
528 pid_t pid;
529 int status;
530 char *file;
531
532 if (entry == NULL && plan->flags & F_EXECPLUS) {
533 if (plan->e_ppos == plan->e_pbnum)
534 return (1);
535 plan->e_argv[plan->e_ppos] = NULL;
536 goto doexec;
537 }
538
539 /* XXX - if file/dir ends in '/' this will not work -- can it? */
540 if ((plan->flags & F_EXECDIR) && \
541 (file = strrchr(entry->fts_path, '/')))
542 file++;
543 else
544 file = entry->fts_path;
545
546 if (plan->flags & F_EXECPLUS) {
547 if ((plan->e_argv[plan->e_ppos] = strdup(file)) == NULL)
548 err(1, NULL);
549 plan->e_len[plan->e_ppos] = strlen(file);
550 plan->e_psize += plan->e_len[plan->e_ppos];
551 if (++plan->e_ppos < plan->e_pnummax &&
552 plan->e_psize < plan->e_psizemax)
553 return (1);
554 plan->e_argv[plan->e_ppos] = NULL;
555 } else {
556 for (cnt = 0; plan->e_argv[cnt]; ++cnt)
557 if (plan->e_len[cnt])
558 brace_subst(plan->e_orig[cnt],
559 &plan->e_argv[cnt], file,
560 plan->e_len[cnt]);
561 }
562
563doexec: if ((plan->flags & F_NEEDOK) && !queryuser(plan->e_argv))
564 return 0;
565
566 /* make sure find output is interspersed correctly with subprocesses */
567 fflush(stdout);
568 fflush(stderr);
569
570 switch (pid = fork()) {
571 case -1:
--- 4 unchanged lines hidden (view full) ---
576 if (!(plan->flags & F_EXECDIR) && fchdir(dotfd)) {
577 warn("chdir");
578 _exit(1);
579 }
580 execvp(plan->e_argv[0], plan->e_argv);
581 warn("%s", plan->e_argv[0]);
582 _exit(1);
583 }
584 if (plan->flags & F_EXECPLUS) {
585 while (--plan->e_ppos >= plan->e_pbnum)
586 free(plan->e_argv[plan->e_ppos]);
587 plan->e_ppos = plan->e_pbnum;
588 plan->e_psize = plan->e_pbsize;
589 }
590 pid = waitpid(pid, &status, 0);
591 return (pid != -1 && WIFEXITED(status) && !WEXITSTATUS(status));
592}
593
594/*
595 * c_exec, c_execdir, c_ok --
596 * build three parallel arrays, one with pointers to the strings passed
597 * on the command line, one with (possibly duplicated) pointers to the
598 * argv array, and one with integer values that are lengths of the
599 * strings, but also flags meaning that the string has to be massaged.
600 */
601PLAN *
602c_exec(option, argvp)
603 OPTION *option;
604 char ***argvp;
605{
606 PLAN *new; /* node returned */
607 long argmax;
608 int cnt, i;
609 char **argv, **ap, *p;
610
611 /* XXX - was in c_execdir, but seems unnecessary!?
612 ftsoptions &= ~FTS_NOSTAT;
613 */
614 isoutput = 1;
615
616 /* XXX - this is a change from the previous coding */
617 new = palloc(option);
618
619 for (ap = argv = *argvp;; ++ap) {
620 if (!*ap)
621 errx(1,
622 "%s: no terminating \";\"", option->name);
623 if (**ap == ';')
624 break;
625 if (**ap == '+' && ap != argv && strcmp(*(ap - 1), "{}") == 0) {
626 new->flags |= F_EXECPLUS;
627 break;
628 }
629 }
630
631 if (ap == argv)
632 errx(1, "%s: no command specified", option->name);
633
634 cnt = ap - *argvp + 1;
635 if (new->flags & F_EXECPLUS) {
636 new->e_ppos = new->e_pbnum = cnt - 2;
637 if ((argmax = sysconf(_SC_ARG_MAX)) == -1) {
638 warn("sysconf(_SC_ARG_MAX)");
639 argmax = _POSIX_ARG_MAX;
640 }
641 /*
642 * Estimate the maximum number of arguments as {ARG_MAX}/10,
643 * and the maximum number of bytes to use for arguments as
644 * {ARG_MAX}*(3/4).
645 */
646 new->e_pnummax = argmax / 10;
647 new->e_psizemax = (argmax / 4) * 3;
648 new->e_pbsize = 0;
649 cnt += new->e_pnummax + 1;
650 }
651 if ((new->e_argv = malloc(cnt * sizeof(char *))) == NULL)
652 err(1, NULL);
653 if ((new->e_orig = malloc(cnt * sizeof(char *))) == NULL)
654 err(1, NULL);
655 if ((new->e_len = malloc(cnt * sizeof(int))) == NULL)
656 err(1, NULL);
657
658 for (argv = *argvp, cnt = 0; argv < ap; ++argv, ++cnt) {
659 new->e_orig[cnt] = *argv;
660 if (new->flags & F_EXECPLUS)
661 new->e_pbsize += strlen(*argv) + 1;
662 for (p = *argv; *p; ++p)
663 if (!(new->flags & F_EXECPLUS) && p[0] == '{' &&
664 p[1] == '}') {
665 if ((new->e_argv[cnt] =
666 malloc(MAXPATHLEN)) == NULL)
667 err(1, NULL);
668 new->e_len[cnt] = MAXPATHLEN;
669 break;
670 }
671 if (!*p) {
672 new->e_argv[cnt] = *argv;
673 new->e_len[cnt] = 0;
674 }
675 }
676 if (new->flags & F_EXECPLUS) {
677 new->e_psize = new->e_pbsize;
678 cnt--;
679 for (i = 0; i < new->e_pnummax; i++) {
680 new->e_argv[cnt] = NULL;
681 new->e_len[cnt] = 0;
682 cnt++;
683 }
684 argv = ap;
685 goto done;
686 }
687 new->e_argv[cnt] = new->e_orig[cnt] = NULL;
688
689done: *argvp = argv + 1;
690 return new;
691}
692
693int
694f_flags(plan, entry)
695 PLAN *plan;
696 FTSENT *entry;
697{
--- 909 unchanged lines hidden ---
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Cimarron D. Taylor of the University of California, Berkeley.
7 *
8 * Redistribution and use in source and binary forms, with or without
--- 26 unchanged lines hidden (view full) ---
35 */
36
37#ifndef lint
38#if 0
39static const char sccsid[] = "@(#)function.c 8.10 (Berkeley) 5/4/95";
40#endif
41#endif /* not lint */
42#include <sys/cdefs.h>
43__FBSDID("$FreeBSD: head/usr.bin/find/function.c 97736 2002-06-02 12:57:41Z tjr $");
44
45#include <sys/param.h>
46#include <sys/ucred.h>
47#include <sys/stat.h>
48#include <sys/wait.h>
49#include <sys/mount.h>
50#include <sys/timeb.h>
51
52#include <dirent.h>
53#include <err.h>
54#include <errno.h>
55#include <fnmatch.h>
56#include <fts.h>
57#include <grp.h>
58#include <limits.h>
59#include <pwd.h>
60#include <regex.h>
61#include <stdio.h>
62#include <stdlib.h>
63#include <string.h>
64#include <unistd.h>
65
66#include "find.h"
--- 457 unchanged lines hidden (view full) ---
524 FTSENT *entry;
525{
526 extern int dotfd;
527 int cnt;
528 pid_t pid;
529 int status;
530 char *file;
531
532 if (entry == NULL && plan->flags & F_EXECPLUS) {
533 if (plan->e_ppos == plan->e_pbnum)
534 return (1);
535 plan->e_argv[plan->e_ppos] = NULL;
536 goto doexec;
537 }
538
539 /* XXX - if file/dir ends in '/' this will not work -- can it? */
540 if ((plan->flags & F_EXECDIR) && \
541 (file = strrchr(entry->fts_path, '/')))
542 file++;
543 else
544 file = entry->fts_path;
545
546 if (plan->flags & F_EXECPLUS) {
547 if ((plan->e_argv[plan->e_ppos] = strdup(file)) == NULL)
548 err(1, NULL);
549 plan->e_len[plan->e_ppos] = strlen(file);
550 plan->e_psize += plan->e_len[plan->e_ppos];
551 if (++plan->e_ppos < plan->e_pnummax &&
552 plan->e_psize < plan->e_psizemax)
553 return (1);
554 plan->e_argv[plan->e_ppos] = NULL;
555 } else {
556 for (cnt = 0; plan->e_argv[cnt]; ++cnt)
557 if (plan->e_len[cnt])
558 brace_subst(plan->e_orig[cnt],
559 &plan->e_argv[cnt], file,
560 plan->e_len[cnt]);
561 }
562
563doexec: if ((plan->flags & F_NEEDOK) && !queryuser(plan->e_argv))
564 return 0;
565
566 /* make sure find output is interspersed correctly with subprocesses */
567 fflush(stdout);
568 fflush(stderr);
569
570 switch (pid = fork()) {
571 case -1:
--- 4 unchanged lines hidden (view full) ---
576 if (!(plan->flags & F_EXECDIR) && fchdir(dotfd)) {
577 warn("chdir");
578 _exit(1);
579 }
580 execvp(plan->e_argv[0], plan->e_argv);
581 warn("%s", plan->e_argv[0]);
582 _exit(1);
583 }
584 if (plan->flags & F_EXECPLUS) {
585 while (--plan->e_ppos >= plan->e_pbnum)
586 free(plan->e_argv[plan->e_ppos]);
587 plan->e_ppos = plan->e_pbnum;
588 plan->e_psize = plan->e_pbsize;
589 }
590 pid = waitpid(pid, &status, 0);
591 return (pid != -1 && WIFEXITED(status) && !WEXITSTATUS(status));
592}
593
594/*
595 * c_exec, c_execdir, c_ok --
596 * build three parallel arrays, one with pointers to the strings passed
597 * on the command line, one with (possibly duplicated) pointers to the
598 * argv array, and one with integer values that are lengths of the
599 * strings, but also flags meaning that the string has to be massaged.
600 */
601PLAN *
602c_exec(option, argvp)
603 OPTION *option;
604 char ***argvp;
605{
606 PLAN *new; /* node returned */
607 long argmax;
608 int cnt, i;
609 char **argv, **ap, *p;
610
611 /* XXX - was in c_execdir, but seems unnecessary!?
612 ftsoptions &= ~FTS_NOSTAT;
613 */
614 isoutput = 1;
615
616 /* XXX - this is a change from the previous coding */
617 new = palloc(option);
618
619 for (ap = argv = *argvp;; ++ap) {
620 if (!*ap)
621 errx(1,
622 "%s: no terminating \";\"", option->name);
623 if (**ap == ';')
624 break;
625 if (**ap == '+' && ap != argv && strcmp(*(ap - 1), "{}") == 0) {
626 new->flags |= F_EXECPLUS;
627 break;
628 }
629 }
630
631 if (ap == argv)
632 errx(1, "%s: no command specified", option->name);
633
634 cnt = ap - *argvp + 1;
635 if (new->flags & F_EXECPLUS) {
636 new->e_ppos = new->e_pbnum = cnt - 2;
637 if ((argmax = sysconf(_SC_ARG_MAX)) == -1) {
638 warn("sysconf(_SC_ARG_MAX)");
639 argmax = _POSIX_ARG_MAX;
640 }
641 /*
642 * Estimate the maximum number of arguments as {ARG_MAX}/10,
643 * and the maximum number of bytes to use for arguments as
644 * {ARG_MAX}*(3/4).
645 */
646 new->e_pnummax = argmax / 10;
647 new->e_psizemax = (argmax / 4) * 3;
648 new->e_pbsize = 0;
649 cnt += new->e_pnummax + 1;
650 }
651 if ((new->e_argv = malloc(cnt * sizeof(char *))) == NULL)
652 err(1, NULL);
653 if ((new->e_orig = malloc(cnt * sizeof(char *))) == NULL)
654 err(1, NULL);
655 if ((new->e_len = malloc(cnt * sizeof(int))) == NULL)
656 err(1, NULL);
657
658 for (argv = *argvp, cnt = 0; argv < ap; ++argv, ++cnt) {
659 new->e_orig[cnt] = *argv;
660 if (new->flags & F_EXECPLUS)
661 new->e_pbsize += strlen(*argv) + 1;
662 for (p = *argv; *p; ++p)
663 if (!(new->flags & F_EXECPLUS) && p[0] == '{' &&
664 p[1] == '}') {
665 if ((new->e_argv[cnt] =
666 malloc(MAXPATHLEN)) == NULL)
667 err(1, NULL);
668 new->e_len[cnt] = MAXPATHLEN;
669 break;
670 }
671 if (!*p) {
672 new->e_argv[cnt] = *argv;
673 new->e_len[cnt] = 0;
674 }
675 }
676 if (new->flags & F_EXECPLUS) {
677 new->e_psize = new->e_pbsize;
678 cnt--;
679 for (i = 0; i < new->e_pnummax; i++) {
680 new->e_argv[cnt] = NULL;
681 new->e_len[cnt] = 0;
682 cnt++;
683 }
684 argv = ap;
685 goto done;
686 }
687 new->e_argv[cnt] = new->e_orig[cnt] = NULL;
688
689done: *argvp = argv + 1;
690 return new;
691}
692
693int
694f_flags(plan, entry)
695 PLAN *plan;
696 FTSENT *entry;
697{
--- 909 unchanged lines hidden ---