[BACK]Return to grep.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/grep.c, Revision 1.46

1.46    ! cheloha     1: /*     $OpenBSD: grep.c,v 1.45 2017/10/12 14:12:00 florian Exp $       */
1.35      kjell       2:
                      3: /* This file is in the public domain */
1.1       art         4:
1.43      bcallah     5: #include <sys/queue.h>
1.18      kjell       6: #include <sys/types.h>
1.46    ! cheloha     7: #include <sys/wait.h>
        !             8:
1.11      vincent     9: #include <ctype.h>
1.18      kjell      10: #include <libgen.h>
1.42      guenther   11: #include <limits.h>
1.43      bcallah    12: #include <signal.h>
                     13: #include <stdio.h>
                     14: #include <stdlib.h>
                     15: #include <string.h>
1.18      kjell      16: #include <time.h>
1.43      bcallah    17: #include <unistd.h>
                     18:
                     19: #include "def.h"
                     20: #include "kbd.h"
                     21: #include "funmap.h"
1.11      vincent    22:
1.34      kjell      23: int     globalwd = FALSE;
1.13      db         24: static int      compile_goto_error(int, int);
1.17      kjell      25: int             next_error(int, int);
1.13      db         26: static int      grep(int, int);
                     27: static int      gid(int, int);
1.28      kjell      28: static struct buffer   *compile_mode(const char *, const char *);
1.1       art        29: void grep_init(void);
                     30:
1.8       vincent    31: static char compile_last_command[NFILEN] = "make ";
                     32:
1.1       art        33: /*
                     34:  * Hints for next-error
                     35:  *
                     36:  * XXX - need some kind of callback to find out when those get killed.
                     37:  */
1.24      deraadt    38: struct mgwin   *compile_win;
                     39: struct buffer  *compile_buffer;
1.1       art        40:
                     41: static PF compile_pf[] = {
1.13      db         42:        compile_goto_error
1.1       art        43: };
                     44:
1.44      bcallah    45: static struct KEYMAPE (1) compilemap = {
                     46:        1,
1.1       art        47:        1,
                     48:        rescan,
                     49:        {
1.13      db         50:                { CCHR('M'), CCHR('M'), compile_pf, NULL }
1.1       art        51:        }
                     52: };
                     53:
                     54: void
                     55: grep_init(void)
                     56: {
                     57:        funmap_add(compile_goto_error, "compile-goto-error");
                     58:        funmap_add(next_error, "next-error");
                     59:        funmap_add(grep, "grep");
                     60:        funmap_add(compile, "compile");
                     61:        funmap_add(gid, "gid");
                     62:        maps_add((KEYMAP *)&compilemap, "compile");
                     63: }
                     64:
1.20      kjell      65: /* ARGSUSED */
1.1       art        66: static int
                     67: grep(int f, int n)
                     68: {
1.25      kjell      69:        char     cprompt[NFILEN], *bufp;
1.24      deraadt    70:        struct buffer   *bp;
                     71:        struct mgwin    *wp;
1.1       art        72:
1.25      kjell      73:        (void)strlcpy(cprompt, "grep -n ", sizeof(cprompt));
                     74:        if ((bufp = eread("Run grep: ", cprompt, NFILEN,
1.16      kjell      75:            EFDEF | EFNEW | EFCR)) == NULL)
1.13      db         76:                return (ABORT);
1.16      kjell      77:        else if (bufp[0] == '\0')
                     78:                return (FALSE);
1.29      kjell      79:        if (strlcat(cprompt, " /dev/null", sizeof(cprompt)) >= sizeof(cprompt))
                     80:                return (FALSE);
1.1       art        81:
1.29      kjell      82:        if ((bp = compile_mode("*grep*", cprompt)) == NULL)
1.25      kjell      83:                return (FALSE);
1.38      kjell      84:        if ((wp = popbuf(bp, WNONE)) == NULL)
1.25      kjell      85:                return (FALSE);
                     86:        curbp = bp;
                     87:        compile_win = curwp = wp;
                     88:        return (TRUE);
                     89: }
                     90:
                     91: /* ARGSUSED */
1.36      kjell      92: int
1.1       art        93: compile(int f, int n)
                     94: {
1.25      kjell      95:        char     cprompt[NFILEN], *bufp;
1.24      deraadt    96:        struct buffer   *bp;
                     97:        struct mgwin    *wp;
1.1       art        98:
1.25      kjell      99:        (void)strlcpy(cprompt, compile_last_command, sizeof(cprompt));
                    100:        if ((bufp = eread("Compile command: ", cprompt, NFILEN,
1.16      kjell     101:            EFDEF | EFNEW | EFCR)) == NULL)
1.14      jason     102:                return (ABORT);
1.16      kjell     103:        else if (bufp[0] == '\0')
                    104:                return (FALSE);
1.14      jason     105:        if (savebuffers(f, n) == ABORT)
1.13      db        106:                return (ABORT);
                    107:        (void)strlcpy(compile_last_command, bufp, sizeof(compile_last_command));
1.1       art       108:
1.29      kjell     109:        if ((bp = compile_mode("*compile*", cprompt)) == NULL)
1.13      db        110:                return (FALSE);
1.38      kjell     111:        if ((wp = popbuf(bp, WNONE)) == NULL)
1.13      db        112:                return (FALSE);
1.1       art       113:        curbp = bp;
                    114:        compile_win = curwp = wp;
1.27      kjell     115:        gotoline(FFARG, 0);
1.13      db        116:        return (TRUE);
1.1       art       117: }
                    118:
                    119: /* id-utils foo. */
1.20      kjell     120: /* ARGSUSED */
1.1       art       121: static int
                    122: gid(int f, int n)
                    123: {
1.29      kjell     124:        char     command[NFILEN];
1.41      guenther  125:        char     cprompt[NFILEN], *bufp;
                    126:        int     c;
1.24      deraadt   127:        struct buffer   *bp;
                    128:        struct mgwin    *wp;
1.29      kjell     129:        int      i, j, len;
1.1       art       130:
1.11      vincent   131:        /* catch ([^\s(){}]+)[\s(){}]* */
                    132:
                    133:        i = curwp->w_doto;
1.15      cloder    134:        /* Skip backwards over delimiters we are currently on */
                    135:        while (i > 0) {
                    136:                c = lgetc(curwp->w_dotp, i);
                    137:                if (isalnum(c) || c == '_')
                    138:                        break;
                    139:
1.11      vincent   140:                i--;
1.15      cloder    141:        }
                    142:
1.11      vincent   143:        /* Skip the symbol itself */
                    144:        for (; i > 0; i--) {
                    145:                c = lgetc(curwp->w_dotp, i - 1);
1.15      cloder    146:                if (!isalnum(c) && c != '_')
1.11      vincent   147:                        break;
                    148:        }
1.25      kjell     149:        /* Fill the symbol in cprompt[] */
                    150:        for (j = 0; j < sizeof(cprompt) - 1 && i < llength(curwp->w_dotp);
1.11      vincent   151:            j++, i++) {
                    152:                c = lgetc(curwp->w_dotp, i);
1.15      cloder    153:                if (!isalnum(c) && c != '_')
1.11      vincent   154:                        break;
1.25      kjell     155:                cprompt[j] = c;
1.11      vincent   156:        }
1.25      kjell     157:        cprompt[j] = '\0';
1.11      vincent   158:
1.25      kjell     159:        if ((bufp = eread("Run gid (with args): ", cprompt, NFILEN,
1.16      kjell     160:            (j ? EFDEF : 0) | EFNEW | EFCR)) == NULL)
1.13      db        161:                return (ABORT);
1.16      kjell     162:        else if (bufp[0] == '\0')
                    163:                return (FALSE);
1.29      kjell     164:        len = snprintf(command, sizeof(command), "gid %s", cprompt);
                    165:        if (len < 0 || len >= sizeof(command))
                    166:                return (FALSE);
1.1       art       167:
1.28      kjell     168:        if ((bp = compile_mode("*gid*", command)) == NULL)
1.13      db        169:                return (FALSE);
1.38      kjell     170:        if ((wp = popbuf(bp, WNONE)) == NULL)
1.13      db        171:                return (FALSE);
1.1       art       172:        curbp = bp;
                    173:        compile_win = curwp = wp;
1.13      db        174:        return (TRUE);
1.1       art       175: }
                    176:
1.24      deraadt   177: struct buffer *
1.28      kjell     178: compile_mode(const char *name, const char *command)
1.1       art       179: {
1.24      deraadt   180:        struct buffer   *bp;
1.26      kjell     181:        FILE    *fpipe;
1.13      db        182:        char    *buf;
1.45      florian   183:        size_t   sz;
                    184:        ssize_t  len;
1.46    ! cheloha   185:        int      ret, n, status;
1.29      kjell     186:        char     cwd[NFILEN], qcmd[NFILEN];
1.18      kjell     187:        char     timestr[NTIME];
                    188:        time_t   t;
1.1       art       189:
1.45      florian   190:        buf = NULL;
                    191:        sz = 0;
                    192:
1.29      kjell     193:        n = snprintf(qcmd, sizeof(qcmd), "%s 2>&1", command);
                    194:        if (n < 0 || n >= sizeof(qcmd))
                    195:                return (NULL);
                    196:
1.1       art       197:        bp = bfind(name, TRUE);
                    198:        if (bclear(bp) != TRUE)
1.13      db        199:                return (NULL);
1.1       art       200:
1.28      kjell     201:        if (getbufcwd(bp->b_cwd, sizeof(bp->b_cwd)) != TRUE)
                    202:                return (NULL);
                    203:        addlinef(bp, "cd %s", bp->b_cwd);
1.29      kjell     204:        addline(bp, qcmd);
1.1       art       205:        addline(bp, "");
                    206:
1.23      deraadt   207:        if (getcwd(cwd, sizeof(cwd)) == NULL)
1.18      kjell     208:                panic("Can't get current directory!");
1.28      kjell     209:        if (chdir(bp->b_cwd) == -1) {
1.40      lum       210:                dobeep();
1.28      kjell     211:                ewprintf("Can't change dir to %s", bp->b_cwd);
1.18      kjell     212:                return (NULL);
1.19      deraadt   213:        }
1.29      kjell     214:        if ((fpipe = popen(qcmd, "r")) == NULL) {
1.40      lum       215:                dobeep();
1.1       art       216:                ewprintf("Problem opening pipe");
1.13      db        217:                return (NULL);
1.1       art       218:        }
1.45      florian   219:        while ((len = getline(&buf, &sz, fpipe)) != -1) {
                    220:                if (buf[len - 1] == '\n')
                    221:                        buf[len - 1] = '\0';
1.1       art       222:                addline(bp, buf);
                    223:        }
1.45      florian   224:        free(buf);
                    225:        if (ferror(fpipe))
                    226:                ewprintf("Problem reading pipe");
1.26      kjell     227:        ret = pclose(fpipe);
1.18      kjell     228:        t = time(NULL);
                    229:        strftime(timestr, sizeof(timestr), "%a %b %e %T %Y", localtime(&t));
1.1       art       230:        addline(bp, "");
1.46    ! cheloha   231:        if (WIFEXITED(ret)) {
        !           232:                status = WEXITSTATUS(ret);
        !           233:                if (status == 0)
        !           234:                        addlinef(bp, "Command finished at %s", timestr);
        !           235:                else
        !           236:                        addlinef(bp, "Command exited abnormally with code %d "
        !           237:                            "at %s", status, timestr);
        !           238:        } else
        !           239:                addlinef(bp, "Subshell killed by signal %d at %s",
        !           240:                    WTERMSIG(ret), timestr);
1.18      kjell     241:
1.32      kjell     242:        bp->b_dotp = bfirstlp(bp);
1.1       art       243:        bp->b_modes[0] = name_mode("fundamental");
                    244:        bp->b_modes[1] = name_mode("compile");
                    245:        bp->b_nmodes = 1;
                    246:
                    247:        compile_buffer = bp;
                    248:
1.18      kjell     249:        if (chdir(cwd) == -1) {
1.40      lum       250:                dobeep();
1.18      kjell     251:                ewprintf("Can't change dir back to %s", cwd);
                    252:                return (NULL);
1.19      deraadt   253:        }
1.13      db        254:        return (bp);
1.1       art       255: }
                    256:
1.20      kjell     257: /* ARGSUSED */
1.1       art       258: static int
                    259: compile_goto_error(int f, int n)
                    260: {
1.24      deraadt   261:        struct buffer   *bp;
                    262:        struct mgwin    *wp;
1.21      kjell     263:        char    *fname, *line, *lp, *ln;
1.29      kjell     264:        int      lineno;
1.28      kjell     265:        char    *adjf, path[NFILEN];
1.21      kjell     266:        const char *errstr;
1.24      deraadt   267:        struct line     *last;
1.1       art       268:
                    269:        compile_win = curwp;
                    270:        compile_buffer = curbp;
1.32      kjell     271:        last = blastlp(compile_buffer);
1.22      deraadt   272:
1.21      kjell     273:  retry:
                    274:        /* last line is compilation result */
                    275:        if (curwp->w_dotp == last)
                    276:                return (FALSE);
1.33      deraadt   277:
1.29      kjell     278:        if ((line = linetostr(curwp->w_dotp)) == NULL)
1.13      db        279:                return (FALSE);
1.1       art       280:        lp = line;
1.21      kjell     281:        if ((fname = strsep(&lp, ":")) == NULL || *fname == '\0')
1.1       art       282:                goto fail;
1.21      kjell     283:        if ((ln = strsep(&lp, ":")) == NULL || *ln == '\0')
1.1       art       284:                goto fail;
1.24      deraadt   285:        lineno = (int)strtonum(ln, INT_MIN, INT_MAX, &errstr);
1.21      kjell     286:        if (errstr)
1.1       art       287:                goto fail;
1.33      deraadt   288:
1.28      kjell     289:        if (fname && fname[0] != '/') {
1.34      kjell     290:                if (getbufcwd(path, sizeof(path)) == FALSE)
                    291:                        goto fail;
1.28      kjell     292:                if (strlcat(path, fname, sizeof(path)) >= sizeof(path))
                    293:                        goto fail;
                    294:                adjf = path;
                    295:        } else {
1.30      jason     296:                adjf = adjustname(fname, TRUE);
1.28      kjell     297:        }
1.1       art       298:        free(line);
                    299:
1.7       vincent   300:        if (adjf == NULL)
                    301:                return (FALSE);
1.10      vincent   302:
1.1       art       303:        if ((bp = findbuffer(adjf)) == NULL)
1.13      db        304:                return (FALSE);
1.38      kjell     305:        if ((wp = popbuf(bp, WNONE)) == NULL)
1.13      db        306:                return (FALSE);
1.1       art       307:        curbp = bp;
                    308:        curwp = wp;
1.27      kjell     309:        if (bp->b_fname[0] == '\0')
1.1       art       310:                readin(adjf);
                    311:        gotoline(FFARG, lineno);
1.13      db        312:        return (TRUE);
1.1       art       313: fail:
1.3       deraadt   314:        free(line);
1.32      kjell     315:        if (curwp->w_dotp != blastlp(curbp)) {
1.1       art       316:                curwp->w_dotp = lforw(curwp->w_dotp);
1.37      kjell     317:                curwp->w_rflag |= WFMOVE;
1.1       art       318:                goto retry;
                    319:        }
1.40      lum       320:        dobeep();
1.1       art       321:        ewprintf("No more hits");
1.13      db        322:        return (FALSE);
1.1       art       323: }
                    324:
1.20      kjell     325: /* ARGSUSED */
1.17      kjell     326: int
1.1       art       327: next_error(int f, int n)
                    328: {
                    329:        if (compile_win == NULL || compile_buffer == NULL) {
1.40      lum       330:                dobeep();
1.1       art       331:                ewprintf("No compilation active");
1.13      db        332:                return (FALSE);
1.1       art       333:        }
                    334:        curwp = compile_win;
                    335:        curbp = compile_buffer;
1.32      kjell     336:        if (curwp->w_dotp == blastlp(curbp)) {
1.40      lum       337:                dobeep();
1.1       art       338:                ewprintf("No more hits");
1.13      db        339:                return (FALSE);
1.1       art       340:        }
                    341:        curwp->w_dotp = lforw(curwp->w_dotp);
1.37      kjell     342:        curwp->w_rflag |= WFMOVE;
1.1       art       343:
1.13      db        344:        return (compile_goto_error(f, n));
1.34      kjell     345: }
                    346:
                    347: /*
                    348:  * Since we don't have variables (we probably should) these are command
                    349:  * processors for changing the values of mode flags.
                    350:  */
                    351: /* ARGSUSED */
                    352: int
                    353: globalwdtoggle(int f, int n)
                    354: {
                    355:        if (f & FFARG)
                    356:                globalwd = n > 0;
                    357:        else
                    358:                globalwd = !globalwd;
                    359:
                    360:        sgarbf = TRUE;
                    361:
                    362:        return (TRUE);
1.1       art       363: }