Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 06 Apr 2001 15:33:58 +0300
From:      Maxim Sobolev <sobomax@FreeBSD.org>
To:        hackers@FreeBSD.org, audit@FreeBSD.org
Subject:   Automatic fontsize definition in vidcontrol(8) [patch]
Message-ID:  <3ACDB7B6.74973132@FreeBSD.org>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------BF05896831049C5323D4B762
Content-Type: text/plain; charset=koi8-r
Content-Transfer-Encoding: 7bit

Hi,

I found it very frustrating that each time I need to change console
font (my native language has 3 different encodings, so I need to do it
regularly) I have to specify not only the font name, but fontsize as
well. I do not see any reasons why vidcontrol(8) can't guess correct
value from the fontfile itself, especially considering that there is
1-to-1 mapping between size of the fontdata and font dimensions. With
this message I'm attaching small patch that adds this functionality to
the utility.

In addition, this patch makes vidcontrol(8) more robust, fixing the
following issues:
o previously vidcontrol could be crashed easily by specifying a valid
uuencoded file with undecoded size greater than the size of the buffer
allocated for that particular fontsize (the same applies for the
screenmap). Now decoding routine will discard any data that exceed the
size of the buffer;

o previously it was quite easy to trash fonts on your console by
erroneously specifying an arbitrary binary file (or even a directory)
instead of a fontfile. Now the utility will refuse to load a binary
file, unless its size is equal to one of 3 possible valid sizes, thus
greatly reducing a possibility of an error.

Please somebody review attached patches.

Thanks!

-Maxim

--------------BF05896831049C5323D4B762
Content-Type: text/plain; charset=koi8-r;
 name="vidcontrol.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="vidcontrol.diff"

Index: decode.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/vidcontrol/decode.c,v
retrieving revision 1.8
diff -d -u -r1.8 decode.c
--- decode.c	1999/08/28 01:20:29	1.8
+++ decode.c	2001/04/06 12:08:43
@@ -35,10 +35,11 @@
 #include <string.h>
 #include "decode.h"
 
-int decode(FILE *fd, char *buffer)
+int decode(FILE *fd, char *buffer, int len)
 {
-	int n, pos = 0;
-	char *p;
+	int n, pos = 0, tpos;
+	char *bp, *p;
+	char tbuffer[3];
 	char temp[128];
 
 #define	DEC(c)	(((c) - ' ') & 0x3f)
@@ -48,31 +49,49 @@
 			return(0);
 	} while (strncmp(temp, "begin ", 6));
 	sscanf(temp, "begin %o %s", &n, temp);
+	bp = buffer;
 	for (;;) {
 		if (!fgets(p = temp, sizeof(temp), fd))
 			return(0);
 		if ((n = DEC(*p)) <= 0)
 			break;
-		for (++p; n > 0; p += 4, n -= 3)
+		for (++p; n > 0; p += 4, n -= 3) {
+			tpos = 0;
 			if (n >= 3) {
-				buffer[pos++] = DEC(p[0])<<2 | DEC(p[1])>>4;
-				buffer[pos++] = DEC(p[1])<<4 | DEC(p[2])>>2;
-				buffer[pos++] = DEC(p[2])<<6 | DEC(p[3]);
+				tbuffer[tpos++] = DEC(p[0])<<2 | DEC(p[1])>>4;
+				tbuffer[tpos++] = DEC(p[1])<<4 | DEC(p[2])>>2;
+				tbuffer[tpos++] = DEC(p[2])<<6 | DEC(p[3]);
 			}
 			else {
 				if (n >= 1) {
-					buffer[pos++] =
+					tbuffer[tpos++] =
 						DEC(p[0])<<2 | DEC(p[1])>>4;
 				}
 				if (n >= 2) {
-					buffer[pos++] =
+					tbuffer[tpos++] =
 						DEC(p[1])<<4 | DEC(p[2])>>2;
 				}
 				if (n >= 3) {
-					buffer[pos++] =
+					tbuffer[tpos++] =
 						DEC(p[2])<<6 | DEC(p[3]);
 				}
 			}
+			if (tpos == 0)
+				continue;
+			if (tpos + pos > len) {
+				tpos = len - pos;
+				/*
+				 * Arrange return value > len to indicate
+				 * overflow.
+				 */
+				pos++;
+			}
+			bcopy(tbuffer, bp, tpos);
+			pos += tpos;
+			bp += tpos;
+			if (pos > len)
+				return(pos);
+		}
 	}
 	if (!fgets(temp, sizeof(temp), fd) || strcmp(temp, "end\n"))
 		return(0);
Index: decode.h
===================================================================
RCS file: /home/ncvs/src/usr.sbin/vidcontrol/decode.h,v
retrieving revision 1.1
diff -d -u -r1.1 decode.h
--- decode.h	1997/03/07 01:34:44	1.1
+++ decode.h	2001/04/06 12:08:43
@@ -1 +1,3 @@
-int decode(FILE *fd, char *buffer);
+/* $FreeBSD$ */
+
+int decode(FILE *fd, char *buffer, int len);
Index: vidcontrol.1
===================================================================
RCS file: /home/ncvs/src/usr.sbin/vidcontrol/vidcontrol.1,v
retrieving revision 1.30
diff -d -u -r1.30 vidcontrol.1
--- vidcontrol.1	2001/03/28 02:32:10	1.30
+++ vidcontrol.1	2001/04/06 12:08:43
@@ -24,7 +24,7 @@
 .Op Fl b Ar color
 .Op Fl c Ar appearance
 .Op Fl d
-.Op Fl f Ar size Ar file
+.Op Fl f Oo Ar size Oc Ar \ file
 .Op Fl g Ar geometry
 .Op Fl i Cm adapter | mode
 .Op Fl l Ar screen_map
@@ -142,7 +142,7 @@
 Used together with the 
 .Xr moused 8
 daemon for text mode cut & paste functionality.
-.It Fl f Ar size Ar file
+.It Fl f [ Ar size ] Ar file
 Load font
 .Ar file
 for
@@ -157,6 +157,11 @@
 .Xr vidfont 1
 command to load the font of your choice.
 .Pp
+.Ar Size
+may be omitted, in this case
+.Nm
+will try to guess it from the size of font file.
+.Pp
 Note that older video cards, such as MDA and CGA, do not support 
 software font.
 See also
@@ -295,6 +300,11 @@
 .Pa iso-8x16 :
 .Pp
 .Dl vidcontrol -f 8x16 iso-8x16
+.Pp
+Furthermore, you can also omit font size
+.Dq 8x16 :
+.Pp
+.Dl vidcontrol -f iso-8x16
 .Pp
 Likewise, you can also abbreviate the screen output map file name for
 the
Index: vidcontrol.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/vidcontrol/vidcontrol.c,v
retrieving revision 1.34
diff -d -u -r1.34 vidcontrol.c
--- vidcontrol.c	2001/01/25 16:53:22	1.34
+++ vidcontrol.c	2001/04/06 12:08:44
@@ -41,6 +41,8 @@
 #include <sys/fbio.h>
 #include <sys/consio.h>
 #include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include "path.h"
 #include "decode.h"
 
@@ -74,12 +76,13 @@
 }
 
 char *
-nextarg(int ac, char **av, int *indp, int oc)
+nextarg(int ac, char **av, int *indp, int oc, int strict)
 {
 	if (*indp < ac)
 		return(av[(*indp)++]);
-	errx(1, "option requires two arguments -- %c", oc);
-	return("");
+	if (strict != 0)
+		errx(1, "option requires two arguments -- %c", oc);
+	return(NULL);
 }
 
 char *
@@ -129,7 +132,7 @@
 		return;
 	}
 	size = sizeof(scrnmap);
-	if (decode(fd, (char *)&scrnmap) != size) {
+	if (decode(fd, (char *)&scrnmap, size) != size) {
 		rewind(fd);
 		if (fread(&scrnmap, 1, size, fd) != size) {
 			warnx("bad screenmap file");
@@ -176,16 +179,38 @@
 
 }
 
+int
+fsize(FILE *file)
+{
+	struct stat sb;
+
+	if (fstat(fileno(file), &sb) == 0)
+		return sb.st_size;
+	else
+		return -1;
+}
+
+#define DATASIZE(x) ((x).w * (x).h * 256 / 8)
+
 void
 load_font(char *type, char *filename)
 {
-	FILE	*fd = 0;
-	int	i, size;
-	unsigned long io;
+	FILE	*fd = NULL;
+	int	h, i, size, w;
+	unsigned long io = 0;	/* silence stupid gcc(1) in the Wall mode */
 	char	*name, *fontmap;
 	char	*prefix[]  = {"", "", FONT_PATH, FONT_PATH, NULL};
 	char	*postfix[] = {"", ".fnt", "", ".fnt"};
 
+	struct sizeinfo {
+		int w;
+		int h;
+		unsigned long io;
+	} sizes[] = {{8, 16, PIO_FONT8x16},
+		     {8, 14, PIO_FONT8x14},
+		     {8,  8,  PIO_FONT8x8},
+		     {0,  0,            0}};
+
 	for (i=0; prefix[i]; i++) {
 		name = mkfullname(prefix[i], filename, postfix[i]);
 		fd = fopen(name, "r");
@@ -193,31 +218,57 @@
 			break;
 	}
 	if (fd == NULL) {
-		warn("font file not found");
+		warnx("%s: font file not found", filename);
 		return;
-	}
-	if (!strcmp(type, "8x8")) {
-		size = 8*256;
-		io = PIO_FONT8x8;
 	}
-	else if (!strcmp(type, "8x14")) {
-		size = 14*256;
-		io = PIO_FONT8x14;
-	}
-	else if (!strcmp(type, "8x16")) {
-		size = 16*256;
-		io = PIO_FONT8x16;
-	}
-	else {
-		warn("bad font size specification");
-		fclose(fd);
-		return;
+	if (type != NULL) {
+		size = 0;
+		if (sscanf(type, "%dx%d", &w, &h) == 2)
+			for (i = 0; sizes[i].w != 0; i++)
+				if (sizes[i].w == w && sizes[i].h == h) {
+					size = DATASIZE(sizes[i]);
+					io = sizes[i].io;
+				}
+
+		if (size == 0) {
+			warnx("%s: bad font size specification", type);
+			fclose(fd);
+			return;
+		}
+	} else {
+		/* Apply heuristics */
+		int j;
+		int dsize[2];
+
+		size = DATASIZE(sizes[0]);
+		fontmap = (char*) malloc(size);
+		dsize[0] = decode(fd, fontmap, size);
+		dsize[1] = fsize(fd);
+		free(fontmap);
+
+		size = 0;
+		for (j = 0; j < 2; j++)
+			for (i = 0; sizes[i].w != 0; i++)
+				if (DATASIZE(sizes[i]) == dsize[j]) {
+					size = dsize[j];
+					io = sizes[i].io;
+					j = 2;	/* XXX */
+					break;
+				}
+
+		if (size == 0) {
+			warnx("%s: can't guess font size", filename);
+			fclose(fd);
+			return;
+		}
+		rewind(fd);
 	}
+
 	fontmap = (char*) malloc(size);
-	if (decode(fd, fontmap) != size) {
+	if (decode(fd, fontmap, size) != size) {
 		rewind(fd);
-		if (fread(fontmap, 1, size, fd) != size) {
-			warnx("bad font file");
+		if (fsize(fd) != size || fread(fontmap, 1, size, fd) != size) {
+			warnx("%s: bad font file", filename);
 			fclose(fd);
 			free(fontmap);
 			return;
@@ -590,7 +641,8 @@
 int
 main(int argc, char **argv)
 {
-	int		opt;
+	char	*font, *type;
+	int	opt;
 
 
 	info.size = sizeof(info);
@@ -608,8 +660,13 @@
 				print_scrnmap();
 				break;
 			case 'f':
-				load_font(optarg,
-					nextarg(argc, argv, &optind, 'f'));
+				type = optarg;
+				font = nextarg(argc, argv, &optind, 'f', 0);
+				if (font == NULL) {
+					type = NULL;
+					font = optarg;
+				}
+				load_font(type, font);
 				break;
 			case 'g':
 				if (sscanf(optarg, "%dx%d", &vesa_cols,

--------------BF05896831049C5323D4B762--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-audit" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3ACDB7B6.74973132>