[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.31

1.31    ! florian     1: /*     $OpenBSD: region.c,v 1.30 2012/04/11 17:51:10 lum 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:
1.31    ! florian   479:        if (getregion(&region) != TRUE) {
        !           480:                close(fd);
1.30      lum       481:                return (FALSE);
1.31    ! florian   482:        }
        !           483:
        !           484:        if ((text = malloc(region.r_size + 1)) == NULL) {
        !           485:                close(fd);
1.30      lum       486:                return (ABORT);
1.31    ! florian   487:        }
        !           488:
1.30      lum       489:        region_get_data(&region, text, region.r_size);
                    490:        textcopy = text;
                    491:        fcntl(fd, F_SETFL, O_NONBLOCK);
                    492:
                    493:        /* There is nothing to write if r_size is zero
                    494:         * but the cmd's output should be read so shutdown
                    495:         * the socket for writing only.
                    496:         */
                    497:        if (region.r_size == 0)
                    498:                shutdown(fd, SHUT_WR);
                    499:
                    500:        bp = bfind("*Shell Command Output*", TRUE);
                    501:        bp->b_flag |= BFREADONLY;
1.31    ! florian   502:        if (bclear(bp) != TRUE) {
        !           503:                close(fd);
        !           504:                free(text);
1.30      lum       505:                return (FALSE);
1.31    ! florian   506:        }
1.30      lum       507:
                    508:        pfd[0].fd = fd;
                    509:        pfd[0].events = POLLIN | POLLOUT;
                    510:        while ((nfds = poll(pfd, 1, TIMEOUT)) != -1 ||
                    511:            (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))) {
                    512:                if (pfd[0].revents & POLLOUT && region.r_size > 0)
                    513:                        pwriteout(fd, &textcopy, &region.r_size);
                    514:                else if (pfd[0].revents & POLLIN)
                    515:                        if (preadin(fd, bp) == FALSE)
                    516:                                break;
                    517:        }
                    518:        close(fd);
                    519:        free(text);
                    520:        /* In case if last line doesn't have a '\n' add the leftover
                    521:         * characters to buffer.
                    522:         */
                    523:        if (leftover[0] != '\0') {
                    524:                addline(bp, leftover);
                    525:                leftover[0] = '\0';
                    526:        }
                    527:        if (nfds == 0) {
                    528:                ewprintf("poll timed out");
                    529:                return (FALSE);
                    530:        } else if (nfds == -1) {
                    531:                ewprintf("poll error");
                    532:                return (FALSE);
                    533:        }
                    534:        return (popbuftop(bp, WNONE));
                    535: }
                    536:
                    537: /*
                    538:  * Write some text from region to fd. Once done shutdown the
                    539:  * write end.
                    540:  */
                    541: void
                    542: pwriteout(int fd, char **text, int *len)
                    543: {
                    544:        int w;
                    545:
                    546:        if (((w = send(fd, *text, *len, MSG_NOSIGNAL)) == -1)) {
                    547:                switch(errno) {
                    548:                case EPIPE:
                    549:                        *len = -1;
                    550:                        break;
                    551:                case EAGAIN:
                    552:                        return;
                    553:                }
                    554:        } else
                    555:                *len -= w;
                    556:
                    557:        *text += w;
                    558:        if (*len <= 0)
                    559:                shutdown(fd, SHUT_WR);
                    560: }
                    561:
                    562: /*
                    563:  * Read some data from socket fd, break on '\n' and add
                    564:  * to buffer. If couldn't break on newline hold leftover
                    565:  * characters and append in next iteration.
                    566:  */
                    567: int
                    568: preadin(int fd, struct buffer *bp)
                    569: {
                    570:        int len;
                    571:        static int nooutput;
                    572:        char buf[BUFSIZ], *p, *q;
                    573:
                    574:        if ((len = read(fd, buf, BUFSIZ - 1)) == 0) {
                    575:                if (nooutput == 0)
                    576:                        addline(bp, "(Shell command succeeded with no output)");
                    577:                nooutput = 0;
                    578:                return (FALSE);
                    579:        }
                    580:        nooutput = 1;
                    581:        buf[len] = '\0';
                    582:        p = q = buf;
                    583:        if (leftover[0] != '\0' && ((q = strchr(p, '\n')) != NULL)) {
                    584:                *q++ = '\0';
                    585:                if (strlcat(leftover, p, sizeof(leftover)) >=
                    586:                    sizeof(leftover)) {
                    587:                        ewprintf("line too long");
                    588:                        return (FALSE);
                    589:                }
                    590:                addline(bp, leftover);
                    591:                leftover[0] = '\0';
                    592:                p = q;
                    593:        }
                    594:        while ((q = strchr(p, '\n')) != NULL) {
                    595:                *q++ = '\0';
                    596:                addline(bp, p);
                    597:                p = q;
                    598:        }
                    599:        if (strlcpy(leftover, p, sizeof(leftover)) >= sizeof(leftover)) {
                    600:                ewprintf("line too long");
                    601:                return (FALSE);
                    602:        }
                    603:        return (TRUE);
1.9       vincent   604: }