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