Index: mime.c =================================================================== --- mime.c (revision 4677) +++ mime.c (working copy) @@ -50,6 +50,24 @@ /* + * Filter info ... + */ + +typedef struct filter_struct +{ + struct filter_struct *next; /* Next element in list */ + char *filter; /* Filter file name */ + int x_ok; /* Is the filter executable? */ +} filter_t; + +/* + * Local globals... + */ + +static filter_t *FilterList = NULL; /* Temporary list of filters */ + + +/* * Local functions... */ @@ -193,6 +211,8 @@ DIR *dir; /* Directory */ struct dirent *dent; /* Directory entry */ char filename[1024]; /* Full filename of types/converts file */ + filter_t *current, /* Current filter in list */ + *next; /* Next filter in list */ /* @@ -254,6 +274,20 @@ closedir(dir); + /* + * Free the temporary list of filters + */ + + for (current = FilterList; current; current = next) + { + next = current->next; + if (current->filter) + free(current->filter); + free(current); + } + + FilterList = NULL; + return (mime); #endif /* WIN32 */ } @@ -383,6 +417,7 @@ *dsttype; /* Destination MIME type */ int cost; /* Cost of filter */ char filterprog[1024]; /* Full path of filter... */ + filter_t *current; /* Current filter in list */ /* @@ -478,15 +513,40 @@ if (strcmp(filter, "-") != 0) { /* - * Verify that the filter exists and is executable... + * Verify that the filter exists and is executable. + * To avoid extra calls to access(2) we keep a list of previously tested + * filters; we search the list before making the call... */ - if (filter[0] == '/') - strlcpy(filterprog, filter, sizeof(filterprog)); - else - snprintf(filterprog, sizeof(filterprog), "%s/%s", filterpath, filter); + for (current = FilterList; current; current = current->next) + if (current->filter && !strcmp(filter, current->filter)) + break; - if (access(filterprog, X_OK)) + if (current == NULL) + { + /* + * We haven't tested this filter before so add an item to the + * list and set it's access(2) result. + */ + + current = malloc(sizeof(filter_t)); + current->filter = strdup(filter); + current->next = FilterList; + FilterList = current; + + if (filter[0] == '/') + strlcpy(filterprog, filter, sizeof(filterprog)); + else + snprintf(filterprog, sizeof(filterprog), "%s/%s", filterpath, filter); + + current->x_ok = (access(filterprog, X_OK) == 0); + } + + /* + * If the filter isn't executable don't add it to the mime database... + */ + + if (!current->x_ok) continue; } #endif /* !WIN32 */