Merge pull request #35 from DevManu-de/dev-redirect-handle
[psh.git] / src / builtins / help.c
blobb6ba7e0f381abb8dd2086baf9ff8ff70e78574c0
1 /*
2 psh/builtins/hash.c - builtin command hash
4 Copyright 2020 Zhang Maiyun.
6 This file is part of Psh, P shell.
8 Psh is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 Psh is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <https://www.gnu.org/licenses/>.
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
30 #include "builtin.h"
31 #include "libpsh/util.h"
32 #include "psh.h"
34 #define MAN 0x00
35 #define SHORT 0x01
36 #define USAGE 0x02
37 #define NBUILTIN (sizeof(builtin_helps) / sizeof(builtin_help_t))
38 /* Help string of all builtins */
39 #ifndef WITHOUT_BUILTIN_HELP
40 typedef char *builtin_help_t[4];
41 const builtin_help_t builtin_helps[63] = {
42 {".", "filename [arguments]",
43 "Execute commands from a file in the current shell.",
44 "Read and execute commands from FILENAME in the current shell. The "
45 "entries in $PATH are used to find the directory containing FILENAME. If "
46 "any ARGUMENTS are supplied, they become the positional parameters when "
47 "FILENAME is executed.\n"
48 "\tExit Status:\n"
49 "\tReturns the status of the last command executed in FILENAME; fails if "
50 "FILENAME cannot be read."},
51 {":", "", "", ""},
52 {"alias", "", "", ""},
53 {"bg", "", "", ""},
54 {"bind", "", "", ""},
55 {"break", "", "", ""},
56 {"builtin", "", "", ""},
57 {"case", "", "", ""},
58 {"cd", "", "", ""},
59 {"chdir", "", "", ""},
60 {"command", "", "", ""},
61 {"continue", "", "", ""},
62 {"declare", "", "", ""},
63 {"do", "", "", ""},
64 {"done", "", "", ""},
65 {"echo", "", "", ""},
66 {"elif", "", "", ""},
67 {"else", "", "", ""},
68 {"esac", "", "", ""},
69 {"eval", "", "", ""},
70 {"exec", "", "", ""},
71 {"exit", "", "", ""},
72 {"export", "", "", ""},
73 {"false", "", "", ""},
74 {"fc", "", "", ""},
75 {"fg", "", "", ""},
76 {"fi", "", "", ""},
77 {"for", "", "", ""},
78 {"getopts", "", "", ""},
79 {"getstat", "", "", ""},
80 {"hash", "", "", ""},
81 {"help", "", "", ""},
82 {"history", "", "", ""},
83 {"if", "", "", ""},
84 {"jobid", "", "", ""},
85 {"jobs", "", "", ""},
86 {"local", "", "", ""},
87 {"logout", "", "", ""},
88 {"popd", "", "", ""},
89 {"pushd", "", "", ""},
90 {"pwd", "", "", ""},
91 {"quit", "", "", ""},
92 {"read", "", "", ""},
93 {"readonly", "", "", ""},
94 {"return", "", "", ""},
95 {"set", "", "", ""},
96 {"setvar", "", "", ""},
97 {"shift", "", "", ""},
98 {"source", "", "", ""},
99 {"test", "", "", ""},
100 {"then", "", "", ""},
101 {"times", "", "", ""},
102 {"trap", "", "", ""},
103 {"true", "", "", ""},
104 {"type", "", "", ""},
105 {"ulimit", "", "", ""},
106 {"umask", "", "", ""},
107 {"unalias", "", "", ""},
108 {"unset", "", "", ""},
109 {"until", "", "", ""},
110 {"wait", "", "", ""},
111 {"which", "", "", ""},
112 {"while", "", "", ""}};
113 #endif
114 static int compare_builtin_helps(const void *key, const void *cur)
116 return strcmp((char *)key, (*(builtin_help_t *)cur)[0]);
119 int builtin_help(int argc, char **argv, psh_state *state)
121 #ifndef WITHOUT_BUILTIN_HELP
122 int type = MAN;
123 int count = 0;
124 /* count always points to the next possible command name */
125 while (++count < argc)
127 if (argv[count][0] != '-')
128 break;
129 if (argv[count][1] == '-')
131 /* Skip this -- */
132 ++count;
133 break;
135 if (argv[count][1] == '\0')
136 /* Treat '-' as an argument. */
137 break;
138 if (argv[count][1] == 'm')
139 type = MAN;
140 else if (argv[count][1] == 's')
141 type = SHORT;
142 else if (argv[count][1] == 'd')
143 type = USAGE;
144 else
146 OUT2E("%s: %s: unrecognized argument -%c\n", state->argv0, argv[0],
147 argv[count][1]);
148 return 1;
151 if (count == argc)
153 size_t count2;
154 /* Print all help */
155 for (count2 = 0; count2 < NBUILTIN; ++count2)
157 printf("%s %s\n", builtin_helps[count2][0],
158 builtin_helps[count2][1]);
160 return 0;
162 /* Go over all positional parameters, print their help */
163 for (; count < argc; ++count)
165 builtin_help_t *itm =
166 bsearch(argv[count], builtin_helps, NBUILTIN,
167 sizeof(builtin_help_t), &compare_builtin_helps);
168 if (itm == NULL)
170 OUT2E("%s: %s: no help topics match `%s'. Try `help help' or `man "
171 "-k %s' or `info %s'.\n",
172 state->argv0, argv[0], argv[count], argv[count], argv[count]);
173 continue;
175 if (type == MAN)
176 /* Print help in man format. */
177 printf("NAME\n\t%s - %s\n\nSYNOPSIS\n\t%s "
178 "%s\n\nDESCRIPTION\n\t%s\n\nSEE "
179 "ALSO\n\tpsh(1)\n\nIMPLEMENTATION\n\tpsh\n",
180 (*itm)[0], (*itm)[2], (*itm)[0], (*itm)[1], (*itm)[3]);
181 else if (type == SHORT)
182 printf("%s - %s\n", (*itm)[0], (*itm)[2]);
183 else if (type == USAGE)
184 printf("%s: %s %s\n", (*itm)[0], (*itm)[0], (*itm)[1]);
186 return 0;
187 #else
188 OUT2E("%s: %s: Built without builtin help.\n", state->argv0, argv[0]);
189 return 1;
190 #endif