diff --git a/utils/help.cpp b/utils/help.cpp index 548617c4..7af880d2 100644 --- a/utils/help.cpp +++ b/utils/help.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -16,23 +16,101 @@ this program. If not, see . help.cpp - Prints a friendly message and ls /bin. + Prints a friendly message and print the names of everything in PATH. *******************************************************************************/ -#include +#include +#include + +#include #include #include +#include +#include +#include #include int main(int /*argc*/, char* /*argv*/[]) { printf("Please enter the name of one of the following programs:\n"); - const char* programname = "ls"; - const char* newargv[] = { programname, "/bin", NULL }; - execvp(programname, (char* const*) newargv); - error(1, errno, "%s", programname); + const char* path = getenv("PATH"); + if ( !path ) + return 0; - return 1; + pid_t child_pid = -1; + + if ( isatty(1) ) + { + int pipe_fds[2]; + if ( pipe(pipe_fds) ) + error(1, errno, "pipe"); + + if ( (child_pid = fork()) < 0 ) + error(1, errno, "fork"); + + if ( !child_pid ) + { + dup2(pipe_fds[0], 0); + close(pipe_fds[0]); + close(pipe_fds[1]); + execlp("column", "column", NULL); + execlp("cat", "cat", NULL); + int ic; + while ( (ic = fgetc(stdin)) != EOF ) + fputc(ic, stdout); + exit(0); + } + + dup2(pipe_fds[1], 1); + close(pipe_fds[0]); + close(pipe_fds[1]); + } + + char* dirname = NULL; + while ( *path ) + { + if ( dirname ) { free(dirname); dirname = NULL; } + size_t len = strcspn(path, ":"); + if ( !len ) { path++; continue; } + dirname = (char*) malloc((len+1) * sizeof(char)); + if ( !dirname ) + error(1, errno, "malloc"); + memcpy(dirname, path, len * sizeof(char)); + dirname[len] = '\0'; + path += len + 1; + DIR* dir = opendir(dirname); + if ( !dir ) + continue; + while ( struct dirent* entry = readdir(dir) ) + { + if ( entry->d_name[0] == '.' ) + continue; + struct stat st; + if ( fstatat(dirfd(dir), entry->d_name, &st, 0) ) + continue; + if ( !S_ISREG(st.st_mode) ) + continue; + if ( !(st.st_mode & 0111) ) + continue; + printf("%s\n", entry->d_name); + } + closedir(dir); + } + free(dirname); + + if ( 0 <= child_pid ) + { + fflush(stdout); + close(1); + int exit_status; + waitpid(child_pid, &exit_status, 0); + if ( WIFSIGNALED(exit_status) ) + exit(128 + WTERMSIG(exit_status)); + if ( WIFEXITED(exit_status) && WEXITSTATUS(exit_status) ) + exit(WEXITSTATUS(exit_status)); + } + + return 0; }