tw.help.c revision 59243
1/* $Header: /src/pub/tcsh/tw.help.c,v 3.16 1999/05/11 13:08:03 christos Exp $ */
2/* tw.help.c: actually look up and print documentation on a file.
3 *	      Look down the path for an appropriate file, then print it.
4 *	      Note that the printing is NOT PAGED.  This is because the
5 *	      function is NOT meant to look at manual pages, it only does so
6 *	      if there is no .help file to look in.
7 */
8/*-
9 * Copyright (c) 1980, 1991 The Regents of the University of California.
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 *    must display the following acknowledgement:
22 *	This product includes software developed by the University of
23 *	California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 *    may be used to endorse or promote products derived from this software
26 *    without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 */
40#include "sh.h"
41
42RCSID("$Id: tw.help.c,v 3.16 1999/05/11 13:08:03 christos Exp $")
43
44#include "tw.h"
45#include "tc.h"
46
47
48static int f = -1;
49static	sigret_t	 cleanf		__P((int));
50static	Char    	*skipslist	__P((Char *));
51static	void		 nextslist 	__P((Char *, Char *));
52
53static char *h_ext[] = {
54    ".help", ".1", ".8", ".6", "", NULL
55};
56
57void
58do_help(command)
59    Char   *command;
60{
61    Char    name[FILSIZ + 1];
62    Char   *cmd_p, *ep;
63    char  **sp;
64
65    signalfun_t orig_intr;
66    Char    curdir[MAXPATHLEN];	/* Current directory being looked at */
67    register Char *hpath;	/* The environment parameter */
68    Char    full[MAXPATHLEN];
69    char    buf[512];		/* full path name and buffer for read */
70    int     len;		/* length of read buffer */
71    Char   *thpath;
72
73
74    /* trim off the whitespace at the beginning */
75    for (cmd_p = command; *cmd_p == ' ' || *cmd_p == '\t'; cmd_p++)
76	continue;
77
78    /* copy the string to a safe place */
79    copyn(name, cmd_p, FILSIZ + 1);
80
81    /* trim off the whitespace that may be at the end */
82    for (cmd_p = name;
83	 *cmd_p != ' ' && *cmd_p != '\t' && *cmd_p != '\0'; cmd_p++)
84	continue;
85    *cmd_p = '\0';
86
87    /* if nothing left, return */
88    if (*name == '\0')
89	return;
90
91    if (adrof1(STRhelpcommand, &aliases)) {	/* if we have an alias */
92	jmp_buf_t osetexit;
93
94	getexit(osetexit);	/* make sure to come back here */
95	if (setexit() == 0)
96	    aliasrun(2, STRhelpcommand, name);	/* then use it. */
97	resexit(osetexit);	/* and finish up */
98    }
99    else {			/* else cat something to them */
100	/* got is, now "cat" the file based on the path $HPATH */
101
102	hpath = str2short(getenv(SEARCHLIST));
103	if (hpath == NULL)
104	    hpath = str2short(DEFAULTLIST);
105	thpath = hpath = Strsave(hpath);
106
107	for (;;) {
108	    if (!*hpath) {
109		xprintf(CGETS(29, 1, "No help file for %S\n"), name);
110		break;
111	    }
112	    nextslist(hpath, curdir);
113	    hpath = skipslist(hpath);
114
115	    /*
116	     * now make the full path name - try first /bar/foo.help, then
117	     * /bar/foo.1, /bar/foo.8, then finally /bar/foo.6.  This is so
118	     * that you don't spit a binary at the tty when $HPATH == $PATH.
119	     */
120	    copyn(full, curdir, (int) (sizeof(full) / sizeof(Char)));
121	    catn(full, STRslash, (int) (sizeof(full) / sizeof(Char)));
122	    catn(full, name, (int) (sizeof(full) / sizeof(Char)));
123	    ep = &full[Strlen(full)];
124	    for (sp = h_ext; *sp; sp++) {
125		*ep = '\0';
126		catn(full, str2short(*sp), (int) (sizeof(full) / sizeof(Char)));
127		if ((f = open(short2str(full), O_RDONLY)) != -1)
128		    break;
129	    }
130	    if (f != -1) {
131		/* so cat it to the terminal */
132		orig_intr = (signalfun_t) sigset(SIGINT, cleanf);
133		while (f != -1 && (len = read(f, (char *) buf, 512)) > 0)
134		    (void) write(SHOUT, (char *) buf, (size_t) len);
135#ifdef convex
136		/* print error in case file is migrated */
137		if (len == -1)
138		    stderror(ERR_SYSTEM, progname, strerror(errno));
139#endif /* convex */
140		(void) sigset(SIGINT, orig_intr);
141		if (f != -1)
142		    (void) close(f);
143		break;
144	    }
145	}
146	xfree((ptr_t) thpath);
147    }
148}
149
150static  sigret_t
151/*ARGSUSED*/
152cleanf(snum)
153int snum;
154{
155#ifdef UNRELSIGS
156    if (snum)
157	(void) sigset(SIGINT, cleanf);
158#endif /* UNRELSIGS */
159    if (f != -1)
160	(void) close(f);
161    f = -1;
162#ifndef SIGVOID
163    return (snum);
164#endif
165}
166
167/* these next two are stolen from CMU's man(1) command for looking down
168 * paths.  they are prety straight forward. */
169
170/*
171 * nextslist takes a search list and copies the next path in it
172 * to np.  A null search list entry is expanded to ".".
173 * If there are no entries in the search list, then np will point
174 * to a null string.
175 */
176
177static void
178nextslist(sl, np)
179    register Char *sl;
180    register Char *np;
181{
182    if (!*sl)
183	*np = '\000';
184    else if (*sl == ':') {
185	*np++ = '.';
186	*np = '\000';
187    }
188    else {
189	while (*sl && *sl != ':')
190	    *np++ = *sl++;
191	*np = '\000';
192    }
193}
194
195/*
196 * skipslist returns the pointer to the next entry in the search list.
197 */
198
199static Char *
200skipslist(sl)
201    register Char *sl;
202{
203    while (*sl && *sl++ != ':')
204	continue;
205    return (sl);
206}
207