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