#include #include #include #include #include #include #include #include #include "completion.h" struct comp_ { char **path_elem; char **exec_elem; size_t nof_path_elem; size_t nof_exec_elem; size_t curr_elem; uid_t uid; gid_t gid; }; int comp_init(comp_t *compp) { comp_t comp; char *path; char *path_elem_start; char *path_elem_end; size_t path_len; size_t i; /* * initialize structure */ if (!(comp = malloc(sizeof *comp))) { return (1); } /* * initialize path elements */ path_elem_start = path = getenv("PATH"); path_elem_end = NULL; path_len = strlen(path); for (i=0; inof_path_elem++; path_elem_end = path+i; if (!(comp->path_elem = realloc(comp->path_elem, comp->nof_path_elem * sizeof (char *)))) { return (1); } if (!(comp->path_elem[comp->nof_path_elem-1] = malloc((path_elem_end - path_elem_start + 1) * sizeof (char)))) { return (1); } memcpy(comp->path_elem[comp->nof_path_elem-1], path_elem_start, path_elem_end - path_elem_start); comp->path_elem[comp->nof_path_elem-1][path_elem_end - path_elem_start] = '\0'; path_elem_start = path+i+1; } } /* * initialize other members */ comp->exec_elem = NULL; comp->nof_exec_elem = comp->curr_elem = 0; comp->uid = getuid(); comp->gid = getgid(); *compp = comp; return (0); } int comp_cleanup(comp_t comp) { size_t i; for (i=0; inof_path_elem; i++) { free(comp->path_elem[i]); } free(comp->path_elem); for (i=0; inof_exec_elem; i++) { free(comp->exec_elem[i]); } free(comp->exec_elem); free(comp); return (0); } int comp_update(comp_t comp, char *hint) { struct dirent *dp; struct stat sb; char buffer[MAX_CMD_LEN+1]; DIR *dirp; size_t hint_len; size_t i; for (i=0; inof_exec_elem; i++) { free(comp->exec_elem[i]); } free(comp->exec_elem); comp->exec_elem = NULL; comp->nof_exec_elem = comp->curr_elem = 0; if ((hint_len = strlen(hint)) == 0) { return (EINVAL); } /* * Each path element */ for (i=0; inof_path_elem; i++) { if (!(dirp = opendir(comp->path_elem[i]))) { continue; } while ((dp = readdir(dirp))) { if (!strncmp(dp->d_name, hint, hint_len)) { snprintf(buffer, MAX_CMD_LEN, "%s/%s", comp->path_elem[i], dp->d_name); if (stat(buffer, &sb)) { continue; } if (sb.st_mode & S_IFREG) { if ((sb.st_uid == comp->uid && sb.st_mode & S_IXUSR) || (sb.st_gid == comp->gid && sb.st_mode & S_IXGRP) || sb.st_mode & S_IXOTH) { comp->nof_exec_elem++; if (!(comp->exec_elem = realloc(comp->exec_elem, comp->nof_exec_elem * sizeof (char *)))) { closedir(dirp); return (ENOMEM); } if (!(comp->exec_elem[comp->nof_exec_elem-1] = strdup(buffer))) { closedir(dirp); return (ENOMEM); } } } } } } return (0); } char * comp_next(comp_t comp) { if (!comp->exec_elem) { return (NULL); } if (comp->curr_elem == comp->nof_exec_elem) { comp->curr_elem = 0; } return (comp->exec_elem[comp->curr_elem++]); }