tw.help.c revision 59415
1283625Sdim/* $Header: /src/pub/tcsh/tw.help.c,v 3.17 2000/01/14 22:57:30 christos Exp $ */
2283625Sdim/* tw.help.c: actually look up and print documentation on a file.
3353358Sdim *	      Look down the path for an appropriate file, then print it.
4353358Sdim *	      Note that the printing is NOT PAGED.  This is because the
5353358Sdim *	      function is NOT meant to look at manual pages, it only does so
6283625Sdim *	      if there is no .help file to look in.
7283625Sdim */
8283625Sdim/*-
9283625Sdim * Copyright (c) 1980, 1991 The Regents of the University of California.
10283625Sdim * All rights reserved.
11283625Sdim *
12283625Sdim * Redistribution and use in source and binary forms, with or without
13283625Sdim * modification, are permitted provided that the following conditions
14283625Sdim * are met:
15283625Sdim * 1. Redistributions of source code must retain the above copyright
16309124Sdim *    notice, this list of conditions and the following disclaimer.
17283625Sdim * 2. Redistributions in binary form must reproduce the above copyright
18283625Sdim *    notice, this list of conditions and the following disclaimer in the
19283625Sdim *    documentation and/or other materials provided with the distribution.
20283625Sdim * 3. All advertising materials mentioning features or use of this software
21321369Sdim *    must display the following acknowledgement:
22321369Sdim *	This product includes software developed by the University of
23321369Sdim *	California, Berkeley and its contributors.
24321369Sdim * 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.17 2000/01/14 22:57:30 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    USE(snum);
156#ifdef UNRELSIGS
157    if (snum)
158	(void) sigset(SIGINT, cleanf);
159#endif /* UNRELSIGS */
160    if (f != -1)
161	(void) close(f);
162    f = -1;
163#ifndef SIGVOID
164    return (snum);
165#endif
166}
167
168/* these next two are stolen from CMU's man(1) command for looking down
169 * paths.  they are prety straight forward. */
170
171/*
172 * nextslist takes a search list and copies the next path in it
173 * to np.  A null search list entry is expanded to ".".
174 * If there are no entries in the search list, then np will point
175 * to a null string.
176 */
177
178static void
179nextslist(sl, np)
180    register Char *sl;
181    register Char *np;
182{
183    if (!*sl)
184	*np = '\000';
185    else if (*sl == ':') {
186	*np++ = '.';
187	*np = '\000';
188    }
189    else {
190	while (*sl && *sl != ':')
191	    *np++ = *sl++;
192	*np = '\000';
193    }
194}
195
196/*
197 * skipslist returns the pointer to the next entry in the search list.
198 */
199
200static Char *
201skipslist(sl)
202    register Char *sl;
203{
204    while (*sl && *sl++ != ':')
205	continue;
206    return (sl);
207}
208