1 /* $OpenBSD: grep.c,v 1.8 2003/04/08 21:19:57 vincent Exp $ */ 2 /* 3 * Copyright (c) 2001 Artur Grabowski <art@openbsd.org>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "def.h" 27 #include "kbd.h" 28 #include "funmap.h" 29 30 static int compile_goto_error(int f, int n); 31 static int next_error(int f, int n); 32 static int grep(int, int); 33 static int compile(int, int); 34 static int gid(int, int); 35 static BUFFER *compile_mode(char *name, char *command); 36 37 38 void grep_init(void); 39 40 static char compile_last_command[NFILEN] = "make "; 41 42 /* 43 * Hints for next-error 44 * 45 * XXX - need some kind of callback to find out when those get killed. 46 */ 47 MGWIN *compile_win; 48 BUFFER *compile_buffer; 49 50 static PF compile_pf[] = { 51 compile_goto_error, 52 }; 53 54 static struct KEYMAPE (1 + IMAPEXT) compilemap = { 55 1, 56 1 + IMAPEXT, 57 rescan, 58 { 59 { CCHR('M'), CCHR('M'), compile_pf, NULL }, 60 } 61 }; 62 63 void 64 grep_init(void) 65 { 66 funmap_add(compile_goto_error, "compile-goto-error"); 67 funmap_add(next_error, "next-error"); 68 funmap_add(grep, "grep"); 69 funmap_add(compile, "compile"); 70 funmap_add(gid, "gid"); 71 maps_add((KEYMAP *)&compilemap, "compile"); 72 } 73 74 static int 75 grep(int f, int n) 76 { 77 char command[NFILEN + 20]; 78 char prompt[NFILEN]; 79 BUFFER *bp; 80 MGWIN *wp; 81 82 (void)strlcpy(prompt, "grep -n ", sizeof prompt); 83 if (eread("Run grep: ", prompt, NFILEN, EFDEF|EFNEW|EFCR) == ABORT) 84 return ABORT; 85 86 (void)snprintf(command, sizeof command, "%s /dev/null", prompt); 87 88 if ((bp = compile_mode("*grep*", command)) == NULL) 89 return FALSE; 90 if ((wp = popbuf(bp)) == NULL) 91 return FALSE; 92 curbp = bp; 93 compile_win = curwp = wp; 94 return TRUE; 95 } 96 97 static int 98 compile(int f, int n) 99 { 100 char command[NFILEN + 20]; 101 char prompt[NFILEN]; 102 BUFFER *bp; 103 MGWIN *wp; 104 105 (void)strlcpy(prompt, compile_last_command, sizeof prompt); 106 if (eread("Compile command: ", prompt, NFILEN, EFDEF|EFNEW|EFCR) == ABORT) 107 return ABORT; 108 (void)strlcpy(compile_last_command, prompt, sizeof compile_last_command); 109 110 (void)snprintf(command, sizeof command, "%s 2>&1", prompt); 111 112 if ((bp = compile_mode("*compile*", command)) == NULL) 113 return FALSE; 114 if ((wp = popbuf(bp)) == NULL) 115 return FALSE; 116 curbp = bp; 117 compile_win = curwp = wp; 118 return TRUE; 119 } 120 121 /* id-utils foo. */ 122 static int 123 gid(int f, int n) 124 { 125 char command[NFILEN + 20]; 126 char prompt[NFILEN]; 127 BUFFER *bp; 128 MGWIN *wp; 129 130 if (eread("Run gid (with args): ", prompt, NFILEN, EFNEW|EFCR) == ABORT) 131 return ABORT; 132 133 (void)snprintf(command, sizeof command, "gid %s", prompt); 134 135 if ((bp = compile_mode("*gid*", command)) == NULL) 136 return FALSE; 137 if ((wp = popbuf(bp)) == NULL) 138 return FALSE; 139 curbp = bp; 140 compile_win = curwp = wp; 141 return TRUE; 142 } 143 144 BUFFER * 145 compile_mode(char *name, char *command) 146 { 147 BUFFER *bp; 148 FILE *pipe; 149 char *buf; 150 size_t len; 151 int ret; 152 153 bp = bfind(name, TRUE); 154 if (bclear(bp) != TRUE) 155 return NULL; 156 157 addlinef(bp, "Running (%s).", command); 158 addline(bp, ""); 159 160 if ((pipe = popen(command, "r")) == NULL) { 161 ewprintf("Problem opening pipe"); 162 return NULL; 163 } 164 /* 165 * We know that our commands are nice and the last line will end with 166 * a \n, so we don't need to try to deal with the last line problem 167 * in fgetln. 168 */ 169 while ((buf = fgetln(pipe, &len)) != NULL) { 170 buf[len - 1] = '\0'; 171 addline(bp, buf); 172 } 173 ret = pclose(pipe); 174 addline(bp, ""); 175 addlinef(bp, "Command (%s) completed %s.", command, 176 ret == 0 ? "successfully" : "with errors"); 177 bp->b_dotp = lforw(bp->b_linep); /* go to first line */ 178 bp->b_modes[0] = name_mode("fundamental"); 179 bp->b_modes[1] = name_mode("compile"); 180 bp->b_nmodes = 1; 181 182 compile_buffer = bp; 183 184 return bp; 185 } 186 187 static int 188 compile_goto_error(int f, int n) 189 { 190 BUFFER *bp; 191 MGWIN *wp; 192 char *fname, *line, *lp, *ln, *lp1; 193 int lineno, len; 194 char *adjf; 195 196 compile_win = curwp; 197 compile_buffer = curbp; 198 199 retry: 200 len = llength(curwp->w_dotp); 201 202 if ((line = malloc(len + 1)) == NULL) 203 return FALSE; 204 205 (void)memcpy(line, curwp->w_dotp->l_text, len); 206 line[len] = '\0'; 207 208 lp = line; 209 if ((fname = strsep(&lp, ":")) == NULL) 210 goto fail; 211 if ((ln = strsep(&lp, ":")) == NULL) 212 goto fail; 213 lineno = strtol(ln, &lp1, 10); 214 if (lp != lp1 + 1) 215 goto fail; 216 free(line); 217 218 adjf = adjustname(fname); 219 if (adjf == NULL) 220 return (FALSE); 221 if ((bp = findbuffer(adjf)) == NULL) 222 return FALSE; 223 if ((wp = popbuf(bp)) == NULL) 224 return FALSE; 225 curbp = bp; 226 curwp = wp; 227 if (bp->b_fname[0] == 0) 228 readin(adjf); 229 gotoline(FFARG, lineno); 230 return TRUE; 231 fail: 232 free(line); 233 if (curwp->w_dotp != lback(curbp->b_linep)) { 234 curwp->w_dotp = lforw(curwp->w_dotp); 235 curwp->w_flag |= WFMOVE; 236 goto retry; 237 } 238 ewprintf("No more hits"); 239 return FALSE; 240 } 241 242 static int 243 next_error(int f, int n) 244 { 245 if (compile_win == NULL || compile_buffer == NULL) { 246 ewprintf("No compilation active"); 247 return FALSE; 248 } 249 curwp = compile_win; 250 curbp = compile_buffer; 251 if (curwp->w_dotp == lback(curbp->b_linep)) { 252 ewprintf("No more hits"); 253 return FALSE; 254 } 255 curwp->w_dotp = lforw(curwp->w_dotp); 256 curwp->w_flag |= WFMOVE; 257 258 return compile_goto_error(f, n); 259 } 260