summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryokota <yokota@FreeBSD.org>1997-10-23 03:23:50 +0000
committeryokota <yokota@FreeBSD.org>1997-10-23 03:23:50 +0000
commitb13f7d1937225188f0f24693eb4bbc08de1788c7 (patch)
tree001f102ce8e842198f62cef3d627e7230f5fc2f8
parent11e6b28c316cc704cbd4a44e14f3a18fb508d03c (diff)
downloadFreeBSD-src-b13f7d1937225188f0f24693eb4bbc08de1788c7.zip
FreeBSD-src-b13f7d1937225188f0f24693eb4bbc08de1788c7.tar.gz
Reject unreasonable values passed to CONS_HISTORY ioctl. It did not
check the value and caused kernel panic when a large value was given. - Move the configuration option SC_HISTORY_SIZE from syscons.h to syscons.c. - Define the maximum total number of history lines of all consoles. It is SC_HISTORY_SIZE*MAXCONS or 1000*MAXCONS; whichever is larger. CONS_HISTORY will allow the user to set the history size up to SC_HISTORY_SIZE unconditionally (or the current height of the console if it is larger than SC_HISTORY_SIZE). If the user requests a larger buffer, it will be granted only if the total number of all allocated history lines and the requested number of lines won't exceed the maximum. - Don't free the previous history buffer and leave the history buffer pointer holding a invalid pointer. Set the pointer to NULL first, then free the buffer. PR: bin/4592
-rw-r--r--sys/dev/syscons/syscons.c104
-rw-r--r--sys/dev/syscons/syscons.h6
-rw-r--r--sys/i386/isa/syscons.c104
-rw-r--r--sys/i386/isa/syscons.h6
-rw-r--r--sys/isa/syscons.c104
-rw-r--r--sys/isa/syscons.h6
6 files changed, 252 insertions, 78 deletions
diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c
index c92bb36..273bb01 100644
--- a/sys/dev/syscons/syscons.c
+++ b/sys/dev/syscons/syscons.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: syscons.c,v 1.233 1997/09/26 15:27:55 itojun Exp $
+ * $Id: syscons.c,v 1.234 1997/10/01 20:46:27 sos Exp $
*/
#include "sc.h"
@@ -71,6 +71,19 @@
#define MAXCONS 16
#endif
+#if !defined(SC_MAX_HISTORY_SIZE)
+#define SC_MAX_HISTORY_SIZE (1000 * MAXCONS)
+#endif
+
+#if !defined(SC_HISTORY_SIZE)
+#define SC_HISTORY_SIZE (ROW * 4)
+#endif
+
+#if (SC_HISTORY_SIZE * MAXCONS) > SC_MAX_HISTORY_SIZE
+#undef SC_MAX_HISTORY_SIZE
+#define SC_MAX_HISTORY_SIZE (SC_HISTORY_SIZE * MAXCONS)
+#endif
+
#define COLD 0
#define WARM 1
@@ -147,6 +160,9 @@ static u_short mouse_or_mask[16] = {
0x0000, 0x0000, 0x0000, 0x0000
};
+static int extra_history_size =
+ SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS;
+
static void none_saver(int blank) { }
static void (*current_saver)(int blank) = none_saver;
int (*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data,
@@ -636,10 +652,12 @@ scattach(struct isa_device *dev)
scp->mouse_xpos/8);
/* initialize history buffer & pointers */
- scp->history_head = scp->history_pos = scp->history =
+ scp->history_head = scp->history_pos =
(u_short *)malloc(scp->history_size*sizeof(u_short),
M_DEVBUF, M_NOWAIT);
- bzero(scp->history_head, scp->history_size*sizeof(u_short));
+ if (scp->history_head != NULL)
+ bzero(scp->history_head, scp->history_size*sizeof(u_short));
+ scp->history = scp->history_head;
/* initialize cursor stuff */
if (!(scp->status & UNKNOWN_MODE))
@@ -780,8 +798,13 @@ scclose(dev_t dev, int flag, int mode, struct proc *p)
}
else {
free(scp->scr_buf, M_DEVBUF);
- if (scp->history != NULL)
+ if (scp->history != NULL) {
free(scp->history, M_DEVBUF);
+ if (scp->history_size / scp->xsize
+ > imax(SC_HISTORY_SIZE, scp->ysize))
+ extra_history_size += scp->history_size / scp->xsize
+ - imax(SC_HISTORY_SIZE, scp->ysize);
+ }
free(scp, M_DEVBUF);
console[minor(dev)] = NULL;
}
@@ -884,6 +907,7 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
u_int i;
struct tty *tp;
scr_stat *scp;
+ u_short *usp;
tp = scdevtotty(dev);
if (!tp)
@@ -956,16 +980,44 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
return 0;
case CONS_HISTORY: /* set history size */
- if (*data) {
+ if (*(int *)data > 0) {
+ int lines; /* buffer size to allocate */
+ int lines0; /* current buffer size */
+
+ lines = imax(*(int *)data, scp->ysize);
+ lines0 = (scp->history != NULL) ?
+ scp->history_size / scp->xsize : scp->ysize;
+ /*
+ * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE
+ * lines or scp->ysize lines, whichever is larger. A value
+ * greater than that is allowed, subject to extra_history_size.
+ */
+ if (lines > imax(lines0, SC_HISTORY_SIZE) + extra_history_size)
+ return EINVAL;
if (cur_console->status & BUFFER_SAVED)
return EBUSY;
- if (scp->history != NULL)
- free(scp->history, M_DEVBUF);
- scp->history_size = max(scp->ysize, *(int *)data)*scp->xsize;
- scp->history_head = scp->history_pos = scp->history =
- (u_short *)malloc(scp->history_size*sizeof(u_short),
- M_DEVBUF, M_WAITOK);
- bzero(scp->history_head, scp->history_size*sizeof(u_short));
+ usp = scp->history;
+ scp->history = NULL;
+ if (usp != NULL)
+ free(usp, M_DEVBUF);
+ scp->history_size = lines * scp->xsize;
+ /*
+ * extra_history_size +=
+ * (lines0 > imax(SC_HISTORY_SIZE, scp->ysize)) ?
+ * lines0 - imax(SC_HISTORY_SIZE, scp->ysize)) : 0;
+ * extra_history_size -=
+ * (lines > imax(SC_HISTORY_SIZE, scp->ysize)) ?
+ * lines - imax(SC_HISTORY_SIZE, scp->ysize)) : 0;
+ * lines0 >= ysize && lines >= ysize... Hey, the above can be
+ * reduced to the following...
+ */
+ extra_history_size +=
+ imax(lines0, SC_HISTORY_SIZE) - imax(lines, SC_HISTORY_SIZE);
+ usp = (u_short *)malloc(scp->history_size * sizeof(u_short),
+ M_DEVBUF, M_WAITOK);
+ bzero(usp, scp->history_size * sizeof(u_short));
+ scp->history_head = scp->history_pos = usp;
+ scp->history = usp;
return 0;
}
else
@@ -1129,6 +1181,9 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
if (!crtc_vga || video_mode_ptr == NULL)
return ENXIO;
+ if (scp->history != NULL)
+ i = imax(scp->history_size / scp->xsize
+ - imax(SC_HISTORY_SIZE, scp->ysize), 0);
switch (cmd & 0xff) {
case M_VGA_C80x60: case M_VGA_M80x60:
if (!(fonts_loaded & FONT_8))
@@ -1178,13 +1233,19 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
free(cut_buffer, M_DEVBUF);
cut_buffer = (char *)malloc(scp->xsize*scp->ysize, M_DEVBUF, M_NOWAIT);
cut_buffer[0] = 0x00;
- if (scp->history != NULL)
- free(scp->history, M_DEVBUF);
- scp->history_size = max(HISTORY_SIZE, scp->xsize*scp->ysize);
- scp->history_head = scp->history_pos = scp->history = (u_short *)
- malloc(scp->history_size*sizeof(u_short), M_DEVBUF, M_NOWAIT);
- if (scp->history != NULL)
- bzero(scp->history, scp->history_size*sizeof(u_short));
+ usp = scp->history;
+ scp->history = NULL;
+ if (usp != NULL) {
+ free(usp, M_DEVBUF);
+ extra_history_size += i;
+ }
+ scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize;
+ usp = (u_short *)malloc(scp->history_size * sizeof(u_short),
+ M_DEVBUF, M_NOWAIT);
+ if (usp != NULL)
+ bzero(usp, scp->history_size * sizeof(u_short));
+ scp->history_head = scp->history_pos = usp;
+ scp->history = usp;
if (scp == cur_console)
set_mode(scp);
scp->status &= ~UNKNOWN_MODE;
@@ -2783,10 +2844,11 @@ static scr_stat
scp->mouse_pos = scp->mouse_oldpos =
scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize +
scp->mouse_xpos/8);
- scp->history_head = scp->history_pos = scp->history =
+ scp->history_head = scp->history_pos =
(u_short *)malloc(scp->history_size*sizeof(u_short),
M_DEVBUF, M_WAITOK);
bzero(scp->history_head, scp->history_size*sizeof(u_short));
+ scp->history = scp->history_head;
/* SOS
if (crtc_vga && video_mode_ptr)
set_mode(scp);
@@ -2840,7 +2902,7 @@ init_scp(scr_stat *scp)
scp->proc = NULL;
scp->smode.mode = VT_AUTO;
scp->history_head = scp->history_pos = scp->history = NULL;
- scp->history_size = max(HISTORY_SIZE, scp->xsize*scp->ysize);
+ scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize;
}
static u_char
diff --git a/sys/dev/syscons/syscons.h b/sys/dev/syscons/syscons.h
index 0c74c32..ccddf83 100644
--- a/sys/dev/syscons/syscons.h
+++ b/sys/dev/syscons/syscons.h
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: syscons.h,v 1.33 1997/09/04 23:01:06 yokota Exp $
+ * $Id: syscons.h,v 1.34 1997/10/01 20:46:29 sos Exp $
*/
#ifndef _I386_ISA_SYSCONS_H_
@@ -102,10 +102,6 @@
#define FONT_8 2
#define FONT_14 4
#define FONT_16 8
-#if !defined(SC_HISTORY_SIZE)
-#define SC_HISTORY_SIZE (ROW * 4)
-#endif /* SC_HISTORY_SIZE */
-#define HISTORY_SIZE (COL * (SC_HISTORY_SIZE))
/* defines related to hardware addresses */
#define MONO_BASE 0x3B4 /* crt controller base mono */
diff --git a/sys/i386/isa/syscons.c b/sys/i386/isa/syscons.c
index c92bb36..273bb01 100644
--- a/sys/i386/isa/syscons.c
+++ b/sys/i386/isa/syscons.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: syscons.c,v 1.233 1997/09/26 15:27:55 itojun Exp $
+ * $Id: syscons.c,v 1.234 1997/10/01 20:46:27 sos Exp $
*/
#include "sc.h"
@@ -71,6 +71,19 @@
#define MAXCONS 16
#endif
+#if !defined(SC_MAX_HISTORY_SIZE)
+#define SC_MAX_HISTORY_SIZE (1000 * MAXCONS)
+#endif
+
+#if !defined(SC_HISTORY_SIZE)
+#define SC_HISTORY_SIZE (ROW * 4)
+#endif
+
+#if (SC_HISTORY_SIZE * MAXCONS) > SC_MAX_HISTORY_SIZE
+#undef SC_MAX_HISTORY_SIZE
+#define SC_MAX_HISTORY_SIZE (SC_HISTORY_SIZE * MAXCONS)
+#endif
+
#define COLD 0
#define WARM 1
@@ -147,6 +160,9 @@ static u_short mouse_or_mask[16] = {
0x0000, 0x0000, 0x0000, 0x0000
};
+static int extra_history_size =
+ SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS;
+
static void none_saver(int blank) { }
static void (*current_saver)(int blank) = none_saver;
int (*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data,
@@ -636,10 +652,12 @@ scattach(struct isa_device *dev)
scp->mouse_xpos/8);
/* initialize history buffer & pointers */
- scp->history_head = scp->history_pos = scp->history =
+ scp->history_head = scp->history_pos =
(u_short *)malloc(scp->history_size*sizeof(u_short),
M_DEVBUF, M_NOWAIT);
- bzero(scp->history_head, scp->history_size*sizeof(u_short));
+ if (scp->history_head != NULL)
+ bzero(scp->history_head, scp->history_size*sizeof(u_short));
+ scp->history = scp->history_head;
/* initialize cursor stuff */
if (!(scp->status & UNKNOWN_MODE))
@@ -780,8 +798,13 @@ scclose(dev_t dev, int flag, int mode, struct proc *p)
}
else {
free(scp->scr_buf, M_DEVBUF);
- if (scp->history != NULL)
+ if (scp->history != NULL) {
free(scp->history, M_DEVBUF);
+ if (scp->history_size / scp->xsize
+ > imax(SC_HISTORY_SIZE, scp->ysize))
+ extra_history_size += scp->history_size / scp->xsize
+ - imax(SC_HISTORY_SIZE, scp->ysize);
+ }
free(scp, M_DEVBUF);
console[minor(dev)] = NULL;
}
@@ -884,6 +907,7 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
u_int i;
struct tty *tp;
scr_stat *scp;
+ u_short *usp;
tp = scdevtotty(dev);
if (!tp)
@@ -956,16 +980,44 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
return 0;
case CONS_HISTORY: /* set history size */
- if (*data) {
+ if (*(int *)data > 0) {
+ int lines; /* buffer size to allocate */
+ int lines0; /* current buffer size */
+
+ lines = imax(*(int *)data, scp->ysize);
+ lines0 = (scp->history != NULL) ?
+ scp->history_size / scp->xsize : scp->ysize;
+ /*
+ * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE
+ * lines or scp->ysize lines, whichever is larger. A value
+ * greater than that is allowed, subject to extra_history_size.
+ */
+ if (lines > imax(lines0, SC_HISTORY_SIZE) + extra_history_size)
+ return EINVAL;
if (cur_console->status & BUFFER_SAVED)
return EBUSY;
- if (scp->history != NULL)
- free(scp->history, M_DEVBUF);
- scp->history_size = max(scp->ysize, *(int *)data)*scp->xsize;
- scp->history_head = scp->history_pos = scp->history =
- (u_short *)malloc(scp->history_size*sizeof(u_short),
- M_DEVBUF, M_WAITOK);
- bzero(scp->history_head, scp->history_size*sizeof(u_short));
+ usp = scp->history;
+ scp->history = NULL;
+ if (usp != NULL)
+ free(usp, M_DEVBUF);
+ scp->history_size = lines * scp->xsize;
+ /*
+ * extra_history_size +=
+ * (lines0 > imax(SC_HISTORY_SIZE, scp->ysize)) ?
+ * lines0 - imax(SC_HISTORY_SIZE, scp->ysize)) : 0;
+ * extra_history_size -=
+ * (lines > imax(SC_HISTORY_SIZE, scp->ysize)) ?
+ * lines - imax(SC_HISTORY_SIZE, scp->ysize)) : 0;
+ * lines0 >= ysize && lines >= ysize... Hey, the above can be
+ * reduced to the following...
+ */
+ extra_history_size +=
+ imax(lines0, SC_HISTORY_SIZE) - imax(lines, SC_HISTORY_SIZE);
+ usp = (u_short *)malloc(scp->history_size * sizeof(u_short),
+ M_DEVBUF, M_WAITOK);
+ bzero(usp, scp->history_size * sizeof(u_short));
+ scp->history_head = scp->history_pos = usp;
+ scp->history = usp;
return 0;
}
else
@@ -1129,6 +1181,9 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
if (!crtc_vga || video_mode_ptr == NULL)
return ENXIO;
+ if (scp->history != NULL)
+ i = imax(scp->history_size / scp->xsize
+ - imax(SC_HISTORY_SIZE, scp->ysize), 0);
switch (cmd & 0xff) {
case M_VGA_C80x60: case M_VGA_M80x60:
if (!(fonts_loaded & FONT_8))
@@ -1178,13 +1233,19 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
free(cut_buffer, M_DEVBUF);
cut_buffer = (char *)malloc(scp->xsize*scp->ysize, M_DEVBUF, M_NOWAIT);
cut_buffer[0] = 0x00;
- if (scp->history != NULL)
- free(scp->history, M_DEVBUF);
- scp->history_size = max(HISTORY_SIZE, scp->xsize*scp->ysize);
- scp->history_head = scp->history_pos = scp->history = (u_short *)
- malloc(scp->history_size*sizeof(u_short), M_DEVBUF, M_NOWAIT);
- if (scp->history != NULL)
- bzero(scp->history, scp->history_size*sizeof(u_short));
+ usp = scp->history;
+ scp->history = NULL;
+ if (usp != NULL) {
+ free(usp, M_DEVBUF);
+ extra_history_size += i;
+ }
+ scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize;
+ usp = (u_short *)malloc(scp->history_size * sizeof(u_short),
+ M_DEVBUF, M_NOWAIT);
+ if (usp != NULL)
+ bzero(usp, scp->history_size * sizeof(u_short));
+ scp->history_head = scp->history_pos = usp;
+ scp->history = usp;
if (scp == cur_console)
set_mode(scp);
scp->status &= ~UNKNOWN_MODE;
@@ -2783,10 +2844,11 @@ static scr_stat
scp->mouse_pos = scp->mouse_oldpos =
scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize +
scp->mouse_xpos/8);
- scp->history_head = scp->history_pos = scp->history =
+ scp->history_head = scp->history_pos =
(u_short *)malloc(scp->history_size*sizeof(u_short),
M_DEVBUF, M_WAITOK);
bzero(scp->history_head, scp->history_size*sizeof(u_short));
+ scp->history = scp->history_head;
/* SOS
if (crtc_vga && video_mode_ptr)
set_mode(scp);
@@ -2840,7 +2902,7 @@ init_scp(scr_stat *scp)
scp->proc = NULL;
scp->smode.mode = VT_AUTO;
scp->history_head = scp->history_pos = scp->history = NULL;
- scp->history_size = max(HISTORY_SIZE, scp->xsize*scp->ysize);
+ scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize;
}
static u_char
diff --git a/sys/i386/isa/syscons.h b/sys/i386/isa/syscons.h
index 0c74c32..ccddf83 100644
--- a/sys/i386/isa/syscons.h
+++ b/sys/i386/isa/syscons.h
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: syscons.h,v 1.33 1997/09/04 23:01:06 yokota Exp $
+ * $Id: syscons.h,v 1.34 1997/10/01 20:46:29 sos Exp $
*/
#ifndef _I386_ISA_SYSCONS_H_
@@ -102,10 +102,6 @@
#define FONT_8 2
#define FONT_14 4
#define FONT_16 8
-#if !defined(SC_HISTORY_SIZE)
-#define SC_HISTORY_SIZE (ROW * 4)
-#endif /* SC_HISTORY_SIZE */
-#define HISTORY_SIZE (COL * (SC_HISTORY_SIZE))
/* defines related to hardware addresses */
#define MONO_BASE 0x3B4 /* crt controller base mono */
diff --git a/sys/isa/syscons.c b/sys/isa/syscons.c
index c92bb36..273bb01 100644
--- a/sys/isa/syscons.c
+++ b/sys/isa/syscons.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: syscons.c,v 1.233 1997/09/26 15:27:55 itojun Exp $
+ * $Id: syscons.c,v 1.234 1997/10/01 20:46:27 sos Exp $
*/
#include "sc.h"
@@ -71,6 +71,19 @@
#define MAXCONS 16
#endif
+#if !defined(SC_MAX_HISTORY_SIZE)
+#define SC_MAX_HISTORY_SIZE (1000 * MAXCONS)
+#endif
+
+#if !defined(SC_HISTORY_SIZE)
+#define SC_HISTORY_SIZE (ROW * 4)
+#endif
+
+#if (SC_HISTORY_SIZE * MAXCONS) > SC_MAX_HISTORY_SIZE
+#undef SC_MAX_HISTORY_SIZE
+#define SC_MAX_HISTORY_SIZE (SC_HISTORY_SIZE * MAXCONS)
+#endif
+
#define COLD 0
#define WARM 1
@@ -147,6 +160,9 @@ static u_short mouse_or_mask[16] = {
0x0000, 0x0000, 0x0000, 0x0000
};
+static int extra_history_size =
+ SC_MAX_HISTORY_SIZE - SC_HISTORY_SIZE * MAXCONS;
+
static void none_saver(int blank) { }
static void (*current_saver)(int blank) = none_saver;
int (*sc_user_ioctl)(dev_t dev, int cmd, caddr_t data,
@@ -636,10 +652,12 @@ scattach(struct isa_device *dev)
scp->mouse_xpos/8);
/* initialize history buffer & pointers */
- scp->history_head = scp->history_pos = scp->history =
+ scp->history_head = scp->history_pos =
(u_short *)malloc(scp->history_size*sizeof(u_short),
M_DEVBUF, M_NOWAIT);
- bzero(scp->history_head, scp->history_size*sizeof(u_short));
+ if (scp->history_head != NULL)
+ bzero(scp->history_head, scp->history_size*sizeof(u_short));
+ scp->history = scp->history_head;
/* initialize cursor stuff */
if (!(scp->status & UNKNOWN_MODE))
@@ -780,8 +798,13 @@ scclose(dev_t dev, int flag, int mode, struct proc *p)
}
else {
free(scp->scr_buf, M_DEVBUF);
- if (scp->history != NULL)
+ if (scp->history != NULL) {
free(scp->history, M_DEVBUF);
+ if (scp->history_size / scp->xsize
+ > imax(SC_HISTORY_SIZE, scp->ysize))
+ extra_history_size += scp->history_size / scp->xsize
+ - imax(SC_HISTORY_SIZE, scp->ysize);
+ }
free(scp, M_DEVBUF);
console[minor(dev)] = NULL;
}
@@ -884,6 +907,7 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
u_int i;
struct tty *tp;
scr_stat *scp;
+ u_short *usp;
tp = scdevtotty(dev);
if (!tp)
@@ -956,16 +980,44 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
return 0;
case CONS_HISTORY: /* set history size */
- if (*data) {
+ if (*(int *)data > 0) {
+ int lines; /* buffer size to allocate */
+ int lines0; /* current buffer size */
+
+ lines = imax(*(int *)data, scp->ysize);
+ lines0 = (scp->history != NULL) ?
+ scp->history_size / scp->xsize : scp->ysize;
+ /*
+ * syscons unconditionally allocates buffers upto SC_HISTORY_SIZE
+ * lines or scp->ysize lines, whichever is larger. A value
+ * greater than that is allowed, subject to extra_history_size.
+ */
+ if (lines > imax(lines0, SC_HISTORY_SIZE) + extra_history_size)
+ return EINVAL;
if (cur_console->status & BUFFER_SAVED)
return EBUSY;
- if (scp->history != NULL)
- free(scp->history, M_DEVBUF);
- scp->history_size = max(scp->ysize, *(int *)data)*scp->xsize;
- scp->history_head = scp->history_pos = scp->history =
- (u_short *)malloc(scp->history_size*sizeof(u_short),
- M_DEVBUF, M_WAITOK);
- bzero(scp->history_head, scp->history_size*sizeof(u_short));
+ usp = scp->history;
+ scp->history = NULL;
+ if (usp != NULL)
+ free(usp, M_DEVBUF);
+ scp->history_size = lines * scp->xsize;
+ /*
+ * extra_history_size +=
+ * (lines0 > imax(SC_HISTORY_SIZE, scp->ysize)) ?
+ * lines0 - imax(SC_HISTORY_SIZE, scp->ysize)) : 0;
+ * extra_history_size -=
+ * (lines > imax(SC_HISTORY_SIZE, scp->ysize)) ?
+ * lines - imax(SC_HISTORY_SIZE, scp->ysize)) : 0;
+ * lines0 >= ysize && lines >= ysize... Hey, the above can be
+ * reduced to the following...
+ */
+ extra_history_size +=
+ imax(lines0, SC_HISTORY_SIZE) - imax(lines, SC_HISTORY_SIZE);
+ usp = (u_short *)malloc(scp->history_size * sizeof(u_short),
+ M_DEVBUF, M_WAITOK);
+ bzero(usp, scp->history_size * sizeof(u_short));
+ scp->history_head = scp->history_pos = usp;
+ scp->history = usp;
return 0;
}
else
@@ -1129,6 +1181,9 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
if (!crtc_vga || video_mode_ptr == NULL)
return ENXIO;
+ if (scp->history != NULL)
+ i = imax(scp->history_size / scp->xsize
+ - imax(SC_HISTORY_SIZE, scp->ysize), 0);
switch (cmd & 0xff) {
case M_VGA_C80x60: case M_VGA_M80x60:
if (!(fonts_loaded & FONT_8))
@@ -1178,13 +1233,19 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
free(cut_buffer, M_DEVBUF);
cut_buffer = (char *)malloc(scp->xsize*scp->ysize, M_DEVBUF, M_NOWAIT);
cut_buffer[0] = 0x00;
- if (scp->history != NULL)
- free(scp->history, M_DEVBUF);
- scp->history_size = max(HISTORY_SIZE, scp->xsize*scp->ysize);
- scp->history_head = scp->history_pos = scp->history = (u_short *)
- malloc(scp->history_size*sizeof(u_short), M_DEVBUF, M_NOWAIT);
- if (scp->history != NULL)
- bzero(scp->history, scp->history_size*sizeof(u_short));
+ usp = scp->history;
+ scp->history = NULL;
+ if (usp != NULL) {
+ free(usp, M_DEVBUF);
+ extra_history_size += i;
+ }
+ scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize;
+ usp = (u_short *)malloc(scp->history_size * sizeof(u_short),
+ M_DEVBUF, M_NOWAIT);
+ if (usp != NULL)
+ bzero(usp, scp->history_size * sizeof(u_short));
+ scp->history_head = scp->history_pos = usp;
+ scp->history = usp;
if (scp == cur_console)
set_mode(scp);
scp->status &= ~UNKNOWN_MODE;
@@ -2783,10 +2844,11 @@ static scr_stat
scp->mouse_pos = scp->mouse_oldpos =
scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize +
scp->mouse_xpos/8);
- scp->history_head = scp->history_pos = scp->history =
+ scp->history_head = scp->history_pos =
(u_short *)malloc(scp->history_size*sizeof(u_short),
M_DEVBUF, M_WAITOK);
bzero(scp->history_head, scp->history_size*sizeof(u_short));
+ scp->history = scp->history_head;
/* SOS
if (crtc_vga && video_mode_ptr)
set_mode(scp);
@@ -2840,7 +2902,7 @@ init_scp(scr_stat *scp)
scp->proc = NULL;
scp->smode.mode = VT_AUTO;
scp->history_head = scp->history_pos = scp->history = NULL;
- scp->history_size = max(HISTORY_SIZE, scp->xsize*scp->ysize);
+ scp->history_size = imax(SC_HISTORY_SIZE, scp->ysize) * scp->xsize;
}
static u_char
diff --git a/sys/isa/syscons.h b/sys/isa/syscons.h
index 0c74c32..ccddf83 100644
--- a/sys/isa/syscons.h
+++ b/sys/isa/syscons.h
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: syscons.h,v 1.33 1997/09/04 23:01:06 yokota Exp $
+ * $Id: syscons.h,v 1.34 1997/10/01 20:46:29 sos Exp $
*/
#ifndef _I386_ISA_SYSCONS_H_
@@ -102,10 +102,6 @@
#define FONT_8 2
#define FONT_14 4
#define FONT_16 8
-#if !defined(SC_HISTORY_SIZE)
-#define SC_HISTORY_SIZE (ROW * 4)
-#endif /* SC_HISTORY_SIZE */
-#define HISTORY_SIZE (COL * (SC_HISTORY_SIZE))
/* defines related to hardware addresses */
#define MONO_BASE 0x3B4 /* crt controller base mono */
OpenPOWER on IntegriCloud