static const char * append_char_function(const char *name) { struct stat stbuf; char *expname = *name == '~' ? fn_tilde_expand(name) : NULL; const char *rs = " "; if (stat(expname ? expname : name, &stbuf) == -1) goto out; if (S_ISDIR(stbuf.st_mode)) rs = "/"; out: if (expname) el_free(expname); return rs; }
/* * return first found file name starting by the ``text'' or NULL if no * such file can be found * value of ``state'' is ignored * * it's caller's responsibility to free returned string */ char * fn_filename_completion_function(const char *text, int state) { static DIR *dir = NULL; static char *filename = NULL, *dirname = NULL, *dirpath = NULL; static size_t filename_len = 0; struct dirent *entry; char *temp; size_t len; if (state == 0 || dir == NULL) { temp = strrchr(text, '/'); if (temp) { char *nptr; temp++; nptr = el_realloc(filename, (strlen(temp) + 1) * sizeof(*nptr)); if (nptr == NULL) { el_free(filename); filename = NULL; return NULL; } filename = nptr; (void)strcpy(filename, temp); len = (size_t)(temp - text); /* including last slash */ nptr = el_realloc(dirname, (len + 1) * sizeof(*nptr)); if (nptr == NULL) { el_free(dirname); dirname = NULL; return NULL; } dirname = nptr; (void)strncpy(dirname, text, len); dirname[len] = '\0'; } else { el_free(filename); if (*text == 0) filename = NULL; else { filename = strdup(text); if (filename == NULL) return NULL; } el_free(dirname); dirname = NULL; } if (dir != NULL) { (void)closedir(dir); dir = NULL; } /* support for ``~user'' syntax */ el_free(dirpath); dirpath = NULL; if (dirname == NULL) { if ((dirname = strdup("")) == NULL) return NULL; dirpath = strdup("./"); } else if (*dirname == '~') dirpath = fn_tilde_expand(dirname); else dirpath = strdup(dirname); if (dirpath == NULL) return NULL; dir = opendir(dirpath); if (!dir) return NULL; /* cannot open the directory */ /* will be used in cycle */ filename_len = filename ? strlen(filename) : 0; } /* find the match */ while ((entry = readdir(dir)) != NULL) { /* skip . and .. */ if (entry->d_name[0] == '.' && (!entry->d_name[1] || (entry->d_name[1] == '.' && !entry->d_name[2]))) continue; if (filename_len == 0) break; /* otherwise, get first entry where first */ /* filename_len characters are equal */ if (entry->d_name[0] == filename[0] /* Some dirents have d_namlen, but it is not portable. */ && strlen(entry->d_name) >= filename_len && strncmp(entry->d_name, filename, filename_len) == 0) break; } if (entry) { /* match found */ /* Some dirents have d_namlen, but it is not portable. */ len = strlen(entry->d_name); len = strlen(dirname) + len + 1; temp = el_malloc(len * sizeof(*temp)); if (temp == NULL) return NULL; (void)snprintf(temp, len, "%s%s", dirname, entry->d_name); } else { (void)closedir(dir); dir = NULL; temp = NULL; } return temp; }
/* * return first found file name starting by the ``text'' or NULL if no * such file can be found * value of ``state'' is ignored * * it's caller's responsibility to free returned string */ char * fn_filename_completion_function(const char *text, int state) { static DIR *dir = NULL; static char *filename = NULL, *dirname = NULL, *dirpath = NULL; static size_t filename_len = 0; struct dirent *entry; char *temp; size_t tempsz, len; if (state == 0 || dir == NULL) { temp = strrchr(text, '/'); if (temp) { size_t sz = strlen(temp + 1) + 1; char *nptr; temp++; nptr = realloc(filename, sz); if (nptr == NULL) { free(filename); filename = NULL; return NULL; } filename = nptr; (void)strlcpy(filename, temp, sz); len = temp - text; /* including last slash */ nptr = realloc(dirname, len + 1); if (nptr == NULL) { free(dirname); dirname = NULL; return NULL; } dirname = nptr; (void)strncpy(dirname, text, len); dirname[len] = '\0'; } else { free(filename); if (*text == 0) filename = NULL; else { filename = strdup(text); if (filename == NULL) return NULL; } free(dirname); dirname = NULL; } if (dir != NULL) { (void)closedir(dir); dir = NULL; } /* support for ``~user'' syntax */ free(dirpath); dirpath = NULL; if (dirname == NULL) { if ((dirname = strdup("")) == NULL) return NULL; dirpath = strdup("./"); } else if (*dirname == '~') dirpath = fn_tilde_expand(dirname); else dirpath = strdup(dirname); if (dirpath == NULL) return NULL; dir = opendir(dirpath); if (!dir) return (NULL); /* cannot open the directory */ /* will be used in cycle */ filename_len = filename ? strlen(filename) : 0; } /* find the match */ while ((entry = readdir(dir)) != NULL) { /* skip . and .. */ if (entry->d_name[0] == '.' && (!entry->d_name[1] || (entry->d_name[1] == '.' && !entry->d_name[2]))) continue; if (filename_len == 0) break; /* otherwise, get first entry where first */ /* filename_len characters are equal */ if (entry->d_name[0] == filename[0] #if HAVE_STRUCT_DIRENT_D_NAMLEN && entry->d_namlen >= filename_len #else && strlen(entry->d_name) >= filename_len #endif && strncmp(entry->d_name, filename, filename_len) == 0) break; } if (entry) { /* match found */ #if HAVE_STRUCT_DIRENT_D_NAMLEN len = entry->d_namlen; #else len = strlen(entry->d_name); #endif tempsz = strlen(dirname) + len + 1; temp = malloc(tempsz); if (temp == NULL) return NULL; (void)snprintf(temp, tempsz, "%s%s", dirname, entry->d_name); } else { (void)closedir(dir); dir = NULL; temp = NULL; } return (temp); }