xref: /freebsd/contrib/tcsh/tw.help.c (revision 6990ffd8a95caaba6858ad44ff1b3157d1efba8f)
1 /* $Header: /src/pub/tcsh/tw.help.c,v 3.17 2000/01/14 22:57:30 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 
42 RCSID("$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 
48 static int f = -1;
49 static	sigret_t	 cleanf		__P((int));
50 static	Char    	*skipslist	__P((Char *));
51 static	void		 nextslist 	__P((Char *, Char *));
52 
53 static char *h_ext[] = {
54     ".help", ".1", ".8", ".6", "", NULL
55 };
56 
57 void
58 do_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 
150 static  sigret_t
151 /*ARGSUSED*/
152 cleanf(snum)
153 int 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 
178 static void
179 nextslist(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 
200 static Char *
201 skipslist(sl)
202     register Char *sl;
203 {
204     while (*sl && *sl++ != ':')
205 	continue;
206     return (sl);
207 }
208