15 void fpclose(FILE *fp) {
22 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
24 static struct decompressor {
25 char *ext; /* starts with `.', has no other dots */
28 { ".gz", "gzip -d -c" },
29 { ".bz2", "bzip2 -d -c" },
34 pipe_open(struct decompressor *dc) {
39 pipe_cmd = xmalloc(strlen(dc->cmd) + strlen(pathname) + 2);
40 sprintf(pipe_cmd, "%s %s", dc->cmd, pathname);
41 fp = popen(pipe_cmd, "r");
43 fprintf(stderr, _("error executing %s\n"), pipe_cmd);
47 /* If a file PATHNAME exists, then open it.
48 If is has a `compressed' extension, then open a pipe reading it */
50 maybe_pipe_open(void) {
53 struct decompressor *dc;
55 if ((fp = fopen(pathname, "r")) != NULL) {
56 t = rindex(pathname, '.');
58 for (dc = &decompressors[0]; dc->cmd; dc++)
59 if (strcmp(t, dc->ext) == 0) {
69 findfile_in_dir(char *fnam, char *dir, int recdepth, char **suf) {
73 char *ff, *fdir, *p, *q, **sp;
74 struct decompressor *dc;
79 ff = index(fnam, '/');
82 fdir[ff-fnam] = 0; /* caller guarantees fdir != "" */
84 fdir = 0; /* just to please gcc */
86 /* Scan the directory twice: first for files, then
87 for subdirectories, so that we do never search
88 a subdirectory when the directory itself already
89 contains the file we are looking for. */
94 while ((de = readdir(d)) != NULL) {
98 if (strcmp(de->d_name, ".") == 0 ||
99 strcmp(de->d_name, "..") == 0)
102 if (strlen(dir) + strlen(de->d_name) + 2 > sizeof(pathname))
105 okdir = (ff && strcmp(de->d_name, fdir) == 0);
107 if ((secondpass && recdepth) || okdir) {
110 a = xmalloc(strlen(dir) + strlen(de->d_name) + 2);
111 sprintf(a, "%s/%s", dir, de->d_name);
112 if (stat(a, &statbuf) == 0 &&
113 S_ISDIR(statbuf.st_mode)) {
115 fp = findfile_in_dir(ff+1, a, 0, suf);
117 fp = findfile_in_dir(fnam, a, recdepth-1, suf);
127 /* Should we be in a subdirectory? */
131 /* Does d_name start right? */
134 while (*p && *p == *q) p++,q++;
138 sprintf(pathname, "%s/%s", dir, de->d_name);
139 if (stat(pathname, &statbuf) != 0 || !S_ISREG(statbuf.st_mode))
142 /* Does tail consist of a known suffix and possibly
143 a compression suffix? */
144 for(sp = suf; *sp; sp++) {
148 return maybe_pipe_open();
151 if (strncmp(p,*sp,l) == 0) {
152 for (dc = &decompressors[0]; dc->cmd; dc++)
153 if (strcmp(p+l, dc->ext) == 0)
154 return pipe_open(dc);
159 if (recdepth > 0 && !secondpass) {
166 /* find input file; leave name in pathname[] */
167 FILE *findfile(char *fnam, char **dirpath, char **suffixes) {
168 char **dp, *dir, **sp;
171 struct decompressor *dc;
173 if (strlen(fnam) >= sizeof(pathname))
176 /* Try explicitly given name first */
177 strcpy(pathname, fnam);
178 fp = maybe_pipe_open();
182 /* Test for full pathname - opening it failed, so need suffix */
183 /* (This is just nonsense, for backwards compatibility.) */
187 for (sp = suffixes; *sp; sp++) {
188 if (strlen(fnam) + strlen(*sp) + 1 > sizeof(pathname))
191 continue; /* we tried it already */
192 sprintf(pathname, "%s%s", fnam, *sp);
193 if(stat(pathname, &statbuf) == 0 && S_ISREG(statbuf.st_mode)
194 && (fp = fopen(pathname, "r")) != NULL)
198 for (sp = suffixes; *sp; sp++) {
199 for (dc = &decompressors[0]; dc->cmd; dc++) {
200 if (strlen(fnam) + strlen(*sp)
201 + strlen(dc->ext) + 1 > sizeof(pathname))
203 sprintf(pathname, "%s%s%s", fnam, *sp, dc->ext);
204 if (stat(pathname, &statbuf) == 0
205 && S_ISREG(statbuf.st_mode)
206 && (fp = fopen(pathname, "r")) != NULL) {
208 return pipe_open(dc);
216 /* Search a list of directories and directory hierarchies */
217 for (dp = dirpath; *dp; dp++) {
219 /* delete trailing slashes; trailing stars denote recursion */
223 while (dl && dir[dl-1] == '*') {
229 } else if (dl > 1 && dir[dl-1] == '/') {
233 fp = findfile_in_dir(fnam, dir, recdepth, suffixes);