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

Annotation of src/usr.bin/mg/region.c, Revision 1.30

1.30    ! lum         1: /*     $OpenBSD: region.c,v 1.29 2009/06/05 18:02:06 kjell Exp $       */
1.17      kjell       2:
                      3: /* This file is in the public domain. */
1.4       niklas      4:
1.1       deraadt     5: /*
                      6:  *             Region based commands.
1.6       mickey      7:  * The routines in this file deal with the region, that magic space between
1.3       millert     8:  * "." and mark.  Some functions are commands.  Some functions are just for
1.1       deraadt     9:  * internal use.
                     10:  */
1.3       millert    11:
1.30    ! lum        12: #include <sys/types.h>
        !            13: #include <sys/socket.h>
        !            14:
        !            15: #include <fcntl.h>
        !            16: #include <poll.h>
        !            17: #include <string.h>
        !            18: #include <unistd.h>
        !            19:
1.3       millert    20: #include "def.h"
                     21:
1.30    ! lum        22: #define TIMEOUT 10000
        !            23:
        !            24: static char leftover[BUFSIZ];
        !            25:
1.19      deraadt    26: static int     getregion(struct region *);
1.30    ! lum        27: static int     iomux(int);
        !            28: static int     pipeio(const char *);
        !            29: static int     preadin(int, struct buffer *);
        !            30: static void    pwriteout(int, char **, int *);
1.19      deraadt    31: static int     setsize(struct region *, RSIZE);
1.1       deraadt    32:
                     33: /*
1.3       millert    34:  * Kill the region.  Ask "getregion" to figure out the bounds of the region.
1.26      kjell      35:  * Move "." to the start, and kill the characters. Mark is cleared afterwards.
1.1       deraadt    36:  */
1.2       millert    37: /* ARGSUSED */
1.3       millert    38: int
1.12      cloder     39: killregion(int f, int n)
1.1       deraadt    40: {
1.3       millert    41:        int     s;
1.19      deraadt    42:        struct region   region;
1.1       deraadt    43:
1.2       millert    44:        if ((s = getregion(&region)) != TRUE)
1.1       deraadt    45:                return (s);
1.3       millert    46:        /* This is a kill-type command, so do magic kill buffer stuff. */
                     47:        if ((lastflag & CFKILL) == 0)
                     48:                kdelete();
                     49:        thisflag |= CFKILL;
1.1       deraadt    50:        curwp->w_dotp = region.r_linep;
                     51:        curwp->w_doto = region.r_offset;
1.28      kjell      52:        curwp->w_dotline = region.r_lineno;
1.29      kjell      53:        s = ldelete(region.r_size, KFORW | KREG);
1.26      kjell      54:        clearmark(FFARG, 0);
                     55:
1.23      kjell      56:        return (s);
1.1       deraadt    57: }
                     58:
                     59: /*
1.26      kjell      60:  * Copy all of the characters in the region to the kill buffer,
                     61:  * clearing the mark afterwards.
                     62:  * This is a bit like a kill region followed by a yank.
1.1       deraadt    63:  */
1.2       millert    64: /* ARGSUSED */
1.3       millert    65: int
1.12      cloder     66: copyregion(int f, int n)
1.1       deraadt    67: {
1.19      deraadt    68:        struct line     *linep;
                     69:        struct region    region;
1.3       millert    70:        int      loffs;
                     71:        int      s;
1.1       deraadt    72:
1.2       millert    73:        if ((s = getregion(&region)) != TRUE)
1.15      db         74:                return (s);
1.3       millert    75:
                     76:        /* kill type command */
                     77:        if ((lastflag & CFKILL) == 0)
1.1       deraadt    78:                kdelete();
                     79:        thisflag |= CFKILL;
1.3       millert    80:
                     81:        /* current line */
                     82:        linep = region.r_linep;
                     83:
                     84:        /* current offset */
                     85:        loffs = region.r_offset;
                     86:
1.1       deraadt    87:        while (region.r_size--) {
1.2       millert    88:                if (loffs == llength(linep)) {  /* End of line.          */
                     89:                        if ((s = kinsert('\n', KFORW)) != TRUE)
1.1       deraadt    90:                                return (s);
                     91:                        linep = lforw(linep);
                     92:                        loffs = 0;
1.3       millert    93:                } else {                        /* Middle of line.       */
1.2       millert    94:                        if ((s = kinsert(lgetc(linep, loffs), KFORW)) != TRUE)
1.15      db         95:                                return (s);
1.1       deraadt    96:                        ++loffs;
                     97:                }
                     98:        }
1.26      kjell      99:        clearmark(FFARG, 0);
                    100:
1.15      db        101:        return (TRUE);
1.1       deraadt   102: }
                    103:
                    104: /*
1.6       mickey    105:  * Lower case region.  Zap all of the upper case characters in the region to
                    106:  * lower case. Use the region code to set the limits. Scan the buffer, doing
                    107:  * the changes. Call "lchange" to ensure that redisplay is done in all
1.3       millert   108:  * buffers.
1.1       deraadt   109:  */
1.2       millert   110: /* ARGSUSED */
1.3       millert   111: int
1.12      cloder    112: lowerregion(int f, int n)
1.1       deraadt   113: {
1.19      deraadt   114:        struct line     *linep;
                    115:        struct region    region;
1.3       millert   116:        int      loffs, c, s;
1.1       deraadt   117:
1.27      kjell     118:        if ((s = checkdirty(curbp)) != TRUE)
                    119:                return (s);
1.10      vincent   120:        if (curbp->b_flag & BFREADONLY) {
                    121:                ewprintf("Buffer is read-only");
                    122:                return (FALSE);
                    123:        }
                    124:
1.2       millert   125:        if ((s = getregion(&region)) != TRUE)
1.15      db        126:                return (s);
1.9       vincent   127:
                    128:        undo_add_change(region.r_linep, region.r_offset, region.r_size);
1.11      deraadt   129:
1.22      kjell     130:        lchange(WFFULL);
1.1       deraadt   131:        linep = region.r_linep;
                    132:        loffs = region.r_offset;
                    133:        while (region.r_size--) {
                    134:                if (loffs == llength(linep)) {
                    135:                        linep = lforw(linep);
                    136:                        loffs = 0;
                    137:                } else {
                    138:                        c = lgetc(linep, loffs);
                    139:                        if (ISUPPER(c) != FALSE)
                    140:                                lputc(linep, loffs, TOLOWER(c));
                    141:                        ++loffs;
                    142:                }
                    143:        }
1.15      db        144:        return (TRUE);
1.1       deraadt   145: }
                    146:
                    147: /*
1.6       mickey    148:  * Upper case region.  Zap all of the lower case characters in the region to
1.3       millert   149:  * upper case.  Use the region code to set the limits.  Scan the buffer,
1.6       mickey    150:  * doing the changes.  Call "lchange" to ensure that redisplay is done in all
1.3       millert   151:  * buffers.
1.1       deraadt   152:  */
1.2       millert   153: /* ARGSUSED */
1.3       millert   154: int
1.12      cloder    155: upperregion(int f, int n)
1.1       deraadt   156: {
1.19      deraadt   157:        struct line      *linep;
                    158:        struct region     region;
1.3       millert   159:        int       loffs, c, s;
1.1       deraadt   160:
1.27      kjell     161:        if ((s = checkdirty(curbp)) != TRUE)
                    162:                return (s);
1.10      vincent   163:        if (curbp->b_flag & BFREADONLY) {
                    164:                ewprintf("Buffer is read-only");
                    165:                return (FALSE);
                    166:        }
1.2       millert   167:        if ((s = getregion(&region)) != TRUE)
1.15      db        168:                return (s);
1.11      deraadt   169:
1.9       vincent   170:        undo_add_change(region.r_linep, region.r_offset, region.r_size);
1.11      deraadt   171:
1.22      kjell     172:        lchange(WFFULL);
1.1       deraadt   173:        linep = region.r_linep;
                    174:        loffs = region.r_offset;
                    175:        while (region.r_size--) {
                    176:                if (loffs == llength(linep)) {
                    177:                        linep = lforw(linep);
                    178:                        loffs = 0;
                    179:                } else {
                    180:                        c = lgetc(linep, loffs);
                    181:                        if (ISLOWER(c) != FALSE)
                    182:                                lputc(linep, loffs, TOUPPER(c));
                    183:                        ++loffs;
                    184:                }
                    185:        }
1.15      db        186:        return (TRUE);
1.1       deraadt   187: }
                    188:
                    189: /*
1.6       mickey    190:  * This routine figures out the bound of the region in the current window,
                    191:  * and stores the results into the fields of the REGION structure. Dot and
                    192:  * mark are usually close together, but I don't know the order, so I scan
                    193:  * outward from dot, in both directions, looking for mark. The size is kept
                    194:  * in a long. At the end, after the size is figured out, it is assigned to
                    195:  * the size field of the region structure. If this assignment loses any bits,
                    196:  * then we print an error. This is "type independent" overflow checking. All
                    197:  * of the callers of this routine should be ready to get an ABORT status,
1.15      db        198:  * because I might add a "if regions is big, ask before clobbering" flag.
1.1       deraadt   199:  */
1.3       millert   200: static int
1.19      deraadt   201: getregion(struct region *rp)
1.2       millert   202: {
1.19      deraadt   203:        struct line     *flp, *blp;
1.3       millert   204:        long     fsize, bsize;
1.1       deraadt   205:
                    206:        if (curwp->w_markp == NULL) {
                    207:                ewprintf("No mark set in this window");
                    208:                return (FALSE);
                    209:        }
1.3       millert   210:
                    211:        /* "r_size" always ok */
                    212:        if (curwp->w_dotp == curwp->w_markp) {
1.1       deraadt   213:                rp->r_linep = curwp->w_dotp;
1.28      kjell     214:                rp->r_lineno = curwp->w_dotline;
1.1       deraadt   215:                if (curwp->w_doto < curwp->w_marko) {
                    216:                        rp->r_offset = curwp->w_doto;
1.3       millert   217:                        rp->r_size = (RSIZE)(curwp->w_marko - curwp->w_doto);
1.1       deraadt   218:                } else {
                    219:                        rp->r_offset = curwp->w_marko;
1.3       millert   220:                        rp->r_size = (RSIZE)(curwp->w_doto - curwp->w_marko);
1.1       deraadt   221:                }
1.15      db        222:                return (TRUE);
1.1       deraadt   223:        }
1.3       millert   224:        /* get region size */
                    225:        flp = blp = curwp->w_dotp;
1.1       deraadt   226:        bsize = curwp->w_doto;
1.2       millert   227:        fsize = llength(flp) - curwp->w_doto + 1;
1.24      kjell     228:        while (lforw(flp) != curbp->b_headp || lback(blp) != curbp->b_headp) {
                    229:                if (lforw(flp) != curbp->b_headp) {
1.1       deraadt   230:                        flp = lforw(flp);
                    231:                        if (flp == curwp->w_markp) {
                    232:                                rp->r_linep = curwp->w_dotp;
                    233:                                rp->r_offset = curwp->w_doto;
1.28      kjell     234:                                rp->r_lineno = curwp->w_dotline;
1.1       deraadt   235:                                return (setsize(rp,
1.3       millert   236:                                    (RSIZE)(fsize + curwp->w_marko)));
1.1       deraadt   237:                        }
1.2       millert   238:                        fsize += llength(flp) + 1;
1.1       deraadt   239:                }
1.24      kjell     240:                if (lback(blp) != curbp->b_headp) {
1.1       deraadt   241:                        blp = lback(blp);
1.2       millert   242:                        bsize += llength(blp) + 1;
1.1       deraadt   243:                        if (blp == curwp->w_markp) {
                    244:                                rp->r_linep = blp;
                    245:                                rp->r_offset = curwp->w_marko;
1.28      kjell     246:                                rp->r_lineno = curwp->w_markline;
1.1       deraadt   247:                                return (setsize(rp,
1.3       millert   248:                                    (RSIZE)(bsize - curwp->w_marko)));
1.1       deraadt   249:                        }
                    250:                }
                    251:        }
1.3       millert   252:        ewprintf("Bug: lost mark");
1.15      db        253:        return (FALSE);
1.1       deraadt   254: }
                    255:
                    256: /*
                    257:  * Set size, and check for overflow.
                    258:  */
1.3       millert   259: static int
1.19      deraadt   260: setsize(struct region *rp, RSIZE size)
1.2       millert   261: {
1.1       deraadt   262:        rp->r_size = size;
                    263:        if (rp->r_size != size) {
                    264:                ewprintf("Region is too large");
1.15      db        265:                return (FALSE);
1.1       deraadt   266:        }
1.15      db        267:        return (TRUE);
1.1       deraadt   268: }
                    269:
                    270: #define PREFIXLENGTH 40
1.3       millert   271: static char    prefix_string[PREFIXLENGTH] = {'>', '\0'};
1.1       deraadt   272:
                    273: /*
1.6       mickey    274:  * Prefix the region with whatever is in prefix_string.  Leaves dot at the
                    275:  * beginning of the line after the end of the region.  If an argument is
1.3       millert   276:  * given, prompts for the line prefix string.
1.1       deraadt   277:  */
1.2       millert   278: /* ARGSUSED */
1.3       millert   279: int
1.12      cloder    280: prefixregion(int f, int n)
1.1       deraadt   281: {
1.19      deraadt   282:        struct line     *first, *last;
                    283:        struct region    region;
1.3       millert   284:        char    *prefix = prefix_string;
                    285:        int      nline;
                    286:        int      s;
1.1       deraadt   287:
1.27      kjell     288:        if ((s = checkdirty(curbp)) != TRUE)
                    289:                return (s);
1.10      vincent   290:        if (curbp->b_flag & BFREADONLY) {
                    291:                ewprintf("Buffer is read-only");
                    292:                return (FALSE);
                    293:        }
1.1       deraadt   294:        if ((f == TRUE) && ((s = setprefix(FFRAND, 1)) != TRUE))
1.15      db        295:                return (s);
1.1       deraadt   296:
                    297:        /* get # of lines to affect */
                    298:        if ((s = getregion(&region)) != TRUE)
                    299:                return (s);
                    300:        first = region.r_linep;
                    301:        last = (first == curwp->w_dotp) ? curwp->w_markp : curwp->w_dotp;
                    302:        for (nline = 1; first != last; nline++)
                    303:                first = lforw(first);
                    304:
1.2       millert   305:        /* move to beginning of region */
1.1       deraadt   306:        curwp->w_dotp = region.r_linep;
                    307:        curwp->w_doto = region.r_offset;
1.28      kjell     308:        curwp->w_dotline = region.r_lineno;
1.1       deraadt   309:
                    310:        /* for each line, go to beginning and insert the prefix string */
                    311:        while (nline--) {
1.5       art       312:                (void)gotobol(FFRAND, 1);
1.1       deraadt   313:                for (prefix = prefix_string; *prefix; prefix++)
1.5       art       314:                        (void)linsert(1, *prefix);
                    315:                (void)forwline(FFRAND, 1);
1.1       deraadt   316:        }
1.5       art       317:        (void)gotobol(FFRAND, 1);
1.15      db        318:        return (TRUE);
1.1       deraadt   319: }
                    320:
                    321: /*
1.25      kjell     322:  * Set line prefix string. Used by prefixregion.
1.1       deraadt   323:  */
1.2       millert   324: /* ARGSUSED */
1.3       millert   325: int
1.12      cloder    326: setprefix(int f, int n)
1.1       deraadt   327: {
1.14      vincent   328:        char    buf[PREFIXLENGTH], *rep;
1.15      db        329:        int     retval;
1.1       deraadt   330:
                    331:        if (prefix_string[0] == '\0')
1.18      kjell     332:                rep = eread("Prefix string: ", buf, sizeof(buf),
                    333:                    EFNEW | EFCR);
1.1       deraadt   334:        else
1.18      kjell     335:                rep = eread("Prefix string (default %s): ", buf, sizeof(buf),
                    336:                    EFNUL | EFNEW | EFCR, prefix_string);
                    337:        if (rep == NULL)
                    338:                return (ABORT);
                    339:        if (rep[0] != '\0') {
1.15      db        340:                (void)strlcpy(prefix_string, rep, sizeof(prefix_string));
1.14      vincent   341:                retval = TRUE;
1.18      kjell     342:        } else if (rep[0] == '\0' && prefix_string[0] != '\0') {
1.14      vincent   343:                /* CR -- use old one */
                    344:                retval = TRUE;
                    345:        } else
                    346:                retval = FALSE;
1.15      db        347:        return (retval);
1.1       deraadt   348: }
1.9       vincent   349:
                    350: int
1.19      deraadt   351: region_get_data(struct region *reg, char *buf, int len)
1.9       vincent   352: {
1.15      db        353:        int      i, off;
1.19      deraadt   354:        struct line     *lp;
1.11      deraadt   355:
1.9       vincent   356:        off = reg->r_offset;
                    357:        lp = reg->r_linep;
1.13      vincent   358:        for (i = 0; i < len; i++) {
1.9       vincent   359:                if (off == llength(lp)) {
                    360:                        lp = lforw(lp);
1.24      kjell     361:                        if (lp == curbp->b_headp)
1.9       vincent   362:                                break;
                    363:                        off = 0;
                    364:                        buf[i] = '\n';
                    365:                } else {
                    366:                        buf[i] = lgetc(lp, off);
                    367:                        off++;
                    368:                }
                    369:        }
1.13      vincent   370:        buf[i] = '\0';
1.15      db        371:        return (i);
1.9       vincent   372: }
                    373:
1.20      kjell     374: void
1.9       vincent   375: region_put_data(const char *buf, int len)
                    376: {
                    377:        int i;
                    378:
1.21      kjell     379:        for (i = 0; buf[i] != '\0' && i < len; i++) {
1.9       vincent   380:                if (buf[i] == '\n')
                    381:                        lnewline();
                    382:                else
                    383:                        linsert(1, buf[i]);
                    384:        }
1.30    ! lum       385: }
        !           386:
        !           387: /*
        !           388:  * Mark whole buffer by first traversing to end-of-buffer
        !           389:  * and then to beginning-of-buffer. Mark, dot are implicitly
        !           390:  * set to eob, bob respectively during traversal.
        !           391:  */
        !           392: int
        !           393: markbuffer(int f, int n)
        !           394: {
        !           395:        if (gotoeob(f,n) == FALSE)
        !           396:                return (FALSE);
        !           397:        if (gotobob(f,n) == FALSE)
        !           398:                return (FALSE);
        !           399:        return (TRUE);
        !           400: }
        !           401:
        !           402: /*
        !           403:  * Pipe text from current region to external command.
        !           404:  */
        !           405: /*ARGSUSED */
        !           406: int
        !           407: piperegion(int f, int n)
        !           408: {
        !           409:        char *cmd, cmdbuf[NFILEN];
        !           410:
        !           411:        /* C-u M-| is not supported yet */
        !           412:        if (n > 1)
        !           413:                return (ABORT);
        !           414:
        !           415:        if (curwp->w_markp == NULL) {
        !           416:                ewprintf("The mark is not set now, so there is no region");
        !           417:                return (FALSE);
        !           418:        }
        !           419:        if ((cmd = eread("Shell command on region: ", cmdbuf, sizeof(cmdbuf),
        !           420:            EFNEW | EFCR)) == NULL || (cmd[0] == '\0'))
        !           421:                return (ABORT);
        !           422:
        !           423:        return (pipeio(cmdbuf));
        !           424: }
        !           425:
        !           426: /*
        !           427:  * Create a socketpair, fork and execl cmd passed. STDIN, STDOUT
        !           428:  * and STDERR of child process are redirected to socket.
        !           429:  */
        !           430: int
        !           431: pipeio(const char* const cmd)
        !           432: {
        !           433:        int s[2];
        !           434:        char *shellp;
        !           435:
        !           436:        if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s) == -1) {
        !           437:                ewprintf("socketpair error");
        !           438:                return (FALSE);
        !           439:        }
        !           440:        switch(fork()) {
        !           441:        case -1:
        !           442:                ewprintf("Can't fork");
        !           443:                return (FALSE);
        !           444:        case 0:
        !           445:                /* Child process */
        !           446:                close(s[0]);
        !           447:                if (dup2(s[1], STDIN_FILENO) == -1)
        !           448:                        _exit(1);
        !           449:                if (dup2(s[1], STDOUT_FILENO) == -1)
        !           450:                        _exit(1);
        !           451:                if (dup2(s[1], STDERR_FILENO) == -1)
        !           452:                        _exit(1);
        !           453:                if ((shellp = getenv("SHELL")) == NULL)
        !           454:                        _exit(1);
        !           455:                execl(shellp, "sh", "-c", cmd, (char *)NULL);
        !           456:                _exit(1);
        !           457:        default:
        !           458:                /* Parent process */
        !           459:                close(s[1]);
        !           460:                return iomux(s[0]);
        !           461:        }
        !           462:        return (FALSE);
        !           463: }
        !           464:
        !           465: /*
        !           466:  * Multiplex read, write on socket fd passed. First get the region,
        !           467:  * find/create *Shell Command Output* buffer and clear it's contents.
        !           468:  * Poll on the fd for both read and write readiness.
        !           469:  */
        !           470: int
        !           471: iomux(int fd)
        !           472: {
        !           473:        struct region region;
        !           474:        struct buffer *bp;
        !           475:        struct pollfd pfd[1];
        !           476:        int nfds;
        !           477:        char *text, *textcopy;
        !           478:
        !           479:        if (getregion(&region) != TRUE)
        !           480:                return (FALSE);
        !           481:
        !           482:        if ((text = malloc(region.r_size + 1)) == NULL)
        !           483:                return (ABORT);
        !           484:
        !           485:        region_get_data(&region, text, region.r_size);
        !           486:        textcopy = text;
        !           487:        fcntl(fd, F_SETFL, O_NONBLOCK);
        !           488:
        !           489:        /* There is nothing to write if r_size is zero
        !           490:         * but the cmd's output should be read so shutdown
        !           491:         * the socket for writing only.
        !           492:         */
        !           493:        if (region.r_size == 0)
        !           494:                shutdown(fd, SHUT_WR);
        !           495:
        !           496:        bp = bfind("*Shell Command Output*", TRUE);
        !           497:        bp->b_flag |= BFREADONLY;
        !           498:        if (bclear(bp) != TRUE)
        !           499:                return (FALSE);
        !           500:
        !           501:        pfd[0].fd = fd;
        !           502:        pfd[0].events = POLLIN | POLLOUT;
        !           503:        while ((nfds = poll(pfd, 1, TIMEOUT)) != -1 ||
        !           504:            (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))) {
        !           505:                if (pfd[0].revents & POLLOUT && region.r_size > 0)
        !           506:                        pwriteout(fd, &textcopy, &region.r_size);
        !           507:                else if (pfd[0].revents & POLLIN)
        !           508:                        if (preadin(fd, bp) == FALSE)
        !           509:                                break;
        !           510:        }
        !           511:        close(fd);
        !           512:        free(text);
        !           513:        /* In case if last line doesn't have a '\n' add the leftover
        !           514:         * characters to buffer.
        !           515:         */
        !           516:        if (leftover[0] != '\0') {
        !           517:                addline(bp, leftover);
        !           518:                leftover[0] = '\0';
        !           519:        }
        !           520:        if (nfds == 0) {
        !           521:                ewprintf("poll timed out");
        !           522:                return (FALSE);
        !           523:        } else if (nfds == -1) {
        !           524:                ewprintf("poll error");
        !           525:                return (FALSE);
        !           526:        }
        !           527:        return (popbuftop(bp, WNONE));
        !           528: }
        !           529:
        !           530: /*
        !           531:  * Write some text from region to fd. Once done shutdown the
        !           532:  * write end.
        !           533:  */
        !           534: void
        !           535: pwriteout(int fd, char **text, int *len)
        !           536: {
        !           537:        int w;
        !           538:
        !           539:        if (((w = send(fd, *text, *len, MSG_NOSIGNAL)) == -1)) {
        !           540:                switch(errno) {
        !           541:                case EPIPE:
        !           542:                        *len = -1;
        !           543:                        break;
        !           544:                case EAGAIN:
        !           545:                        return;
        !           546:                }
        !           547:        } else
        !           548:                *len -= w;
        !           549:
        !           550:        *text += w;
        !           551:        if (*len <= 0)
        !           552:                shutdown(fd, SHUT_WR);
        !           553: }
        !           554:
        !           555: /*
        !           556:  * Read some data from socket fd, break on '\n' and add
        !           557:  * to buffer. If couldn't break on newline hold leftover
        !           558:  * characters and append in next iteration.
        !           559:  */
        !           560: int
        !           561: preadin(int fd, struct buffer *bp)
        !           562: {
        !           563:        int len;
        !           564:        static int nooutput;
        !           565:        char buf[BUFSIZ], *p, *q;
        !           566:
        !           567:        if ((len = read(fd, buf, BUFSIZ - 1)) == 0) {
        !           568:                if (nooutput == 0)
        !           569:                        addline(bp, "(Shell command succeeded with no output)");
        !           570:                nooutput = 0;
        !           571:                return (FALSE);
        !           572:        }
        !           573:        nooutput = 1;
        !           574:        buf[len] = '\0';
        !           575:        p = q = buf;
        !           576:        if (leftover[0] != '\0' && ((q = strchr(p, '\n')) != NULL)) {
        !           577:                *q++ = '\0';
        !           578:                if (strlcat(leftover, p, sizeof(leftover)) >=
        !           579:                    sizeof(leftover)) {
        !           580:                        ewprintf("line too long");
        !           581:                        return (FALSE);
        !           582:                }
        !           583:                addline(bp, leftover);
        !           584:                leftover[0] = '\0';
        !           585:                p = q;
        !           586:        }
        !           587:        while ((q = strchr(p, '\n')) != NULL) {
        !           588:                *q++ = '\0';
        !           589:                addline(bp, p);
        !           590:                p = q;
        !           591:        }
        !           592:        if (strlcpy(leftover, p, sizeof(leftover)) >= sizeof(leftover)) {
        !           593:                ewprintf("line too long");
        !           594:                return (FALSE);
        !           595:        }
        !           596:        return (TRUE);
1.9       vincent   597: }