Date: Thu, 13 Dec 2001 13:00:01 -0800 (PST) From: Peter Sanchez <fut0n@linuxforlesbians.org> To: freebsd-bugs@FreeBSD.org Subject: Re: bin/32807: which utility replacement in C Message-ID: <200112132100.fBDL01r64612@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/32807; it has been noted by GNATS.
From: Peter Sanchez <fut0n@linuxforlesbians.org>
To: David Hill <david@visual-network.net>,
freebsd-gnats-submit@FreeBSD.org
Cc:
Subject: Re: bin/32807: which utility replacement in C
Date: Thu, 13 Dec 2001 13:56:33 -0700
Now I feel like an idiot. I knew about that bug and simple forgot about
it. Here is the updated source. Sorry about that.
Peter
-----------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#define NGROUPS 15
struct pathinfo
{
char *path;
struct pathinfo *next;
};
struct pathinfo *all = NULL;
struct passwd *pw;
uid_t uid;
int found = 1, gfail = 0;
int groups[NGROUPS + 1], ngroups = (NGROUPS + 1);
void
printusage(bin)
char *bin;
{
fprintf(stderr,"usage: %s [-a] [-s] program ...\n",bin);
return;
}
int
file_exists(file)
char *file;
{
struct stat info;
int check, i;
check = stat(file,&info);
if(check == -1)
return check; /* file doesnt exist */
if(S_ISDIR(info.st_mode))
return -1; /* file is a directory */
/*
* I did not use access() here cause of man page warnings that
* it is a potential security risk and shoule NEVER be used. Not
* quit sure on how it can be a security risk, but I worked around
* it anyways.
*/
if(info.st_uid == uid && info.st_mode & S_IFREG && info.st_mode & S_IXUSR)
return check; /* user executable */
if(gfail)
{
if(info.st_gid == pw->pw_gid && info.st_mode & S_IFREG &&
info.st_mode & S_IXGRP)
return check; /* group executable */
}
else
{
for(i = 0; i < ngroups; i++)
{
if(info.st_gid == groups[i] && info.st_mode & S_IFREG &&
info.st_mode & S_IXGRP)
return check; /* group executable */
}
}
if(info.st_mode & S_IFREG && info.st_mode & S_IXOTH)
return check; /* other executable */
else
return -1;
}
void
losepath(void)
{
struct pathinfo *tmp;
while(all != NULL)
{
tmp = all->next;
free(all);
all = tmp;
}
return;
}
void
findpath(void)
{
struct pathinfo *cur = NULL;
char *userpath = getenv("PATH");
int i, x;
if(userpath == NULL)
exit(1);
all = (struct pathinfo *)malloc((unsigned)sizeof(struct pathinfo));
if(all == NULL)
{
fprintf(stderr,"Out of memory, malloc() failed!\n");
exit(1);
}
cur = all;
while((cur->path = strsep(&userpath,":")) != NULL)
{
cur->next = (struct pathinfo *)malloc((unsigned)sizeof(struct pathinfo));
if(cur->next == NULL)
{
losepath();
fprintf(stderr,"Out of memory, malloc() failed!\n");
exit(1);
}
cur = cur->next;
}
cur->next = NULL;
cur = all;
return;
}
void
findprog(prog, aflag, sflag)
char *prog;
int aflag;
int sflag;
{
struct pathinfo *tmp;
char tmpbuf[2048];
tmp = all;
while(all != NULL)
{
if(strchr(prog,'/'))
strncpy(tmpbuf,prog,2048);
else
snprintf(tmpbuf,2048,"%s/%s",all->path,prog);
if(!file_exists(tmpbuf))
{
found = 0;
if(sflag && aflag) ;
else if(sflag && !aflag)
{
all = tmp;
return;
}
else if(aflag && !sflag)
printf("%s\n",tmpbuf);
else
{
printf("%s\n",tmpbuf);
all = tmp;
return;
}
}
all = all->next;
}
all = tmp;
return;
}
int
main(argc, argv)
int argc;
char *argv[];
{
char buf[1024];
int aflag, sflag, pass, i;
aflag = sflag = pass = 0;
if(argc < 2)
return 1;
if(!strncmp(argv[1],"-h",2) || !strncmp(argv[1],"--h",3) ||
!strcmp(argv[1],"?"))
{
printusage(argv[0]);
return 1;
}
uid = getuid();
pw = getpwuid(uid);
if(getgrouplist(pw->pw_name,pw->pw_gid,groups,&ngroups) == -1)
gfail = 1;
findpath();
for(i = 1; i < argc; i++)
{
if(!pass && *argv[i] == '-')
{
if(!strcmp(argv[i],"-a"))
aflag = 1;
else if(!strcmp(argv[i],"-s"))
sflag = 1;
else
{
printusage(argv[0]);
return 1;
}
continue;
}
pass = 1;
strncpy(buf,argv[i],1024);
findprog(buf,aflag,sflag);
}
losepath();
return sflag ? found : 0;
}
On Thu, Dec 13, 2001 at 01:03:45PM -0500, David Hill wrote:
>
>
> -----Original Message-----
> From: owner-freebsd-bugs@FreeBSD.ORG
> [mailto:owner-freebsd-bugs@FreeBSD.ORG]On Behalf Of Peter Sanchez
> Sent: Thursday, December 13, 2001 12:39 PM
> To: freebsd-gnats-submit@FreeBSD.org
> Subject: bin/32807: which utility replacement in C
>
>
>
> >Number: 32807
> >Category: bin
> >Synopsis: which utility replacement in C
> >Confidential: no
> >Severity: non-critical
> >Priority: low
> >Responsible: freebsd-bugs
> >State: open
> >Quarter:
> >Keywords:
> >Date-Required:
> >Class: change-request
> >Submitter-Id: current-users
> >Arrival-Date: Thu Dec 13 09:40:00 PST 2001
> >Closed-Date:
> >Last-Modified:
> >Originator: Peter Sanchez
> >Release: 4.4-STABLE
> >Organization:
> >Environment:
> FreeBSD char.linuxforlesbians.org 4.4-STABLE FreeBSD 4.4-STABLE #0: Thu
> Nov 22 14:19:15 MST 2001
> root@char.linuxforlesbians.org:/usr/src/sys/compile/CHAR i386
> >Description:
> Just a simple C program to replace the perl which utility that comes
> default at /usr/bin/which (/usr/src/usr.bin/which). Its slighly faster
> than the perl version.
> >How-To-Repeat:
> N/A
> >Fix:
> #include <stdio.h>
> #include <string.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <pwd.h>
>
> #define NGROUPS 15
>
> struct pathinfo
> {
> char path[1024];
> struct pathinfo *next;
> };
>
> struct pathinfo *all = NULL;
> struct passwd *pw;
> uid_t uid;
> int found = 1, gfail = 0;
> int groups[NGROUPS + 1], ngroups = (NGROUPS + 1);
>
> void
> printusage(bin)
> char *bin;
> {
> fprintf(stderr,"usage: %s [-a] [-s] program ...\n",bin);
> return;
> }
>
> int
> file_exists(file)
> char *file;
> {
> struct stat info;
> int check, i;
>
> check = stat(file,&info);
> if(check == -1)
> return check; /* file doesnt exist */
>
> if(S_ISDIR(info.st_mode))
> return -1; /* file is a directory */
>
> /*
> * I did not use access() here cause of man page warnings that
> * it is a potential security risk and shoule NEVER be used. Not
> * quit sure on how it can be a security risk, but I worked around
> * it anyways.
> */
> if(info.st_uid == uid && info.st_mode & S_IFREG && info.st_mode &
> S_IXUSR)
> return check; /* user executable */
>
> if(gfail)
> {
> if(info.st_gid == pw->pw_gid && info.st_mode & S_IFREG &&
> info.st_mode & S_IXGRP)
> return check; /* group executable */
> }
> else
> {
> for(i = 0; i < ngroups; i++)
> {
> if(info.st_gid == groups[i] && info.st_mode & S_IFREG &&
> info.st_mode & S_IXGRP)
> return check; /* group executable */
> }
> }
>
> if(info.st_mode & S_IFREG && info.st_mode & S_IXOTH)
> return check; /* other executable */
> else
> return -1;
> }
>
> void
> losepath(void)
> {
> struct pathinfo *tmp;
>
> while(all != NULL)
> {
> tmp = all->next;
> free(all);
> all = tmp;
> }
> return;
> }
>
> void
> findpath(void)
> {
> struct pathinfo *cur = NULL;
> char *userpath = getenv("PATH");
> int i, x;
>
> if(userpath == NULL)
> exit(1);
>
> all = (struct pathinfo *)malloc((unsigned)sizeof(struct pathinfo));
> if(all == NULL)
> {
> fprintf(stderr,"Out of memory, malloc() failed!\n");
> exit(1);
> }
> cur = all;
>
> for(i = 0, x = 0; i < strlen(userpath); i++)
> {
> if(userpath[i] == ':')
> {
> cur->path[x] = '\0';
> x = 0;
> cur->next = (struct pathinfo
> *)malloc((unsigned)sizeof(struct pathinfo));
> if(cur->next == NULL)
> {
> losepath();
> fprintf(stderr,"Out of memory, malloc() failed!\n");
> exit(1);
> }
> cur = cur->next;
> }
> else
> cur->path[x++] = userpath[i];
> }
> cur->path[x] = '\0';
> cur->next = NULL;
> cur = all;
> return;
> }
>
> void
> findprog(prog, aflag, sflag)
> char *prog;
> int aflag;
> int sflag;
> {
> struct pathinfo *tmp;
> char tmpbuf[2048];
>
> tmp = all;
> while(all != NULL)
> {
> if(strchr(prog,'/'))
> strncpy(tmpbuf,prog,2048);
> else
> snprintf(tmpbuf,2048,"%s/%s",all->path,prog);
>
> if(!file_exists(tmpbuf))
> {
> found = 0;
> if(sflag && aflag) ;
> else if(sflag && !aflag)
> {
> all = tmp;
> return;
> }
> else if(aflag && !sflag)
> printf("%s\n",tmpbuf);
> else
> {
> printf("%s\n",tmpbuf);
> all = tmp;
> return;
> }
> }
> all = all->next;
> }
> all = tmp;
> return;
> }
>
> int
> main(argc, argv)
> int argc;
> char *argv[];
> {
> char buf[1024];
> int aflag, sflag, pass, i;
>
> aflag = sflag = pass = 0;
> if(argc < 2)
> return 1;
>
> if(!strncmp(argv[1],"-h",2) || !strncmp(argv[1],"--h",3) ||
> !strcmp(argv[1],"?"))
> {
> printusage(argv[0]);
> return 1;
> }
>
> uid = getuid();
> pw = getpwuid(uid);
> if(getgrouplist(pw->pw_name,pw->pw_gid,groups,&ngroups) == -1)
> gfail = 1;
>
> findpath();
> for(i = 1; i < argc; i++)
> {
> if(!pass && *argv[i] == '-')
> {
> if(!strcmp(argv[i],"-a"))
> aflag = 1;
> else if(!strcmp(argv[i],"-s"))
> sflag = 1;
> else
> {
> printusage(argv[0]);
> return 1;
> }
> continue;
> }
>
> pass = 1;
> strncpy(buf,argv[i],1024);
> findprog(buf,aflag,sflag);
> }
>
> losepath();
> return sflag ? found : 0;
> }
> >Release-Note:
> >Audit-Trail:
> >Unformatted:
>
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-bugs" in the body of the message
>
> ---
>
> Needs a little work. If my PATH env variable contains a "path" larger
> than 1024, this app seg faults.
>
> $ export PATH=$PATH:`perl -e "print '/bin/','x' x 4048"`
> $ ./which ls
> Segmentation fault (core dumped)
>
> - David
>
> ---
> Outgoing mail is certified Virus Free.
> Checked by AVG anti-virus system (http://www.grisoft.com).
> Version: 6.0.303 / Virus Database: 164 - Release Date: 11/24/2001
>
--
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?200112132100.fBDL01r64612>
