Subject: lib/33625: [PATCH] allow using t_puts inside of libedit
To: None <lib-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <chardin@2wire.com>
List: netbsd-bugs
Date: 06/01/2006 16:35:00
>Number:         33625
>Category:       lib
>Synopsis:       [PATCH] allow using t_puts inside of libedit
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu Jun 01 16:35:00 +0000 2006
>Originator:     Charles Hardin
>Release:        CVS HEAD libedit on a FreeBSD box (sorry)
>Organization:
2Wire
>Environment:
FreeBSD reddevil.2wire.com 4.7-RELEASE FreeBSD 4.7-RELEASE #0: Mon Mar 20 14:47:22 PST 2006     root@reddevil.2wire.com:/usr/obj/usr/src/sys/REDDEVILIPSEC  i386
>Description:
Was writing a threaded application that was monitoring multiple consoles using libedit and ran across a problem with output appearing on the other tty... Tracked it back to a comment in libedit and made a patch that fixed our problem by allowing the use of t_puts instead of tputs...
>How-To-Repeat:
Should probably right a test application - but, a little too lazy for that... The application just started n threads and did an el_init for each thread to a different tty[0-9]...

Then when going thru the history it would get flushed to the wrong terminal in some cases... it's just a race condition...

So, did the patch below to allow the use of t_puts so I can pass the EditLine pointer all the way to the output routines...
>Fix:
Index: common.c
===================================================================
RCS file: /cvsroot/src/lib/libedit/common.c,v
retrieving revision 1.19
diff -u -r1.19 common.c
--- common.c	6 Mar 2006 21:11:56 -0000	1.19
+++ common.c	1 Jun 2006 16:31:57 -0000
@@ -910,7 +910,7 @@
 	int tmplen;
 
 	tmplen = c_gets(el, tmpbuf, "\n: ");
-	term__putc('\n');
+	term__putc(el, '\n');
 
 	if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1)
 		term_beep(el);
Index: read.c
===================================================================
RCS file: /cvsroot/src/lib/libedit/read.c,v
retrieving revision 1.39
diff -u -r1.39 read.c
--- read.c	2 Aug 2005 12:11:14 -0000	1.39
+++ read.c	1 Jun 2006 16:31:57 -0000
@@ -223,7 +223,7 @@
 		ma->level--;
 	}
 	term_beep(el);
-	term__flush();
+	term__flush(el);
 }
 
 
@@ -311,7 +311,7 @@
 	int num_read;
 	c_macro_t *ma = &el->el_chared.c_macro;
 
-	term__flush();
+	term__flush(el);
 	for (;;) {
 		if (ma->level < 0) {
 			if (!read_preread(el))
@@ -368,7 +368,7 @@
 	re_refresh(el);		/* print the prompt */
 
 	if (el->el_flags & UNBUFFERED)
-		term__flush();
+		term__flush(el);
 }
 
 protected void
@@ -445,7 +445,7 @@
 		else
 			cp = el->el_line.lastchar;
 
-		term__flush();
+		term__flush(el);
 
 		while ((*el->el_read.read_char)(el, cp) == 1) {
 			/* make sure there is space next character */
@@ -588,7 +588,7 @@
 			    "*** editor ERROR ***\r\n\n");
 #endif /* DEBUG_READ */
 			term_beep(el);
-			term__flush();
+			term__flush(el);
 			break;
 		}
 		el->el_state.argument = 1;
@@ -598,7 +598,7 @@
 			break;
 	}
 
-	term__flush();		/* flush any buffered output */
+	term__flush(el);		/* flush any buffered output */
 	/* make sure the tty is set up correctly */
 	if ((el->el_flags & UNBUFFERED) == 0) {
 		read_finish(el);
Index: refresh.c
===================================================================
RCS file: /cvsroot/src/lib/libedit/refresh.c,v
retrieving revision 1.27
diff -u -r1.27 refresh.c
--- refresh.c	9 Nov 2005 22:11:10 -0000	1.27
+++ refresh.c	1 Jun 2006 16:31:57 -0000
@@ -323,9 +323,9 @@
 {
 
 	term_move_to_line(el, el->el_refresh.r_oldcv);
-	term__putc('\n');
+	term__putc(el, '\n');
 	re_clear_display(el);
-	term__flush();
+	term__flush(el);
 }
 
 
@@ -1011,7 +1011,7 @@
 	/* now go there */
 	term_move_to_line(el, v);
 	term_move_to_char(el, h);
-	term__flush();
+	term__flush(el);
 }
 
 
@@ -1022,7 +1022,7 @@
 re_fastputc(EditLine *el, int c)
 {
 
-	term__putc(c);
+	term__putc(el, c);
 	el->el_display[el->el_cursor.v][el->el_cursor.h++] = c;
 	if (el->el_cursor.h >= el->el_term.t_size.h) {
 		/* if we must overflow */
@@ -1049,12 +1049,12 @@
 		}
 		if (EL_HAS_AUTO_MARGINS) {
 			if (EL_HAS_MAGIC_MARGINS) {
-				term__putc(' ');
-				term__putc('\b');
+				term__putc(el, ' ');
+				term__putc(el, '\b');
 			}
 		} else {
-			term__putc('\r');
-			term__putc('\n');
+			term__putc(el, '\r');
+			term__putc(el, '\n');
 		}
 	}
 }
@@ -1094,7 +1094,7 @@
 		re_fastputc(el, (int)(((((unsigned int)c) >> 3) & 7) + '0'));
 		re_fastputc(el, (c & 7) + '0');
 	}
-	term__flush();
+	term__flush(el);
 }
 
 
@@ -1133,7 +1133,7 @@
 	} else {
 		term_move_to_line(el, el->el_refresh.r_oldcv);
 					/* go to last line */
-		term__putc('\r');	/* go to BOL */
-		term__putc('\n');	/* go to new line */
+		term__putc(el, '\r');	/* go to BOL */
+		term__putc(el, '\n');	/* go to new line */
 	}
 }
Index: sig.c
===================================================================
RCS file: /cvsroot/src/lib/libedit/sig.c,v
retrieving revision 1.11
diff -u -r1.11 sig.c
--- sig.c	7 Aug 2003 16:44:33 -0000	1.11
+++ sig.c	1 Jun 2006 16:31:57 -0000
@@ -80,7 +80,7 @@
 		tty_rawmode(sel);
 		if (ed_redisplay(sel, 0) == CC_REFRESH)
 			re_refresh(sel);
-		term__flush();
+		term__flush(sel);
 		break;
 
 	case SIGWINCH:
Index: term.c
===================================================================
RCS file: /cvsroot/src/lib/libedit/term.c,v
retrieving revision 1.45
diff -u -r1.45 term.c
--- term.c	18 Mar 2006 19:23:14 -0000	1.45
+++ term.c	1 Jun 2006 16:31:57 -0000
@@ -273,9 +273,6 @@
 private void	term_reset_arrow(EditLine *);
 
 
-private FILE *term_outfile = NULL;	/* XXX: How do we fix that? */
-
-
 /* term_setflags():
  *	Set the terminal capability flags
  */
@@ -347,7 +344,6 @@
 	if (el->el_term.t_val == NULL)
 		return (-1);
 	(void) memset(el->el_term.t_val, 0, T_val * sizeof(int));
-	term_outfile = el->el_outfile;
 	(void) term_set(el, NULL);
 	term_init_arrow(el);
 	return (0);
@@ -418,7 +414,7 @@
          */
 	tlen = 0;
 	for (tmp = tlist; tmp < &tlist[T_str]; tmp++)
-		if (*tmp != NULL && *tmp != '\0' && *tmp != *str) {
+		if (*tmp != NULL && *tmp[0] != '\0' && *tmp != *str) {
 			char *ptr;
 
 			for (ptr = *tmp; *ptr != '\0'; termbuf[tlen++] = *ptr++)
@@ -559,12 +555,12 @@
 				del--;
 			} else {
 				if ((del > 1) && GoodStr(T_DO)) {
-					(void) tputs(tgoto(Str(T_DO), del, del),
-					    del, term__putc);
+					term__puts(el,
+					    tgoto(Str(T_DO), del, del), del);
 					del = 0;
 				} else {
 					for (; del > 0; del--)
-						term__putc('\n');
+						term__putc(el, '\n');
 					/* because the \n will become \r\n */
 					el->el_cursor.h = 0;
 				}
@@ -572,12 +568,11 @@
 		}
 	} else {		/* del < 0 */
 		if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up)))
-			(void) tputs(tgoto(Str(T_UP), -del, -del), -del,
-			    term__putc);
+			term__puts(el, tgoto(Str(T_UP), -del, -del), -del);
 		else {
 			if (GoodStr(T_up))
 				for (; del < 0; del++)
-					(void) tputs(Str(T_up), 1, term__putc);
+					term__puts(el, Str(T_up), 1);
 		}
 	}
 	el->el_cursor.v = where;/* now where is here */
@@ -604,7 +599,7 @@
 		return;
 	}
 	if (!where) {		/* if where is first column */
-		term__putc('\r');	/* do a CR */
+		term__putc(el, '\r');	/* do a CR */
 		el->el_cursor.h = 0;
 		return;
 	}
@@ -612,12 +607,12 @@
 
 	if ((del < -4 || del > 4) && GoodStr(T_ch))
 		/* go there directly */
-		(void) tputs(tgoto(Str(T_ch), where, where), where, term__putc);
+		term__puts(el, tgoto(Str(T_ch), where, where), where);
 	else {
 		if (del > 0) {	/* moving forward */
 			if ((del > 4) && GoodStr(T_RI))
-				(void) tputs(tgoto(Str(T_RI), del, del),
-				    del, term__putc);
+				term__puts(el, tgoto(Str(T_RI), del, del),
+				    del);
 			else {
 					/* if I can do tabs, use them */
 				if (EL_CAN_TAB) {
@@ -628,7 +623,7 @@
 						    (el->el_cursor.h & 0370);
 						    i < (where & 0370);
 						    i += 8)
-							term__putc('\t');	
+							term__putc(el, '\t');	
 							/* then tab over */
 						el->el_cursor.h = where & 0370;
 					}
@@ -648,8 +643,8 @@
 			}
 		} else {	/* del < 0 := moving backward */
 			if ((-del > 4) && GoodStr(T_LE))
-				(void) tputs(tgoto(Str(T_LE), -del, -del),
-				    -del, term__putc);
+				term__puts(el, tgoto(Str(T_LE), -del, -del),
+				    -del);
 			else {	/* can't go directly there */
 				/*
 				 * if the "cost" is greater than the "cost"
@@ -660,12 +655,12 @@
 				    (((unsigned int) where >> 3) +
 				     (where & 07)))
 				    : (-del > where)) {
-					term__putc('\r');	/* do a CR */
+					term__putc(el, '\r');	/* do a CR */
 					el->el_cursor.h = 0;
 					goto mc_again;	/* and try again */
 				}
 				for (i = 0; i < -del; i++)
-					term__putc('\b');
+					term__putc(el, '\b');
 			}
 		}
 	}
@@ -690,7 +685,7 @@
 		return;
 	}
 	do {
-		term__putc(*cp++);
+		term__putc(el, *cp++);
 		el->el_cursor.h++;
 	} while (--n);
 
@@ -706,7 +701,7 @@
 				    != '\0')
 					term_overwrite(el, &c, 1);
 				else
-					term__putc(' ');
+					term__putc(el, ' ');
 				el->el_cursor.h = 1;
 			}
 		} else		/* no wrap, but cursor stays on screen */
@@ -740,19 +735,18 @@
 	if (GoodStr(T_DC))	/* if I have multiple delete */
 		if ((num > 1) || !GoodStr(T_dc)) {	/* if dc would be more
 							 * expen. */
-			(void) tputs(tgoto(Str(T_DC), num, num),
-			    num, term__putc);
+			term__puts(el, tgoto(Str(T_DC), num, num), num);
 			return;
 		}
 	if (GoodStr(T_dm))	/* if I have delete mode */
-		(void) tputs(Str(T_dm), 1, term__putc);
+		term__puts(el, Str(T_dm), 1);
 
 	if (GoodStr(T_dc))	/* else do one at a time */
 		while (num--)
-			(void) tputs(Str(T_dc), 1, term__putc);
+			term__puts(el, Str(T_dc), 1);
 
 	if (GoodStr(T_ed))	/* if I have delete mode */
-		(void) tputs(Str(T_ed), 1, term__putc);
+		term__puts(el, Str(T_ed), 1);
 }
 
 
@@ -781,37 +775,36 @@
 	if (GoodStr(T_IC))	/* if I have multiple insert */
 		if ((num > 1) || !GoodStr(T_ic)) {
 				/* if ic would be more expensive */
-			(void) tputs(tgoto(Str(T_IC), num, num),
-			    num, term__putc);
+			term__puts(el, tgoto(Str(T_IC), num, num), num);
 			term_overwrite(el, cp, num);
 				/* this updates el_cursor.h */
 			return;
 		}
 	if (GoodStr(T_im) && GoodStr(T_ei)) {	/* if I have insert mode */
-		(void) tputs(Str(T_im), 1, term__putc);
+		term__puts(el, Str(T_im), 1);
 
 		el->el_cursor.h += num;
 		do
-			term__putc(*cp++);
+			term__putc(el, *cp++);
 		while (--num);
 
 		if (GoodStr(T_ip))	/* have to make num chars insert */
-			(void) tputs(Str(T_ip), 1, term__putc);
+			term__puts(el, Str(T_ip), 1);
 
-		(void) tputs(Str(T_ei), 1, term__putc);
+		term__puts(el, Str(T_ei), 1);
 		return;
 	}
 	do {
 		if (GoodStr(T_ic))	/* have to make num chars insert */
-			(void) tputs(Str(T_ic), 1, term__putc);
+			term__puts(el, Str(T_ic), 1);
 					/* insert a char */
 
-		term__putc(*cp++);
+		term__putc(el, *cp++);
 
 		el->el_cursor.h++;
 
 		if (GoodStr(T_ip))	/* have to make num chars insert */
-			(void) tputs(Str(T_ip), 1, term__putc);
+			term__puts(el, Str(T_ip), 1);
 					/* pad the inserted char */
 
 	} while (--num);
@@ -827,10 +820,10 @@
 	int i;
 
 	if (EL_CAN_CEOL && GoodStr(T_ce))
-		(void) tputs(Str(T_ce), 1, term__putc);
+		term__puts(el, Str(T_ce), 1);
 	else {
 		for (i = 0; i < num; i++)
-			term__putc(' ');
+			term__putc(el, ' ');
 		el->el_cursor.h += num;	/* have written num spaces */
 	}
 }
@@ -845,14 +838,14 @@
 
 	if (GoodStr(T_cl))
 		/* send the clear screen code */
-		(void) tputs(Str(T_cl), Val(T_li), term__putc);
+		term__puts(el, Str(T_cl), Val(T_li));
 	else if (GoodStr(T_ho) && GoodStr(T_cd)) {
-		(void) tputs(Str(T_ho), Val(T_li), term__putc);	/* home */
+		term__puts(el, Str(T_ho), Val(T_li));	/* home */
 		/* clear to bottom of screen */
-		(void) tputs(Str(T_cd), Val(T_li), term__putc);
+		term__puts(el, Str(T_cd), Val(T_li));
 	} else {
-		term__putc('\r');
-		term__putc('\n');
+		term__putc(el, '\r');
+		term__putc(el, '\n');
 	}
 }
 
@@ -865,9 +858,9 @@
 {
 	if (GoodStr(T_bl))
 		/* what termcap says we should use */
-		(void) tputs(Str(T_bl), 1, term__putc);
+		term__puts(el, Str(T_bl), 1);
 	else
-		term__putc('\007');	/* an ASCII bell; ^G */
+		term__putc(el, '\007');	/* an ASCII bell; ^G */
 }
 
 
@@ -879,9 +872,9 @@
 term_clear_to_bottom(EditLine *el)
 {
 	if (GoodStr(T_cd))
-		(void) tputs(Str(T_cd), Val(T_li), term__putc);
+		term__puts(el, Str(T_cd), Val(T_li));
 	else if (GoodStr(T_ce))
-		(void) tputs(Str(T_ce), Val(T_li), term__putc);
+		term__puts(el, Str(T_ce), Val(T_li));
 }
 #endif
 
@@ -1238,14 +1231,47 @@
 }
 
 
+#ifdef _HAVE_T_PUTS_
+private void
+term__outc(char c, void *arg)
+{
+	EditLine *el;
+	el = (EditLine *)arg;
+	return (fputc(c, el->el_outfile));
+}
+
+protected void 
+term__puts(EditLine *el, const char *str, int cnt)
+{
+	(void) t_puts(NULL, str, cnt, term__outc, el);
+}
+#else
+private FILE *term_outfile = NULL;	/* XXX: How do we fix that? */
+
+private int
+term__outc(int c)
+{
+
+	return (fputc(c, term_outfile));
+}
+
+protected void 
+term__puts(EditLine *el, const char *str, int cnt)
+{
+	term_outfile = el->el_outfile;
+	(void) tputs(str, cnt, term__outc);
+}
+#endif
+
+
 /* term__putc():
  *	Add a character
  */
 protected int
-term__putc(int c)
+term__putc(EditLine *el, int c)
 {
 
-	return (fputc(c, term_outfile));
+	return (fputc(c, el->el_outfile));
 }
 
 
@@ -1253,10 +1279,10 @@
  *	Flush output
  */
 protected void
-term__flush(void)
+term__flush(EditLine *el)
 {
 
-	(void) fflush(term_outfile);
+	(void) fflush(el->el_outfile);
 }
 
 /* term_writec():
@@ -1269,7 +1295,7 @@
 	int cnt = key__decode_char(buf, sizeof(buf), 0, c);
 	buf[cnt] = '\0';
 	term_overwrite(el, buf, cnt);
-	term__flush();
+	term__flush(el);
 }
 
 
@@ -1530,7 +1556,7 @@
 				    *argv);
 			return (-1);
 		}
-		(void) tputs(scap, 1, term__putc);
+		term__puts(el, scap, 1);
 		break;
 	case 1:
 		argv++;
@@ -1558,7 +1584,7 @@
 				    *argv);
 			return (-1);
 		}
-		(void) tputs(tgoto(scap, arg_cols, arg_rows), 1, term__putc);
+		term__puts(el, tgoto(scap, arg_cols, arg_rows), 1);
 		break;
 	default:
 		/* This is wrong, but I will ignore it... */
@@ -1614,8 +1640,7 @@
 				    *argv);
 			return (-1);
 		}
-		(void) tputs(tgoto(scap, arg_cols, arg_rows), arg_rows,
-		    term__putc);
+		term__puts(el, tgoto(scap, arg_cols, arg_rows), arg_rows);
 		break;
 	}
 	return (0);
Index: term.h
===================================================================
RCS file: /cvsroot/src/lib/libedit/term.h,v
retrieving revision 1.17
diff -u -r1.17 term.h
--- term.h	6 Mar 2006 21:11:56 -0000	1.17
+++ term.h	1 Jun 2006 16:31:57 -0000
@@ -103,8 +103,9 @@
 protected int	term_telltc(EditLine *, int, const char **);
 protected int	term_echotc(EditLine *, int, const char **);
 protected void	term_writec(EditLine *, int);
-protected int	term__putc(int);
-protected void	term__flush(void);
+protected void	term__puts(EditLine *, const char *, int);
+protected int	term__putc(EditLine *, int);
+protected void	term__flush(EditLine *);
 
 /*
  * Easy access macros