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