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>