|
|
1.1 root 1: /*
2: * Expand $SRCPATH and apply it to each argument printing the
3: * full path of the result.
4: * Allow pattern type arguments for example.
5: * srcpath "*.[ch]"
6: * Will find all .c and .h files on $SRCPATH eliminating duplicates.
7: * .: will automatically be prepended to $SRCPATH so that files
8: * in the current directory have preference.
9: *
10: * The first arguments may be -p pathlist for example
11: * srcpath -p ".:/usr/src/cmd" "*.c"
12: * Note: . is not automatically prepended to this list.
13: *
14: * The -a option disables shadowing. Normally if a file is found
15: * in two directorys on the path only the first if printed.
16: * -a causes it to be printed twice.
17: *
18: * Normally srcpath silently bypasses directorys and matching files
19: * on which it has no read permission. The -w option causes it to
20: * print a warning message on stderr.
21: */
22: #include <stdio.h>
23: #include <sys/types.h>
24: #include <sys/dir.h>
25: #include <path.h>
26: #include <dirent.h>
27: #include <access.h>
28:
29: struct savepath {
30: char name[DIRSIZ + 1]; /* zero terminated directory name */
31: char *path; /* pointer to path or NULL */
32: };
33:
34: static struct savepath *found = NULL;
35: static int ents;
36: static int allsw, warnsw;
37:
38: /*
39: * Print out of space message and die.
40: */
41: static void
42: outSpace()
43: {
44: fprintf(stderr, "srcpath: out of space");
45: exit(1);
46: }
47:
48: /*
49: * Print cannot read warning if warnsw is on.
50: */
51: static void
52: noRead(name)
53: char *name;
54: {
55: if (warnsw)
56: fprintf(stderr, "srcpath: cannot read '%s'\n", name);
57: }
58:
59: /*
60: * Check if the directory entry matches any argv entries.
61: */
62: static void
63: checkit(d_name, argv, path)
64: char *d_name;
65: register char *argv[];
66: char *path;
67: {
68: char work[DIRSIZ + 1]; /* zero terminated version of dent->d_name */
69: char name[MAXPATH];
70: static int nents; /* number of entries allowed */
71:
72: memcpy(work, d_name, DIRSIZ);
73: work[DIRSIZ] = '\0';
74:
75: for (;NULL != *argv; argv++) {
76: /* the filename must match the arguement */
77: if (!pnmatch(work, *argv, 0))
78: continue;
79:
80: /* we must have read permission */
81: sprintf(name, "%s/%s", path, work);
82: if(access(name, AREAD)) {
83: noRead(name);
84: continue;
85: }
86:
87: /* realloc() more space if we've run out. */
88: if(ents >= nents) {
89: extern char *realloc();
90:
91: nents += 20;
92: found = realloc(found, nents * sizeof(*found));
93: if(NULL == found)
94: outSpace();
95: }
96:
97: /* save name and pointer to path */
98: strcpy(found[ents].name, work);
99: found[ents++].path = path;
100: }
101: }
102:
103: /*
104: * Compare two directory entrys by name then location of the path pointer.
105: */
106: static int
107: compr(d1, d2)
108: register struct savepath *d1, *d2;
109: {
110: register int i;
111:
112: return ((i = strcmp(d1->name, d2->name)) ? i : (d1->path - d2->path));
113: }
114:
115: main(argc, argv)
116: char *argv[];
117: {
118: register char *p;
119: char *end, *env, *dotenv;
120: extern char *optarg, *getenv(), *strchr();
121: extern int optind;
122: int i, errflag;
123:
124: dotenv = NULL;
125: allsw, errflag = 0;
126: while ((i = getopt(argc, argv, "?awp:")) != EOF) {
127: switch (i) {
128: case 'a':
129: allsw = 1; /* print all matches */
130: break;
131: case 'w':
132: warnsw = 1; /* warn of inaccessable files */
133: break;
134: /* if args start -p pathlist use that pathlist not $SRCPATH */
135: case 'p':
136: dotenv = optarg;
137: break;
138: default:
139: errflag++;
140: }
141: }
142: argv += optind; /* point argv at first file name */
143: if (errflag) {
144: fprintf(stderr,
145: "usage: srcpath [-aw] [-p path] file ...\n");
146: exit(1);
147: }
148:
149: if (NULL == dotenv) { /* no use of -p */
150: if (NULL == (env = getenv("SRCPATH"))) {
151: if (NULL == (dotenv = malloc(2)))
152: outSpace();
153: strcpy(dotenv, ".");
154: }
155: else {
156: /* prepend .: to $SRCPATH */
157: if (NULL == (dotenv = malloc(strlen(env) + 3)))
158: outSpace();
159: sprintf(dotenv, ".%c%s", LISTSEP, env);
160: }
161: }
162:
163: /* replace LISTSEP with '\0' and locate the end */
164: for (end = dotenv; *end; end++)
165: if (LISTSEP == *end)
166: *end = '\0';
167:
168: /* for each path name */
169: for (p = dotenv; p < end; p = strchr(p, '\0') + 1) {
170: DIR *dirp;
171: struct dirent *dp;
172:
173: /* ignore bad path entries */
174: if (access(p, ALIST) || (NULL == (dirp = opendir(p)))) {
175: noRead(p);
176: continue;
177: }
178:
179: /* for each directory entry */
180: while (NULL != (dp = readdir(dirp)))
181: checkit(dp->d_name, argv, p);
182:
183: closedir(dirp);
184: }
185:
186: /* sort by name then position on pathlist */
187: qsort(found, ents, sizeof(struct savepath), compr);
188:
189: /* eliminate duplicate names and print the remainder. */
190: for (i = 1; i <= ents; i++) {
191: if (!allsw && !strcmp(found[i - 1].name, found[i].name))
192: found[i].path = NULL;
193: if (NULL != found[i - 1].path)
194: printf("%s/%s\n", found[i - 1].path, found[i - 1].name);
195: }
196: exit(0);
197: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.