1
0
Fork 0
src/Wip/which.c

98 lines
2.3 KiB
C

#include <errno.h>
#include <stdbool.h>
#include <stdio.h> /* fprintf(3) */
#include <stdlib.h> /* exit(3) */
#include <sysexits.h>
#include <unistd.h> /* access(2), chdir(2) */
#include "libshell.h" /* getpaths(3) */
void
usage(char *name){
fprintf(stderr, "Usage: %s (-a) [name]\n", name);
exit(EX_USAGE);
}
int
which(char *program, char **paths, char *name, bool breakonfirst){
char **q;
int retval;
retval = 0;
for(q = paths; *q != NULL; ++q){
if(chdir(*q) != 0)
switch(retval = errno){
/* Non-issues in the context of this program */
case EACCES: /* Access denied */
case ELOOP: /* Too many symlinks in path */
case ENAMETOOLONG: /* Name too long */
case ENOENT: /* Directory doesn't exist */
case ENOTDIR: /* Not a directory */
continue;
case EFAULT:
goto apology;
case EIO:
goto ioerr;
}
/* Changed dir, now check for file in dir */
if(access(program, R_OK | X_OK) != 0)
switch(retval = errno){
case EACCES:
case ELOOP:
case ENAMETOOLONG:
case ENOENT:
case EROFS:
continue;
case EFAULT:
goto apology;
case EIO:
goto ioerr;
}
else{
fprintf(stdout, "%s%s\n", *q, program);
if(breakonfirst != 0)
break;
}
}
end:
return retval;
apology:
fprintf(stderr,
/* EFAULT means the pointer passed to either chdir(2) or access(2) was outside
* of the address space available to the program. This means something's Very
* Wrong with getpaths(3) and libshell has to be fixed. That'd be a serious,
* common error, so try to reassure the user and solicit a bug report. */
"%s: EFAULT\n"
"You the user did nothing to invoke this error message. This is an error in\n"
"which, a program you or another program executed. PLEASE e-mail the creator\n"
"of this program (the address can be found in the corresponding manual page)\n"
"and tell them you got this error and what you were doing when it happened.\n"
"Sorry!\n", name);
goto end;
ioerr:
fprintf(stderr, "%s: filesystem I/O error\n", name);
goto end;
}
int main(int argc, char *argv[]){
int i;
char **paths;
int retval;
if(argc <= 1)
usage(argv[0]);
if((paths = getpaths()) == NULL){
fprintf(stderr, "%s: Could not get the value of $PATH\n", argv[0]);
exit(1);
}
for(i = 1; i < argc; ++i)
if((retval = which(argv[i], paths, argv[0], 1)) != 0)
break;
free(*paths);
free(paths);
return retval;
}