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