Wed Jul 27 02:23:30 2011 UTC ()
- don't leave cursor dangling on memory failure or after clearing the list
- compute the string length to be strvis'ed after the string is encoded


(christos)
diff -r1.38 -r1.39 src/lib/libedit/history.c

cvs diff -r1.38 -r1.39 src/lib/libedit/history.c (expand / switch to unified diff)

--- src/lib/libedit/history.c 2011/01/16 03:05:51 1.38
+++ src/lib/libedit/history.c 2011/07/27 02:23:29 1.39
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: history.c,v 1.38 2011/01/16 03:05:51 christos Exp $ */ 1/* $NetBSD: history.c,v 1.39 2011/07/27 02:23:29 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1992, 1993 4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Christos Zoulas of Cornell University. 8 * Christos Zoulas of Cornell University.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include "config.h" 35#include "config.h"
36#if !defined(lint) && !defined(SCCSID) 36#if !defined(lint) && !defined(SCCSID)
37#if 0 37#if 0
38static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93"; 38static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
39#else 39#else
40__RCSID("$NetBSD: history.c,v 1.38 2011/01/16 03:05:51 christos Exp $"); 40__RCSID("$NetBSD: history.c,v 1.39 2011/07/27 02:23:29 christos Exp $");
41#endif 41#endif
42#endif /* not lint && not SCCSID */ 42#endif /* not lint && not SCCSID */
43 43
44/* 44/*
45 * hist.c: TYPE(History) access functions 45 * hist.c: TYPE(History) access functions
46 */ 46 */
47#include <string.h> 47#include <string.h>
48#include <stdlib.h> 48#include <stdlib.h>
49#include <stdarg.h> 49#include <stdarg.h>
50#ifdef HAVE_VIS_H 50#ifdef HAVE_VIS_H
51#include <vis.h> 51#include <vis.h>
52#else 52#else
53#include "np/vis.h" 53#include "np/vis.h"
@@ -455,61 +455,63 @@ history_def_delete(history_t *h,  @@ -455,61 +455,63 @@ history_def_delete(history_t *h,
455 hp->next->prev = hp->prev; 455 hp->next->prev = hp->prev;
456 h_free((ptr_t) evp->str); 456 h_free((ptr_t) evp->str);
457 h_free(hp); 457 h_free(hp);
458 h->cur--; 458 h->cur--;
459} 459}
460 460
461 461
462/* history_def_insert(): 462/* history_def_insert():
463 * Insert element with string str in the h list 463 * Insert element with string str in the h list
464 */ 464 */
465private int 465private int
466history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str) 466history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str)
467{ 467{
 468 hentry_t *c;
468 469
469 h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t)); 470 c = h_malloc(sizeof(*c));
470 if (h->cursor == NULL) 471 if (c == NULL)
471 goto oomem; 472 goto oomem;
472 if ((h->cursor->ev.str = h_strdup(str)) == NULL) { 473 if ((c->ev.str = h_strdup(str)) == NULL) {
473 h_free((ptr_t)h->cursor); 474 h_free((ptr_t)c);
474 goto oomem; 475 goto oomem;
475 } 476 }
476 h->cursor->data = NULL; 477 c->data = NULL;
477 h->cursor->ev.num = ++h->eventid; 478 c->ev.num = ++h->eventid;
478 h->cursor->next = h->list.next; 479 c->next = h->list.next;
479 h->cursor->prev = &h->list; 480 c->prev = &h->list;
480 h->list.next->prev = h->cursor; 481 h->list.next->prev = c;
481 h->list.next = h->cursor; 482 h->list.next = c;
482 h->cur++; 483 h->cur++;
 484 h->cursor = c;
483 485
484 *ev = h->cursor->ev; 486 *ev = c->ev;
485 return (0); 487 return (0);
486oomem: 488oomem:
487 he_seterrev(ev, _HE_MALLOC_FAILED); 489 he_seterrev(ev, _HE_MALLOC_FAILED);
488 return (-1); 490 return (-1);
489} 491}
490 492
491 493
492/* history_def_enter(): 494/* history_def_enter():
493 * Default function to enter an item in the history 495 * Default function to enter an item in the history
494 */ 496 */
495private int 497private int
496history_def_enter(ptr_t p, TYPE(HistEvent) *ev, const Char *str) 498history_def_enter(ptr_t p, TYPE(HistEvent) *ev, const Char *str)
497{ 499{
498 history_t *h = (history_t *) p; 500 history_t *h = (history_t *) p;
499 501
500 if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list && 502 if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list &&
501 Strcmp(h->list.next->ev.str, str) == 0) 503 Strcmp(h->list.next->ev.str, str) == 0)
502 return (0);  504 return (0);
503 505
504 if (history_def_insert(h, ev, str) == -1) 506 if (history_def_insert(h, ev, str) == -1)
505 return (-1); /* error, keep error message */ 507 return (-1); /* error, keep error message */
506 508
507 /* 509 /*
508 * Always keep at least one entry. 510 * Always keep at least one entry.
509 * This way we don't have to check for the empty list. 511 * This way we don't have to check for the empty list.
510 */ 512 */
511 while (h->cur > h->max && h->cur > 0) 513 while (h->cur > h->max && h->cur > 0)
512 history_def_delete(h, ev, h->list.prev); 514 history_def_delete(h, ev, h->list.prev);
513 515
514 return (1); 516 return (1);
515} 517}
@@ -541,26 +543,27 @@ history_def_init(ptr_t *p, TYPE(HistEven @@ -541,26 +543,27 @@ history_def_init(ptr_t *p, TYPE(HistEven
541} 543}
542 544
543 545
544/* history_def_clear(): 546/* history_def_clear():
545 * Default history cleanup function 547 * Default history cleanup function
546 */ 548 */
547private void 549private void
548history_def_clear(ptr_t p, TYPE(HistEvent) *ev) 550history_def_clear(ptr_t p, TYPE(HistEvent) *ev)
549{ 551{
550 history_t *h = (history_t *) p; 552 history_t *h = (history_t *) p;
551 553
552 while (h->list.prev != &h->list) 554 while (h->list.prev != &h->list)
553 history_def_delete(h, ev, h->list.prev); 555 history_def_delete(h, ev, h->list.prev);
 556 h->cursor = &h->list;
554 h->eventid = 0; 557 h->eventid = 0;
555 h->cur = 0; 558 h->cur = 0;
556} 559}
557 560
558 561
559 562
560 563
561/************************************************************************/ 564/************************************************************************/
562 565
563/* history_init(): 566/* history_init():
564 * Initialization function. 567 * Initialization function.
565 */ 568 */
566public TYPE(History) * 569public TYPE(History) *
@@ -784,56 +787,57 @@ done: @@ -784,56 +787,57 @@ done:
784} 787}
785 788
786 789
787/* history_save(): 790/* history_save():
788 * TYPE(History) save function 791 * TYPE(History) save function
789 */ 792 */
790private int 793private int
791history_save(TYPE(History) *h, const char *fname) 794history_save(TYPE(History) *h, const char *fname)
792{ 795{
793 FILE *fp; 796 FILE *fp;
794 TYPE(HistEvent) ev; 797 TYPE(HistEvent) ev;
795 int i = -1, retval; 798 int i = -1, retval;
796 size_t len, max_size; 799 size_t len, max_size;
797 char *ptr; 800 char *ptr, *str;
798#ifdef WIDECHAR 801#ifdef WIDECHAR
799 static ct_buffer_t conv; 802 static ct_buffer_t conv;
800#endif 803#endif
801 804
802 if ((fp = fopen(fname, "w")) == NULL) 805 if ((fp = fopen(fname, "w")) == NULL)
803 return (-1); 806 return (-1);
804 807
805 if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) 808 if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1)
806 goto done; 809 goto done;
807 if (fputs(hist_cookie, fp) == EOF) 810 if (fputs(hist_cookie, fp) == EOF)
808 goto done; 811 goto done;
809 ptr = h_malloc(max_size = 1024); 812 ptr = h_malloc(max_size = 1024);
810 if (ptr == NULL) 813 if (ptr == NULL)
811 goto done; 814 goto done;
812 for (i = 0, retval = HLAST(h, &ev); 815 for (i = 0, retval = HLAST(h, &ev);
813 retval != -1; 816 retval != -1;
814 retval = HPREV(h, &ev), i++) { 817 retval = HPREV(h, &ev), i++) {
815 len = Strlen(ev.str) * 4; 818 str = ct_encode_string(ev.str, &conv);
 819 len = strlen(str) * 4;
816 if (len >= max_size) { 820 if (len >= max_size) {
817 char *nptr; 821 char *nptr;
818 max_size = (len + 1024) & ~1023; 822 max_size = (len + 1024) & ~1023;
819 nptr = h_realloc(ptr, max_size); 823 nptr = h_realloc(ptr, max_size);
820 if (nptr == NULL) { 824 if (nptr == NULL) {
821 i = -1; 825 i = -1;
822 goto oomem; 826 goto oomem;
823 } 827 }
824 ptr = nptr; 828 ptr = nptr;
825 } 829 }
826 (void) strvis(ptr, ct_encode_string(ev.str, &conv), VIS_WHITE); 830 (void) strvis(ptr, str, VIS_WHITE);
827 (void) fprintf(fp, "%s\n", ptr); 831 (void) fprintf(fp, "%s\n", ptr);
828 } 832 }
829oomem: 833oomem:
830 h_free((ptr_t)ptr); 834 h_free((ptr_t)ptr);
831done: 835done:
832 (void) fclose(fp); 836 (void) fclose(fp);
833 return (i); 837 return (i);
834} 838}
835 839
836 840
837/* history_prev_event(): 841/* history_prev_event():
838 * Find the previous event, with number given 842 * Find the previous event, with number given
839 */ 843 */