File: which.c

package info (click to toggle)
splitvt 1.6.5-9
  • links: PTS
  • area: main
  • in suites: etch-m68k
  • size: 340 kB
  • ctags: 393
  • sloc: ansic: 4,764; sh: 78; makefile: 37; perl: 15
file content (118 lines) | stat: -rw-r--r-- 2,233 bytes parent folder | download | duplicates (13)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

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

/* * * * * * * Routines to parse a line into an array of tokens * * * * * * */

static int istoken(c, tokens)
char c;
char *tokens;
{
	while ( *tokens ) {
		if ( c == *(tokens++) )
			return(1);
	}
	return(0);
}

/* This version of tokenize is destructive to the line it parses. */

void tokenize(array, line, tokens)
char *array[];
char *line;
char *tokens;
{
	char *head, *ptr;
	int i=0;

	for ( head=line; *line; ) {
		if ( istoken(*line, tokens) ) {
			*(line++)='\0';
			array[i++]=head;
			while ( istoken(*line, tokens) )
				++line;
			head=line;
		} else
			++line;
	}
	array[i++]=head;
	array[i]=NULL;
}

/* Return the pathname of the command, or NULL if it's not in our PATH */
/* Warning: We use a static buffer that is overwritten at each invocation. */

char *pathsearch(command, secure)
char *command;
int secure;
{
#ifndef S_IFREG
#define S_IFREG 0100000
#endif
	char *path, *newpath, *paths[256];
	static char buffer[1024];
	int i;
	struct stat sb;

	if ( (path=(char *)getenv("PATH")) == NULL )
		return(NULL);
	if ( (newpath=(char *)malloc(strlen(path)+1)) == NULL )
		return(NULL);
	strcpy(newpath, path);

	tokenize(paths, newpath, ":");
	for ( i=0; paths[i]; ++i ) {
		if ( secure && paths[i][0] != '/' ) {
			/* Only allow full pathnames */
			continue;
		}

		/* Make sure the file exists */
		sprintf(buffer, "%s/%s", paths[i], command);
		if ( stat(buffer, &sb) != 0 )
			continue;

		/* Make sure it's a regular file */
		if ( (sb.st_mode & S_IFREG) != S_IFREG )
			continue;

		/* Now make sure we can execute it */
		if ( sb.st_uid == getuid() ) {
			/* User execute permission? */
			if ( sb.st_mode & 0100 )
				break;
		} else if ( sb.st_gid == getgid() ) {
			/* Group execute permission? */
			if ( sb.st_mode & 0010 )
				break;
		} else {
			/* Other execute permission? */
			if ( sb.st_mode & 0001 )
				break;
		}
	}
	(void) free(newpath);

	if ( paths[i] == NULL )
		return(NULL);
	else
		return(buffer);
}
	

main(argc, argv)
int argc;
char *argv[];
{
	char *path;

	if ( argc != 2 ) {
		fprintf(stderr, "Usage: %s command\n", argv[0]);
		exit(1);
	}

	if ( (path=pathsearch(argv[1], 0)) )
		printf("%s\n", path);
	exit(0);
}