2 * help - display help for calc
4 * Copyright (C) 1999-2007 Landon Curt Noll
6 * Calc is open software; you can redistribute it and/or modify it under
7 * the terms of the version 2.1 of the GNU Lesser General Public License
8 * as published by the Free Software Foundation.
10 * Calc is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
13 * Public License for more details.
15 * A copy of version 2.1 of the GNU Lesser General Public License is
16 * distributed with calc under the filename COPYING-LGPL. You should have
17 * received a copy with calc; if not, write to Free Software Foundation, Inc.
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * @(#) $Revision: 30.3 $
21 * @(#) $Id: help.c,v 30.3 2013/08/11 01:08:32 chongo Exp $
22 * @(#) $Source: /usr/local/src/cmd/calc/RCS/help.c,v $
24 * Under source code control: 1997/09/14 10:58:30
25 * File existed as early as: 1997
27 * chongo <was here> /\oo/\ http://www.isthe.com/chongo/
28 * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
34 #include <sys/types.h>
40 #include "have_unistd.h"
41 #if defined(HAVE_UNISTD_H)
47 # define pclose _pclose
52 * some help topics are symbols, so we alias them to nice filenames
54 STATIC
struct help_alias
{
68 {"copying", "COPYING"},
69 {"copying-lgpl", "COPYING-LGPL"},
70 {"copying_lgpl", "COPYING-LGPL"},
71 {"COPYING_LGPL", "COPYING-LGPL"},
72 {"Copyright", "copyright"},
73 {"COPYRIGHT", "copyright"},
74 {"Copyleft", "copyright"},
75 {"COPYLEFT", "copyright"},
76 {"define", "command"},
84 {"stdlib", "resource"},
92 EXTERN
char *pager
; /* $PAGER or default */
96 * page_file - output an open file thru a pager
98 * The popen() below is fairly safe. The $PAGER environment variable
99 * (supplied by the user) is the command we need to run without args.
100 * True, the user could set $PAGER is a bogus prog ... but if -m is
101 * 5 or 7 (read and exec allowed), then the calc is given ``permission''
102 * to open the help file for reading as well as to exec the pager!
105 * stream open file stream of the file to send to the pager
108 page_file(FILE *stream
)
110 FILE *cmd
; /* pager command */
111 char buf
[BUFSIZ
+1]; /* I/O buffer */
112 char *fgets_ret
; /* fgets() return value */
115 * flush any pending I/O
122 * form a write pipe to a pager
124 if (pager
== NULL
|| pager
[0] == '\0') {
127 cmd
= popen(pager
, "w");
130 fprintf(stderr
, "unable form pipe to pager: %s", pager
);
135 * read the help file and send non-## lines to the pager
142 * read the next line that does not begin with ##
145 while ((fgets_ret
= fgets(buf
, BUFSIZ
, stream
)) != NULL
&&
146 buf
[0] == '#' && buf
[1] == '#') {
150 * stop reading when we reach EOF (or error) on help file
152 if (fgets_ret
== NULL
) {
158 * write the line to pager, if possible
160 * We have to use fprintf() instead of fputs() because
161 * on NetBSD, fputs() function returns 0 on success and
162 # EOF on error. *sigh*
164 } while (fprintf(cmd
, "%s", buf
) > 0);
167 * all done, EOF or error, so just clean up
178 * givehelp - display a help file
181 * type the type of help to give, NULL => index
186 struct help_alias
*p
; /* help alias being considered */
187 FILE *stream
; /* help file stream */
188 char *helppath
; /* path to the help file */
192 * check permissions to see if we are allowed to help
194 if (!allow_exec
|| !allow_read
) {
196 "sorry, help is only allowed with -m mode 5 or 7\n");
200 /* catch the case where we just print the index */
202 type
= DEFAULTCALCHELP
; /* the help index file */
205 /* alias the type of help, if needed */
206 for (p
=halias
; p
->topic
; ++p
) {
207 if (strcmp(type
, p
->topic
) == 0) {
214 * sanity check on name
216 /* look for /. or a leading . */
217 if (strstr(type
, "/.") != NULL
|| type
[0] == '.') {
218 fprintf(stderr
, "bad help name\n");
221 /* look for chars that could be shell meta chars */
222 for (c
= type
; *c
; ++c
) {
232 if (!isascii((int)*c
) || !isalnum((int)*c
)) {
233 fprintf(stderr
, "bogus char in help name\n");
241 * special case for Copyright and Copyleft
243 if (strcmp(type
, "copyright") == 0) {
244 fputs(Copyright
, stdout
);
250 * open the helpfile (looking in HELPDIR first)
253 if (sizeof(CUSTOMHELPDIR
) > sizeof(HELPDIR
)) {
254 helppath
= (char *)malloc(sizeof(CUSTOMHELPDIR
)+1+strlen(type
));
256 helppath
= (char *)malloc(sizeof(HELPDIR
)+1+strlen(type
));
259 helppath
= (char *)malloc(sizeof(HELPDIR
)+1+strlen(type
));
261 if (helppath
== NULL
) {
262 fprintf(stderr
, "malloc failure in givehelp()\n");
265 sprintf(helppath
, "%s/%s", HELPDIR
, type
);
266 stream
= fopen(helppath
, "r");
267 if (stream
!= NULL
) {
270 * we have the help file open, now display it
273 (void) fclose(stream
);
277 * open the helpfile (looking in CUSTOMHELPDIR last)
281 sprintf(helppath
, "%s/%s", CUSTOMHELPDIR
, type
);
282 stream
= fopen(helppath
, "r");
283 if (stream
== NULL
) {
285 /* no such help file */
287 "%s: no such help file, try: help help\n",
291 /* we have the help file open, now display it */
293 (void) fclose(stream
);