1 /* tw.help.c: actually look up and print documentation on a file.
2 * Look down the path for an appropriate file, then print it.
3 * Note that the printing is NOT PAGED. This is because the
4 * function is NOT meant to look at manual pages, it only does so
5 * if there is no .help file to look in.
8 * Copyright (c) 1980, 1991 The Regents of the University of California.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 static void cleanf (int);
42 static Char
*skipslist (Char
*);
43 static void nextslist (const Char
*, Char
*);
45 static const char *const h_ext
[] = {
46 ".help", ".1", ".8", ".6", "", NULL
50 do_help(const Char
*command
)
54 /* trim off the whitespace at the beginning */
55 while (*command
== ' ' || *command
== '\t')
58 /* copy the string to a safe place */
59 name
= Strsave(command
);
60 cleanup_push(name
, xfree
);
62 /* trim off the whitespace that may be at the end */
64 *cmd_p
!= ' ' && *cmd_p
!= '\t' && *cmd_p
!= '\0'; cmd_p
++)
68 /* if nothing left, return */
74 if (adrof1(STRhelpcommand
, &aliases
)) { /* if we have an alias */
78 getexit(osetexit
); /* make sure to come back here */
79 omark
= cleanup_push_mark();
81 aliasrun(2, STRhelpcommand
, name
); /* then use it. */
82 cleanup_pop_mark(omark
);
83 resexit(osetexit
); /* and finish up */
85 else { /* else cat something to them */
86 Char
*thpath
, *hpath
; /* The environment parameter */
87 Char
*curdir
; /* Current directory being looked at */
88 struct Strbuf full
= Strbuf_INIT
;
90 /* got is, now "cat" the file based on the path $HPATH */
92 hpath
= str2short(getenv(SEARCHLIST
));
94 hpath
= str2short(DEFAULTLIST
);
95 thpath
= hpath
= Strsave(hpath
);
96 cleanup_push(thpath
, xfree
);
97 curdir
= xmalloc((Strlen(thpath
) + 1) * sizeof (*curdir
));
98 cleanup_push(curdir
, xfree
);
99 cleanup_push(&full
, Strbuf_cleanup
);
102 const char *const *sp
;
106 xprintf(CGETS(29, 1, "No help file for %S\n"), name
);
109 nextslist(hpath
, curdir
);
110 hpath
= skipslist(hpath
);
113 * now make the full path name - try first /bar/foo.help, then
114 * /bar/foo.1, /bar/foo.8, then finally /bar/foo.6. This is so
115 * that you don't spit a binary at the tty when $HPATH == $PATH.
118 Strbuf_append(&full
, curdir
);
119 Strbuf_append(&full
, STRslash
);
120 Strbuf_append(&full
, name
);
122 for (sp
= h_ext
; *sp
; sp
++) {
124 Strbuf_append(&full
, str2short(*sp
));
125 Strbuf_terminate(&full
);
126 if ((f
= xopen(short2str(full
.s
), O_RDONLY
|O_LARGEFILE
)) != -1)
130 unsigned char buf
[512];
132 struct sigaction osa
, sa
;
135 /* so cat it to the terminal */
136 cleanup_push(&f
, open_cleanup
);
137 sa
.sa_handler
= cleanf
;
138 sigemptyset(&sa
.sa_mask
);
140 (void)sigaction(SIGINT
, &sa
, &osa
);
141 cleanup_push(&osa
, sigint_cleanup
);
142 (void)sigprocmask(SIG_UNBLOCK
, &set
, &oset
);
143 cleanup_push(&oset
, sigprocmask_cleanup
);
144 while ((len
= xread(f
, buf
, sizeof(buf
))) > 0)
145 (void) xwrite(SHOUT
, buf
, len
);
148 /* print error in case file is migrated */
150 stderror(ERR_SYSTEM
, progname
, strerror(errno
));
169 /* these next two are stolen from CMU's man(1) command for looking down
170 * paths. they are prety straight forward. */
173 * nextslist takes a search list and copies the next path in it
174 * to np. A null search list entry is expanded to ".".
175 * If there are no entries in the search list, then np will point
180 nextslist(const Char
*sl
, Char
*np
)
184 else if (*sl
== ':') {
189 while (*sl
&& *sl
!= ':')
196 * skipslist returns the pointer to the next entry in the search list.
202 while (*sl
&& *sl
++ != ':')