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