Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 10 Mar 2002 08:51:40 -0700
From:      Peter Sanchez <fut0n@linuxforlesbians.org>
To:        wolfram schneider <wosch@FreeBSD.org>, freebsd-bugs@FreeBSD.org
Subject:   Re: bin/35719: which(1) ignore empty components of $PATH.
Message-ID:  <20020310085139.B52034@sushi.linuxforlesbians.org>
In-Reply-To: <200203092323.g29NNsl91233@freefall.freebsd.org>; from wosch@FreeBSD.org on Sat, Mar 09, 2002 at 03:23:54PM -0800
References:  <200203092323.g29NNsl91233@freefall.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
I wrote a which(1) replacement in C but the current version in -current
already was committed. My version addressed all the issues you posted
about -current which(1). Here is my code again, maybe the gods will take 
another peak at it:


/*
 * which - a which utility for Unix
 *
 * SYNOPSIS: For FreeBSD-4.x and later
 *
 * DESCRIPTION:
 * Utility to get the full system path of an executable in the 
 * users PATH environment variable.
 *
 * Works for:
 *      FreeBSD 4.x and probably most earlier versions
 *
 * AUTHOR:      Peter Sanchez <psanchez@packet-addiction.org>
 */

#ifndef lint
static const char rcsid[] = "$FreeBSD$";
#endif /* not lint */

#include <sys/types.h>
#include <sys/stat.h>

#include <err.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include <sysexits.h>

#define NGROUPS 15

struct pathinfo {
        struct  pathinfo *next;
        char    *path;
};

struct pathinfo *all = NULL;
int found = 1;

void
usage(void)
{
        (void)fprintf(stderr, "usage: which [-a] [-s] program ...\n");
        exit(EX_USAGE);
}

int
file_exists(char *file)
{
        struct stat info;
        int check;

        check = stat(file, &info);
        if (check == -1)
                return check; /* file doesnt exist */

        return (info.st_mode & S_IFREG && access(file, X_OK) == 0) ? check : -1;
}

void
losepath(void)
{
        struct pathinfo *tmp;

        while (all != NULL) {
                tmp = all->next;
                free(all);
                all = tmp;
        }
}

void
findpath(void)
{
        struct pathinfo *cur = NULL;
        char *userpath = getenv("PATH");
    
        if (userpath == NULL || strlen(userpath) == 0)
                errx(EX_OSERR, "No PATH variable.");

        all = (struct pathinfo *)malloc(sizeof(struct pathinfo));
        if (all == NULL)
                err(EX_OSERR, (char *)NULL);
                /* NOTREACHED */

        cur = all;

        while ((cur->path = strsep(&userpath, ":")) != NULL) {
                cur->next = (struct pathinfo *)malloc(sizeof(struct pathinfo));
                if (cur->next == NULL) {
                        losepath();
                        err(EX_OSERR, (char *)NULL);
                        /* NOTREACHED */
                }

                if (strlen(cur->path) == 0) {
                        /* warnx("PATH element of 0 length."); */
                        cur->path = ".";
                }

                cur = cur->next;
        }
        cur->next = NULL;
        cur = all;
}

void
findprog(char *prog, int aflag, int sflag)
{
        struct pathinfo *tmp;
        char *tmpbuf;

        tmp = all;
        while (all != NULL) {
                if (all->path == NULL)
                        break;
                if (strchr(prog, '/')) {
                        tmpbuf = strdup(prog);
                        if (tmpbuf == NULL) {
                                losepath();
                                err(EX_OSERR, (char *)NULL);
                                /* NOTREACHED */
                        }
                }
                else {
                        tmpbuf = malloc(strlen(all->path) + (strlen(prog) + 1));
                        if (tmpbuf == NULL) {
                                losepath();
                                err(EX_OSERR, (char *)NULL);
                                /* NOTREACHED */
                        }
                        sprintf(tmpbuf, "%s/%s", all->path, prog);
                }

                if (file_exists(tmpbuf) == 0) {
                        found = 0;
                        if (sflag && aflag) ;
                        else if (sflag && !aflag) {
                                all = tmp;
                                free(tmpbuf);
                                return;
                        }
                        else if (aflag && !sflag)
                                (void)printf("%s\n", tmpbuf);
                        else {
                                (void)printf("%s\n", tmpbuf);
                                all = tmp;
                                free(tmpbuf);
                                return;
                        }
                }
                all = all->next;
                free(tmpbuf);
        }
        all = tmp;
}

int
main(int argc, char *argv[])
{
        char ch;
        int aflag, sflag, i;

        aflag = sflag = 0;
        if (argc < 2)
                exit(EX_USAGE);
       
        while ((ch = getopt(argc, argv, "ash?")) != -1) {
                switch (ch) {
                        case 'a':
                                aflag = 1;
                                break;
                        case 's':
                                sflag = 1;
                                break;
                        case 'h':
                        case '?':
                        default:
                                usage();
                                /* NOTREACHED */
                }
        }
        argc -= optind;
        argv += optind;
    
        findpath();
        for (i = 0; i < argc; i++)
                findprog(argv[i], aflag, sflag);
    
        losepath();
        return sflag ? found : 0;
}


On Sat, Mar 09, 2002 at 03:23:54PM -0800, wolfram schneider wrote:
> 
> >Number:         35719
> >Category:       bin
> >Synopsis:       which(1) ignore empty components of $PATH.
> >Confidential:   no
> >Severity:       non-critical
> >Priority:       low
> >Responsible:    freebsd-bugs
> >State:          open
> >Quarter:        
> >Keywords:       
> >Date-Required:
> >Class:          sw-bug
> >Submitter-Id:   current-users
> >Arrival-Date:   Sat Mar 09 15:30:00 PST 2002
> >Closed-Date:
> >Last-Modified:
> >Originator:     wolfram schneider
> >Release:        
> >Organization:
> >Environment:
> >Description:
>       The new c version of which(1) command 
> ignore empty components of $PATH.
> 
> $ cd /bin
> $ env PATH=: which date
> $ echo $?
> 1
> 
> 
> It should print:
> ./date
> >How-To-Repeat:
>       
> >Fix:
>       
> >Release-Note:
> >Audit-Trail:
> >Unformatted:
> 
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-bugs" in the body of the message

-- 
Peter Sanchez, aka fut0n	|	"The ability to read is what
 - fut0n@linuxforlesbians.org	|	 distinguishes Unix users from
 - www.linuxforlesbians.org	|	 those of more popular platforms."
 - FreeBSD or DIE		|			- John Lasser

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020310085139.B52034>